From 49c33dab8b7a57780affea28db976ccab8dc345b Mon Sep 17 00:00:00 2001 From: XpLoDWilD Date: Fri, 26 Jul 2013 12:37:55 +0200 Subject: fimc/s3cfb: Remove inlines breaking build on 4.3 If anyone have any idea why it cannot find function body for these two functions... Others are fine. Change-Id: Ifebb2e995a4ef4e779bed2e8f12aa7990ac19b41 --- drivers/media/video/exynos/fimc-lite/fimc-lite-core.c | 2 +- drivers/media/video/exynos/fimc-lite/fimc-lite-core.h | 2 +- drivers/video/samsung_extdisp/s3cfb_extdsp.h | 2 +- drivers/video/samsung_extdisp/s3cfb_extdsp_main.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/exynos/fimc-lite/fimc-lite-core.c b/drivers/media/video/exynos/fimc-lite/fimc-lite-core.c index 011787c..0a10f2e 100644 --- a/drivers/media/video/exynos/fimc-lite/fimc-lite-core.c +++ b/drivers/media/video/exynos/fimc-lite/fimc-lite-core.c @@ -122,7 +122,7 @@ static struct flite_fmt *find_format(u32 *pixelformat, u32 *mbus_code, int index } #endif -inline struct flite_fmt const *find_flite_format(struct v4l2_mbus_framefmt *mf) +struct flite_fmt const *find_flite_format(struct v4l2_mbus_framefmt *mf) { int num_fmt = ARRAY_SIZE(flite_formats); diff --git a/drivers/media/video/exynos/fimc-lite/fimc-lite-core.h b/drivers/media/video/exynos/fimc-lite/fimc-lite-core.h index 2c46c8b..a8a0a2e 100644 --- a/drivers/media/video/exynos/fimc-lite/fimc-lite-core.h +++ b/drivers/media/video/exynos/fimc-lite/fimc-lite-core.h @@ -295,7 +295,7 @@ static inline void user_to_drv(struct v4l2_ctrl *ctrl, s32 value) ctrl->cur.val = ctrl->val = value; } -inline struct flite_fmt const *find_flite_format(struct v4l2_mbus_framefmt *mf); +struct flite_fmt const *find_flite_format(struct v4l2_mbus_framefmt *mf); /* * Add buf to the capture active buffers queue. diff --git a/drivers/video/samsung_extdisp/s3cfb_extdsp.h b/drivers/video/samsung_extdisp/s3cfb_extdsp.h index 99f134c..11f4f37 100644 --- a/drivers/video/samsung_extdisp/s3cfb_extdsp.h +++ b/drivers/video/samsung_extdisp/s3cfb_extdsp.h @@ -151,7 +151,7 @@ struct s3cfb_extdsp_user_window { #define S3CFB_EXTDSP_GET_FREE_BUFFER _IOW('F', 329, unsigned int) extern struct fb_ops s3cfb_extdsp_ops; -extern inline struct s3cfb_extdsp_global *get_extdsp_global(int id); +extern struct s3cfb_extdsp_global *get_extdsp_global(int id); /* S3CFB_EXTDSP */ extern int s3cfb_extdsp_enable_window(struct s3cfb_extdsp_global *fbdev, int id); diff --git a/drivers/video/samsung_extdisp/s3cfb_extdsp_main.c b/drivers/video/samsung_extdisp/s3cfb_extdsp_main.c index 4f9f2b2..dacd94d 100644 --- a/drivers/video/samsung_extdisp/s3cfb_extdsp_main.c +++ b/drivers/video/samsung_extdisp/s3cfb_extdsp_main.c @@ -43,7 +43,7 @@ struct s3cfb_extdsp_extdsp_desc *fbextdsp; -inline struct s3cfb_extdsp_global *get_extdsp_global(int id) +struct s3cfb_extdsp_global *get_extdsp_global(int id) { struct s3cfb_extdsp_global *fbdev; -- cgit v1.1 From 26ecd9742bd036be3ee91d2ddec0a019ff4c0646 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Sun, 4 Aug 2013 17:26:30 +0200 Subject: mmc: fix the workqueue overload battery waste After switching to the smdk4412 kernel I noticed a workqueue overload, battery lasting less, and Android OS showing up at the top as result. Tracing showed that mmc_host_clk_gate_work was one of the runqueues called regularly in the background. The #ifdef is clearly reversed and that leads to the ndelay being called every time, while ndelay was never called before. Not yet sure if this fixes the "apparent" regression but it's not bad so far, after 1h of uptime android OS is below Android System. Change-Id: Ief78ed7ddb3eec85636844b9a730cac832b096b4 --- drivers/mmc/core/host.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 7966957..67758bf 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -110,12 +110,12 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host) if (!host->clk_requests) { spin_unlock_irqrestore(&host->clk_lock, flags); /* wait only when clk_gate_delay is 0 */ -#ifdef CONFIG_WIMAX_CMC +#ifndef CONFIG_WIMAX_CMC if (!host->clkgate_delay) { #endif tick_ns = DIV_ROUND_UP(1000000000, freq); ndelay(host->clk_delay * tick_ns); -#ifdef CONFIG_WIMAX_CMC +#ifndef CONFIG_WIMAX_CMC } #endif } else { -- cgit v1.1 From a8583839d9318fb5601b80769fc45d358a56faf0 Mon Sep 17 00:00:00 2001 From: Daniel Hillenbrand Date: Sat, 10 Aug 2013 17:13:32 +0200 Subject: max8997: move sysfs node for pwm level Change-Id: I1ca8450000be99505c7c48c6c4fd2dfb15bba670 --- drivers/motor/max8997_vibrator.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/motor/max8997_vibrator.c b/drivers/motor/max8997_vibrator.c index c3b07f8..827793d 100644 --- a/drivers/motor/max8997_vibrator.c +++ b/drivers/motor/max8997_vibrator.c @@ -225,7 +225,7 @@ void vibtonz_pwm(int nForce) } EXPORT_SYMBOL(vibtonz_pwm); -static ssize_t pwm_val_show(struct device *dev, +static ssize_t pwm_value_show(struct device *dev, struct device_attribute *attr, char *buf) { int count; @@ -233,19 +233,19 @@ static ssize_t pwm_val_show(struct device *dev, pwm_val = ((pwm_duty - pwm_duty_min) * 100) / pwm_duty_min; count = sprintf(buf, "%lu\n", pwm_val); - pr_debug("[VIB] pwm_val: %lu\n", pwm_val); + pr_debug("[VIB] pwm_value: %lu\n", pwm_val); return count; } -ssize_t pwm_val_store(struct device *dev, +ssize_t pwm_value_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { if (kstrtoul(buf, 0, &pwm_val)) - pr_err("[VIB] %s: error on storing pwm_val\n", __func__); + pr_err("[VIB] %s: error on storing pwm_value\n", __func__); - pr_info("[VIB] %s: pwm_val=%lu\n", __func__, pwm_val); + pr_info("[VIB] %s: pwm_value=%lu\n", __func__, pwm_val); pwm_duty = (pwm_val * pwm_duty_min) / 100 + pwm_duty_min; @@ -261,28 +261,10 @@ ssize_t pwm_val_store(struct device *dev, return size; } -static DEVICE_ATTR(pwm_val, S_IRUGO | S_IWUSR, - pwm_val_show, pwm_val_store); +static DEVICE_ATTR(pwm_value, S_IRUGO | S_IWUSR, + pwm_value_show, pwm_value_store); #endif -static int create_vibrator_sysfs(void) -{ - int ret; - struct kobject *vibrator_kobj; - vibrator_kobj = kobject_create_and_add("vibrator", NULL); - if (unlikely(!vibrator_kobj)) - return -ENOMEM; - - ret = sysfs_create_file(vibrator_kobj, - &dev_attr_pwm_val.attr); - if (unlikely(ret < 0)) { - pr_err("[VIB] sysfs_create_file failed: %d\n", ret); - return ret; - } - - return 0; -} - static int __devinit vibrator_probe(struct platform_device *pdev) { struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent); @@ -323,8 +305,6 @@ static int __devinit vibrator_probe(struct platform_device *pdev) INIT_WORK(&ddata->work, vibrator_work); spin_lock_init(&ddata->lock); - create_vibrator_sysfs(); - ddata->pwm = pwm_request(pdata->pwm_id, "vibrator"); if (IS_ERR(ddata->pwm)) { pr_err("[VIB] Failed to request pwm.\n"); @@ -343,6 +323,12 @@ static int __devinit vibrator_probe(struct platform_device *pdev) goto err_timed_output_register; } + /* User controllable pwm level */ + error = device_create_file(ddata->dev.dev, &dev_attr_pwm_value); + if (error < 0) { + pr_err("[VIB] create sysfs fail: pwm_value\n"); + } + #ifdef CONFIG_VIBETONZ g_data = ddata; pwm_duty_max = g_data->pdata->duty; -- cgit v1.1 From fcd2c1e6345d7bc73305365fb86eada6f4d5c448 Mon Sep 17 00:00:00 2001 From: Daniel Hillenbrand Date: Sat, 10 Aug 2013 20:31:55 +0200 Subject: mshci: disable MMC_CAP_ERASE on u1 Change-Id: I944a80e4ffd9d7b86b18a13534a3fa8fd2104934 --- drivers/mmc/host/mshci.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/host/mshci.c b/drivers/mmc/host/mshci.c index 45997c5..f93a7eb 100644 --- a/drivers/mmc/host/mshci.c +++ b/drivers/mmc/host/mshci.c @@ -2045,7 +2045,11 @@ int mshci_add_host(struct mshci_host *host) mmc->ops = &mshci_ops; mmc->f_min = 400000; mmc->f_max = host->max_clk; +#ifdef CONFIG_MACH_U1 + mmc->caps |= MMC_CAP_SDIO_IRQ; +#else mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE; +#endif mmc->caps |= MMC_CAP_4_BIT_DATA; -- cgit v1.1 From 9c135abddcf1b3f7a30104d7171c9488f63881f9 Mon Sep 17 00:00:00 2001 From: sbrissen Date: Tue, 13 Aug 2013 07:43:12 -0400 Subject: isa1200: move sysfs node for pwm level Change-Id: I50b353531a1ee581217305b257d30317ce73b0c7 --- drivers/motor/isa1200_vibrator.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/motor/isa1200_vibrator.c b/drivers/motor/isa1200_vibrator.c index 4b26dc3..0f2da51 100644 --- a/drivers/motor/isa1200_vibrator.c +++ b/drivers/motor/isa1200_vibrator.c @@ -269,7 +269,7 @@ static void isa1200_vibrator_enable(struct timed_output_dev *_dev, int value) spin_unlock_irqrestore(&data->lock, flags); } -static ssize_t pwm_val_show(struct device *dev, +static ssize_t pwm_value_show(struct device *dev, struct device_attribute *attr, char *buf) { int count; @@ -277,19 +277,19 @@ static ssize_t pwm_val_show(struct device *dev, pwm_val = ((isapwm_duty - 500) * 100) / 500; count = sprintf(buf, "%lu\n", pwm_val); - pr_debug("[VIB] pwm_val: %lu\n", pwm_val); + pr_debug("[VIB] pwm_value: %lu\n", pwm_val); return count; } -ssize_t pwm_val_store(struct device *dev, +ssize_t pwm_value_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { if (kstrtoul(buf, 0, &pwm_val)) - pr_err("[VIB] %s: error on storing pwm_val\n", __func__); + pr_err("[VIB] %s: error on storing pwm_value\n", __func__); - pr_info("[VIB] %s: pwm_val=%lu\n", __func__, pwm_val); + pr_info("[VIB] %s: pwm_value=%lu\n", __func__, pwm_val); isapwm_duty = (pwm_val * 500) / 100 + 500; @@ -307,26 +307,8 @@ ssize_t pwm_val_store(struct device *dev, return size; } -static DEVICE_ATTR(pwm_val, S_IRUGO | S_IWUSR, - pwm_val_show, pwm_val_store); - -static int create_vibrator_sysfs(void) -{ - int ret; - struct kobject *vibrator_kobj; - vibrator_kobj = kobject_create_and_add("vibrator", NULL); - if (unlikely(!vibrator_kobj)) - return -ENOMEM; - - ret = sysfs_create_file(vibrator_kobj, - &dev_attr_pwm_val.attr); - if (unlikely(ret < 0)) { - pr_err("[VIB] sysfs_create_file failed: %d\n", ret); - return ret; - } - - return 0; -} +static DEVICE_ATTR(pwm_value, S_IRUGO | S_IWUSR, + pwm_value_show, pwm_value_store); static int __devinit isa1200_vibrator_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -373,12 +355,16 @@ static int __devinit isa1200_vibrator_i2c_probe(struct i2c_client *client, ddata->duty = pdata->duty; ddata->period = pdata->period; + /* User controllable pwm level */ + ret = device_create_file(ddata->dev.dev, &dev_attr_pwm_value); + if (ret < 0) { + pr_err("[VIB] create sysfs fail: pwm_value\n"); + } + ddata->dev.name = "vibrator"; ddata->dev.get_time = isa1200_vibrator_get_time; ddata->dev.enable = isa1200_vibrator_enable; - create_vibrator_sysfs(); - hrtimer_init(&ddata->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ddata->timer.function = isa1200_vibrator_timer_func; INIT_WORK(&ddata->work, isa1200_vibrator_work); -- cgit v1.1 From 008d6925cd8509bcf525950f66d9c9f913a207ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20G?= Date: Thu, 15 Aug 2013 23:59:31 +0200 Subject: Increase lowest GPU step for 1400MHz devices Devices using the 1400MHz Exynos 4210 are using 1280*800 screens. This is a much bigger resolution than the Galaxy S2. 100MHz as the lowest GPU step is too low for these devices, resulting in lag. Bump it up to 134MHz. Change-Id: Ifd08cdc2e263695232d034890e54585f122453ff --- .../video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c index 3bf6805..e0199b2 100644 --- a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c +++ b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c @@ -76,7 +76,11 @@ int mali_dvfs_control=0; /*dvfs table*/ mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ +#ifdef CONFIG_EXYNOS4210_1400MHZ_SUPPORT + /*step 0*/{134 ,1000000 , 950000}, +#else /*step 0*/{100 ,1000000 , 950000}, +#endif /*step 1*/{160 ,1000000 , 950000}, /*step 2*/{267 ,1000000 ,1000000} }; @@ -87,7 +91,7 @@ mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ #define ASV_LEVEL_SUPPORT 0 static unsigned int asv_3d_volt_5_table[ASV_5_LEVEL][MALI_DVFS_STEPS] = { - /* L3 (100MHz) L2(160MHz), L1(267MHz) */ + /* L3 (100/134MHz) L2(160MHz), L1(267MHz) */ {1000000, 1000000, 1100000}, /* S */ {1000000, 1000000, 1100000}, /* A */ { 950000, 950000, 1000000}, /* B */ @@ -96,7 +100,7 @@ static unsigned int asv_3d_volt_5_table[ASV_5_LEVEL][MALI_DVFS_STEPS] = { }; static unsigned int asv_3d_volt_8_table[ASV_8_LEVEL][MALI_DVFS_STEPS] = { - /* L3 (100MHz) L2(160MHz), L1(267MHz) */ + /* L3 (100/134MHz) L2(160MHz), L1(267MHz) */ {1000000, 1000000, 1100000}, /* SS */ {1000000, 1000000, 1100000}, /* A1 */ {1000000, 1000000, 1100000}, /* A2 */ -- cgit v1.1 From 81acf891b5786d5b392bc0af2a81f193cb90bfc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20G?= Date: Fri, 16 Aug 2013 18:30:12 +0200 Subject: mali: pick the right GPU voltage table for 1400MHz devices, restore thresholds 8-level table was always used, resulting in increased voltages for 1400MHz devices. Now, the right table (5-level) can be picked at runtime. Restore the thresholds to stock value for more stable frequencies. Change-Id: I29900535c15557e75c72793b7169771982fce7f9 --- .../samsung/mali/platform/orion-m400/mali_platform_dvfs.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c index 3bf6805..98a8852 100644 --- a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c +++ b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c @@ -67,8 +67,8 @@ mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={ /*dvfs threshold*/ mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={ /*step 0*/{((int)((255*0)/100)) ,((int)((255*85)/100))}, - /*step 1*/{((int)((255*80)/100)) ,((int)((255*90)/100))}, - /*step 2*/{((int)((255*80)/100)) ,((int)((255*100)/100))} }; + /*step 1*/{((int)((255*75)/100)) ,((int)((255*85)/100))}, + /*step 2*/{((int)((255*75)/100)) ,((int)((255*100)/100))} }; /*dvfs status*/ mali_dvfs_currentstatus maliDvfsStatus; @@ -84,7 +84,6 @@ mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ #define ASV_8_LEVEL 8 #define ASV_5_LEVEL 5 -#define ASV_LEVEL_SUPPORT 0 static unsigned int asv_3d_volt_5_table[ASV_5_LEVEL][MALI_DVFS_STEPS] = { /* L3 (100MHz) L2(160MHz), L1(267MHz) */ @@ -269,16 +268,18 @@ static unsigned int decideNextStatus(unsigned int utilization) static mali_bool mali_dvfs_table_update(void) { unsigned int exynos_result_of_asv_group; + unsigned int target_asv; unsigned int i; exynos_result_of_asv_group = exynos_result_of_asv & 0xf; - MALI_PRINT(("exynos_result_of_asv_group = 0x%x\n", exynos_result_of_asv_group)); + target_asv = exynos_result_of_asv >> 28; + MALI_PRINT(("exynos_result_of_asv_group = 0x%x, target_asv = 0x%x\n", exynos_result_of_asv_group, target_asv)); - if (ASV_LEVEL_SUPPORT) { //asv level information will be added. + if (target_asv == 0x8) { //SUPPORT_1400MHZ for (i = 0; i < MALI_DVFS_STEPS; i++) { mali_dvfs[i].vol = asv_3d_volt_5_table[exynos_result_of_asv_group][i]; MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); } - } else { + } else if (target_asv == 0x4){ //SUPPORT_1200MHZ for (i = 0; i < MALI_DVFS_STEPS; i++) { mali_dvfs[i].vol = asv_3d_volt_8_table[exynos_result_of_asv_group][i]; MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); -- cgit v1.1 From e0d43667b66bec7c2b59973ce3203f97af7688dc Mon Sep 17 00:00:00 2001 From: Daniel Hillenbrand Date: Mon, 19 Aug 2013 22:03:11 +0200 Subject: n7100: add cyanogenmod mdnie preset Change-Id: I42e3ec88452239a6b953dff0e636a8c2e5dbf958 --- drivers/video/samsung/mdnie_table_t0.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/video/samsung/mdnie_table_t0.h b/drivers/video/samsung/mdnie_table_t0.h index 94062c8..f653e4e 100644 --- a/drivers/video/samsung/mdnie_table_t0.h +++ b/drivers/video/samsung/mdnie_table_t0.h @@ -3,6 +3,18 @@ #include "mdnie.h" +static const unsigned short tune_cyanogenmod[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0008, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090, 0x0080, /*DE egth*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; static const unsigned short tune_dynamic_gallery[] = { 0x0000, 0x0000, /*BANK 0*/ @@ -638,6 +650,7 @@ struct mdnie_tunning_info etc_table[CABC_MAX][OUTDOOR_MAX][TONE_MAX] = { struct mdnie_tunning_info tunning_table[CABC_MAX][MODE_MAX][SCENARIO_MAX] = { { { + {"CYANOGENMOD", tune_cyanogenmod}, {"DYNAMIC_UI", tune_dynamic_ui}, {"DYNAMIC_VIDEO", tune_dynamic_video}, {"DYNAMIC_VIDEO", tune_dynamic_video}, @@ -647,6 +660,7 @@ struct mdnie_tunning_info tunning_table[CABC_MAX][MODE_MAX][SCENARIO_MAX] = { {"DYNAMIC_GALLERY", tune_dynamic_gallery}, {"DYNAMIC_VT", tune_dynamic_vt}, }, { + {"CYANOGENMOD", tune_cyanogenmod}, {"STANDARD_UI", tune_standard_ui}, {"STANDARD_VIDEO", tune_standard_video}, {"STANDARD_VIDEO", tune_standard_video}, @@ -656,6 +670,7 @@ struct mdnie_tunning_info tunning_table[CABC_MAX][MODE_MAX][SCENARIO_MAX] = { {"STANDARD_GALLERY", tune_standard_gallery}, {"STANDARD_VT", tune_standard_vt}, }, { + {"CYANOGENMOD", tune_cyanogenmod}, {"NATURAL_UI", tune_natural_ui}, {"NATURAL_VIDEO", tune_natural_video}, {"NATURAL_VIDEO_WARM", tune_natural_video}, @@ -665,6 +680,7 @@ struct mdnie_tunning_info tunning_table[CABC_MAX][MODE_MAX][SCENARIO_MAX] = { {"NATURAL_GALLERY", tune_natural_gallery}, {"NATURAL_VT", tune_natural_vt}, }, { + {"CYANOGENMOD", tune_cyanogenmod}, {"MOVIE_UI", tune_movie_ui}, {"MOVIE_VIDEO", tune_movie_video}, {"MOVIE_VIDEO", tune_movie_video}, -- cgit v1.1 From b07657a606584eb7328c10d6f57fbb0f0db6d070 Mon Sep 17 00:00:00 2001 From: Daniel Hillenbrand Date: Wed, 21 Aug 2013 20:28:55 +0200 Subject: cypress: report led status via sysfs Change-Id: Iddecb0688e758eca3ba77b520510a6728ad1e3bb --- drivers/input/keyboard/cypress/cypress-touchkey.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.c b/drivers/input/keyboard/cypress/cypress-touchkey.c index 6ccd693..1944e56 100644 --- a/drivers/input/keyboard/cypress/cypress-touchkey.c +++ b/drivers/input/keyboard/cypress/cypress-touchkey.c @@ -1078,6 +1078,17 @@ static ssize_t touch_update_read(struct device *dev, return count; } +static ssize_t touchkey_led_control_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + + ret = sprintf(buf, "%d\n", touchkey_led_status); + pr_info("[Touchkey] %s: touchkey_led_status=%d\n", __func__, touchkey_led_status); + + return ret; +} + static ssize_t touchkey_led_control(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) @@ -1559,7 +1570,7 @@ static DEVICE_ATTR(recommended_version, S_IRUGO | S_IWUSR | S_IWGRP, touch_version_read, touch_version_write); static DEVICE_ATTR(updated_version, S_IRUGO | S_IWUSR | S_IWGRP, touch_update_read, touch_update_write); -static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR | S_IWGRP, NULL, +static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR | S_IWGRP, touchkey_led_control_show, touchkey_led_control); static DEVICE_ATTR(touchkey_menu, S_IRUGO | S_IWUSR | S_IWGRP, touchkey_menu_show, NULL); -- cgit v1.1 From a64df5bd240324b9551cffbf9171888ccaa3fdeb Mon Sep 17 00:00:00 2001 From: Daniel Hillenbrand Date: Fri, 23 Aug 2013 21:54:03 +0200 Subject: cypress-touchkey: remove backlight timeout feature Userspace implementation: http://review.cyanogenmod.org/48796 http://review.cyanogenmod.org/48872 http://review.cyanogenmod.org/48884 Change-Id: Id4ac50168220310e82aa4aae367dad4e72e3a9c3 --- drivers/input/keyboard/cypress/cypress-touchkey.c | 518 ++++++++-------------- drivers/input/keyboard/cypress/cypress-touchkey.h | 23 - drivers/input/touchscreen/mms152_ts.c | 34 -- drivers/input/touchscreen/mms_ts.c | 9 - drivers/input/touchscreen/mxt224_u1.c | 6 - 5 files changed, 175 insertions(+), 415 deletions(-) delete mode 100644 drivers/input/keyboard/cypress/cypress-touchkey.h (limited to 'drivers') diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.c b/drivers/input/keyboard/cypress/cypress-touchkey.c index 1944e56..ef8a6b8 100644 --- a/drivers/input/keyboard/cypress/cypress-touchkey.c +++ b/drivers/input/keyboard/cypress/cypress-touchkey.c @@ -37,8 +37,6 @@ #include #include "issp_extern.h" -#include "cypress-touchkey.h" - #ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT540E #include #else @@ -66,7 +64,7 @@ static int touchkey_keycode[] = { 0, KEY_MENU, KEY_ENTER, KEY_BACK, KEY_END, #elif defined(TK_USE_4KEY_TYPE_NA) - KEY_SEARCH, KEY_BACK, KEY_HOME, KEY_MENU, + KEY_SEARCH, KEY_BACK, KEY_HOMEPAGE, KEY_MENU, #elif defined(TK_USE_2KEY_TYPE_M0) KEY_BACK, KEY_MENU, @@ -78,11 +76,6 @@ static int touchkey_keycode[] = { 0, }; static const int touchkey_count = sizeof(touchkey_keycode) / sizeof(int); -struct touchkey_i2c *tkey_i2c_local; -struct timer_list touch_led_timer; -int touch_led_timeout = 3; // timeout for the touchkey backlight in secs -int touch_led_disabled = 0; // 1= force disable the touchkey backlight - #if defined(TK_HAS_AUTOCAL) static u16 raw_data0; static u16 raw_data1; @@ -115,8 +108,8 @@ static bool g_debug_tkey = FALSE; static int touchkey_i2c_check(struct touchkey_i2c *tkey_i2c); -static u8 menu_sensitivity; -static u8 back_sensitivity; +static u16 menu_sensitivity; +static u16 back_sensitivity; #if defined(TK_USE_4KEY) static u8 home_sensitivity; static u8 search_sensitivity; @@ -161,10 +154,10 @@ static ssize_t brightness_control(struct device *dev, int data; if (sscanf(buf, "%d\n", &data) == 1) { - pr_err("[TouchKey] touch_led_brightness: %d\n", data); + printk(KERN_ERR "[TouchKey] touch_led_brightness: %d\n", data); change_touch_key_led_voltage(data); } else { - pr_err("[TouchKey] touch_led_brightness Error\n"); + printk(KERN_ERR "[TouchKey] touch_led_brightness Error\n"); } return size; @@ -191,7 +184,7 @@ static int i2c_touchkey_read(struct i2c_client *client, if ((client == NULL) || !(touchkey_enable == 1) || !touchkey_probe) { - pr_err("[TouchKey] touchkey is not enabled. %d\n", + printk(KERN_ERR "[TouchKey] touchkey is not enabled. %d\n", __LINE__); return -ENODEV; } @@ -210,7 +203,7 @@ static int i2c_touchkey_read(struct i2c_client *client, if (err >= 0) return 0; - pr_err("[TouchKey] %s %d i2c transfer error\n", + printk(KERN_ERR "[TouchKey] %s %d i2c transfer error\n", __func__, __LINE__); mdelay(10); } @@ -229,7 +222,7 @@ static int i2c_touchkey_write(struct i2c_client *client, if ((client == NULL) || !(touchkey_enable == 1) || !touchkey_probe) { - pr_err("[TouchKey] touchkey is not enabled. %d\n", + printk(KERN_ERR "[TouchKey] touchkey is not enabled. %d\n", __LINE__); return -ENODEV; } @@ -249,7 +242,7 @@ static int i2c_touchkey_write(struct i2c_client *client, if (err >= 0) return 0; - pr_debug("[TouchKey] %s %d i2c transfer error\n", + printk(KERN_DEBUG "[TouchKey] %s %d i2c transfer error\n", __func__, __LINE__); mdelay(10); } @@ -272,10 +265,11 @@ static int touchkey_autocalibration(struct touchkey_i2c *tkey_i2c) while (retry < 3) { ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 4); if (ret < 0) { - pr_err("[TouchKey]i2c read fail.\n"); + printk(KERN_ERR "[TouchKey]i2c read fail.\n"); return ret; } - pr_debug("[TouchKey] data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", + printk(KERN_DEBUG + "[TouchKey] data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", data[0], data[1], data[2], data[3]); /* Send autocal Command */ @@ -290,23 +284,24 @@ static int touchkey_autocalibration(struct touchkey_i2c *tkey_i2c) ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 6); if ((data[5] & TK_BIT_AUTOCAL)) { - pr_debug("[Touchkey] autocal Enabled\n"); + printk(KERN_DEBUG "[Touchkey] autocal Enabled\n"); break; } else - pr_debug("[Touchkey] autocal disabled, retry %d\n", + printk(KERN_DEBUG + "[Touchkey] autocal disabled, retry %d\n", retry); retry = retry + 1; } if (retry == 3) - pr_debug("[Touchkey] autocal failed\n"); + printk(KERN_DEBUG "[Touchkey] autocal failed\n"); return count; } #endif -#if 0 /* CONFIG_TARGET_LOCALE_NAATT */ +#ifdef CONFIG_TARGET_LOCALE_NAATT static ssize_t set_touchkey_autocal_testmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) @@ -317,7 +312,7 @@ static ssize_t set_touchkey_autocal_testmode(struct device *dev, int on_off; if (sscanf(buf, "%d\n", &on_off) == 1) { - pr_err("[TouchKey] Test Mode : %d\n", on_off); + printk(KERN_ERR "[TouchKey] Test Mode : %d\n", on_off); if (on_off == 1) { set_data = 0x40; @@ -333,7 +328,7 @@ static ssize_t set_touchkey_autocal_testmode(struct device *dev, #endif } } else { - pr_err("[TouchKey] touch_led_brightness Error\n"); + printk(KERN_ERR "[TouchKey] touch_led_brightness Error\n"); } return count; @@ -348,24 +343,24 @@ static ssize_t touchkey_raw_data0_show(struct device *dev, u8 data[26] = { 0, }; int ret; - pr_debug("called %s\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 26); #if defined(CONFIG_TARGET_LOCALE_NA) - pr_debug("called %s data[18] =%d,data[19] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[18] =%d,data[19] = %d\n", __func__, data[18], data[19]); raw_data0 = ((0x00FF & data[18]) << 8) | data[19]; #elif defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1)\ || defined(CONFIG_MACH_M3)\ || defined(CONFIG_MACH_T0) - pr_debug("called %s data[16] =%d,data[17] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[16] =%d,data[17] = %d\n", __func__, data[16], data[17]); raw_data0 = ((0x00FF & data[16]) << 8) | data[17]; /* menu*/ #elif defined(CONFIG_MACH_Q1_BD) - pr_debug("called %s data[16] =%d,data[17] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[16] =%d,data[17] = %d\n", __func__, data[16], data[17]); raw_data0 = ((0x00FF & data[14]) << 8) | data[15]; #else - pr_debug("called %s data[18] =%d,data[19] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[18] =%d,data[19] = %d\n", __func__, data[10], data[11]); raw_data0 = ((0x00FF & data[10]) << 8) | data[11]; #endif @@ -379,24 +374,24 @@ static ssize_t touchkey_raw_data1_show(struct device *dev, u8 data[26] = { 0, }; int ret; - pr_debug("called %s\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 26); #if defined(CONFIG_TARGET_LOCALE_NA) - pr_debug("called %s data[20] =%d,data[21] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[20] =%d,data[21] = %d\n", __func__, data[20], data[21]); raw_data1 = ((0x00FF & data[20]) << 8) | data[21]; #elif defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1)\ || defined(CONFIG_MACH_M3)\ || defined(CONFIG_MACH_T0) - pr_debug("called %s data[14] =%d,data[15] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[14] =%d,data[15] = %d\n", __func__, data[14], data[15]); raw_data1 = ((0x00FF & data[14]) << 8) | data[15]; /*back*/ #elif defined(CONFIG_MACH_Q1_BD) - pr_debug("called %s data[14] =%d,data[15] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[14] =%d,data[15] = %d\n", __func__, data[14], data[15]); raw_data1 = ((0x00FF & data[16]) << 8) | data[17]; #else - pr_debug("called %s data[20] =%d,data[21] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[20] =%d,data[21] = %d\n", __func__, data[12], data[13]); raw_data1 = ((0x00FF & data[12]) << 8) | data[13]; #endif /* CONFIG_TARGET_LOCALE_NA */ @@ -410,14 +405,14 @@ static ssize_t touchkey_raw_data2_show(struct device *dev, u8 data[26] = { 0, }; int ret; - pr_debug("called %s\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 26); #if defined(CONFIG_TARGET_LOCALE_NA) - pr_debug("called %s data[22] =%d,data[23] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[22] =%d,data[23] = %d\n", __func__, data[22], data[23]); raw_data2 = ((0x00FF & data[22]) << 8) | data[23]; #else - pr_debug("called %s data[22] =%d,data[23] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[22] =%d,data[23] = %d\n", __func__, data[14], data[15]); raw_data2 = ((0x00FF & data[14]) << 8) | data[15]; #endif /* CONFIG_TARGET_LOCALE_NA */ @@ -431,14 +426,14 @@ static ssize_t touchkey_raw_data3_show(struct device *dev, u8 data[26] = { 0, }; int ret; - pr_debug("called %s\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 26); #if defined(CONFIG_TARGET_LOCALE_NA) - pr_debug("called %s data[24] =%d,data[25] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[24] =%d,data[25] = %d\n", __func__, data[24], data[25]); raw_data3 = ((0x00FF & data[24]) << 8) | data[25]; #else - pr_debug("called %s data[24] =%d,data[25] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[24] =%d,data[25] = %d\n", __func__, data[16], data[17]); raw_data3 = ((0x00FF & data[16]) << 8) | data[17]; #endif /* CONFIG_TARGET_LOCALE_NA */ @@ -456,9 +451,9 @@ static ssize_t touchkey_idac0_show(struct device *dev, return 0; #endif - pr_debug("called %s\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10); - pr_debug("called %s data[6] =%d\n", __func__, data[6]); + printk(KERN_DEBUG "called %s data[6] =%d\n", __func__, data[6]); idac0 = data[6]; return sprintf(buf, "%d\n", idac0); } @@ -474,9 +469,9 @@ static ssize_t touchkey_idac1_show(struct device *dev, return 0; #endif - pr_debug("called %s\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10); - pr_debug("called %s data[7] = %d\n", __func__, data[7]); + printk(KERN_DEBUG "called %s data[7] = %d\n", __func__, data[7]); idac1 = data[7]; return sprintf(buf, "%d\n", idac1); } @@ -492,9 +487,9 @@ static ssize_t touchkey_idac2_show(struct device *dev, return 0; #endif - pr_debug("called %s\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10); - pr_debug("called %s data[8] =%d\n", __func__, data[8]); + printk(KERN_DEBUG "called %s data[8] =%d\n", __func__, data[8]); idac2 = data[8]; return sprintf(buf, "%d\n", idac2); } @@ -510,9 +505,9 @@ static ssize_t touchkey_idac3_show(struct device *dev, return 0; #endif - pr_debug("called %s\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10); - pr_debug("called %s data[9] = %d\n", __func__, data[9]); + printk(KERN_DEBUG "called %s data[9] = %d\n", __func__, data[9]); idac3 = data[9]; return sprintf(buf, "%d\n", idac3); } @@ -524,9 +519,9 @@ static ssize_t touchkey_threshold_show(struct device *dev, u8 data[10]; int ret; - pr_debug("called %s\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10); - pr_debug("called %s data[4] = %d\n", __func__, data[4]); + printk(KERN_DEBUG "called %s data[4] = %d\n", __func__, data[4]); touchkey_threshold = data[4]; return sprintf(buf, "%d\n", touchkey_threshold); } @@ -544,12 +539,13 @@ static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c) ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3); if (ret < 0) { - pr_debug("[TouchKey] i2c read fail. do not excute firm update.\n"); + printk(KERN_DEBUG + "[TouchKey] i2c read fail. do not excute firm update.\n"); data[1] = 0; data[2] = 0; } - pr_err("%s F/W version: 0x%x, Module version:0x%x\n", __func__, + printk(KERN_ERR "%s F/W version: 0x%x, Module version:0x%x\n", __func__, data[1], data[2]); tkey_i2c->firmware_ver = data[1]; @@ -563,34 +559,39 @@ static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c) if ((tkey_i2c->firmware_ver < TK_FIRMWARE_VER) && (tkey_i2c->module_ver == TK_MODULE_VER)) { #endif - pr_debug("[TouchKey] firmware auto update excute\n"); + printk(KERN_DEBUG "[TouchKey] firmware auto update excute\n"); tkey_i2c->update_status = TK_UPDATE_DOWN; while (retry--) { if (ISSP_main(tkey_i2c) == 0) { - pr_debug("[TouchKey]firmware update succeeded\n"); + printk(KERN_DEBUG + "[TouchKey]firmware update succeeded\n"); tkey_i2c->update_status = TK_UPDATE_PASS; msleep(50); break; } msleep(50); - pr_debug("[TouchKey] firmware update failed. retry\n"); + printk(KERN_DEBUG + "[TouchKey] firmware update failed. retry\n"); } if (retry <= 0) { tkey_i2c->pdata->power_on(0); tkey_i2c->update_status = TK_UPDATE_FAIL; - pr_debug("[TouchKey] firmware update failed.\n"); + printk(KERN_DEBUG + "[TouchKey] firmware update failed.\n"); } ret = touchkey_i2c_check(tkey_i2c); if (ret < 0) { - pr_debug("[TouchKey] i2c read fail.\n"); + printk(KERN_DEBUG + "[TouchKey] i2c read fail.\n"); return TK_UPDATE_FAIL; } #if defined(CONFIG_TARGET_LOCALE_KOR) ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3); if (ret < 0) { - pr_debug("[TouchKey] i2c read fail. do not excute firm update.\n"); + printk(KERN_DEBUG + "[TouchKey] i2c read fail. do not excute firm update.\n"); } tkey_i2c->firmware_ver = data[1]; tkey_i2c->module_ver = data[2]; @@ -598,10 +599,13 @@ static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c) printk(KERN_DEBUG "[TouchKey] firm ver = %d, module ver = %d\n", tkey_i2c->firmware_ver, tkey_i2c->module_ver); } else { - pr_debug("[TouchKey] firmware auto update do not excute\n"); - pr_debug("[TouchKey] firmware_ver(banary=%d, current=%d)\n", + printk(KERN_DEBUG + "[TouchKey] firmware auto update do not excute\n"); + printk(KERN_DEBUG + "[TouchKey] firmware_ver(banary=%d, current=%d)\n", TK_FIRMWARE_VER, tkey_i2c->firmware_ver); - pr_debug("[TouchKey] module_ver(banary=%d, current=%d)\n", + printk(KERN_DEBUG + "[TouchKey] module_ver(banary=%d, current=%d)\n", TK_MODULE_VER, tkey_i2c->module_ver); } enable_irq(tkey_i2c->irq); @@ -616,11 +620,12 @@ static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c) ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3); if (ret < 0) { - pr_debug("[TouchKey] i2c read fail. do not excute firm update.\n"); + printk(KERN_DEBUG + "[TouchKey] i2c read fail. do not excute firm update.\n"); return ret; } - pr_err("%s F/W version: 0x%x, Module version:0x%x\n", __func__, + printk(KERN_ERR "%s F/W version: 0x%x, Module version:0x%x\n", __func__, data[1], data[2]); retry = 3; @@ -631,11 +636,12 @@ static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c) tkey_i2c->update_status = TK_UPDATE_DOWN; while (retry--) { if (ISSP_main(tkey_i2c) == 0) { - pr_err("[TOUCHKEY]Touchkey_update succeeded\n"); + printk(KERN_ERR + "[TOUCHKEY]Touchkey_update succeeded\n"); tkey_i2c->update_status = TK_UPDATE_PASS; break; } - pr_err("touchkey_update failed...retry...\n"); + printk(KERN_ERR "touchkey_update failed...retry...\n"); } if (retry <= 0) { tkey_i2c->pdata->power_on(0); @@ -644,9 +650,11 @@ static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c) } } else { if (tkey_i2c->firmware_ver >= 0x0A) { - pr_err("[TouchKey] Not F/W update. Cypess touch-key F/W version is latest\n"); + printk(KERN_ERR + "[TouchKey] Not F/W update. Cypess touch-key F/W version is latest\n"); } else { - pr_err("[TouchKey] Not F/W update. Cypess touch-key version(module or F/W) is not valid\n"); + printk(KERN_ERR + "[TouchKey] Not F/W update. Cypess touch-key version(module or F/W) is not valid\n"); } } return ret; @@ -657,7 +665,6 @@ static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c) static irqreturn_t touchkey_interrupt(int irq, void *dev_id) { struct touchkey_i2c *tkey_i2c = dev_id; - static const int ledCmd[] = {TK_CMD_LED_ON, TK_CMD_LED_OFF}; u8 data[3]; int ret; int retry = 10; @@ -672,7 +679,8 @@ static irqreturn_t touchkey_interrupt(int irq, void *dev_id) if (!ret) break; else { - pr_debug("[TouchKey] i2c read failed, ret:%d, retry: %d\n", + printk(KERN_DEBUG + "[TouchKey] i2c read failed, ret:%d, retry: %d\n", ret, retry); continue; } @@ -686,58 +694,33 @@ static irqreturn_t touchkey_interrupt(int irq, void *dev_id) pressed = !(data[0] & TK_BIT_PRESS_EV); if (keycode_type <= 0 || keycode_type >= touchkey_count) { - pr_debug("[Touchkey] keycode_type err\n"); + printk(KERN_DEBUG "[Touchkey] keycode_type err\n"); return IRQ_HANDLED; } - if (pressed) { + if (pressed) set_touchkey_debug('P'); - // enable lights on keydown - if (touch_led_disabled == 0) { - if (touchkey_led_status == TK_CMD_LED_OFF) { - pr_debug("[Touchkey] %s: keydown - LED ON\n", __func__); - i2c_touchkey_write(tkey_i2c->client, (u8 *) &ledCmd[0], 1); - touchkey_led_status = TK_CMD_LED_ON; - } - if (timer_pending(&touch_led_timer) == 1) { - mod_timer(&touch_led_timer, jiffies + (HZ * touch_led_timeout)); - } - } - - } else { - // touch led timeout on keyup - if (touch_led_disabled == 0) { - if (timer_pending(&touch_led_timer) == 0) { - pr_debug("[Touchkey] %s: keyup - add_timer\n", __func__); - touch_led_timer.expires = jiffies + (HZ * touch_led_timeout); - add_timer(&touch_led_timer); - } else { - mod_timer(&touch_led_timer, jiffies + (HZ * touch_led_timeout)); - } - } - } - if (get_tsp_status() && pressed) - pr_debug("[TouchKey] touchkey pressed but don't send event because touch is pressed.\n"); + printk(KERN_DEBUG "[TouchKey] touchkey pressed but don't send event because touch is pressed.\n"); else { input_report_key(tkey_i2c->input_dev, touchkey_keycode[keycode_type], pressed); input_sync(tkey_i2c->input_dev); #if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP) - pr_debug("[TouchKey] keycode:%d pressed:%d\n", + printk(KERN_DEBUG "[TouchKey] keycode:%d pressed:%d\n", touchkey_keycode[keycode_type], pressed); #else - pr_debug("[TouchKey] pressed:%d\n", + printk(KERN_DEBUG "[TouchKey] pressed:%d\n", pressed); #endif #if defined(CONFIG_TARGET_LOCALE_KOR) if (g_debug_tkey == true) { - pr_debug("[TouchKey] keycode[%d]=%d pressed:%d\n", + printk(KERN_DEBUG "[TouchKey] keycode[%d]=%d pressed:%d\n", keycode_type, touchkey_keycode[keycode_type], pressed); } else { - pr_debug("[TouchKey] pressed:%d\n", pressed); + printk(KERN_DEBUG "[TouchKey] pressed:%d\n", pressed); } #endif } @@ -756,7 +739,7 @@ static irqreturn_t touchkey_interrupt(int irq, void *dev_id) #if 0 if (gpio_get_value(_3_GPIO_TOUCH_INT)) { - pr_debug("[TouchKey] Unknown state.\n", __func__); + printk(KERN_DEBUG "[TouchKey] Unknown state.\n", __func__); return IRQ_HANDLED; } #endif @@ -780,7 +763,8 @@ static irqreturn_t touchkey_interrupt(int irq, void *dev_id) if (!ret) break; else { - pr_debug("[TouchKey] i2c read failed, ret:%d, retry: %d\n", + printk(KERN_DEBUG + "[TouchKey] i2c read failed, ret:%d, retry: %d\n", ret, retry); continue; } @@ -821,16 +805,15 @@ static irqreturn_t touchkey_interrupt(int irq, void *dev_id) pressed = !(data[0] & TK_BIT_PRESS_EV); if (keycode_type <= 0 || keycode_type >= touchkey_count) { - pr_debug("[Touchkey] keycode_type err\n"); + printk(KERN_DEBUG "[Touchkey] keycode_type err\n"); return IRQ_HANDLED; } - if (pressed) { + if (pressed) set_touchkey_debug('P'); - } if (get_tsp_status() && pressed) - pr_debug("[TouchKey] touchkey pressed" + printk(KERN_DEBUG "[TouchKey] touchkey pressed" " but don't send event because touch is pressed.\n"); else { input_report_key(touchkey_driver->input_dev, @@ -844,14 +827,14 @@ static irqreturn_t touchkey_interrupt(int irq, void *dev_id) printk(KERN_DEBUG "search key sensitivity = %d\n", search_sensitivity); if (keycode_type == 2) - pr_debug("back key sensitivity = %d\n", + printk(KERN_DEBUG "back key sensitivity = %d\n", back_sensitivity); #ifdef CONFIG_TARGET_LOCALE_NA if (keycode_type == 3) - pr_debug("home key sensitivity = %d\n", + printk(KERN_DEBUG "home key sensitivity = %d\n", home_sensitivity); if (keycode_type == 4) - pr_debug("menu key sensitivity = %d\n", + printk(KERN_DEBUG "menu key sensitivity = %d\n", menu_sensitivity); #endif @@ -871,7 +854,7 @@ static int sec_touchkey_early_suspend(struct early_suspend *h) disable_irq(tkey_i2c->irq); ret = cancel_work_sync(&tkey_i2c->update_work); if (ret) { - pr_debug("[Touchkey] enable_irq ret=%d\n", ret); + printk(KERN_DEBUG "[Touchkey] enable_irq ret=%d\n", ret); enable_irq(tkey_i2c->irq); } @@ -884,9 +867,9 @@ static int sec_touchkey_early_suspend(struct early_suspend *h) touchkey_enable = 0; set_touchkey_debug('S'); - pr_debug("[TouchKey] sec_touchkey_early_suspend\n"); + printk(KERN_DEBUG "[TouchKey] sec_touchkey_early_suspend\n"); if (touchkey_enable < 0) { - pr_debug("[TouchKey] ---%s---touchkey_enable: %d\n", + printk(KERN_DEBUG "[TouchKey] ---%s---touchkey_enable: %d\n", __func__, touchkey_enable); return 0; } @@ -909,13 +892,13 @@ static int sec_touchkey_late_resume(struct early_suspend *h) #endif set_touchkey_debug('R'); - pr_debug("[TouchKey] sec_touchkey_late_resume\n"); + printk(KERN_DEBUG "[TouchKey] sec_touchkey_late_resume\n"); /* enable ldo11 */ tkey_i2c->pdata->power_on(1); if (touchkey_enable < 0) { - pr_debug("[TouchKey] ---%s---touchkey_enable: %d\n", + printk(KERN_DEBUG "[TouchKey] ---%s---touchkey_enable: %d\n", __func__, touchkey_enable); return 0; } @@ -932,7 +915,7 @@ static int sec_touchkey_late_resume(struct early_suspend *h) touchled_cmd_reversed = 0; i2c_touchkey_write(tkey_i2c->client, (u8 *) &touchkey_led_status, 1); - pr_debug("[Touchkey] LED returned on\n"); + printk(KERN_DEBUG "[Touchkey] LED returned on\n"); } #ifdef TEST_JIG_MODE i2c_touchkey_write(tkey_i2c->client, &get_touch, 1); @@ -951,7 +934,7 @@ static int touchkey_i2c_check(struct touchkey_i2c *tkey_i2c) ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3); if (ret < 0) { - pr_err("[TouchKey] module version read fail\n"); + printk(KERN_ERR "[TouchKey] module version read fail\n"); return ret; } @@ -983,8 +966,8 @@ static ssize_t touch_version_read(struct device *dev, count = sprintf(buf, "0x%x\n", data[1]); - pr_debug("[TouchKey] touch_version_read 0x%x\n", data[1]); - pr_debug("[TouchKey] module_version_read 0x%x\n", data[2]); + printk(KERN_DEBUG "[TouchKey] touch_version_read 0x%x\n", data[1]); + printk(KERN_DEBUG "[TouchKey] module_version_read 0x%x\n", data[2]); return count; } @@ -1006,15 +989,16 @@ void touchkey_update_func(struct work_struct *work) #if defined(CONFIG_TARGET_LOCALE_NAATT) char data[3]; i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3); - pr_debug("[Touchkey] %s: F/W version: 0x%x, Module version:0x%x\n", + printk(KERN_DEBUG "[%s] F/W version: 0x%x, Module version:0x%x\n", __func__, data[1], data[2]); #endif tkey_i2c->update_status = TK_UPDATE_DOWN; - pr_debug("[Touchkey] %s: start\n", __func__); + printk(KERN_DEBUG "[TouchKey] %s start\n", __func__); touchkey_enable = 0; while (retry--) { if (ISSP_main(tkey_i2c) == 0) { - pr_debug("[TouchKey] touchkey_update succeeded\n"); + printk(KERN_DEBUG + "[TouchKey] touchkey_update succeeded\n"); msleep(50); touchkey_enable = 1; #if defined(TK_HAS_AUTOCAL) @@ -1078,17 +1062,6 @@ static ssize_t touch_update_read(struct device *dev, return count; } -static ssize_t touchkey_led_control_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret; - - ret = sprintf(buf, "%d\n", touchkey_led_status); - pr_info("[Touchkey] %s: touchkey_led_status=%d\n", __func__, touchkey_led_status); - - return ret; -} - static ssize_t touchkey_led_control(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) @@ -1104,13 +1077,13 @@ static ssize_t touchkey_led_control(struct device *dev, #endif ret = sscanf(buf, "%d", &data); if (ret != 1) { - printk(KERN_DEBUG "[Touchkey] %s: %d err\n", + printk(KERN_DEBUG "[TouchKey] %s, %d err\n", __func__, __LINE__); return size; } if (data != 1 && data != 2) { - printk(KERN_DEBUG "[Touchkey] %s: wrong cmd %x\n", + printk(KERN_DEBUG "[TouchKey] %s wrong cmd %x\n", __func__, data); return size; } @@ -1122,154 +1095,17 @@ static ssize_t touchkey_led_control(struct device *dev, data = ledCmd[data-1]; #endif - if (touch_led_disabled == 0) { - ret = i2c_touchkey_write(tkey_i2c->client, (u8 *) &data, 1); - } - - if(data == ledCmd[0]) { - if (touch_led_disabled == 0) { - if (timer_pending(&touch_led_timer) == 0) { - pr_debug("[Touchkey] %s: add_timer\n", __func__); - touch_led_timer.expires = jiffies + (HZ * touch_led_timeout); - add_timer(&touch_led_timer); - } else { - mod_timer(&touch_led_timer, jiffies + (HZ * touch_led_timeout)); - } - } - } else { - if (timer_pending(&touch_led_timer) == 1) { - pr_debug("[Touchkey] %s: del_timer\n", __func__); - del_timer(&touch_led_timer); - } - } - - if (ret == -ENODEV) { - pr_err("[Touchkey] error to write i2c\n"); + ret = i2c_touchkey_write(tkey_i2c->client, (u8 *) &data, 1); + + if (ret == -ENODEV) touchled_cmd_reversed = 1; - } - pr_debug("[Touchkey] %s: touchkey_led_status=%d\n", __func__, data); touchkey_led_status = data; return size; } -static ssize_t touch_led_force_disable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret; - - ret = sprintf(buf, "%d\n", touch_led_disabled); - pr_info("[Touchkey] %s: touch_led_disabled=%d\n", __func__, touch_led_disabled); - - return ret; -} - -static ssize_t touch_led_force_disable_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t size) -{ - struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev); - static const int ledCmd[] = {TK_CMD_LED_ON, TK_CMD_LED_OFF}; - int data, ret; - - ret = sscanf(buf, "%d\n", &data); - if (unlikely(ret != 1)) { - pr_err("[Touchkey] %s: err\n", __func__); - return -EINVAL; - } - pr_info("[Touchkey] %s: value=%d\n", __func__, data); - - if (data == 1) { - i2c_touchkey_write(tkey_i2c->client, (u8 *) &ledCmd[1], 1); - touchkey_led_status = TK_CMD_LED_OFF; - } - touch_led_disabled = data; - - return size; -} -static DEVICE_ATTR(force_disable, S_IRUGO | S_IWUSR | S_IWGRP, - touch_led_force_disable_show, touch_led_force_disable_store); - -static ssize_t touch_led_timeout_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret; - - ret = sprintf(buf, "%d\n", touch_led_timeout); - pr_info("[Touchkey] %s: touch_led_timeout=%d\n", __func__, touch_led_timeout); - - return ret; -} - -static ssize_t touch_led_timeout_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t size) -{ - int data; - int ret; - - ret = sscanf(buf, "%d\n", &data); - if (unlikely(ret != 1)) { - pr_err("[Touchkey] %s: err\n", __func__); - return -EINVAL; - } - pr_info("[Touchkey] %s: new timeout=%d\n", __func__, data); - touch_led_timeout = data; - - return size; -} -static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR | S_IWGRP, - touch_led_timeout_show, touch_led_timeout_store); - -void touch_led_timedout(unsigned long ptr) -{ - queue_work(tkey_i2c_local->wq, &tkey_i2c_local->work); -} - -void touch_led_timedout_work(struct work_struct *work) -{ - struct touchkey_i2c *tkey_i2c = container_of(work, struct touchkey_i2c, work); - static const int ledCmd[] = {TK_CMD_LED_ON, TK_CMD_LED_OFF}; - - if (touch_led_timeout != 0) - { - pr_debug("[Touchkey] %s: disabling touchled\n", __func__); - i2c_touchkey_write(tkey_i2c->client, (u8 *) &ledCmd[1], 1); - touchkey_led_status = TK_CMD_LED_OFF; - } -} - -void touchscreen_state_report(int state) -{ - static const int ledCmd[] = {TK_CMD_LED_ON, TK_CMD_LED_OFF}; - - if (touch_led_disabled == 0) { - if (state == 1) { - if(touchkey_led_status == TK_CMD_LED_OFF) { - pr_debug("[Touchkey] %s: enable touchleds\n", __func__); - i2c_touchkey_write(tkey_i2c_local->client, (u8 *) &ledCmd[0], 1); - touchkey_led_status = TK_CMD_LED_ON; - } else { - if (timer_pending(&touch_led_timer) == 1) { - pr_debug("[Touchkey] %s: mod_timer\n", __func__); - mod_timer(&touch_led_timer, jiffies + (HZ * touch_led_timeout)); - } - } - } else if (state == 0) { - if (timer_pending(&touch_led_timer) == 1) { - pr_debug("[Touchkey] %s: mod_timer\n", __func__); - mod_timer(&touch_led_timer, jiffies + (HZ * touch_led_timeout)); - } else if (touchkey_led_status == TK_CMD_LED_ON){ - pr_debug("[Touchkey] %s: add_timer\n", __func__); - touch_led_timer.expires = jiffies + (HZ * touch_led_timeout); - add_timer(&touch_led_timer); - } - } - } -} - -#if defined(TK_USE_4KEY) || defined(CONFIG_TARGET_LOCALE_NAATT) || defined(CONFIG_TARGET_LOCALE_NA) +#if defined(TK_USE_4KEY) static ssize_t touchkey_menu_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1277,20 +1113,20 @@ static ssize_t touchkey_menu_show(struct device *dev, u8 data[18] = { 0, }; int ret; - pr_debug("[Touchkey] %s called\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 18); #ifdef CONFIG_TARGET_LOCALE_NA if (tkey_i2c->module_ver < 8) { - pr_debug("[Touchkey] %s: data[12] =%d,data[13] = %d\n", + printk(KERN_DEBUG "called %s data[12] =%d,data[13] = %d\n", __func__, data[12], data[13]); menu_sensitivity = ((0x00FF & data[12]) << 8) | data[13]; } else { - pr_debug("[Touchkey] %s: data[17] =%d\n", __func__, + printk(KERN_DEBUG "called %s data[17] =%d\n", __func__, data[17]); menu_sensitivity = data[17]; } #else - pr_debug("[Touchkey] %s: data[10] =%d,data[11] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[10] =%d,data[11] = %d\n", __func__, data[10], data[11]); menu_sensitivity = ((0x00FF & data[10]) << 8) | data[11]; #endif /* CONFIG_TARGET_LOCALE_NA */ @@ -1304,20 +1140,20 @@ static ssize_t touchkey_home_show(struct device *dev, u8 data[18] = { 0, }; int ret; - pr_debug("[TouchKey] %s called\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 18); #ifdef CONFIG_TARGET_LOCALE_NA if (tkey_i2c->module_ver < 8) { - pr_debug("[Touchkey] %s: data[10] =%d,data[11] = %d\n", + printk(KERN_DEBUG "called %s data[10] =%d,data[11] = %d\n", __func__, data[10], data[11]); home_sensitivity = ((0x00FF & data[10]) << 8) | data[11]; } else { - pr_debug("[Touchkey] %s: data[15] =%d\n", __func__, + printk(KERN_DEBUG "called %s data[15] =%d\n", __func__, data[15]); home_sensitivity = data[15]; } #else - pr_debug("[Touchkey] %s: data[12] =%d,data[13] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[12] =%d,data[13] = %d\n", __func__, data[12], data[13]); home_sensitivity = ((0x00FF & data[12]) << 8) | data[13]; #endif /* CONFIG_TARGET_LOCALE_NA */ @@ -1331,20 +1167,20 @@ static ssize_t touchkey_back_show(struct device *dev, u8 data[18] = { 0, }; int ret; - pr_debug("[TouchKey] %s called\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 18); #ifdef CONFIG_TARGET_LOCALE_NA if (tkey_i2c->module_ver < 8) { - pr_debug("[Touchkey] %s: data[8] =%d,data[9] = %d\n", + printk(KERN_DEBUG "called %s data[8] =%d,data[9] = %d\n", __func__, data[8], data[9]); back_sensitivity = ((0x00FF & data[8]) << 8) | data[9]; } else { - pr_debug("[Touchkey] %s: data[13] =%d\n", __func__, + printk(KERN_DEBUG "called %s data[13] =%d\n", __func__, data[13]); back_sensitivity = data[13]; } #else - pr_debug("[Touchkey] %s: data[14] =%d,data[15] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[14] =%d,data[15] = %d\n", __func__, data[14], data[15]); back_sensitivity = ((0x00FF & data[14]) << 8) | data[15]; #endif /* CONFIG_TARGET_LOCALE_NA */ @@ -1358,20 +1194,20 @@ static ssize_t touchkey_search_show(struct device *dev, u8 data[18] = { 0, }; int ret; - pr_debug("[TouchKey] %s called\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 18); #ifdef CONFIG_TARGET_LOCALE_NA if (tkey_i2c->module_ver < 8) { - pr_debug("[Touchkey] %s: data[6] =%d,data[7] = %d\n", + printk(KERN_DEBUG "called %s data[6] =%d,data[7] = %d\n", __func__, data[6], data[7]); search_sensitivity = ((0x00FF & data[6]) << 8) | data[7]; } else { - pr_debug("[Touchkey] %s: data[11] =%d\n", __func__, + printk(KERN_DEBUG "called %s data[11] =%d\n", __func__, data[11]); search_sensitivity = data[11]; } #else - pr_debug("[Touchkey] %s: data[16] =%d,data[17] = %d\n", __func__, + printk(KERN_DEBUG "called %s data[16] =%d,data[17] = %d\n", __func__, data[16], data[17]); search_sensitivity = ((0x00FF & data[16]) << 8) | data[17]; #endif /* CONFIG_TARGET_LOCALE_NA */ @@ -1390,13 +1226,17 @@ static ssize_t touchkey_menu_show(struct device *dev, ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 14); - pr_debug("[Touchkey] %s: data[13] =%d\n", __func__, data[13]); - menu_sensitivity = data[13]; + printk(KERN_DEBUG "called %s data[12] = %d, data[13] =%d\n", __func__, + data[12], data[13]); + menu_sensitivity = ((0x00FF & data[12]) << 8) | data[13]; + printk(KERN_DEBUG "called %s menu_sensitivity =%d\n", __func__, + menu_sensitivity); + #else u8 data[10]; int ret; - pr_debug("[TouchKey] %s called\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10); menu_sensitivity = data[7]; #endif @@ -1415,13 +1255,16 @@ static ssize_t touchkey_back_show(struct device *dev, ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 14); - pr_debug("[Touchkey] %s: data[11] =%d\n", __func__, data[11]); - back_sensitivity = data[11]; + printk(KERN_DEBUG "called %s data[10] = %d, data[11] =%d\n", __func__, + data[10], data[11]); + back_sensitivity =((0x00FF & data[10]) << 8) | data[11]; + printk(KERN_DEBUG "called %s back_sensitivity =%d\n", __func__, + back_sensitivity); #else u8 data[10]; int ret; - pr_debug("[TouchKey] %s called\n", __func__); + printk(KERN_DEBUG "called %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10); back_sensitivity = data[9]; #endif @@ -1452,7 +1295,7 @@ static ssize_t autocalibration_status(struct device *dev, int ret; struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev); - pr_debug("[Touchkey] %s\n", __func__); + printk(KERN_DEBUG "[Touchkey] %s\n", __func__); ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 6); if ((data[5] & TK_BIT_AUTOCAL)) @@ -1498,19 +1341,20 @@ static ssize_t set_touchkey_update_show(struct device *dev, while (retry--) { if (ISSP_main(tkey_i2c) == 0) { - pr_err("[TouchKey] Touchkey_update succeeded\n"); + printk(KERN_ERR + "[TouchKey]Touchkey_update succeeded\n"); tkey_i2c->update_status = TK_UPDATE_PASS; count = 1; msleep(50); break; } - pr_err("[TouchKey] touchkey_update failed... retry...\n"); + printk(KERN_ERR "touchkey_update failed... retry...\n"); } if (retry <= 0) { /* disable ldo11 */ tkey_i2c->pdata->power_on(0); count = 0; - pr_err("[TouchKey] Touchkey_update fail\n"); + printk(KERN_ERR "[TouchKey]Touchkey_update fail\n"); tkey_i2c->update_status = TK_UPDATE_FAIL; enable_irq(tkey_i2c->irq); return count; @@ -1541,8 +1385,8 @@ static ssize_t set_touchkey_firm_version_read_show(struct device *dev, i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3); count = sprintf(buf, "0x%x\n", data[1]); - pr_debug("[TouchKey] touch_version_read 0x%x\n", data[1]); - pr_debug("[TouchKey] module_version_read 0x%x\n", data[2]); + printk(KERN_DEBUG "[TouchKey] touch_version_read 0x%x\n", data[1]); + printk(KERN_DEBUG "[TouchKey] module_version_read 0x%x\n", data[2]); return count; } @@ -1553,7 +1397,8 @@ static ssize_t set_touchkey_firm_status_show(struct device *dev, struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev); int count = 0; - pr_debug("[TouchKey] touch_update_read: update_status %d\n", + printk(KERN_DEBUG + "[TouchKey] touch_update_read: update_status %d\n", tkey_i2c->update_status); if (tkey_i2c->update_status == TK_UPDATE_PASS) @@ -1570,7 +1415,7 @@ static DEVICE_ATTR(recommended_version, S_IRUGO | S_IWUSR | S_IWGRP, touch_version_read, touch_version_write); static DEVICE_ATTR(updated_version, S_IRUGO | S_IWUSR | S_IWGRP, touch_update_read, touch_update_write); -static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR | S_IWGRP, touchkey_led_control_show, +static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR | S_IWGRP, NULL, touchkey_led_control); static DEVICE_ATTR(touchkey_menu, S_IRUGO | S_IWUSR | S_IWGRP, touchkey_menu_show, NULL); @@ -1597,7 +1442,7 @@ static DEVICE_ATTR(touchkey_brightness, S_IRUGO | S_IWUSR | S_IWGRP, NULL, brightness_control); #endif -#if 0 /* #if defined(CONFIG_TARGET_LOCALE_NAATT) */ +#if defined(CONFIG_TARGET_LOCALE_NAATT) static DEVICE_ATTR(touchkey_autocal_start, S_IRUGO | S_IWUSR | S_IWGRP, NULL, set_touchkey_autocal_testmode); #endif @@ -1636,7 +1481,7 @@ static struct attribute *touchkey_attributes[] = { #ifdef LED_LDO_WITH_REGULATOR &dev_attr_touchkey_brightness.attr, #endif -#if 0/* defined(CONFIG_TARGET_LOCALE_NAATT) */ +#if defined(CONFIG_TARGET_LOCALE_NAATT) &dev_attr_touchkey_autocal_start.attr, #endif #if defined(TK_HAS_AUTOCAL) @@ -1652,8 +1497,6 @@ static struct attribute *touchkey_attributes[] = { &dev_attr_autocal_enable.attr, &dev_attr_autocal_stat.attr, #endif - &dev_attr_timeout.attr, - &dev_attr_force_disable.attr, NULL, }; @@ -1673,7 +1516,7 @@ static int i2c_touchkey_probe(struct i2c_client *client, int i; int ret; - pr_debug("[TouchKey] i2c_touchkey_probe\n"); + printk(KERN_DEBUG "[TouchKey] i2c_touchkey_probe\n"); if (pdata == NULL) { printk(KERN_ERR "%s: no pdata\n", __func__); @@ -1683,7 +1526,7 @@ static int i2c_touchkey_probe(struct i2c_client *client, /*Check I2C functionality */ ret = i2c_check_functionality(client->adapter, I2C_FUNC_I2C); if (ret == 0) { - pr_err("[Touchkey] No I2C functionality found\n"); + printk(KERN_ERR "[Touchkey] No I2C functionality found\n"); ret = -ENODEV; return ret; } @@ -1691,15 +1534,14 @@ static int i2c_touchkey_probe(struct i2c_client *client, /*Obtain kernel memory space for touchkey i2c */ tkey_i2c = kzalloc(sizeof(struct touchkey_i2c), GFP_KERNEL); if (NULL == tkey_i2c) { - pr_err("[Touchkey] failed to allocate tkey_i2c.\n"); + printk(KERN_ERR "[Touchkey] failed to allocate tkey_i2c.\n"); return -ENOMEM; } - tkey_i2c_local = tkey_i2c; input_dev = input_allocate_device(); if (!input_dev) { - pr_err("[Touchkey] failed to allocate input device\n"); + printk(KERN_ERR"[Touchkey] failed to allocate input device\n"); kfree(tkey_i2c); return -ENOMEM; } @@ -1728,7 +1570,7 @@ static int i2c_touchkey_probe(struct i2c_client *client, ret = input_register_device(input_dev); if (ret) { - pr_err("[Touchkey] failed to register input device\n"); + printk(KERN_ERR"[Touchkey] failed to register input device\n"); input_free_device(input_dev); kfree(tkey_i2c); return err; @@ -1746,24 +1588,27 @@ static int i2c_touchkey_probe(struct i2c_client *client, tkey_i2c->dev = device_create(sec_class, NULL, 0, NULL, "sec_touchkey"); if (IS_ERR(tkey_i2c->dev)) { - pr_err("[TouchKey] Failed to create device(tkey_i2c->dev)!\n"); + printk(KERN_ERR "Failed to create device(tkey_i2c->dev)!\n"); input_unregister_device(input_dev); } else { dev_set_drvdata(tkey_i2c->dev, tkey_i2c); ret = sysfs_create_group(&tkey_i2c->dev->kobj, &touchkey_attr_group); if (ret) { - pr_err("[TouchKey]: failed to create sysfs group\n"); + printk(KERN_ERR + "[TouchKey]: failed to create sysfs group\n"); } } #if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1) gpio_request(GPIO_OLED_DET, "OLED_DET"); ret = gpio_get_value(GPIO_OLED_DET); - pr_debug("[TouchKey] OLED_DET = %d\n", ret); + printk(KERN_DEBUG + "[TouchKey] OLED_DET = %d\n", ret); if (ret == 0) { - pr_debug("[TouchKey] device wasn't connected to board\n"); + printk(KERN_DEBUG + "[TouchKey] device wasn't connected to board\n"); input_unregister_device(input_dev); touchkey_probe = false; @@ -1772,7 +1617,7 @@ static int i2c_touchkey_probe(struct i2c_client *client, #else ret = touchkey_i2c_check(tkey_i2c); if (ret < 0) { - pr_debug("[TouchKey] probe failed\n"); + printk(KERN_DEBUG"[TouchKey] probe failed\n"); input_unregister_device(input_dev); touchkey_probe = false; return -EBUSY; @@ -1784,7 +1629,8 @@ static int i2c_touchkey_probe(struct i2c_client *client, IRQF_DISABLED | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, tkey_i2c->name, tkey_i2c); if (ret < 0) { - pr_err("[Touchkey]: failed to request irq(%d) - %d\n", + printk(KERN_ERR + "[Touchkey]: failed to request irq(%d) - %d\n", tkey_i2c->irq, ret); input_unregister_device(input_dev); touchkey_probe = false; @@ -1796,7 +1642,8 @@ static int i2c_touchkey_probe(struct i2c_client *client, #if defined(TK_HAS_FIRMWARE_UPDATE) ret = touchkey_firmware_update(tkey_i2c); if (ret < 0) { - pr_err("[Touchkey]: failed firmware updating process (%d)\n", + printk(KERN_ERR + "[Touchkey]: failed firmware updating process (%d)\n", ret); input_unregister_device(input_dev); touchkey_probe = false; @@ -1816,17 +1663,6 @@ static int i2c_touchkey_probe(struct i2c_client *client, touchkey_autocalibration(tkey_i2c); #endif set_touchkey_debug('K'); - - // init workqueue - tkey_i2c->wq = create_singlethread_workqueue("tkey_i2c_wq"); - if (!tkey_i2c->wq) { - ret = -ENOMEM; - pr_err("[Touchkey] %s: could not create workqueue\n", __func__); - } - - /* this is the thread function we run on the work queue */ - INIT_WORK(&tkey_i2c->work, touch_led_timedout_work); - return 0; } @@ -1844,13 +1680,13 @@ static int __init touchkey_init(void) #if defined(CONFIG_MACH_M0) if (system_rev < TOUCHKEY_FW_UPDATEABLE_HW_REV) { - pr_debug("[Touchkey] Doesn't support this board rev %d\n", + printk(KERN_DEBUG "[Touchkey] Doesn't support this board rev %d\n", system_rev); return 0; } #elif defined(CONFIG_MACH_C1) if (system_rev < TOUCHKEY_FW_UPDATEABLE_HW_REV) { - pr_debug("[Touchkey] Doesn't support this board rev %d\n", + printk(KERN_DEBUG "[Touchkey] Doesn't support this board rev %d\n", system_rev); return 0; } @@ -1863,23 +1699,19 @@ static int __init touchkey_init(void) ret = i2c_add_driver(&touchkey_i2c_driver); if (ret) { - pr_err("[TouchKey] registration failed, module not inserted.ret= %d\n", + printk(KERN_ERR + "[TouchKey] registration failed, module not inserted.ret= %d\n", ret); } #ifdef TEST_JIG_MODE i2c_touchkey_write(tkey_i2c->client, &get_touch, 1); #endif - - // init the touchled timer - init_timer(&touch_led_timer); - touch_led_timer.function = touch_led_timedout; - return ret; } static void __exit touchkey_exit(void) { - pr_debug("[TouchKey] %s\n", __func__); + printk(KERN_DEBUG "[TouchKey] %s\n", __func__); i2c_del_driver(&touchkey_i2c_driver); } diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.h b/drivers/input/keyboard/cypress/cypress-touchkey.h deleted file mode 100644 index 61abce2..0000000 --- a/drivers/input/keyboard/cypress/cypress-touchkey.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2012 The CyanogenMod Project - * - * Authors: Daniel Hillenbrand - * Marco Hillenbrand - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -void touchscreen_state_report(int state); diff --git a/drivers/input/touchscreen/mms152_ts.c b/drivers/input/touchscreen/mms152_ts.c index ad1dc98..fa1d295 100644 --- a/drivers/input/touchscreen/mms152_ts.c +++ b/drivers/input/touchscreen/mms152_ts.c @@ -49,8 +49,6 @@ #include -#include "../keyboard/cypress/cypress-touchkey.h" - #ifdef CONFIG_INPUT_FBSUSPEND #ifdef CONFIG_DRM #include @@ -977,10 +975,6 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) if (info->panel == 'M') { if (info->finger_state[id] != 0) { info->finger_state[id] = 0; - - // report state to cypress-touchkey for backlight timeout - touchscreen_state_report(0); - #ifdef CONFIG_LCD_FREQ_SWITCH dev_notice(&client->dev, "R(%c)(%d) [%2d]", info->ldi, @@ -994,10 +988,6 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) } else { if (info->finger_state[id] != 0) { info->finger_state[id] = 0; - - // report state to cypress-touchkey for backlight timeout - touchscreen_state_report(0); - dev_notice(&client->dev, "R [%2d]", id); } @@ -1006,10 +996,6 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) if (info->panel == 'M') { if (info->finger_state[id] != 0) { info->finger_state[id] = 0; - - // report state to cypress-touchkey for backlight timeout - touchscreen_state_report(0); - #ifdef CONFIG_LCD_FREQ_SWITCH dev_notice(&client->dev, "R(%c)(%d) [%2d],([%4d],[%3d])", @@ -1025,10 +1011,6 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) } else { if (info->finger_state[id] != 0) { info->finger_state[id] = 0; - - // report state to cypress-touchkey for backlight timeout - touchscreen_state_report(0); - dev_notice(&client->dev, "R [%2d],([%4d],[%3d]),S:%d W:%d", id, x, y, tmp[4], tmp[5]); @@ -1058,10 +1040,6 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) #ifdef CONFIG_SAMSUNG_PRODUCT_SHIP if (info->finger_state[id] == 0) { info->finger_state[id] = 1; - - // report state to cypress-touchkey for backlight timeout - touchscreen_state_report(1); - #ifdef CONFIG_LCD_FREQ_SWITCH dev_notice(&client->dev, "P(%c)(%d) [%2d]", info->ldi, @@ -1074,10 +1052,6 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) #else if (info->finger_state[id] == 0) { info->finger_state[id] = 1; - - // report state to cypress-touchkey for backlight timeout - touchscreen_state_report(1); - #ifdef CONFIG_LCD_FREQ_SWITCH dev_notice(&client->dev, "P(%c)(%d) [%2d],([%4d],[%3d]) w=%d, major=%d, minor=%d, angle=%d, palm=%d", @@ -1108,20 +1082,12 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) #ifdef CONFIG_SAMSUNG_PRODUCT_SHIP if (info->finger_state[id] == 0) { info->finger_state[id] = 1; - - // report state to cypress-touchkey for backlight timeout - touchscreen_state_report(1); - dev_notice(&client->dev, "P [%2d]", id); } #else if (info->finger_state[id] == 0) { info->finger_state[id] = 1; - - // report state to cypress-touchkey for backlight timeout - touchscreen_state_report(1); - dev_notice(&client->dev, "P [%2d],([%4d],[%3d]),S:%d W:%d", id, x, y, tmp[4], tmp[5]); diff --git a/drivers/input/touchscreen/mms_ts.c b/drivers/input/touchscreen/mms_ts.c index ebca68c..cdb47f7 100644 --- a/drivers/input/touchscreen/mms_ts.c +++ b/drivers/input/touchscreen/mms_ts.c @@ -50,8 +50,6 @@ #include -#include "../keyboard/cypress/cypress-touchkey.h" - #define MAX_FINGERS 10 #define MAX_WIDTH 30 #define MAX_PRESSURE 255 @@ -682,9 +680,6 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) , angle, palm); #else if (info->finger_state[id] != 0) { - // report state to cypress-touchkey for backlight timeout - touchscreen_state_report(0); - dev_notice(&client->dev, "finger [%d] up, palm %d\n", id, palm); } @@ -723,10 +718,6 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) #else if (info->finger_state[id] == 0) { info->finger_state[id] = 1; - - // report state to cypress-touchkey for backlight timeout - touchscreen_state_report(1); - dev_notice(&client->dev, "finger [%d] down, palm %d\n", id, palm); } diff --git a/drivers/input/touchscreen/mxt224_u1.c b/drivers/input/touchscreen/mxt224_u1.c index cd0674f..5a243fb 100644 --- a/drivers/input/touchscreen/mxt224_u1.c +++ b/drivers/input/touchscreen/mxt224_u1.c @@ -28,8 +28,6 @@ #include #include -#include "../keyboard/cypress/cypress-touchkey.h" - #define OBJECT_TABLE_START_ADDRESS 7 #define OBJECT_TABLE_ELEMENT_SIZE 6 @@ -1339,10 +1337,6 @@ static void report_input_data(struct mxt224_data *data) copy_data->lock_status = 1; } } - - /* tell cypress keypad we had finger activity */ - touchscreen_state_report(touch_is_pressed); - } void palm_recovery(void) -- cgit v1.1 From ca322a3f77e20f3988dbaec53f2d209929c8ab74 Mon Sep 17 00:00:00 2001 From: Daniel Hillenbrand Date: Tue, 27 Aug 2013 05:50:13 -0400 Subject: smdk4412: max77693_haptic: move sysfs node Change-Id: If25044f5eb36ea0374c691c8fee3965b785b8cbf --- drivers/motor/max77693_haptic.c | 65 +++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/motor/max77693_haptic.c b/drivers/motor/max77693_haptic.c index 1836e33..beb7f2a 100644 --- a/drivers/motor/max77693_haptic.c +++ b/drivers/motor/max77693_haptic.c @@ -3,7 +3,7 @@ * * Copyright (C) 2011 ByungChang Cha * Copyright (C) 2012 The CyanogenMod Project - * Daniel Hillenbrand + * Daniel Hillenbrand * * 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 @@ -260,64 +260,46 @@ void vibtonz_pwm(int nForce) EXPORT_SYMBOL(vibtonz_pwm); #endif -static ssize_t pwm_val_show(struct device *dev, +static ssize_t pwm_value_show(struct device *dev, struct device_attribute *attr, char *buf) { int count; - pwm_val = ((pwm_duty - 18525) * 100) / 18525; + pwm_val = ((pwm_duty - 18525) * 100) / 18525; count = sprintf(buf, "%lu\n", pwm_val); - pr_debug("[VIB] pwm_val: %lu\n", pwm_val); + pr_debug("[VIB] pwm_value: %lu\n", pwm_val); return count; } -ssize_t pwm_val_store(struct device *dev, +ssize_t pwm_value_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { if (kstrtoul(buf, 0, &pwm_val)) pr_err("[VIB] %s: error on storing pwm_val\n", __func__); - pr_info("[VIB] %s: pwm_val=%lu\n", __func__, pwm_val); + pr_info("[VIB] %s: pwm_value=%lu\n", __func__, pwm_val); - pwm_duty = (pwm_val * 18525) / 100 + 18525; + pwm_duty = (pwm_val * 18525) / 100 + 18525; - /* make sure new pwm duty is in range */ - if(pwm_duty > 37050) - { - pwm_duty = 37050; - } - else if (pwm_duty < 18525) - { - pwm_duty = 18525; - } + /* make sure new pwm duty is in range */ + if(pwm_duty > 37050) + { + pwm_duty = 37050; + } + else if (pwm_duty < 18525) + { + pwm_duty = 18525; + } pr_info("[VIB] %s: pwm_duty=%d\n", __func__, pwm_duty); return size; } -static DEVICE_ATTR(pwm_val, S_IRUGO | S_IWUSR, - pwm_val_show, pwm_val_store); - -static int create_vibrator_sysfs(void) -{ - int ret; - struct kobject *vibrator_kobj; - vibrator_kobj = kobject_create_and_add("vibrator", NULL); - if (unlikely(!vibrator_kobj)) - return -ENOMEM; - - ret = sysfs_create_file(vibrator_kobj, - &dev_attr_pwm_val.attr); - if (unlikely(ret < 0)) { - pr_err("[VIB] sysfs_create_file failed: %d\n", ret); - return ret; - } - - return 0; -} +static DEVICE_ATTR(pwm_value, S_IRUGO | S_IWUSR, + pwm_value_show, pwm_value_store); static int max77693_haptic_probe(struct platform_device *pdev) { @@ -381,8 +363,6 @@ static int max77693_haptic_probe(struct platform_device *pdev) hap_data->tout_dev.get_time = haptic_get_time; hap_data->tout_dev.enable = haptic_enable; - create_vibrator_sysfs(); - #ifdef CONFIG_ANDROID_TIMED_OUTPUT error = timed_output_dev_register(&hap_data->tout_dev); if (error < 0) { @@ -390,8 +370,15 @@ static int max77693_haptic_probe(struct platform_device *pdev) error = -EFAULT; goto err_timed_output_register; } -#endif + pr_err("[VIB] timed_output device is registrated\n"); + + /* User controllable pwm level */ + error = device_create_file(hap_data->tout_dev.dev, &dev_attr_pwm_value); + if (error < 0) { + pr_err("[VIB] create sysfs fail: pwm_value\n"); + } +#endif pr_debug("[VIB] -- %s\n", __func__); return error; -- cgit v1.1 From 3afe058d7eccd99d0f6dd036ac1a36163f8c4434 Mon Sep 17 00:00:00 2001 From: arrrghhh Date: Sat, 31 Aug 2013 01:15:31 -0600 Subject: Fix kernel build error Change-Id: I1191517240ae7bcfb2fcbbffc98e22f28e8fa151 --- drivers/input/keyboard/cypress/cypress-touchkey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.c b/drivers/input/keyboard/cypress/cypress-touchkey.c index ef8a6b8..6c248a4 100644 --- a/drivers/input/keyboard/cypress/cypress-touchkey.c +++ b/drivers/input/keyboard/cypress/cypress-touchkey.c @@ -324,7 +324,7 @@ static ssize_t set_touchkey_autocal_testmode(struct device *dev, tkey_i2c->pdata->power_on(1); msleep(50); #if defined(TK_HAS_AUTOCAL) - touchkey_autocalibration(); + touchkey_autocalibration(tkey_i2c); #endif } } else { -- cgit v1.1 From 0a49c6da693e5f4ab5a9c8d1ceb2969a97b9e22b Mon Sep 17 00:00:00 2001 From: Dorian Snyder Date: Sun, 1 Sep 2013 22:05:46 -0700 Subject: d710: cypress: fix home button and auto-update defconfig Change-Id: I1dd142d0b168101a8170e742d115bf70a47daa48 --- drivers/input/keyboard/cypress/cypress-touchkey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.c b/drivers/input/keyboard/cypress/cypress-touchkey.c index 6c248a4..d73ec15 100644 --- a/drivers/input/keyboard/cypress/cypress-touchkey.c +++ b/drivers/input/keyboard/cypress/cypress-touchkey.c @@ -64,7 +64,7 @@ static int touchkey_keycode[] = { 0, KEY_MENU, KEY_ENTER, KEY_BACK, KEY_END, #elif defined(TK_USE_4KEY_TYPE_NA) - KEY_SEARCH, KEY_BACK, KEY_HOMEPAGE, KEY_MENU, + KEY_SEARCH, KEY_BACK, KEY_HOME, KEY_MENU, #elif defined(TK_USE_2KEY_TYPE_M0) KEY_BACK, KEY_MENU, -- cgit v1.1 From 1a05356029493b29f866cf04f7550243ef3ae687 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Thu, 19 Sep 2013 18:28:10 +0100 Subject: max77693: Standardize the output of the "online" property Return "0" when no power supply is present Fixes CYAN-2138 Change-Id: I4a4391a454e8e1c5681f8a27ce498f77b4934e28 --- drivers/battery/max77693_charger.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/battery/max77693_charger.c b/drivers/battery/max77693_charger.c index 35289a6..98fc901 100644 --- a/drivers/battery/max77693_charger.c +++ b/drivers/battery/max77693_charger.c @@ -1376,6 +1376,10 @@ static int max77693_charger_get_property(struct power_supply *psy, val->intval = max77693_get_online_type(chg_data); #else val->intval = max77693_get_cable_type(chg_data); + if (val->intval == POWER_SUPPLY_TYPE_BATTERY) { + /* Userspace expects 0 for no-supply */ + val->intval = 0; + } #endif break; case POWER_SUPPLY_PROP_CURRENT_MAX: -- cgit v1.1 From e531c03040b9ad3a86d3b751fb47b3362d85f373 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Thu, 19 Sep 2013 18:35:39 +0100 Subject: Revert "max77693: Standardize the output of the "online" property" This reverts commit 1a05356029493b29f866cf04f7550243ef3ae687, the enumerator breakage introduced by change Iafbd9fb45253b02d539ac0ba114f57b3bf9eeed4 can be reverted cleanly without further impact and it's a cleaner fix Change-Id: I351c320f98691241fbe321a0b1ac54152802deb4 --- drivers/battery/max77693_charger.c | 4 ---- drivers/power/power_supply_sysfs.c | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/battery/max77693_charger.c b/drivers/battery/max77693_charger.c index 98fc901..35289a6 100644 --- a/drivers/battery/max77693_charger.c +++ b/drivers/battery/max77693_charger.c @@ -1376,10 +1376,6 @@ static int max77693_charger_get_property(struct power_supply *psy, val->intval = max77693_get_online_type(chg_data); #else val->intval = max77693_get_cable_type(chg_data); - if (val->intval == POWER_SUPPLY_TYPE_BATTERY) { - /* Userspace expects 0 for no-supply */ - val->intval = 0; - } #endif break; case POWER_SUPPLY_PROP_CURRENT_MAX: diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index a647e74..a5235ab 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -42,7 +42,7 @@ static ssize_t power_supply_show_property(struct device *dev, struct device_attribute *attr, char *buf) { static char *type_text[] = { - "Unknown", "Battery", "UPS", "Mains", "USB", + "Battery", "UPS", "Mains", "USB", "USB_DCP", "USB_CDP", "USB_ACA", "DOCK", "MISC", "WIRELESS", "OTG" }; -- cgit v1.1 From 7b9279ea69dd091a8b659c1ea38266e0fe3fb289 Mon Sep 17 00:00:00 2001 From: Tanguy Pruvot Date: Sat, 19 Oct 2013 14:57:41 +0200 Subject: tzic: add required ifdef for sec asm extension others files using this implements this flag and ifdef to keep compat with gcc 4.4.3 Change-Id: I290caa7727b750be2f82f13eb5260b877700f81d --- drivers/misc/Makefile | 1 + drivers/misc/tzic.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b7291cf..881a9af 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -88,4 +88,5 @@ obj-$(CONFIG_SLP_LOWMEM_NOTIFY) += slp_lowmem_notify.o obj-$(CONFIG_MACH_M0_CTC) += cw_tty.o # Secure OS Mobicore Interface +CFLAGS_tzic.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) obj-$(CONFIG_MOBICORE_SUPPORT) += tzic.o diff --git a/drivers/misc/tzic.c b/drivers/misc/tzic.c index e1da409..6a5e3ba 100644 --- a/drivers/misc/tzic.c +++ b/drivers/misc/tzic.c @@ -42,7 +42,9 @@ u32 exynos_smc1(u32 cmd, u32 arg1, u32 arg2, u32 arg3) register u32 reg3 __asm__("r3") = arg3; __asm__ volatile ( - ".arch_extension sec\n" +#ifdef REQUIRES_SEC + ".arch_extension sec\n" +#endif "smc 0\n" : "+r"(reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3) ); @@ -65,7 +67,9 @@ int exynos_smc_read_oemflag(u32 ctrl_word, u32 *val) reg2 = idx; __asm__ volatile ( +#ifdef REQUIRES_SEC ".arch_extension sec\n" +#endif "smc 0\n" :"+r" (reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3) @@ -79,7 +83,9 @@ int exynos_smc_read_oemflag(u32 ctrl_word, u32 *val) reg2 = idx; __asm__ volatile ( +#ifdef REQUIRES_SEC ".arch_extension sec\n" +#endif "smc 0\n" :"+r" (reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3) -- cgit v1.1 From 7fc3ce7312fec9320aeffb1a6c6c6d4bf2408669 Mon Sep 17 00:00:00 2001 From: sbrissen Date: Wed, 23 Oct 2013 13:19:08 -0400 Subject: Add support for Note 8 (N5100 and N5110) Change-Id: I6c9798682f9f6349b37cb452353bd0c0e6958401 --- drivers/battery/Kconfig | 9 + drivers/battery/Makefile | 1 + drivers/battery/battery-factory.c | 36 + drivers/battery/max17047_fuelgauge_c.c | 2217 ++++ drivers/battery/samsung_battery.c | 23 +- drivers/input/keyboard/Kconfig | 5 + drivers/input/keyboard/gpio_keys.c | 124 +- drivers/input/touchscreen/Kconfig | 26 + drivers/input/touchscreen/synaptics_fw.h | 8851 ++++++++++++++- drivers/input/touchscreen/synaptics_fw_updater.c | 91 +- drivers/input/touchscreen/synaptics_s7301.c | 478 +- drivers/input/touchscreen/synaptics_sysfs.c | 429 +- drivers/input/touchscreen/synaptics_sysfs.h | 1 + drivers/input/touchscreen/wacom/w9002_flash.c | 1253 ++ drivers/input/touchscreen/wacom/w9002_flash.h | 211 + drivers/input/touchscreen/wacom/wacom_i2c.c | 54 +- drivers/input/touchscreen/wacom/wacom_i2c_firm.c | 7 + drivers/input/touchscreen/wacom/wacom_i2c_flash.c | 28 +- drivers/input/touchscreen/wacom/wacom_i2c_func.c | 52 +- drivers/media/video/Kconfig | 9 + drivers/media/video/Makefile | 1 + drivers/media/video/isx012.c | 352 +- drivers/media/video/isx012.h | 39 +- drivers/media/video/isx012_regs.h | 14 +- drivers/media/video/isx012_regs_kona.h | 11284 +++++++++++++++++++ drivers/media/video/samsung/fimc/fimc_capture.c | 17 +- .../video/samsung/mali/common/mali_kernel_mem_os.c | 10 +- drivers/media/video/sr130pc20.c | 1999 ++++ drivers/media/video/sr130pc20.h | 646 ++ drivers/media/video/sr130pc20_regs.h | 4229 +++++++ drivers/misc/max77693-muic.c | 8 +- drivers/net/wireless/bcmdhd/dhd_sec_feature.h | 3 +- drivers/power/sec_battery_px.c | 2 +- drivers/sensor/Kconfig | 54 + drivers/sensor/Makefile | 6 + drivers/sensor/al3201.c | 51 +- drivers/sensor/k3dh_kona.c | 1080 ++ drivers/sensor/k3dh_reg.h | 1 + drivers/sensor/yas_mag_driver-yas532.c | 2909 +++++ drivers/sensor/yas_mag_driver.c | 27 + drivers/sensor/yas_mag_kernel_driver.c | 2192 ++++ drivers/sensor/yas_ori_kernel_driver.c | 695 ++ drivers/sensor/yas_pcb_test.c | 1282 +++ drivers/sensor/yas_pcb_test.h | 106 + drivers/sensor/yas_types.h | 48 + drivers/staging/android/binder.c | 2 +- drivers/video/backlight/Kconfig | 7 + drivers/video/backlight/Makefile | 1 + drivers/video/backlight/lp855x_bl.c | 466 + drivers/video/samsung/Kconfig | 6 + drivers/video/samsung/Makefile | 5 + drivers/video/samsung/mdnie_color_tone_4412.h | 239 + drivers/video/samsung/mdnie_kona.c | 1171 ++ drivers/video/samsung/mdnie_kona.h | 148 + drivers/video/samsung/mdnie_table_4412_kona.h | 319 + drivers/video/samsung/mdnie_table_ebook.h | 153 + drivers/video/samsung/mdnie_table_kona.h | 1304 +++ drivers/video/samsung/mdnie_tuning_kona.c | 294 + drivers/video/samsung/s3cfb_ielcd_kona.c | 136 + drivers/video/samsung/s3cfb_ielcd_kona.h | 28 + drivers/video/samsung/s3cfb_main.c | 21 + drivers/video/samsung/s3cfb_mdnie_kona.c | 120 + drivers/video/samsung/s3cfb_mdnie_kona.h | 88 + drivers/video/samsung/s3cfb_nt71391.c | 415 + 64 files changed, 45646 insertions(+), 237 deletions(-) create mode 100755 drivers/battery/max17047_fuelgauge_c.c create mode 100644 drivers/input/touchscreen/wacom/w9002_flash.c create mode 100644 drivers/input/touchscreen/wacom/w9002_flash.h create mode 100644 drivers/media/video/isx012_regs_kona.h create mode 100644 drivers/media/video/sr130pc20.c create mode 100755 drivers/media/video/sr130pc20.h create mode 100644 drivers/media/video/sr130pc20_regs.h create mode 100644 drivers/sensor/k3dh_kona.c create mode 100644 drivers/sensor/yas_mag_driver-yas532.c create mode 100644 drivers/sensor/yas_mag_driver.c create mode 100644 drivers/sensor/yas_mag_kernel_driver.c create mode 100644 drivers/sensor/yas_ori_kernel_driver.c create mode 100644 drivers/sensor/yas_pcb_test.c create mode 100644 drivers/sensor/yas_pcb_test.h create mode 100644 drivers/sensor/yas_types.h create mode 100644 drivers/video/backlight/lp855x_bl.c create mode 100644 drivers/video/samsung/mdnie_color_tone_4412.h create mode 100644 drivers/video/samsung/mdnie_kona.c create mode 100644 drivers/video/samsung/mdnie_kona.h create mode 100644 drivers/video/samsung/mdnie_table_4412_kona.h create mode 100644 drivers/video/samsung/mdnie_table_ebook.h create mode 100644 drivers/video/samsung/mdnie_table_kona.h create mode 100644 drivers/video/samsung/mdnie_tuning_kona.c create mode 100644 drivers/video/samsung/s3cfb_ielcd_kona.c create mode 100644 drivers/video/samsung/s3cfb_ielcd_kona.h create mode 100644 drivers/video/samsung/s3cfb_mdnie_kona.c create mode 100644 drivers/video/samsung/s3cfb_mdnie_kona.h create mode 100644 drivers/video/samsung/s3cfb_nt71391.c (limited to 'drivers') diff --git a/drivers/battery/Kconfig b/drivers/battery/Kconfig index acfbdb3..489bca1 100644 --- a/drivers/battery/Kconfig +++ b/drivers/battery/Kconfig @@ -45,6 +45,15 @@ config BATTERY_MAX17047_FUELGAUGE in handheld and portable equipment. The MAX17047 is configured to operate with a single lithium cell +config BATTERY_MAX17047_C_FUELGAUGE + tristate "Maxim MAX17047 Fuel Gauge - COULOMB_COUNTING" + depends on I2C + help + MAX17047 is fuel-gauge systems for lithium-ion (Li+) batteries + in handheld and portable equipment. The MAX17047 is configured + to operate with a single lithium cell + + config BATTERY_SMB136_CHARGER tristate "SMB136 battery charger support" depends on I2C diff --git a/drivers/battery/Makefile b/drivers/battery/Makefile index bb1af5e..af56fec 100644 --- a/drivers/battery/Makefile +++ b/drivers/battery/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_MAX8997_CHARGER) += max8997-charger.o obj-$(CONFIG_BATTERY_MAX17043_FUELGAUGE) += max17043_fuelgauge.o obj-$(CONFIG_BATTERY_MAX17042_FUELGAUGE) += max17042_fuelgauge.o obj-$(CONFIG_BATTERY_MAX17047_FUELGAUGE) += max17047_fuelgauge.o +obj-$(CONFIG_BATTERY_MAX17047_C_FUELGAUGE) += max17047_fuelgauge_c.o obj-$(CONFIG_BATTERY_SMB136_CHARGER) += smb136_charger.o obj-$(CONFIG_BATTERY_MAX77693_CHARGER) += max77693_charger.o diff --git a/drivers/battery/battery-factory.c b/drivers/battery/battery-factory.c index c1cd9b1..0f20fed 100644 --- a/drivers/battery/battery-factory.c +++ b/drivers/battery/battery-factory.c @@ -121,6 +121,9 @@ static ssize_t factory_show_property(struct device *dev, int i; int cnt, dat, d_max, d_min, d_total; int val; +#if defined(CONFIG_MACH_KONA) + int comp1, comp3; +#endif const ptrdiff_t off = attr - factory_attrs; pr_debug("%s: %s\n", __func__, factory_attrs[off].attr.name); @@ -149,10 +152,16 @@ static ssize_t factory_show_property(struct device *dev, val = 0; for (cnt = 0; cnt < CNT_TEMPER_AVG; cnt++) { msleep(100); +#if defined(CONFIG_MACH_KONA) + info->battery_temper_adc = battery_get_info(info, + POWER_SUPPLY_PROP_TEMP); +#else battery_get_info(info, POWER_SUPPLY_PROP_TEMP); +#endif val += info->battery_temper_adc; info->battery_temper_adc_avg = val / (cnt + 1); } +#if !defined(CONFIG_MACH_KONA) #ifdef CONFIG_S3C_ADC info->battery_temper_avg = info->pdata->covert_adc( info->battery_temper_adc_avg, @@ -160,6 +169,10 @@ static ssize_t factory_show_property(struct device *dev, #else info->battery_temper_avg = info->battery_temper; #endif +#else + info->battery_temper_avg = info->battery_temper_adc_avg; +#endif + val = info->battery_temper_avg; pr_info("%s: temper avg(%d)\n", __func__, val); i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", val); @@ -185,6 +198,9 @@ static ssize_t factory_show_property(struct device *dev, d_total += dat; } val = (d_total - d_max - d_min) / (CNT_VOLTAGE_AVG - 2); +#if defined(CONFIG_MACH_KONA) + val /= 1000; +#endif pr_info("%s: voltage avg(%d)\n", __func__, val); i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", val); break; @@ -242,8 +258,28 @@ static ssize_t factory_show_property(struct device *dev, i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", val); break; case BATT_VOL_ADC: + i += scnprintf(buf + i, PAGE_SIZE - i, "N/A\n"); + break; case BATT_VOL_ADC_CAL: +#if defined(CONFIG_MACH_KONA) + /* For using compensation 1% value */ + comp1 = info->is_comp_1; + i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", comp1); + break; +#else + i += scnprintf(buf + i, PAGE_SIZE - i, "N/A\n"); + break; +#endif case BATT_VOL_ADC_AVER: +#if defined(CONFIG_MACH_KONA) + /* For using compensation 3% value */ + comp3 = info->is_comp_3; + i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", comp3); + break; +#else + i += scnprintf(buf + i, PAGE_SIZE - i, "N/A\n"); + break; +#endif case BATT_TEMP_ADC_CAL: case AUTH_BATTERY: i += scnprintf(buf + i, PAGE_SIZE - i, "N/A\n"); diff --git a/drivers/battery/max17047_fuelgauge_c.c b/drivers/battery/max17047_fuelgauge_c.c new file mode 100755 index 0000000..4b26cb0 --- /dev/null +++ b/drivers/battery/max17047_fuelgauge_c.c @@ -0,0 +1,2217 @@ +/* + * max17047_fuelgauge.c + * + * Copyright (C) 2011 Samsung Electronics + * SangYoung Son + * + * based on max17040_battery.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC)\ + || defined(CONFIG_MACH_T0_CHN_CTC) +#ifdef CONFIG_DEBUG_FS +#include +#endif +#endif + +/* TRIM ERROR DETECTION */ +#define USE_TRIM_ERROR_DETECTION + +#define CONFIG_FUELGAUGE_MAX17047_COULOMB_COUNTING + +/* MAX17047 Registers. */ +#define MAX17047_REG_STATUS 0x00 +#define MAX17047_REG_VALRT_TH 0x01 +#define MAX17047_REG_TALRT_TH 0x02 +#define MAX17047_REG_SALRT_TH 0x03 +#define MAX17047_REG_REMCAP_REP 0x05 +#define MAX17047_SOCREP 0x06 +#define MAX17047_REG_VCELL 0x09 +#define MAX17047_REG_FULLCAP 0x10 +#define MAX17047_REG_TEMPERATURE 0x08 +#define MAX17047_REG_CYCLES 0x17 +#define MAX17047_REG_DESIGNCAP_REG 0x18 +#define MAX17047_REG_AVGVCELL 0x19 +#define MAX17047_REG_CONFIG 0x1D +#define MAX17047_REG_VERSION 0x21 +#define MAX17047_REG_FULLCAP_NOM 0x23 +#define MAX17047_REG_LEARNCFG 0x28 +#define MAX17047_REG_FILTERCFG 0x29 +#define MAX17047_REG_MISCCFG 0x2B +#define MAX17047_REG_CGAIN 0x2E +#define MAX17047_REG_RCOMP 0x38 +#define MAX17047_REG_VFOCV 0xFB +#define MAX17047_REG_SOC_VF 0xFF +#define MAX17047_REG_FULLCAP 0x10 +#define MAX17047_REG_FULLCAPNOM 0x23 +#define MAX17047_REG_CURRENT 0x0A +#define MAX17047_REG_AVG_CURRENT 0x0B +#define MAX17047_REG_DQACC 0x45 +#define MAX17047_REG_DPACC 0x46 +#define MAX17047_REG_VFSOC 0xFF + + + + +/* Polling work */ +#undef DEBUG_FUELGAUGE_POLLING +#define MAX17047_POLLING_INTERVAL 10000 + +/* rcomp update */ +#if defined(CONFIG_MACH_C1_KOR_SKT) || \ + defined(CONFIG_MACH_C1_KOR_KT) || \ + defined(CONFIG_MACH_C1_KOR_LGT) +#define CHECK_RCOMP_UPDATE +#define MAX17047_NEW_RCOMP 0x0070 +#endif + +/* adjust full soc */ +#if defined(CONFIG_MACH_T0) +#if defined(CONFIG_TARGET_LOCALE_KOR) +#define FULL_SOC_DEFAULT 9700 +#define FULL_SOC_LOW 9600 +#define FULL_SOC_HIGH 10050 +#define KEEP_FULL_SOC 100 /* 1.0% */ +#else +#define FULL_SOC_DEFAULT 9650 +#define FULL_SOC_LOW 9500 +#define FULL_SOC_HIGH 10050 +#define KEEP_FULL_SOC 100 /* 1.0% */ +#endif +#elif defined(CONFIG_MACH_GC1) +#define FULL_SOC_DEFAULT 9700 +#define FULL_SOC_LOW 9650 +#define FULL_SOC_HIGH 10000 +#define KEEP_FULL_SOC 110 /* 1.1% */ +#elif defined(CONFIG_MACH_KONA) +#define FULL_SOC_DEFAULT 9900 +#define FULL_SOC_LOW 9700 +#define FULL_SOC_HIGH 10000 +#define KEEP_FULL_SOC 100 // /* 1.0% */ +#else /* M0, C1,,, */ +#define FULL_SOC_DEFAULT 9850 +#define FULL_SOC_LOW 9700 +#define FULL_SOC_HIGH 10000 +#define KEEP_FULL_SOC 100 /* 1.0% */ +#endif +#define KEEP_SOC_DEFAULT 50 /* 0.5% */ + +struct max17047_fuelgauge_data { + struct i2c_client *client; + struct max17047_platform_data *pdata; + + struct power_supply fuelgauge; + + /* workqueue */ + struct delayed_work update_work; +#ifdef DEBUG_FUELGAUGE_POLLING + struct delayed_work polling_work; +#endif + + /* mutex */ + struct mutex irq_lock; + + /* wakelock */ + struct wake_lock update_wake_lock; + + unsigned int irq; + + unsigned int vcell; + unsigned int avgvcell; + unsigned int vfocv; + unsigned int soc; + unsigned int rawsoc; + unsigned int temperature; + +/*#if defined(CONFIG_FUELGAUGE_MAX17047_COULOMB_COUNTING)*/ + u32 previous_fullcap; + u32 previous_vffullcap; + + /* low battery comp */ + int low_batt_comp_cnt[LOW_BATT_COMP_RANGE_NUM][LOW_BATT_COMP_LEVEL_NUM]; + + /* low battery boot */ + int low_batt_boot_flag; + bool is_low_batt_alarm; + + /* miscellaneous */ + unsigned long fullcap_check_interval; + int full_check_flag; + bool is_first_check; +/*#endif*/ + + /* adjust full soc */ + int full_soc; + +#if defined(CONFIG_MACH_GC1) + int prev_status; +#endif + +#ifdef USE_TRIM_ERROR_DETECTION + /* trim error state */ + bool trim_err; +#endif + +#ifdef CONFIG_DEBUG_FS + struct dentry *fg_debugfs_dir; +#endif + +#ifdef CONFIG_HIBERNATION + u8 *reg_dump; +#endif + +}; + +static struct battery_data_t fg_battery_data[] = { + /* SDI battery data */ + { + .Capacity = 0x2530, + .low_battery_comp_voltage = 3500, + .low_battery_table = { + /* range, slope, offset */ + {-5000, 0, 0}, /* dummy for top limit */ + {-1250, 0, 3320}, + {-750, 97, 3451}, + {-100, 96, 3461}, + {0, 0, 3456}, + }, + .temp_adjust_table = { + /* range, slope, offset */ + {47000, 122, 8950}, + {60000, 200, 51000}, + {100000, 0, 0}, /* dummy for top limit */ + }, + .type_str = "SDI", + } +}; + + +#define MAX17047_CAPACITY 0x2530 + +static int max17047_i2c_read(struct i2c_client *client, int reg, u8 *buf) +{ + int ret; + + ret = i2c_smbus_read_i2c_block_data(client, reg, 2, buf); + if (ret < 0) + pr_err("%s: err %d, reg: 0x%02x\n", __func__, ret, reg); + + return ret; +} + +static int max17047_i2c_write(struct i2c_client *client, int reg, u8 *buf) +{ + int ret; + + ret = i2c_smbus_write_i2c_block_data(client, reg, 2, buf); + if (ret < 0) + pr_err("%s: err %d, reg: 0x%02x, data: 0x%x%x\n", __func__, + ret, reg, buf[0], buf[1]); + + return ret; +} + +static int fg_read_register(struct i2c_client *client, + u8 addr) +{ + u8 data[2]; + + if (max17047_i2c_read(client, addr, data) < 0) { + dev_err(&client->dev, "%s: Failed to read addr(0x%x)\n", + __func__, addr); + return -1; + } + + return (data[1] << 8) | data[0]; +} + +static int fg_write_register(struct i2c_client *client, + u8 addr, u16 w_data) +{ + u8 data[2]; + + data[0] = w_data & 0xFF; + data[1] = w_data >> 8; + + if (max17047_i2c_write(client, addr, data) < 0) { + dev_err(&client->dev, "%s: Failed to write addr(0x%x)\n", + __func__, addr); + return -1; + } + + return 0; +} + +static void max17047_test_read(struct max17047_fuelgauge_data *fg_data) +{ + int reg; + u8 data[2]; + int i; + u8 buf[673]; + + struct timespec ts; + struct rtc_time tm; + pr_info("%s\n", __func__); + + getnstimeofday(&ts); + rtc_time_to_tm(ts.tv_sec, &tm); + + pr_info("%s: %d/%d/%d %02d:%02d\n", __func__, + tm.tm_mday, + tm.tm_mon + 1, + tm.tm_year + 1900, + tm.tm_hour, + tm.tm_min); + + i = 0; + for (reg = 0; reg < 0x50; reg++) { + if (!(reg & 0xf)) + i += sprintf(buf + i, "\n%02x| ", reg); + max17047_i2c_read(fg_data->client, reg, data); + i += sprintf(buf + i, "%02x%02x ", data[1], data[0]); + } + for (reg = 0xe0; reg < 0x100; reg++) { + if (!(reg & 0xf)) + i += sprintf(buf + i, "\n%02x| ", reg); + max17047_i2c_read(fg_data->client, reg, data); + i += sprintf(buf + i, "%02x%02x ", data[1], data[0]); + } + + pr_info(" 0 1 2 3 4 5 6 7"); + pr_cont(" 8 9 a b c d e f"); + pr_cont("%s\n", buf); +} + +static int fg_check_battery_present(struct i2c_client *client) +{ + u8 status_data[2]; + int ret = 1; + + /* 1. Check Bst bit */ + if (max17047_i2c_read(client, MAX17047_REG_STATUS, status_data) < 0) { + dev_err(&client->dev, + "%s: Failed to read STATUS_REG\n", __func__); + return 0; + } + + if (status_data[0] & (0x1 << 3)) { + dev_info(&client->dev, + "%s: addr(0x01), data(0x%04x)\n", __func__, + (status_data[1]<<8) | status_data[0]); + dev_info(&client->dev, "%s: battery is absent!!\n", __func__); + ret = 0; + } + + return ret; +} + +static int max17047_get_temperature(struct i2c_client *client) +{ +#if defined(CONFIG_MACH_KONA) + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + u8 data[2] = {0x00, 0x00}; + int temper = 0; + + if (fg_check_battery_present(client)) { + if (max17047_i2c_read(client, MAX17047_REG_TEMPERATURE, data) < 0) { + dev_err(&client->dev, + "%s: Failed to read TEMPERATURE_REG\n", + __func__); + return -1; + } + + if (data[1]&(0x1 << 7)) { + temper = ((~(data[1]))&0xFF)+1; + temper *= (-1000); + temper -= ((~((int)data[0]))+1) * 39 / 10; + } else { + temper = data[1] & 0x7f; + temper *= 1000; + temper += data[0] * 39 / 10; + } + } else + temper = 20000; + + dev_info(&client->dev, "%s: TEMPERATURE(%d), data(0x%04x)\n", + __func__, temper/100, (data[1]<<8) | data[0]); + + return temper/100; +#else + return 300; +#endif +} + +/* max17047_get_XXX(); Return current value and update data value */ +static int max17047_get_vfocv(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + u8 data[2]; + int ret; + u32 vfocv; + pr_debug("%s\n", __func__); + + ret = max17047_i2c_read(client, MAX17047_REG_VFOCV, data); + if (ret < 0) + return ret; + + vfocv = fg_data->vfocv = ((data[0] >> 3) + (data[1] << 5)) * 625 / 1000; + + pr_debug("%s: VFOCV(0x%02x%02x, %d)\n", __func__, + data[1], data[0], vfocv); + return vfocv * 1000; +} + +static int fg_read_vcell(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + u8 data[2]; + u32 vcell; + u16 w_data; + u32 temp; + u32 temp2; + + if (max17047_i2c_read(client, MAX17047_REG_VCELL, data) < 0) { + dev_err(&client->dev, "%s: Failed to read VCELL\n", __func__); + return -1; + } + + w_data = (data[1]<<8) | data[0]; + + temp = (w_data & 0xFFF) * 78125; + vcell = temp / 1000000; + + temp = ((w_data & 0xF000) >> 4) * 78125; + temp2 = temp / 1000000; + vcell += (temp2 << 4); + + dev_info(&client->dev, "%s: VCELL(%d), data(0x%04x)\n", + __func__, vcell, (data[1]<<8) | data[0]); + + return vcell; +} + + +static int max17047_get_vcell(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + u8 data[2]; + int ret; + u32 vcell; + pr_debug("%s\n", __func__); + + ret = max17047_i2c_read(client, MAX17047_REG_VCELL, data); + if (ret < 0) + return ret; + + vcell = fg_data->vcell = ((data[0] >> 3) + (data[1] << 5)) * 625; + + pr_debug("%s: VCELL(0x%02x%02x, %d)\n", __func__, + data[1], data[0], vcell); + return vcell; +} + +static int max17047_get_avgvcell(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + u8 data[2]; + int ret; + u32 avgvcell; + pr_debug("%s\n", __func__); + + ret = max17047_i2c_read(client, MAX17047_REG_AVGVCELL, data); + if (ret < 0) + return ret; + + avgvcell = fg_data->avgvcell = ((data[0] >> 3) + (data[1] << 5)) * 625; + + pr_debug("%s: AVGVCELL(0x%02x%02x, %d)\n", __func__, + data[1], data[0], avgvcell); + return avgvcell; +} + +static int max17047_get_rawsoc(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + u8 data[2]; + int soc; + + if (max17047_i2c_read(client, MAX17047_SOCREP, data) < 0) { + dev_err(&client->dev, "%s: Failed to read SOCREP\n", __func__); + return -1; + } + + soc = (data[1] * 100) + (data[0] * 100 / 256); + + dev_dbg(&client->dev, "%s: raw capacity (0.01%%) (%d)\n", + __func__, soc); + + dev_dbg(&client->dev, "%s: raw capacity (%d), data(0x%04x)\n", + __func__, soc, (data[1]<<8) | data[0]); + + return min(soc, 10000); +} + +#if 0 +static int max17047_get_soc(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + int rawsoc, soc, fullsoc, empty; + pr_debug("%s\n", __func__); + + rawsoc = max17047_get_rawsoc(fg_data->client); + +#if defined(CONFIG_MACH_C1) + empty = 0; +#else /* M0, T0,,, */ + empty = 29; +#endif + + if (fg_data->full_soc <= 0) + fg_data->full_soc = FULL_SOC_DEFAULT; + fullsoc = fg_data->full_soc - empty; + rawsoc -= empty; + + soc = fg_data->soc = + ((rawsoc < empty) ? 0 : (min((rawsoc * 100 / fullsoc), 100))); + + pr_info("%s: SOC(%d, %d / %d)\n", __func__, soc, rawsoc, fullsoc); + return soc; +} + +#else +/* soc should be 0.1% unit */ +static int max17047_get_soc(struct i2c_client *client) +{ + u8 data[2]; + int soc; + + if (max17047_i2c_read(client, MAX17047_SOCREP, data) < 0) { + pr_err("%s: Failed to read SOCREP\n", __func__); + return -1; + } + + soc = ((data[1] * 100) + (data[0] * 100 / 256)) / 10; + + pr_info("%s: raw capacity (%d), data(0x%04x)\n", __func__, soc, (data[1]<<8) | data[0]); + + return min(soc, 1000); +} +#endif + +static int fg_reset_capacity_by_jig_connection(struct i2c_client *client) +{ + pr_info("%s: DesignCap = Capacity - 1 (Jig Connection)\n", __func__); + + return fg_write_register(client, MAX17047_REG_DESIGNCAP_REG, + fg_battery_data[SDI].Capacity - 1); +} + +#if defined(CONFIG_MACH_KONA) +/* For using JIG detach */ +struct i2c_client *fg_client; + +void fg_reset_capacity_by_jig_connection_ex(void) +{ + + pr_info("%s: DesignCap = Capacity - 1 (Jig Connection)\n", __func__); + printk("[BAT] %s call!!\n", __func__); + + + fg_write_register(fg_client, MAX17047_REG_DESIGNCAP_REG, + fg_battery_data[SDI].Capacity - 1); +} +EXPORT_SYMBOL(fg_reset_capacity_by_jig_connection_ex); +#endif + +static void fg_periodic_read(struct i2c_client *client) +{ + u8 reg; + int i; + int data[0x10]; + char *str = NULL; + + str = kzalloc(sizeof(char)*1024, GFP_KERNEL); + if (!str) + return; + + for (i = 0; i < 16; i++) { + for (reg = 0; reg < 0x10; reg++) + data[reg] = fg_read_register(client, reg + i * 0x10); + + sprintf(str+strlen(str), + "%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,", + data[0x00], data[0x01], data[0x02], data[0x03], + data[0x04], data[0x05], data[0x06], data[0x07]); + sprintf(str+strlen(str), + "%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,", + data[0x08], data[0x09], data[0x0a], data[0x0b], + data[0x0c], data[0x0d], data[0x0e], data[0x0f]); + if (i == 4) + i = 13; + } + + dev_info(&client->dev, "maxim check %s", str); + + kfree(str); +} + +static int fg_read_current(struct i2c_client *client) +{ + u8 data1[2], data2[2]; + u32 temp, sign; + s32 i_current; + s32 avg_current; + + if (max17047_i2c_read(client, MAX17047_REG_CURRENT, data1) < 0) { + pr_err("%s: Failed to read CURRENT\n", + __func__); + return -1; + } + + if (max17047_i2c_read(client, MAX17047_REG_AVG_CURRENT, data2) < 0) { + pr_err("%s: Failed to read AVERAGE CURRENT\n", + __func__); + return -1; + } + + temp = ((data1[1]<<8) | data1[0]) & 0xFFFF; + if (temp & (0x1 << 15)) { + sign = NEGATIVE; + temp = (~temp & 0xFFFF) + 1; + } else + sign = POSITIVE; + + /* 1.5625uV/0.01Ohm(Rsense) = 156.25uA */ + i_current = temp * 15625 / 100000; + if (sign) + i_current *= -1; + + temp = ((data2[1]<<8) | data2[0]) & 0xFFFF; + if (temp & (0x1 << 15)) { + sign = NEGATIVE; + temp = (~temp & 0xFFFF) + 1; + } else + sign = POSITIVE; + + /* 1.5625uV/0.01Ohm(Rsense) = 156.25uA */ + avg_current = temp * 15625 / 100000; + if (sign) + avg_current *= -1; + + pr_info("%s: CURRENT(%dmA), AVG_CURRENT(%dmA)\n", + __func__, i_current, avg_current); + + fg_periodic_read(client); + + return i_current; +} + +static int fg_read_avg_current(struct i2c_client *client) +{ + u8 data2[2]; + u32 temp, sign; + s32 avg_current; + + if (max17047_i2c_read(client, MAX17047_REG_AVG_CURRENT, data2) < 0) { + pr_err("%s: Failed to read AVERAGE CURRENT\n", + __func__); + return -1; + } + + temp = ((data2[1]<<8) | data2[0]) & 0xFFFF; + if (temp & (0x1 << 15)) { + sign = NEGATIVE; + temp = (~temp & 0xFFFF) + 1; + } else + sign = POSITIVE; + + /* 1.5625uV/0.01Ohm(Rsense) = 156.25uA */ + avg_current = temp * 15625 / 100000; + + if (sign) + avg_current *= -1; + + return avg_current; +} + +/* soc should be 0.1% unit */ +static int fg_read_vfsoc(struct i2c_client *client) +{ + u8 data[2]; + int soc; + + if (max17047_i2c_read(client, MAX17047_REG_VFSOC, data) < 0) { + pr_err("%s: Failed to read VFSOC\n", __func__); + return -1; + } + + soc = ((data[1] * 100) + (data[0] * 100 / 256)) / 10; + + return min(soc, 1000); +} + + +int get_fuelgauge_value(struct i2c_client *client, int data) +{ + int ret = 0; + + switch (data) { + case FG_LEVEL: + /*ret = fg_read_soc(client);*/ + ret = max17047_get_soc(client); + + break; + + case FG_TEMPERATURE: + /*ret = fg_read_temp(client);*/ + break; + + case FG_VOLTAGE: + ret = fg_read_vcell(client); + break; + + case FG_CURRENT: + ret = fg_read_current(client); + break; + + case FG_CURRENT_AVG: + ret = fg_read_avg_current(client); + break; + + case FG_CHECK_STATUS: + /*ret = fg_check_status_reg(client);*/ + break; + + case FG_RAW_SOC: + /*ret = fg_read_rawsoc(client);*/ + break; + + case FG_VF_SOC: + ret = fg_read_vfsoc(client); + break; + + case FG_AV_SOC: + /*ret = fg_read_avsoc(client);*/ + break; + + case FG_FULLCAP: + /*ret = fg_read_fullcap(client);*/ + break; + + case FG_MIXCAP: + /*ret = fg_read_mixcap(client);*/ + break; + + case FG_AVCAP: + /*ret = fg_read_avcap(client);*/ + break; + + case FG_REPCAP: + /*ret = fg_read_repcap(client);*/ + break; + + default: + ret = -1; + break; + } + + return ret; +} + + +void fg_check_vf_fullcap_range(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = + i2c_get_clientdata(client); + + static int new_vffullcap; + bool is_vffullcap_changed = true; + + if (is_jig_attached == JIG_ON) + fg_reset_capacity_by_jig_connection(client); + + new_vffullcap = fg_read_register(client, MAX17047_REG_FULLCAP_NOM); + if (new_vffullcap < 0) + new_vffullcap = fg_battery_data[SDI].Capacity; + + /* compare with initial capacity */ + if (new_vffullcap > + (fg_battery_data[SDI].Capacity * 110 / 100)) { + pr_info("%s: [Case 1] capacity = 0x%04x, NewVfFullCap = 0x%04x\n", + __func__, fg_battery_data[SDI].Capacity, + new_vffullcap); + + new_vffullcap = + (fg_battery_data[SDI].Capacity * 110) / 100; + + fg_write_register(client, MAX17047_REG_DQACC, + (u16)(new_vffullcap / 4)); + fg_write_register(client, MAX17047_REG_DPACC, (u16)0x3200); + } else if (new_vffullcap < + (fg_battery_data[SDI].Capacity * 50 / 100)) { + pr_info("%s: [Case 5] capacity = 0x%04x, NewVfFullCap = 0x%04x\n", + __func__, fg_battery_data[SDI].Capacity, new_vffullcap); + + new_vffullcap = + (fg_battery_data[SDI].Capacity * 50) / 100; + + fg_write_register(client, MAX17047_REG_DQACC, + (u16)(new_vffullcap / 4)); + fg_write_register(client, MAX17047_REG_DPACC, (u16)0x3200); + } else { + /* compare with previous capacity */ + if (new_vffullcap > + (fg_data->previous_vffullcap * 110 / 100)) { + pr_info("%s: [Case 2] previous_vffullcap = 0x%04x, NewVfFullCap = 0x%04x\n", + __func__, fg_data->previous_vffullcap, + new_vffullcap); + + new_vffullcap = + (fg_data->previous_vffullcap * 110) / + 100; + + fg_write_register(client, MAX17047_REG_DQACC, + (u16)(new_vffullcap / 4)); + fg_write_register(client, MAX17047_REG_DPACC, (u16)0x3200); + } else if (new_vffullcap < + (fg_data->previous_vffullcap * 90 / 100)) { + pr_info("%s: [Case 3] previous_vffullcap = 0x%04x, NewVfFullCap = 0x%04x\n", + __func__, fg_data->previous_vffullcap, new_vffullcap); + + new_vffullcap = + (fg_data->previous_vffullcap * 90) / 100; + + fg_write_register(client, MAX17047_REG_DQACC, + (u16)(new_vffullcap / 4)); + fg_write_register(client, MAX17047_REG_DPACC, (u16)0x3200); + } else { + pr_info("%s: [Case 4] previous_vffullcap = 0x%04x, NewVfFullCap = 0x%04x\n", + __func__, fg_data->previous_vffullcap, + new_vffullcap); + is_vffullcap_changed = false; + } + } + + /* delay for register setting (dQacc, dPacc) */ + if (is_vffullcap_changed) + msleep(300); + + fg_data->previous_vffullcap = + fg_read_register(client, MAX17047_REG_FULLCAP_NOM); + + if (is_vffullcap_changed) + pr_info("%s : VfFullCap(0x%04x), dQacc(0x%04x), dPacc(0x%04x)\n", + __func__, + fg_read_register(client, MAX17047_REG_FULLCAP_NOM), + fg_read_register(client, MAX17047_REG_DQACC), + fg_read_register(client, MAX17047_REG_DPACC)); + +} + +void fg_set_full_charged(struct i2c_client *client) +{ + pr_info("[FG_Set_Full] (B) FullCAP(%d), RemCAP(%d)\n", + (fg_read_register(client, MAX17047_REG_FULLCAP)/2), + (fg_read_register(client, MAX17047_REG_REMCAP_REP)/2)); + + fg_write_register(client, MAX17047_REG_FULLCAP, + (u16)fg_read_register(client, MAX17047_REG_REMCAP_REP)); + + pr_info("[FG_Set_Full] (A) FullCAP(%d), RemCAP(%d)\n", + (fg_read_register(client, MAX17047_REG_FULLCAP)/2), + (fg_read_register(client, MAX17047_REG_REMCAP_REP)/2)); +} + +static void add_low_batt_comp_cnt(struct i2c_client *client, + int range, int level) +{ + struct max17047_fuelgauge_data *fg_data = + i2c_get_clientdata(client); + int i; + int j; + + /* Increase the requested count value, and reset others. */ + fg_data->low_batt_comp_cnt[range-1][level/2]++; + + for (i = 0; i < LOW_BATT_COMP_RANGE_NUM; i++) { + for (j = 0; j < LOW_BATT_COMP_LEVEL_NUM; j++) { + if (i == range-1 && j == level/2) + continue; + else + fg_data->low_batt_comp_cnt[i][j] = 0; + } + } +} + + +static int get_low_batt_threshold(struct i2c_client *client, + int range, int nCurrent, int level) +{ + int ret = 0; + + ret = fg_battery_data[SDI].low_battery_table[range][OFFSET] + + ((nCurrent * + fg_battery_data[SDI].low_battery_table[range][SLOPE]) / + 1000); + + return ret; +} + +void reset_low_batt_comp_cnt(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = + i2c_get_clientdata(client); + + memset(fg_data->low_batt_comp_cnt, 0, + sizeof(fg_data->low_batt_comp_cnt)); +} + +static void display_low_batt_comp_cnt(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = + i2c_get_clientdata(client); + + pr_info("Check Array(%s): [%d, %d], [%d, %d], ", + fg_battery_data[SDI].type_str, + fg_data->low_batt_comp_cnt[0][0], + fg_data->low_batt_comp_cnt[0][1], + fg_data->low_batt_comp_cnt[1][0], + fg_data->low_batt_comp_cnt[1][1]); + pr_info("[%d, %d], [%d, %d], [%d, %d]\n", + fg_data->low_batt_comp_cnt[2][0], + fg_data->low_batt_comp_cnt[2][1], + fg_data->low_batt_comp_cnt[3][0], + fg_data->low_batt_comp_cnt[3][1], + fg_data->low_batt_comp_cnt[4][0], + fg_data->low_batt_comp_cnt[4][1]); +} + + +static int check_low_batt_comp_condition( + struct i2c_client *client, int *nLevel) +{ + struct max17047_fuelgauge_data *fg_data = + i2c_get_clientdata(client); + int i; + int j; + int ret = 0; + + for (i = 0; i < LOW_BATT_COMP_RANGE_NUM; i++) { + for (j = 0; j < LOW_BATT_COMP_LEVEL_NUM; j++) { + if (fg_data->low_batt_comp_cnt[i][j] >= + MAX_LOW_BATT_CHECK_CNT) { + display_low_batt_comp_cnt(client); + ret = 1; + *nLevel = j*2 + 1; + break; + } + } + } + + return ret; +} + +void fg_low_batt_compensation(struct i2c_client *client, u32 level) +{ +#if defined(CONFIG_MACH_KONA) + struct power_supply *battery_psy = power_supply_get_by_name("battery"); + union power_supply_propval value; +#endif + int read_val; + u32 temp; + + pr_info("%s: Adjust SOCrep to %d!!\n", + __func__, level); + + read_val = fg_read_register(client, MAX17047_REG_FULLCAP); + if (read_val < 0) + return; + +#if defined(CONFIG_MACH_KONA) + if (read_val > 2) { /* 3% compensation */ + /* RemCapREP (05h) = FullCap(10h) x 0.0301 */ + temp = read_val * (level*100 + 1) / 10000; + + /* Display conpensation 3% value for debug screen */ + value.intval = 1; + battery_psy->set_property(battery_psy, + POWER_SUPPLY_PROP_COMPENSATION_3, + &value); + } else { /* 1% compensation */ + /* RemCapREP (05h) = FullCap(10h) x 0.0090 */ + temp = read_val * (level*90) / 10000; + + /* Display conpensation 1% value for debug screen */ + value.intval = 1; + battery_psy->set_property(battery_psy, + POWER_SUPPLY_PROP_COMPENSATION_1, + &value); + } +#else + if (read_val > 2) /* 3% compensation */ + /* RemCapREP (05h) = FullCap(10h) x 0.0301 */ + temp = read_val * (level*100 + 1) / 10000; + else /* 1% compensation */ + /* RemCapREP (05h) = FullCap(10h) x 0.0090 */ + temp = read_val * (level*90) / 10000; +#endif + + fg_write_register(client, MAX17047_REG_REMCAP_REP, (u16)temp); +} + +void prevent_early_poweroff(struct i2c_client *client, + int vcell, int *fg_soc) +{ + int soc = 0; + int read_val; + + soc = get_fuelgauge_value(client, FG_LEVEL); + + if (soc > POWER_OFF_SOC_HIGH_MARGIN) + return; + + pr_info("%s: soc=%d%%, vcell=%d\n", __func__, + soc, vcell); + + if (vcell > POWER_OFF_VOLTAGE_HIGH_MARGIN) { + read_val = fg_read_register(client, MAX17047_REG_FULLCAP); + /* FullCAP * 0.013 */ + fg_write_register(client, MAX17047_REG_REMCAP_REP, + (u16)(read_val * 13 / 1000)); + msleep(200); + *fg_soc = max17047_get_soc(client); + dev_info(&client->dev, "%s : new soc=%d, vcell=%d\n", + __func__, *fg_soc, vcell); + } +} + +int low_batt_compensation(struct i2c_client *client, + int fg_soc, int fg_vcell, int fg_current) +{ + struct max17047_fuelgauge_data *fg_data = + i2c_get_clientdata(client); + int fg_avg_current = 0; + int fg_min_current = 0; + int new_level = 0; + int i, table_size; + + /* Not charging, Under low battery comp voltage */ + if (fg_vcell <= fg_battery_data[SDI].low_battery_comp_voltage) { + fg_avg_current = fg_read_avg_current(client); + fg_min_current = min(fg_avg_current, fg_current); + + table_size = + sizeof(fg_battery_data[SDI].low_battery_table) / + (sizeof(s16)*TABLE_MAX); + + for (i = 1; i < CURRENT_RANGE_MAX_NUM; i++) { + if ((fg_min_current >= fg_battery_data[SDI].low_battery_table[i-1][RANGE]) && + (fg_min_current < fg_battery_data[SDI].low_battery_table[i][RANGE])) { + if (fg_soc >= 2 && fg_vcell < + get_low_batt_threshold(client, + i, fg_min_current, 1)) { + add_low_batt_comp_cnt( + client, i, 1); + } else { + reset_low_batt_comp_cnt(client); + } + } + } + + if (check_low_batt_comp_condition(client, &new_level)) { + fg_low_batt_compensation(client, new_level); + reset_low_batt_comp_cnt(client); + + /* Do not update soc right after + * low battery compensation + * to prevent from powering-off suddenly + */ + pr_info("%s: SOC is set to %d by low compensation!!\n", + __func__, max17047_get_soc(client)); + } + } + + /* Prevent power off over 3500mV */ + prevent_early_poweroff(client, fg_vcell, &fg_soc); + + return fg_soc; +} + +int fg_adjust_capacity(struct i2c_client *client) +{ + u8 data[2]; + + data[0] = 0; + data[1] = 0; + + /* 1. Write RemCapREP(05h)=0; */ + if (max17047_i2c_write(client, MAX17047_REG_REMCAP_REP, data) < 0) { + pr_err("%s: Failed to write RemCap_REP\n", __func__); + return -1; + } + msleep(200); + + pr_info("%s: After adjust - RepSOC(%d)\n", __func__, max17047_get_soc(client)); + + return 0; +} + +static bool is_booted_in_low_battery(struct i2c_client *client) +{ + int fg_vcell = get_fuelgauge_value(client, FG_VOLTAGE); + int fg_current = get_fuelgauge_value(client, FG_CURRENT); + int threshold = 0; + + threshold = 3300 + ((fg_current * 17) / 100); + + if (fg_vcell <= threshold) + return true; + else + return false; +} + +static bool fuelgauge_recovery_handler(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = + i2c_get_clientdata(client); + int current_soc; + int avsoc; + int temperature; + + if (fg_data->soc > LOW_BATTERY_SOC_REDUCE_UNIT) { + pr_err("%s: Reduce the Reported SOC by 1%%\n", + __func__); + current_soc = + get_fuelgauge_value(client, FG_LEVEL); + + if (current_soc) { + pr_info("%s: Returning to Normal discharge path\n", + __func__); + pr_info("%s: Actual SOC(%d) non-zero\n", + __func__, current_soc); + fg_data->is_low_batt_alarm = false; + } else { + temperature = + get_fuelgauge_value(client, FG_TEMPERATURE); + avsoc = + get_fuelgauge_value(client, FG_AV_SOC); + + if ((fg_data->soc > avsoc) || + (temperature < 0)) { + fg_data->soc -= + LOW_BATTERY_SOC_REDUCE_UNIT; + pr_err("%s: New Reduced RepSOC (%d)\n", + __func__, fg_data->soc); + } else + pr_info("%s: Waiting for recovery (AvSOC:%d)\n", + __func__, avsoc); + } + } + + return fg_data->is_low_batt_alarm; +} + + +static int get_fuelgauge_soc(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = + i2c_get_clientdata(client); + struct power_supply *battery_psy = power_supply_get_by_name("battery"); + union power_supply_propval value; + int fg_soc; + int fg_vfsoc; + int fg_vcell; + int fg_current; + int avg_current; + ktime_t current_time; + struct timespec ts; + int fullcap_check_interval; + int cable_type; + + if (fg_data->is_low_batt_alarm) { + if (fuelgauge_recovery_handler(client)) { + fg_soc = fg_data->soc; + goto return_soc; + } + } + + current_time = alarm_get_elapsed_realtime(); + ts = ktime_to_timespec(current_time); + + /* check fullcap range */ + fullcap_check_interval = + (ts.tv_sec - fg_data->fullcap_check_interval); + if (fullcap_check_interval > + VFFULLCAP_CHECK_INTERVAL) { + dev_info(&client->dev, + "%s: check fullcap range (interval:%d)\n", + __func__, fullcap_check_interval); + fg_check_vf_fullcap_range(client); + fg_data->fullcap_check_interval = ts.tv_sec; + } + + fg_soc = get_fuelgauge_value(client, FG_LEVEL); + if (fg_soc < 0) { + pr_info("Can't read soc!!!"); + fg_soc = fg_data->soc; + } + + if (!battery_psy) { + pr_info("%s : battery driver didn't load yet.\n", __func__); + return fg_soc; + } + + battery_psy->get_property(battery_psy, + POWER_SUPPLY_PROP_ONLINE, + &value); + + cable_type = value.intval; + + if (fg_data->low_batt_boot_flag) { + fg_soc = 0; + + if (cable_type != POWER_SUPPLY_TYPE_BATTERY && + !is_booted_in_low_battery(client)) { + fg_adjust_capacity(client); + fg_data->low_batt_boot_flag = 0; + } + + if (cable_type == POWER_SUPPLY_TYPE_BATTERY) + fg_data->low_batt_boot_flag = 0; + } + + fg_vcell = get_fuelgauge_value(client, FG_VOLTAGE); + fg_current = get_fuelgauge_value(client, FG_CURRENT); + avg_current = get_fuelgauge_value(client, FG_CURRENT_AVG); + fg_vfsoc = get_fuelgauge_value(client, FG_VF_SOC); + + + battery_psy->get_property(battery_psy, + POWER_SUPPLY_PROP_STATUS, + &value); + + /* Algorithm for reducing time to fully charged (from MAXIM) */ + if (value.intval != POWER_SUPPLY_STATUS_DISCHARGING && + value.intval != POWER_SUPPLY_STATUS_FULL && + cable_type != POWER_SUPPLY_TYPE_USB && + /* Skip when first check after boot up */ + !fg_data->is_first_check && + (fg_vfsoc > VFSOC_FOR_FULLCAP_LEARNING && + (fg_current > LOW_CURRENT_FOR_FULLCAP_LEARNING && + fg_current < HIGH_CURRENT_FOR_FULLCAP_LEARNING) && + (avg_current > LOW_AVGCURRENT_FOR_FULLCAP_LEARNING && + avg_current < HIGH_AVGCURRENT_FOR_FULLCAP_LEARNING))) { + + if (fg_data->full_check_flag == 2) { + pr_info("%s: force fully charged SOC !! (%d)", + __func__, fg_data->full_check_flag); + fg_set_full_charged(client); + fg_soc = get_fuelgauge_value(client, FG_LEVEL); + } else if (fg_data->full_check_flag < 2) + pr_info("%s: full_check_flag (%d)", + __func__, fg_data->full_check_flag); + + /* prevent overflow */ + if (fg_data->full_check_flag++ > 10000) + fg_data->full_check_flag = 3; + } else + fg_data->full_check_flag = 0; + + /* Checks vcell level and tries to compensate SOC if needed.*/ + /* If jig cable is connected, then skip low batt compensation check. */ + if (is_jig_attached != JIG_ON && + value.intval == POWER_SUPPLY_STATUS_DISCHARGING) + fg_soc = low_batt_compensation( + client, fg_soc, fg_vcell, fg_current); + + if (fg_data->is_first_check) + fg_data->is_first_check = false; + fg_data->soc = fg_soc; + +return_soc: + +#if defined(CONFIG_MACH_KONA) + if (fg_data->full_soc <= 0) + fg_data->full_soc = FULL_SOC_DEFAULT; + + fg_soc =(min((fg_soc * 10000 / (fg_data->full_soc)), 1000)); +#endif + + pr_info("%s: soc(%d), low_batt_alarm(%d)\n", + __func__, fg_data->soc, + fg_data->is_low_batt_alarm); + + return fg_soc; +} + +static void max17047_adjust_fullsoc(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = + i2c_get_clientdata(client); + int prev_full_soc = fg_data->full_soc; + int raw_soc = max17047_get_rawsoc(fg_data->client); + int keep_soc = 0; + + if (raw_soc < 0) { + pr_err("%s : fg data error!(%d)\n", __func__, raw_soc); + fg_data->full_soc = FULL_SOC_DEFAULT; + return; + } + + if (raw_soc < FULL_SOC_LOW) + fg_data->full_soc = FULL_SOC_LOW; + else if (raw_soc > FULL_SOC_HIGH) { + keep_soc = FULL_SOC_HIGH / 100; + fg_data->full_soc = (FULL_SOC_HIGH - keep_soc); + } else { + keep_soc = ((raw_soc * KEEP_FULL_SOC) / 10000); + if (raw_soc > (FULL_SOC_LOW + keep_soc)) + fg_data->full_soc = raw_soc - keep_soc; + else + fg_data->full_soc = FULL_SOC_LOW; + } + + if (prev_full_soc != fg_data->full_soc) + pr_info("%s : full_soc(%d->%d), rsoc(%d), keep(%d)\n", __func__, + prev_full_soc, fg_data->full_soc, raw_soc, keep_soc); +} + +/* SOC% alert, disabled(0xFF00) */ +static void max17047_set_salrt(struct max17047_fuelgauge_data *fg_data, + u8 min, u8 max) +{ + struct i2c_client *client = fg_data->client; + u8 i2c_data[2]; + pr_info("%s: min(%d%%), max(%d%%)\n", __func__, min, max); + + i2c_data[1] = max; + i2c_data[0] = min; + max17047_i2c_write(client, MAX17047_REG_SALRT_TH, i2c_data); + + max17047_i2c_read(client, MAX17047_REG_SALRT_TH, i2c_data); + if ((i2c_data[0] != min) || (i2c_data[1] != max)) + pr_err("%s: SALRT_TH is not valid (0x%02d%02d ? 0x%02d%02d)\n", + __func__, i2c_data[1], i2c_data[0], max, min); +} + +/* Temperature alert, disabled(0x7F80) */ +static void max17047_set_talrt(struct max17047_fuelgauge_data *fg_data, + u8 min, u8 max) +{ + struct i2c_client *client = fg_data->client; + u8 i2c_data[2]; + pr_info("%s: min(0x%02x), max(0x%02x)\n", __func__, min, max); + + i2c_data[1] = max; + i2c_data[0] = min; + max17047_i2c_write(client, MAX17047_REG_TALRT_TH, i2c_data); + + max17047_i2c_read(client, MAX17047_REG_TALRT_TH, i2c_data); + if ((i2c_data[0] != min) || (i2c_data[1] != max)) + pr_err("%s: TALRT_TH is not valid (0x%02d%02d ? 0x%02d%02d)\n", + __func__, i2c_data[1], i2c_data[0], max, min); +} + +/* Voltage alert, disabled(0xFF00) */ +static void max17047_set_valrt(struct max17047_fuelgauge_data *fg_data, + u8 min, u8 max) +{ + struct i2c_client *client = fg_data->client; + u8 i2c_data[2]; + pr_info("%s: min(%dmV), max(%dmV)\n", __func__, min * 20, max * 20); + + i2c_data[1] = max; + i2c_data[0] = min; + max17047_i2c_write(client, MAX17047_REG_VALRT_TH, i2c_data); + + max17047_i2c_read(client, MAX17047_REG_VALRT_TH, i2c_data); + if ((i2c_data[0] != min) || (i2c_data[1] != max)) + pr_err("%s: VALRT_TH is not valid (0x%02d%02d ? 0x%02d%02d)\n", + __func__, i2c_data[1], i2c_data[0], max, min); +} + +static void max17047_alert_init(struct max17047_fuelgauge_data *fg_data) +{ + struct i2c_client *client = fg_data->client; + u8 i2c_data[2]; + pr_debug("%s\n", __func__); + + /* SALRT Threshold setting */ + /* min 1%, max disable */ + max17047_set_salrt(fg_data, 0x01, 0xFF); + + /* TALRT Threshold setting */ + /* min disable, max disable */ + max17047_set_talrt(fg_data, 0x80, 0x7F); + + /* VALRT Threshold setting */ + /* min disable, max disable */ + max17047_set_valrt(fg_data, 0x00, 0xFF); + + /* Enable SOC alerts */ + max17047_i2c_read(client, MAX17047_REG_CONFIG, i2c_data); + i2c_data[0] |= (0x1 << 2); + max17047_i2c_write(client, MAX17047_REG_CONFIG, i2c_data); +} + +static void max17047_reg_init(struct max17047_fuelgauge_data *fg_data) +{ + struct i2c_client *client = fg_data->client; + u8 i2c_data[2]; + pr_debug("%s\n", __func__); + + if (max17047_i2c_read(client, MAX17047_REG_FILTERCFG, i2c_data) < 0) + return; + + /* Clear average vcell (12 sec) */ + i2c_data[0] &= 0x8f; + + max17047_i2c_write(client, MAX17047_REG_FILTERCFG, i2c_data); + + i2c_data[0] = 0xd9; + i2c_data[1] = 0x35; + max17047_i2c_write(client, MAX17047_REG_CGAIN, i2c_data); +} + +static void max17047_update_work(struct work_struct *work) +{ + struct max17047_fuelgauge_data *fg_data = container_of(work, + struct max17047_fuelgauge_data, + update_work.work); + struct power_supply *battery_psy; + struct i2c_client *client = fg_data->client; + union power_supply_propval value; + pr_debug("%s\n", __func__); + +#ifdef CONFIG_SLP + battery_psy = &fg_data->fuelgauge; +#else + battery_psy = power_supply_get_by_name("battery"); +#endif + + max17047_get_vcell(client); + max17047_get_vfocv(client); + max17047_get_avgvcell(client); + max17047_get_rawsoc(client); + max17047_get_soc(client); + + pr_info("%s: VCELL(%d), VFOCV(%d), AVGVCELL(%d), RAWSOC(%d), SOC(%d)\n", + __func__, fg_data->vcell, + fg_data->vfocv, fg_data->avgvcell, + fg_data->rawsoc, fg_data->soc); + + max17047_test_read(fg_data); + + if (!battery_psy || !battery_psy->set_property) { + pr_err("%s: fail to get battery power supply\n", __func__); + return; + } + + battery_psy->set_property(battery_psy, + POWER_SUPPLY_PROP_STATUS, + &value); + + wake_lock_timeout(&fg_data->update_wake_lock, HZ); +} + +#ifdef DEBUG_FUELGAUGE_POLLING +static void max17047_polling_work(struct work_struct *work) +{ + struct max17047_fuelgauge_data *fg_data = container_of(work, + struct max17047_fuelgauge_data, + polling_work.work); + int reg; + int i; + u8 data[2]; + u8 buf[512]; + + max17047_get_vcell(fg_data->client); + max17047_get_vfocv(fg_data->client); + max17047_get_avgvcell(fg_data->client); + max17047_get_rawsoc(fg_data->client); + max17047_get_soc(fg_data->client); + + pr_info("%s: VCELL(%d), VFOCV(%d), AVGVCELL(%d), RAWSOC(%d), SOC(%d)\n", + __func__, fg_data->vcell, + fg_data->vfocv, fg_data->avgvcell, + fg_data->rawsoc, fg_data->soc); + + max17047_test_read(fg_data); + + schedule_delayed_work(&fg_data->polling_work, + msecs_to_jiffies(MAX17047_POLLING_INTERVAL)); +} +#endif + +static enum power_supply_property max17047_fuelgauge_props[] = { + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_VOLTAGE_AVG, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_TEMP, +}; + +static int max17047_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct max17047_fuelgauge_data *fg_data = container_of(psy, + struct max17047_fuelgauge_data, + fuelgauge); + switch (psp) { + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + switch (val->intval) { + case VOLTAGE_TYPE_VCELL: + val->intval = max17047_get_vcell(fg_data->client); + break; + case VOLTAGE_TYPE_VFOCV: + val->intval = max17047_get_vfocv(fg_data->client); + break; + default: + val->intval = max17047_get_vcell(fg_data->client); + break; + } + break; + case POWER_SUPPLY_PROP_VOLTAGE_AVG: + val->intval = max17047_get_avgvcell(fg_data->client); + break; + /* Current (mA) */ + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = get_fuelgauge_value(fg_data->client, FG_CURRENT); + break; + /* Average Current (mA) */ + case POWER_SUPPLY_PROP_CURRENT_AVG: + val->intval = get_fuelgauge_value(fg_data->client, FG_CURRENT_AVG); + break; + case POWER_SUPPLY_PROP_CAPACITY: + switch (val->intval) { + case SOC_TYPE_ADJUSTED: + /*val->intval = max17047_get_soc(fg_data->client);*/ + val->intval = get_fuelgauge_soc(fg_data->client) / 10; + break; + case SOC_TYPE_RAW: + val->intval = max17047_get_rawsoc(fg_data->client); + break; + case SOC_TYPE_FULL: + val->intval = fg_data->full_soc; + break; + default: + val->intval = get_fuelgauge_soc(fg_data->client) / 10; + break; + } + break; + case POWER_SUPPLY_PROP_TEMP: + val->intval = max17047_get_temperature(fg_data->client); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int max17047_reset_soc(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + u8 data[2]; + int vfocv, fullcap; + + /* delay for current stablization */ + msleep(500); + + dev_info(&client->dev, + "%s: Before quick-start - VCELL(%d), VFOCV(%d), VfSOC(%d), RepSOC(%d)\n", + __func__, max17047_get_vcell(client), max17047_get_vfocv(client), + fg_read_vfsoc(client), max17047_get_soc(client)); + dev_info(&client->dev, + "%s: Before quick-start - current(%d), avg current(%d)\n", + __func__, fg_read_current(client), + fg_read_avg_current(client)); + + if (is_jig_attached == JIG_OFF) { + dev_info(&client->dev, + "%s : Return by No JIG_ON signal\n", __func__); + return 0; + } + + fg_write_register(client, MAX17047_REG_CYCLES, 0); + + if (max17047_i2c_read(client, MAX17047_REG_MISCCFG, data) < 0) { + dev_err(&client->dev, "%s: Failed to read MiscCFG\n", __func__); + return -1; + } + + data[1] |= (0x1 << 2); + if (max17047_i2c_write(client, MAX17047_REG_MISCCFG, data) < 0) { + dev_err(&client->dev, + "%s: Failed to write MiscCFG\n", __func__); + return -1; + } + + msleep(250); + fg_write_register(client, MAX17047_REG_FULLCAP, + fg_battery_data[SDI].Capacity); + msleep(500); + + dev_info(&client->dev, + "%s: After quick-start - VCELL(%d), VFOCV(%d), VfSOC(%d), RepSOC(%d)\n", + __func__, max17047_get_vcell(client), max17047_get_vfocv(client), + fg_read_vfsoc(client), max17047_get_soc(client)); + dev_info(&client->dev, + "%s: After quick-start - current(%d), avg current(%d)\n", + __func__, fg_read_current(client), + fg_read_avg_current(client)); + fg_write_register(client, MAX17047_REG_CYCLES, 0x00a0); + +/* P8 is not turned off by Quickstart @3.4V + * (It's not a problem, depend on mode data) + * Power off for factory test(File system, etc..) */ + vfocv = max17047_get_vfocv(client); + if (vfocv < POWER_OFF_VOLTAGE_LOW_MARGIN) { + dev_info(&client->dev, "%s: Power off condition(%d)\n", + __func__, vfocv); + + fullcap = fg_read_register(client, MAX17047_REG_FULLCAP); + /* FullCAP * 0.009 */ + fg_write_register(client, MAX17047_REG_REMCAP_REP, + (u16)(fullcap * 9 / 1000)); + msleep(200); + dev_info(&client->dev, "%s: new soc=%d, vfocv=%d\n", __func__, + max17047_get_soc(client), vfocv); + } + + dev_info(&client->dev, + "%s: Additional step - VfOCV(%d), VfSOC(%d), RepSOC(%d)\n", + __func__, max17047_get_vfocv(client), + fg_read_vfsoc(client), max17047_get_soc(client)); + + return 0; +} + + +static int max17047_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct max17047_fuelgauge_data *fg_data = container_of(psy, + struct max17047_fuelgauge_data, + fuelgauge); + + switch (psp) { + case POWER_SUPPLY_PROP_CAPACITY: + max17047_reset_soc(fg_data->client); + break; + case POWER_SUPPLY_PROP_STATUS: + if (val->intval != POWER_SUPPLY_STATUS_FULL) + return -EINVAL; + pr_info("%s: charger full state!\n", __func__); + /* adjust full soc */ + max17047_adjust_fullsoc(fg_data->client); + break; +#if defined(CONFIG_MACH_GC1) + case POWER_SUPPLY_PROP_RCOMP: + if (fg_data->prev_status == val->intval) { + pr_debug("%s: No rcomp change, prev(%d) = cur(%d)\n", + __func__, fg_data->prev_status, val->intval); + } else { + if (val->intval == POWER_SUPPLY_STATUS_CHARGING) + max17047_set_rcomp(fg_data->client, 1); + else + max17047_set_rcomp(fg_data->client, 0); + max17047_get_rcomp(fg_data->client, val->intval); + fg_data->prev_status = val->intval; + } + break; +#endif + default: + return -EINVAL; + } + + return 0; +} + +static irqreturn_t max17047_fuelgauge_isr(int irq, void *data) +{ + struct max17047_fuelgauge_data *fg_data = data; + struct i2c_client *client = fg_data->client; + u8 i2c_data[2]; + pr_info("%s: irq(%d)\n", __func__, irq); + mutex_lock(&fg_data->irq_lock); + + max17047_i2c_read(client, MAX17047_REG_STATUS, i2c_data); + pr_info("%s: MAX17047_REG_STATUS(0x%02x%02x)\n", __func__, + i2c_data[1], i2c_data[0]); + + cancel_delayed_work(&fg_data->update_work); + wake_lock(&fg_data->update_wake_lock); + schedule_delayed_work(&fg_data->update_work, msecs_to_jiffies(1000)); + + mutex_unlock(&fg_data->irq_lock); + return IRQ_HANDLED; +} + +#if defined(CONFIG_TARGET_LOCALE_KOR) +#ifdef CONFIG_DEBUG_FS +static int max17047_debugfs_open(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->i_private; + return 0; +} + +static ssize_t max17047_debugfs_read_registers(struct file *filp, + char __user *buffer, size_t count, loff_t *ppos) +{ + struct max17047_fuelgauge_data *fg_data = filp->private_data; + struct i2c_client *client = NULL; + u8 i2c_data[2]; + int reg = 0; + char *buf; + size_t len = 0; + ssize_t ret; + + if (!fg_data) { + pr_err("%s : fg_data is null\n", __func__); + return 0; + } + + client = fg_data->client; + + if (*ppos != 0) + return 0; + + if (count < sizeof(buf)) + return -ENOSPC; + + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + reg = MAX17047_REG_STATUS; + max17047_i2c_read(client, reg, i2c_data); + len += snprintf(buf + len, PAGE_SIZE - len, + "status(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]); + + reg = MAX17047_REG_CONFIG; + max17047_i2c_read(client, reg, i2c_data); + len += snprintf(buf + len, PAGE_SIZE - len, + "config(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]); + + reg = MAX17047_REG_RCOMP; + max17047_i2c_read(client, reg, i2c_data); + len += snprintf(buf + len, PAGE_SIZE - len, + "rcomp(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]); + + reg = MAX17047_REG_CGAIN; + max17047_i2c_read(client, reg, i2c_data); + len += snprintf(buf + len, PAGE_SIZE - len, + "cgain(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]); + + reg = MAX17047_REG_SALRT_TH; + max17047_i2c_read(client, reg, i2c_data); + len += snprintf(buf + len, PAGE_SIZE - len, + "salrt(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]); + + reg = MAX17047_REG_MISCCFG; + max17047_i2c_read(client, reg, i2c_data); + len += snprintf(buf + len, PAGE_SIZE - len, + "misc(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]); + + reg = 0x39; + max17047_i2c_read(client, reg, i2c_data); + len += snprintf(buf + len, PAGE_SIZE - len, + "tempc0(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]); + + reg = 0x0F; + max17047_i2c_read(client, reg, i2c_data); + len += snprintf(buf + len, PAGE_SIZE - len, + "remCap(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]); + + reg = 0x10; + max17047_i2c_read(client, reg, i2c_data); + len += snprintf(buf + len, PAGE_SIZE - len, + "fullCap(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]); + + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + + ret = simple_read_from_buffer(buffer, len, ppos, buf, PAGE_SIZE); + kfree(buf); + + return ret; +} + +static const struct file_operations max17047_debugfs_fops = { + .owner = THIS_MODULE, + .open = max17047_debugfs_open, + .read = max17047_debugfs_read_registers, +}; + +static ssize_t max17047_debugfs_read_defaultdata(struct file *filp, + char __user *buffer, size_t count, loff_t *ppos) +{ + struct max17047_fuelgauge_data *fg_data = filp->private_data; + struct i2c_client *client = NULL; + u8 i2c_data[2]; + int reg = 0; + char *buf; + size_t len = 0; + ssize_t ret; + + if (!fg_data) { + pr_err("%s : fg_data is null\n", __func__); + return 0; + } + + client = fg_data->client; + + if (*ppos != 0) + return 0; + + if (count < sizeof(buf)) + return -ENOSPC; + + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + reg = MAX17047_REG_RCOMP; + max17047_i2c_read(client, reg, i2c_data); + len += snprintf(buf + len, PAGE_SIZE - len, + "rcomp=%02x%02x ", i2c_data[1], i2c_data[0]); + + len += snprintf(buf + len, PAGE_SIZE - len, + "fsoc=%d", fg_data->full_soc); + + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + + ret = simple_read_from_buffer(buffer, len, ppos, buf, PAGE_SIZE); + kfree(buf); + + return ret; +} + +static const struct file_operations max17047_debugfs_fops2 = { + .owner = THIS_MODULE, + .open = max17047_debugfs_open, + .read = max17047_debugfs_read_defaultdata, +}; +#endif +#endif + +#ifdef CHECK_RCOMP_UPDATE +static void max17047_check_rcomp_update(struct i2c_client *client) +{ + u8 data[2]; + int ret, rcomp; + + /* read rcomp */ + ret = max17047_i2c_read(client, MAX17047_REG_RCOMP, data); + if (ret < 0) + return; + + rcomp = (data[1] << 8) | data[0]; + pr_info("%s: rcomp = 0x%04x\n", __func__, rcomp); + + /* check rcomp update */ + if (rcomp != MAX17047_NEW_RCOMP) { + data[0] = MAX17047_NEW_RCOMP & 0xff; + data[1] = MAX17047_NEW_RCOMP >> 8; + max17047_i2c_write(client, MAX17047_REG_RCOMP, data); + pr_info("%s: set new rcomp = 0x%04x\n", + __func__, MAX17047_NEW_RCOMP); + max17047_i2c_read(client, MAX17047_REG_RCOMP, data); + rcomp = (data[1] << 8) | data[0]; + pr_info("%s: verify rcomp = 0x%04x\n", __func__, rcomp); + } +} +#endif + +static int __devinit max17047_fuelgauge_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct max17047_fuelgauge_data *fg_data; + struct max17047_platform_data *pdata = client->dev.platform_data; + int ret = -ENODEV; + int rawsoc, firstsoc; + ktime_t current_time; + struct timespec ts; + + pr_info("%s: fuelgauge init\n", __func__); + + if (!pdata) { + pr_err("%s: no platform data\n", __func__); + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) + return -EIO; + + fg_data = kzalloc(sizeof(struct max17047_fuelgauge_data), GFP_KERNEL); + if (!fg_data) + return -ENOMEM; + + fg_data->client = client; + fg_data->pdata = pdata; + fg_client = client; + + i2c_set_clientdata(client, fg_data); + + mutex_init(&fg_data->irq_lock); + + wake_lock_init(&fg_data->update_wake_lock, WAKE_LOCK_SUSPEND, + "fuel-update"); + + /* Initialize full_soc, set this before fisrt SOC reading */ + fg_data->full_soc = FULL_SOC_DEFAULT; + /* first full_soc update */ + rawsoc = max17047_get_rawsoc(fg_data->client); + if (rawsoc > FULL_SOC_DEFAULT) + max17047_adjust_fullsoc(client); + firstsoc = max17047_get_soc(client); + pr_info("%s: rsoc=%d, fsoc=%d, soc=%d\n", __func__, + rawsoc, fg_data->full_soc, firstsoc); + + if (fg_data->pdata->psy_name) + fg_data->fuelgauge.name = + fg_data->pdata->psy_name; + else + fg_data->fuelgauge.name = "max17047-fuelgauge"; + + fg_data->fuelgauge.type = POWER_SUPPLY_TYPE_BATTERY; + fg_data->fuelgauge.properties = max17047_fuelgauge_props; + fg_data->fuelgauge.num_properties = + ARRAY_SIZE(max17047_fuelgauge_props); + fg_data->fuelgauge.get_property = max17047_get_property; + fg_data->fuelgauge.set_property = max17047_set_property; + + ret = power_supply_register(&client->dev, &fg_data->fuelgauge); + if (ret) { + pr_err("%s: failed power supply register\n", __func__); + goto err_psy_reg_fg; + } + + current_time = alarm_get_elapsed_realtime(); + ts = ktime_to_timespec(current_time); + + fg_data->fullcap_check_interval = ts.tv_sec; + + /* Init parameters to prevent wrong compensation */ + fg_data->previous_fullcap = + fg_read_register(fg_data->client, MAX17047_REG_FULLCAP); + + fg_data->previous_vffullcap = + fg_read_register(fg_data->client, MAX17047_REG_FULLCAPNOM); + + max17047_test_read(fg_data); + + if (is_jig_attached == JIG_ON) + fg_reset_capacity_by_jig_connection(fg_data->client); + + /* Initialize fuelgauge alert */ + max17047_alert_init(fg_data); + + INIT_DELAYED_WORK_DEFERRABLE(&fg_data->update_work, + max17047_update_work); + + /* Request IRQ */ + fg_data->irq = gpio_to_irq(fg_data->pdata->irq_gpio); + ret = gpio_request(fg_data->pdata->irq_gpio, "fuelgauge-irq"); + if (ret) { + pr_err("%s: failed requesting gpio %d\n", __func__, + fg_data->pdata->irq_gpio); + goto err_irq; + } + gpio_direction_input(fg_data->pdata->irq_gpio); + gpio_free(fg_data->pdata->irq_gpio); + + ret = request_threaded_irq(fg_data->irq, NULL, + max17047_fuelgauge_isr, IRQF_TRIGGER_FALLING, + "max17047-alert", fg_data); + if (ret < 0) { + pr_err("%s: fail to request max17047 irq: %d: %d\n", + __func__, fg_data->irq, ret); + goto err_irq; + } + + ret = enable_irq_wake(fg_data->irq); + if (ret < 0) { + pr_err("%s: failed enable irq wake %d\n", __func__, + fg_data->irq); + goto err_enable_irq; + } + +#ifdef DEBUG_FUELGAUGE_POLLING + INIT_DELAYED_WORK_DEFERRABLE(&fg_data->polling_work, + max17047_polling_work); + schedule_delayed_work(&fg_data->polling_work, 0); +#else + max17047_test_read(fg_data); +#endif + + pr_info("%s: probe complete\n", __func__); + +#if defined(CONFIG_TARGET_LOCALE_KOR) +#ifdef CONFIG_DEBUG_FS + fg_data->fg_debugfs_dir = + debugfs_create_dir("fg_debug", NULL); + if (fg_data->fg_debugfs_dir) { + if (!debugfs_create_file("max17047_regs", 0644, + fg_data->fg_debugfs_dir, + fg_data, &max17047_debugfs_fops)) + pr_err("%s : debugfs_create_file, error\n", __func__); + if (!debugfs_create_file("default_data", 0644, + fg_data->fg_debugfs_dir, + fg_data, &max17047_debugfs_fops2)) + pr_err("%s : debugfs_create_file2, error\n", __func__); + } else + pr_err("%s : debugfs_create_dir, error\n", __func__); +#endif +#endif + + return 0; + +err_enable_irq: + free_irq(fg_data->irq, fg_data); +err_irq: + power_supply_unregister(&fg_data->fuelgauge); +err_psy_reg_fg: + wake_lock_destroy(&fg_data->update_wake_lock); + mutex_destroy(&fg_data->irq_lock); + kfree(fg_data); + return ret; +} + +static int __devexit max17047_fuelgauge_remove(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + + wake_lock_destroy(&fg_data->update_wake_lock); + free_irq(fg_data->irq, fg_data); + power_supply_unregister(&fg_data->fuelgauge); +#ifdef DEBUG_FUELGAUGE_POLLING + cancel_delayed_work(&fg_data->polling_work); +#endif + cancel_delayed_work(&fg_data->update_work); + mutex_destroy(&fg_data->irq_lock); + kfree(fg_data); + + return 0; +} + +#ifdef CONFIG_PM +static int max17047_fuelgauge_suspend(struct device *dev) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + struct power_supply *psy = power_supply_get_by_name("battery"); + union power_supply_propval value; + int charge_state, voltage_max, voltage_min; + int valrt_vol; + pr_info("%s\n", __func__); + +#ifdef DEBUG_FUELGAUGE_POLLING + cancel_delayed_work(&fg_data->polling_work); +#endif + +#if !defined(CONFIG_SLP) + /* default disable */ + valrt_vol = 0; + + /* voltage alert recharge voltage */ + if (!psy) { + pr_err("%s: fail to get battery psy\n", __func__); + return 0; + } + psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &value); + charge_state = value.intval; + + if (charge_state == POWER_SUPPLY_STATUS_FULL) { + psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + &value); + voltage_max = value.intval; + + /* valrt voltage set as recharge voltage */ + valrt_vol = voltage_max - RECHG_DROP_VALUE; + } else { + psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + &value); + voltage_min = value.intval; + + /* valrt voltage set as min voltage - 50mV */ + valrt_vol = voltage_min - 50000; + } + + pr_info("%s: charge state(%d), vcell(%d), valrt(%d)\n", __func__, + charge_state, fg_data->vcell, valrt_vol); + + /* set voltage alert */ + max17047_set_valrt(fg_data, (valrt_vol / 1000 / 20), 0xFF); +#endif + + return 0; +} + +static int max17047_fuelgauge_resume(struct device *dev) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client); + pr_info("%s\n", __func__); + +#if !defined(CONFIG_SLP) + /* min disable, max disable */ + max17047_set_valrt(fg_data, 0x00, 0xFF); +#endif + +#ifdef DEBUG_FUELGAUGE_POLLING + schedule_delayed_work(&fg_data->polling_work, 0); +#endif + + return 0; +} +#else +#define max17047_fuelgauge_suspend NULL +#define max17047_fuelgauge_resume NULL +#endif /* CONFIG_PM */ + +static const struct i2c_device_id max17047_fuelgauge_id[] = { + {"max17047-fuelgauge", 0}, + {} +}; + +#ifdef CONFIG_HIBERNATION +static const u16 save_addr[] = { + MAX17047_REG_VALRT_TH, + MAX17047_REG_TALRT_TH, + MAX17047_REG_SALRT_TH, + + MAX17047_REG_TEMPERATURE, + MAX17047_REG_CONFIG, + + MAX17047_REG_LEARNCFG, + MAX17047_REG_FILTERCFG, + MAX17047_REG_MISCCFG, + MAX17047_REG_CGAIN, + MAX17047_REG_RCOMP, + MAX17047_REG_SOC_VF, +}; + + +static int max17047_freeze(struct device *dev) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + struct max17047_fuelgauge_data *fg_data + = i2c_get_clientdata(client); + int i, j; + + if (fg_data->reg_dump) { + dev_err(dev, "Register dump is not clean.\n"); + return -EINVAL; + } + + fg_data->reg_dump = kzalloc(sizeof(u16) * ARRAY_SIZE(save_addr), + GFP_KERNEL); + if (!fg_data->reg_dump) { + dev_err(dev, "Cannot allocate memory for hibernation dump.\n"); + return -ENOMEM; + } + + for (i = 0, j = 0; i < ARRAY_SIZE(save_addr); i++, j += 2) + max17047_i2c_read(client, save_addr[i] + , &(fg_data->reg_dump[j])); + + return 0; +} + +static int max17047_restore(struct device *dev) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + struct max17047_fuelgauge_data *fg_data + = i2c_get_clientdata(client); + int i, j; + + if (!fg_data->reg_dump) { + dev_err(dev, "Cannot allocate memory for hibernation dump.\n"); + return -ENOMEM; + } + + for (i = 0, j = 0; i < ARRAY_SIZE(save_addr); i++, j += 2) + max17047_i2c_write(client, save_addr[i] + , &(fg_data->reg_dump[j])); + + kfree(fg_data->reg_dump); + fg_data->reg_dump = NULL; + + return 0; +} +#endif + + + +#ifdef CONFIG_PM +const struct dev_pm_ops max17047_pm = { + .suspend = max17047_fuelgauge_suspend, + .resume = max17047_fuelgauge_resume, +#ifdef CONFIG_HIBERNATION + .freeze = max17047_freeze, + .thaw = max17047_restore, + .restore = max17047_restore, +#endif +}; +#endif + + +MODULE_DEVICE_TABLE(i2c, max17047_fuelgauge_id); + +static struct i2c_driver max17047_i2c_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "max17047-fuelgauge", + .pm = &max17047_pm, + + }, + .probe = max17047_fuelgauge_i2c_probe, + .remove = __devexit_p(max17047_fuelgauge_remove), + .id_table = max17047_fuelgauge_id, +}; + +static int __init max17047_fuelgauge_init(void) +{ + return i2c_add_driver(&max17047_i2c_driver); +} + +static void __exit max17047_fuelgauge_exit(void) +{ + i2c_del_driver(&max17047_i2c_driver); +} + +module_init(max17047_fuelgauge_init); +module_exit(max17047_fuelgauge_exit); + +MODULE_AUTHOR("SangYoung Son "); +MODULE_DESCRIPTION("max17047 Fuel gauge driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/battery/samsung_battery.c b/drivers/battery/samsung_battery.c index ffe10e9..8bc5c7f 100644 --- a/drivers/battery/samsung_battery.c +++ b/drivers/battery/samsung_battery.c @@ -2007,6 +2007,14 @@ static int samsung_battery_set_property(struct power_supply *ps, case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: info->pdata->voltage_min = val->intval; break; +#if defined(CONFIG_MACH_KONA) + case POWER_SUPPLY_PROP_COMPENSATION_3: + info->is_comp_3 = val->intval; + break; + case POWER_SUPPLY_PROP_COMPENSATION_1: + info->is_comp_1 = val->intval; + break; +#endif default: return -EINVAL; } @@ -2037,12 +2045,19 @@ static int samsung_usb_get_property(struct power_supply *ps, return -EINVAL; /* Set enable=1 only if the USB charger is connected */ - val->intval = ((info->charge_virt_state != - POWER_SUPPLY_STATUS_DISCHARGING) && - ((info->cable_type == POWER_SUPPLY_TYPE_USB) || +#if defined(CONFIG_MACH_KONA) + val->intval = (((info->cable_type == POWER_SUPPLY_TYPE_USB) || (info->cable_type == POWER_SUPPLY_TYPE_USB_CDP) || ((info->cable_type == POWER_SUPPLY_TYPE_DOCK) && (info->online_prop == ONLINE_PROP_USB)))); +#else + val->intval = ((info->charge_virt_state != + POWER_SUPPLY_STATUS_DISCHARGING) && + ((info->cable_type == POWER_SUPPLY_TYPE_USB) || + (info->cable_type == POWER_SUPPLY_TYPE_USB_CDP) || + ((info->cable_type == POWER_SUPPLY_TYPE_DOCK) && + (info->online_prop == ONLINE_PROP_USB)))); +#endif return 0; } @@ -2161,9 +2176,11 @@ static __devinit int samsung_battery_probe(struct platform_device *pdev) pr_info("%s: VF detect source: %s\n", __func__, vf_src_name[info->pdata->vf_det_src]); +#if !defined(CONFIG_MACH_KONA) /* recalculate recharge voltage, it depends on max voltage value */ info->pdata->recharge_voltage = info->pdata->voltage_max - RECHG_DROP_VALUE; +#endif pr_info("%s: Recharge voltage: %d\n", __func__, info->pdata->recharge_voltage); diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 6c03331..61e680e 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -563,6 +563,11 @@ config KEYBOARD_W90P910 To compile this driver as a module, choose M here: the module will be called w90p910_keypad. +config SENSORS_HALL + tristate "HALL" + help + Say Y here to enable the HALL. + source "drivers/input/keyboard/cypress/Kconfig" endif diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index bf75ef5..b1fddc8 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -47,10 +47,20 @@ struct gpio_keys_drvdata { unsigned int n_buttons; int (*enable)(struct device *dev); void (*disable)(struct device *dev); +#ifdef CONFIG_SENSORS_HALL + int gpio_flip_cover; + bool flip_cover; + struct delayed_work flip_cover_dwork; +#endif struct gpio_button_data data[0]; /* WARNING: this area can be expanded. Do NOT add any member! */ }; +#ifdef CONFIG_SENSORS_HALL +int flip_cover_open; +extern ts_powered_on; +#endif + /* * SYSFS interface for enabling/disabling keys and switches: * @@ -376,12 +386,36 @@ out: return count; } +#ifdef CONFIG_SENSORS_HALL +static ssize_t hall_detect_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); + + if (ddata->flip_cover){ + printk("%s: OPEN",__func__); + sprintf(buf, "OPEN"); + }else{ + printk("%s: CLOSE",__func__); + sprintf(buf, "CLOSE"); + } + + return strlen(buf); +} +#endif + static DEVICE_ATTR(sec_key_pressed, 0664, key_pressed_show, NULL); static DEVICE_ATTR(wakeup_keys, 0664, NULL, wakeup_enable); +#ifdef CONFIG_SENSORS_HALL +static DEVICE_ATTR(hall_detect, 0664, hall_detect_show, NULL); +#endif static struct attribute *sec_key_attrs[] = { &dev_attr_sec_key_pressed.attr, &dev_attr_wakeup_keys.attr, +#ifdef CONFIG_SENSORS_HALL + &dev_attr_hall_detect.attr, +#endif NULL, }; @@ -531,9 +565,16 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata) } } #endif +#ifdef CONFIG_SENSORS_HALL + if(!flip_cover_open && button->code == KEY_POWER){ + printk(KERN_DEBUG" cover closed...ignoring PWR button"); + }else{ +#endif input_event(input, type, button->code, !!state); input_sync(input); - +#ifdef CONFIG_SENSORS_HALL + } +#endif if (button->code == KEY_POWER) printk(KERN_DEBUG"[keys]PWR %d\n", !!state); } @@ -652,11 +693,83 @@ fail2: return error; } +#ifdef CONFIG_SENSORS_HALL +static void flip_cover_work(struct work_struct *work) +{ + struct gpio_keys_drvdata *ddata = + container_of(work, struct gpio_keys_drvdata, + flip_cover_dwork.work); + + ddata->flip_cover = gpio_get_value(ddata->gpio_flip_cover); + + printk(KERN_DEBUG "[keys] %s : %d\n", + __func__, ddata->flip_cover); + + /* input_report_switch(ddata->input, SW_FLIP, ddata->flip_cover); + input_sync(ddata->input);*/ + + flip_cover_open = ddata->flip_cover; + + if(!ts_powered_on && !ddata->flip_cover){ + printk("screen already off\n"); + }else{ + input_report_key(ddata->input, KEY_POWER, 1); + input_sync(ddata->input); + input_report_key(ddata->input, KEY_POWER, 0); + input_sync(ddata->input); + } +} + +static irqreturn_t flip_cover_detect(int irq, void *dev_id) +{ + struct gpio_keys_drvdata *ddata = dev_id; + + cancel_delayed_work_sync(&ddata->flip_cover_dwork); + schedule_delayed_work(&ddata->flip_cover_dwork, HZ / 20); + return IRQ_HANDLED; +} +#endif + static int gpio_keys_open(struct input_dev *input) { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); + +#ifdef CONFIG_SENSORS_HALL + int ret = 0; + int irq = gpio_to_irq(ddata->gpio_flip_cover); + + INIT_DELAYED_WORK(&ddata->flip_cover_dwork, flip_cover_work); + + ret = request_threaded_irq( + irq, NULL, + flip_cover_detect, + IRQF_DISABLED | IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "flip_cover", ddata); + + if (ret) { + printk(KERN_ERR + "keys: failed to request flip cover irq %d gpio %d\n", + irq, ddata->gpio_flip_cover); + goto hall_sensor_error; + } + + ret = enable_irq_wake(irq); + if (ret < 0) { + printk(KERN_ERR + "keys: Failed to Enable Wakeup Source(%d) \n", + ret); + goto hall_sensor_error; + } + + /* update the current status */ + schedule_delayed_work(&ddata->flip_cover_dwork, HZ / 2); - return ddata->enable ? ddata->enable(input->dev.parent) : 0; +hall_sensor_error: + +#endif + + return ddata->enable ? ddata->enable(input->dev.parent) : 0; } static void gpio_keys_close(struct input_dev *input) @@ -690,6 +803,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) ddata->n_buttons = pdata->nbuttons; ddata->enable = pdata->enable; ddata->disable = pdata->disable; +#ifdef CONFIG_SENSORS_HALL + ddata->gpio_flip_cover = pdata->gpio_flip_cover; +#endif mutex_init(&ddata->disable_lock); platform_set_drvdata(pdev, ddata); @@ -698,6 +814,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) input->name = pdata->name ? : pdev->name; input->phys = "gpio-keys/input0"; input->dev.parent = &pdev->dev; +/*#ifdef CONFIG_SENSORS_HALL + input->evbit[0] |= BIT_MASK(EV_SW); + input_set_capability(input, EV_SW, SW_FLIP); +#endif*/ input->open = gpio_keys_open; input->close = gpio_keys_close; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8c4ba2a..ec4d775 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -958,6 +958,27 @@ config TOUCHSCREEN_SYNAPTICS_S7301 To compile this driver as a module, choose M here: the module will be called melfas_ts. +config TOUCHSCREEN_SYNAPTICS_S7301_KEYS + bool "S7301 touch key support" + default n + help + Say Y here if you want support for SYNAPTICS S7301 + touchscreen controller Keys. + +config TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND + bool "S7301 touch key workaround" + default n + help + Say Y here if you want support for SYNAPTICS S7301 + touchscreen controller reset control + +config TOUCHSCREEN_SYNAPTICS_S7301_KEYLED + bool "S7301 touch keyled support" + default n + help + Say Y here if you want support for SYNAPTICS S7301 + with GPIO led control + config TOUCHSCREEN_CYTTSP4 tristate "Cypress GEN4 Touchscreen Interface" depends on I2C @@ -974,6 +995,11 @@ config SEC_TOUCHSCREEN_DVFS_LOCK help Say Y here if you want support for lock the cpu frequency. +config SEC_TOUCHSCREEN_SURFACE_TOUCH + tristate "SEC surface touch" + help + Say Y here if you want support for surface touch. + config KEYPAD_MELFAS_TOUCH tristate "Melfas touch keypad support" default n diff --git a/drivers/input/touchscreen/synaptics_fw.h b/drivers/input/touchscreen/synaptics_fw.h index 2cc5314..a5da7325 100644 --- a/drivers/input/touchscreen/synaptics_fw.h +++ b/drivers/input/touchscreen/synaptics_fw.h @@ -1,6 +1,8854 @@ #ifndef __RMI_FW_H #define __RMI_FW_H +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) +const char *rmi_config_ver_button = "00"; + +#if defined(CONFIG_KONA_01_BD) +const u8 rmi_fw_button[] = { + /*0000:*/ 0x82, 0x78, 0x14, 0xfe, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + /*0010:*/ 0x53, 0x37, 0x33, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0020:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0030:*/ 0x44, 0x53, 0x34, 0x20, 0x52, 0x33, 0x2e, 0x35, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0040:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0050:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0060:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0070:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0080:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0090:*/ 0x49, 0x32, 0x43, 0x00, 0x04, 0x00, 0xff, 0x00, 0x0c, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + /*00a0:*/ 0x49, 0x32, 0x43, 0x00, 0x04, 0x00, 0xff, 0x00, 0x0c, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + /*00b0:*/ 0x69, 0x96, 0x7e, 0xd0, 0x20, 0x5a, 0x00, 0x20, 0xc5, 0xc0, 0x2a, 0x79, 0xac, 0x74, 0x2e, 0x45, + /*00c0:*/ 0x57, 0x05, 0x48, 0x7c, 0xd7, 0x03, 0xb0, 0x50, 0xe0, 0x77, 0x3c, 0x8b, 0x79, 0xf6, 0x71, 0x75, + /*00d0:*/ 0xca, 0xec, 0xb0, 0x31, 0x53, 0xaa, 0x37, 0xe9, 0x19, 0x47, 0x46, 0x84, 0xba, 0x28, 0x18, 0xe9, + /*00e0:*/ 0x51, 0x89, 0xe7, 0xce, 0x3e, 0x64, 0x26, 0xa6, 0x25, 0x31, 0xc5, 0x0d, 0x9a, 0xa9, 0x93, 0xfa, + /*00f0:*/ 0x7c, 0x9a, 0x20, 0x17, 0x1a, 0x92, 0x35, 0xa6, 0x9a, 0x75, 0xa0, 0x23, 0x4f, 0xb1, 0xec, 0x1e, + /*0100:*/ 0x64, 0xce, 0x5c, 0x97, 0x6f, 0xf6, 0x36, 0x81, 0xf8, 0x90, 0x17, 0xb0, 0x0d, 0x0c, 0xd3, 0x50, + /*0110:*/ 0x2b, 0xb3, 0x37, 0x31, 0xe9, 0x03, 0x0c, 0x63, 0xf1, 0x9e, 0x52, 0x2d, 0xf5, 0xd3, 0x44, 0x87, + /*0120:*/ 0xa3, 0xef, 0xc0, 0x55, 0xf3, 0xca, 0x62, 0x4f, 0xc8, 0x13, 0xbd, 0x20, 0xe6, 0x3a, 0xac, 0xcd, + /*0130:*/ 0x2b, 0x4b, 0x2c, 0x18, 0x21, 0x16, 0xf3, 0xb6, 0xaa, 0x41, 0xe2, 0x66, 0xfc, 0x6f, 0x1f, 0xce, + /*0140:*/ 0x7f, 0x17, 0xdd, 0xfd, 0x49, 0xde, 0x8b, 0x2b, 0xec, 0xf9, 0xe4, 0xed, 0xaf, 0x8c, 0x26, 0xe0, + /*0150:*/ 0xb5, 0x30, 0xde, 0x4b, 0xb9, 0x9e, 0x4d, 0xfe, 0x43, 0x86, 0xce, 0x9e, 0x0b, 0x6f, 0xb9, 0xc8, + /*0160:*/ 0x1e, 0xcb, 0x83, 0xee, 0xdb, 0xf3, 0xcb, 0x5f, 0xa2, 0x9b, 0xba, 0x53, 0x3d, 0xde, 0x85, 0xce, + /*0170:*/ 0xda, 0xdc, 0xfd, 0x86, 0xe6, 0xdc, 0xb0, 0x14, 0xc0, 0x87, 0x68, 0x6d, 0x15, 0x39, 0x99, 0x81, + /*0180:*/ 0xf4, 0x8f, 0xfa, 0x4b, 0x47, 0x53, 0x99, 0x05, 0xe8, 0x9f, 0xd7, 0x8c, 0x0a, 0xdd, 0x12, 0x95, + /*0190:*/ 0xc6, 0xd0, 0xe3, 0xf9, 0x2c, 0xb0, 0xee, 0x4f, 0x50, 0x51, 0x9e, 0x2c, 0x7f, 0x07, 0xd7, 0xd7, + /*01a0:*/ 0xa6, 0xfc, 0x58, 0x56, 0x65, 0x04, 0x49, 0x73, 0x05, 0x3e, 0xd2, 0xe9, 0x37, 0xb8, 0xd7, 0xbc, + /*01b0:*/ 0x79, 0x5f, 0x8c, 0xc7, 0x28, 0xe6, 0x39, 0xef, 0x29, 0x7f, 0x26, 0x52, 0xd8, 0xda, 0x99, 0x4c, + /*01c0:*/ 0x6b, 0x6e, 0x7a, 0xd3, 0x9e, 0x75, 0xca, 0x55, 0xb2, 0x29, 0x88, 0xb8, 0x0b, 0x1d, 0x1c, 0x81, + /*01d0:*/ 0x98, 0x15, 0xf7, 0x59, 0x1d, 0x73, 0xc3, 0x8d, 0x42, 0x5e, 0xce, 0x78, 0x9b, 0x36, 0x49, 0xbe, + /*01e0:*/ 0xad, 0xc9, 0x81, 0xa4, 0x7e, 0x4c, 0xcb, 0x35, 0x52, 0x17, 0xd7, 0x73, 0x29, 0x4e, 0x81, 0xdf, + /*01f0:*/ 0x66, 0x04, 0x1d, 0x49, 0x3f, 0xa0, 0xf2, 0x2f, 0x42, 0xd0, 0xf4, 0xe9, 0x49, 0xae, 0x52, 0xf7, + /*0200:*/ 0xce, 0x67, 0x45, 0x5c, 0x59, 0x91, 0xb0, 0x83, 0xc0, 0x2e, 0xf4, 0x77, 0xcb, 0x65, 0xb5, 0xd3, + /*0210:*/ 0x18, 0x15, 0x9e, 0x05, 0x30, 0x8f, 0xb7, 0xb8, 0x40, 0x1f, 0x71, 0xb1, 0x0f, 0x81, 0x03, 0x89, + /*0220:*/ 0xb7, 0x6d, 0xef, 0x46, 0x6e, 0x45, 0x46, 0xc5, 0xd3, 0x94, 0x92, 0x41, 0xca, 0xc5, 0x32, 0xac, + /*0230:*/ 0x34, 0x10, 0x2b, 0x1a, 0x4f, 0xec, 0x94, 0xcf, 0x91, 0xd9, 0x80, 0xf1, 0x60, 0x9d, 0xe7, 0x63, + /*0240:*/ 0x51, 0xa7, 0xec, 0xe6, 0x1d, 0xf8, 0x38, 0xc7, 0xec, 0xe7, 0x69, 0x08, 0x02, 0x7b, 0x09, 0x89, + /*0250:*/ 0x84, 0x9a, 0xbd, 0x1f, 0x04, 0x9f, 0xf3, 0x20, 0xc8, 0x23, 0x4c, 0xd7, 0x0a, 0x64, 0x47, 0x43, + /*0260:*/ 0xb6, 0xc8, 0xad, 0xb7, 0xd5, 0xa4, 0xb0, 0xea, 0x57, 0x8d, 0xe9, 0x4e, 0x18, 0x81, 0x08, 0x26, + /*0270:*/ 0x68, 0x66, 0xe6, 0x0b, 0xb2, 0x5d, 0xf5, 0xc3, 0xc1, 0xc1, 0x25, 0x84, 0xdd, 0x00, 0x34, 0x10, + /*0280:*/ 0x94, 0xb6, 0xaf, 0x9f, 0x6a, 0xd5, 0x34, 0x1e, 0x9a, 0x42, 0xd0, 0xa7, 0xc9, 0xd7, 0x3f, 0xc3, + /*0290:*/ 0x43, 0xf2, 0x80, 0x94, 0x2e, 0xb9, 0xdb, 0x60, 0x76, 0xc5, 0xf5, 0x6f, 0xe8, 0x83, 0x96, 0x1b, + /*02a0:*/ 0x96, 0x80, 0xed, 0xb4, 0x0b, 0xc3, 0x34, 0x92, 0xa3, 0xe7, 0xb8, 0x07, 0x23, 0x1b, 0x1b, 0x44, + /*02b0:*/ 0x4a, 0x09, 0xf5, 0xb9, 0x50, 0x75, 0xf2, 0xd6, 0x75, 0xae, 0xef, 0xfa, 0x29, 0x4f, 0x7a, 0xf0, + /*02c0:*/ 0xfa, 0x01, 0xf4, 0x0c, 0x67, 0x2c, 0x2d, 0x36, 0x75, 0xfb, 0xe9, 0xaa, 0xf5, 0x4b, 0x87, 0xbb, + /*02d0:*/ 0xb8, 0xe7, 0x62, 0x4f, 0xbb, 0xc1, 0xc7, 0xd6, 0xa4, 0x10, 0xa3, 0xca, 0xb9, 0x80, 0x7a, 0x1e, + /*02e0:*/ 0xb0, 0xc5, 0xaa, 0x84, 0x0e, 0xe8, 0x10, 0x25, 0xa4, 0xd5, 0x1d, 0xc3, 0x2f, 0x11, 0x8e, 0xdc, + /*02f0:*/ 0xae, 0x9d, 0x51, 0x75, 0x40, 0x9e, 0x92, 0xec, 0x94, 0xff, 0x24, 0xbd, 0x00, 0x51, 0x43, 0x15, + /*0300:*/ 0x22, 0x7f, 0x7e, 0x22, 0xfa, 0x57, 0x2b, 0x1c, 0xf3, 0xb1, 0x11, 0x62, 0x0d, 0xb3, 0x68, 0x1a, + /*0310:*/ 0x6f, 0x2c, 0xb1, 0x6a, 0x0a, 0xb6, 0xc0, 0x8e, 0x14, 0x2f, 0x49, 0xd6, 0x65, 0x77, 0xb9, 0xfb, + /*0320:*/ 0x62, 0x78, 0xbf, 0x05, 0x1d, 0x37, 0xc7, 0x59, 0xa0, 0x1a, 0x8e, 0xb3, 0x08, 0x07, 0x69, 0x12, + /*0330:*/ 0x8b, 0xa1, 0x36, 0xd2, 0x42, 0xfe, 0x5a, 0xf7, 0xa6, 0xfd, 0x8b, 0x27, 0x6d, 0x1d, 0x3b, 0x8b, + /*0340:*/ 0xcb, 0xe9, 0x2b, 0x3f, 0xdd, 0xe0, 0xa4, 0x4e, 0x97, 0x41, 0x72, 0x15, 0xfc, 0x7a, 0x40, 0x84, + /*0350:*/ 0x24, 0x56, 0x76, 0xdd, 0x7b, 0xb8, 0xf6, 0xdc, 0x15, 0x01, 0x4a, 0x5f, 0x21, 0xae, 0xc0, 0xbd, + /*0360:*/ 0x14, 0x83, 0x35, 0x64, 0x54, 0x7d, 0xb5, 0x8b, 0xc6, 0x8d, 0xe0, 0x6a, 0xe4, 0x2b, 0x69, 0x49, + /*0370:*/ 0xd1, 0x0b, 0x17, 0x27, 0x09, 0x9a, 0x52, 0x82, 0x57, 0x90, 0x2f, 0x24, 0x43, 0xc3, 0x9d, 0x7d, + /*0380:*/ 0x31, 0x26, 0x6f, 0x54, 0x7d, 0xb6, 0x51, 0x15, 0x47, 0x4e, 0x9e, 0x96, 0x81, 0x29, 0xcb, 0xaa, + /*0390:*/ 0x01, 0xee, 0x77, 0x57, 0xc0, 0xf6, 0xb4, 0xe0, 0xd7, 0x90, 0xa9, 0x44, 0x2c, 0xe3, 0xa9, 0x32, + /*03a0:*/ 0x17, 0x3d, 0x5c, 0xe3, 0xc9, 0x82, 0xb2, 0x56, 0xb3, 0x9b, 0xda, 0xd6, 0x7c, 0x7d, 0x64, 0xd4, + /*03b0:*/ 0xe4, 0x39, 0x0d, 0xcc, 0xf3, 0x02, 0x59, 0xbe, 0x4b, 0x58, 0x4e, 0x1f, 0x47, 0x46, 0x55, 0x97, + /*03c0:*/ 0x67, 0xe7, 0xdc, 0x2f, 0xb1, 0x91, 0x81, 0x0b, 0x46, 0x97, 0x78, 0x25, 0x29, 0xb0, 0x7f, 0xa2, + /*03d0:*/ 0xb9, 0xfa, 0xf4, 0x20, 0x19, 0xab, 0xae, 0xf4, 0x7e, 0x74, 0x92, 0xf3, 0x63, 0x97, 0x05, 0xf4, + /*03e0:*/ 0x8c, 0xc8, 0xfb, 0xa7, 0x6f, 0xdf, 0x2d, 0xa8, 0x80, 0x17, 0x0c, 0x37, 0x6d, 0xe4, 0x97, 0x5b, + /*03f0:*/ 0xa4, 0x1d, 0xda, 0xb7, 0x45, 0xf0, 0xce, 0x7d, 0x31, 0xcc, 0xc2, 0x29, 0x37, 0xd1, 0x8c, 0x3d, + /*0400:*/ 0xcc, 0xa2, 0xf0, 0x70, 0x16, 0x9b, 0x87, 0xc6, 0x97, 0x20, 0x99, 0x8b, 0xb4, 0xb5, 0x39, 0xf7, + /*0410:*/ 0x7c, 0x7f, 0x86, 0x37, 0x79, 0x6e, 0x8b, 0x1b, 0xbf, 0xfb, 0x68, 0xd3, 0xf4, 0x61, 0x58, 0xe5, + /*0420:*/ 0x8a, 0xb0, 0xee, 0x70, 0x06, 0x18, 0x0c, 0x6b, 0x64, 0xf3, 0xb0, 0x64, 0x30, 0xee, 0xd3, 0xd1, + /*0430:*/ 0xa8, 0xe1, 0x30, 0xfc, 0x82, 0x36, 0x67, 0x93, 0x05, 0x6b, 0x4a, 0x33, 0x93, 0x5b, 0x8d, 0xdf, + /*0440:*/ 0xf4, 0x19, 0x3b, 0x85, 0xf0, 0x36, 0xf7, 0x50, 0xaa, 0x5e, 0xf7, 0x83, 0x93, 0x67, 0x78, 0x33, + /*0450:*/ 0x77, 0x3f, 0x9e, 0x34, 0x06, 0x6c, 0xcb, 0xc3, 0x00, 0x7f, 0xea, 0x39, 0x6d, 0xc5, 0x5e, 0x91, + /*0460:*/ 0xb1, 0x00, 0xbe, 0x6f, 0x08, 0x96, 0x01, 0xe4, 0xcb, 0x9f, 0x92, 0x79, 0x50, 0xaa, 0xda, 0x1e, + /*0470:*/ 0xec, 0x12, 0x2b, 0x4b, 0x0a, 0xa3, 0xcf, 0x8c, 0x1f, 0x4b, 0x15, 0xee, 0xec, 0x18, 0xa6, 0xfe, + /*0480:*/ 0xd5, 0x73, 0x82, 0x1d, 0x6e, 0x21, 0x8c, 0xe5, 0xf4, 0x36, 0x83, 0x9e, 0x00, 0x7b, 0x60, 0x9f, + /*0490:*/ 0x0d, 0xb4, 0x60, 0x70, 0xe0, 0x99, 0xc6, 0x55, 0xb9, 0xee, 0x3e, 0x24, 0x06, 0x15, 0x79, 0x0d, + /*04a0:*/ 0xa6, 0xc7, 0x79, 0x97, 0x01, 0x5c, 0x52, 0x38, 0xfa, 0x5b, 0x71, 0x38, 0xfa, 0xbf, 0xa0, 0x2c, + /*04b0:*/ 0x2c, 0x9d, 0x25, 0xfa, 0x70, 0xd7, 0x32, 0xb1, 0x33, 0xb6, 0xcd, 0xcd, 0xcd, 0xf6, 0x97, 0x3b, + /*04c0:*/ 0x3b, 0x0a, 0x33, 0xbb, 0x7a, 0xa5, 0x89, 0x14, 0xa6, 0x15, 0x44, 0xdb, 0x91, 0x07, 0x75, 0x48, + /*04d0:*/ 0xd5, 0x45, 0x46, 0x71, 0x1c, 0xf2, 0x12, 0xbc, 0x61, 0x70, 0x50, 0x56, 0xd3, 0x21, 0x5d, 0xc4, + /*04e0:*/ 0x29, 0x9f, 0x04, 0xfe, 0xe8, 0xdb, 0x77, 0x42, 0xde, 0xf3, 0xef, 0x2b, 0xfb, 0x34, 0xe7, 0x00, + /*04f0:*/ 0x8a, 0x50, 0x40, 0x3f, 0x62, 0x3d, 0x94, 0x49, 0xd2, 0x95, 0x27, 0xec, 0x86, 0xcd, 0xa2, 0x05, + /*0500:*/ 0xac, 0xfe, 0xb0, 0x83, 0xee, 0x52, 0x05, 0x7c, 0x40, 0x27, 0x4b, 0xc7, 0x93, 0xaa, 0x92, 0xce, + /*0510:*/ 0x72, 0x70, 0x8d, 0x9a, 0x5b, 0x88, 0x6b, 0x59, 0xa7, 0x61, 0xf7, 0x12, 0xe8, 0x61, 0xb6, 0x23, + /*0520:*/ 0xe8, 0xd3, 0xfc, 0x6a, 0xec, 0x4a, 0x05, 0xcd, 0x49, 0x74, 0xf4, 0xcb, 0x0e, 0xe3, 0x95, 0x95, + /*0530:*/ 0x0e, 0xc3, 0xd7, 0x9e, 0xb6, 0x6e, 0xcb, 0x4f, 0xdc, 0xe3, 0x3d, 0x87, 0x23, 0x3a, 0xc8, 0x8d, + /*0540:*/ 0x4f, 0x7b, 0xd8, 0xe9, 0x12, 0x46, 0x92, 0x0c, 0x75, 0xe0, 0x6b, 0x35, 0xf1, 0x82, 0xbc, 0xbb, + /*0550:*/ 0x09, 0x3f, 0xf9, 0xa7, 0xb6, 0x29, 0x62, 0x64, 0x09, 0x02, 0x5b, 0xf7, 0x47, 0xac, 0x69, 0xe5, + /*0560:*/ 0xb9, 0x7a, 0x6a, 0x7b, 0xb1, 0xad, 0xf4, 0x5f, 0xa4, 0x2c, 0x31, 0x06, 0x69, 0x63, 0x25, 0x32, + /*0570:*/ 0x75, 0x35, 0x95, 0x06, 0x41, 0xf8, 0x40, 0xce, 0x35, 0x2c, 0xad, 0x9b, 0xfb, 0xc0, 0x87, 0xed, + /*0580:*/ 0xe9, 0xd9, 0xe1, 0x65, 0x45, 0xc1, 0x98, 0x87, 0x0f, 0x2d, 0xc9, 0x38, 0xbc, 0x24, 0xdb, 0xa7, + /*0590:*/ 0x51, 0xae, 0x04, 0xa8, 0x3e, 0x1f, 0xab, 0xd4, 0xbb, 0x00, 0x08, 0x93, 0xc3, 0xcf, 0x15, 0x94, + /*05a0:*/ 0x2c, 0xd9, 0xa4, 0x0f, 0xb1, 0xc4, 0xda, 0xc6, 0xac, 0x24, 0x17, 0x8a, 0xda, 0xab, 0x4e, 0xa7, + /*05b0:*/ 0xeb, 0xeb, 0xc2, 0xdd, 0x01, 0x51, 0xfd, 0xc2, 0xf9, 0x3a, 0x2b, 0x97, 0x19, 0x3f, 0x1a, 0x84, + /*05c0:*/ 0x65, 0x14, 0xd6, 0xac, 0xf8, 0xbd, 0xe5, 0xa3, 0xb4, 0x19, 0x4b, 0xbe, 0x02, 0xe7, 0x71, 0xff, + /*05d0:*/ 0x14, 0xbe, 0xfa, 0x49, 0x20, 0x50, 0x74, 0x43, 0x68, 0x23, 0x86, 0x4b, 0xe3, 0xbe, 0x4d, 0x16, + /*05e0:*/ 0x93, 0xd0, 0xcf, 0xa5, 0x5a, 0x56, 0x0a, 0x4e, 0x05, 0xf0, 0x24, 0xf0, 0xe9, 0xbb, 0xf3, 0xd2, + /*05f0:*/ 0xcf, 0xaa, 0x1d, 0x6b, 0x99, 0x31, 0x79, 0xd8, 0x26, 0xc8, 0x0a, 0xa4, 0x32, 0xb1, 0xe2, 0x0c, + /*0600:*/ 0xaa, 0xb4, 0xe0, 0x05, 0xc4, 0x60, 0xb9, 0xdf, 0xad, 0x95, 0x51, 0x29, 0xbc, 0xa8, 0xcb, 0xae, + /*0610:*/ 0xc3, 0x75, 0xbf, 0x42, 0x8f, 0x02, 0xe8, 0xf1, 0x74, 0x2a, 0x93, 0x98, 0xce, 0x7e, 0x13, 0xd5, + /*0620:*/ 0xd6, 0x2c, 0xd5, 0x08, 0x45, 0xe2, 0x6d, 0xe1, 0x2a, 0x63, 0x8d, 0xa4, 0x3e, 0xab, 0x73, 0x6d, + /*0630:*/ 0x4c, 0x06, 0xf8, 0x44, 0x5a, 0xb1, 0x65, 0x0f, 0x1d, 0xf3, 0xcd, 0xf2, 0x3e, 0xde, 0xa2, 0x12, + /*0640:*/ 0xe6, 0x1c, 0xbd, 0x84, 0x65, 0x13, 0xb5, 0x3c, 0x9a, 0xa8, 0x17, 0xc3, 0x9e, 0xb4, 0xab, 0x52, + /*0650:*/ 0x30, 0x4c, 0x0a, 0xc2, 0xff, 0x20, 0x4b, 0xb4, 0x8e, 0xf9, 0x4a, 0xb6, 0x21, 0xaa, 0x47, 0x68, + /*0660:*/ 0x61, 0x6f, 0x81, 0x0e, 0x36, 0xe7, 0x19, 0x2f, 0x68, 0xbb, 0x18, 0x29, 0xdd, 0xf1, 0xc3, 0x57, + /*0670:*/ 0x9a, 0xe0, 0x66, 0x47, 0xda, 0xe2, 0x24, 0x27, 0xb7, 0x75, 0x6d, 0x99, 0x5f, 0x94, 0x5b, 0xae, + /*0680:*/ 0x60, 0xde, 0xc2, 0x2a, 0xd5, 0x36, 0x24, 0x61, 0x6a, 0x39, 0x08, 0x32, 0x18, 0x04, 0x41, 0x0f, + /*0690:*/ 0x24, 0xc2, 0x4a, 0x5f, 0xa2, 0x32, 0xf6, 0x8a, 0xe4, 0x03, 0x9e, 0x85, 0xb0, 0xe6, 0x5b, 0xeb, + /*06a0:*/ 0x15, 0x21, 0xce, 0xc7, 0xdc, 0x90, 0xfb, 0x22, 0x94, 0xf1, 0x77, 0x1b, 0x60, 0x17, 0x97, 0x6e, + /*06b0:*/ 0x19, 0x51, 0xde, 0xf6, 0x73, 0xa5, 0xf1, 0xf5, 0x71, 0xc5, 0xa2, 0x44, 0x61, 0x20, 0xe3, 0x08, + /*06c0:*/ 0x82, 0xd6, 0x9f, 0xfe, 0xdb, 0x11, 0x10, 0xfb, 0x38, 0x72, 0x9e, 0x3a, 0x1b, 0xa2, 0x28, 0xdb, + /*06d0:*/ 0x37, 0xef, 0xaf, 0x13, 0x6b, 0xde, 0x35, 0xa3, 0xc0, 0x42, 0x2c, 0xd3, 0xe0, 0x11, 0xe9, 0xe4, + /*06e0:*/ 0x94, 0x9c, 0x1e, 0xe4, 0x01, 0x02, 0x22, 0x8c, 0x13, 0x27, 0xda, 0xe6, 0x30, 0x61, 0x67, 0xca, + /*06f0:*/ 0x40, 0x87, 0x06, 0xce, 0x72, 0xa7, 0x14, 0x15, 0xa7, 0xe6, 0xa3, 0x7c, 0x51, 0xb7, 0xdd, 0x3e, + /*0700:*/ 0x2b, 0x8c, 0x7d, 0x56, 0x86, 0xb8, 0x3e, 0x17, 0xe8, 0x73, 0xce, 0xe8, 0x4a, 0xd9, 0xac, 0x9b, + /*0710:*/ 0x2b, 0x09, 0x3a, 0xb0, 0xb3, 0x96, 0xad, 0x98, 0xfd, 0x55, 0xdc, 0x0f, 0xf0, 0x1c, 0xaa, 0x8a, + /*0720:*/ 0xba, 0x6a, 0xfb, 0xf1, 0xac, 0x36, 0x35, 0x02, 0x42, 0x85, 0x6a, 0x81, 0x41, 0x78, 0xe1, 0x75, + /*0730:*/ 0xc2, 0x55, 0x5e, 0x15, 0x4c, 0x99, 0x22, 0xcc, 0x19, 0xc4, 0x91, 0x32, 0x80, 0x70, 0xa6, 0x7a, + /*0740:*/ 0x76, 0xa4, 0xfb, 0xfb, 0xa3, 0x94, 0x5d, 0xc7, 0x01, 0x92, 0x9a, 0xc7, 0xc1, 0x6f, 0x0e, 0x20, + /*0750:*/ 0xbc, 0x3d, 0x84, 0xf7, 0xa9, 0xe5, 0x6d, 0x72, 0x8c, 0x8a, 0x82, 0xfc, 0x53, 0x80, 0xdf, 0x34, + /*0760:*/ 0x82, 0xff, 0x69, 0xcb, 0x33, 0xbc, 0xeb, 0x6c, 0xe4, 0xbd, 0x9d, 0xc4, 0x67, 0xdc, 0x25, 0x55, + /*0770:*/ 0x51, 0xb5, 0x5f, 0xf5, 0x5c, 0xe4, 0x35, 0xfc, 0x55, 0xe5, 0x2d, 0xdf, 0x51, 0x2c, 0xcc, 0x28, + /*0780:*/ 0xaa, 0xe4, 0x7b, 0x5f, 0x87, 0x2a, 0x79, 0x48, 0xf3, 0xf6, 0xaf, 0x22, 0xf1, 0xe3, 0x62, 0x29, + /*0790:*/ 0x31, 0x65, 0x87, 0xef, 0x97, 0xa7, 0x18, 0xf6, 0xf4, 0xc7, 0x71, 0x5d, 0x53, 0xd5, 0x1b, 0x20, + /*07a0:*/ 0x4f, 0x15, 0x4b, 0x20, 0x3a, 0x5d, 0x37, 0xbb, 0x90, 0x80, 0xf3, 0xc2, 0xd0, 0x37, 0xb0, 0xe9, + /*07b0:*/ 0xad, 0xab, 0x28, 0xf4, 0x20, 0x23, 0x3d, 0x53, 0x68, 0xff, 0x00, 0x39, 0x99, 0x17, 0xde, 0xd1, + /*07c0:*/ 0x0d, 0x8d, 0xd9, 0x84, 0x03, 0xb9, 0x2b, 0x20, 0x8c, 0x98, 0x00, 0xbf, 0x59, 0x9c, 0xe8, 0xba, + /*07d0:*/ 0x29, 0x3f, 0xf8, 0x5c, 0x5b, 0xd2, 0xf3, 0x76, 0xf6, 0xac, 0x0b, 0x9e, 0x8d, 0xf4, 0x2a, 0xb2, + /*07e0:*/ 0x4e, 0xaf, 0xb9, 0xe9, 0xd1, 0xb3, 0x40, 0xa6, 0x08, 0xc5, 0x1a, 0x31, 0xb4, 0xd8, 0x05, 0x24, + /*07f0:*/ 0xdf, 0x29, 0xf0, 0xc0, 0xf6, 0x90, 0x0f, 0x0c, 0x72, 0xdb, 0x4d, 0x32, 0xbe, 0xd6, 0x72, 0x57, + /*0800:*/ 0xe3, 0xc3, 0xaa, 0x3c, 0x4b, 0x12, 0xea, 0xc8, 0xf6, 0xb8, 0x0f, 0xdf, 0xa9, 0x21, 0x8a, 0x20, + /*0810:*/ 0xfc, 0x2a, 0x14, 0xa0, 0x9d, 0xb4, 0xea, 0xbf, 0x09, 0xbe, 0xca, 0x32, 0xff, 0xd8, 0xfc, 0x91, + /*0820:*/ 0x2c, 0xf4, 0x58, 0x67, 0x79, 0x4a, 0xb7, 0x0f, 0x9d, 0x30, 0xf9, 0x8d, 0xbd, 0xaf, 0x28, 0x3b, + /*0830:*/ 0xdf, 0x8b, 0xa2, 0x83, 0xb1, 0xef, 0x3a, 0x1a, 0x8e, 0xff, 0x59, 0x1b, 0x25, 0xf7, 0x0f, 0x30, + /*0840:*/ 0x34, 0xc4, 0xbe, 0x4a, 0x41, 0xc4, 0x37, 0xf9, 0x59, 0x07, 0x42, 0x20, 0x28, 0xac, 0xca, 0x32, + /*0850:*/ 0xed, 0xd2, 0x03, 0x06, 0xa7, 0x96, 0x69, 0xb7, 0xe9, 0xde, 0xc8, 0x28, 0x06, 0xd8, 0x4d, 0xe7, + /*0860:*/ 0xab, 0xd5, 0xef, 0x00, 0x0f, 0x45, 0x50, 0xfb, 0x50, 0xbf, 0x79, 0x7d, 0xdc, 0x50, 0xa9, 0xec, + /*0870:*/ 0xbb, 0x92, 0x31, 0xce, 0x44, 0x9c, 0x06, 0x33, 0x8f, 0x39, 0x74, 0x74, 0xf4, 0x6c, 0xd6, 0xa6, + /*0880:*/ 0x8f, 0x50, 0x2b, 0x09, 0x1e, 0xeb, 0x31, 0x98, 0xc6, 0xfc, 0xfc, 0x40, 0x45, 0x45, 0x85, 0x82, + /*0890:*/ 0xa9, 0x4d, 0xd0, 0xfa, 0xd1, 0xe6, 0x0c, 0xda, 0x0a, 0x59, 0x2b, 0x7d, 0x9e, 0x93, 0x4e, 0x41, + /*08a0:*/ 0xce, 0x96, 0xc9, 0x9a, 0x7b, 0xd4, 0x83, 0xe8, 0x43, 0xdb, 0xb5, 0x6d, 0xe8, 0x1a, 0xa6, 0xe8, + /*08b0:*/ 0xf0, 0x5f, 0x7f, 0xf3, 0x40, 0x2c, 0x86, 0xbb, 0x7e, 0xfc, 0xa2, 0x64, 0xef, 0x99, 0xc8, 0xb7, + /*08c0:*/ 0x71, 0x9a, 0x4e, 0xd8, 0xe8, 0x16, 0x5d, 0x29, 0x7d, 0x76, 0x08, 0xdf, 0x0d, 0xde, 0x6b, 0x16, + /*08d0:*/ 0x29, 0xbd, 0xce, 0x46, 0x65, 0x85, 0xc8, 0xcd, 0xf4, 0x39, 0xa5, 0xa6, 0x87, 0xa8, 0x18, 0x85, + /*08e0:*/ 0x6b, 0x60, 0xd7, 0x94, 0xcd, 0x21, 0x04, 0x18, 0x73, 0x58, 0xb3, 0xd4, 0x88, 0x0a, 0xd0, 0x33, + /*08f0:*/ 0x70, 0xe7, 0x80, 0x18, 0x22, 0x48, 0xc4, 0xce, 0x53, 0xac, 0x96, 0x2d, 0xb3, 0x65, 0xd3, 0x6b, + /*0900:*/ 0x1f, 0xb9, 0xb4, 0xd9, 0x24, 0xf0, 0x13, 0x4d, 0xcc, 0x5e, 0x6d, 0xe8, 0x80, 0xce, 0xc8, 0xe4, + /*0910:*/ 0xb3, 0x56, 0x91, 0x7a, 0x27, 0xb0, 0x1a, 0x32, 0x55, 0x49, 0xa0, 0xc4, 0xa5, 0x44, 0xf0, 0xb4, + /*0920:*/ 0x8a, 0x35, 0x0b, 0x45, 0x37, 0xf5, 0x3c, 0xe4, 0x89, 0x46, 0x1a, 0x56, 0xea, 0xc0, 0xd3, 0x8e, + /*0930:*/ 0x65, 0x90, 0x7b, 0x8d, 0x32, 0x65, 0x51, 0x89, 0x8d, 0x96, 0xab, 0x98, 0xb1, 0xd6, 0x71, 0x6e, + /*0940:*/ 0x46, 0xf2, 0x33, 0xe9, 0x37, 0x14, 0xf7, 0x11, 0xd4, 0xa8, 0xbf, 0x2a, 0x22, 0xe9, 0xc7, 0xbd, + /*0950:*/ 0xad, 0x08, 0x95, 0x73, 0xb4, 0x5e, 0x1f, 0x92, 0xfa, 0x9a, 0x1a, 0xe9, 0x77, 0x22, 0xce, 0xa6, + /*0960:*/ 0xd2, 0xc5, 0xa3, 0xf9, 0x41, 0xd8, 0x88, 0x0b, 0xe2, 0x28, 0xf1, 0x7c, 0xda, 0x84, 0x71, 0xd1, + /*0970:*/ 0x00, 0x30, 0x6d, 0x6e, 0x6c, 0xba, 0x38, 0xcd, 0x51, 0x20, 0xe2, 0x85, 0x30, 0xc1, 0x4f, 0xba, + /*0980:*/ 0x8a, 0x89, 0xf2, 0x50, 0x43, 0xf6, 0x1b, 0x4a, 0xa7, 0x2e, 0x8b, 0x67, 0xc4, 0x6d, 0x32, 0x9a, + /*0990:*/ 0xba, 0xfb, 0xa7, 0xb2, 0x3f, 0xa3, 0x2d, 0xc6, 0x7c, 0x64, 0x94, 0xde, 0xcf, 0x27, 0x86, 0x90, + /*09a0:*/ 0xc7, 0xd5, 0xa3, 0x36, 0xa6, 0x10, 0xcb, 0xcd, 0x58, 0x53, 0x0b, 0xa6, 0xb4, 0x46, 0x2a, 0xf7, + /*09b0:*/ 0x28, 0x63, 0x6a, 0x4f, 0x0e, 0xd6, 0x48, 0x3f, 0x93, 0x09, 0x12, 0xb6, 0xd7, 0x4f, 0x59, 0x96, + /*09c0:*/ 0xf9, 0xa7, 0x31, 0x0f, 0x59, 0xe1, 0x27, 0xf1, 0x66, 0x99, 0xe7, 0xb4, 0x04, 0xdb, 0xb0, 0xa0, + /*09d0:*/ 0x41, 0x1c, 0x98, 0x4c, 0xed, 0x04, 0x19, 0x06, 0xd0, 0x4a, 0x94, 0xef, 0x17, 0xf0, 0x65, 0x5b, + /*09e0:*/ 0x47, 0x2e, 0x64, 0x59, 0xb4, 0x45, 0x26, 0x37, 0x21, 0x5a, 0x8a, 0x11, 0xda, 0x41, 0x71, 0x87, + /*09f0:*/ 0x43, 0x3d, 0xe7, 0xb9, 0xaf, 0x7e, 0x81, 0x81, 0xc9, 0xd1, 0xf1, 0x0f, 0x62, 0xcc, 0x35, 0xef, + /*0a00:*/ 0x8d, 0xee, 0x9d, 0x7a, 0x57, 0xa0, 0xad, 0x9b, 0x40, 0xc8, 0x28, 0xbf, 0xa8, 0xf4, 0xf5, 0x37, + /*0a10:*/ 0x60, 0xdb, 0xdb, 0xc8, 0xe5, 0xd1, 0x7b, 0xbc, 0x53, 0x43, 0x8b, 0xf8, 0x10, 0xbe, 0x9d, 0x56, + /*0a20:*/ 0x14, 0x75, 0xcc, 0x66, 0x5b, 0x8c, 0x2b, 0x33, 0xaf, 0xa6, 0xe4, 0x08, 0x29, 0xf6, 0x50, 0x7a, + /*0a30:*/ 0x0d, 0x11, 0xa1, 0xea, 0x30, 0x49, 0x98, 0x8b, 0xa6, 0x4d, 0x29, 0x73, 0x7d, 0xfa, 0x87, 0xc9, + /*0a40:*/ 0x6a, 0x13, 0xfa, 0x75, 0xa0, 0x5a, 0x89, 0xc0, 0xb4, 0x64, 0x96, 0x79, 0x42, 0x6f, 0x30, 0xef, + /*0a50:*/ 0x13, 0x1b, 0xe7, 0x44, 0xec, 0x55, 0xb1, 0x77, 0xa6, 0xd9, 0x63, 0x09, 0xc3, 0x29, 0x95, 0x5f, + /*0a60:*/ 0xee, 0x92, 0xb6, 0x6e, 0xb4, 0xfd, 0xf2, 0x48, 0x35, 0x13, 0x2c, 0xb7, 0x34, 0xd8, 0x2d, 0x6e, + /*0a70:*/ 0xce, 0x21, 0xda, 0xe8, 0x71, 0x86, 0x3a, 0x34, 0x80, 0x5d, 0x59, 0xd5, 0x32, 0x99, 0x95, 0x52, + /*0a80:*/ 0x83, 0xd5, 0x7b, 0xd5, 0xa7, 0xa3, 0x52, 0x48, 0x92, 0xdc, 0x1f, 0x34, 0x84, 0x72, 0x08, 0x5a, + /*0a90:*/ 0xce, 0xb7, 0x02, 0xea, 0xd1, 0x75, 0x39, 0xe2, 0xa5, 0xae, 0x72, 0x56, 0x2b, 0xcc, 0xd1, 0xc8, + /*0aa0:*/ 0x95, 0x54, 0x34, 0x35, 0x94, 0x80, 0xdb, 0x62, 0xbf, 0x1f, 0xe0, 0xbc, 0x0f, 0x43, 0xce, 0xce, + /*0ab0:*/ 0x64, 0xfe, 0xbe, 0x7d, 0xe1, 0xc6, 0x81, 0xfe, 0xa6, 0x2b, 0xd7, 0x02, 0x10, 0x83, 0x03, 0xb6, + /*0ac0:*/ 0x4d, 0x59, 0x5f, 0x12, 0x39, 0x90, 0x2d, 0x0c, 0xd8, 0x29, 0xbc, 0xae, 0xed, 0x41, 0x66, 0x37, + /*0ad0:*/ 0x2c, 0x90, 0xf7, 0xba, 0xf8, 0x09, 0x20, 0x3f, 0x38, 0xd4, 0x7a, 0x24, 0x7b, 0x1a, 0x8b, 0xc6, + /*0ae0:*/ 0x69, 0x2b, 0x4d, 0x15, 0xb3, 0xd7, 0x79, 0x5f, 0x87, 0xe5, 0x48, 0x5d, 0x2a, 0x89, 0x85, 0xd7, + /*0af0:*/ 0x96, 0xf9, 0x39, 0x91, 0xdb, 0x3d, 0x9e, 0x5b, 0x39, 0xe8, 0x3a, 0x29, 0x4c, 0xd1, 0x22, 0xce, + /*0b00:*/ 0x3f, 0xa4, 0xf3, 0xad, 0x28, 0xc2, 0xee, 0xa3, 0x27, 0x19, 0x0a, 0x86, 0x13, 0xeb, 0xcc, 0xc8, + /*0b10:*/ 0x69, 0xbf, 0x46, 0xf7, 0xe4, 0x6d, 0xf8, 0x31, 0xbb, 0xd7, 0x45, 0xfd, 0x0a, 0x68, 0xee, 0x2b, + /*0b20:*/ 0xb5, 0x71, 0xb2, 0xad, 0x5b, 0x80, 0x5e, 0x69, 0x58, 0x11, 0x6a, 0xea, 0x30, 0x88, 0x33, 0xec, + /*0b30:*/ 0xa9, 0xed, 0x2f, 0x8c, 0x95, 0x30, 0xec, 0x4a, 0xc1, 0x47, 0xbd, 0xd0, 0x60, 0x8c, 0x23, 0x0f, + /*0b40:*/ 0x9e, 0x11, 0x62, 0xc6, 0xc2, 0xb4, 0xc6, 0x43, 0x4c, 0xa6, 0x66, 0xe8, 0xbc, 0xed, 0x57, 0xfb, + /*0b50:*/ 0x6d, 0x73, 0x80, 0xd3, 0x5f, 0xe1, 0x90, 0x27, 0xd5, 0x32, 0x20, 0x9d, 0x1f, 0x72, 0x5d, 0xad, + /*0b60:*/ 0xdc, 0xb3, 0x3d, 0x86, 0x75, 0x95, 0x1b, 0x34, 0x52, 0x46, 0x66, 0x58, 0xf6, 0x9a, 0xd7, 0x06, + /*0b70:*/ 0xf0, 0x40, 0x64, 0x55, 0x74, 0xa5, 0x70, 0x56, 0x17, 0x71, 0xe7, 0xee, 0xf8, 0x18, 0x77, 0xdd, + /*0b80:*/ 0x23, 0x78, 0x01, 0xde, 0x3d, 0x5b, 0x97, 0xd1, 0x35, 0x00, 0x94, 0xd9, 0x12, 0xe3, 0x7b, 0x66, + /*0b90:*/ 0xac, 0x58, 0xdb, 0xe8, 0xb0, 0x41, 0x83, 0x3e, 0x7c, 0xdc, 0x04, 0x41, 0x2f, 0xf5, 0x89, 0xce, + /*0ba0:*/ 0xbd, 0xf6, 0xa9, 0x95, 0x20, 0x62, 0x66, 0x5d, 0x6a, 0x1d, 0x08, 0xca, 0x44, 0x80, 0x7e, 0xb0, + /*0bb0:*/ 0xfd, 0x45, 0x82, 0x92, 0x80, 0x52, 0x99, 0x90, 0x16, 0x59, 0xd1, 0x29, 0xa1, 0xf2, 0x56, 0x84, + /*0bc0:*/ 0xa4, 0x5d, 0xdd, 0x82, 0x27, 0x80, 0x17, 0x84, 0x1f, 0x6e, 0x71, 0xb0, 0x7c, 0xb8, 0x39, 0xf6, + /*0bd0:*/ 0x9e, 0x55, 0xe6, 0x85, 0xa6, 0x20, 0x56, 0x6b, 0x8e, 0x4e, 0xd5, 0xd1, 0x93, 0xa3, 0xf8, 0x01, + /*0be0:*/ 0xc5, 0x04, 0x73, 0x76, 0xdd, 0x79, 0x03, 0x50, 0xc3, 0x6f, 0x89, 0x53, 0x97, 0x3e, 0xf9, 0xa4, + /*0bf0:*/ 0xfa, 0xf8, 0xd6, 0x43, 0xcd, 0x98, 0x0d, 0x69, 0xf0, 0xff, 0xa3, 0xd6, 0xb9, 0xa6, 0x0a, 0x59, + /*0c00:*/ 0x87, 0x45, 0x5e, 0x1c, 0x0d, 0x5c, 0xc3, 0x30, 0x1c, 0x69, 0xd0, 0x26, 0xc4, 0x64, 0x9f, 0xd9, + /*0c10:*/ 0xd3, 0xad, 0xbe, 0x19, 0xfd, 0x77, 0x71, 0xdb, 0xa4, 0x60, 0x93, 0x6c, 0x7e, 0xc5, 0x11, 0x41, + /*0c20:*/ 0xab, 0x40, 0xa7, 0x57, 0x70, 0x4b, 0xac, 0x56, 0x21, 0x3e, 0xb7, 0xc3, 0x1e, 0x25, 0xf9, 0xab, + /*0c30:*/ 0x86, 0x8b, 0x56, 0xf1, 0x62, 0x37, 0x24, 0xe3, 0x38, 0xb3, 0x51, 0xa8, 0xcb, 0xaa, 0x09, 0xe8, + /*0c40:*/ 0x81, 0xa2, 0x9e, 0xc6, 0x4e, 0xbe, 0x7b, 0xfd, 0x96, 0x13, 0xb5, 0x2d, 0x7c, 0xf1, 0xa8, 0xf6, + /*0c50:*/ 0x3d, 0x01, 0x2d, 0x8a, 0x8d, 0xf7, 0x8c, 0x0e, 0x6a, 0xf0, 0x00, 0x32, 0xe0, 0x8a, 0xe8, 0xa6, + /*0c60:*/ 0x7a, 0x78, 0xad, 0xcb, 0xef, 0xc8, 0xfe, 0x06, 0x74, 0x04, 0x00, 0xf5, 0xc7, 0xf5, 0x00, 0xca, + /*0c70:*/ 0x9d, 0x50, 0x57, 0x95, 0x29, 0x13, 0x34, 0xe0, 0xa6, 0xad, 0x81, 0x09, 0x9f, 0x76, 0xc1, 0xde, + /*0c80:*/ 0x1b, 0x17, 0xd4, 0x9d, 0xa0, 0x68, 0x1e, 0x6d, 0xd8, 0x3a, 0xe3, 0xa8, 0x9b, 0xfd, 0x55, 0x37, + /*0c90:*/ 0xb9, 0xfb, 0x04, 0x17, 0x8c, 0x91, 0xcc, 0x51, 0xdf, 0x96, 0x51, 0x8d, 0x26, 0x1c, 0x38, 0x0c, + /*0ca0:*/ 0x74, 0x42, 0x6a, 0x48, 0xdb, 0xb0, 0xed, 0xca, 0x95, 0xa5, 0x07, 0x76, 0x39, 0xaa, 0x9d, 0xc1, + /*0cb0:*/ 0xf0, 0xe3, 0x71, 0xce, 0x8c, 0x09, 0x88, 0x63, 0x15, 0x6d, 0x15, 0x3a, 0xdb, 0xaf, 0xad, 0x8f, + /*0cc0:*/ 0x63, 0x64, 0x37, 0x65, 0x63, 0x19, 0x7f, 0x63, 0x8a, 0xb6, 0x21, 0xc9, 0x0b, 0xd3, 0x78, 0x0d, + /*0cd0:*/ 0x21, 0x08, 0x6e, 0x66, 0xf7, 0xd8, 0xfa, 0xdf, 0x1e, 0x67, 0xae, 0xa3, 0x0b, 0xa8, 0xfb, 0xab, + /*0ce0:*/ 0xa6, 0xcb, 0x28, 0x74, 0x47, 0x8e, 0x76, 0xb7, 0xf5, 0xe5, 0x8b, 0xe9, 0x90, 0x26, 0x78, 0xe8, + /*0cf0:*/ 0x88, 0x1a, 0x9b, 0xd6, 0x07, 0xe1, 0x4d, 0xe9, 0xc6, 0xc2, 0x3c, 0x42, 0xa5, 0x7c, 0x03, 0xb1, + /*0d00:*/ 0x40, 0xd8, 0xec, 0xdf, 0x63, 0x90, 0x38, 0x13, 0x17, 0x9a, 0x34, 0x93, 0x93, 0x7d, 0x17, 0x82, + /*0d10:*/ 0xac, 0x78, 0x36, 0x21, 0x8b, 0x13, 0x33, 0xe0, 0xb7, 0xc7, 0xf3, 0x35, 0xff, 0xd7, 0xf5, 0x18, + /*0d20:*/ 0xdc, 0x8f, 0xe9, 0xd3, 0x63, 0xf4, 0x69, 0x5a, 0xc2, 0xf7, 0x70, 0x1d, 0xd6, 0x2e, 0x24, 0x31, + /*0d30:*/ 0x03, 0x3f, 0x71, 0xc5, 0x1b, 0xa1, 0x0a, 0xa0, 0xaa, 0xfb, 0xd3, 0xc4, 0x2d, 0x0c, 0x5d, 0xb4, + /*0d40:*/ 0xf4, 0x69, 0xa2, 0x82, 0xe5, 0xd7, 0x2b, 0x2c, 0xf6, 0x08, 0x1d, 0xb2, 0x14, 0x98, 0x66, 0xc1, + /*0d50:*/ 0x15, 0x0d, 0xc9, 0xcc, 0x1d, 0xc2, 0x54, 0x9b, 0x80, 0x27, 0xec, 0x27, 0x70, 0x4b, 0x5c, 0xee, + /*0d60:*/ 0xc0, 0xd3, 0x3c, 0x68, 0x50, 0x00, 0xf5, 0x80, 0x56, 0x46, 0xc3, 0x30, 0x97, 0xca, 0x5e, 0x72, + /*0d70:*/ 0x50, 0x1d, 0xb2, 0x82, 0x22, 0x73, 0x6f, 0x01, 0xf9, 0xcc, 0x98, 0xf6, 0xc5, 0xdc, 0x75, 0x2e, + /*0d80:*/ 0xa6, 0x96, 0x75, 0x75, 0xf1, 0x61, 0x58, 0x2c, 0x9f, 0x7e, 0x5f, 0xba, 0x7b, 0xe3, 0xfa, 0x47, + /*0d90:*/ 0xf7, 0x8e, 0xc1, 0x0f, 0xeb, 0xf2, 0x7a, 0x4e, 0x35, 0x09, 0x60, 0xf0, 0x38, 0xeb, 0x57, 0x5e, + /*0da0:*/ 0xa3, 0x3f, 0x77, 0x3f, 0xc4, 0xcc, 0xf4, 0xf8, 0xc5, 0x33, 0x19, 0x8e, 0xc8, 0x4a, 0xd1, 0xe5, + /*0db0:*/ 0x17, 0x70, 0xdb, 0xf7, 0x7d, 0xbc, 0x7d, 0xe0, 0x2b, 0x7e, 0x10, 0x66, 0x51, 0x47, 0x64, 0xf9, + /*0dc0:*/ 0x62, 0xcf, 0x37, 0xbb, 0x92, 0xf5, 0xb3, 0xdf, 0x11, 0x37, 0x93, 0x81, 0x6f, 0xd8, 0xb4, 0x74, + /*0dd0:*/ 0x09, 0xcb, 0x36, 0x9e, 0x44, 0xe5, 0xce, 0x3e, 0xfb, 0x3b, 0xaa, 0x1b, 0xfc, 0x46, 0x7b, 0xe6, + /*0de0:*/ 0xb0, 0x86, 0x46, 0xbf, 0xf5, 0xc2, 0xa2, 0xdc, 0x5c, 0x91, 0xa7, 0x9f, 0x1b, 0xdd, 0x9f, 0x58, + /*0df0:*/ 0x12, 0x44, 0xfe, 0x55, 0x85, 0xc3, 0xfc, 0x12, 0x13, 0x3e, 0xf3, 0x7b, 0xd7, 0x47, 0x4d, 0x26, + /*0e00:*/ 0x93, 0x32, 0x45, 0x16, 0xd0, 0x03, 0x66, 0x23, 0xe2, 0x4f, 0x92, 0x21, 0x3c, 0x18, 0x9f, 0x2e, + /*0e10:*/ 0xdd, 0xec, 0x8f, 0xeb, 0x3b, 0xef, 0x26, 0xef, 0x35, 0x98, 0xf3, 0x26, 0x90, 0x3d, 0x01, 0x46, + /*0e20:*/ 0xc4, 0x3d, 0x49, 0x19, 0xc2, 0xc7, 0xc5, 0x57, 0xf1, 0xd4, 0x1d, 0x63, 0xb3, 0xe3, 0xec, 0x29, + /*0e30:*/ 0xb7, 0x8c, 0xa6, 0xb7, 0xae, 0x63, 0x79, 0x5e, 0xc8, 0x02, 0xde, 0x38, 0x4d, 0xee, 0x6e, 0x7e, + /*0e40:*/ 0x0f, 0x70, 0xe2, 0xc0, 0x23, 0x83, 0xf6, 0xd7, 0x9e, 0x53, 0xd5, 0x44, 0x96, 0xb1, 0xfe, 0x0c, + /*0e50:*/ 0xbb, 0x00, 0x6a, 0xb3, 0xab, 0xeb, 0x31, 0xae, 0x6e, 0x63, 0xed, 0x91, 0x16, 0x44, 0x43, 0xd4, + /*0e60:*/ 0x2d, 0xf3, 0x7a, 0x95, 0x5c, 0x93, 0xa9, 0x44, 0x91, 0x7c, 0xb0, 0xc7, 0xdd, 0x92, 0x1c, 0xde, + /*0e70:*/ 0xa6, 0xc3, 0xf1, 0x58, 0x4d, 0x25, 0xcd, 0x88, 0x1a, 0x54, 0xbe, 0x50, 0x2b, 0x9a, 0xfb, 0xbc, + /*0e80:*/ 0xd6, 0x4d, 0x59, 0x2d, 0xcd, 0x76, 0x16, 0x3c, 0x1c, 0xfd, 0x7a, 0xae, 0x41, 0xae, 0xfa, 0x95, + /*0e90:*/ 0xd6, 0xb8, 0x8b, 0xac, 0xa9, 0xee, 0x93, 0x2a, 0x55, 0x21, 0x4b, 0x6c, 0x1a, 0x28, 0x2f, 0x8d, + /*0ea0:*/ 0x9c, 0x42, 0xd0, 0xb0, 0x21, 0x90, 0x0a, 0xce, 0xa5, 0x55, 0x6d, 0x52, 0x8e, 0xb7, 0x98, 0xad, + /*0eb0:*/ 0xd4, 0xdf, 0x48, 0x48, 0x71, 0x7a, 0x66, 0x4a, 0xb2, 0x45, 0x17, 0xab, 0x5b, 0x91, 0x05, 0x7f, + /*0ec0:*/ 0x72, 0xf3, 0xd3, 0x89, 0x1f, 0x81, 0x1f, 0xd4, 0xe8, 0x38, 0x5d, 0x68, 0x24, 0xca, 0x5e, 0xe1, + /*0ed0:*/ 0xd4, 0x9e, 0xac, 0x17, 0x09, 0x0e, 0x88, 0x70, 0x7a, 0xae, 0xc1, 0xc8, 0x94, 0xf5, 0x6b, 0x21, + /*0ee0:*/ 0x69, 0xc5, 0xd2, 0xb6, 0x0b, 0xc7, 0x2e, 0x27, 0x0b, 0xf2, 0xfd, 0x74, 0x8b, 0xd6, 0xd9, 0x7d, + /*0ef0:*/ 0xcd, 0x58, 0x38, 0x20, 0xc8, 0x68, 0x48, 0x08, 0xbd, 0x18, 0x69, 0x0a, 0x4f, 0x04, 0x4e, 0xcf, + /*0f00:*/ 0x43, 0x7c, 0x6f, 0x11, 0x86, 0x5b, 0xbb, 0x5b, 0x25, 0x76, 0x77, 0xf0, 0x7b, 0xbd, 0xc7, 0xd2, + /*0f10:*/ 0x2c, 0x47, 0xf3, 0x13, 0x3c, 0xfd, 0xbc, 0xa3, 0x80, 0x22, 0xcf, 0x18, 0x92, 0x36, 0x09, 0x9a, + /*0f20:*/ 0x96, 0x72, 0x05, 0xb3, 0x67, 0xa2, 0x2a, 0xee, 0x1c, 0x7c, 0x84, 0x37, 0x1c, 0x0d, 0xaa, 0x02, + /*0f30:*/ 0xcd, 0xf6, 0xc6, 0x65, 0x14, 0x2d, 0xcd, 0x18, 0x42, 0xc2, 0x3f, 0xee, 0x09, 0xcd, 0x57, 0xf9, + /*0f40:*/ 0xdd, 0xa9, 0xd4, 0xf1, 0xb3, 0x97, 0x9f, 0xf7, 0xb7, 0x4a, 0x39, 0x9c, 0xb5, 0x64, 0xd2, 0x66, + /*0f50:*/ 0x58, 0x78, 0x69, 0x65, 0xfa, 0x21, 0xfd, 0x1e, 0x0f, 0xe2, 0x37, 0x57, 0xf9, 0x8d, 0x56, 0x34, + /*0f60:*/ 0x76, 0xb4, 0x07, 0xa4, 0x9b, 0xf4, 0x27, 0xf0, 0x26, 0x95, 0x23, 0xf5, 0x6a, 0x35, 0x99, 0x52, + /*0f70:*/ 0xac, 0x40, 0x51, 0xd2, 0xf2, 0x2b, 0x22, 0x54, 0xff, 0x45, 0xda, 0x84, 0x1e, 0x72, 0x53, 0xa3, + /*0f80:*/ 0xb2, 0x9e, 0xc0, 0x6e, 0x68, 0x62, 0xa1, 0x8a, 0x74, 0xa9, 0x90, 0xfa, 0x19, 0xd0, 0x25, 0x13, + /*0f90:*/ 0xd0, 0x3b, 0x59, 0xcd, 0x85, 0x5e, 0xc4, 0x4b, 0x7b, 0x3c, 0xd4, 0xc1, 0x91, 0xa9, 0xc0, 0xce, + /*0fa0:*/ 0x5a, 0xa6, 0xc0, 0x84, 0x0c, 0xea, 0xd5, 0xeb, 0xad, 0x6c, 0x81, 0x12, 0xb4, 0x3d, 0xac, 0x20, + /*0fb0:*/ 0xcc, 0x4c, 0x82, 0xa0, 0xc3, 0x77, 0x01, 0x20, 0xeb, 0xc0, 0xd5, 0x86, 0xa0, 0x79, 0x1f, 0x75, + /*0fc0:*/ 0x27, 0xf6, 0xd4, 0xae, 0x45, 0x0f, 0x42, 0x36, 0x7f, 0x96, 0x8a, 0x9a, 0x6d, 0x65, 0xa7, 0xa3, + /*0fd0:*/ 0x8b, 0x6a, 0xea, 0xb6, 0x72, 0xb8, 0x37, 0x3f, 0x3f, 0x64, 0x64, 0x84, 0xa3, 0x68, 0x44, 0x7a, + /*0fe0:*/ 0x10, 0xe6, 0x9c, 0x54, 0x54, 0x6b, 0xc9, 0x83, 0x88, 0x49, 0x71, 0x25, 0x7a, 0x01, 0x36, 0x15, + /*0ff0:*/ 0x8e, 0x84, 0x8c, 0x41, 0x8a, 0x07, 0xc3, 0x9a, 0x87, 0x16, 0x52, 0xe8, 0xe7, 0x49, 0xd3, 0xc8, + /*1000:*/ 0x8c, 0x4a, 0xfe, 0xd9, 0xd2, 0x8c, 0xac, 0x45, 0xf2, 0xc5, 0x57, 0x73, 0xf7, 0x47, 0x1c, 0x1d, + /*1010:*/ 0x33, 0x2a, 0x16, 0x87, 0xf2, 0xfc, 0xec, 0xcd, 0x41, 0x8f, 0x5e, 0xa4, 0x40, 0x75, 0x75, 0x33, + /*1020:*/ 0xcd, 0x40, 0x13, 0x77, 0xa6, 0xb7, 0x3a, 0xf4, 0xd5, 0x5c, 0x3d, 0x9e, 0xdc, 0xd2, 0x31, 0x4f, + /*1030:*/ 0x6a, 0x4f, 0xae, 0x9b, 0xa4, 0xe7, 0xb6, 0xb9, 0x3c, 0x87, 0x02, 0x5f, 0x48, 0xbe, 0x87, 0xa7, + /*1040:*/ 0x92, 0x52, 0x8f, 0x72, 0x15, 0xbe, 0xce, 0x65, 0xfe, 0x1d, 0x9e, 0xf8, 0x9f, 0xc3, 0x8e, 0x57, + /*1050:*/ 0xbf, 0xa7, 0xe6, 0x8f, 0xb1, 0x50, 0x8c, 0x19, 0x42, 0x8a, 0x4b, 0x6f, 0x4f, 0xcf, 0xe6, 0xd5, + /*1060:*/ 0x0d, 0xa3, 0xe7, 0x02, 0x2a, 0x35, 0x17, 0xc5, 0x74, 0xab, 0xa0, 0x6d, 0xee, 0x58, 0x35, 0x10, + /*1070:*/ 0xc6, 0xb6, 0xf1, 0x9b, 0xe2, 0x1e, 0xfc, 0xb8, 0x95, 0xcb, 0xbb, 0xb2, 0x0a, 0xc2, 0x1c, 0x67, + /*1080:*/ 0xa3, 0x1d, 0x62, 0x44, 0x96, 0xdb, 0x36, 0xf0, 0xfd, 0xd2, 0x48, 0x98, 0x92, 0xdc, 0xec, 0xf4, + /*1090:*/ 0x44, 0x81, 0xf8, 0x3a, 0x6f, 0x1e, 0x24, 0x14, 0x26, 0x0c, 0x15, 0x74, 0xf1, 0x45, 0x8d, 0xfb, + /*10a0:*/ 0xee, 0x32, 0x61, 0x72, 0x28, 0x41, 0xc4, 0x12, 0xc0, 0x37, 0xca, 0x7f, 0x70, 0x86, 0xce, 0xf5, + /*10b0:*/ 0x34, 0xcf, 0xc6, 0x99, 0x5a, 0x74, 0xc9, 0xad, 0xce, 0x7d, 0x35, 0x80, 0x00, 0x47, 0xbf, 0xdd, + /*10c0:*/ 0x49, 0x42, 0xde, 0x17, 0xf1, 0xf2, 0x77, 0x1f, 0x3e, 0x47, 0x7e, 0x18, 0x2a, 0xb5, 0xae, 0x43, + /*10d0:*/ 0x46, 0x7d, 0xa9, 0x10, 0xfa, 0x0a, 0xca, 0x54, 0xf6, 0x03, 0xe0, 0xa2, 0xd3, 0xe5, 0x2b, 0xca, + /*10e0:*/ 0xe5, 0x3b, 0x46, 0xb6, 0xe2, 0x0e, 0x36, 0x71, 0x68, 0xaf, 0x51, 0xc3, 0xd9, 0xeb, 0x64, 0x60, + /*10f0:*/ 0x78, 0x2c, 0xfc, 0x5f, 0x73, 0x1f, 0xa0, 0x8a, 0xa5, 0xe5, 0xc3, 0x90, 0x3e, 0xc8, 0x83, 0x56, + /*1100:*/ 0xda, 0x17, 0xee, 0x23, 0x3b, 0x7a, 0x6d, 0xfe, 0xef, 0xa9, 0xe8, 0x92, 0xc5, 0xa5, 0xd7, 0x5e, + /*1110:*/ 0x11, 0x18, 0xd8, 0xf5, 0x1c, 0xd8, 0x1d, 0x9b, 0x0b, 0x79, 0x91, 0xa3, 0x02, 0x7d, 0xa3, 0x0f, + /*1120:*/ 0xc2, 0xcc, 0xb0, 0x0d, 0xfc, 0x7e, 0xbd, 0x1b, 0xee, 0x42, 0x90, 0x65, 0x20, 0xd8, 0xad, 0x41, + /*1130:*/ 0x6b, 0xba, 0xb0, 0xeb, 0xaa, 0xa4, 0x1b, 0x80, 0x97, 0xa7, 0x88, 0x2e, 0xdc, 0xfd, 0x55, 0x65, + /*1140:*/ 0xe9, 0xf1, 0xb6, 0x9a, 0x27, 0xca, 0x23, 0x30, 0x46, 0x3e, 0x6f, 0x0c, 0x57, 0xc3, 0xd7, 0xca, + /*1150:*/ 0xe3, 0x99, 0xe6, 0x09, 0xa1, 0x5c, 0x72, 0xd8, 0x65, 0x08, 0x21, 0xfe, 0xb0, 0x48, 0xc9, 0xf9, + /*1160:*/ 0x42, 0xad, 0xda, 0x11, 0x70, 0x56, 0x0a, 0xa5, 0x3b, 0xd9, 0xee, 0xc7, 0x30, 0x9b, 0x23, 0xd9, + /*1170:*/ 0xa0, 0x82, 0x8d, 0xe0, 0x77, 0x67, 0x4a, 0x85, 0x8b, 0x52, 0x9a, 0x16, 0xf1, 0x6a, 0x74, 0x96, + /*1180:*/ 0xf7, 0xfe, 0xa6, 0x83, 0x72, 0xb6, 0x82, 0x78, 0x44, 0xd7, 0x51, 0x70, 0x92, 0x8e, 0x64, 0xc3, + /*1190:*/ 0x8c, 0x92, 0x18, 0xc9, 0x7a, 0x4d, 0x7e, 0xd1, 0x11, 0x53, 0xa6, 0x14, 0xed, 0x9c, 0x04, 0x01, + /*11a0:*/ 0xdb, 0x9f, 0xfd, 0x38, 0xc7, 0xf0, 0xb0, 0x70, 0x96, 0x7a, 0x67, 0xdc, 0x19, 0xeb, 0xaf, 0xf9, + /*11b0:*/ 0x25, 0x1f, 0xbc, 0xc0, 0xa4, 0xa8, 0x05, 0x7b, 0x9e, 0xd5, 0xe8, 0x1c, 0xe3, 0x71, 0xab, 0x92, + /*11c0:*/ 0xc9, 0xb4, 0xac, 0xb0, 0xe0, 0xf1, 0x59, 0x0b, 0x58, 0x3e, 0xca, 0x9d, 0x3e, 0xd0, 0xae, 0xeb, + /*11d0:*/ 0x51, 0xf0, 0x3c, 0xc0, 0xb9, 0x0b, 0xda, 0xba, 0x6b, 0xd8, 0x1f, 0x97, 0x68, 0x75, 0xbc, 0x88, + /*11e0:*/ 0x44, 0x5c, 0x37, 0xc7, 0x0c, 0xd7, 0xf1, 0x1d, 0x03, 0xe8, 0x0e, 0xa6, 0xae, 0xd0, 0x66, 0xa4, + /*11f0:*/ 0xd1, 0xf5, 0x52, 0xc8, 0x7b, 0x1e, 0xfe, 0x4b, 0x5d, 0xdd, 0xca, 0xad, 0x21, 0xde, 0x28, 0xf4, + /*1200:*/ 0x98, 0x98, 0x9c, 0xd2, 0x62, 0xd7, 0x00, 0xde, 0x6a, 0xf1, 0xa1, 0xe4, 0x1c, 0xaf, 0x1f, 0x9b, + /*1210:*/ 0x90, 0x8a, 0x40, 0x9d, 0x78, 0x64, 0x75, 0x60, 0xaa, 0xc7, 0xce, 0x63, 0x65, 0x1e, 0x65, 0x74, + /*1220:*/ 0x9b, 0x37, 0xb2, 0xb7, 0x54, 0xc5, 0x6d, 0xce, 0x1d, 0x08, 0x3a, 0x01, 0x07, 0xc1, 0x80, 0x21, + /*1230:*/ 0x1e, 0x25, 0xbe, 0x97, 0xbb, 0x53, 0x3f, 0x8a, 0xcf, 0x1c, 0xfe, 0x7f, 0x93, 0xfb, 0x0c, 0x5a, + /*1240:*/ 0x52, 0xf2, 0x63, 0xba, 0xd0, 0xa5, 0x5b, 0xd8, 0x98, 0xb8, 0x95, 0xd4, 0xc8, 0xb1, 0x04, 0x99, + /*1250:*/ 0x83, 0xb4, 0xcb, 0xe4, 0x3a, 0xea, 0x02, 0x5e, 0x88, 0x6e, 0xfd, 0xf8, 0x79, 0x5f, 0x03, 0x99, + /*1260:*/ 0x56, 0xea, 0x25, 0xc8, 0x08, 0x1b, 0x6a, 0x8d, 0x28, 0xe6, 0x08, 0x47, 0x67, 0xf5, 0xc7, 0x52, + /*1270:*/ 0x60, 0x08, 0x42, 0x5f, 0x58, 0x01, 0x0a, 0xf2, 0xa3, 0xa3, 0x1e, 0x91, 0x17, 0x5d, 0xe8, 0xe4, + /*1280:*/ 0x14, 0x10, 0x67, 0xc3, 0x1c, 0x3e, 0x71, 0x23, 0x45, 0xf3, 0xc9, 0x73, 0xc9, 0xc5, 0x94, 0x67, + /*1290:*/ 0x51, 0x22, 0xa5, 0xf9, 0x45, 0xce, 0x35, 0x20, 0xf7, 0xf7, 0x1a, 0xea, 0x52, 0x25, 0x17, 0xb1, + /*12a0:*/ 0xec, 0xc5, 0x4e, 0xe9, 0x03, 0x8f, 0xc2, 0x0c, 0xa3, 0x00, 0xd9, 0xe8, 0xe8, 0xb2, 0xbe, 0xaf, + /*12b0:*/ 0xcb, 0xda, 0xf8, 0xbe, 0x2d, 0x2e, 0x92, 0x23, 0x3b, 0x9b, 0x27, 0x65, 0x7f, 0x03, 0xc7, 0x8e, + /*12c0:*/ 0x9c, 0x86, 0x66, 0xf4, 0x67, 0xb4, 0x7b, 0x7d, 0x44, 0x73, 0x8e, 0x7e, 0x32, 0x87, 0x58, 0xa9, + /*12d0:*/ 0xcf, 0x92, 0xc8, 0x07, 0x41, 0xc5, 0x41, 0x17, 0x34, 0xed, 0x3b, 0xd6, 0x30, 0xca, 0x66, 0x50, + /*12e0:*/ 0x4a, 0x1e, 0x68, 0xcc, 0x91, 0xe2, 0x78, 0x38, 0xfc, 0x04, 0x72, 0xfb, 0xbb, 0x63, 0x4f, 0x30, + /*12f0:*/ 0xc2, 0xbb, 0x4a, 0xd5, 0xc9, 0x0e, 0x53, 0xc7, 0x5c, 0x83, 0x1d, 0xc0, 0x42, 0x22, 0xfa, 0xba, + /*1300:*/ 0x31, 0xfa, 0x85, 0x75, 0x8e, 0x7b, 0x1b, 0x63, 0x2a, 0x13, 0x2a, 0x33, 0x01, 0x86, 0xc0, 0xdd, + /*1310:*/ 0xfd, 0x14, 0xc5, 0x84, 0x9b, 0xcc, 0xa5, 0x89, 0x31, 0x27, 0x6e, 0x3b, 0xc6, 0xb0, 0xf2, 0x23, + /*1320:*/ 0x61, 0x52, 0x5b, 0x3a, 0xf2, 0x63, 0x3a, 0xc2, 0x6e, 0xaf, 0x98, 0x97, 0x5c, 0xbc, 0xd4, 0xf3, + /*1330:*/ 0xd4, 0x98, 0x25, 0x73, 0xc6, 0xbb, 0x64, 0x85, 0x88, 0x95, 0x0d, 0xcb, 0xaa, 0xfd, 0x57, 0x9c, + /*1340:*/ 0xa8, 0x4f, 0x32, 0xa4, 0xce, 0xf0, 0x0d, 0x1c, 0xac, 0x9a, 0x53, 0x84, 0xb8, 0x4e, 0x48, 0xc0, + /*1350:*/ 0xfb, 0xc2, 0x48, 0x1e, 0x76, 0xb4, 0xf2, 0x7c, 0xde, 0xe1, 0xc4, 0xf4, 0xb7, 0x09, 0x19, 0x7e, + /*1360:*/ 0x0d, 0x40, 0x92, 0xa3, 0x4e, 0x14, 0xcf, 0x15, 0x17, 0x6c, 0x81, 0x55, 0xaa, 0xce, 0xa6, 0x8b, + /*1370:*/ 0xbf, 0xd6, 0x30, 0x06, 0xa0, 0x1b, 0x18, 0x40, 0xca, 0x69, 0xab, 0xe2, 0x3e, 0xa5, 0xf2, 0x85, + /*1380:*/ 0x43, 0x54, 0x76, 0x5d, 0xe3, 0x96, 0xd4, 0x39, 0x47, 0x70, 0x1a, 0x71, 0x94, 0xcd, 0x9d, 0xfa, + /*1390:*/ 0xb0, 0x89, 0xab, 0x7a, 0x2e, 0x49, 0xb5, 0x34, 0x66, 0xbb, 0xdc, 0x6e, 0x5a, 0x1d, 0x65, 0x20, + /*13a0:*/ 0xce, 0x49, 0x1d, 0xeb, 0x73, 0x83, 0x00, 0x05, 0xb0, 0x5a, 0x56, 0xc3, 0xa5, 0x0f, 0x03, 0xb0, + /*13b0:*/ 0xdb, 0xb5, 0xf0, 0x61, 0x2c, 0xfd, 0x37, 0x38, 0x7d, 0xf8, 0xc4, 0x09, 0xd0, 0xf3, 0xdc, 0x62, + /*13c0:*/ 0xca, 0x29, 0x71, 0xb9, 0x44, 0xc4, 0x24, 0x21, 0xc5, 0xfe, 0x9c, 0xd9, 0xd4, 0x89, 0x44, 0x00, + /*13d0:*/ 0x20, 0xae, 0xd9, 0xae, 0xd6, 0xea, 0x5d, 0x04, 0x35, 0x4c, 0x09, 0x47, 0xfa, 0x85, 0x7f, 0x1e, + /*13e0:*/ 0x52, 0x62, 0xb7, 0x8a, 0x05, 0xc5, 0x47, 0x39, 0x2d, 0xe8, 0xf0, 0xf7, 0x57, 0x67, 0xf5, 0xda, + /*13f0:*/ 0x47, 0xe9, 0x10, 0x84, 0xb4, 0xf9, 0x3f, 0x8d, 0xae, 0xdd, 0xce, 0x76, 0xc9, 0xfe, 0x0b, 0x52, + /*1400:*/ 0x63, 0x1d, 0xde, 0x2a, 0x25, 0x54, 0x9c, 0xab, 0x2b, 0x52, 0x30, 0x8c, 0x80, 0xe8, 0x50, 0xe0, + /*1410:*/ 0x2b, 0x6b, 0xf5, 0x42, 0xbc, 0x26, 0x85, 0x9f, 0xd3, 0x9a, 0xbe, 0x41, 0xd2, 0xf1, 0xa6, 0xd7, + /*1420:*/ 0xf2, 0xcd, 0x72, 0xab, 0x8d, 0x4c, 0x46, 0x7b, 0xaf, 0x82, 0x58, 0xd7, 0x2f, 0x16, 0x07, 0x28, + /*1430:*/ 0xf0, 0x3a, 0x7e, 0x85, 0xc3, 0xf3, 0xe8, 0xe5, 0x00, 0x06, 0x00, 0xb5, 0x97, 0x19, 0x9f, 0xde, + /*1440:*/ 0x99, 0x1f, 0xf5, 0x08, 0x97, 0x02, 0x6e, 0x60, 0xc5, 0xa7, 0x77, 0x99, 0xcf, 0x04, 0xa6, 0x2f, + /*1450:*/ 0xb5, 0xca, 0xff, 0x4b, 0xd7, 0xee, 0xcc, 0x90, 0x6c, 0x77, 0xac, 0x95, 0x3f, 0x24, 0xa5, 0x50, + /*1460:*/ 0x00, 0x9d, 0xf5, 0x7e, 0xed, 0x37, 0xa8, 0xd6, 0xd7, 0xf2, 0xf7, 0x14, 0xb8, 0x2e, 0x7e, 0x1f, + /*1470:*/ 0xa3, 0x02, 0xec, 0x4c, 0xf5, 0xc6, 0x7b, 0x03, 0x99, 0x3b, 0x9d, 0xaf, 0xad, 0xe2, 0x44, 0x7c, + /*1480:*/ 0x89, 0xd6, 0xd3, 0x09, 0x0c, 0xed, 0x48, 0x17, 0x3e, 0xcc, 0xce, 0x08, 0x1d, 0x2d, 0x47, 0x36, + /*1490:*/ 0xf8, 0x6c, 0x37, 0xcd, 0x7c, 0xc7, 0xf3, 0x06, 0x17, 0x8c, 0xca, 0xfe, 0x36, 0x4c, 0xb8, 0x10, + /*14a0:*/ 0x08, 0xe6, 0xd5, 0xa8, 0x99, 0x56, 0x48, 0xe0, 0x18, 0x44, 0x72, 0x63, 0x3d, 0x09, 0xd5, 0xd9, + /*14b0:*/ 0x5a, 0xe1, 0x4c, 0x38, 0xd1, 0xdc, 0x0b, 0x47, 0xd3, 0x8a, 0x1a, 0xf8, 0xe8, 0x75, 0x3b, 0x1a, + /*14c0:*/ 0x9c, 0xcb, 0x89, 0x37, 0xc4, 0xa6, 0xa3, 0xbe, 0xf6, 0xe5, 0x40, 0xd3, 0x44, 0x1d, 0xea, 0x92, + /*14d0:*/ 0xfa, 0xf2, 0xd6, 0x0d, 0x52, 0xf0, 0x8c, 0x0b, 0x3a, 0x55, 0x75, 0x7a, 0xfc, 0xef, 0x81, 0xdb, + /*14e0:*/ 0xc5, 0x97, 0x81, 0xe3, 0x32, 0xd8, 0x8a, 0x49, 0xf0, 0x14, 0x28, 0x14, 0xac, 0x7a, 0xc6, 0x21, + /*14f0:*/ 0xe2, 0xa9, 0x61, 0xc4, 0xa5, 0xd2, 0x8d, 0xd6, 0x36, 0xba, 0x4f, 0x20, 0x43, 0xeb, 0xac, 0xef, + /*1500:*/ 0x6a, 0x81, 0x0a, 0x54, 0x37, 0x35, 0x34, 0x09, 0xce, 0xdc, 0x78, 0x43, 0x00, 0xc5, 0x46, 0x0e, + /*1510:*/ 0x17, 0xb1, 0x7a, 0x51, 0x96, 0x54, 0xee, 0x24, 0x32, 0xf9, 0x09, 0x66, 0xff, 0xf6, 0xb9, 0x9f, + /*1520:*/ 0x06, 0xa4, 0x55, 0x8c, 0x3b, 0x9d, 0xcd, 0x31, 0x01, 0x33, 0x61, 0xeb, 0xd3, 0x45, 0x49, 0x34, + /*1530:*/ 0x2e, 0xff, 0xa3, 0x7f, 0xf5, 0xb0, 0x37, 0x00, 0x31, 0x84, 0xb1, 0xa1, 0x9f, 0xa4, 0xdb, 0xc7, + /*1540:*/ 0xa2, 0xd9, 0x23, 0x4c, 0xf0, 0x09, 0x57, 0x9b, 0x4b, 0xbc, 0x6b, 0xe4, 0x15, 0x55, 0x9f, 0x3d, + /*1550:*/ 0x97, 0xa6, 0xab, 0x0a, 0x86, 0xde, 0xd3, 0x83, 0xd2, 0x81, 0x21, 0x75, 0x60, 0x66, 0xd8, 0xa1, + /*1560:*/ 0xd0, 0xdb, 0x08, 0x42, 0xe6, 0xf1, 0xeb, 0x6f, 0x59, 0xe2, 0x0f, 0xd1, 0x00, 0x3a, 0x09, 0x86, + /*1570:*/ 0x61, 0x8f, 0x3c, 0x6d, 0x02, 0x48, 0x41, 0x1a, 0x9b, 0xcd, 0x33, 0xd6, 0xbe, 0x15, 0x88, 0x2a, + /*1580:*/ 0x94, 0xf9, 0xc9, 0xda, 0x03, 0xb3, 0x1c, 0xaa, 0x22, 0x19, 0xa9, 0x9e, 0xdd, 0xe7, 0x7e, 0x92, + /*1590:*/ 0xdf, 0x06, 0xd7, 0x0c, 0xe0, 0x19, 0xa8, 0xec, 0x9a, 0x33, 0xfa, 0x30, 0xa7, 0xe9, 0xc9, 0x3d, + /*15a0:*/ 0x6a, 0x14, 0x89, 0x5b, 0xe9, 0x19, 0xfd, 0xf5, 0xdb, 0xfe, 0x70, 0x4a, 0x09, 0x18, 0x9a, 0x90, + /*15b0:*/ 0x16, 0x88, 0xb2, 0x60, 0x6e, 0x34, 0xa5, 0x22, 0x7e, 0x2d, 0x5a, 0x37, 0x0e, 0xbe, 0x71, 0x7e, + /*15c0:*/ 0x5a, 0xd4, 0x38, 0x0b, 0x25, 0x49, 0x4d, 0x07, 0x47, 0xee, 0x3d, 0xfe, 0x8f, 0x81, 0xdb, 0xb2, + /*15d0:*/ 0xda, 0x0d, 0x71, 0xbc, 0x10, 0x36, 0x69, 0xd5, 0xec, 0xdd, 0x57, 0xc4, 0xeb, 0x52, 0xd6, 0x2c, + /*15e0:*/ 0xce, 0xaf, 0xe7, 0xae, 0xfa, 0xf6, 0x22, 0x8e, 0x72, 0x39, 0xcb, 0x48, 0x0f, 0x76, 0x9c, 0x51, + /*15f0:*/ 0x54, 0x7b, 0x7c, 0x2d, 0x5d, 0x4e, 0x54, 0x82, 0xf4, 0xfd, 0x6b, 0xdf, 0x97, 0xed, 0xec, 0x68, + /*1600:*/ 0xb7, 0x03, 0x26, 0x74, 0x46, 0xcc, 0x3f, 0x6d, 0x49, 0x52, 0xce, 0xe2, 0x82, 0x12, 0x79, 0x85, + /*1610:*/ 0x95, 0xb6, 0x4c, 0x9e, 0x61, 0xd9, 0xc4, 0xaa, 0xd6, 0xcd, 0x0b, 0xad, 0x78, 0xd8, 0xed, 0x07, + /*1620:*/ 0x5c, 0x8b, 0xe4, 0x1c, 0x86, 0x85, 0xf2, 0xee, 0x98, 0x81, 0x4f, 0xa9, 0x74, 0x22, 0xd5, 0x7f, + /*1630:*/ 0xf3, 0x48, 0xec, 0x30, 0xde, 0x23, 0x10, 0xa8, 0x6e, 0x1e, 0xbb, 0x6b, 0x31, 0xd1, 0x26, 0x48, + /*1640:*/ 0xac, 0x4a, 0x19, 0x66, 0xef, 0x2e, 0x5f, 0xd9, 0x7a, 0xc6, 0xfa, 0xc3, 0x06, 0xf0, 0xfe, 0x6c, + /*1650:*/ 0xd3, 0xf5, 0xdd, 0x6b, 0x09, 0x39, 0x17, 0x99, 0x29, 0xff, 0x24, 0x51, 0x3b, 0x06, 0x35, 0x92, + /*1660:*/ 0xda, 0x9f, 0x9f, 0x32, 0x40, 0x5c, 0x05, 0x60, 0x18, 0xd5, 0xb4, 0xd7, 0x9d, 0x7f, 0xd8, 0x5b, + /*1670:*/ 0x3e, 0x67, 0xee, 0xaa, 0x12, 0xd0, 0xd1, 0x61, 0x78, 0x60, 0x28, 0x63, 0xd8, 0x91, 0xe1, 0x86, + /*1680:*/ 0x78, 0x01, 0x62, 0x55, 0xa8, 0x5c, 0x7d, 0xf5, 0x80, 0x97, 0x16, 0xaa, 0xcc, 0x62, 0xec, 0x35, + /*1690:*/ 0x18, 0x53, 0xda, 0xfc, 0x3b, 0x5b, 0x2f, 0xe5, 0xd0, 0xb9, 0xba, 0x31, 0xed, 0xbe, 0xe0, 0xf1, + /*16a0:*/ 0xfa, 0x54, 0x8f, 0x1d, 0x1a, 0xfc, 0xfb, 0xe0, 0xbb, 0x30, 0x0c, 0x6a, 0xf7, 0x80, 0x27, 0xbb, + /*16b0:*/ 0xb2, 0xc3, 0x38, 0xb9, 0x01, 0x2c, 0x93, 0x00, 0xac, 0xb0, 0xef, 0x9a, 0x44, 0x7d, 0xfb, 0x0b, + /*16c0:*/ 0x91, 0x36, 0xac, 0xb7, 0x0a, 0xe9, 0x29, 0xdc, 0x82, 0x8a, 0x76, 0x75, 0x12, 0xec, 0x81, 0x20, + /*16d0:*/ 0x55, 0x2b, 0x67, 0x28, 0xa6, 0x1a, 0x73, 0xde, 0x82, 0xac, 0x0f, 0xa6, 0xd8, 0xa6, 0x96, 0xf7, + /*16e0:*/ 0xe6, 0x27, 0x33, 0xa3, 0x4d, 0x37, 0x66, 0xbd, 0xcf, 0xa3, 0x70, 0x4f, 0xae, 0xb3, 0x55, 0x92, + /*16f0:*/ 0x8b, 0x7c, 0x5f, 0xd3, 0x5e, 0x8a, 0x84, 0xf8, 0x30, 0x95, 0x16, 0xb5, 0xfc, 0xc2, 0x23, 0x25, + /*1700:*/ 0x65, 0xdb, 0x48, 0xcd, 0xfc, 0xc4, 0xbf, 0xca, 0xa3, 0xd3, 0x8b, 0xe4, 0x5c, 0x7a, 0x97, 0x5d, + /*1710:*/ 0xa8, 0xc5, 0xf9, 0x1a, 0x91, 0x60, 0x3b, 0x20, 0x77, 0xe7, 0x35, 0x99, 0x43, 0x47, 0x1c, 0x96, + /*1720:*/ 0x54, 0xeb, 0x9f, 0xc0, 0x7e, 0xb0, 0xcd, 0x9f, 0x62, 0xec, 0x5c, 0xd9, 0x37, 0xc8, 0x4d, 0x92, + /*1730:*/ 0xc0, 0x76, 0xfa, 0x3b, 0xbd, 0x4b, 0xd1, 0x1f, 0x43, 0xd9, 0x55, 0x7a, 0xb8, 0x7c, 0x7b, 0xa3, + /*1740:*/ 0x0c, 0x26, 0x5f, 0x6b, 0x7c, 0x38, 0xc2, 0x72, 0x36, 0xd7, 0xc0, 0x5c, 0x57, 0x69, 0xd1, 0x1a, + /*1750:*/ 0xc6, 0xda, 0x20, 0x3a, 0x2a, 0x43, 0x2b, 0x32, 0x86, 0x37, 0x8d, 0x44, 0x20, 0x0c, 0xcf, 0xb4, + /*1760:*/ 0xe8, 0x7b, 0x38, 0xc2, 0xea, 0x4f, 0xd2, 0xf3, 0xe0, 0x44, 0x11, 0xa4, 0x60, 0x11, 0xea, 0x09, + /*1770:*/ 0x3a, 0x04, 0x0b, 0xe8, 0xcc, 0x55, 0xbf, 0xa2, 0xe7, 0xee, 0x4e, 0xbf, 0xc6, 0x10, 0xbf, 0x0c, + /*1780:*/ 0xb9, 0x24, 0xa9, 0x8c, 0x46, 0x81, 0xc7, 0x44, 0x3e, 0x63, 0x50, 0xce, 0x4c, 0x91, 0xfc, 0xe8, + /*1790:*/ 0x2e, 0x97, 0x76, 0xc5, 0xf4, 0xd0, 0x36, 0x5a, 0x6c, 0x30, 0xfe, 0xc1, 0x02, 0x86, 0x07, 0xd3, + /*17a0:*/ 0xeb, 0x57, 0x6d, 0x43, 0xf9, 0xfa, 0xc7, 0x39, 0xd5, 0xfa, 0x70, 0xa4, 0x55, 0x7c, 0x4e, 0x93, + /*17b0:*/ 0xca, 0xd9, 0x78, 0xcb, 0xa2, 0x1d, 0x79, 0x96, 0x55, 0x16, 0x94, 0x8d, 0x74, 0xda, 0xa5, 0x1c, + /*17c0:*/ 0xf6, 0xa3, 0xcc, 0x33, 0x0e, 0x3a, 0x29, 0xa0, 0xf9, 0x7d, 0x8b, 0x13, 0x6e, 0x7f, 0x02, 0x4a, + /*17d0:*/ 0x50, 0xd3, 0x7c, 0x1e, 0x09, 0x3c, 0xd0, 0x03, 0xad, 0x0d, 0xb2, 0xfa, 0xa1, 0x8b, 0xd3, 0x69, + /*17e0:*/ 0x91, 0x7a, 0x6a, 0xe2, 0x66, 0x1a, 0xe4, 0x3d, 0xdf, 0xab, 0x3f, 0xfa, 0x39, 0xb3, 0x66, 0x0a, + /*17f0:*/ 0x80, 0x1a, 0x07, 0x75, 0xe6, 0xfd, 0x9b, 0x9b, 0xfe, 0xf0, 0x9c, 0x3f, 0x9e, 0x43, 0xc8, 0xe3, + /*1800:*/ 0xbd, 0xb4, 0x32, 0x25, 0x4f, 0x96, 0x8f, 0xba, 0x46, 0x34, 0xdc, 0x9e, 0x18, 0xe8, 0x16, 0x9a, + /*1810:*/ 0xc1, 0x8c, 0x41, 0x16, 0x2d, 0x88, 0x0b, 0x1d, 0x6f, 0x2a, 0xbf, 0x99, 0x85, 0x14, 0xa3, 0x89, + /*1820:*/ 0x86, 0xac, 0xf6, 0xe3, 0x7b, 0xcf, 0x48, 0xec, 0xe0, 0x74, 0xbc, 0x96, 0x95, 0x4d, 0x76, 0x1d, + /*1830:*/ 0x5e, 0x76, 0x49, 0x63, 0x62, 0x75, 0x21, 0x87, 0x4d, 0x62, 0xb3, 0xfe, 0x0b, 0xf5, 0xed, 0x8c, + /*1840:*/ 0x95, 0x9c, 0xd3, 0xc5, 0x5f, 0x14, 0xd8, 0x4e, 0x41, 0xaa, 0xd9, 0x1f, 0xb3, 0x67, 0x35, 0xaf, + /*1850:*/ 0x0d, 0x3a, 0xcb, 0xe5, 0xcc, 0x84, 0xc4, 0xab, 0x45, 0x38, 0xa9, 0x45, 0x66, 0x12, 0x75, 0x93, + /*1860:*/ 0xc0, 0x36, 0x42, 0x88, 0xb6, 0x5e, 0x3f, 0xae, 0x67, 0xe5, 0x5f, 0xe2, 0xc1, 0x93, 0xca, 0x84, + /*1870:*/ 0x55, 0xa1, 0xda, 0xec, 0x53, 0xe8, 0x74, 0xc2, 0xdb, 0x25, 0xdf, 0x8a, 0xfb, 0xfa, 0xf0, 0x14, + /*1880:*/ 0xf7, 0x92, 0x67, 0xbb, 0x0a, 0x5e, 0xfa, 0x53, 0x4f, 0x5f, 0xf9, 0x05, 0x7b, 0xbd, 0x02, 0x3e, + /*1890:*/ 0x30, 0xdf, 0x90, 0xef, 0x3d, 0x84, 0x0b, 0x71, 0x8b, 0x08, 0xc3, 0xae, 0xb7, 0xdb, 0xe1, 0x19, + /*18a0:*/ 0x56, 0x85, 0x65, 0x98, 0x53, 0x32, 0x4b, 0xe7, 0xd5, 0x01, 0x4f, 0x02, 0xf2, 0xa1, 0xb6, 0x61, + /*18b0:*/ 0xf9, 0xa2, 0xd1, 0xb0, 0xb7, 0x87, 0x21, 0x62, 0x60, 0x7a, 0x91, 0x14, 0x7a, 0x11, 0x6d, 0xb4, + /*18c0:*/ 0x79, 0x40, 0xa4, 0x9a, 0x6d, 0xcf, 0xe2, 0x6d, 0x8a, 0xd2, 0x7d, 0xfb, 0x2b, 0x11, 0xfa, 0x92, + /*18d0:*/ 0xe3, 0x6f, 0x47, 0x7f, 0xa2, 0x41, 0x3b, 0x90, 0x36, 0x68, 0x90, 0x96, 0xf3, 0xf5, 0x27, 0xeb, + /*18e0:*/ 0x99, 0x6b, 0x31, 0x5b, 0x94, 0x7d, 0xa6, 0x2d, 0xdf, 0xfd, 0xee, 0x2c, 0x54, 0x59, 0x1c, 0xb7, + /*18f0:*/ 0xa9, 0xd0, 0x9a, 0x43, 0x82, 0x05, 0x47, 0xba, 0x26, 0xe3, 0x7d, 0x98, 0xd9, 0x4e, 0xe9, 0xed, + /*1900:*/ 0xbb, 0x30, 0x27, 0xb0, 0xed, 0xc4, 0x95, 0xb5, 0x64, 0x98, 0x66, 0xe6, 0x44, 0x9d, 0x63, 0x3f, + /*1910:*/ 0xb8, 0xdd, 0x35, 0xed, 0x79, 0x9c, 0x30, 0xd0, 0x5a, 0xfc, 0x14, 0xcf, 0x6b, 0x05, 0x48, 0x5d, + /*1920:*/ 0x35, 0xd7, 0xd6, 0x8c, 0xce, 0xee, 0x21, 0x73, 0x01, 0xeb, 0x8a, 0x14, 0x01, 0x1c, 0xee, 0x8a, + /*1930:*/ 0xbc, 0x7a, 0xbb, 0xbb, 0x7b, 0x89, 0x8a, 0xfa, 0x6a, 0xf8, 0x90, 0x6f, 0x07, 0xba, 0x77, 0x7b, + /*1940:*/ 0x27, 0x01, 0xfd, 0x67, 0x52, 0xcf, 0xf5, 0xc2, 0xa7, 0x2d, 0x79, 0xbf, 0x50, 0x7a, 0xc9, 0x1c, + /*1950:*/ 0x6a, 0x6f, 0x38, 0xa1, 0x76, 0x80, 0x22, 0x01, 0xa8, 0x4e, 0x6c, 0x8d, 0x64, 0x55, 0x63, 0x89, + /*1960:*/ 0xf8, 0xe4, 0x59, 0x37, 0xf7, 0xae, 0x6b, 0x61, 0x98, 0x7e, 0x43, 0xdd, 0xba, 0xf0, 0x07, 0x28, + /*1970:*/ 0x91, 0xe7, 0x8a, 0xf7, 0xe4, 0xaa, 0x86, 0x0b, 0x26, 0x1e, 0x3c, 0x45, 0x9b, 0x84, 0xd0, 0xe0, + /*1980:*/ 0xcf, 0x81, 0x1b, 0x61, 0x9b, 0xef, 0xde, 0x8c, 0xc0, 0xa4, 0x83, 0xe7, 0x31, 0x18, 0xf1, 0x66, + /*1990:*/ 0x2d, 0x65, 0x6f, 0x2e, 0xfb, 0x60, 0x99, 0xa4, 0xbd, 0x20, 0x6b, 0x83, 0xe6, 0x2d, 0x93, 0xbc, + /*19a0:*/ 0x9b, 0xce, 0xa5, 0x1e, 0x9b, 0xda, 0xb4, 0x69, 0x89, 0xb9, 0x42, 0x3a, 0x1a, 0xcc, 0x13, 0x7f, + /*19b0:*/ 0x5e, 0xc6, 0xa2, 0x4c, 0x8a, 0x82, 0xc0, 0x19, 0x2f, 0xe0, 0xac, 0x58, 0xb4, 0xbc, 0x69, 0x2f, + /*19c0:*/ 0x11, 0xa2, 0x85, 0x0b, 0x72, 0x32, 0x74, 0x83, 0x11, 0x58, 0xe0, 0x7a, 0xce, 0x55, 0xda, 0x6e, + /*19d0:*/ 0x2f, 0xe9, 0x6c, 0x62, 0xdc, 0xbd, 0x89, 0x0d, 0xfd, 0x7a, 0x32, 0xb9, 0x28, 0x7a, 0xc2, 0xb6, + /*19e0:*/ 0x10, 0x67, 0xf1, 0x6a, 0xe2, 0x04, 0x17, 0x9d, 0x2d, 0xe0, 0xde, 0xc3, 0xad, 0xff, 0xb6, 0x4b, + /*19f0:*/ 0x11, 0x3d, 0x53, 0x21, 0x6a, 0xe6, 0x30, 0xad, 0x15, 0x7d, 0x13, 0x28, 0x3c, 0xea, 0x29, 0x32, + /*1a00:*/ 0xa7, 0xb6, 0x67, 0x07, 0x1f, 0x0e, 0x72, 0xe8, 0xd7, 0xcf, 0x59, 0xb5, 0x68, 0xf4, 0xb6, 0x81, + /*1a10:*/ 0xed, 0xf5, 0xb8, 0xab, 0xfb, 0xee, 0x6c, 0x94, 0xff, 0x03, 0xa9, 0xc8, 0x1a, 0x30, 0x9b, 0x16, + /*1a20:*/ 0xff, 0x9b, 0x40, 0x57, 0x70, 0x9f, 0xb9, 0xcb, 0xf6, 0x79, 0x88, 0xee, 0x3f, 0xf1, 0xa0, 0x8d, + /*1a30:*/ 0x67, 0x26, 0x90, 0x71, 0x84, 0x34, 0xce, 0x7b, 0xaa, 0x83, 0xd1, 0x00, 0x33, 0xfd, 0x4d, 0x86, + /*1a40:*/ 0x55, 0x53, 0xc0, 0x6b, 0x3a, 0x44, 0xd8, 0xdb, 0x40, 0x24, 0xb8, 0xef, 0x7d, 0x2b, 0x7d, 0x03, + /*1a50:*/ 0x79, 0xaf, 0x0f, 0x86, 0x21, 0x4e, 0x41, 0xc6, 0x60, 0x21, 0x8e, 0x58, 0x26, 0x1b, 0x72, 0xfe, + /*1a60:*/ 0x71, 0x21, 0x0e, 0xa1, 0xd6, 0xf7, 0x41, 0x50, 0x68, 0xca, 0x3f, 0x62, 0xdf, 0xd1, 0x41, 0xe1, + /*1a70:*/ 0xdc, 0xc2, 0x7f, 0x82, 0xd8, 0x6e, 0x3e, 0xf9, 0x30, 0xee, 0x71, 0xcd, 0x1f, 0x0f, 0x4f, 0xb3, + /*1a80:*/ 0x03, 0xfb, 0x20, 0x75, 0x91, 0x1a, 0xbf, 0xb0, 0xc1, 0xc4, 0x65, 0x4b, 0x65, 0x52, 0x2a, 0x13, + /*1a90:*/ 0xb1, 0xb1, 0xc8, 0xe1, 0x9e, 0xc5, 0x78, 0x40, 0xae, 0xf6, 0x57, 0x12, 0xc9, 0x49, 0x24, 0xee, + /*1aa0:*/ 0x87, 0x6b, 0xa0, 0x0c, 0x0f, 0xb1, 0xbe, 0xac, 0xcb, 0x8b, 0xe9, 0x3f, 0x1b, 0xaa, 0x79, 0x9f, + /*1ab0:*/ 0xc4, 0xff, 0xac, 0xf9, 0xf7, 0x53, 0xab, 0xa8, 0xf2, 0x00, 0xc0, 0xa4, 0x24, 0x22, 0x97, 0x58, + /*1ac0:*/ 0x0c, 0x39, 0x96, 0xe2, 0xe9, 0xcf, 0x62, 0xcb, 0x8f, 0xdb, 0xa8, 0xdd, 0x5a, 0x5c, 0xb2, 0xce, + /*1ad0:*/ 0xae, 0x84, 0x2a, 0x68, 0x7c, 0x38, 0x56, 0x78, 0xe1, 0xa6, 0x7c, 0x6b, 0x8b, 0x47, 0x07, 0xe4, + /*1ae0:*/ 0xc7, 0x54, 0x9a, 0x76, 0x34, 0xe5, 0xf5, 0x23, 0x49, 0x15, 0x90, 0x73, 0xa3, 0x0a, 0x5c, 0x4b, + /*1af0:*/ 0x99, 0x6f, 0x7b, 0x0f, 0x61, 0x9e, 0xf9, 0xa5, 0x95, 0x42, 0xbd, 0x19, 0xa5, 0x31, 0x08, 0xdd, + /*1b00:*/ 0x9a, 0x23, 0xdb, 0x2c, 0x19, 0x50, 0xbb, 0xc3, 0x3b, 0x51, 0xec, 0xd9, 0x38, 0x5b, 0x1b, 0x58, + /*1b10:*/ 0x79, 0xfb, 0xa2, 0x94, 0x6a, 0xe1, 0xd9, 0x03, 0x58, 0xd2, 0xb7, 0xfe, 0xc2, 0x99, 0xf4, 0x45, + /*1b20:*/ 0x28, 0x00, 0x11, 0x41, 0x67, 0x09, 0x1a, 0x82, 0x48, 0x11, 0x25, 0x82, 0x66, 0xd9, 0x08, 0xe4, + /*1b30:*/ 0xf3, 0x4f, 0xf1, 0x4c, 0x40, 0x78, 0xb7, 0x40, 0x5f, 0x16, 0xd6, 0x4d, 0x9d, 0x25, 0xcb, 0xff, + /*1b40:*/ 0xe1, 0xe7, 0xaf, 0x0c, 0x5b, 0x9a, 0x57, 0xf6, 0xc1, 0xd0, 0x1c, 0x20, 0x68, 0x9a, 0x51, 0x7a, + /*1b50:*/ 0xbd, 0xcb, 0x96, 0x21, 0x57, 0xe4, 0x70, 0x9d, 0x9c, 0xda, 0xaa, 0x89, 0x0d, 0xc2, 0x53, 0xa9, + /*1b60:*/ 0x6b, 0x78, 0x12, 0xeb, 0x77, 0x4d, 0x5c, 0xe4, 0x5e, 0x2b, 0x30, 0x0f, 0xb3, 0x08, 0x9f, 0x68, + /*1b70:*/ 0xf1, 0xb4, 0x37, 0xac, 0xed, 0x39, 0x0e, 0x59, 0xfa, 0xc4, 0xa8, 0xfa, 0xcc, 0x76, 0x77, 0xba, + /*1b80:*/ 0x15, 0xae, 0xbe, 0x0f, 0x89, 0xb7, 0x3c, 0xf5, 0x27, 0x2c, 0xfc, 0x05, 0xb2, 0x32, 0x40, 0x61, + /*1b90:*/ 0x0d, 0xdd, 0x0a, 0x8a, 0x0c, 0xa5, 0x7e, 0x2c, 0x5e, 0x50, 0x6b, 0xa1, 0x3b, 0x87, 0x23, 0xa0, + /*1ba0:*/ 0xa9, 0x4c, 0x46, 0x4c, 0xfb, 0xe2, 0x39, 0x3a, 0x3b, 0x43, 0x9b, 0x24, 0x8b, 0x4c, 0xae, 0x25, + /*1bb0:*/ 0x81, 0x72, 0x5e, 0xaf, 0xe3, 0x3f, 0x8c, 0x5b, 0x2f, 0xfd, 0x48, 0x61, 0x29, 0x9e, 0xba, 0x76, + /*1bc0:*/ 0x73, 0x3c, 0xeb, 0xeb, 0x30, 0x18, 0xa9, 0x89, 0x4c, 0xbc, 0x09, 0xb6, 0xd7, 0x46, 0x27, 0x76, + /*1bd0:*/ 0x51, 0x41, 0x52, 0x29, 0x2a, 0x73, 0x2d, 0xf0, 0x13, 0x9c, 0x00, 0x38, 0xe1, 0xe6, 0xc7, 0x9c, + /*1be0:*/ 0x7b, 0x07, 0xab, 0xf0, 0xf9, 0x0f, 0xc0, 0xce, 0x6a, 0xba, 0x10, 0x03, 0xfa, 0x55, 0x8b, 0x1a, + /*1bf0:*/ 0xfc, 0xd4, 0xdf, 0x8d, 0xf5, 0x98, 0x7e, 0xf1, 0x70, 0xff, 0x41, 0x9d, 0x66, 0xa3, 0x3a, 0x99, + /*1c00:*/ 0x5e, 0xe2, 0x9f, 0x29, 0x3b, 0xc8, 0xe9, 0x32, 0xb7, 0x1a, 0xb3, 0x47, 0xde, 0x42, 0x2d, 0x37, + /*1c10:*/ 0x2f, 0x13, 0xe6, 0x4a, 0xd8, 0x4d, 0xfc, 0x65, 0x6b, 0xaa, 0xd7, 0x58, 0xab, 0x86, 0x95, 0x88, + /*1c20:*/ 0x36, 0xf8, 0xf9, 0xa6, 0xd6, 0x66, 0xf3, 0xa7, 0x18, 0x62, 0x7d, 0xa3, 0x5f, 0xbe, 0xac, 0xba, + /*1c30:*/ 0x9f, 0x02, 0x3b, 0xa7, 0x43, 0x2a, 0xb5, 0x48, 0x70, 0x76, 0xda, 0xa2, 0x06, 0xb4, 0x67, 0x48, + /*1c40:*/ 0x33, 0xd9, 0x2d, 0xce, 0xd2, 0xe0, 0xd5, 0x3b, 0x81, 0xbb, 0x7a, 0x6a, 0xa9, 0xe5, 0xac, 0x82, + /*1c50:*/ 0x7c, 0x05, 0x7d, 0x93, 0x03, 0x15, 0xc2, 0x8f, 0x14, 0x44, 0xf9, 0xe2, 0xb2, 0x85, 0xfd, 0xe4, + /*1c60:*/ 0x7f, 0xaf, 0x3f, 0x36, 0x1e, 0xdc, 0x0f, 0x81, 0x29, 0x22, 0xfd, 0xb6, 0xf4, 0xa1, 0xef, 0xe2, + /*1c70:*/ 0x28, 0x82, 0xcb, 0x1c, 0x50, 0x4b, 0x68, 0x92, 0xc5, 0x40, 0xba, 0x8f, 0xb0, 0x13, 0x1e, 0xb7, + /*1c80:*/ 0xc4, 0x89, 0x78, 0x90, 0x52, 0x4a, 0x0d, 0xa9, 0x21, 0x25, 0x46, 0x65, 0x6c, 0x3f, 0x44, 0xb6, + /*1c90:*/ 0x6c, 0x6b, 0x91, 0xe2, 0x84, 0x75, 0x33, 0x58, 0x67, 0xf1, 0x19, 0x91, 0xd2, 0x18, 0xdb, 0x6c, + /*1ca0:*/ 0x80, 0x06, 0x8f, 0xb4, 0x13, 0xde, 0x16, 0x1b, 0x70, 0x8e, 0x11, 0x92, 0xfd, 0xa5, 0x38, 0xbf, + /*1cb0:*/ 0x3b, 0x88, 0x8a, 0xec, 0x26, 0xe7, 0x04, 0x47, 0x34, 0x63, 0xcc, 0xcb, 0x57, 0x35, 0x2d, 0xe7, + /*1cc0:*/ 0x77, 0x7c, 0xe3, 0x84, 0xfc, 0xdd, 0x45, 0x3b, 0x45, 0x9e, 0x7c, 0xf8, 0x78, 0x5d, 0x42, 0x09, + /*1cd0:*/ 0x23, 0x9c, 0xf5, 0x8e, 0x95, 0x0a, 0xac, 0x64, 0x35, 0x20, 0x78, 0xca, 0x3e, 0x2b, 0x5f, 0xd5, + /*1ce0:*/ 0xb0, 0x22, 0xc6, 0x3a, 0x9a, 0x6f, 0xa7, 0x57, 0xf6, 0x83, 0xb4, 0xad, 0xe9, 0xd7, 0x0f, 0xaa, + /*1cf0:*/ 0x93, 0x49, 0x6b, 0x04, 0xf9, 0x35, 0x16, 0x37, 0x7f, 0x82, 0xac, 0x7e, 0x87, 0x32, 0x84, 0xef, + /*1d00:*/ 0x1c, 0x06, 0x6a, 0xdc, 0x26, 0x23, 0xcd, 0x39, 0x3c, 0x71, 0xae, 0x7d, 0x08, 0x6d, 0x76, 0xa4, + /*1d10:*/ 0xf0, 0x68, 0xd6, 0x6c, 0xec, 0xc4, 0x10, 0x6c, 0xaf, 0x8e, 0x50, 0x2c, 0xd8, 0x06, 0xcd, 0x19, + /*1d20:*/ 0x05, 0xf8, 0x16, 0x3a, 0x28, 0xb9, 0x2e, 0x00, 0x0b, 0xf9, 0xa9, 0x1b, 0x5a, 0xa5, 0x34, 0x9c, + /*1d30:*/ 0xbe, 0x65, 0xb5, 0xe6, 0xb4, 0xc1, 0x8a, 0xfe, 0x1c, 0x24, 0x0f, 0x7e, 0x91, 0x8c, 0x65, 0x3d, + /*1d40:*/ 0xaa, 0x26, 0x13, 0x91, 0x8b, 0xee, 0xd9, 0x0c, 0xdc, 0xc7, 0x08, 0x21, 0x8c, 0xc4, 0xb7, 0x86, + /*1d50:*/ 0x45, 0xf7, 0x11, 0x35, 0x9d, 0x76, 0x38, 0x81, 0x6c, 0xc5, 0x49, 0x87, 0xe2, 0xe9, 0x48, 0x5c, + /*1d60:*/ 0xf9, 0x15, 0x30, 0x10, 0x2e, 0xee, 0x6e, 0x4d, 0x9b, 0xd3, 0xb8, 0x10, 0xff, 0xdd, 0x5d, 0xe1, + /*1d70:*/ 0x2c, 0x38, 0xfe, 0x0f, 0xae, 0x14, 0xb9, 0x21, 0x74, 0x6a, 0xc0, 0xf8, 0x29, 0x2e, 0xa1, 0xb0, + /*1d80:*/ 0xf9, 0x3c, 0x72, 0x46, 0x1b, 0xe7, 0xa2, 0xef, 0x18, 0x0b, 0xe3, 0xc7, 0x6b, 0x60, 0x6a, 0x7f, + /*1d90:*/ 0x60, 0x36, 0xa5, 0xa9, 0x3b, 0x13, 0x97, 0xd4, 0xee, 0x5a, 0x23, 0xd0, 0xc9, 0x2d, 0x3a, 0x1f, + /*1da0:*/ 0x84, 0x86, 0x42, 0xc5, 0x94, 0xf0, 0x6f, 0x9e, 0xd7, 0xa9, 0xa0, 0x63, 0xd0, 0xc2, 0xa2, 0x57, + /*1db0:*/ 0x3a, 0xe5, 0x14, 0xc9, 0xce, 0x7a, 0x77, 0xfc, 0x72, 0x99, 0xf7, 0x02, 0x92, 0xdb, 0x95, 0xf3, + /*1dc0:*/ 0x66, 0x17, 0xb0, 0xe1, 0x83, 0xe3, 0x13, 0x55, 0xe4, 0xf2, 0xb7, 0x45, 0x35, 0x34, 0x5e, 0x3b, + /*1dd0:*/ 0x1d, 0x68, 0x0a, 0x38, 0x94, 0x43, 0x7b, 0xc0, 0x21, 0x77, 0x3e, 0x11, 0x51, 0xba, 0x1b, 0x0c, + /*1de0:*/ 0x1f, 0x0b, 0x28, 0x23, 0xca, 0x79, 0x5b, 0x3c, 0xc8, 0x4b, 0x84, 0xd8, 0xa0, 0xfc, 0x9d, 0x7f, + /*1df0:*/ 0xad, 0xce, 0x6a, 0xe4, 0x7b, 0xbd, 0xbc, 0xbe, 0x9c, 0xef, 0x2c, 0x5e, 0x5c, 0x64, 0x1e, 0x5d, + /*1e00:*/ 0x97, 0x83, 0x20, 0x63, 0x5b, 0x4d, 0x18, 0xdd, 0xe3, 0x08, 0x7a, 0xfd, 0x7a, 0xb0, 0xb4, 0x89, + /*1e10:*/ 0xfe, 0x5d, 0x59, 0x5a, 0x50, 0x91, 0x6a, 0xe3, 0xd8, 0xe4, 0x4c, 0x74, 0x06, 0x1e, 0xb8, 0xcb, + /*1e20:*/ 0x27, 0x0e, 0x57, 0x76, 0x4c, 0x31, 0x76, 0x86, 0xd4, 0x37, 0x93, 0x6c, 0x13, 0x45, 0x6d, 0x79, + /*1e30:*/ 0xef, 0xab, 0xb6, 0x07, 0x7b, 0x07, 0xc0, 0x26, 0xa1, 0x61, 0x40, 0xa0, 0x67, 0x36, 0xfc, 0xb5, + /*1e40:*/ 0x8b, 0x75, 0x02, 0xd8, 0x4d, 0x60, 0x40, 0xeb, 0xf4, 0x02, 0xb2, 0xe3, 0x5e, 0x22, 0x13, 0xf5, + /*1e50:*/ 0xb4, 0x71, 0xb9, 0x64, 0x3a, 0x71, 0xba, 0xdb, 0x4e, 0xbe, 0x8e, 0x35, 0x18, 0xe1, 0xf3, 0xf1, + /*1e60:*/ 0xde, 0xd9, 0xba, 0x88, 0x1e, 0x08, 0xd7, 0x79, 0x54, 0xdd, 0x1c, 0xda, 0xa3, 0xcd, 0x18, 0x7b, + /*1e70:*/ 0x84, 0x17, 0xc7, 0x0a, 0x17, 0x9f, 0x14, 0x58, 0x6c, 0xce, 0x7f, 0x1b, 0x7c, 0x0b, 0xcd, 0x82, + /*1e80:*/ 0xee, 0x1a, 0x9f, 0x24, 0x94, 0x01, 0x76, 0xbe, 0x68, 0xb5, 0xc5, 0x9e, 0x6f, 0x3c, 0x90, 0x02, + /*1e90:*/ 0x2b, 0x58, 0xc3, 0x2e, 0x9d, 0xc0, 0x4e, 0xa2, 0x78, 0xf2, 0x2d, 0x8a, 0x07, 0x82, 0xbe, 0xd4, + /*1ea0:*/ 0xbf, 0x4a, 0x08, 0xa3, 0xa5, 0x89, 0xe0, 0x3f, 0x28, 0x0b, 0xec, 0xac, 0x77, 0xdd, 0xac, 0x52, + /*1eb0:*/ 0x7a, 0x58, 0x65, 0x59, 0x48, 0x03, 0xf9, 0x27, 0xd1, 0xa9, 0x7b, 0x37, 0xbe, 0x4c, 0x6c, 0x6b, + /*1ec0:*/ 0x73, 0x15, 0x74, 0xfc, 0x83, 0x1e, 0xbd, 0x67, 0x20, 0x14, 0xe9, 0xad, 0x93, 0x13, 0xd5, 0x45, + /*1ed0:*/ 0x2a, 0xdc, 0x6c, 0xa3, 0x04, 0xe7, 0x5f, 0x58, 0xea, 0x95, 0x25, 0x25, 0xe8, 0xb5, 0x32, 0x26, + /*1ee0:*/ 0xd8, 0xa1, 0x16, 0x0c, 0xbe, 0x63, 0xee, 0xc3, 0x52, 0xba, 0x01, 0xbe, 0xfd, 0xc1, 0x9b, 0x5c, + /*1ef0:*/ 0xf4, 0x6d, 0x1c, 0x08, 0x0a, 0xd9, 0xd9, 0xa6, 0xd2, 0x24, 0x05, 0x7c, 0x05, 0x8c, 0x4a, 0x7a, + /*1f00:*/ 0xfe, 0x35, 0x11, 0x82, 0xb6, 0x94, 0xe1, 0x3e, 0xc3, 0xd1, 0xad, 0x88, 0x3c, 0x2f, 0xb2, 0x2c, + /*1f10:*/ 0x75, 0xef, 0x37, 0xd8, 0x33, 0x9a, 0xf6, 0x65, 0x8f, 0x58, 0xa7, 0x64, 0x52, 0xb8, 0x95, 0x19, + /*1f20:*/ 0xe6, 0xee, 0x39, 0x03, 0xdd, 0x8d, 0x33, 0x47, 0xb5, 0xb7, 0x4b, 0x6f, 0x55, 0xb6, 0x8e, 0xca, + /*1f30:*/ 0x3d, 0x6f, 0xc7, 0x39, 0x1f, 0x56, 0xa1, 0xa8, 0xef, 0x0b, 0xcb, 0x52, 0xea, 0x2d, 0x1f, 0x11, + /*1f40:*/ 0xee, 0x6b, 0x6a, 0x26, 0x84, 0xce, 0x02, 0x5a, 0x10, 0x2d, 0x6f, 0xd6, 0x8f, 0xf9, 0x68, 0xd8, + /*1f50:*/ 0x0a, 0x67, 0xeb, 0x09, 0x7c, 0xd0, 0xa8, 0xfd, 0x47, 0x40, 0x49, 0x6f, 0xb1, 0xcd, 0x01, 0xaa, + /*1f60:*/ 0x2d, 0x85, 0xb8, 0xc7, 0x81, 0x3e, 0xc7, 0xa9, 0xbe, 0xc5, 0xc6, 0x20, 0xf2, 0x4d, 0x61, 0xff, + /*1f70:*/ 0x64, 0x45, 0xed, 0xa0, 0xa0, 0xa8, 0xbb, 0xb4, 0x78, 0x44, 0x1c, 0x7f, 0xe8, 0x87, 0x7b, 0xc1, + /*1f80:*/ 0x29, 0xc2, 0x71, 0x0d, 0x9a, 0xa7, 0x9c, 0xc4, 0x03, 0x1b, 0x6c, 0x25, 0x2f, 0x9f, 0xc4, 0xd1, + /*1f90:*/ 0x67, 0x19, 0x81, 0x3f, 0x71, 0x94, 0xcd, 0xed, 0x84, 0x9d, 0x0f, 0x42, 0xae, 0x38, 0xdf, 0xbd, + /*1fa0:*/ 0xc3, 0x92, 0x6b, 0xa8, 0x8b, 0x18, 0x45, 0xe2, 0xf3, 0x1c, 0x7c, 0xe6, 0x06, 0xeb, 0x41, 0x48, + /*1fb0:*/ 0xe1, 0x44, 0x79, 0x28, 0xa2, 0xfe, 0x46, 0x85, 0x9d, 0x1a, 0x83, 0x1d, 0x9c, 0xe3, 0xe2, 0xc9, + /*1fc0:*/ 0x33, 0x68, 0xa8, 0xa9, 0x07, 0x9c, 0x7f, 0x71, 0xe7, 0xf0, 0x4e, 0x21, 0x90, 0x80, 0xc1, 0x3e, + /*1fd0:*/ 0x1f, 0xae, 0xdd, 0xb8, 0x5a, 0x17, 0x86, 0x9a, 0xdf, 0xec, 0xde, 0xaa, 0x48, 0x99, 0x4b, 0xd9, + /*1fe0:*/ 0xa8, 0x9b, 0xbc, 0x34, 0x65, 0x30, 0x1a, 0x72, 0xf4, 0x69, 0xee, 0x81, 0x06, 0x86, 0xbe, 0x65, + /*1ff0:*/ 0x74, 0x22, 0xdc, 0x45, 0x61, 0x4d, 0x11, 0x16, 0x94, 0xc3, 0xaf, 0x31, 0xf2, 0x2e, 0x7e, 0x0a, + /*2000:*/ 0xe9, 0xcc, 0x15, 0x55, 0xdd, 0x5c, 0x4b, 0xc8, 0xe6, 0x54, 0x65, 0x71, 0x96, 0xb6, 0x05, 0xa1, + /*2010:*/ 0xf6, 0x12, 0xf5, 0x2e, 0xbd, 0x04, 0x7d, 0xc9, 0xb6, 0xe1, 0x40, 0x64, 0x35, 0x33, 0x2e, 0x1e, + /*2020:*/ 0xfd, 0xcb, 0x48, 0x03, 0xc1, 0x90, 0x27, 0x65, 0x2c, 0xa5, 0x3b, 0xba, 0x99, 0x89, 0x1d, 0x63, + /*2030:*/ 0x27, 0x31, 0xa4, 0x45, 0x7a, 0x5d, 0xbb, 0x67, 0xea, 0x3e, 0x3d, 0x03, 0x71, 0x8b, 0xda, 0x94, + /*2040:*/ 0xc6, 0x09, 0xb6, 0xfb, 0x87, 0x2e, 0x50, 0x67, 0x04, 0x3d, 0xf0, 0x54, 0xd8, 0xcb, 0xee, 0x74, + /*2050:*/ 0x59, 0x15, 0x9a, 0x40, 0xb2, 0xf1, 0xae, 0xa2, 0x9c, 0x76, 0x6b, 0x2b, 0x70, 0xc8, 0xe9, 0x20, + /*2060:*/ 0x95, 0x16, 0xb8, 0xb2, 0x7e, 0x43, 0xd7, 0x5b, 0x3d, 0xce, 0x82, 0x22, 0x61, 0xff, 0x64, 0x14, + /*2070:*/ 0xcc, 0x7e, 0xf8, 0x73, 0x5e, 0x72, 0xf3, 0xfc, 0xea, 0xbf, 0x44, 0xc4, 0x1b, 0x25, 0xd1, 0xbd, + /*2080:*/ 0x95, 0x3a, 0xb0, 0x1b, 0x1f, 0xfa, 0x7b, 0xbe, 0x52, 0x80, 0x21, 0xb6, 0x22, 0x0b, 0x9c, 0x38, + /*2090:*/ 0x3d, 0xbb, 0xae, 0x2f, 0xd8, 0xaf, 0x45, 0x00, 0x47, 0x44, 0xcd, 0x6a, 0x66, 0x8c, 0xc5, 0x35, + /*20a0:*/ 0xfd, 0x6d, 0xe4, 0xf5, 0xfa, 0xfa, 0x00, 0xff, 0x96, 0xdb, 0x91, 0xad, 0x00, 0x05, 0xbe, 0x99, + /*20b0:*/ 0xa0, 0x15, 0x4d, 0xb6, 0xb5, 0x26, 0xc4, 0x82, 0xa9, 0xd4, 0xbc, 0x2f, 0xe1, 0x85, 0x18, 0xd0, + /*20c0:*/ 0xa7, 0xdc, 0xbe, 0x53, 0x84, 0xac, 0x2a, 0xc3, 0xf9, 0x8c, 0x01, 0x6e, 0xdb, 0x3e, 0x7a, 0xf4, + /*20d0:*/ 0x0b, 0xf3, 0x82, 0x34, 0x4d, 0x8a, 0x67, 0x0a, 0x68, 0x5c, 0x87, 0xd5, 0x12, 0x11, 0xf7, 0xd0, + /*20e0:*/ 0xf2, 0xd7, 0x3c, 0x2c, 0x7a, 0xf6, 0xee, 0x3a, 0x7f, 0xa3, 0x66, 0xb4, 0x76, 0x5e, 0x2b, 0x14, + /*20f0:*/ 0x17, 0xdc, 0x28, 0x89, 0xa4, 0xba, 0x8e, 0x66, 0x82, 0x18, 0xfe, 0x04, 0xcc, 0x44, 0xf8, 0xd9, + /*2100:*/ 0x76, 0x30, 0x30, 0xad, 0x4c, 0xa0, 0x5f, 0x8a, 0x7b, 0x59, 0x07, 0xb9, 0x1f, 0xdc, 0x88, 0xac, + /*2110:*/ 0xbf, 0xcb, 0x8d, 0x64, 0x34, 0x01, 0xd6, 0xb1, 0x03, 0xd7, 0xa8, 0x0b, 0x2f, 0xee, 0x98, 0x8d, + /*2120:*/ 0x18, 0x9f, 0x19, 0xf4, 0xc3, 0x9c, 0x44, 0x9a, 0x2b, 0xdf, 0x88, 0x79, 0xad, 0x0f, 0x13, 0x3e, + /*2130:*/ 0xd7, 0xb9, 0x5c, 0x50, 0xed, 0x0c, 0xda, 0xb0, 0xb6, 0x6e, 0xdb, 0x6d, 0x03, 0x31, 0xc6, 0x97, + /*2140:*/ 0xac, 0x8f, 0x9c, 0x2d, 0x16, 0x88, 0x72, 0x49, 0x82, 0x99, 0xc0, 0x71, 0x59, 0x27, 0xb6, 0x39, + /*2150:*/ 0xc8, 0x30, 0x56, 0x8e, 0x8f, 0xa2, 0xa5, 0xbe, 0xc4, 0x01, 0x1e, 0x12, 0x42, 0xab, 0xd1, 0x9c, + /*2160:*/ 0x4c, 0x34, 0xef, 0x87, 0x36, 0xf2, 0xce, 0xde, 0xf5, 0x23, 0x71, 0x12, 0x7e, 0xb6, 0x8e, 0x25, + /*2170:*/ 0x82, 0x7d, 0xd6, 0xac, 0x07, 0xbb, 0x01, 0xfc, 0x9d, 0x14, 0xdf, 0x24, 0x38, 0x7c, 0xd8, 0x42, + /*2180:*/ 0x3a, 0xf9, 0xb1, 0xfd, 0x66, 0x9f, 0x7c, 0x47, 0x9d, 0x57, 0x3b, 0x75, 0x44, 0x63, 0xe8, 0x4c, + /*2190:*/ 0x7c, 0xf2, 0xfc, 0xec, 0x43, 0x83, 0x87, 0xd3, 0x13, 0x73, 0x33, 0x98, 0x7d, 0x33, 0x0b, 0x4b, + /*21a0:*/ 0x44, 0xb2, 0xc1, 0x9c, 0xb3, 0x03, 0x67, 0x80, 0xef, 0x95, 0x06, 0xe0, 0xbb, 0xe1, 0xe5, 0x33, + /*21b0:*/ 0x21, 0x73, 0x1f, 0x91, 0xf1, 0x14, 0xdc, 0x9e, 0x53, 0xe3, 0x14, 0x85, 0x43, 0x1e, 0xaa, 0x5d, + /*21c0:*/ 0x08, 0x7b, 0x28, 0x8d, 0x43, 0x27, 0xec, 0x2d, 0xab, 0xe7, 0xe2, 0x09, 0xc9, 0x15, 0x1a, 0x87, + /*21d0:*/ 0x58, 0xa6, 0xfe, 0x35, 0xd0, 0xd9, 0x87, 0x39, 0x7e, 0xae, 0xc2, 0x91, 0x0a, 0x0f, 0xf3, 0x48, + /*21e0:*/ 0xe2, 0x5d, 0x4c, 0x1a, 0x56, 0xbb, 0x74, 0x8e, 0x9f, 0x25, 0xf0, 0x90, 0x46, 0xcf, 0x50, 0x35, + /*21f0:*/ 0x7a, 0x59, 0xe1, 0x6a, 0xd4, 0x24, 0x97, 0x4a, 0xca, 0xdb, 0xbd, 0x83, 0xd9, 0xa9, 0x6a, 0xae, + /*2200:*/ 0xea, 0x46, 0x97, 0x14, 0xdd, 0xaf, 0x46, 0x79, 0x98, 0xb7, 0x20, 0xf2, 0x3e, 0x98, 0xd8, 0x6c, + /*2210:*/ 0xc5, 0x57, 0x5d, 0xed, 0x08, 0xda, 0x0f, 0x98, 0x06, 0xd8, 0xdc, 0x2c, 0x28, 0x8d, 0xc5, 0x21, + /*2220:*/ 0x33, 0xc1, 0xc4, 0x2d, 0x1e, 0x85, 0x7b, 0x82, 0x12, 0x74, 0x78, 0x2b, 0xf5, 0x0b, 0x77, 0xeb, + /*2230:*/ 0xc8, 0x6f, 0x42, 0x83, 0xe2, 0x19, 0x25, 0x6b, 0xff, 0x92, 0xb7, 0x63, 0x82, 0xae, 0xc9, 0x0d, + /*2240:*/ 0xa0, 0xc3, 0x64, 0x6f, 0x13, 0x8c, 0xf2, 0x8a, 0xa2, 0xb6, 0x57, 0x99, 0x2e, 0x92, 0xa6, 0x3c, + /*2250:*/ 0xa1, 0x86, 0x05, 0x76, 0x4f, 0x55, 0x5d, 0x2b, 0x3c, 0x28, 0x30, 0x00, 0x51, 0x5e, 0xa1, 0x90, + /*2260:*/ 0x35, 0x0b, 0x78, 0xb6, 0x04, 0x82, 0xca, 0xe0, 0x3e, 0xb9, 0xe0, 0x12, 0x19, 0x62, 0xfd, 0x05, + /*2270:*/ 0x81, 0xd7, 0x78, 0xb9, 0x23, 0x14, 0xe3, 0xb3, 0x4d, 0xac, 0x97, 0x80, 0xac, 0x4c, 0x98, 0xea, + /*2280:*/ 0x60, 0x89, 0x62, 0x8b, 0xc0, 0xd2, 0x37, 0x5c, 0x5a, 0x63, 0xcf, 0x7a, 0x55, 0x3a, 0x67, 0xeb, + /*2290:*/ 0xec, 0xcb, 0xd6, 0xf7, 0x39, 0x33, 0xf0, 0x6e, 0x4c, 0x8c, 0x0f, 0x75, 0x60, 0x5a, 0x5f, 0x08, + /*22a0:*/ 0x52, 0x93, 0x86, 0x50, 0xf3, 0xf1, 0x99, 0x9f, 0x3a, 0x02, 0x9e, 0xe8, 0xca, 0xe7, 0x95, 0x47, + /*22b0:*/ 0xb0, 0x37, 0x4e, 0xa1, 0x53, 0xc8, 0xaf, 0xb6, 0x6e, 0x55, 0xdf, 0xf8, 0x7d, 0xf2, 0xe7, 0x36, + /*22c0:*/ 0xc2, 0xf8, 0xbc, 0x54, 0xe7, 0x01, 0x13, 0x6b, 0x3f, 0xcc, 0xd0, 0x84, 0xe4, 0xac, 0xd8, 0x0a, + /*22d0:*/ 0x26, 0x2f, 0x82, 0xe1, 0xce, 0x3d, 0x60, 0xe4, 0xb9, 0xb2, 0xad, 0xd9, 0x9c, 0x4c, 0x2f, 0xa3, + /*22e0:*/ 0x2b, 0x37, 0x8f, 0x0d, 0x65, 0x38, 0xc5, 0x76, 0xca, 0x97, 0xa1, 0x64, 0xca, 0x3c, 0x14, 0xb6, + /*22f0:*/ 0xb3, 0x68, 0xaf, 0xb2, 0x47, 0x66, 0x4b, 0x85, 0x21, 0x1e, 0xa2, 0x60, 0xd7, 0x85, 0x8a, 0x9b, + /*2300:*/ 0x35, 0x0e, 0xd8, 0x20, 0x12, 0x8b, 0xca, 0x25, 0x17, 0xc4, 0x57, 0xb8, 0x6a, 0x6f, 0xac, 0xa9, + /*2310:*/ 0xf4, 0xe9, 0x3c, 0xc1, 0x05, 0x4a, 0x8c, 0x5c, 0xba, 0xbb, 0x82, 0xe7, 0xa7, 0xd0, 0x58, 0x44, + /*2320:*/ 0x13, 0x86, 0xac, 0x3c, 0x63, 0x9b, 0xa8, 0xb5, 0x56, 0x13, 0x55, 0xce, 0xc3, 0xd3, 0x29, 0xec, + /*2330:*/ 0x96, 0x27, 0x17, 0xde, 0x8a, 0xec, 0x31, 0x56, 0x6e, 0x3b, 0xfa, 0x4e, 0xa9, 0x51, 0x9c, 0x1c, + /*2340:*/ 0x67, 0x70, 0xbb, 0xc7, 0x50, 0x2d, 0xfb, 0xc9, 0x21, 0x64, 0x4c, 0xdd, 0xe7, 0xd2, 0x57, 0xfe, + /*2350:*/ 0x09, 0x12, 0x0d, 0xe7, 0x5b, 0x0f, 0x81, 0x21, 0x13, 0x44, 0x2f, 0x57, 0xab, 0xe8, 0xac, 0xf6, + /*2360:*/ 0x02, 0x23, 0x3d, 0xa1, 0x4f, 0xf5, 0x54, 0x20, 0xe2, 0x82, 0x4d, 0xf4, 0x22, 0x15, 0xc5, 0x70, + /*2370:*/ 0xf7, 0x9d, 0xd7, 0x3b, 0xb5, 0x30, 0x82, 0x94, 0x47, 0x26, 0xba, 0xb1, 0x15, 0xe6, 0x7c, 0xba, + /*2380:*/ 0xb0, 0xcd, 0xd2, 0xe6, 0x69, 0x52, 0x35, 0x0b, 0x77, 0x78, 0xd2, 0x65, 0x7c, 0xa3, 0xba, 0x56, + /*2390:*/ 0x61, 0xa0, 0xb1, 0x93, 0x83, 0xa1, 0x28, 0x23, 0x37, 0xb5, 0x1f, 0x56, 0x64, 0xdc, 0x66, 0x02, + /*23a0:*/ 0x22, 0x2d, 0xa7, 0x14, 0x77, 0x3e, 0xc0, 0xdb, 0x5c, 0x84, 0x63, 0x0f, 0xea, 0x37, 0x36, 0x34, + /*23b0:*/ 0xab, 0xab, 0x99, 0x5b, 0x81, 0x37, 0x22, 0xa5, 0x94, 0xe5, 0xf2, 0x79, 0x2f, 0x45, 0xc7, 0xc9, + /*23c0:*/ 0xa7, 0xfa, 0x6d, 0xbe, 0x02, 0x99, 0x2e, 0xeb, 0x6c, 0xc8, 0xc3, 0x24, 0x48, 0xbc, 0x9b, 0x4e, + /*23d0:*/ 0x13, 0x05, 0xfe, 0x9f, 0x67, 0xe7, 0x62, 0xc3, 0x74, 0x6d, 0x24, 0xf9, 0x42, 0x71, 0x77, 0x85, + /*23e0:*/ 0x4f, 0xb4, 0xba, 0x77, 0xbc, 0xdc, 0x49, 0x94, 0x73, 0x24, 0xe1, 0x62, 0xe1, 0xee, 0x8f, 0xd1, + /*23f0:*/ 0xa1, 0x7a, 0x72, 0x40, 0xba, 0x5e, 0x8c, 0x60, 0x31, 0x6e, 0x5d, 0x71, 0x15, 0x42, 0xf9, 0x70, + /*2400:*/ 0x61, 0x88, 0x08, 0x72, 0xa7, 0x03, 0x92, 0x3d, 0xc0, 0x0f, 0xed, 0x11, 0xf9, 0x32, 0xbe, 0x42, + /*2410:*/ 0x03, 0xb3, 0xb9, 0x15, 0xe1, 0x50, 0x00, 0xcf, 0xcd, 0x19, 0x19, 0x82, 0x32, 0x39, 0x43, 0x1a, + /*2420:*/ 0x54, 0xbd, 0xf4, 0xd8, 0x47, 0xe1, 0x01, 0x7a, 0xf5, 0xdb, 0x6f, 0xae, 0xad, 0xd4, 0x52, 0x6a, + /*2430:*/ 0xe0, 0x98, 0xa8, 0x8e, 0x1b, 0x1c, 0x54, 0x75, 0x6f, 0x71, 0x53, 0xbd, 0xea, 0x26, 0x78, 0x50, + /*2440:*/ 0x7b, 0x10, 0xe5, 0x5b, 0x56, 0xe4, 0xd8, 0x47, 0x20, 0xf8, 0x39, 0xb5, 0x29, 0xab, 0x99, 0x66, + /*2450:*/ 0xe9, 0xc9, 0xa2, 0x30, 0x8e, 0x14, 0xfc, 0x2c, 0x14, 0xdc, 0xba, 0xc9, 0x8a, 0xa1, 0x06, 0xab, + /*2460:*/ 0xfd, 0xc8, 0x93, 0x52, 0x26, 0x44, 0xf6, 0x0d, 0xc9, 0x46, 0x8a, 0x4e, 0x0b, 0x96, 0x98, 0x4d, + /*2470:*/ 0xf3, 0x71, 0x8f, 0xdf, 0x02, 0x2a, 0xa6, 0x8b, 0xe7, 0x6d, 0x6c, 0x80, 0x18, 0x21, 0x3c, 0x7c, + /*2480:*/ 0x6f, 0xc0, 0xb6, 0xea, 0x5d, 0x78, 0xb5, 0x46, 0xf9, 0x27, 0xfa, 0x4f, 0xd3, 0xbe, 0x83, 0xe2, + /*2490:*/ 0xaa, 0x26, 0xee, 0x71, 0x86, 0x5d, 0xf1, 0x05, 0x15, 0x97, 0x98, 0x0a, 0xdd, 0xa3, 0x67, 0x93, + /*24a0:*/ 0x50, 0xc1, 0x1a, 0xa7, 0xd1, 0xa0, 0xcd, 0xa4, 0xfe, 0xfa, 0x5a, 0x0e, 0x34, 0x64, 0x4c, 0x00, + /*24b0:*/ 0x41, 0xfc, 0x6e, 0x8c, 0x65, 0x60, 0xa5, 0xe9, 0xea, 0xc1, 0xd2, 0xed, 0x27, 0xd1, 0x3c, 0x87, + /*24c0:*/ 0xbb, 0xdd, 0xc8, 0xfa, 0x10, 0xa4, 0x90, 0x68, 0x4d, 0x8c, 0x9f, 0x3d, 0x47, 0x41, 0x1e, 0x38, + /*24d0:*/ 0x55, 0x7a, 0x02, 0xb5, 0xfc, 0xea, 0xcc, 0x33, 0x15, 0x62, 0xa3, 0x0c, 0x16, 0x39, 0x3a, 0x1d, + /*24e0:*/ 0xfd, 0x6d, 0x89, 0xb2, 0x93, 0x18, 0xb1, 0xfb, 0x74, 0x2b, 0x58, 0x6e, 0x2e, 0xa3, 0x0a, 0xfc, + /*24f0:*/ 0xed, 0x5e, 0xc9, 0xfc, 0xda, 0xdc, 0x61, 0xf1, 0x1b, 0xdc, 0x8b, 0xd6, 0x19, 0x3d, 0x3f, 0x68, + /*2500:*/ 0x90, 0x83, 0x19, 0x79, 0xe7, 0xfe, 0x11, 0x14, 0xf7, 0xe7, 0x3d, 0x94, 0x08, 0x60, 0xbd, 0xaa, + /*2510:*/ 0xdd, 0x87, 0xd0, 0xf4, 0xd2, 0xf5, 0xe4, 0x90, 0xa8, 0x73, 0xae, 0xb6, 0xb3, 0x8a, 0xc1, 0x36, + /*2520:*/ 0xa1, 0x1a, 0x03, 0x7c, 0xbe, 0x9d, 0xcb, 0xbc, 0x3a, 0x0f, 0x16, 0x54, 0xdb, 0xd6, 0xb4, 0x84, + /*2530:*/ 0x79, 0xe3, 0x95, 0xee, 0x5a, 0x65, 0x88, 0x1a, 0x68, 0x82, 0xc1, 0x32, 0x47, 0x94, 0x4a, 0x8b, + /*2540:*/ 0xb8, 0x1b, 0xa4, 0x77, 0x49, 0x65, 0x51, 0xbb, 0xbd, 0x0c, 0xd2, 0x7b, 0xbd, 0xff, 0xd9, 0x72, + /*2550:*/ 0x2e, 0x37, 0xc2, 0xc0, 0xf0, 0x03, 0xc7, 0x13, 0x46, 0xef, 0x7b, 0xa1, 0xf1, 0xa5, 0xbd, 0x1f, + /*2560:*/ 0x0e, 0x2f, 0x4e, 0x20, 0x51, 0xc7, 0x54, 0x57, 0x84, 0x78, 0xac, 0x7b, 0xc9, 0xe1, 0x8d, 0x66, + /*2570:*/ 0x51, 0x12, 0x79, 0x7c, 0x9c, 0x3d, 0xe2, 0xf3, 0x8e, 0x6b, 0x77, 0x84, 0x47, 0x14, 0x4d, 0x87, + /*2580:*/ 0xac, 0xa0, 0x9a, 0x5f, 0xd7, 0x4f, 0x18, 0x44, 0x8e, 0x96, 0x6f, 0xf4, 0xf0, 0x45, 0x73, 0x36, + /*2590:*/ 0x34, 0xa5, 0xaa, 0x24, 0xec, 0xde, 0x68, 0xa3, 0xda, 0x9e, 0xfc, 0x19, 0xba, 0x0e, 0x31, 0x80, + /*25a0:*/ 0x20, 0xad, 0x73, 0x0c, 0x35, 0x2d, 0x5f, 0x50, 0x41, 0x58, 0x02, 0xb6, 0x4c, 0xeb, 0xcf, 0xa1, + /*25b0:*/ 0x6e, 0x54, 0x66, 0xf9, 0xfb, 0xfa, 0x73, 0x48, 0x53, 0x9d, 0xbc, 0x7b, 0xe4, 0x6e, 0xad, 0xa7, + /*25c0:*/ 0x68, 0x6c, 0x3a, 0xed, 0xd9, 0x01, 0x49, 0xbe, 0xe8, 0x03, 0x36, 0xb6, 0x06, 0x2f, 0xfc, 0xfa, + /*25d0:*/ 0x5c, 0xd1, 0xe2, 0x4d, 0x62, 0xdc, 0x1c, 0xb8, 0x9b, 0xfc, 0x6e, 0x26, 0x3c, 0x38, 0xc3, 0x3d, + /*25e0:*/ 0xe0, 0x52, 0x61, 0x10, 0x34, 0x97, 0x15, 0x3f, 0xa9, 0xdc, 0xc2, 0xad, 0x32, 0xf7, 0x3d, 0x70, + /*25f0:*/ 0xe7, 0xf1, 0x2e, 0xe8, 0x1e, 0xbd, 0x8e, 0x90, 0xfb, 0x22, 0x73, 0xde, 0xe7, 0xb8, 0x9c, 0xce, + /*2600:*/ 0x9b, 0x89, 0xd3, 0x51, 0xfd, 0xe9, 0x07, 0xbe, 0x32, 0x14, 0x04, 0x22, 0xf8, 0x73, 0x75, 0x39, + /*2610:*/ 0x6d, 0x77, 0x21, 0x58, 0x5e, 0x64, 0x98, 0x36, 0x67, 0xc4, 0xed, 0x70, 0x25, 0xf7, 0x79, 0x12, + /*2620:*/ 0x53, 0xa8, 0xff, 0x59, 0x0b, 0xb7, 0xe0, 0x78, 0x35, 0xe5, 0x47, 0x70, 0xd9, 0xc5, 0x13, 0xe7, + /*2630:*/ 0xda, 0xa9, 0x09, 0xc9, 0x17, 0x68, 0x58, 0xb8, 0xbc, 0xa3, 0xf3, 0xf6, 0x02, 0xda, 0x35, 0x93, + /*2640:*/ 0x7f, 0xf2, 0x4e, 0x5f, 0x2f, 0xf2, 0x30, 0xca, 0xce, 0x23, 0xb3, 0x13, 0xff, 0xa3, 0xd6, 0x76, + /*2650:*/ 0xf8, 0xd5, 0xb8, 0xad, 0x52, 0xe3, 0x55, 0x15, 0x6e, 0x3b, 0x61, 0x5e, 0x25, 0x97, 0xda, 0x62, + /*2660:*/ 0xe6, 0x5a, 0x1a, 0xc3, 0x2e, 0x5d, 0xcd, 0xb9, 0x41, 0xe3, 0x72, 0x0b, 0x12, 0x94, 0x95, 0x08, + /*2670:*/ 0x06, 0x86, 0x45, 0xf9, 0x38, 0x8d, 0x41, 0xf6, 0x3e, 0x84, 0x6d, 0x06, 0xfb, 0x41, 0x55, 0x0d, + /*2680:*/ 0x8e, 0x31, 0x8d, 0x8d, 0x7c, 0x9b, 0x1e, 0x54, 0x5a, 0xac, 0xe1, 0x3e, 0xc0, 0x03, 0x36, 0x23, + /*2690:*/ 0x81, 0x13, 0xe7, 0xcc, 0x1b, 0xc3, 0x9c, 0x6a, 0xc1, 0xfc, 0xe9, 0x9c, 0x20, 0xa0, 0x4a, 0x84, + /*26a0:*/ 0x0f, 0x17, 0xcc, 0xf1, 0xb6, 0xcc, 0xf9, 0x5e, 0x52, 0x0a, 0x70, 0x03, 0x24, 0x73, 0x65, 0x5b, + /*26b0:*/ 0x28, 0x8d, 0xe5, 0x99, 0x8e, 0x47, 0xfd, 0x75, 0x63, 0xd6, 0x6a, 0x16, 0xe7, 0xa8, 0x27, 0x44, + /*26c0:*/ 0x76, 0xf6, 0x81, 0xf9, 0xec, 0x37, 0x49, 0x5b, 0x50, 0x19, 0x11, 0x8e, 0xe4, 0x21, 0x6f, 0xca, + /*26d0:*/ 0xd3, 0x91, 0xb7, 0x2d, 0x91, 0x1b, 0x99, 0x19, 0xb6, 0xfb, 0xcd, 0xb6, 0xe4, 0x11, 0xd3, 0x26, + /*26e0:*/ 0x70, 0xa9, 0x3f, 0x3e, 0x81, 0x66, 0x8c, 0x97, 0xce, 0xe8, 0x98, 0x0a, 0x55, 0x57, 0x7f, 0x14, + /*26f0:*/ 0x8b, 0x9d, 0xb5, 0x81, 0x3b, 0x61, 0x25, 0x5e, 0xa0, 0xda, 0xcc, 0x64, 0xf1, 0xe2, 0xe4, 0xa0, + /*2700:*/ 0x86, 0xdb, 0xec, 0x17, 0x94, 0x06, 0xe8, 0xa3, 0x6d, 0x65, 0xd7, 0x0e, 0xda, 0x42, 0xfa, 0x65, + /*2710:*/ 0x2f, 0x86, 0xde, 0xb3, 0x0c, 0x85, 0x46, 0xb2, 0x5f, 0x43, 0x40, 0xc7, 0x06, 0xfc, 0xd7, 0xbc, + /*2720:*/ 0x13, 0x3d, 0x1e, 0x7c, 0xfe, 0x21, 0x92, 0x51, 0xcd, 0xb6, 0xf2, 0xdd, 0xf2, 0xf1, 0x63, 0x3d, + /*2730:*/ 0x23, 0x81, 0xd4, 0x82, 0x2e, 0x7b, 0x7d, 0x9b, 0xa4, 0x45, 0x30, 0xf5, 0xbf, 0x32, 0x01, 0xbd, + /*2740:*/ 0xda, 0x6e, 0xb6, 0x43, 0xbc, 0xb3, 0xf2, 0xbb, 0x7c, 0x99, 0xcc, 0x84, 0xc2, 0x32, 0x89, 0xe9, + /*2750:*/ 0xfa, 0xeb, 0x75, 0x52, 0x77, 0xc2, 0xf4, 0x18, 0x1f, 0x16, 0xef, 0x3a, 0xcd, 0xef, 0xce, 0x7f, + /*2760:*/ 0x69, 0xcf, 0x0d, 0x50, 0xa4, 0xc6, 0x17, 0xf8, 0x00, 0x28, 0xed, 0xa6, 0x98, 0x97, 0xb8, 0x42, + /*2770:*/ 0xae, 0xc1, 0x43, 0x4d, 0x00, 0x0c, 0x41, 0x67, 0xf1, 0xe5, 0xed, 0x28, 0x75, 0x64, 0x27, 0x57, + /*2780:*/ 0x0a, 0x42, 0xa0, 0x9f, 0x81, 0x6b, 0xf4, 0xa8, 0x4a, 0x92, 0xe4, 0xf4, 0xe2, 0x02, 0x5d, 0xf1, + /*2790:*/ 0x2c, 0xe6, 0x61, 0x2d, 0xc8, 0x73, 0x24, 0x58, 0xb9, 0x52, 0x8c, 0x3d, 0x69, 0x5f, 0xc4, 0xc5, + /*27a0:*/ 0x7c, 0x76, 0x40, 0x0f, 0x27, 0x98, 0x30, 0x34, 0xc7, 0xb3, 0x9f, 0x8c, 0xa2, 0x59, 0x90, 0x60, + /*27b0:*/ 0xe5, 0xbe, 0x1c, 0x06, 0xc5, 0x7e, 0x3b, 0xce, 0x8c, 0x18, 0x19, 0x52, 0xe5, 0x20, 0xc9, 0x58, + /*27c0:*/ 0xea, 0x6b, 0x24, 0x44, 0x8f, 0x8d, 0x41, 0xbc, 0xb7, 0xd9, 0x7d, 0x38, 0xc5, 0xf9, 0xe4, 0x8d, + /*27d0:*/ 0xf6, 0x7a, 0x01, 0x3d, 0x0f, 0x9c, 0xf3, 0x55, 0x54, 0x78, 0xa8, 0xb8, 0x2e, 0x4f, 0xfd, 0x4e, + /*27e0:*/ 0xc7, 0xea, 0x78, 0xbc, 0xa3, 0x35, 0xa6, 0x8a, 0x70, 0xfb, 0xef, 0xb0, 0x5e, 0x72, 0x91, 0x3e, + /*27f0:*/ 0x43, 0xc0, 0xb0, 0x1e, 0x7a, 0x3a, 0xcd, 0xa1, 0xfd, 0x02, 0x6b, 0x55, 0xc1, 0xd2, 0x3a, 0xd1, + /*2800:*/ 0x65, 0x71, 0x5d, 0x2c, 0x57, 0xce, 0x15, 0xec, 0x08, 0xb0, 0x83, 0xf0, 0xac, 0x4f, 0x10, 0xa0, + /*2810:*/ 0x80, 0xc3, 0x64, 0x82, 0x87, 0xb4, 0x99, 0x83, 0xd3, 0x3b, 0x21, 0x03, 0xbc, 0xa3, 0x8a, 0x4f, + /*2820:*/ 0xcb, 0x72, 0x0f, 0x13, 0x55, 0xb8, 0x50, 0x30, 0x8a, 0xc7, 0x3e, 0xc8, 0x1b, 0xd2, 0x80, 0xec, + /*2830:*/ 0x87, 0x25, 0x4f, 0x9f, 0x19, 0xd6, 0x3f, 0xfc, 0x7b, 0xed, 0x1b, 0x8b, 0xa8, 0x27, 0x82, 0xa2, + /*2840:*/ 0x67, 0xae, 0xed, 0xd9, 0x1d, 0xba, 0x29, 0x2c, 0xd2, 0x11, 0x6a, 0xbd, 0x98, 0x0a, 0xca, 0x16, + /*2850:*/ 0xaf, 0xe6, 0x80, 0x10, 0xe4, 0x3c, 0x0e, 0xd2, 0xd2, 0xfe, 0x4a, 0x71, 0x1f, 0x6e, 0x6e, 0xf4, + /*2860:*/ 0xf5, 0x4a, 0x27, 0xf8, 0xb8, 0x6a, 0xf1, 0x47, 0xbe, 0xfe, 0x48, 0x31, 0x87, 0xd1, 0x31, 0x1d, + /*2870:*/ 0x6e, 0x64, 0xde, 0x2a, 0x50, 0xb6, 0x47, 0xf2, 0x35, 0xd7, 0x97, 0x70, 0x2a, 0xf7, 0xf1, 0xa7, + /*2880:*/ 0x14, 0x57, 0x09, 0x45, 0xa9, 0x64, 0x6b, 0x3f, 0x98, 0xc7, 0xe9, 0xf4, 0x5f, 0x74, 0xe4, 0x44, + /*2890:*/ 0x34, 0xce, 0x4a, 0x60, 0x80, 0x6c, 0xe7, 0x88, 0xc9, 0xab, 0x26, 0x5a, 0xc4, 0x5f, 0xe3, 0x09, + /*28a0:*/ 0x2d, 0xc8, 0x95, 0xae, 0xfc, 0x8e, 0xdf, 0xc9, 0x3c, 0x65, 0x5c, 0xf5, 0x7c, 0x04, 0x20, 0xcb, + /*28b0:*/ 0x22, 0xb7, 0x6b, 0x91, 0xc3, 0x2d, 0xa0, 0x25, 0xc2, 0x69, 0x7b, 0x3d, 0x86, 0x1a, 0x20, 0x49, + /*28c0:*/ 0x8d, 0x42, 0xc1, 0xc4, 0x9a, 0x1f, 0xf3, 0x3f, 0x52, 0xf0, 0xf1, 0xe2, 0x5c, 0xf0, 0x37, 0x12, + /*28d0:*/ 0x99, 0x13, 0x21, 0x70, 0x39, 0x7c, 0x74, 0x22, 0xff, 0xc6, 0xc6, 0x0c, 0xbc, 0xf6, 0x8d, 0x72, + /*28e0:*/ 0xeb, 0xa4, 0x13, 0x79, 0xd7, 0x23, 0xa8, 0xdb, 0x59, 0x7b, 0x70, 0xfd, 0x06, 0xf5, 0x6c, 0x53, + /*28f0:*/ 0xe5, 0x04, 0x74, 0xa7, 0xc8, 0xb6, 0xe6, 0x95, 0x99, 0x95, 0x89, 0x55, 0xc7, 0xdd, 0xc9, 0x45, + /*2900:*/ 0xb5, 0x88, 0xc7, 0xbd, 0x0d, 0x52, 0xf0, 0x08, 0x03, 0x87, 0x9e, 0x8b, 0xe6, 0x68, 0x57, 0xde, + /*2910:*/ 0x81, 0x77, 0x92, 0x91, 0x45, 0x41, 0x3a, 0xfe, 0x2f, 0xf0, 0x2c, 0x3b, 0xed, 0x9d, 0x3e, 0xbf, + /*2920:*/ 0x4a, 0x8e, 0x7f, 0x54, 0xaa, 0x5c, 0x08, 0x84, 0x86, 0xf3, 0xc3, 0x04, 0x86, 0x2a, 0xab, 0xaf, + /*2930:*/ 0xcc, 0xac, 0xd8, 0x59, 0x7d, 0xa1, 0xd3, 0x70, 0x4f, 0xb1, 0x1b, 0x05, 0xbb, 0x61, 0x85, 0xd7, + /*2940:*/ 0x3b, 0xaf, 0x3c, 0x80, 0x2a, 0xae, 0x1b, 0xfe, 0x24, 0xb6, 0x1d, 0x23, 0x3d, 0xae, 0x39, 0x5a, + /*2950:*/ 0xe5, 0xc4, 0x23, 0x39, 0x4f, 0x4c, 0x7e, 0x83, 0x4e, 0x8a, 0x8a, 0x89, 0x5f, 0x9e, 0x28, 0x1b, + /*2960:*/ 0xd8, 0xdf, 0xb8, 0xf7, 0x0e, 0x9d, 0x83, 0x23, 0x33, 0x77, 0x09, 0x96, 0x4b, 0x3c, 0xd3, 0x34, + /*2970:*/ 0x32, 0x75, 0x8b, 0x57, 0xd0, 0x75, 0xa1, 0xbe, 0xbf, 0xaa, 0x47, 0xfd, 0x34, 0xe1, 0x8d, 0xb2, + /*2980:*/ 0x15, 0x23, 0xdb, 0x9e, 0x68, 0x87, 0x98, 0xf4, 0x50, 0xc2, 0x43, 0xaf, 0x3a, 0x76, 0xcb, 0xb8, + /*2990:*/ 0x3f, 0x8f, 0x5c, 0x0d, 0x82, 0x4d, 0x86, 0xfe, 0x53, 0x51, 0xea, 0xba, 0xf7, 0x47, 0x9f, 0xbd, + /*29a0:*/ 0xb9, 0xf3, 0xe7, 0x5c, 0x21, 0x05, 0x9f, 0xa0, 0x51, 0x53, 0xec, 0xda, 0xce, 0x5d, 0xd7, 0x54, + /*29b0:*/ 0xbb, 0x95, 0xb8, 0xf0, 0x81, 0xf5, 0x80, 0x72, 0x6c, 0x11, 0xf6, 0x50, 0x7e, 0xb6, 0x7b, 0x17, + /*29c0:*/ 0xd4, 0xd9, 0xca, 0x9f, 0x2a, 0x42, 0xef, 0x81, 0x72, 0x68, 0x21, 0x4a, 0x32, 0x41, 0xa8, 0x2b, + /*29d0:*/ 0x6b, 0xf7, 0xc2, 0x9d, 0xdc, 0x14, 0x0e, 0xfa, 0x35, 0x95, 0x7d, 0x9c, 0xb5, 0x2c, 0x52, 0xac, + /*29e0:*/ 0xf3, 0x4a, 0x82, 0x9a, 0x6b, 0xa6, 0x5a, 0x53, 0xbe, 0x75, 0x7e, 0xd7, 0x62, 0x28, 0xe1, 0x42, + /*29f0:*/ 0x1b, 0x44, 0x8c, 0xb3, 0xf7, 0x59, 0x60, 0xb4, 0x6d, 0x87, 0x89, 0xf3, 0x5b, 0xe9, 0x02, 0xee, + /*2a00:*/ 0x38, 0xdb, 0xcb, 0x3f, 0x5a, 0x99, 0x68, 0x43, 0x13, 0x62, 0x6b, 0x05, 0xd7, 0xc0, 0x81, 0x10, + /*2a10:*/ 0xbf, 0x56, 0x4e, 0x2a, 0x21, 0xe2, 0x17, 0x64, 0xfa, 0x2c, 0xc1, 0xee, 0xa0, 0xee, 0x91, 0xcb, + /*2a20:*/ 0x12, 0xaa, 0x14, 0x08, 0xc1, 0x29, 0x23, 0xb4, 0xc6, 0xaf, 0xff, 0xf8, 0x4d, 0x05, 0x6c, 0xe8, + /*2a30:*/ 0x20, 0x11, 0xdf, 0xc4, 0x0f, 0x2c, 0x49, 0xc9, 0xd3, 0xf2, 0x7d, 0x37, 0x9c, 0xc0, 0xc1, 0x99, + /*2a40:*/ 0xf5, 0xa1, 0x91, 0x10, 0x45, 0x6a, 0xf4, 0x61, 0x3e, 0x0f, 0x08, 0x4f, 0x84, 0xe9, 0x22, 0x0d, + /*2a50:*/ 0x1e, 0x78, 0x44, 0xd8, 0x31, 0x49, 0x6a, 0x31, 0x2a, 0x43, 0x5c, 0x64, 0x66, 0x43, 0x10, 0x9d, + /*2a60:*/ 0xa2, 0x74, 0x84, 0x28, 0xbf, 0x78, 0x5a, 0xfd, 0xbe, 0x2d, 0x01, 0xeb, 0x55, 0xa9, 0x41, 0x94, + /*2a70:*/ 0xd1, 0x7b, 0x72, 0x62, 0x82, 0x92, 0x64, 0xef, 0x05, 0xe9, 0xd0, 0x35, 0x3d, 0x46, 0x4d, 0xb4, + /*2a80:*/ 0x9f, 0x1e, 0x09, 0x38, 0x8c, 0x37, 0x70, 0x9e, 0xfb, 0x04, 0xa0, 0xd1, 0x49, 0x92, 0x85, 0x74, + /*2a90:*/ 0x23, 0x19, 0x41, 0xc3, 0x56, 0xf0, 0x89, 0xdf, 0x00, 0x83, 0x4b, 0xcb, 0xf1, 0x66, 0x9b, 0x8d, + /*2aa0:*/ 0x61, 0xf0, 0x6d, 0xee, 0x6b, 0x34, 0xc3, 0x88, 0x7e, 0xbf, 0x62, 0x3f, 0xe7, 0x4d, 0x85, 0x70, + /*2ab0:*/ 0xba, 0x7c, 0xe4, 0x78, 0x8f, 0xa1, 0x01, 0x58, 0x68, 0x67, 0x05, 0x36, 0x17, 0x0c, 0x4f, 0xe3, + /*2ac0:*/ 0xd4, 0x85, 0x39, 0x93, 0x8f, 0xf6, 0xd6, 0x93, 0x16, 0xd9, 0x19, 0x7c, 0xa6, 0x94, 0x76, 0xad, + /*2ad0:*/ 0xf4, 0xec, 0x5b, 0x63, 0x3d, 0x3e, 0x65, 0x29, 0x39, 0x6c, 0xa7, 0xe0, 0xbf, 0xe5, 0x64, 0x17, + /*2ae0:*/ 0xa9, 0xcb, 0xb9, 0x96, 0x58, 0x85, 0xdb, 0x55, 0x33, 0x31, 0x70, 0xac, 0x89, 0x01, 0x54, 0x83, + /*2af0:*/ 0x8d, 0x52, 0xa6, 0x6d, 0x71, 0x5f, 0x7b, 0xb6, 0x43, 0x8b, 0x44, 0x4e, 0xe4, 0x38, 0x67, 0x32, + /*2b00:*/ 0x4b, 0x5b, 0xea, 0xfd, 0xe5, 0x4c, 0x44, 0x15, 0x80, 0xde, 0x1c, 0x5d, 0x8c, 0xa5, 0xa1, 0x03, + /*2b10:*/ 0x56, 0x81, 0x78, 0x9b, 0xcc, 0x2f, 0xbb, 0x98, 0x55, 0xc8, 0x2b, 0x2c, 0x3d, 0x5a, 0x9c, 0x01, + /*2b20:*/ 0x73, 0x9f, 0x25, 0x24, 0x2a, 0xf9, 0xf0, 0x69, 0x59, 0x11, 0x7f, 0x0e, 0xa9, 0xfc, 0x14, 0x2d, + /*2b30:*/ 0x75, 0xa1, 0x24, 0xa0, 0x02, 0x29, 0x81, 0x04, 0x79, 0xfe, 0x7e, 0x99, 0x45, 0x01, 0xc0, 0xd4, + /*2b40:*/ 0x38, 0x9c, 0x9c, 0x24, 0xe8, 0x02, 0x26, 0xae, 0x10, 0x3d, 0x37, 0x33, 0xe3, 0x74, 0xd4, 0xfc, + /*2b50:*/ 0xe3, 0x82, 0x8e, 0xa2, 0x1c, 0x22, 0x8d, 0xd7, 0x94, 0xb3, 0xb3, 0x3c, 0xfc, 0xeb, 0xa9, 0x9c, + /*2b60:*/ 0xc6, 0x1c, 0x9e, 0x39, 0xaf, 0xb9, 0xfb, 0x65, 0x9a, 0xc7, 0xa3, 0xaa, 0x65, 0x23, 0x14, 0xb3, + /*2b70:*/ 0x30, 0x9f, 0x26, 0x3d, 0x44, 0x94, 0xe8, 0x44, 0xe1, 0xa8, 0x48, 0xb2, 0x6a, 0x1d, 0x2c, 0x49, + /*2b80:*/ 0xff, 0x90, 0x82, 0x9b, 0x21, 0xa9, 0xee, 0x51, 0x32, 0xfc, 0xa3, 0x77, 0x87, 0xf5, 0x1d, 0xc5, + /*2b90:*/ 0xd3, 0xb3, 0x1c, 0x25, 0x36, 0xa7, 0x23, 0xaf, 0xbf, 0x16, 0x25, 0x73, 0x91, 0x02, 0x04, 0xf7, + /*2ba0:*/ 0x4d, 0xe0, 0xa1, 0x12, 0x68, 0xa8, 0x89, 0xbe, 0x16, 0xed, 0x84, 0x18, 0x68, 0x17, 0x7b, 0x27, + /*2bb0:*/ 0x73, 0xc2, 0x07, 0xcf, 0x89, 0xdd, 0x18, 0x3c, 0x0f, 0x0c, 0x94, 0x2e, 0x9c, 0x44, 0xba, 0xf5, + /*2bc0:*/ 0x4f, 0x3b, 0xd4, 0xb7, 0x3a, 0x61, 0xd3, 0x4c, 0x1a, 0x09, 0x3c, 0x37, 0x29, 0x49, 0x8a, 0x38, + /*2bd0:*/ 0x91, 0xda, 0xb9, 0x64, 0x3c, 0xdd, 0xfe, 0x2a, 0x84, 0xb3, 0x56, 0x8c, 0xdb, 0x27, 0x73, 0x96, + /*2be0:*/ 0x5b, 0xfa, 0x89, 0x4d, 0xda, 0xd8, 0x0e, 0x72, 0x44, 0x6c, 0x66, 0x4f, 0x1a, 0x18, 0xa3, 0xf3, + /*2bf0:*/ 0xdc, 0xc0, 0x55, 0xa5, 0x25, 0x61, 0xd6, 0xf7, 0x09, 0xe1, 0xb6, 0x43, 0x4e, 0x1c, 0x6c, 0xd4, + /*2c00:*/ 0x49, 0xfe, 0x6c, 0xd1, 0xda, 0x1d, 0x53, 0xf7, 0x4e, 0x4d, 0xb2, 0x43, 0x0d, 0x98, 0x2e, 0x29, + /*2c10:*/ 0x9f, 0xd5, 0xfc, 0x21, 0x31, 0xd8, 0x74, 0x1a, 0x3b, 0xf7, 0x50, 0x06, 0x57, 0x6c, 0xbe, 0x5e, + /*2c20:*/ 0x5a, 0x29, 0xef, 0xac, 0xde, 0xf2, 0xe3, 0xad, 0x69, 0x6f, 0x67, 0x78, 0xce, 0x9f, 0xc4, 0x42, + /*2c30:*/ 0xb0, 0xac, 0xeb, 0x30, 0x7f, 0x23, 0x93, 0x86, 0xe7, 0x7d, 0x35, 0x32, 0xe3, 0x6b, 0x0e, 0x8b, + /*2c40:*/ 0x58, 0x83, 0x50, 0xe3, 0x5f, 0x12, 0xd4, 0xa7, 0xf2, 0x1b, 0xfb, 0xb1, 0xf9, 0x7e, 0x1e, 0x05, + /*2c50:*/ 0x7f, 0xec, 0x88, 0x2e, 0xd3, 0xda, 0x49, 0x3f, 0x3a, 0xc9, 0xb7, 0x3f, 0x44, 0xc5, 0xb6, 0x01, + /*2c60:*/ 0xb0, 0x6f, 0xa1, 0x3c, 0x9e, 0x44, 0x02, 0xf1, 0x11, 0x92, 0xf1, 0xd1, 0x7d, 0x2a, 0xa7, 0xc2, + /*2c70:*/ 0x7f, 0x5b, 0xc3, 0x0e, 0x03, 0xe1, 0x86, 0xf4, 0x63, 0x19, 0x15, 0xad, 0x1b, 0x0d, 0x9b, 0x04, + /*2c80:*/ 0x55, 0x49, 0xcb, 0x89, 0x85, 0x98, 0x6a, 0xd0, 0x18, 0x4d, 0xa2, 0x3e, 0x8c, 0x8b, 0x6c, 0x5b, + /*2c90:*/ 0xcf, 0xd1, 0xcb, 0xf3, 0x1a, 0x7b, 0x7b, 0x97, 0xe1, 0xa9, 0xd3, 0xcd, 0xc1, 0xbd, 0x25, 0x99, + /*2ca0:*/ 0x51, 0xde, 0x67, 0x08, 0x13, 0xa2, 0x91, 0x52, 0x4e, 0xf3, 0xca, 0xe7, 0xf3, 0xdc, 0x94, 0x1e, + /*2cb0:*/ 0x00, 0x60, 0x69, 0xfe, 0x98, 0xe9, 0x06, 0xc4, 0xf9, 0x9f, 0xdd, 0x2b, 0x25, 0x11, 0x41, 0x4f, + /*2cc0:*/ 0x7a, 0x75, 0x62, 0x4e, 0xbe, 0x00, 0x7b, 0xee, 0x38, 0x57, 0xd3, 0x5a, 0xf7, 0xc2, 0x33, 0x37, + /*2cd0:*/ 0x59, 0xe3, 0xd5, 0x20, 0x4e, 0xb1, 0x8d, 0xcf, 0x43, 0x03, 0xf3, 0x65, 0xca, 0xb6, 0xd1, 0x52, + /*2ce0:*/ 0x36, 0x8e, 0xdd, 0xb0, 0x30, 0x6c, 0xcf, 0xec, 0xe1, 0x04, 0xc1, 0x5b, 0x40, 0x7b, 0x4d, 0x02, + /*2cf0:*/ 0x91, 0x46, 0x3c, 0x90, 0x87, 0x60, 0xe4, 0x1b, 0xe0, 0xe1, 0x2c, 0xeb, 0x16, 0x6f, 0x6c, 0x72, + /*2d00:*/ 0xda, 0x71, 0x1f, 0x55, 0x3a, 0xe7, 0x52, 0x15, 0xff, 0x09, 0x4a, 0x84, 0x0c, 0xc5, 0x92, 0x69, + /*2d10:*/ 0x94, 0x5c, 0xb2, 0x15, 0x7f, 0x00, 0xe3, 0xf1, 0x43, 0x8b, 0x06, 0xa3, 0x51, 0xdf, 0xd1, 0x3c, + /*2d20:*/ 0x14, 0xe0, 0xe4, 0x18, 0xae, 0xe2, 0x56, 0x00, 0x6d, 0x04, 0xa0, 0xef, 0x21, 0xfe, 0x0e, 0xd6, + /*2d30:*/ 0x19, 0x78, 0x19, 0x98, 0xa4, 0x86, 0x6c, 0xc2, 0x39, 0x3b, 0x61, 0x33, 0xf9, 0xd9, 0xed, 0xcb, + /*2d40:*/ 0x8b, 0x14, 0x4e, 0xc2, 0x0f, 0x5d, 0xf0, 0x19, 0x0b, 0x21, 0x25, 0x61, 0x79, 0x93, 0x3d, 0x0d, + /*2d50:*/ 0xed, 0x6f, 0x1a, 0xa0, 0x19, 0xab, 0xb6, 0x56, 0xce, 0xa5, 0x51, 0xa4, 0x09, 0xf6, 0xc5, 0x95, + /*2d60:*/ 0x63, 0x85, 0x5f, 0x24, 0xd7, 0xd4, 0xba, 0x07, 0xa3, 0x62, 0x55, 0xe7, 0x3f, 0x7c, 0x3a, 0x8b, + /*2d70:*/ 0xc3, 0xc8, 0xe9, 0x94, 0x59, 0x59, 0xc9, 0x87, 0xc9, 0xc1, 0xdb, 0xb9, 0xc0, 0x13, 0xa1, 0x1e, + /*2d80:*/ 0xd4, 0x49, 0x32, 0xa3, 0x31, 0x42, 0xb4, 0x32, 0xed, 0x0a, 0xfd, 0xf4, 0xf8, 0x76, 0x01, 0x28, + /*2d90:*/ 0xaf, 0x1e, 0x7b, 0xd6, 0x7e, 0xf7, 0x05, 0x4c, 0x15, 0xee, 0x50, 0x74, 0x15, 0xbf, 0x19, 0xc7, + /*2da0:*/ 0x5e, 0xa6, 0x8d, 0xb9, 0x0d, 0xfc, 0x4a, 0xf1, 0x55, 0x4f, 0x2a, 0xea, 0x1c, 0x91, 0xdf, 0x47, + /*2db0:*/ 0xf2, 0x3a, 0xab, 0x09, 0x3a, 0x96, 0x92, 0x4b, 0xdd, 0xf7, 0x13, 0x82, 0xa1, 0x77, 0x44, 0x96, + /*2dc0:*/ 0xe2, 0x7b, 0x9d, 0xcb, 0xdd, 0x3b, 0x10, 0xf6, 0x45, 0x5b, 0xd0, 0x9e, 0xfb, 0x50, 0x10, 0x86, + /*2dd0:*/ 0x31, 0x05, 0x5c, 0x8e, 0x77, 0xb2, 0x49, 0x86, 0xe1, 0x35, 0x45, 0x65, 0x28, 0x5b, 0x05, 0xce, + /*2de0:*/ 0x4b, 0xef, 0xf2, 0x62, 0xde, 0xa3, 0x89, 0xf9, 0x8f, 0x68, 0x2a, 0x2c, 0xcd, 0x06, 0xd0, 0xb5, + /*2df0:*/ 0xb4, 0x4d, 0xa2, 0x38, 0xd1, 0x3c, 0x01, 0x13, 0x3c, 0x98, 0x8b, 0x72, 0x80, 0x4a, 0x22, 0x73, + /*2e00:*/ 0x45, 0x15, 0x5a, 0xaf, 0x27, 0x76, 0x7e, 0xd0, 0x5e, 0xad, 0x37, 0xdb, 0x59, 0xac, 0xd1, 0x11, + /*2e10:*/ 0x9e, 0xca, 0x10, 0x59, 0x29, 0x7d, 0x2f, 0xc4, 0xcb, 0x83, 0xdb, 0x96, 0x54, 0x7d, 0xa7, 0x4c, + /*2e20:*/ 0x61, 0x0b, 0x0e, 0xa1, 0xcd, 0xa5, 0x5d, 0x9c, 0x5d, 0xc7, 0x5a, 0x5d, 0x10, 0xfc, 0x43, 0x7b, + /*2e30:*/ 0x91, 0xd0, 0x2a, 0xdc, 0x9f, 0x4b, 0xeb, 0xaa, 0x53, 0xf3, 0x5a, 0x54, 0x16, 0x78, 0xd2, 0x67, + /*2e40:*/ 0x28, 0x1a, 0x39, 0x2e, 0x9a, 0x5b, 0xae, 0x7e, 0x2f, 0xc2, 0xf6, 0xa7, 0xaf, 0x8a, 0x84, 0xdf, + /*2e50:*/ 0x6b, 0xdb, 0xbc, 0xdf, 0xd7, 0x2e, 0xd5, 0x27, 0xbb, 0x31, 0x40, 0xb9, 0x54, 0xb1, 0xf9, 0x08, + /*2e60:*/ 0xdb, 0x69, 0xff, 0x2e, 0x40, 0xa9, 0x98, 0x36, 0x02, 0x24, 0x52, 0x27, 0x48, 0x5b, 0x16, 0x56, + /*2e70:*/ 0x8a, 0x2c, 0x7d, 0x15, 0xd1, 0xd8, 0xb2, 0x74, 0xbf, 0x2e, 0x65, 0x61, 0xe8, 0x1c, 0x53, 0x99, + /*2e80:*/ 0x54, 0x0a, 0xc0, 0x53, 0xc4, 0xdd, 0x62, 0x38, 0x49, 0x1a, 0xb7, 0xf1, 0xc0, 0xee, 0xf7, 0x58, + /*2e90:*/ 0xa9, 0xcd, 0xd2, 0x49, 0xcc, 0x6d, 0xee, 0x43, 0xd0, 0x0c, 0xd4, 0x4b, 0x15, 0x3d, 0x00, 0x7f, + /*2ea0:*/ 0x08, 0x29, 0x25, 0x1e, 0x13, 0xc4, 0xfa, 0x84, 0x9a, 0xbd, 0x22, 0xd9, 0xf8, 0x0f, 0xa9, 0xb6, + /*2eb0:*/ 0x13, 0x6f, 0x03, 0xd1, 0x91, 0xf7, 0x88, 0x36, 0xbd, 0xb3, 0xb1, 0x67, 0xca, 0x39, 0x4e, 0x1d, + /*2ec0:*/ 0xc7, 0xbc, 0xdf, 0xbb, 0x25, 0x1c, 0xcc, 0x59, 0xd1, 0x69, 0x9e, 0x56, 0xe3, 0x93, 0x63, 0xd5, + /*2ed0:*/ 0x44, 0xdd, 0x6b, 0x69, 0x1e, 0x51, 0xd0, 0x22, 0x69, 0x3f, 0x04, 0x43, 0xa5, 0xd6, 0x8f, 0x2f, + /*2ee0:*/ 0x6d, 0xe8, 0xd6, 0x0e, 0x3d, 0x58, 0x2a, 0x83, 0xd2, 0xee, 0x0e, 0x9d, 0x2c, 0xa8, 0xb5, 0xfa, + /*2ef0:*/ 0x65, 0x19, 0x04, 0x2d, 0x19, 0x8c, 0x07, 0xf5, 0x2f, 0x01, 0xf8, 0xc5, 0x38, 0x24, 0xd4, 0x6e, + /*2f00:*/ 0xfd, 0xd6, 0xad, 0xf6, 0xac, 0xcd, 0x92, 0x27, 0x93, 0x0b, 0xf9, 0x60, 0x22, 0x2b, 0xa2, 0xae, + /*2f10:*/ 0x86, 0x79, 0xd7, 0xd6, 0xb6, 0xad, 0x64, 0x59, 0x69, 0xe0, 0x83, 0xf3, 0xf9, 0x49, 0x19, 0x08, + /*2f20:*/ 0x9a, 0xa3, 0xfd, 0xf5, 0x92, 0x2d, 0x35, 0x06, 0x44, 0x32, 0xe7, 0xdf, 0x5e, 0x83, 0x93, 0x42, + /*2f30:*/ 0xe4, 0xf8, 0x24, 0xad, 0x65, 0x6d, 0x37, 0x58, 0x87, 0x80, 0x2b, 0xac, 0xc7, 0x27, 0xce, 0x2d, + /*2f40:*/ 0x07, 0x10, 0x7e, 0x1d, 0xa4, 0x80, 0x2c, 0x16, 0xf0, 0x3b, 0x66, 0x3d, 0x74, 0x15, 0x25, 0xe0, + /*2f50:*/ 0x46, 0xf3, 0x08, 0xbd, 0x0b, 0x6e, 0x44, 0x5a, 0xc5, 0x0e, 0x53, 0x01, 0x4b, 0x80, 0x16, 0x91, + /*2f60:*/ 0x07, 0x94, 0x8f, 0x66, 0xb9, 0x38, 0xa1, 0x44, 0xed, 0xd4, 0x44, 0x58, 0x36, 0xd2, 0x12, 0xf3, + /*2f70:*/ 0xb0, 0x41, 0x7a, 0xfa, 0xaa, 0xca, 0x35, 0xf2, 0xd6, 0x4e, 0xf7, 0x8b, 0xce, 0x9b, 0x7d, 0x67, + /*2f80:*/ 0xdc, 0xbb, 0x46, 0xc8, 0x19, 0xbf, 0x0d, 0xd0, 0x7a, 0xee, 0x10, 0xb7, 0x9c, 0x85, 0x94, 0xb4, + /*2f90:*/ 0xfd, 0x49, 0x0d, 0x77, 0x9e, 0x95, 0x0b, 0xe2, 0xd5, 0xef, 0x28, 0x08, 0xee, 0xbf, 0xf9, 0x4b, + /*2fa0:*/ 0x39, 0x74, 0x02, 0x96, 0x1a, 0x8f, 0x34, 0x8b, 0x3a, 0xd9, 0x3f, 0x63, 0xa4, 0xfd, 0x63, 0xbd, + /*2fb0:*/ 0xc6, 0xfd, 0x8f, 0x02, 0x97, 0x44, 0xbc, 0xb1, 0xe5, 0x95, 0xd0, 0x5b, 0xa8, 0x3c, 0x11, 0xd9, + /*2fc0:*/ 0x93, 0xbf, 0x66, 0x82, 0xdc, 0xdd, 0xd5, 0x99, 0xee, 0x92, 0x09, 0x8e, 0x06, 0x0e, 0x7e, 0x67, + /*2fd0:*/ 0x00, 0xb5, 0x93, 0xb3, 0x39, 0x00, 0xe2, 0xe2, 0xb7, 0xe3, 0xe0, 0x1f, 0x3e, 0xd7, 0x8a, 0xc7, + /*2fe0:*/ 0x7e, 0xa6, 0xce, 0x8b, 0x08, 0xaa, 0x9a, 0xde, 0x27, 0xd2, 0xaf, 0xca, 0x72, 0x41, 0xb0, 0x4f, + /*2ff0:*/ 0xea, 0xf5, 0x7b, 0x85, 0x46, 0x03, 0xa6, 0x1f, 0x50, 0x7f, 0x74, 0xba, 0x01, 0xae, 0x88, 0x1e, + /*3000:*/ 0x0a, 0x50, 0x71, 0xb9, 0xcc, 0x78, 0x5a, 0xdd, 0x4c, 0xad, 0x30, 0xbd, 0xe8, 0x34, 0x8a, 0xe1, + /*3010:*/ 0xaf, 0xa9, 0xeb, 0xb9, 0x22, 0x69, 0xd7, 0x30, 0x45, 0xa6, 0x06, 0xf3, 0xd6, 0x4e, 0xac, 0x19, + /*3020:*/ 0xcf, 0x12, 0x66, 0x1d, 0xd2, 0x11, 0xe1, 0xcf, 0x3c, 0x12, 0x21, 0xcd, 0x74, 0xd2, 0xba, 0x62, + /*3030:*/ 0xcc, 0x6c, 0xb9, 0x67, 0xfd, 0xc4, 0x5a, 0x94, 0xc5, 0x6f, 0x1e, 0xb7, 0x49, 0x8c, 0x24, 0x96, + /*3040:*/ 0xf1, 0x8c, 0x30, 0xb9, 0xfc, 0x2f, 0xdf, 0x9d, 0xb7, 0x6c, 0x81, 0x63, 0xf5, 0x0f, 0x1c, 0xfd, + /*3050:*/ 0x15, 0xbe, 0x0b, 0x36, 0xff, 0xa2, 0xc9, 0x07, 0x40, 0x85, 0x70, 0xe4, 0x4f, 0xb0, 0xa9, 0x11, + /*3060:*/ 0x8b, 0x8d, 0x6f, 0x74, 0x17, 0x7d, 0x4c, 0xf9, 0xc6, 0x23, 0x81, 0x56, 0x21, 0xcb, 0x99, 0x1c, + /*3070:*/ 0x31, 0x03, 0xa1, 0x05, 0x5a, 0x29, 0x9a, 0xf1, 0x2e, 0xf5, 0x07, 0xb1, 0x8b, 0x6b, 0xea, 0xb6, + /*3080:*/ 0xd0, 0xe8, 0x78, 0x93, 0xb3, 0x2d, 0xcf, 0xa6, 0xb8, 0x7e, 0xfe, 0x7c, 0x91, 0x25, 0xa6, 0xf1, + /*3090:*/ 0xc8, 0xaa, 0xff, 0xcd, 0x4a, 0xf3, 0x22, 0x62, 0x98, 0xbb, 0x95, 0xa7, 0x9e, 0xff, 0x23, 0x37, + /*30a0:*/ 0x88, 0x79, 0xbe, 0x02, 0x8e, 0x85, 0xd3, 0x8e, 0x38, 0x50, 0xab, 0x9a, 0x47, 0xa8, 0xa7, 0x1a, + /*30b0:*/ 0x22, 0x06, 0xd2, 0xcb, 0xa9, 0x49, 0xd0, 0xfc, 0xa2, 0x3f, 0xb5, 0x8c, 0x80, 0xa4, 0x65, 0xf0, + /*30c0:*/ 0x7a, 0xe0, 0xf5, 0x05, 0xf8, 0x1f, 0x75, 0x8b, 0x03, 0xa8, 0xd7, 0x45, 0xd1, 0x17, 0xf4, 0x85, + /*30d0:*/ 0x94, 0x85, 0x5a, 0xb3, 0x26, 0x52, 0x4d, 0x24, 0x45, 0x93, 0xd2, 0x19, 0x04, 0x3d, 0xb9, 0x4e, + /*30e0:*/ 0xe7, 0xac, 0x7c, 0xd3, 0x38, 0x2e, 0x13, 0xce, 0x72, 0xf7, 0x26, 0x49, 0x04, 0xd0, 0xe4, 0x9b, + /*30f0:*/ 0x0f, 0x4c, 0x91, 0x27, 0x37, 0x89, 0x20, 0x54, 0x8b, 0xf9, 0xbc, 0x46, 0xab, 0x97, 0x5d, 0xf3, + /*3100:*/ 0x8c, 0xf4, 0xdf, 0x79, 0x3d, 0x13, 0x84, 0xb1, 0x12, 0x33, 0x2d, 0x83, 0xc0, 0xb0, 0xc8, 0x77, + /*3110:*/ 0xb7, 0x2e, 0x24, 0x9d, 0xdd, 0x10, 0x31, 0x6f, 0x1b, 0xef, 0x9c, 0x20, 0xcd, 0x8d, 0x90, 0x07, + /*3120:*/ 0xbf, 0x1c, 0x6f, 0x46, 0xb6, 0x6e, 0xdd, 0x90, 0x8a, 0xf8, 0xf7, 0x14, 0xc0, 0xbe, 0xd4, 0x9b, + /*3130:*/ 0x6f, 0x2a, 0xf5, 0x37, 0xf5, 0xc9, 0x5a, 0x80, 0x5d, 0xef, 0x76, 0x99, 0x7c, 0xfd, 0xd7, 0x04, + /*3140:*/ 0xa5, 0x7b, 0xe5, 0x1e, 0x45, 0x20, 0x82, 0xaa, 0xf6, 0x4f, 0x6a, 0x34, 0xfd, 0xbe, 0x61, 0xc2, + /*3150:*/ 0x2d, 0xbc, 0x5f, 0xcc, 0x56, 0xc4, 0x4d, 0x62, 0x08, 0xcb, 0xf2, 0x2b, 0x1b, 0x79, 0xd6, 0xe3, + /*3160:*/ 0xb6, 0xc2, 0xb0, 0x98, 0xaa, 0xde, 0xb9, 0xf8, 0xf8, 0x26, 0x5e, 0xf1, 0x74, 0x61, 0x5e, 0x10, + /*3170:*/ 0xa6, 0xa7, 0x45, 0x50, 0x2b, 0x94, 0x6d, 0x0d, 0x03, 0x66, 0x81, 0xed, 0x6c, 0x30, 0x48, 0x96, + /*3180:*/ 0x56, 0xda, 0x29, 0x3d, 0x9a, 0xb1, 0xa3, 0x64, 0x1f, 0xcd, 0xc9, 0x63, 0x42, 0x01, 0x08, 0x34, + /*3190:*/ 0x1d, 0x0e, 0x92, 0xca, 0xec, 0x3f, 0x9f, 0x87, 0xda, 0x68, 0xbb, 0xf1, 0x7c, 0x47, 0xc5, 0x26, + /*31a0:*/ 0x72, 0xee, 0x46, 0x90, 0x5c, 0xa7, 0x49, 0xd8, 0xd8, 0xba, 0xd6, 0xc9, 0x52, 0x9f, 0x48, 0x38, + /*31b0:*/ 0x16, 0xd9, 0xe2, 0x99, 0x88, 0xab, 0x1f, 0xca, 0xd9, 0x63, 0xd4, 0xf2, 0x48, 0x07, 0x92, 0x45, + /*31c0:*/ 0xc9, 0xe7, 0x97, 0xdf, 0x7b, 0xf7, 0x4b, 0x69, 0x5b, 0x19, 0x3b, 0x3f, 0x79, 0xc2, 0x23, 0x90, + /*31d0:*/ 0xff, 0x84, 0x5a, 0x8a, 0xe8, 0xdf, 0xcb, 0xaf, 0x3d, 0xa0, 0x15, 0x81, 0x43, 0xc6, 0xb5, 0xd9, + /*31e0:*/ 0x68, 0xc7, 0x83, 0x0b, 0x8a, 0x77, 0x16, 0xb6, 0x75, 0x23, 0x98, 0x9d, 0x0a, 0x08, 0x47, 0x4f, + /*31f0:*/ 0x0b, 0x84, 0x21, 0xdf, 0x61, 0xd5, 0x75, 0x6a, 0x2e, 0x3d, 0x82, 0x58, 0xc6, 0xa8, 0x21, 0xa1, + /*3200:*/ 0xa6, 0x39, 0x33, 0x68, 0x31, 0x70, 0x73, 0x84, 0x15, 0x0e, 0xb5, 0x4f, 0xc4, 0x80, 0x9f, 0x10, + /*3210:*/ 0x34, 0xf5, 0x6d, 0xa6, 0x49, 0x8f, 0x85, 0x36, 0xb4, 0x4c, 0x2f, 0x1e, 0x60, 0xa6, 0xfc, 0xd6, + /*3220:*/ 0xb2, 0x48, 0x2c, 0x7b, 0xdc, 0x02, 0xc7, 0x21, 0x24, 0x47, 0x20, 0x45, 0xd6, 0xbb, 0x29, 0xf6, + /*3230:*/ 0x0d, 0x25, 0x12, 0x58, 0xfe, 0xec, 0x88, 0x29, 0x9d, 0x83, 0xe5, 0x24, 0xac, 0xa3, 0x9b, 0x1f, + /*3240:*/ 0x35, 0x58, 0xe2, 0x3a, 0xf0, 0x85, 0xe1, 0x37, 0xd4, 0x91, 0xe2, 0xbf, 0xd7, 0xf4, 0x03, 0xf2, + /*3250:*/ 0xe4, 0x9d, 0x09, 0x27, 0x95, 0x3f, 0x0e, 0x3d, 0xfd, 0xf7, 0x41, 0xee, 0xb1, 0x76, 0xe1, 0xaf, + /*3260:*/ 0xed, 0x68, 0x37, 0xd5, 0xea, 0xe8, 0x6e, 0xc6, 0x11, 0xe6, 0xd7, 0xb0, 0x59, 0x19, 0x4a, 0x83, + /*3270:*/ 0x3d, 0xec, 0x38, 0xc9, 0x5b, 0xed, 0xe8, 0xe3, 0x76, 0x03, 0xcd, 0x4a, 0x90, 0xa9, 0x21, 0xd5, + /*3280:*/ 0xf4, 0x89, 0xc2, 0x7a, 0xb7, 0xa6, 0x02, 0x40, 0x5c, 0xb7, 0xe7, 0xea, 0x3e, 0xb4, 0x3e, 0x42, + /*3290:*/ 0x81, 0x6e, 0x88, 0x87, 0x7c, 0xa1, 0x71, 0xd5, 0x08, 0x7f, 0x87, 0xa0, 0x34, 0x74, 0x4a, 0x73, + /*32a0:*/ 0x8b, 0xf6, 0xfe, 0x41, 0xc8, 0xd4, 0x1d, 0x3a, 0x1e, 0xae, 0xff, 0xf4, 0x7e, 0xfe, 0xdd, 0x44, + /*32b0:*/ 0x9a, 0x3e, 0x8f, 0x5e, 0xf1, 0xdd, 0xd2, 0x38, 0x61, 0x58, 0x1e, 0xf7, 0xcd, 0x30, 0x3d, 0x88, + /*32c0:*/ 0xc4, 0x14, 0x56, 0xb3, 0x1b, 0x68, 0x0a, 0x02, 0x58, 0x47, 0x42, 0xc6, 0xf0, 0x0c, 0x6a, 0xe9, + /*32d0:*/ 0xa4, 0x20, 0x32, 0x74, 0x5a, 0xf5, 0x54, 0xa4, 0x48, 0x61, 0x6a, 0xa8, 0x12, 0x6b, 0xd9, 0xa7, + /*32e0:*/ 0x0c, 0x6c, 0xcf, 0x74, 0x1c, 0x22, 0xe4, 0x7e, 0x94, 0xe6, 0xf6, 0x9f, 0x0f, 0x17, 0x2b, 0xb1, + /*32f0:*/ 0xf0, 0xb4, 0x3b, 0x6a, 0x98, 0xfd, 0x33, 0x56, 0x6b, 0x10, 0x3e, 0x75, 0xa8, 0x0e, 0x4a, 0x99, + /*3300:*/ 0x1c, 0xfb, 0xe4, 0x70, 0x94, 0x6f, 0xbd, 0xd9, 0x40, 0x68, 0x46, 0x1f, 0x42, 0xac, 0x6c, 0x2d, + /*3310:*/ 0x0d, 0x45, 0xb0, 0x63, 0x81, 0x15, 0xdc, 0x59, 0x54, 0x73, 0xd7, 0xcd, 0xf5, 0x39, 0x93, 0x0a, + /*3320:*/ 0x09, 0xc1, 0x6f, 0x26, 0xc2, 0x33, 0xdd, 0x31, 0x87, 0xab, 0xff, 0x93, 0x96, 0xa4, 0x27, 0xda, + /*3330:*/ 0xd3, 0x5e, 0x30, 0xb4, 0x04, 0x93, 0xd5, 0xdd, 0x83, 0x4b, 0x19, 0x36, 0xb4, 0xdd, 0xeb, 0x45, + /*3340:*/ 0x70, 0x7c, 0xe7, 0x0b, 0x53, 0xda, 0x85, 0x6f, 0x66, 0xcc, 0x88, 0x3d, 0xfe, 0x7f, 0x54, 0xe2, + /*3350:*/ 0x12, 0x18, 0xc8, 0xed, 0x0b, 0x49, 0xc3, 0x4e, 0x88, 0x24, 0xae, 0x50, 0x38, 0xed, 0x78, 0x69, + /*3360:*/ 0x0d, 0x2d, 0x31, 0x46, 0xce, 0x89, 0xcc, 0x3b, 0x34, 0x8e, 0x12, 0xf4, 0xa4, 0x84, 0x6b, 0xc1, + /*3370:*/ 0x2f, 0x69, 0x3a, 0x35, 0x67, 0xb7, 0x13, 0x9d, 0x14, 0x59, 0x2c, 0x73, 0xac, 0x97, 0x1c, 0xc9, + /*3380:*/ 0x23, 0xe0, 0xec, 0xf5, 0x84, 0xb6, 0x30, 0x8a, 0x7f, 0xe6, 0x9b, 0x0d, 0xad, 0xdc, 0xa4, 0x9e, + /*3390:*/ 0xe4, 0x9f, 0x92, 0xae, 0x05, 0xd7, 0xf3, 0x74, 0x54, 0x24, 0xf8, 0x9f, 0x09, 0xa4, 0xc9, 0x3c, + /*33a0:*/ 0x6d, 0xda, 0x01, 0xeb, 0x25, 0x06, 0x66, 0xdd, 0xc0, 0x2d, 0x73, 0xfd, 0x45, 0xd1, 0xe4, 0x34, + /*33b0:*/ 0x73, 0xb4, 0x62, 0x11, 0xaf, 0x82, 0x2d, 0xcb, 0xaa, 0xb7, 0x9c, 0x83, 0xc5, 0x57, 0x86, 0xc3, + /*33c0:*/ 0xdd, 0xa0, 0xf1, 0x6d, 0xf3, 0x5a, 0xbe, 0xa8, 0xb6, 0x9f, 0x66, 0x9c, 0x7b, 0x48, 0xf1, 0x71, + /*33d0:*/ 0x83, 0x94, 0x54, 0x8d, 0x85, 0xb5, 0x03, 0xd1, 0x88, 0xb9, 0xe6, 0xcb, 0x78, 0xab, 0xea, 0x24, + /*33e0:*/ 0x54, 0x7e, 0x3f, 0x66, 0xa0, 0x3e, 0x63, 0x9b, 0x8c, 0x57, 0x2c, 0xa9, 0x97, 0xba, 0xfd, 0x6e, + /*33f0:*/ 0x05, 0xbb, 0xda, 0x9f, 0x1c, 0x9d, 0x6d, 0xea, 0x04, 0x84, 0x8c, 0x07, 0x78, 0xa2, 0x80, 0x1e, + /*3400:*/ 0x1e, 0xe0, 0x0b, 0x8f, 0x89, 0xf3, 0x84, 0x23, 0x17, 0x71, 0xff, 0x15, 0x64, 0x49, 0x2e, 0x90, + /*3410:*/ 0x0e, 0x50, 0x20, 0x2f, 0xf1, 0x9b, 0xb9, 0xb3, 0xe6, 0xf0, 0xee, 0xbb, 0x5f, 0x6d, 0xa6, 0xa2, + /*3420:*/ 0x10, 0x8f, 0xaf, 0x2f, 0x4e, 0xe9, 0x27, 0xa0, 0x04, 0x48, 0xda, 0x9a, 0x03, 0x64, 0x33, 0x42, + /*3430:*/ 0x0e, 0x02, 0x2e, 0x1f, 0x0e, 0x87, 0x0c, 0xd7, 0xe7, 0x09, 0xac, 0x79, 0x42, 0x93, 0xd7, 0x4a, + /*3440:*/ 0xaa, 0x5f, 0x07, 0xed, 0xb1, 0xaf, 0x0c, 0x22, 0x63, 0x2a, 0x9c, 0x9d, 0x4b, 0x6c, 0xf6, 0x80, + /*3450:*/ 0x0a, 0x1e, 0x4a, 0x50, 0x07, 0x64, 0xc6, 0xcc, 0x3a, 0x2a, 0x64, 0x9e, 0xde, 0x5b, 0x2d, 0x6c, + /*3460:*/ 0xe3, 0x48, 0xb5, 0x11, 0x9d, 0x3c, 0xf0, 0x8f, 0x5c, 0x0d, 0xd7, 0x02, 0xf5, 0xce, 0xff, 0x71, + /*3470:*/ 0x06, 0xc4, 0x4b, 0x7d, 0x67, 0x7e, 0xef, 0xc4, 0x78, 0x60, 0xba, 0x58, 0x0f, 0xbc, 0x84, 0x7b, + /*3480:*/ 0xc5, 0xba, 0xde, 0x8b, 0xdc, 0x60, 0x78, 0xab, 0xf2, 0xde, 0xd4, 0xed, 0x00, 0x22, 0x6b, 0xa4, + /*3490:*/ 0x4a, 0x79, 0x43, 0x79, 0xba, 0x03, 0x84, 0x25, 0x0c, 0x41, 0x1d, 0x1f, 0x19, 0x23, 0x7c, 0xf7, + /*34a0:*/ 0x20, 0xa3, 0xfd, 0xa1, 0x4f, 0xff, 0xfe, 0x8c, 0x7e, 0xb9, 0x07, 0x7d, 0xbe, 0x79, 0x18, 0xa8, + /*34b0:*/ 0x24, 0x2a, 0x95, 0x01, 0xf3, 0x3f, 0xb1, 0xa6, 0xe4, 0xda, 0xcf, 0x68, 0x42, 0x08, 0x2c, 0x4d, + /*34c0:*/ 0x2a, 0xd7, 0xb3, 0x6f, 0x4a, 0xb4, 0x6b, 0xe9, 0x0b, 0xfb, 0x73, 0xb1, 0x21, 0x0a, 0x44, 0xab, + /*34d0:*/ 0x47, 0x02, 0xdb, 0xb5, 0x0b, 0x13, 0x6f, 0x0c, 0x78, 0x40, 0xbd, 0x73, 0x04, 0xf2, 0x7e, 0x54, + /*34e0:*/ 0x85, 0x35, 0x78, 0x52, 0x6d, 0xf4, 0x05, 0x70, 0x51, 0xa2, 0xb9, 0x6f, 0x34, 0x8c, 0x4b, 0x7b, + /*34f0:*/ 0xb8, 0x6c, 0x3b, 0xa5, 0xe7, 0x22, 0xc6, 0x46, 0xa8, 0x09, 0xc3, 0x6b, 0x19, 0x01, 0x50, 0xa5, + /*3500:*/ 0x58, 0xef, 0x4d, 0xfa, 0xee, 0x20, 0xbd, 0xcb, 0xd1, 0x56, 0xae, 0x7e, 0xc3, 0x6f, 0x61, 0x52, + /*3510:*/ 0xde, 0x9e, 0x59, 0xc4, 0x41, 0x52, 0x78, 0x39, 0x97, 0x30, 0x24, 0x9e, 0x92, 0xea, 0xbc, 0x69, + /*3520:*/ 0xf9, 0x8d, 0x1d, 0x1a, 0xce, 0x74, 0x52, 0x4f, 0x04, 0x5f, 0x0e, 0xd8, 0xb7, 0xb4, 0xf5, 0x5b, + /*3530:*/ 0xa9, 0x1c, 0xc0, 0x0d, 0xf3, 0xbc, 0x27, 0xde, 0x37, 0xe6, 0x26, 0x11, 0xd4, 0x9b, 0x25, 0x42, + /*3540:*/ 0xd7, 0xc1, 0xf6, 0xde, 0xb5, 0xae, 0x24, 0x59, 0x2a, 0x83, 0xb5, 0xa6, 0x8f, 0x03, 0xd3, 0xbf, + /*3550:*/ 0xcb, 0x58, 0x76, 0xe0, 0xf7, 0xdb, 0x63, 0xa4, 0x18, 0xbc, 0xfb, 0x0c, 0x76, 0x3e, 0x73, 0x71, + /*3560:*/ 0x4a, 0xdc, 0x5a, 0x0e, 0xf8, 0x59, 0x88, 0xc1, 0xc9, 0x55, 0x13, 0xc7, 0xab, 0x57, 0x85, 0x5b, + /*3570:*/ 0x46, 0x4d, 0x19, 0x14, 0x0c, 0xb0, 0x43, 0xd2, 0x92, 0xef, 0x6f, 0x8b, 0xd9, 0x06, 0xd3, 0x2f, + /*3580:*/ 0xaf, 0xf3, 0xa5, 0x09, 0x71, 0x96, 0x97, 0x5a, 0xfd, 0x03, 0x65, 0xad, 0x8e, 0x62, 0xce, 0x91, + /*3590:*/ 0x96, 0xd3, 0x91, 0x11, 0xb2, 0x85, 0xc7, 0xcb, 0x29, 0x79, 0x8d, 0x37, 0xd7, 0xec, 0x13, 0x43, + /*35a0:*/ 0x20, 0x08, 0x40, 0x8f, 0xa2, 0xee, 0xa5, 0x1f, 0xed, 0xa5, 0x78, 0x4b, 0x59, 0x50, 0x60, 0x09, + /*35b0:*/ 0x66, 0x0b, 0x0a, 0x5a, 0xc1, 0xd6, 0xe3, 0x96, 0xcd, 0xa2, 0x61, 0x26, 0x57, 0xa0, 0x51, 0x7e, + /*35c0:*/ 0x11, 0x21, 0xad, 0xce, 0xf5, 0x26, 0xdc, 0x8c, 0x3e, 0xd0, 0x61, 0xd8, 0x11, 0x2c, 0x7a, 0x68, + /*35d0:*/ 0xca, 0x95, 0x26, 0xde, 0x3c, 0xb4, 0xf1, 0x4b, 0x1e, 0xb8, 0x21, 0x83, 0x1e, 0xdb, 0xd9, 0x9d, + /*35e0:*/ 0x73, 0x60, 0xfa, 0x26, 0x2b, 0x41, 0xd1, 0x55, 0x16, 0x7b, 0x9f, 0xa8, 0xa4, 0x1f, 0x18, 0x5b, + /*35f0:*/ 0x6d, 0x22, 0xab, 0x73, 0x71, 0x7c, 0x04, 0xa8, 0xef, 0x3f, 0x1d, 0x2c, 0x9a, 0x98, 0x4e, 0xff, + /*3600:*/ 0xc7, 0xef, 0x7b, 0x63, 0x4d, 0x79, 0xe2, 0x33, 0x0a, 0xd8, 0x26, 0x30, 0xfc, 0xa3, 0x24, 0x5e, + /*3610:*/ 0x2f, 0xd7, 0xb3, 0x90, 0x1e, 0x45, 0x30, 0x41, 0x00, 0x59, 0x92, 0x62, 0x20, 0xb3, 0xff, 0x5d, + /*3620:*/ 0x47, 0x31, 0x6e, 0x87, 0xe5, 0x7e, 0x9d, 0x73, 0x8d, 0x3d, 0x74, 0x9c, 0x4b, 0xf7, 0xc8, 0x86, + /*3630:*/ 0xe4, 0xa7, 0xac, 0x4c, 0xf9, 0x51, 0x2f, 0x4d, 0xd2, 0x02, 0x9b, 0xcf, 0xb7, 0x68, 0x7f, 0x25, + /*3640:*/ 0xc7, 0x22, 0xfa, 0x75, 0xe5, 0xdd, 0x7e, 0xd3, 0x28, 0x07, 0x87, 0x78, 0x62, 0x20, 0x0e, 0xa1, + /*3650:*/ 0xab, 0x3e, 0xfd, 0xd0, 0x04, 0xe6, 0xd8, 0xf0, 0xa3, 0x1e, 0x05, 0xf5, 0x7e, 0x5e, 0xd8, 0xee, + /*3660:*/ 0x62, 0xc2, 0x71, 0xf7, 0x4a, 0x05, 0x84, 0x90, 0x15, 0x0a, 0x4a, 0x25, 0x32, 0x3c, 0x1c, 0xfe, + /*3670:*/ 0x14, 0xe2, 0x19, 0x3b, 0x97, 0xe4, 0x38, 0x8b, 0x7d, 0x30, 0x4b, 0x00, 0x62, 0x01, 0x68, 0x0f, + /*3680:*/ 0x01, 0xe3, 0xbb, 0x7d, 0x1a, 0x74, 0x0d, 0x09, 0x8e, 0x7a, 0xfe, 0x00, 0xc3, 0xb8, 0x23, 0xe7, + /*3690:*/ 0x98, 0xf5, 0xd7, 0x2b, 0x32, 0x2a, 0x4a, 0xbf, 0xe2, 0x21, 0x5f, 0xd8, 0x7a, 0x7c, 0x65, 0x0a, + /*36a0:*/ 0xba, 0x46, 0xfb, 0x66, 0x27, 0xdb, 0xd2, 0xa6, 0x52, 0x49, 0x7a, 0xb2, 0xee, 0x58, 0xe0, 0xc2, + /*36b0:*/ 0x90, 0x76, 0x90, 0x4a, 0x6f, 0xa1, 0x04, 0x44, 0xba, 0x9e, 0x40, 0x33, 0x16, 0x27, 0xa3, 0x0e, + /*36c0:*/ 0x6b, 0xed, 0x26, 0x0a, 0xaa, 0xc2, 0x09, 0x6a, 0xd6, 0x7c, 0x86, 0x9d, 0x3c, 0x57, 0x66, 0x01, + /*36d0:*/ 0xf0, 0x59, 0xd1, 0x2a, 0xf4, 0x5e, 0xa8, 0x4f, 0xff, 0x1a, 0xb2, 0xc6, 0xc6, 0xaa, 0x1e, 0x0d, + /*36e0:*/ 0x8d, 0x32, 0x05, 0x6d, 0x97, 0x25, 0xea, 0x32, 0x14, 0x4b, 0x6b, 0x20, 0x2a, 0x8c, 0x2b, 0xc1, + /*36f0:*/ 0x58, 0xcb, 0xa6, 0x87, 0x50, 0x96, 0xdb, 0x48, 0x3b, 0xcf, 0x6a, 0x41, 0x30, 0x72, 0x2d, 0x00, + /*3700:*/ 0x54, 0x6c, 0x03, 0x86, 0x88, 0x1a, 0x67, 0x8f, 0xa1, 0x4c, 0xdc, 0xf5, 0x7c, 0x16, 0xcf, 0x6f, + /*3710:*/ 0xa1, 0x5c, 0x59, 0x83, 0xb2, 0xca, 0xc3, 0xa4, 0x86, 0xa3, 0x0b, 0xab, 0x45, 0xeb, 0xf0, 0x21, + /*3720:*/ 0x8d, 0x06, 0x7f, 0x44, 0xa2, 0x4f, 0xeb, 0x63, 0x6f, 0x41, 0x11, 0x45, 0x7d, 0x00, 0xe9, 0x80, + /*3730:*/ 0x98, 0x25, 0xe3, 0x9c, 0x5f, 0x21, 0x9e, 0x3c, 0xfa, 0x8f, 0x0c, 0x35, 0x29, 0xce, 0x6e, 0xd6, + /*3740:*/ 0x48, 0x2c, 0x30, 0x90, 0xce, 0x35, 0x9d, 0x23, 0x10, 0x7d, 0x21, 0x0e, 0xc2, 0x93, 0x93, 0x8c, + /*3750:*/ 0xc5, 0xfc, 0xc6, 0x33, 0x05, 0x56, 0xa3, 0x53, 0x28, 0xd5, 0x3f, 0xc2, 0x80, 0x22, 0x9d, 0x5f, + /*3760:*/ 0xaa, 0x97, 0x06, 0x0b, 0xa1, 0xa7, 0x7b, 0x12, 0x7f, 0xcc, 0xca, 0xbc, 0x3e, 0x72, 0xd2, 0x17, + /*3770:*/ 0xb0, 0xd0, 0xe2, 0x0e, 0x36, 0xe4, 0xeb, 0xd5, 0x25, 0xc7, 0x94, 0xc4, 0x36, 0xa5, 0x2f, 0xee, + /*3780:*/ 0x03, 0xe3, 0x99, 0x3b, 0x9a, 0x57, 0x81, 0x71, 0xc6, 0xdc, 0x18, 0xea, 0x88, 0x10, 0x59, 0xfd, + /*3790:*/ 0x9d, 0x31, 0x71, 0x79, 0x55, 0x5d, 0x65, 0xf1, 0x20, 0x81, 0x9e, 0x0e, 0x42, 0x91, 0x2a, 0xa7, + /*37a0:*/ 0x0a, 0x79, 0xa8, 0x33, 0xd5, 0x00, 0x1d, 0x55, 0xb2, 0x47, 0xc6, 0xda, 0x47, 0x1e, 0x55, 0x7a, + /*37b0:*/ 0xb5, 0x16, 0xe9, 0x16, 0x75, 0x1c, 0x1a, 0x6e, 0x57, 0x30, 0xf4, 0xe1, 0xf0, 0x92, 0x2d, 0x28, + /*37c0:*/ 0xfa, 0x30, 0xc5, 0xc2, 0x6e, 0x6b, 0x0b, 0x98, 0x64, 0xd7, 0x3f, 0x6e, 0x73, 0x20, 0xb1, 0xda, + /*37d0:*/ 0x9a, 0xc4, 0x04, 0xe9, 0xc8, 0x8c, 0x09, 0xb3, 0x0f, 0x06, 0xa8, 0x07, 0x11, 0xc2, 0x15, 0x27, + /*37e0:*/ 0x08, 0xeb, 0x42, 0x29, 0xfb, 0x7c, 0xb2, 0xd5, 0x2c, 0x25, 0x85, 0x6b, 0x07, 0x51, 0xdc, 0x0a, + /*37f0:*/ 0x6b, 0xd4, 0xdb, 0x1d, 0xf7, 0x21, 0x59, 0xa0, 0xb5, 0xd9, 0xdf, 0x62, 0x34, 0xd0, 0xce, 0xad, + /*3800:*/ 0xfc, 0xad, 0x16, 0xcc, 0x01, 0x9d, 0x55, 0x5e, 0x84, 0xdd, 0x5f, 0xad, 0x3a, 0x36, 0x81, 0x5c, + /*3810:*/ 0xaf, 0x48, 0xce, 0x4d, 0xb7, 0x39, 0x02, 0x47, 0x20, 0x55, 0xd6, 0xbd, 0x4e, 0xf8, 0xe8, 0x78, + /*3820:*/ 0x74, 0xb3, 0x8e, 0x76, 0xbf, 0x71, 0x1e, 0x46, 0x5b, 0x33, 0x74, 0x23, 0xe1, 0x8b, 0xee, 0x89, + /*3830:*/ 0x38, 0xdb, 0xde, 0xb7, 0xae, 0x06, 0x3c, 0x51, 0x1b, 0xaf, 0xf6, 0x32, 0x61, 0x5b, 0xe2, 0xf6, + /*3840:*/ 0x7e, 0x0e, 0x78, 0xe8, 0xcf, 0x1a, 0x4a, 0x39, 0xf8, 0xda, 0x4f, 0x1b, 0xb5, 0xe4, 0x25, 0x3e, + /*3850:*/ 0x41, 0xef, 0x28, 0xcb, 0x17, 0x2f, 0xa4, 0x55, 0xd6, 0xf9, 0x88, 0x48, 0x26, 0x66, 0x56, 0xfe, + /*3860:*/ 0x30, 0x4d, 0x7d, 0x6b, 0xf8, 0x61, 0x80, 0x0f, 0x3d, 0x36, 0xb3, 0x7d, 0x73, 0x40, 0x17, 0x92, + /*3870:*/ 0x51, 0x58, 0x05, 0x49, 0x4b, 0x83, 0x13, 0x2a, 0x24, 0xd5, 0x92, 0xac, 0x40, 0x67, 0xe3, 0xa8, + /*3880:*/ 0xe9, 0xa6, 0x85, 0x58, 0xd7, 0xf4, 0xfc, 0x1d, 0xb5, 0x68, 0x19, 0xa7, 0xf8, 0xd8, 0xa5, 0x75, + /*3890:*/ 0xe0, 0x6d, 0xc6, 0x5a, 0xa6, 0xa3, 0x1c, 0x16, 0xd3, 0xf3, 0x61, 0xbb, 0x3c, 0x61, 0xb1, 0x3d, + /*38a0:*/ 0x58, 0xb9, 0x3f, 0x8a, 0xb2, 0x61, 0x6d, 0x78, 0x92, 0x20, 0x6e, 0xff, 0x69, 0x5e, 0x3e, 0xe2, + /*38b0:*/ 0x16, 0xb2, 0xc4, 0x44, 0x8d, 0xb9, 0x86, 0xa5, 0xcf, 0xc7, 0x97, 0xc1, 0x10, 0xed, 0xe7, 0x76, + /*38c0:*/ 0xe3, 0xa6, 0x51, 0x8f, 0x01, 0xb5, 0xd0, 0x34, 0xe2, 0xab, 0x7d, 0x45, 0xb6, 0x1f, 0x7c, 0xde, + /*38d0:*/ 0x5a, 0xa7, 0x59, 0x9e, 0xd2, 0x4b, 0x6d, 0xc8, 0xf4, 0x29, 0xb4, 0x73, 0x20, 0x0a, 0xc5, 0x60, + /*38e0:*/ 0xd1, 0x6e, 0xad, 0x8f, 0xb7, 0x56, 0xd3, 0xaa, 0xf9, 0xff, 0x16, 0xcc, 0x7b, 0x87, 0x2c, 0x3a, + /*38f0:*/ 0xa1, 0x1c, 0x57, 0x24, 0x5f, 0xb5, 0xb0, 0x99, 0x9c, 0xdb, 0xef, 0xdc, 0x4f, 0x6c, 0xea, 0x39, + /*3900:*/ 0x6d, 0x3d, 0x75, 0x65, 0x90, 0x79, 0xb5, 0x4b, 0xa9, 0x86, 0x74, 0xc5, 0xe6, 0x60, 0x7c, 0x2e, + /*3910:*/ 0xa4, 0x64, 0x93, 0xc8, 0x24, 0x54, 0x9b, 0xbf, 0x08, 0x07, 0xd1, 0x94, 0x87, 0xea, 0x9d, 0x88, + /*3920:*/ 0x19, 0x52, 0x32, 0xa4, 0xb5, 0x09, 0xf1, 0xb8, 0xee, 0x33, 0xc9, 0xff, 0x17, 0x9e, 0xbc, 0xb9, + /*3930:*/ 0xb4, 0x53, 0x93, 0xf4, 0x76, 0xa2, 0xd0, 0x87, 0xce, 0x22, 0xea, 0xee, 0xe3, 0xeb, 0x88, 0x58, + /*3940:*/ 0xb5, 0xb2, 0xd8, 0xed, 0x4c, 0x01, 0x2a, 0x8c, 0x25, 0x6f, 0xbf, 0xb1, 0xe5, 0x23, 0xf1, 0x7a, + /*3950:*/ 0x78, 0x2b, 0x32, 0x37, 0x99, 0xc3, 0xb0, 0x23, 0xa2, 0x9f, 0x72, 0xb6, 0x71, 0x88, 0x92, 0x32, + /*3960:*/ 0x52, 0x77, 0xd1, 0xb6, 0x0d, 0xbe, 0x6e, 0xd4, 0xdc, 0xf9, 0xb2, 0x0f, 0xcc, 0x8d, 0x8a, 0x96, + /*3970:*/ 0xce, 0x7f, 0x8f, 0xa4, 0x0e, 0x8f, 0x5f, 0x4c, 0x35, 0x54, 0xcb, 0xe2, 0xfa, 0xad, 0x5d, 0xd5, + /*3980:*/ 0x5d, 0x70, 0xf2, 0x82, 0x78, 0x27, 0xb9, 0xf9, 0x02, 0x15, 0x53, 0x00, 0xae, 0x29, 0x85, 0xf4, + /*3990:*/ 0xba, 0xc6, 0x0e, 0x6c, 0xb6, 0xe9, 0xef, 0xe1, 0x88, 0x42, 0xc5, 0x1a, 0x23, 0x5f, 0x19, 0xaf, + /*39a0:*/ 0x15, 0x9e, 0x26, 0x48, 0x42, 0x91, 0xc5, 0xc0, 0xfe, 0xfb, 0x72, 0x0c, 0x98, 0x98, 0xfa, 0xed, + /*39b0:*/ 0x94, 0x12, 0x1f, 0xc5, 0x14, 0x00, 0x55, 0xa5, 0x10, 0xc6, 0xf6, 0x3e, 0x64, 0x8c, 0xa7, 0x4e, + /*39c0:*/ 0x11, 0x84, 0x16, 0xeb, 0x48, 0x90, 0x49, 0xc2, 0xbf, 0x3c, 0xab, 0x54, 0xe4, 0x28, 0x59, 0x43, + /*39d0:*/ 0x77, 0xad, 0x1a, 0x14, 0xd8, 0xc3, 0x3e, 0x88, 0x3f, 0x7f, 0x38, 0xbf, 0xe2, 0x65, 0x89, 0x6d, + /*39e0:*/ 0x9e, 0x4e, 0x91, 0x5f, 0x6a, 0x70, 0x48, 0x17, 0xa0, 0x87, 0x68, 0x0d, 0x4b, 0x7c, 0x56, 0x1f, + /*39f0:*/ 0x57, 0xb0, 0x4d, 0x54, 0x78, 0x3e, 0x2b, 0xdb, 0x12, 0xed, 0x1d, 0x69, 0x7a, 0x48, 0x03, 0x46, + /*3a00:*/ 0x3c, 0xa8, 0x45, 0xff, 0xc7, 0x23, 0x17, 0x2d, 0xdd, 0x6b, 0xad, 0x4a, 0xff, 0x9d, 0x8d, 0xa2, + /*3a10:*/ 0x9e, 0x3d, 0x5b, 0xe6, 0x7a, 0x0f, 0x31, 0x6e, 0x0a, 0xca, 0xc4, 0x48, 0x91, 0xe5, 0xd2, 0x38, + /*3a20:*/ 0xfe, 0x87, 0x1b, 0x4a, 0xa1, 0xca, 0xd6, 0xad, 0x4d, 0x90, 0xff, 0x65, 0x93, 0xc1, 0x22, 0xdd, + /*3a30:*/ 0x46, 0x16, 0x89, 0x08, 0x6e, 0x6d, 0x35, 0x5e, 0x13, 0x95, 0x6d, 0x0e, 0xce, 0xd1, 0x3c, 0x98, + /*3a40:*/ 0x15, 0x0a, 0xee, 0xaa, 0xbb, 0x7e, 0xba, 0x21, 0x1c, 0x1d, 0x52, 0x6d, 0xaa, 0x86, 0xcd, 0x42, + /*3a50:*/ 0x52, 0xf4, 0xdf, 0xca, 0x57, 0xf8, 0x26, 0x7b, 0xc7, 0x31, 0x37, 0xec, 0xbb, 0x5b, 0x61, 0xe5, + /*3a60:*/ 0xda, 0xa9, 0x93, 0xd6, 0xe1, 0xd7, 0xcf, 0xdc, 0xeb, 0x3a, 0xcb, 0x19, 0x73, 0x40, 0xf3, 0xde, + /*3a70:*/ 0x5d, 0x4a, 0xaf, 0x46, 0x62, 0xbb, 0xf7, 0x4b, 0x4c, 0xe1, 0x50, 0xa7, 0xc5, 0x14, 0x71, 0xbf, + /*3a80:*/ 0x3a, 0x03, 0x8a, 0xd2, 0xaa, 0x9a, 0x44, 0x91, 0xaf, 0xd1, 0x44, 0x24, 0xa4, 0x0e, 0x47, 0x32, + /*3a90:*/ 0x51, 0x62, 0x14, 0x10, 0x8d, 0x21, 0x2d, 0x7e, 0x62, 0x12, 0x5d, 0xc1, 0x46, 0xcc, 0x9d, 0xd0, + /*3aa0:*/ 0xa0, 0xa2, 0x35, 0x33, 0xcb, 0x4c, 0xc0, 0x5a, 0x20, 0x2e, 0xc8, 0x49, 0x03, 0x12, 0x00, 0xc9, + /*3ab0:*/ 0x5c, 0xc8, 0xc3, 0xff, 0xfa, 0x1f, 0x85, 0x18, 0x78, 0xe4, 0x7f, 0x95, 0x07, 0xce, 0xb3, 0xf3, + /*3ac0:*/ 0xb1, 0x75, 0x76, 0xf3, 0xd8, 0x82, 0xc8, 0xc9, 0x5e, 0xb5, 0x30, 0xa6, 0xbf, 0xcb, 0x0a, 0x21, + /*3ad0:*/ 0x1e, 0x98, 0x06, 0x8e, 0x4c, 0x7a, 0xb4, 0x72, 0x36, 0xf5, 0xca, 0x07, 0xce, 0x90, 0xf2, 0x1f, + /*3ae0:*/ 0xcd, 0x68, 0xac, 0x7f, 0x12, 0x8a, 0x19, 0x2c, 0x60, 0x3a, 0x9a, 0x65, 0x79, 0x48, 0x01, 0x89, + /*3af0:*/ 0x9e, 0x61, 0xff, 0xe4, 0x36, 0x4f, 0x0d, 0x9b, 0x69, 0xaa, 0x9f, 0x01, 0x87, 0x53, 0x13, 0x0c, + /*3b00:*/ 0x93, 0x20, 0x21, 0x87, 0x41, 0x48, 0xfc, 0x82, 0xe9, 0x12, 0x4c, 0x17, 0xd0, 0xee, 0xdc, 0x68, + /*3b10:*/ 0xf9, 0xdd, 0x28, 0x13, 0xa4, 0x28, 0x12, 0x97, 0x38, 0xe9, 0xb9, 0x7c, 0x0e, 0xfe, 0xc3, 0xd3, + /*3b20:*/ 0x86, 0x7d, 0xb3, 0x82, 0x66, 0xb8, 0x98, 0xeb, 0xdd, 0x24, 0x82, 0xa6, 0x26, 0x82, 0xd0, 0xf0, + /*3b30:*/ 0x44, 0xd1, 0x1e, 0x49, 0xee, 0xf5, 0x48, 0x75, 0x87, 0xca, 0xe2, 0xdf, 0x81, 0x9a, 0x5b, 0x83, + /*3b40:*/ 0xfd, 0xa1, 0xef, 0x87, 0x83, 0x95, 0xe5, 0x8c, 0x74, 0x35, 0x38, 0xd9, 0x7c, 0x56, 0x5f, 0xf0, + /*3b50:*/ 0xd4, 0x60, 0xb8, 0x97, 0xe2, 0x96, 0x06, 0xd3, 0xc9, 0xc9, 0x88, 0x31, 0x02, 0x2a, 0xb2, 0x28, + /*3b60:*/ 0xb2, 0xcc, 0x91, 0xcb, 0x01, 0xec, 0xb5, 0x9d, 0x09, 0x6e, 0xd0, 0xde, 0xf0, 0xce, 0x72, 0x93, + /*3b70:*/ 0x6c, 0xcb, 0xaa, 0x2b, 0x29, 0x84, 0xbe, 0xab, 0xff, 0x42, 0x2e, 0x4f, 0xc1, 0x65, 0x22, 0x91, + /*3b80:*/ 0xac, 0xb3, 0xfb, 0x53, 0x98, 0x56, 0x8f, 0x16, 0xbe, 0x1d, 0x7f, 0x29, 0x17, 0xdc, 0x9d, 0xf8, + /*3b90:*/ 0x59, 0x8b, 0xa9, 0x76, 0x01, 0xa8, 0x24, 0xa7, 0x00, 0xdd, 0xa3, 0xe5, 0x6e, 0x27, 0x66, 0x2f, + /*3ba0:*/ 0xe7, 0x1d, 0x0d, 0x2a, 0x75, 0x80, 0x10, 0x38, 0xf6, 0x3d, 0x45, 0x18, 0xb0, 0x31, 0xcb, 0xe0, + /*3bb0:*/ 0x8e, 0x73, 0x14, 0xbc, 0x36, 0x16, 0xf3, 0xa8, 0xd5, 0x3e, 0xf6, 0xdc, 0xa7, 0x33, 0xcb, 0x49, + /*3bc0:*/ 0xb6, 0x45, 0x00, 0xb6, 0xcc, 0x9d, 0x40, 0xbc, 0x1d, 0x12, 0xbb, 0xe4, 0xd0, 0x3f, 0xa6, 0x28, + /*3bd0:*/ 0x5d, 0x0f, 0xa2, 0x90, 0xbe, 0x1f, 0x90, 0x6a, 0xb8, 0x22, 0x89, 0xf9, 0x3a, 0xdd, 0x7a, 0xe8, + /*3be0:*/ 0x63, 0x1f, 0x1f, 0x15, 0xa1, 0xbd, 0x72, 0x6d, 0x83, 0x02, 0x5e, 0x95, 0x5c, 0x33, 0x20, 0xb4, + /*3bf0:*/ 0xe5, 0x39, 0x87, 0xd9, 0x57, 0xd7, 0xb6, 0x86, 0x21, 0xff, 0xfa, 0x67, 0x7e, 0x94, 0xac, 0xda, + /*3c00:*/ 0xf0, 0xe0, 0x4e, 0xc4, 0x88, 0x84, 0x01, 0xcc, 0xfa, 0x37, 0x27, 0xbe, 0x63, 0x8f, 0x41, 0x94, + /*3c10:*/ 0x75, 0x06, 0x8c, 0x10, 0xd5, 0xf7, 0xe1, 0x2c, 0x92, 0xe1, 0x4f, 0xda, 0xdf, 0xac, 0x64, 0xe8, + /*3c20:*/ 0x8e, 0xbb, 0x8b, 0x9a, 0x70, 0x57, 0x50, 0xb3, 0x63, 0x77, 0xcf, 0xa6, 0xb0, 0x91, 0x13, 0xa4, + /*3c30:*/ 0x29, 0xf1, 0x27, 0x1d, 0x4e, 0x37, 0x6b, 0x81, 0xd3, 0x0d, 0x3c, 0xb6, 0x91, 0x42, 0xf4, 0x70, + /*3c40:*/ 0x64, 0x86, 0x2f, 0xee, 0xec, 0xc2, 0x97, 0xb7, 0xb6, 0xf2, 0x86, 0x8a, 0x7a, 0x2d, 0x6c, 0x06, + /*3c50:*/ 0x5d, 0x24, 0xd9, 0xf9, 0xc8, 0xd2, 0xd6, 0xb5, 0xb8, 0xd7, 0x0a, 0x1e, 0x31, 0x4f, 0x04, 0x9c, + /*3c60:*/ 0x4b, 0xe0, 0x21, 0xdf, 0xb3, 0x8d, 0xdf, 0xc7, 0x9d, 0x57, 0x62, 0xa4, 0xff, 0x88, 0x07, 0x0e, + /*3c70:*/ 0xad, 0x7f, 0x39, 0xe8, 0x8a, 0x04, 0x64, 0xde, 0x94, 0xc3, 0xa3, 0xd0, 0xc8, 0x40, 0x27, 0x63, + /*3c80:*/ 0x76, 0x4b, 0xa0, 0xe1, 0xdc, 0xf1, 0xec, 0x93, 0xd3, 0xa2, 0x69, 0x8a, 0xa7, 0xe2, 0x33, 0x97, + /*3c90:*/ 0x58, 0xff, 0x7e, 0x66, 0x24, 0x2c, 0x61, 0x7f, 0x3a, 0xdf, 0x92, 0x31, 0x4b, 0x66, 0x52, 0x7e, + /*3ca0:*/ 0xa3, 0x88, 0x7e, 0x57, 0xe6, 0x51, 0xf6, 0x7f, 0x98, 0x93, 0x6b, 0xd7, 0x7d, 0x7d, 0xee, 0x72, + /*3cb0:*/ 0xc6, 0x15, 0xe1, 0x30, 0x2a, 0xeb, 0x48, 0x8f, 0x8d, 0xed, 0x62, 0x0c, 0x53, 0x93, 0x62, 0x1e, + /*3cc0:*/ 0x61, 0x1a, 0x2e, 0x34, 0xad, 0xd2, 0x47, 0x0d, 0x08, 0x8e, 0xae, 0x35, 0x77, 0x25, 0x67, 0x00, + /*3cd0:*/ 0x9a, 0xf0, 0x51, 0x5e, 0x16, 0x94, 0x31, 0xd7, 0x24, 0x17, 0xa5, 0xe5, 0x2e, 0x92, 0x36, 0xcb, + /*3ce0:*/ 0x36, 0xf8, 0x16, 0xb7, 0x7b, 0xff, 0x2d, 0x25, 0x02, 0x00, 0xb3, 0x75, 0x78, 0xd5, 0xb2, 0x69, + /*3cf0:*/ 0xae, 0x95, 0xd8, 0xc4, 0x4e, 0xa1, 0x6f, 0x93, 0x20, 0xae, 0x74, 0x56, 0x7a, 0xed, 0x24, 0xbb, + /*3d00:*/ 0xc7, 0x8d, 0x0a, 0xbe, 0x9f, 0x5c, 0xd4, 0xa2, 0x20, 0xe9, 0x5e, 0x01, 0x6d, 0x16, 0xe1, 0x59, + /*3d10:*/ 0x05, 0x65, 0xa7, 0x5b, 0xdc, 0x3f, 0x15, 0xf0, 0x43, 0x97, 0x0f, 0x72, 0x60, 0x47, 0xf8, 0x1c, + /*3d20:*/ 0xff, 0xdc, 0xcf, 0xb1, 0xc3, 0x2a, 0x44, 0x9d, 0x37, 0xec, 0x8b, 0x0d, 0x7d, 0x37, 0xa5, 0x2f, + /*3d30:*/ 0x3c, 0x74, 0xca, 0x90, 0x2c, 0x0c, 0x8f, 0x88, 0x01, 0x48, 0x81, 0x0b, 0x8b, 0xf8, 0xc7, 0xb8, + /*3d40:*/ 0x96, 0x45, 0x06, 0x4e, 0x60, 0x04, 0xd8, 0xae, 0x30, 0xcb, 0x6b, 0xf9, 0xdd, 0x0a, 0x31, 0x8d, + /*3d50:*/ 0xde, 0x60, 0x42, 0xf3, 0xf1, 0x87, 0x31, 0x85, 0x25, 0x62, 0xcc, 0x92, 0x54, 0x49, 0x96, 0xd5, + /*3d60:*/ 0x72, 0xc7, 0xb7, 0xf1, 0x01, 0x0b, 0x30, 0xe5, 0x8b, 0xba, 0x49, 0x05, 0xe0, 0xa2, 0x54, 0xee, + /*3d70:*/ 0x45, 0xae, 0xd3, 0x75, 0x35, 0x61, 0x9a, 0x10, 0xee, 0x1f, 0x2a, 0x83, 0xfe, 0x81, 0x0d, 0xc4, + /*3d80:*/ 0xc2, 0x35, 0xc9, 0xf0, 0xed, 0x01, 0xf3, 0x5f, 0x9b, 0x66, 0x41, 0xc1, 0x10, 0x04, 0xc3, 0x57, + /*3d90:*/ 0x04, 0x74, 0x31, 0x72, 0xd9, 0x15, 0x9d, 0xe6, 0xc9, 0x2e, 0xb9, 0xd0, 0x2c, 0xe5, 0x27, 0x85, + /*3da0:*/ 0xa8, 0xe8, 0x8b, 0x44, 0x20, 0x99, 0x1e, 0x12, 0x33, 0xff, 0x4c, 0xa1, 0x59, 0x2c, 0x44, 0xd2, + /*3db0:*/ 0x51, 0x94, 0xa1, 0xc1, 0x65, 0xe8, 0x77, 0xad, 0xf7, 0x2c, 0x3c, 0x1b, 0xeb, 0x85, 0x31, 0x7e, + /*3dc0:*/ 0x7a, 0x3d, 0xe3, 0x49, 0xc3, 0xe7, 0x8f, 0xe1, 0x39, 0x88, 0x33, 0xd1, 0x8d, 0xf5, 0xec, 0x2c, + /*3dd0:*/ 0x43, 0x6a, 0x63, 0x8a, 0xad, 0x7b, 0x61, 0x8c, 0x55, 0x10, 0x89, 0x2e, 0x50, 0x0c, 0x72, 0x49, + /*3de0:*/ 0xad, 0xaf, 0xc4, 0x3f, 0x34, 0xdb, 0xc9, 0x23, 0x90, 0x18, 0xd6, 0x8c, 0xe9, 0xab, 0x5b, 0x01, + /*3df0:*/ 0x9c, 0x5d, 0x05, 0x65, 0x5c, 0x14, 0x27, 0x28, 0xa7, 0x42, 0x93, 0xbe, 0xde, 0xd2, 0x3a, 0x1f, + /*3e00:*/ 0x3f, 0x32, 0xaf, 0x89, 0x34, 0xfa, 0x7a, 0x0d, 0xdd, 0x66, 0xdc, 0x16, 0x60, 0x69, 0x24, 0x04, + /*3e10:*/ 0x1e, 0x9e, 0x55, 0x09, 0x3c, 0x98, 0xb3, 0x95, 0xcc, 0xa4, 0x51, 0xb4, 0x17, 0x80, 0x3a, 0x74, + /*3e20:*/ 0x2c, 0x2f, 0x54, 0x28, 0x83, 0xf9, 0xc4, 0x8a, 0x6b, 0x42, 0x57, 0x6c, 0x14, 0xba, 0xca, 0x51, + /*3e30:*/ 0x27, 0xeb, 0x90, 0x98, 0x59, 0x84, 0x0c, 0xea, 0x90, 0x6e, 0xf3, 0xb2, 0xc3, 0x50, 0xd2, 0x4e, + /*3e40:*/ 0xa0, 0xb3, 0xc0, 0x09, 0x41, 0x59, 0xb5, 0x18, 0x0e, 0x14, 0x27, 0xb1, 0x95, 0x21, 0x0c, 0xe7, + /*3e50:*/ 0x24, 0x79, 0x62, 0x9c, 0x90, 0xe5, 0x44, 0x98, 0x7b, 0x5f, 0xba, 0x46, 0x5f, 0x61, 0xbb, 0x25, + /*3e60:*/ 0xd3, 0x3b, 0x63, 0xdf, 0xc4, 0x76, 0xce, 0x55, 0x4d, 0xaf, 0x69, 0xfd, 0xab, 0xaa, 0x2c, 0x52, + /*3e70:*/ 0xaa, 0x20, 0x38, 0x7e, 0x29, 0x4a, 0x7d, 0x09, 0xee, 0xa8, 0x77, 0xe0, 0xed, 0x54, 0x64, 0x50, + /*3e80:*/ 0x19, 0x1f, 0xc7, 0x34, 0x79, 0xbf, 0x06, 0xf9, 0xac, 0x61, 0x6a, 0xd7, 0x8e, 0xb0, 0x65, 0x4d, + /*3e90:*/ 0xa0, 0xc1, 0x9a, 0xbb, 0x44, 0xbd, 0x30, 0xa0, 0xfb, 0xf5, 0x35, 0x91, 0xa7, 0x09, 0xbb, 0x48, + /*3ea0:*/ 0x4f, 0x94, 0x33, 0xe2, 0x3d, 0x79, 0xc0, 0x0b, 0x27, 0x42, 0x9f, 0x7c, 0x4c, 0x1a, 0xe5, 0x17, + /*3eb0:*/ 0xb2, 0xdf, 0xa3, 0x87, 0x4b, 0x76, 0xd3, 0x78, 0x24, 0x6b, 0xd4, 0x54, 0x7e, 0x73, 0x37, 0x2b, + /*3ec0:*/ 0xe1, 0xbe, 0xba, 0xbd, 0x6b, 0xb4, 0x5c, 0x7b, 0xba, 0xbc, 0x98, 0x65, 0xcb, 0xdf, 0xb9, 0x99, + /*3ed0:*/ 0x25, 0xeb, 0xe5, 0x93, 0xff, 0x8f, 0x82, 0x6c, 0x5f, 0x6b, 0xde, 0x47, 0xb7, 0x16, 0x92, 0x81, + /*3ee0:*/ 0x7c, 0x77, 0xe3, 0x0b, 0x6f, 0xf2, 0x9a, 0xa0, 0x98, 0xf4, 0xf5, 0xcd, 0x6e, 0xf4, 0x64, 0x65, + /*3ef0:*/ 0xc2, 0x87, 0x85, 0x54, 0x32, 0x11, 0x37, 0xde, 0xfb, 0x7e, 0x51, 0x64, 0x4b, 0x7f, 0x57, 0x34, + /*3f00:*/ 0x1c, 0xa3, 0x37, 0x11, 0x1e, 0x66, 0x43, 0xf5, 0x6d, 0x4d, 0x08, 0x94, 0x7c, 0x79, 0xb7, 0xfe, + /*3f10:*/ 0x20, 0x78, 0x2e, 0x19, 0x49, 0xf6, 0x3b, 0x86, 0xe4, 0xa1, 0xc5, 0x65, 0xef, 0xa9, 0x97, 0x55, + /*3f20:*/ 0x37, 0xed, 0x23, 0xd2, 0x5a, 0x14, 0x5a, 0xde, 0x6c, 0xda, 0x50, 0xfb, 0xcb, 0x56, 0x56, 0x8e, + /*3f30:*/ 0xf1, 0xd1, 0x18, 0x0d, 0x17, 0x7f, 0x3a, 0xb3, 0x07, 0x25, 0x1a, 0x76, 0x1f, 0xd8, 0x67, 0x97, + /*3f40:*/ 0x43, 0xfa, 0x02, 0xa8, 0x7c, 0x6d, 0x56, 0xb1, 0xd4, 0xba, 0x1d, 0x06, 0x60, 0x86, 0x66, 0xd6, + /*3f50:*/ 0xd5, 0x1b, 0x5e, 0x64, 0xf5, 0x02, 0x44, 0xa4, 0x8d, 0x21, 0x27, 0xd2, 0x16, 0xe4, 0xd9, 0xad, + /*3f60:*/ 0xac, 0x08, 0x12, 0x81, 0xd6, 0xe4, 0x4e, 0x68, 0xe4, 0xaf, 0x62, 0x8c, 0x7e, 0xef, 0x42, 0xa9, + /*3f70:*/ 0xff, 0x3f, 0x3b, 0x6c, 0x9f, 0xec, 0xa5, 0x9c, 0xf5, 0xf8, 0x4f, 0xa9, 0x37, 0x79, 0x86, 0x92, + /*3f80:*/ 0x2b, 0x6d, 0x75, 0xbc, 0x50, 0x5e, 0x78, 0x1c, 0xbe, 0x03, 0xcf, 0x7d, 0x37, 0x21, 0xcf, 0x43, + /*3f90:*/ 0x4e, 0x2b, 0x68, 0x7b, 0x77, 0x44, 0x39, 0x85, 0x1b, 0x1c, 0x4a, 0x1f, 0x75, 0x68, 0xa6, 0x9c, + /*3fa0:*/ 0x8c, 0x0f, 0x35, 0x78, 0x20, 0x1a, 0xe5, 0xa6, 0x2b, 0xbf, 0x4a, 0x08, 0x04, 0xe5, 0x9d, 0x08, + /*3fb0:*/ 0x4f, 0x03, 0x11, 0xc9, 0x08, 0x1a, 0xde, 0xd1, 0x9d, 0x7c, 0x74, 0x49, 0x5d, 0x09, 0xff, 0x38, + /*3fc0:*/ 0x29, 0x76, 0xa6, 0xf8, 0x9a, 0xda, 0xda, 0x9a, 0xb6, 0xc9, 0x39, 0x59, 0x62, 0xe1, 0x4b, 0x7f, + /*3fd0:*/ 0x11, 0xac, 0xa6, 0x21, 0x85, 0x0b, 0x2a, 0x0e, 0xa6, 0x89, 0x61, 0x00, 0xdc, 0xb0, 0x5a, 0x9b, + /*3fe0:*/ 0x1b, 0xbd, 0x44, 0x74, 0x01, 0xbc, 0x31, 0x7f, 0xbb, 0x2f, 0x4c, 0x83, 0x8d, 0xe2, 0x99, 0xea, + /*3ff0:*/ 0xad, 0xbb, 0xb4, 0xe5, 0xb6, 0x4d, 0xa8, 0xf6, 0x99, 0xe2, 0x85, 0x27, 0x08, 0x70, 0x84, 0x05, + /*4000:*/ 0xed, 0x8d, 0x0e, 0x89, 0x9a, 0x03, 0xc3, 0xe6, 0xa6, 0xe1, 0x8d, 0xc3, 0x2e, 0xdd, 0xc8, 0x53, + /*4010:*/ 0xb8, 0xd7, 0x88, 0xf6, 0x88, 0xb2, 0xb4, 0x38, 0xa6, 0xc4, 0xc1, 0x2c, 0x71, 0x41, 0x8f, 0xc3, + /*4020:*/ 0x51, 0x77, 0x20, 0x0c, 0xa6, 0x4c, 0xac, 0xcd, 0xf5, 0xae, 0x4c, 0x37, 0x57, 0xf5, 0x1c, 0x09, + /*4030:*/ 0xe3, 0xcf, 0x5c, 0x69, 0xed, 0x92, 0x5e, 0xce, 0xf1, 0x83, 0x41, 0xf7, 0xa1, 0x05, 0x3f, 0x56, + /*4040:*/ 0x5e, 0x76, 0x06, 0x63, 0xb7, 0x73, 0x2a, 0xe4, 0x83, 0x10, 0xe6, 0x30, 0x7e, 0x9a, 0xd6, 0xc5, + /*4050:*/ 0x8d, 0x7f, 0xf8, 0xeb, 0xf6, 0x05, 0x32, 0x24, 0xf1, 0x70, 0xa9, 0x85, 0x69, 0x5c, 0x37, 0x02, + /*4060:*/ 0x4a, 0x7e, 0x23, 0xee, 0x91, 0xa2, 0xdd, 0xaa, 0x51, 0x6b, 0x1b, 0x39, 0x76, 0x28, 0x9e, 0xbf, + /*4070:*/ 0xe5, 0xd9, 0xfe, 0x0b, 0x89, 0x63, 0xff, 0x47, 0x50, 0x8f, 0x66, 0x0e, 0x96, 0x0f, 0x3d, 0x8c, + /*4080:*/ 0xdd, 0x55, 0xfd, 0xae, 0x37, 0x18, 0x71, 0x0e, 0x08, 0x48, 0x65, 0x53, 0xb8, 0x1b, 0x9d, 0xc5, + /*4090:*/ 0x1f, 0x0f, 0x9e, 0x9a, 0xcf, 0xfb, 0x37, 0xf0, 0x6e, 0x5c, 0x8b, 0xec, 0x3b, 0x3a, 0xd3, 0xce, + /*40a0:*/ 0xc5, 0x94, 0x24, 0x88, 0x0b, 0x6a, 0x03, 0x4c, 0x52, 0xf7, 0xb2, 0x1d, 0x07, 0xae, 0x81, 0x3d, + /*40b0:*/ 0xf1, 0xfd, 0x8e, 0xcc, 0x3a, 0x47, 0x6e, 0xa9, 0x19, 0xf7, 0x16, 0x8e, 0x15, 0x93, 0x56, 0x20, + /*40c0:*/ 0x7e, 0x67, 0xd3, 0x17, 0xcb, 0xfa, 0x4b, 0xf1, 0x63, 0x02, 0x81, 0x14, 0x1e, 0xbd, 0x73, 0x95, + /*40d0:*/ 0xcc, 0xfd, 0x70, 0xa6, 0x30, 0x3e, 0x41, 0x64, 0x5a, 0x12, 0xc6, 0x50, 0x28, 0xf0, 0x83, 0x60, + /*40e0:*/ 0xd7, 0xb9, 0x72, 0x1d, 0x87, 0xab, 0x74, 0xf5, 0xb7, 0x30, 0xa1, 0xae, 0x89, 0x76, 0xfe, 0x92, + /*40f0:*/ 0x07, 0x34, 0x78, 0x8e, 0x8b, 0xb1, 0x44, 0x85, 0x37, 0xcf, 0xe8, 0x56, 0xe7, 0xaa, 0xa9, 0x70, + /*4100:*/ 0xe9, 0x79, 0x59, 0xa6, 0x3c, 0x9d, 0xad, 0xc5, 0x0f, 0x7d, 0x3c, 0x8e, 0xb9, 0xdc, 0xd4, 0xf7, + /*4110:*/ 0xe4, 0xcd, 0xa7, 0x27, 0xfd, 0x20, 0x33, 0x9d, 0x64, 0xcd, 0xcc, 0xaf, 0xb9, 0x43, 0xc6, 0x6b, + /*4120:*/ 0xcd, 0xaa, 0xf8, 0x8a, 0x97, 0x30, 0x95, 0xcc, 0xf2, 0x9f, 0x70, 0x25, 0x3f, 0x7b, 0x27, 0x0f, + /*4130:*/ 0xc2, 0x0f, 0xd7, 0x33, 0xde, 0x08, 0x90, 0xc2, 0x5d, 0xb5, 0xc0, 0x1a, 0x39, 0x86, 0xb3, 0x62, + /*4140:*/ 0xeb, 0x19, 0xee, 0x4c, 0x10, 0xe6, 0x75, 0x40, 0x7a, 0x9d, 0x8f, 0x80, 0x39, 0x75, 0x77, 0x37, + /*4150:*/ 0x27, 0x4e, 0x36, 0xa6, 0xc6, 0x7a, 0xb9, 0x0d, 0x7c, 0x5c, 0x7f, 0xbc, 0xe5, 0x9c, 0xe2, 0x13, + /*4160:*/ 0xfe, 0x3f, 0xc6, 0x30, 0xf8, 0xbb, 0xe6, 0x19, 0xcf, 0x2e, 0xfb, 0x6c, 0x10, 0x38, 0x61, 0x72, + /*4170:*/ 0xe3, 0x32, 0xfc, 0xcb, 0x72, 0x88, 0x6b, 0x62, 0x20, 0x32, 0x0b, 0xbc, 0xc3, 0xfd, 0x23, 0x9c, + /*4180:*/ 0xad, 0x96, 0xa7, 0xa4, 0x4e, 0x40, 0xfc, 0xac, 0x04, 0xbc, 0x8e, 0x17, 0x43, 0xba, 0x2b, 0xbf, + /*4190:*/ 0x0a, 0x5f, 0x2b, 0xaa, 0x74, 0x06, 0x1f, 0x75, 0x8e, 0xa4, 0x57, 0xdf, 0x1e, 0x4c, 0xfa, 0xb9, + /*41a0:*/ 0xb4, 0x33, 0x72, 0xd7, 0x88, 0x6b, 0x19, 0xb0, 0x36, 0x76, 0x07, 0xb2, 0x79, 0x77, 0x50, 0xc1, + /*41b0:*/ 0xb9, 0xa5, 0x28, 0x8d, 0xc8, 0x70, 0x3d, 0xdf, 0xe9, 0x96, 0x49, 0xf4, 0xbd, 0xed, 0x62, 0x3c, + /*41c0:*/ 0xe0, 0x63, 0x41, 0x84, 0x55, 0xef, 0x54, 0x2f, 0xb4, 0x94, 0x7d, 0x32, 0x56, 0x01, 0x04, 0x40, + /*41d0:*/ 0x73, 0x43, 0xdd, 0x84, 0xbe, 0xe6, 0x2f, 0xa1, 0xa7, 0xec, 0xed, 0x6f, 0x45, 0xd3, 0x74, 0x58, + /*41e0:*/ 0x5f, 0xae, 0x10, 0x4a, 0xe3, 0x7e, 0xc9, 0xca, 0xee, 0xe0, 0x05, 0xc5, 0x95, 0x34, 0xff, 0x5e, + /*41f0:*/ 0xda, 0x21, 0xf3, 0x49, 0x80, 0xf8, 0xd8, 0x33, 0x3a, 0x93, 0xab, 0xdd, 0x76, 0xdc, 0x77, 0x06, + /*4200:*/ 0x83, 0x9b, 0x67, 0x8a, 0xa0, 0x72, 0x2a, 0x32, 0x24, 0x00, 0x85, 0x1e, 0x27, 0x22, 0x91, 0x85, + /*4210:*/ 0xde, 0xb0, 0x9b, 0xc0, 0xa8, 0x03, 0x90, 0x9e, 0xe3, 0x18, 0x64, 0x91, 0x2c, 0xaa, 0x21, 0xbb, + /*4220:*/ 0xca, 0x34, 0x42, 0x9c, 0xcd, 0x73, 0x5e, 0xff, 0x7a, 0x9a, 0xc0, 0x1c, 0x6e, 0xb2, 0x45, 0xec, + /*4230:*/ 0x09, 0xe4, 0xed, 0x3f, 0xa2, 0xf2, 0x82, 0xa8, 0xa3, 0xc0, 0xd3, 0x4e, 0xbc, 0xe5, 0x11, 0x9b, + /*4240:*/ 0x5e, 0x3d, 0x0e, 0x1e, 0xcc, 0x85, 0x4c, 0x5d, 0x97, 0xa6, 0xa2, 0xe7, 0x90, 0xad, 0x0a, 0xf5, + /*4250:*/ 0x83, 0x65, 0xc6, 0xcc, 0x4f, 0x52, 0xe0, 0x38, 0xe9, 0x25, 0xa7, 0x83, 0x03, 0x4a, 0x0f, 0x72, + /*4260:*/ 0xe5, 0xc9, 0x36, 0x32, 0xb9, 0x7d, 0x58, 0xa2, 0x05, 0x0e, 0x30, 0x13, 0xd3, 0xfc, 0x30, 0x86, + /*4270:*/ 0xbd, 0xab, 0x67, 0xcf, 0x86, 0x4d, 0xa5, 0xfe, 0x6d, 0xb5, 0x91, 0x1e, 0xcf, 0x44, 0xc8, 0x40, + /*4280:*/ 0x2b, 0xaa, 0x96, 0x33, 0xb5, 0x8e, 0x32, 0x59, 0x0d, 0x0c, 0x6d, 0x91, 0x24, 0x7a, 0x49, 0x1a, + /*4290:*/ 0x8d, 0x8f, 0x14, 0xa6, 0x25, 0x35, 0xef, 0x8f, 0xb6, 0x53, 0xaf, 0xe2, 0xa5, 0xa4, 0x3d, 0x19, + /*42a0:*/ 0x9e, 0x61, 0x5c, 0x38, 0x60, 0xdc, 0x7a, 0x90, 0xda, 0xb0, 0xc7, 0x78, 0x2d, 0xc9, 0x8e, 0xc4, + /*42b0:*/ 0x2a, 0xe5, 0x9d, 0x10, 0x26, 0xef, 0x4f, 0x79, 0xf2, 0xf7, 0x89, 0x79, 0xdb, 0xc1, 0xf3, 0xc3, + /*42c0:*/ 0x38, 0x6a, 0xd3, 0x59, 0x31, 0x69, 0xfd, 0xd6, 0x9d, 0x26, 0x54, 0x44, 0x0e, 0x2b, 0xc5, 0x9a, + /*42d0:*/ 0x9f, 0x77, 0xb7, 0x73, 0x40, 0xc5, 0xa2, 0x46, 0x3b, 0xb9, 0xb6, 0xab, 0x58, 0x93, 0x88, 0x9c, + /*42e0:*/ 0xe5, 0xae, 0x1b, 0x90, 0xf8, 0xdf, 0xdf, 0xd6, 0x4d, 0x2e, 0x3b, 0xeb, 0x3a, 0x6f, 0xe3, 0x28, + /*42f0:*/ 0x73, 0x32, 0x71, 0xb3, 0x7c, 0xd8, 0x7a, 0xa2, 0xfc, 0x61, 0x56, 0x2c, 0x89, 0x63, 0x16, 0xbd, + /*4300:*/ 0xea, 0xd2, 0x49, 0x1b, 0x43, 0xcf, 0x2a, 0xce, 0xd2, 0x00, 0xe8, 0xef, 0x60, 0xf9, 0x9e, 0x41, + /*4310:*/ 0x23, 0xde, 0x64, 0xa1, 0x05, 0x64, 0x55, 0xdb, 0xb0, 0xac, 0x37, 0xd1, 0x41, 0xd4, 0xfa, 0xde, + /*4320:*/ 0x9c, 0x18, 0x46, 0x59, 0xac, 0x51, 0xc4, 0xd4, 0xb9, 0x4c, 0x35, 0xfa, 0xcd, 0xfd, 0x23, 0xde, + /*4330:*/ 0xa8, 0x5d, 0x7c, 0xdb, 0xa1, 0x1a, 0x99, 0x9d, 0x21, 0x12, 0x81, 0xa8, 0xd1, 0x20, 0xc2, 0xd4, + /*4340:*/ 0x6c, 0xe9, 0x8b, 0x16, 0x22, 0x55, 0x5b, 0x0e, 0x1d, 0xde, 0x36, 0x54, 0x96, 0x76, 0x51, 0x36, + /*4350:*/ 0x13, 0x4a, 0x9f, 0x0f, 0x42, 0x11, 0xb2, 0x8a, 0x69, 0xec, 0x5b, 0xbd, 0xbd, 0xe6, 0x90, 0x1d, + /*4360:*/ 0x6f, 0x36, 0x18, 0x6d, 0x71, 0x18, 0x6b, 0xa0, 0x08, 0x0c, 0x6a, 0xbd, 0xc9, 0xc9, 0x03, 0xbb, + /*4370:*/ 0x2b, 0x13, 0xc4, 0x81, 0xd4, 0x98, 0xaa, 0x33, 0xa7, 0x7c, 0x9d, 0x2a, 0xcf, 0xf4, 0xc8, 0x33, + /*4380:*/ 0xc8, 0x54, 0x80, 0x2e, 0x85, 0x05, 0xf3, 0x67, 0x34, 0x07, 0xe1, 0x5c, 0x49, 0x4a, 0x72, 0x7e, + /*4390:*/ 0x1b, 0x64, 0xc1, 0x66, 0xe8, 0x3d, 0x30, 0x38, 0x8c, 0x58, 0x3c, 0x0f, 0x64, 0x54, 0x9b, 0x1b, + /*43a0:*/ 0x5e, 0xb7, 0x87, 0x95, 0xf7, 0x92, 0xbe, 0x4c, 0x42, 0x03, 0x77, 0x74, 0xea, 0x9e, 0xf3, 0x92, + /*43b0:*/ 0x94, 0x0d, 0x47, 0x33, 0x23, 0x88, 0x74, 0x71, 0x47, 0xab, 0x1d, 0xd5, 0x92, 0x81, 0x73, 0x66, + /*43c0:*/ 0x62, 0xc3, 0x27, 0xe5, 0xe0, 0x84, 0xfa, 0xe4, 0x6a, 0x2e, 0x07, 0xea, 0xdb, 0x44, 0x24, 0xef, + /*43d0:*/ 0x8a, 0xb0, 0x5e, 0xb0, 0x61, 0x03, 0x9c, 0xf8, 0xc7, 0xc8, 0x34, 0x1b, 0x87, 0xc7, 0xf1, 0x3b, + /*43e0:*/ 0xb5, 0x7e, 0xb7, 0x37, 0x4d, 0x3a, 0xb7, 0x4b, 0x2e, 0x21, 0xe2, 0x3e, 0x0d, 0xe7, 0x07, 0x3c, + /*43f0:*/ 0x43, 0xb2, 0x6d, 0x87, 0xa9, 0x79, 0x96, 0x86, 0x0c, 0x0e, 0xbc, 0x0d, 0x5e, 0x5b, 0x9f, 0xbf, + /*4400:*/ 0xc0, 0xfe, 0x4b, 0x81, 0xa2, 0x91, 0x39, 0xf9, 0x59, 0xfa, 0x96, 0x80, 0x2a, 0x90, 0x13, 0x4c, + /*4410:*/ 0x4e, 0x08, 0x1e, 0xcc, 0xfe, 0x1f, 0x94, 0x2b, 0x1b, 0x3f, 0x80, 0xa2, 0x03, 0xc2, 0xee, 0x37, + /*4420:*/ 0x52, 0xa2, 0xb7, 0xfb, 0x2c, 0x42, 0xe6, 0xd9, 0x57, 0xa4, 0xdd, 0x41, 0x02, 0xfc, 0x9f, 0x40, + /*4430:*/ 0x62, 0xb8, 0xc6, 0x4b, 0x42, 0xe4, 0xd8, 0x50, 0x47, 0xad, 0xea, 0x55, 0x21, 0xe7, 0xbb, 0xa4, + /*4440:*/ 0xf5, 0x07, 0x70, 0x6f, 0xba, 0x7e, 0x30, 0x31, 0x03, 0x15, 0x9d, 0x44, 0x29, 0x16, 0xe0, 0x95, + /*4450:*/ 0x67, 0xf0, 0x4b, 0x27, 0x94, 0xaf, 0x48, 0x2f, 0x3d, 0xe8, 0x8c, 0x64, 0x47, 0x32, 0xa0, 0xb7, + /*4460:*/ 0x23, 0x27, 0xbf, 0xca, 0xdf, 0x6a, 0xc1, 0x41, 0x19, 0x82, 0xd4, 0x97, 0xee, 0x24, 0xbc, 0x65, + /*4470:*/ 0xd3, 0x8b, 0x10, 0xf8, 0x1b, 0x70, 0xe1, 0x5c, 0xeb, 0xa2, 0xa9, 0x89, 0x62, 0xec, 0xaa, 0xf6, + /*4480:*/ 0xb1, 0xda, 0xf9, 0xe5, 0x0c, 0x47, 0xa0, 0x06, 0x93, 0x6c, 0x54, 0xea, 0x48, 0x9d, 0x57, 0x90, + /*4490:*/ 0x8f, 0x5f, 0xd0, 0x6f, 0x97, 0x2a, 0x64, 0x46, 0x05, 0x22, 0x5a, 0xda, 0xbd, 0xb0, 0x47, 0x73, + /*44a0:*/ 0x62, 0x2c, 0x75, 0xcb, 0xed, 0x7d, 0x0b, 0x14, 0x30, 0xb3, 0x78, 0x4c, 0xe7, 0x9c, 0xaf, 0x9b, + /*44b0:*/ 0x7a, 0x97, 0xde, 0x12, 0xac, 0x5e, 0x6a, 0x96, 0xd7, 0xfd, 0x8c, 0x3f, 0xe8, 0xed, 0x61, 0x1d, + /*44c0:*/ 0x5e, 0xcf, 0xfb, 0xb9, 0x49, 0x80, 0xde, 0x1b, 0xb8, 0x12, 0x81, 0x5a, 0xdb, 0xd6, 0xb7, 0x0f, + /*44d0:*/ 0x50, 0xf5, 0x7e, 0xf8, 0xa6, 0xcc, 0xfa, 0x86, 0x25, 0xdb, 0xd1, 0xd1, 0xfb, 0x99, 0xbe, 0x28, + /*44e0:*/ 0x60, 0xc9, 0x83, 0xe6, 0x64, 0x56, 0xf6, 0x15, 0x8d, 0xf0, 0xad, 0xd2, 0x3f, 0x6f, 0x18, 0xe8, + /*44f0:*/ 0xee, 0x3c, 0x25, 0x52, 0x3f, 0x32, 0x29, 0x99, 0x36, 0xc2, 0x18, 0xb0, 0xea, 0xc5, 0x87, 0x60, + /*4500:*/ 0xda, 0xe4, 0x78, 0x89, 0xee, 0xaa, 0x9d, 0x4e, 0xfa, 0xca, 0xe1, 0xbe, 0xda, 0x46, 0x22, 0x28, + /*4510:*/ 0x13, 0x0e, 0xf1, 0x8e, 0x15, 0x6d, 0x68, 0x07, 0xc5, 0x0a, 0x41, 0x4f, 0x2d, 0xd6, 0x0c, 0x89, + /*4520:*/ 0x13, 0x5b, 0x79, 0x46, 0x0e, 0x14, 0x4d, 0x8a, 0xb1, 0xe0, 0x6e, 0xcc, 0x46, 0xa2, 0x35, 0xa6, + /*4530:*/ 0xf0, 0x61, 0x80, 0xe8, 0xd0, 0x24, 0xab, 0x1d, 0xa4, 0x28, 0x93, 0xb8, 0x87, 0xa5, 0xd0, 0xe4, + /*4540:*/ 0x9c, 0xfd, 0x29, 0x75, 0x8e, 0x85, 0x20, 0x25, 0xcb, 0xbb, 0x21, 0x20, 0xf9, 0x31, 0x07, 0xaf, + /*4550:*/ 0x5d, 0xf7, 0xc1, 0x7f, 0x89, 0xad, 0xab, 0xbf, 0x65, 0xf8, 0x71, 0xb0, 0x7f, 0xd2, 0xad, 0xd1, + /*4560:*/ 0x51, 0x48, 0x9f, 0xf0, 0xaa, 0xc0, 0xde, 0x60, 0x40, 0xe4, 0x2b, 0xb5, 0x0e, 0x24, 0xdd, 0xfa, + /*4570:*/ 0x0f, 0x52, 0xc3, 0x6e, 0xcc, 0xa2, 0xb9, 0x32, 0x30, 0x92, 0x24, 0x51, 0xb9, 0xff, 0x7d, 0xef, + /*4580:*/ 0x5b, 0x6c, 0xf2, 0xde, 0x08, 0x11, 0x94, 0x52, 0xac, 0x53, 0xd3, 0xc5, 0x97, 0xd6, 0xd2, 0x78, + /*4590:*/ 0x1c, 0x70, 0xea, 0xd8, 0x81, 0x7f, 0xd6, 0x3b, 0x27, 0x6f, 0x94, 0x59, 0x98, 0xcf, 0x5d, 0x06, + /*45a0:*/ 0x9b, 0x97, 0x47, 0xf9, 0x4f, 0x50, 0xb9, 0x56, 0x36, 0xb5, 0xb6, 0xb9, 0xe3, 0xe2, 0xce, 0x63, + /*45b0:*/ 0x0c, 0x3f, 0xc5, 0xe1, 0xde, 0x8f, 0xcb, 0x8b, 0x36, 0x8d, 0x8d, 0xb9, 0xa6, 0xfb, 0x1b, 0xe4, + /*45c0:*/ 0xe9, 0xea, 0xd0, 0xf0, 0x75, 0x2e, 0x75, 0x58, 0xfc, 0x48, 0x49, 0xad, 0x97, 0x3e, 0xc8, 0xdd, + /*45d0:*/ 0x12, 0x78, 0x79, 0xd1, 0xdc, 0xd7, 0x49, 0x05, 0x65, 0x64, 0x26, 0x9e, 0x00, 0xf5, 0x2b, 0xc2, + /*45e0:*/ 0x03, 0x74, 0xb3, 0x23, 0x74, 0xd5, 0xb4, 0x4b, 0xb4, 0x6e, 0x0e, 0x1e, 0xb3, 0xae, 0x14, 0xe2, + /*45f0:*/ 0xe8, 0xfb, 0xc2, 0xf6, 0xd5, 0x99, 0xd2, 0x90, 0x27, 0x13, 0xf9, 0x20, 0x7b, 0xd0, 0x76, 0x95, + /*4600:*/ 0x67, 0x45, 0x7a, 0x9b, 0x3c, 0x41, 0xc0, 0x6e, 0x6c, 0x2f, 0x0a, 0xe9, 0xcc, 0xa5, 0x8b, 0x41, + /*4610:*/ 0x8c, 0x27, 0xd6, 0xce, 0xde, 0x8f, 0x02, 0xd3, 0xad, 0xd5, 0x88, 0x19, 0xbb, 0xeb, 0xb8, 0x3c, + /*4620:*/ 0x45, 0xea, 0xff, 0xe8, 0x10, 0x93, 0xaf, 0xab, 0x24, 0xff, 0x10, 0x8e, 0x60, 0x92, 0x88, 0x0c, + /*4630:*/ 0x42, 0x17, 0xf4, 0x42, 0xbc, 0x7e, 0xfe, 0xbf, 0x14, 0x09, 0x6f, 0xff, 0xa2, 0x42, 0x43, 0x97, + /*4640:*/ 0x5f, 0x24, 0xae, 0xa1, 0xcf, 0x48, 0xe6, 0x35, 0x3f, 0x12, 0x55, 0x38, 0x0a, 0x91, 0x05, 0x46, + /*4650:*/ 0x9d, 0x80, 0xb3, 0x75, 0x24, 0x64, 0x19, 0x8e, 0xea, 0x65, 0x94, 0x22, 0xfe, 0x6c, 0xa4, 0x82, + /*4660:*/ 0x16, 0x96, 0x7f, 0x57, 0x4b, 0x72, 0x54, 0x9e, 0x84, 0x22, 0x06, 0x64, 0x24, 0xe1, 0x50, 0xc7, + /*4670:*/ 0x78, 0xb8, 0xa4, 0xb4, 0xfe, 0x60, 0xa1, 0x0c, 0xf6, 0xba, 0xdd, 0x93, 0x0f, 0xf5, 0x36, 0xe2, + /*4680:*/ 0xb6, 0x9c, 0xd3, 0xc8, 0x96, 0xb4, 0xd2, 0x02, 0x38, 0x42, 0x9a, 0x2f, 0x1b, 0x46, 0xd2, 0x20, + /*4690:*/ 0xc6, 0x90, 0xd5, 0xd4, 0x42, 0xf0, 0xd5, 0x14, 0xd1, 0xb1, 0xec, 0x02, 0x41, 0x25, 0xbb, 0x35, + /*46a0:*/ 0x0b, 0x9a, 0x66, 0x1d, 0xc8, 0xf9, 0xc1, 0x6a, 0x59, 0xfc, 0xc5, 0x57, 0xda, 0xdf, 0xe2, 0x8a, + /*46b0:*/ 0x8b, 0x1b, 0x21, 0x1d, 0x45, 0x76, 0x57, 0x8a, 0x0c, 0xd8, 0x21, 0xa0, 0x34, 0x42, 0xeb, 0xa7, + /*46c0:*/ 0x01, 0x62, 0x5f, 0x5d, 0xf5, 0x12, 0x44, 0x42, 0x4a, 0xb1, 0x2c, 0x9a, 0x44, 0x79, 0x9e, 0x6b, + /*46d0:*/ 0xde, 0xbf, 0x13, 0x8c, 0x22, 0x4f, 0xe7, 0x50, 0xd4, 0x0a, 0x18, 0x4f, 0x50, 0xf0, 0xbb, 0x16, + /*46e0:*/ 0xf5, 0x57, 0x2c, 0xd8, 0x66, 0x3f, 0x83, 0x62, 0xe8, 0x5a, 0xd4, 0x05, 0x67, 0xe0, 0xa7, 0x40, + /*46f0:*/ 0x08, 0xc3, 0x9e, 0x5b, 0xbb, 0x3a, 0xd3, 0x44, 0x15, 0xa6, 0xb3, 0x12, 0xea, 0x89, 0xd9, 0xbc, + /*4700:*/ 0xc1, 0xc8, 0x01, 0x39, 0x1c, 0xc7, 0xc0, 0xfa, 0xea, 0x85, 0xf9, 0x27, 0xe9, 0x10, 0x93, 0x49, + /*4710:*/ 0x5e, 0xa2, 0xb2, 0x40, 0xf3, 0x6f, 0xd1, 0xfb, 0x67, 0xfa, 0x1e, 0x44, 0xc5, 0x7d, 0x49, 0xbe, + /*4720:*/ 0xeb, 0xff, 0x2b, 0x0d, 0xcd, 0x82, 0xd5, 0x42, 0xd1, 0xf2, 0x26, 0x78, 0x8e, 0xec, 0x67, 0x01, + /*4730:*/ 0xb0, 0x5f, 0x0b, 0x28, 0x59, 0x49, 0x8d, 0x2d, 0x77, 0x30, 0x77, 0xfb, 0xf0, 0x1b, 0x1a, 0x83, + /*4740:*/ 0x93, 0x22, 0x0c, 0x92, 0xa5, 0x74, 0xbb, 0xe2, 0xa6, 0xe5, 0x9e, 0x86, 0x6c, 0x34, 0xee, 0x28, + /*4750:*/ 0xec, 0x81, 0xdc, 0x1f, 0x78, 0x54, 0x2c, 0x5a, 0xe6, 0xdf, 0x37, 0x61, 0xd1, 0x9b, 0x75, 0x87, + /*4760:*/ 0xc8, 0xe7, 0x9e, 0x1a, 0x26, 0x82, 0x16, 0xaa, 0x4e, 0x0a, 0xfc, 0xc1, 0xa6, 0xf3, 0xb6, 0xaf, + /*4770:*/ 0x1f, 0xff, 0xc2, 0xb4, 0xb7, 0x33, 0x13, 0xb3, 0xc4, 0xc7, 0x7d, 0xb1, 0xd3, 0x69, 0x5c, 0x8e, + /*4780:*/ 0xe7, 0x49, 0x52, 0x47, 0x16, 0x28, 0x14, 0x4a, 0x54, 0xb5, 0xe3, 0xa8, 0x62, 0x2d, 0x22, 0xb1, + /*4790:*/ 0x78, 0xe2, 0x15, 0x63, 0x6f, 0x0f, 0x7e, 0x5c, 0x3b, 0xc3, 0x12, 0xfd, 0x67, 0x62, 0x24, 0x12, + /*47a0:*/ 0x96, 0x75, 0x30, 0x87, 0x77, 0x81, 0x49, 0xa8, 0x95, 0x3b, 0x94, 0xb8, 0x32, 0x24, 0x65, 0xe5, + /*47b0:*/ 0xd7, 0x05, 0x07, 0xf4, 0xa2, 0xc7, 0x67, 0x1d, 0x0a, 0xc4, 0xee, 0x25, 0xf9, 0x6a, 0xc2, 0xf3, + /*47c0:*/ 0x06, 0xd9, 0xcc, 0x48, 0x0f, 0x85, 0xb0, 0x93, 0xdb, 0x27, 0x46, 0xfe, 0xc7, 0x8d, 0xcb, 0x02, + /*47d0:*/ 0xd5, 0xad, 0x0c, 0x18, 0xc1, 0x19, 0xab, 0xd5, 0xd9, 0xbf, 0x7a, 0xfe, 0xc1, 0x27, 0x80, 0xca, + /*47e0:*/ 0xca, 0x14, 0x1f, 0x4f, 0x64, 0xfb, 0xe5, 0x03, 0x28, 0x16, 0xa2, 0xc9, 0x09, 0x93, 0xdd, 0x40, + /*47f0:*/ 0xc3, 0x2f, 0x46, 0xd5, 0xcf, 0x29, 0xe0, 0x9c, 0xab, 0x0a, 0x5b, 0xab, 0xbd, 0x0e, 0x28, 0x16, + /*4800:*/ 0xc6, 0x5d, 0x3f, 0x5e, 0x41, 0x5a, 0x35, 0xd0, 0x3b, 0x9f, 0x49, 0x25, 0x00, 0x4b, 0x81, 0xda, + /*4810:*/ 0x04, 0xd4, 0x03, 0xe3, 0xd8, 0xb3, 0x51, 0xba, 0x4c, 0xe2, 0x1c, 0xb8, 0x9a, 0xaa, 0x0d, 0x00, + /*4820:*/ 0x21, 0x93, 0x0a, 0xcb, 0xa4, 0x1e, 0xf9, 0x50, 0x9f, 0xf0, 0xa3, 0x01, 0x84, 0xf1, 0xcf, 0x7f, + /*4830:*/ 0x93, 0x19, 0xbd, 0x53, 0x0c, 0xd1, 0x89, 0xe6, 0x2f, 0x10, 0x80, 0x91, 0x33, 0xb7, 0x99, 0xaa, + /*4840:*/ 0xe1, 0x26, 0xf7, 0xde, 0x76, 0x09, 0xf6, 0x45, 0x89, 0x33, 0xd0, 0xf0, 0xf8, 0xf6, 0xd4, 0x59, + /*4850:*/ 0x94, 0xf9, 0x06, 0xe5, 0x7c, 0xb4, 0x61, 0xac, 0x2f, 0x9a, 0x8e, 0x2d, 0x28, 0x37, 0x11, 0x3a, + /*4860:*/ 0x1d, 0xf7, 0x06, 0x79, 0x52, 0x8b, 0xa9, 0xd9, 0xa8, 0x89, 0xfc, 0xb4, 0xbf, 0xbe, 0x56, 0xfd, + /*4870:*/ 0x8a, 0x62, 0x89, 0x21, 0x6a, 0x58, 0x03, 0x22, 0x43, 0x56, 0x33, 0xca, 0x3e, 0x2a, 0x87, 0x66, + /*4880:*/ 0x16, 0xda, 0xb5, 0x96, 0x51, 0x86, 0xb9, 0x7e, 0x6d, 0xb5, 0xb5, 0xb2, 0x57, 0x5b, 0x75, 0xd5, + /*4890:*/ 0xd5, 0xc2, 0x72, 0x7b, 0x9e, 0xa5, 0xab, 0x45, 0x71, 0x77, 0x87, 0xc8, 0xb7, 0x0d, 0xbd, 0xea, + /*48a0:*/ 0x29, 0xd1, 0xc3, 0x15, 0x55, 0xa5, 0x16, 0x4c, 0x38, 0xa8, 0x86, 0x66, 0xd5, 0x7a, 0xf4, 0x47, + /*48b0:*/ 0x63, 0xb5, 0x01, 0x99, 0xec, 0xbb, 0x7e, 0x72, 0x4d, 0x6c, 0x49, 0x55, 0xde, 0xc1, 0xfa, 0xd9, + /*48c0:*/ 0x34, 0x60, 0x48, 0x48, 0x14, 0x9d, 0xb9, 0x9e, 0x5f, 0x2b, 0x7b, 0xbd, 0x68, 0x6a, 0xb2, 0x6d, + /*48d0:*/ 0xc6, 0x0b, 0x89, 0xbb, 0x84, 0xdd, 0x33, 0x5c, 0xc1, 0x36, 0x5e, 0xeb, 0x71, 0x39, 0x32, 0xd3, + /*48e0:*/ 0xdf, 0xdd, 0xd4, 0x46, 0x8d, 0x63, 0xaa, 0xea, 0x47, 0xc4, 0x15, 0x01, 0xe3, 0x37, 0xfc, 0x91, + /*48f0:*/ 0x92, 0xca, 0x90, 0xb5, 0xa0, 0x8d, 0xd7, 0xdb, 0x7a, 0xe2, 0x9d, 0x82, 0x7f, 0xb7, 0x40, 0x72, + /*4900:*/ 0xfb, 0x5e, 0xc9, 0x5a, 0xf9, 0xcf, 0xa8, 0x9f, 0x42, 0xa6, 0x66, 0xa6, 0x91, 0x41, 0x6c, 0xf8, + /*4910:*/ 0x59, 0xbf, 0x9e, 0xbb, 0x62, 0xab, 0x05, 0x1f, 0x19, 0x6e, 0x5f, 0x23, 0x48, 0x85, 0xa7, 0xaf, + /*4920:*/ 0xeb, 0x26, 0x7f, 0xb3, 0x42, 0xfe, 0x37, 0xd6, 0xa0, 0x9f, 0x47, 0xb3, 0x3a, 0x05, 0x6c, 0x78, + /*4930:*/ 0x08, 0x5d, 0xaa, 0x19, 0x37, 0xff, 0x69, 0x0d, 0x96, 0x2a, 0xd2, 0x8a, 0x0d, 0x7f, 0xbf, 0x5b, + /*4940:*/ 0x26, 0x40, 0x3e, 0x47, 0x30, 0xb5, 0xc1, 0x48, 0xa5, 0x4e, 0x76, 0xae, 0x8d, 0xba, 0x5b, 0x0b, + /*4950:*/ 0x22, 0xef, 0xdf, 0xa5, 0x33, 0xc6, 0xe9, 0x79, 0x5d, 0x1e, 0x6a, 0xec, 0xa2, 0xa6, 0xfa, 0x5f, + /*4960:*/ 0xac, 0x42, 0x67, 0x60, 0x06, 0x65, 0x6b, 0xf2, 0x3d, 0xbf, 0x92, 0x54, 0xfb, 0xe8, 0x7e, 0x1a, + /*4970:*/ 0xb5, 0x9b, 0x57, 0x86, 0x21, 0xc4, 0x80, 0x50, 0x54, 0xe7, 0xfc, 0x10, 0x9c, 0xb5, 0xde, 0x50, + /*4980:*/ 0x13, 0x92, 0x3a, 0x85, 0x09, 0xd3, 0x02, 0xa2, 0xf0, 0x38, 0xf0, 0x6d, 0x98, 0x9a, 0x59, 0x92, + /*4990:*/ 0xad, 0x89, 0x0d, 0xfd, 0xdf, 0x84, 0xbb, 0x77, 0x2d, 0x4c, 0xbb, 0x8c, 0xa5, 0xe2, 0xea, 0x45, + /*49a0:*/ 0xfd, 0x40, 0x07, 0xbc, 0xa0, 0xf0, 0x84, 0x48, 0x17, 0xd2, 0x58, 0x94, 0xbf, 0x89, 0x04, 0x7e, + /*49b0:*/ 0x6e, 0xc9, 0x7a, 0xcc, 0x4a, 0x65, 0xf7, 0xb4, 0xf4, 0x2f, 0xae, 0x6e, 0xae, 0x7f, 0x1c, 0xa7, + /*49c0:*/ 0xda, 0xce, 0x73, 0xda, 0x7c, 0x9c, 0xed, 0x7c, 0x5c, 0xc6, 0x56, 0x8b, 0xc7, 0xc1, 0x53, 0xb4, + /*49d0:*/ 0x5a, 0x30, 0x70, 0x09, 0xd7, 0xdd, 0x20, 0xd0, 0x2a, 0x47, 0x82, 0xb2, 0xa1, 0xd5, 0x69, 0x0a, + /*49e0:*/ 0xc1, 0xf8, 0xe9, 0x69, 0x60, 0x17, 0x3f, 0x4c, 0x79, 0x92, 0x33, 0x16, 0x92, 0xbf, 0x4a, 0x73, + /*49f0:*/ 0x7f, 0x0a, 0xd1, 0x96, 0x83, 0x53, 0x1c, 0x01, 0x01, 0x5d, 0xe4, 0xf1, 0xe3, 0xa1, 0xc4, 0x91, + /*4a00:*/ 0x71, 0x14, 0xbf, 0x60, 0x5a, 0xf5, 0x95, 0x0a, 0x45, 0x35, 0x39, 0x81, 0xea, 0xd4, 0x66, 0x69, + /*4a10:*/ 0xa6, 0x12, 0x6d, 0xa8, 0xb8, 0x32, 0x92, 0x1b, 0xa4, 0x59, 0x46, 0x6c, 0x8c, 0xed, 0xc0, 0x4c, + /*4a20:*/ 0x55, 0x99, 0xb3, 0xc1, 0x51, 0xfa, 0x30, 0xf0, 0x54, 0x2f, 0x6e, 0x7d, 0xbc, 0xb3, 0x9a, 0x9d, + /*4a30:*/ 0x27, 0x42, 0x30, 0xbf, 0x0e, 0x41, 0x87, 0x65, 0x70, 0x10, 0xbc, 0xf1, 0x4b, 0x3e, 0x64, 0x48, + /*4a40:*/ 0x88, 0xfb, 0xfa, 0x1b, 0x9a, 0xcb, 0xf5, 0xf7, 0x5c, 0xf8, 0xcc, 0xb2, 0xad, 0xc7, 0x96, 0x16, + /*4a50:*/ 0x36, 0xe4, 0x8c, 0x23, 0x21, 0x38, 0x60, 0x6c, 0x6d, 0xaa, 0xef, 0xc9, 0x26, 0xde, 0x1f, 0x17, + /*4a60:*/ 0xad, 0x4a, 0xa6, 0xbb, 0xcb, 0xce, 0x76, 0x40, 0x5e, 0x86, 0xdb, 0x97, 0x1f, 0x70, 0x86, 0xf7, + /*4a70:*/ 0x8f, 0xf8, 0x11, 0x39, 0x03, 0xc7, 0x0c, 0xcc, 0x71, 0x29, 0x00, 0x2a, 0x4e, 0x62, 0x49, 0xad, + /*4a80:*/ 0xb0, 0xfa, 0xfb, 0x80, 0x2e, 0xe8, 0x70, 0x73, 0x57, 0x42, 0xd3, 0xc0, 0x68, 0x7e, 0xaa, 0x0a, + /*4a90:*/ 0xdb, 0x99, 0x89, 0x07, 0x8a, 0x6d, 0x4c, 0x9c, 0xbc, 0x33, 0x4f, 0xee, 0x7f, 0x27, 0x45, 0x0f, + /*4aa0:*/ 0x7f, 0x16, 0xcb, 0x5b, 0xd7, 0x88, 0x9a, 0xbf, 0x4b, 0x98, 0x01, 0x1c, 0xaf, 0x06, 0x7f, 0x1e, + /*4ab0:*/ 0x4d, 0x07, 0x70, 0xb8, 0x7f, 0xac, 0xbb, 0x79, 0xc3, 0x10, 0x01, 0xbc, 0x43, 0x97, 0x46, 0x38, + /*4ac0:*/ 0x6e, 0x96, 0x82, 0x31, 0xe6, 0x2e, 0xa0, 0x56, 0xd6, 0xfa, 0xce, 0x3c, 0x43, 0xcd, 0xfe, 0x63, + /*4ad0:*/ 0x3d, 0xd8, 0x48, 0x28, 0x8d, 0x80, 0xb8, 0xe3, 0xfd, 0x3b, 0x74, 0x90, 0xbd, 0x64, 0x2d, 0x3f, + /*4ae0:*/ 0x18, 0x94, 0x39, 0x9c, 0x52, 0x8a, 0x6b, 0x88, 0x7b, 0xd2, 0xa7, 0x89, 0x16, 0x7b, 0x89, 0x45, + /*4af0:*/ 0xdd, 0x0e, 0xf1, 0xc7, 0xc4, 0x9b, 0xb8, 0x90, 0xb8, 0x97, 0x93, 0x4f, 0x98, 0x49, 0xef, 0xef, + /*4b00:*/ 0x0a, 0x78, 0xc9, 0xaf, 0xc3, 0xe2, 0xb6, 0x9c, 0x22, 0x69, 0x8b, 0x86, 0xff, 0x76, 0x04, 0x60, + /*4b10:*/ 0xab, 0x35, 0x92, 0x1c, 0xa8, 0xac, 0xdd, 0x99, 0x09, 0xdf, 0x97, 0xfe, 0x25, 0x86, 0x0a, 0x43, + /*4b20:*/ 0xdd, 0x5c, 0xee, 0x40, 0xdf, 0x68, 0x7b, 0x87, 0x70, 0xd0, 0x45, 0xa9, 0x9c, 0xd8, 0x19, 0xca, + /*4b30:*/ 0xfd, 0x08, 0x4a, 0xfc, 0x26, 0xfb, 0xb0, 0x3d, 0xab, 0xf9, 0x04, 0x77, 0x26, 0xc9, 0x18, 0x45, + /*4b40:*/ 0xdf, 0xf5, 0xed, 0x8a, 0xb6, 0x9a, 0x08, 0x2d, 0xa9, 0xb3, 0xd1, 0xea, 0x82, 0xfd, 0x5c, 0xbf, + /*4b50:*/ 0x32, 0x90, 0xc7, 0x2d, 0x01, 0xf9, 0x56, 0xb0, 0x6b, 0xfe, 0x7a, 0xe2, 0x03, 0x90, 0x48, 0x60, + /*4b60:*/ 0xdc, 0x0b, 0xc9, 0x2f, 0x95, 0xe6, 0x0b, 0x73, 0xb5, 0xeb, 0x3d, 0xfe, 0xbe, 0x7e, 0x89, 0x24, + /*4b70:*/ 0x15, 0x68, 0x08, 0x86, 0x38, 0xad, 0x27, 0x55, 0x9a, 0x56, 0x58, 0x06, 0x0a, 0x4b, 0x78, 0xde, + /*4b80:*/ 0x94, 0xb0, 0xa5, 0x95, 0x10, 0x85, 0x63, 0x8e, 0xcb, 0xd2, 0x26, 0x35, 0x14, 0xa3, 0x1d, 0xd8, + /*4b90:*/ 0x62, 0xc0, 0x42, 0x4c, 0xa4, 0xad, 0x9e, 0x59, 0x50, 0xf8, 0xcf, 0x55, 0xb8, 0x01, 0xfe, 0x68, + /*4ba0:*/ 0x92, 0x08, 0x8b, 0x8d, 0xd8, 0xab, 0x1d, 0xed, 0xec, 0x01, 0xbc, 0xf5, 0xe3, 0x7c, 0x5c, 0x13, + /*4bb0:*/ 0xef, 0x7d, 0x14, 0x21, 0xd1, 0x8e, 0x9b, 0xe4, 0x34, 0x78, 0x59, 0x45, 0x9c, 0x86, 0x37, 0xc2, + /*4bc0:*/ 0x24, 0xd1, 0xeb, 0x14, 0x83, 0x0a, 0x80, 0xde, 0x45, 0xa1, 0x17, 0x41, 0xd1, 0x36, 0x1e, 0x95, + /*4bd0:*/ 0x4d, 0x00, 0x13, 0x2d, 0x15, 0x7d, 0x4b, 0x52, 0x90, 0x32, 0x12, 0xc2, 0x7d, 0x72, 0xaa, 0x2a, + /*4be0:*/ 0x16, 0x54, 0x08, 0xb7, 0x2b, 0x86, 0xa5, 0xa6, 0x62, 0x2c, 0x8a, 0x0d, 0xd8, 0x50, 0x89, 0xf9, + /*4bf0:*/ 0xb2, 0x52, 0xd2, 0xd9, 0xa2, 0xa3, 0x21, 0x14, 0x87, 0x89, 0xe1, 0xe7, 0xce, 0xf0, 0x5f, 0xd8, + /*4c00:*/ 0x75, 0x61, 0xd6, 0x66, 0xcf, 0xda, 0x00, 0x21, 0xa6, 0xf0, 0xb4, 0x41, 0xcf, 0xf4, 0x71, 0x51, + /*4c10:*/ 0xba, 0x27, 0x32, 0x7c, 0x3c, 0xb6, 0xc8, 0x29, 0x53, 0x1f, 0xc5, 0xc1, 0xfd, 0x9f, 0xa8, 0x08, + /*4c20:*/ 0x30, 0x51, 0x7f, 0xf6, 0x8b, 0x6a, 0xa2, 0xbe, 0xd4, 0xf5, 0x15, 0xaf, 0x49, 0x19, 0xb9, 0x8e, + /*4c30:*/ 0x19, 0xfc, 0x70, 0x0c, 0x28, 0xdc, 0xee, 0x85, 0xb7, 0x5b, 0xde, 0x02, 0xdd, 0x85, 0x8c, 0x9b, + /*4c40:*/ 0x78, 0x13, 0x35, 0x1b, 0xd2, 0xe8, 0xcf, 0x9a, 0xc1, 0x3d, 0x21, 0xa2, 0xc5, 0x34, 0xdd, 0x9e, + /*4c50:*/ 0x6f, 0xeb, 0xc4, 0x82, 0x18, 0xd8, 0x5a, 0x31, 0x4a, 0x75, 0x45, 0xc9, 0x6f, 0x56, 0x63, 0x1f, + /*4c60:*/ 0xc9, 0x4d, 0x35, 0x74, 0x58, 0x31, 0xf1, 0x3e, 0xd7, 0xc5, 0x95, 0xf7, 0x29, 0x4f, 0x24, 0xf7, + /*4c70:*/ 0xd9, 0xba, 0xb6, 0x43, 0x34, 0x69, 0x34, 0x04, 0xf0, 0xac, 0x4c, 0x08, 0xed, 0xf9, 0xf4, 0xe3, + /*4c80:*/ 0xdc, 0xc5, 0x3e, 0x4f, 0x65, 0xde, 0xba, 0xb3, 0xaf, 0x6f, 0x1a, 0x1f, 0x21, 0x00, 0x80, 0xc2, + /*4c90:*/ 0x7c, 0x54, 0x55, 0x35, 0x05, 0x23, 0x65, 0x8c, 0x1a, 0x19, 0x2e, 0xd8, 0x4f, 0xfb, 0xb9, 0xfa, + /*4ca0:*/ 0x73, 0x5f, 0x33, 0x0e, 0xfb, 0x32, 0xf5, 0x84, 0x5e, 0xd1, 0x5d, 0x0c, 0x6d, 0x6b, 0x06, 0xc6, + /*4cb0:*/ 0x09, 0x5b, 0x14, 0x40, 0x84, 0x68, 0xca, 0x4e, 0xf3, 0xd0, 0xe0, 0x98, 0x86, 0xbe, 0xb8, 0x60, + /*4cc0:*/ 0x8c, 0xf6, 0xf3, 0x0e, 0xec, 0x70, 0xea, 0x53, 0x19, 0x2c, 0xfb, 0x69, 0x00, 0x37, 0x06, 0x36, + /*4cd0:*/ 0x3b, 0xee, 0xf1, 0x9e, 0xcb, 0xdb, 0x03, 0x00, 0x25, 0x35, 0xa1, 0x7b, 0xb2, 0x79, 0xce, 0x53, + /*4ce0:*/ 0xfe, 0xcb, 0x3c, 0x99, 0xde, 0x50, 0x5a, 0x26, 0xa0, 0xe4, 0x28, 0x96, 0xf6, 0x8d, 0x30, 0x97, + /*4cf0:*/ 0xcd, 0x6e, 0xbb, 0xb0, 0x70, 0x29, 0x60, 0xe8, 0x48, 0x1b, 0xe9, 0xfb, 0xa4, 0x29, 0xea, 0x52, + /*4d00:*/ 0x8f, 0x76, 0x77, 0x1a, 0xdb, 0xcd, 0x39, 0x7a, 0xcf, 0x9d, 0x66, 0xf3, 0x06, 0x9a, 0xb9, 0x80, + /*4d10:*/ 0xb7, 0xe7, 0xab, 0xbd, 0xe3, 0xbe, 0x33, 0xb2, 0x3a, 0x4b, 0x43, 0xc5, 0xa8, 0x91, 0x1c, 0xba, + /*4d20:*/ 0x89, 0xd4, 0x2b, 0xba, 0xfb, 0x91, 0xe0, 0x27, 0xf5, 0x57, 0xd8, 0x2d, 0x7b, 0xad, 0x3d, 0x0d, + /*4d30:*/ 0x2c, 0x21, 0xf8, 0x3a, 0x6a, 0x86, 0xbf, 0x66, 0x35, 0xb2, 0x3a, 0x55, 0xb7, 0x41, 0xf2, 0x8c, + /*4d40:*/ 0x82, 0x2f, 0xf9, 0x36, 0x5e, 0x63, 0xfe, 0x15, 0x23, 0x61, 0xa4, 0xee, 0x53, 0x45, 0xd3, 0xdc, + /*4d50:*/ 0xc5, 0x1b, 0xce, 0xb7, 0x3c, 0x23, 0x6d, 0x40, 0xa1, 0x28, 0x05, 0x0f, 0xd0, 0xb8, 0x9b, 0x48, + /*4d60:*/ 0xb3, 0xe1, 0x91, 0xe1, 0x0e, 0xe5, 0xd3, 0x7e, 0xaa, 0x7a, 0xad, 0xa1, 0xcb, 0xa9, 0x06, 0x4a, + /*4d70:*/ 0x22, 0x57, 0xa1, 0x7b, 0xd9, 0xf5, 0x09, 0x48, 0x09, 0x34, 0x88, 0xcf, 0xfd, 0xf8, 0xdd, 0x3d, + /*4d80:*/ 0xc2, 0x7c, 0x5b, 0x36, 0xb0, 0x53, 0x2f, 0x5f, 0x41, 0x3e, 0x15, 0x71, 0xb0, 0x06, 0x18, 0x68, + /*4d90:*/ 0x64, 0xc8, 0xdb, 0xab, 0x4a, 0x1f, 0xc0, 0x24, 0xd1, 0x4c, 0x59, 0xe8, 0x9e, 0xce, 0x10, 0x16, + /*4da0:*/ 0x68, 0x1f, 0x70, 0x1f, 0x31, 0xde, 0xa3, 0xe2, 0x20, 0xbb, 0xfc, 0x93, 0xa6, 0x43, 0x23, 0xea, + /*4db0:*/ 0x3a, 0x45, 0xe5, 0x93, 0x80, 0x92, 0x43, 0x5b, 0x05, 0x3d, 0x65, 0xe2, 0xbf, 0x56, 0x3f, 0x26, + /*4dc0:*/ 0x82, 0x0b, 0x1e, 0xd4, 0x46, 0x3a, 0x7a, 0x5a, 0x44, 0x91, 0x7e, 0x38, 0x3b, 0x6a, 0x17, 0xaf, + /*4dd0:*/ 0xc5, 0x5a, 0xb2, 0x68, 0xce, 0x68, 0x9c, 0x3c, 0x71, 0xc9, 0xde, 0xaa, 0x9b, 0xee, 0xd3, 0x50, + /*4de0:*/ 0x3c, 0xfd, 0xd8, 0x82, 0xc2, 0x6b, 0x92, 0x1a, 0xf9, 0x0c, 0x65, 0x20, 0x96, 0xc2, 0xd4, 0x2c, + /*4df0:*/ 0x0e, 0x89, 0x9d, 0xc7, 0xe0, 0xb9, 0x9b, 0x12, 0xad, 0xea, 0x0d, 0x97, 0x24, 0x99, 0xbe, 0x81, + /*4e00:*/ 0x08, 0x1f, 0x19, 0x70, 0x7f, 0x12, 0x9b, 0x46, 0x6b, 0xe3, 0xaf, 0x0b, 0xbb, 0xdd, 0xf9, 0xee, + /*4e10:*/ 0xfc, 0x40, 0x5b, 0x60, 0xb7, 0x9e, 0x00, 0xfe, 0x83, 0xca, 0x02, 0x31, 0xdb, 0x0a, 0x1a, 0xbe, + /*4e20:*/ 0xf1, 0x5f, 0xf9, 0x4f, 0xce, 0x03, 0x8c, 0xed, 0x31, 0x22, 0xaa, 0xcd, 0xa5, 0x34, 0xf5, 0xb2, + /*4e30:*/ 0x68, 0xad, 0x3e, 0xb4, 0x80, 0xa9, 0x11, 0x32, 0x56, 0x4d, 0xd6, 0x34, 0xe0, 0x3c, 0xf3, 0x49, + /*4e40:*/ 0x67, 0x5c, 0x8a, 0xf2, 0x08, 0xbf, 0x48, 0xac, 0xc1, 0x85, 0xa7, 0xfe, 0xcd, 0x8f, 0x46, 0x3c, + /*4e50:*/ 0xd5, 0x49, 0xfe, 0xf3, 0x9c, 0x61, 0x20, 0xd6, 0x16, 0x53, 0xfe, 0x67, 0x1d, 0x74, 0x44, 0x43, + /*4e60:*/ 0xab, 0x01, 0x7a, 0x1f, 0xdf, 0x83, 0x51, 0xbb, 0x25, 0xfc, 0xd7, 0x22, 0x94, 0x22, 0x03, 0x6c, + /*4e70:*/ 0x66, 0xa3, 0xa4, 0x0e, 0x19, 0x39, 0xd4, 0x9b, 0xfb, 0x4e, 0x37, 0x9d, 0x0d, 0xef, 0x7f, 0x7c, + /*4e80:*/ 0x08, 0x6b, 0xff, 0xbc, 0xab, 0xd9, 0xfe, 0xd9, 0x37, 0xd5, 0x8e, 0x5f, 0x33, 0xa3, 0xf1, 0xa4, + /*4e90:*/ 0x14, 0x77, 0xdb, 0x2b, 0xda, 0x8e, 0x5f, 0xb0, 0x33, 0x70, 0x6d, 0xd7, 0x84, 0xbf, 0xe5, 0x76, + /*4ea0:*/ 0xc3, 0xed, 0x1b, 0x34, 0xaa, 0xc1, 0x8d, 0x91, 0xf9, 0x44, 0x9b, 0xb7, 0x40, 0x92, 0x5d, 0xf3, + /*4eb0:*/ 0x3f, 0xe0, 0xb2, 0x34, 0x6b, 0x43, 0xc2, 0x04, 0xf5, 0x22, 0x95, 0xf5, 0xf6, 0x0a, 0x0d, 0x3c, + /*4ec0:*/ 0x51, 0xde, 0xa5, 0x32, 0x85, 0x29, 0x49, 0xd2, 0x37, 0x97, 0x44, 0x8f, 0x09, 0x49, 0xb7, 0xcb, + /*4ed0:*/ 0x76, 0xb5, 0x5d, 0x27, 0x24, 0x08, 0xb0, 0x73, 0x6d, 0xd5, 0xce, 0x44, 0xe2, 0xbf, 0x5a, 0xa1, + /*4ee0:*/ 0x52, 0x19, 0xdd, 0x09, 0xc1, 0x8c, 0x04, 0x0c, 0x5c, 0x4d, 0x80, 0xeb, 0x28, 0xb2, 0xf6, 0x74, + /*4ef0:*/ 0x98, 0xef, 0xe9, 0xfc, 0x67, 0xb1, 0x6a, 0x4d, 0x99, 0x50, 0xcc, 0x5e, 0x4e, 0x48, 0xaf, 0x3a, + /*4f00:*/ 0x2b, 0xf9, 0xd5, 0x8a, 0xf5, 0x2c, 0xb1, 0x48, 0x24, 0x3c, 0x93, 0xd8, 0xd0, 0x0a, 0x7a, 0x72, + /*4f10:*/ 0x20, 0xe6, 0xe1, 0x38, 0x6b, 0xa5, 0x30, 0x03, 0xaf, 0x3c, 0x52, 0x34, 0xdf, 0x42, 0x0c, 0x62, + /*4f20:*/ 0xfd, 0x7e, 0x11, 0x3a, 0x8b, 0x89, 0x36, 0x34, 0xf4, 0xdb, 0x88, 0xe4, 0xb9, 0x0a, 0xb8, 0x72, + /*4f30:*/ 0x3f, 0x42, 0x13, 0x7e, 0x4b, 0x4e, 0x6d, 0xae, 0x3c, 0x49, 0x26, 0x12, 0x75, 0x70, 0x8f, 0x43, + /*4f40:*/ 0xaa, 0xb3, 0x1a, 0x87, 0x12, 0x99, 0x43, 0x7c, 0x37, 0x52, 0xc6, 0xb1, 0x72, 0x5a, 0xab, 0xc8, + /*4f50:*/ 0x49, 0xd5, 0x30, 0x49, 0x8f, 0xf0, 0x06, 0xae, 0x97, 0x7d, 0x97, 0x57, 0x5e, 0x2b, 0x6a, 0x43, + /*4f60:*/ 0xa2, 0x8d, 0xa8, 0x4e, 0xcf, 0xa3, 0xbb, 0x1a, 0x28, 0x23, 0x06, 0x3d, 0x61, 0x2a, 0x4c, 0x97, + /*4f70:*/ 0x9a, 0xd2, 0x3e, 0xc1, 0x68, 0xc5, 0x3c, 0x81, 0x61, 0x7f, 0x8b, 0xea, 0x0f, 0x42, 0x9c, 0x89, + /*4f80:*/ 0xb8, 0xb1, 0x8a, 0xd1, 0x74, 0x09, 0x6c, 0x13, 0xee, 0x22, 0x8a, 0x3c, 0x59, 0xf6, 0x6c, 0xdb, + /*4f90:*/ 0xfd, 0xe9, 0x12, 0x29, 0xd9, 0x56, 0xdf, 0xe9, 0x9b, 0x4f, 0x30, 0x0e, 0x1c, 0x4c, 0x3f, 0x57, + /*4fa0:*/ 0xea, 0xd2, 0x9a, 0x00, 0x2d, 0x05, 0xfa, 0x0d, 0xcd, 0x2a, 0x6b, 0x7b, 0x12, 0xae, 0xe5, 0xe2, + /*4fb0:*/ 0xb0, 0xa1, 0x3c, 0xfc, 0xcb, 0x41, 0x00, 0x4c, 0x79, 0xbd, 0x02, 0x47, 0x36, 0x1b, 0x2a, 0xbc, + /*4fc0:*/ 0x46, 0x3a, 0x29, 0x68, 0x4b, 0x41, 0x5f, 0x47, 0x2b, 0xdb, 0x4c, 0x0d, 0xba, 0x7d, 0x3e, 0xd8, + /*4fd0:*/ 0x9a, 0x74, 0x62, 0x3d, 0x5d, 0x29, 0xec, 0x52, 0x65, 0x65, 0xdb, 0x95, 0xa5, 0x52, 0xff, 0xbb, + /*4fe0:*/ 0xef, 0xdb, 0xe9, 0xe4, 0xef, 0xb8, 0x0f, 0x94, 0x84, 0xab, 0xcb, 0x2e, 0x3c, 0x07, 0xee, 0xc1, + /*4ff0:*/ 0x26, 0xa5, 0xcd, 0xc4, 0x8f, 0xd7, 0x4c, 0xb5, 0x8c, 0xa8, 0x82, 0xbb, 0xda, 0xfe, 0x18, 0x25, + /*5000:*/ 0x0a, 0x5a, 0x1c, 0x02, 0x5a, 0x84, 0xa7, 0x1e, 0xdb, 0x8a, 0xc3, 0x97, 0xf0, 0x3a, 0x82, 0x06, + /*5010:*/ 0x08, 0x55, 0x93, 0x72, 0x66, 0xec, 0xac, 0x86, 0x3a, 0xb4, 0x27, 0xf4, 0x9d, 0x91, 0x96, 0xe8, + /*5020:*/ 0x6c, 0x06, 0x6c, 0xc0, 0xe4, 0x18, 0x1c, 0x54, 0x72, 0x2e, 0x4c, 0x56, 0xb6, 0x15, 0xe0, 0x72, + /*5030:*/ 0x66, 0xf0, 0xb0, 0xde, 0x53, 0x32, 0x30, 0x6c, 0xe4, 0x3f, 0x6e, 0x6e, 0x6a, 0xa3, 0xc5, 0x30, + /*5040:*/ 0xc8, 0xba, 0x71, 0x11, 0x9c, 0x57, 0x34, 0xb4, 0x92, 0x7d, 0x19, 0x3c, 0xcd, 0x9d, 0x22, 0xa2, + /*5050:*/ 0xf9, 0xdb, 0x99, 0x73, 0xfe, 0xcc, 0x10, 0x2d, 0xdf, 0x96, 0xf6, 0x8b, 0xce, 0x74, 0x91, 0xcb, + /*5060:*/ 0xd8, 0x50, 0x6b, 0x9d, 0x56, 0xec, 0x53, 0x7e, 0x5b, 0xaa, 0x7b, 0xa3, 0x9b, 0xaf, 0xa5, 0x7e, + /*5070:*/ 0xa4, 0xfa, 0x10, 0xdb, 0x73, 0x6e, 0xba, 0x66, 0x66, 0x17, 0xd5, 0x60, 0xa7, 0x9c, 0x4b, 0xdf, + /*5080:*/ 0xa7, 0x5e, 0x45, 0xfe, 0x5f, 0xbe, 0xf1, 0xd2, 0x63, 0x1a, 0x4d, 0x26, 0x22, 0x6e, 0x03, 0xe0, + /*5090:*/ 0x45, 0x89, 0x30, 0x41, 0x43, 0xad, 0x2b, 0xad, 0xf4, 0x0e, 0x0f, 0xa5, 0x33, 0xfc, 0x49, 0x30, + /*50a0:*/ 0x44, 0xf5, 0xc5, 0x8e, 0xe2, 0xa6, 0x32, 0x4b, 0x0c, 0xd5, 0x4d, 0x91, 0xe3, 0x48, 0xe2, 0xb7, + /*50b0:*/ 0xad, 0x24, 0xfb, 0xf9, 0x13, 0xe0, 0x3c, 0x8a, 0x03, 0xc6, 0x35, 0xbc, 0xd6, 0x6e, 0x03, 0x20, + /*50c0:*/ 0xda, 0x2b, 0x95, 0x22, 0x23, 0x55, 0xab, 0x79, 0x58, 0xd0, 0x55, 0x1a, 0x4d, 0xa4, 0xfd, 0x6e, + /*50d0:*/ 0x6b, 0x99, 0xc1, 0xf0, 0xba, 0x5d, 0x51, 0xfe, 0x59, 0xc3, 0x52, 0x19, 0x1b, 0x33, 0x89, 0x60, + /*50e0:*/ 0x07, 0xaf, 0x23, 0xd1, 0x01, 0xcd, 0xc9, 0xfa, 0x58, 0xa6, 0x7d, 0xec, 0x3e, 0x19, 0xc6, 0xc0, + /*50f0:*/ 0xa9, 0x5e, 0x9a, 0xb1, 0xe8, 0x58, 0xcb, 0x05, 0x36, 0x11, 0x98, 0xa3, 0x35, 0x32, 0x87, 0x44, + /*5100:*/ 0x5f, 0x6b, 0xdf, 0x09, 0x15, 0x42, 0xd7, 0xe9, 0x72, 0x56, 0x3f, 0x6b, 0x19, 0x08, 0x46, 0xf0, + /*5110:*/ 0x25, 0x77, 0x96, 0x04, 0x0f, 0x99, 0x4e, 0xa9, 0xbb, 0x7d, 0xad, 0x19, 0x6b, 0x2e, 0x42, 0x41, + /*5120:*/ 0xbc, 0xd2, 0xf0, 0x4b, 0xc6, 0xc5, 0x72, 0xa1, 0x39, 0x22, 0x56, 0x9b, 0x72, 0x34, 0x01, 0x3b, + /*5130:*/ 0x70, 0x33, 0x0f, 0xa3, 0x80, 0xf3, 0x9b, 0xcf, 0x4c, 0x22, 0xb5, 0xce, 0xd7, 0xe1, 0xdd, 0xa9, + /*5140:*/ 0xa0, 0x04, 0x87, 0xd0, 0xe2, 0x76, 0xed, 0xb6, 0x17, 0xb5, 0xf8, 0x20, 0x4c, 0xb2, 0x1c, 0x25, + /*5150:*/ 0x8b, 0x7e, 0x10, 0x65, 0xe3, 0xaa, 0x9b, 0x58, 0xfe, 0x41, 0x68, 0x9b, 0x2e, 0x02, 0x93, 0x86, + /*5160:*/ 0xab, 0xba, 0xb2, 0x70, 0xed, 0x13, 0x21, 0x94, 0xc7, 0x4f, 0xac, 0xb3, 0x77, 0xbb, 0xf1, 0x62, + /*5170:*/ 0x08, 0xfd, 0xe6, 0x53, 0xa0, 0x03, 0xc7, 0xbb, 0xcc, 0xf8, 0x90, 0x93, 0x2d, 0xc7, 0xee, 0xf8, + /*5180:*/ 0xf5, 0x08, 0xf8, 0x70, 0x2b, 0xc7, 0x29, 0x49, 0xc6, 0xc1, 0xbe, 0xc9, 0x48, 0x4b, 0xb4, 0x87, + /*5190:*/ 0xa3, 0xcb, 0x24, 0x88, 0x5f, 0xd7, 0xc0, 0x28, 0x2e, 0x13, 0x12, 0x6c, 0xf5, 0x00, 0x09, 0x12, + /*51a0:*/ 0x59, 0x8d, 0x38, 0x6c, 0xb7, 0x33, 0xda, 0x11, 0x66, 0x06, 0xd5, 0x11, 0x99, 0x1f, 0x3f, 0x44, + /*51b0:*/ 0xf1, 0x5e, 0x58, 0x7f, 0x30, 0xaf, 0x73, 0x8d, 0x24, 0x01, 0x5c, 0x1d, 0x02, 0x4a, 0x15, 0xd9, + /*51c0:*/ 0x8c, 0x6e, 0x12, 0xe6, 0x54, 0x73, 0xe9, 0x62, 0x31, 0xf9, 0x8e, 0x3c, 0x00, 0xff, 0x80, 0x48, + /*51d0:*/ 0xb9, 0x24, 0x18, 0x2f, 0xa7, 0xd8, 0x07, 0xd0, 0x84, 0x64, 0xe6, 0xad, 0x9d, 0xe9, 0xa7, 0xd8, + /*51e0:*/ 0x3c, 0xaa, 0x59, 0x19, 0x5a, 0x29, 0x61, 0xf8, 0x39, 0xcb, 0x16, 0x63, 0x9e, 0x6a, 0xc8, 0xcd, + /*51f0:*/ 0x5d, 0x4f, 0x97, 0x8c, 0xe3, 0xf1, 0x9a, 0xa0, 0x33, 0x24, 0x7c, 0x15, 0x65, 0x95, 0xb3, 0x09, + /*5200:*/ 0xaf, 0x2f, 0x11, 0x6c, 0xac, 0xea, 0x75, 0x33, 0x4b, 0x5a, 0xf3, 0x9f, 0x38, 0xa4, 0x60, 0xd8, + /*5210:*/ 0x0c, 0xff, 0x92, 0x97, 0x35, 0x63, 0xbe, 0x2f, 0x44, 0xa5, 0xc6, 0x4d, 0x61, 0x3e, 0xc5, 0xad, + /*5220:*/ 0xc6, 0x9b, 0x41, 0x02, 0x0c, 0x9d, 0x1e, 0xc5, 0xb1, 0x21, 0x0e, 0xd3, 0x44, 0xd8, 0x36, 0x49, + /*5230:*/ 0x73, 0x20, 0x23, 0xbc, 0x97, 0x99, 0xf0, 0xc2, 0x6f, 0x2c, 0x10, 0x69, 0x9d, 0xfe, 0x4d, 0x85, + /*5240:*/ 0xf7, 0xd6, 0x86, 0x87, 0x05, 0x42, 0x8d, 0xcb, 0xc7, 0x9f, 0xbd, 0x28, 0x0b, 0xdd, 0x8c, 0xe0, + /*5250:*/ 0x60, 0x61, 0x77, 0xb5, 0xca, 0x50, 0x33, 0x3d, 0xd4, 0x82, 0x51, 0x8d, 0x5b, 0x14, 0x28, 0x98, + /*5260:*/ 0x88, 0x90, 0x34, 0x1e, 0x77, 0xf6, 0x7f, 0xc2, 0x00, 0xf8, 0x55, 0x6d, 0xf9, 0xce, 0xb0, 0x3a, + /*5270:*/ 0xec, 0xe5, 0x5f, 0x8b, 0x2b, 0x12, 0x5c, 0x9b, 0x01, 0x33, 0xa6, 0x9b, 0x8b, 0xb1, 0x6a, 0x8d, + /*5280:*/ 0x70, 0xb2, 0x9e, 0x07, 0x27, 0x5a, 0x40, 0x5d, 0xba, 0x7f, 0x8b, 0x4c, 0x99, 0x49, 0x6e, 0x31, + /*5290:*/ 0x1e, 0xe4, 0x7e, 0x4a, 0x5d, 0xc3, 0xd1, 0x04, 0x0a, 0x7a, 0xab, 0x6a, 0x3c, 0x38, 0xa7, 0x7f, + /*52a0:*/ 0xd0, 0xcd, 0x06, 0x6a, 0x81, 0x37, 0x28, 0x25, 0xe9, 0xd2, 0xe6, 0x79, 0x1c, 0x43, 0x36, 0x80, + /*52b0:*/ 0x2b, 0x1d, 0xee, 0xd4, 0x4b, 0x7a, 0x5f, 0x9a, 0x7c, 0x38, 0xc1, 0x08, 0xa9, 0x17, 0x18, 0xd2, + /*52c0:*/ 0x6c, 0x78, 0xf0, 0xaa, 0xb4, 0x62, 0x38, 0x96, 0x6e, 0x96, 0x7b, 0x21, 0xc3, 0x21, 0x9b, 0xb2, + /*52d0:*/ 0x70, 0x5d, 0x7b, 0x2f, 0xb1, 0xc6, 0x96, 0x1a, 0xe0, 0xd7, 0x76, 0x6a, 0x6f, 0x4b, 0x23, 0x38, + /*52e0:*/ 0x9b, 0xc7, 0xac, 0xbf, 0x44, 0x01, 0x0f, 0xb6, 0x66, 0x97, 0xa5, 0xc6, 0xf8, 0xc2, 0xfa, 0x3b, + /*52f0:*/ 0x78, 0x48, 0xd1, 0xac, 0xe8, 0x47, 0xd0, 0x0e, 0x80, 0x0c, 0x52, 0xf0, 0xd4, 0x04, 0x4a, 0xd7, + /*5300:*/ 0x60, 0x49, 0xe5, 0x78, 0xe6, 0xc6, 0x91, 0xbc, 0x67, 0x12, 0x9a, 0x14, 0x39, 0x3a, 0xd5, 0x3a, + /*5310:*/ 0xa4, 0x2c, 0xfc, 0x1c, 0x30, 0x99, 0xdd, 0xf2, 0xba, 0xe6, 0xfa, 0xe3, 0x1d, 0xd9, 0xae, 0x64, + /*5320:*/ 0x11, 0x87, 0x92, 0x51, 0xc9, 0x61, 0x50, 0xb0, 0x82, 0x6d, 0x0b, 0x43, 0x8b, 0xf6, 0xae, 0x8e, + /*5330:*/ 0x83, 0x7d, 0x00, 0xfc, 0xd9, 0xf5, 0x4b, 0x14, 0x36, 0xf1, 0x4a, 0xea, 0x33, 0x92, 0x8c, 0x16, + /*5340:*/ 0x91, 0xb9, 0xf0, 0x44, 0xa2, 0x31, 0xed, 0x0e, 0x6b, 0x45, 0xb3, 0xe2, 0x47, 0xab, 0xc6, 0x70, + /*5350:*/ 0xf8, 0x84, 0xe8, 0xa4, 0x41, 0x9f, 0x32, 0xd5, 0x61, 0x6b, 0x81, 0x38, 0x34, 0x5b, 0x88, 0xf2, + /*5360:*/ 0x82, 0xae, 0x6c, 0x5e, 0xa0, 0x6f, 0xb1, 0x93, 0xaf, 0x6b, 0x04, 0xbe, 0xd5, 0xcb, 0xae, 0xac, + /*5370:*/ 0xd0, 0x09, 0x2a, 0x7d, 0x9f, 0xa6, 0xa9, 0xa2, 0x46, 0x61, 0x82, 0xaa, 0x95, 0x9c, 0xf1, 0x36, + /*5380:*/ 0x57, 0xb5, 0xcf, 0x5a, 0x00, 0x43, 0xac, 0x5c, 0xb4, 0xd9, 0xe2, 0x08, 0x03, 0x5c, 0x88, 0xc4, + /*5390:*/ 0xab, 0x50, 0xa6, 0x72, 0xae, 0xe0, 0x56, 0xba, 0x93, 0x9a, 0x87, 0x20, 0xe1, 0x08, 0x55, 0x2c, + /*53a0:*/ 0xeb, 0xff, 0xfd, 0xc6, 0x31, 0xc0, 0xb2, 0xce, 0x62, 0xe4, 0x8b, 0x31, 0xc3, 0xa9, 0x70, 0xed, + /*53b0:*/ 0x0f, 0x98, 0x04, 0x70, 0x07, 0xa3, 0x17, 0xc5, 0xb6, 0x15, 0x02, 0x2b, 0x62, 0x68, 0xb9, 0x18, + /*53c0:*/ 0xa4, 0x88, 0xf8, 0xad, 0x61, 0x63, 0x9d, 0x4f, 0x71, 0xd5, 0xbc, 0x32, 0x86, 0xa9, 0x2b, 0x6b, + /*53d0:*/ 0xdf, 0x2d, 0x0d, 0x4b, 0x6f, 0x65, 0xe4, 0x57, 0xae, 0x76, 0xac, 0x48, 0xeb, 0xa8, 0x12, 0xc5, + /*53e0:*/ 0x30, 0x93, 0x12, 0xfb, 0x85, 0xa9, 0x76, 0xe4, 0xca, 0x36, 0xbc, 0xb4, 0xd4, 0xa5, 0x6f, 0x3c, + /*53f0:*/ 0x77, 0x16, 0x05, 0x00, 0x3f, 0xd3, 0x0b, 0x93, 0x3e, 0xf0, 0xdd, 0xa3, 0xd9, 0xba, 0xfd, 0x6d, + /*5400:*/ 0x6e, 0x91, 0x64, 0x41, 0xa0, 0x40, 0xd7, 0x1a, 0x25, 0x33, 0xb8, 0x35, 0x50, 0x56, 0xa6, 0xf1, + /*5410:*/ 0x18, 0x19, 0x98, 0x5e, 0x74, 0x4b, 0xb0, 0xc0, 0xf2, 0xbb, 0x5b, 0x06, 0x1c, 0xc7, 0x35, 0x3b, + /*5420:*/ 0x3f, 0x00, 0x58, 0x20, 0x4a, 0x52, 0x25, 0xd2, 0x10, 0x79, 0x3b, 0x78, 0xd3, 0x6b, 0x39, 0x5c, + /*5430:*/ 0xf3, 0x22, 0xde, 0xb8, 0xd6, 0x8b, 0xe9, 0x2c, 0x03, 0x55, 0xd4, 0x82, 0x66, 0x33, 0x6e, 0xa1, + /*5440:*/ 0x68, 0xd8, 0x63, 0x1f, 0xda, 0xf8, 0x14, 0x4c, 0xfd, 0x78, 0x70, 0x3e, 0xdf, 0xdb, 0x83, 0x99, + /*5450:*/ 0x94, 0x61, 0xa5, 0x86, 0x64, 0xae, 0x9c, 0xfe, 0x33, 0xc7, 0x20, 0x04, 0x5a, 0xbe, 0xd4, 0x74, + /*5460:*/ 0xef, 0x19, 0x39, 0xf8, 0xf9, 0xff, 0xcc, 0x96, 0x3a, 0xb6, 0x1c, 0x54, 0xd8, 0xd7, 0xcb, 0xf6, + /*5470:*/ 0xd7, 0x97, 0x51, 0xd2, 0xd8, 0x86, 0x8e, 0x04, 0x5f, 0xc6, 0x5c, 0x3e, 0x71, 0x87, 0xa6, 0x50, + /*5480:*/ 0xeb, 0x41, 0x45, 0x45, 0xba, 0x0f, 0x67, 0x32, 0x44, 0x64, 0xbf, 0xde, 0xbc, 0x4c, 0x11, 0xfe, + /*5490:*/ 0xc2, 0x24, 0xe2, 0xf3, 0x30, 0xb2, 0x87, 0xa1, 0x62, 0xf6, 0xa0, 0x7d, 0xf7, 0xd9, 0x68, 0x83, + /*54a0:*/ 0x7a, 0x1b, 0x00, 0x0d, 0x01, 0xd8, 0xc0, 0xa6, 0x99, 0x2a, 0x95, 0x44, 0x5f, 0xda, 0xf6, 0xc3, + /*54b0:*/ 0xa0, 0x30, 0x0b, 0x1d, 0x88, 0xb4, 0xae, 0xc7, 0x2b, 0xae, 0x06, 0x2a, 0xb1, 0x72, 0x64, 0xec, + /*54c0:*/ 0x0b, 0xdc, 0xc6, 0xba, 0x92, 0xa6, 0xb9, 0x6e, 0x4f, 0x69, 0x12, 0x99, 0xb5, 0x00, 0xcf, 0x8d, + /*54d0:*/ 0x8e, 0x0b, 0x94, 0x75, 0xf2, 0x89, 0xb4, 0x35, 0x48, 0x9d, 0x7f, 0x76, 0x15, 0xb9, 0x92, 0x0b, + /*54e0:*/ 0x82, 0xba, 0x88, 0x8a, 0xff, 0x21, 0x3b, 0xd8, 0x53, 0x02, 0x78, 0x6a, 0x2a, 0x7c, 0x34, 0xb5, + /*54f0:*/ 0xfc, 0xc7, 0xb8, 0x99, 0xe0, 0xed, 0xb8, 0x52, 0xce, 0xc8, 0x68, 0x5e, 0x67, 0x2a, 0x7a, 0x4b, + /*5500:*/ 0x75, 0x78, 0x0f, 0x9d, 0xbe, 0x0e, 0x4c, 0xde, 0x5a, 0x1b, 0xc2, 0x36, 0xf3, 0xe4, 0x8a, 0xfd, + /*5510:*/ 0xf3, 0x72, 0x42, 0x38, 0xac, 0xd3, 0xc4, 0xaa, 0x16, 0xfa, 0x60, 0x8b, 0x4e, 0xd5, 0x87, 0x34, + /*5520:*/ 0x78, 0x01, 0x8b, 0x3b, 0x48, 0x1e, 0x57, 0x46, 0x59, 0x2d, 0x6c, 0xda, 0x80, 0xb2, 0x4b, 0x9c, + /*5530:*/ 0x77, 0xa2, 0x1c, 0xc0, 0x70, 0x63, 0xc1, 0x0e, 0x30, 0xf1, 0x26, 0xd1, 0xdd, 0x75, 0xf8, 0x3f, + /*5540:*/ 0x2c, 0xeb, 0x9d, 0xdf, 0xbc, 0x74, 0xff, 0x46, 0x6e, 0xbc, 0x7f, 0x9b, 0x41, 0xce, 0x20, 0xb0, + /*5550:*/ 0xb7, 0xff, 0x99, 0xc3, 0x13, 0x7c, 0xf6, 0x4b, 0xb3, 0x35, 0x37, 0xaa, 0xf2, 0x9a, 0xad, 0x67, + /*5560:*/ 0x81, 0xe0, 0x9d, 0xa6, 0x4f, 0x48, 0x68, 0xc2, 0x22, 0xaf, 0xf8, 0xdf, 0xf9, 0x2f, 0x08, 0x84, + /*5570:*/ 0x2c, 0xcb, 0xc4, 0x86, 0xe2, 0x5a, 0x38, 0x94, 0x45, 0x4d, 0xd7, 0x30, 0x97, 0x5a, 0xd4, 0x60, + /*5580:*/ 0x3b, 0x20, 0xb5, 0xf8, 0x39, 0x8c, 0x1a, 0x60, 0x05, 0xbb, 0x9e, 0x61, 0x8c, 0x56, 0x96, 0x39, + /*5590:*/ 0xe4, 0x78, 0x10, 0x07, 0x14, 0xb3, 0xbe, 0x0d, 0x24, 0x58, 0x78, 0xa8, 0x79, 0x29, 0xf0, 0xcc, + /*55a0:*/ 0x12, 0x4b, 0x5a, 0x9a, 0xa4, 0x4b, 0xa8, 0x37, 0x5e, 0xc3, 0x1b, 0x13, 0x77, 0x24, 0x09, 0x29, + /*55b0:*/ 0xcc, 0xf9, 0x05, 0xd7, 0x20, 0xe9, 0x16, 0xd5, 0xb0, 0x4d, 0x61, 0x44, 0xd7, 0x29, 0x9b, 0xd7, + /*55c0:*/ 0x6c, 0xaa, 0x82, 0xc9, 0x6e, 0x3a, 0x07, 0x8b, 0x9c, 0xef, 0x6a, 0xc0, 0x91, 0x11, 0x4b, 0x2d, + /*55d0:*/ 0x26, 0xd7, 0x3b, 0x11, 0x88, 0x4d, 0x6f, 0xf4, 0xad, 0xf3, 0xde, 0xdb, 0xa5, 0xb9, 0x7b, 0x64, + /*55e0:*/ 0x60, 0x7b, 0xd8, 0xf2, 0xd3, 0xa3, 0x64, 0x1a, 0x56, 0xc9, 0x5e, 0x6a, 0x86, 0xbd, 0x28, 0xea, + /*55f0:*/ 0x31, 0x28, 0x15, 0x84, 0x5c, 0xe5, 0x0a, 0x89, 0x54, 0x69, 0x14, 0x5b, 0xca, 0x24, 0x56, 0xc2, + /*5600:*/ 0x71, 0x96, 0xdf, 0x31, 0x9b, 0x72, 0x9f, 0xb3, 0xce, 0xd4, 0x87, 0xf6, 0x6f, 0x32, 0x89, 0x72, + /*5610:*/ 0x82, 0x7c, 0x59, 0x5c, 0x57, 0xfa, 0x01, 0x89, 0xd2, 0x2d, 0x45, 0xe3, 0x53, 0x62, 0xc9, 0x40, + /*5620:*/ 0x73, 0xa0, 0xcd, 0x96, 0xe1, 0xe5, 0x42, 0xed, 0x1a, 0x51, 0xb2, 0xb6, 0xc3, 0x18, 0xed, 0xd1, + /*5630:*/ 0x1f, 0x07, 0x69, 0x66, 0xbd, 0x27, 0x78, 0x6e, 0xd9, 0xf0, 0xe5, 0x37, 0x75, 0xbd, 0x67, 0xcf, + /*5640:*/ 0x62, 0x4e, 0xd2, 0xb1, 0xfa, 0xa9, 0x0c, 0x4a, 0xd3, 0x96, 0x96, 0x0f, 0xcd, 0x9b, 0x80, 0x1a, + /*5650:*/ 0x3b, 0x4a, 0x99, 0xdb, 0xd4, 0x16, 0x02, 0x62, 0x15, 0x97, 0xfa, 0xac, 0xd2, 0x04, 0x0b, 0xd5, + /*5660:*/ 0x7b, 0x20, 0x1d, 0xf3, 0x9c, 0xed, 0x32, 0x9b, 0x90, 0x2d, 0x95, 0xb1, 0x7e, 0x2c, 0xf8, 0x27, + /*5670:*/ 0x2c, 0x06, 0x8b, 0x23, 0x93, 0xc5, 0xa2, 0x0d, 0x94, 0xfc, 0xfd, 0x56, 0xe1, 0xe6, 0xa9, 0x81, + /*5680:*/ 0xe2, 0x48, 0x53, 0xee, 0x6d, 0xe9, 0x44, 0x92, 0x1b, 0x73, 0x16, 0xd6, 0x99, 0x12, 0xa4, 0x6a, + /*5690:*/ 0xa1, 0xfc, 0x8b, 0x1a, 0xf0, 0xb4, 0x1c, 0x67, 0xd4, 0x83, 0x65, 0x69, 0x9c, 0x64, 0xb1, 0x9e, + /*56a0:*/ 0x0b, 0x74, 0xbb, 0x0f, 0xa8, 0x7d, 0xb9, 0x39, 0x3b, 0x2c, 0x89, 0xcf, 0x70, 0x74, 0x27, 0xcf, + /*56b0:*/ 0x4a, 0xdd, 0x8a, 0xe5, 0x05, 0x46, 0x6d, 0x84, 0xba, 0x1d, 0x70, 0x78, 0x5a, 0x6f, 0x9a, 0xf1, + /*56c0:*/ 0xb4, 0xf8, 0x11, 0x7b, 0x39, 0xe7, 0x03, 0x67, 0x58, 0x6b, 0x64, 0x8c, 0x8d, 0xa3, 0xd2, 0x7d, + /*56d0:*/ 0xf4, 0x35, 0x4e, 0x48, 0x61, 0xc8, 0xaa, 0x57, 0xb9, 0xf5, 0xcd, 0x9c, 0xaa, 0x38, 0x78, 0x17, + /*56e0:*/ 0xaf, 0x59, 0x11, 0x2b, 0xfa, 0x49, 0x6c, 0xf3, 0xdf, 0x53, 0xb0, 0xb5, 0x3d, 0x1e, 0x37, 0x7e, + /*56f0:*/ 0x11, 0x2c, 0x56, 0xfa, 0xc7, 0x77, 0x6d, 0x6c, 0xd8, 0xd6, 0x12, 0x41, 0x12, 0xa2, 0x02, 0x06, + /*5700:*/ 0xcd, 0x5d, 0x75, 0xba, 0x86, 0xe5, 0xe5, 0x27, 0xdf, 0x8c, 0xd0, 0x06, 0xeb, 0x41, 0xbe, 0x8d, + /*5710:*/ 0xe1, 0xa2, 0x90, 0x8f, 0x4b, 0xbf, 0x76, 0x03, 0x75, 0x33, 0x29, 0x1a, 0x80, 0x57, 0xd6, 0x67, + /*5720:*/ 0x01, 0x72, 0xc1, 0x5a, 0xea, 0xd3, 0xbe, 0xb1, 0xac, 0x6c, 0x13, 0xc5, 0xc2, 0x72, 0x7d, 0x22, + /*5730:*/ 0xb0, 0xa2, 0xab, 0xf6, 0x52, 0x78, 0x37, 0xcf, 0x38, 0x1e, 0x13, 0xb9, 0xee, 0x71, 0x5a, 0xc4, + /*5740:*/ 0xfc, 0x6a, 0x11, 0xe1, 0xd6, 0x6e, 0x01, 0x32, 0x5a, 0x51, 0x35, 0x39, 0x59, 0x30, 0xc5, 0x15, + /*5750:*/ 0x87, 0x52, 0x63, 0xe8, 0x07, 0x39, 0xd8, 0xf0, 0x85, 0xf5, 0x7c, 0x31, 0x6d, 0xbf, 0x24, 0x27, + /*5760:*/ 0xf7, 0x66, 0xca, 0x6a, 0x81, 0xc8, 0x38, 0x02, 0x07, 0x20, 0x49, 0x2e, 0x9e, 0xe6, 0xe9, 0x5e, + /*5770:*/ 0x64, 0x81, 0xed, 0xea, 0xf9, 0x87, 0x53, 0xed, 0x06, 0xe0, 0x27, 0xba, 0x29, 0x0b, 0x00, 0xa0, + /*5780:*/ 0x2c, 0xbf, 0xee, 0x37, 0x44, 0x63, 0xa0, 0xf4, 0xe3, 0x9a, 0xc5, 0xba, 0x6f, 0x50, 0x1c, 0x72, + /*5790:*/ 0x14, 0x89, 0x3c, 0x14, 0xc4, 0xf7, 0x8c, 0x4d, 0x7d, 0x2a, 0xa2, 0xb4, 0x94, 0xfe, 0xfd, 0xce, + /*57a0:*/ 0xcf, 0x07, 0x71, 0x33, 0xe0, 0x46, 0xe0, 0x03, 0x94, 0x42, 0x9d, 0x55, 0x69, 0x2c, 0x3d, 0x74, + /*57b0:*/ 0x6b, 0x74, 0x52, 0x49, 0x34, 0x9c, 0x51, 0xc0, 0x19, 0x0c, 0x5e, 0x74, 0x76, 0xc2, 0x4a, 0x0a, + /*57c0:*/ 0x14, 0x88, 0x4e, 0x2a, 0xa5, 0x9a, 0x9e, 0xc3, 0x99, 0x72, 0x5e, 0xef, 0x9c, 0x94, 0xac, 0xa7, + /*57d0:*/ 0x61, 0x78, 0xc2, 0x36, 0x17, 0x82, 0x2d, 0xce, 0x7d, 0x92, 0xd0, 0x8a, 0x3b, 0x3e, 0x1f, 0x1d, + /*57e0:*/ 0x83, 0xf9, 0xa8, 0x44, 0xdf, 0xce, 0x84, 0x31, 0xdc, 0xf2, 0xd6, 0x0d, 0xb9, 0x0b, 0x89, 0xc5, + /*57f0:*/ 0x77, 0xae, 0xa1, 0x9a, 0x75, 0xc6, 0x93, 0x6e, 0xdb, 0x61, 0xdd, 0x3d, 0x8e, 0x7c, 0x4b, 0x53, + /*5800:*/ 0x14, 0x1d, 0x3c, 0x51, 0x5f, 0x60, 0xfe, 0x6a, 0x1d, 0xef, 0x49, 0x30, 0x03, 0xf3, 0xb2, 0x7c, + /*5810:*/ 0xf5, 0x1c, 0x88, 0x68, 0xf4, 0xb8, 0xf5, 0x36, 0x4f, 0x17, 0x11, 0x39, 0x44, 0xfc, 0xaa, 0xe2, + /*5820:*/ 0x51, 0x20, 0x77, 0xc7, 0xe0, 0xf4, 0x6e, 0x8c, 0xa5, 0x77, 0xc7, 0x66, 0x2c, 0x24, 0xb1, 0xae, + /*5830:*/ 0xc1, 0xbd, 0x1a, 0x64, 0x1c, 0x1e, 0xa3, 0xbb, 0x52, 0xb3, 0x53, 0x1a, 0x5e, 0x94, 0xd6, 0x10, + /*5840:*/ 0xd4, 0x17, 0x6e, 0x36, 0xe8, 0x09, 0x6a, 0x0f, 0x67, 0x73, 0x40, 0xb8, 0xcf, 0xdd, 0xc0, 0xac, + /*5850:*/ 0x3a, 0xfd, 0x08, 0xcd, 0xd2, 0x42, 0xc0, 0xb0, 0x4e, 0xc3, 0xca, 0x66, 0x2b, 0x84, 0x19, 0x6f, + /*5860:*/ 0x2e, 0xf2, 0x22, 0x21, 0x56, 0xb7, 0x17, 0xbe, 0x47, 0xc2, 0x96, 0x6e, 0x60, 0xf2, 0xc7, 0x1f, + /*5870:*/ 0x9b, 0xb5, 0x82, 0xea, 0x02, 0x46, 0x4e, 0x04, 0xca, 0x64, 0xa1, 0x70, 0xd6, 0xd0, 0xd7, 0x3d, + /*5880:*/ 0x15, 0x42, 0x68, 0x17, 0xfd, 0x7f, 0x7f, 0x9a, 0x12, 0x1b, 0xcc, 0x7a, 0x59, 0x85, 0x5e, 0xfd, + /*5890:*/ 0x74, 0x55, 0x8b, 0xc9, 0x55, 0xf7, 0x44, 0x64, 0xa8, 0xff, 0xd3, 0xb5, 0x32, 0x2e, 0xb1, 0x3a, + /*58a0:*/ 0x36, 0xe2, 0x4d, 0x18, 0x35, 0x37, 0x5c, 0x5b, 0x8d, 0x9b, 0x51, 0x51, 0x39, 0xb2, 0xbe, 0x5a, + /*58b0:*/ 0xaf, 0xf6, 0xa4, 0x35, 0xc5, 0x62, 0x26, 0x9e, 0x60, 0xa8, 0xad, 0x12, 0x89, 0xef, 0x23, 0x9a, + /*58c0:*/ 0x54, 0x74, 0xa6, 0x07, 0x40, 0xab, 0x97, 0xf4, 0xcc, 0xa9, 0x37, 0xd2, 0x43, 0xda, 0x9b, 0xdb, + /*58d0:*/ 0x07, 0x3c, 0x6f, 0x33, 0x64, 0x6b, 0xfd, 0xa7, 0x72, 0x5c, 0x61, 0xce, 0xe7, 0x2a, 0x21, 0x96, + /*58e0:*/ 0xac, 0xb4, 0x04, 0x2d, 0x0b, 0x8b, 0x6d, 0xa8, 0xbd, 0x48, 0xab, 0xcd, 0xc9, 0x1f, 0x12, 0xf3, + /*58f0:*/ 0xb6, 0x83, 0xec, 0xa2, 0x89, 0x8b, 0x89, 0x35, 0x62, 0x10, 0x5e, 0xc8, 0x28, 0xcc, 0x2f, 0xfb, + /*5900:*/ 0x85, 0xb4, 0x9a, 0xab, 0x51, 0x1a, 0x78, 0x84, 0x42, 0xec, 0x99, 0xad, 0x5b, 0x53, 0x24, 0x39, + /*5910:*/ 0x68, 0x4c, 0xdb, 0xef, 0xab, 0x5c, 0x89, 0xfa, 0x6f, 0xf7, 0x23, 0x6c, 0x42, 0x7d, 0xbf, 0xe9, + /*5920:*/ 0x29, 0x96, 0x1f, 0x47, 0x39, 0x86, 0x02, 0x36, 0x5a, 0x1a, 0x98, 0xe4, 0x1a, 0x7b, 0x03, 0x3b, + /*5930:*/ 0x6c, 0x5f, 0x41, 0x61, 0x20, 0x26, 0xe2, 0xf2, 0x26, 0x8a, 0xf7, 0x50, 0xe4, 0x50, 0xd2, 0x64, + /*5940:*/ 0xea, 0xec, 0xf5, 0x37, 0xea, 0xf7, 0x68, 0x8b, 0x31, 0x24, 0xc8, 0x78, 0x96, 0x2d, 0xc6, 0x9b, + /*5950:*/ 0x46, 0xa1, 0x9a, 0xe2, 0xdc, 0xbb, 0x26, 0x14, 0xd8, 0x7e, 0x78, 0xb9, 0x60, 0x1d, 0xc4, 0x4b, + /*5960:*/ 0x66, 0xad, 0x2d, 0x11, 0x40, 0x70, 0xcd, 0x41, 0xb5, 0xb5, 0x8d, 0xe1, 0xc2, 0x44, 0x6a, 0xcf, + /*5970:*/ 0x87, 0x28, 0xa8, 0x8a, 0xc6, 0x9b, 0xb4, 0xd8, 0x14, 0xae, 0x0e, 0xae, 0x4e, 0xde, 0x7f, 0xf1, + /*5980:*/ 0x79, 0xec, 0x9c, 0xed, 0x96, 0x33, 0xfd, 0x40, 0xae, 0xbf, 0x34, 0xa2, 0x9c, 0x5a, 0xf7, 0xcd, + /*5990:*/ 0x4b, 0xab, 0xaa, 0xd2, 0xd5, 0xb2, 0x39, 0xcd, 0x4a, 0x23, 0xc7, 0xb9, 0x82, 0x55, 0xa9, 0x00, + /*59a0:*/ 0xf1, 0x6d, 0x29, 0x99, 0x0d, 0xc6, 0x83, 0x5a, 0x21, 0xaa, 0x09, 0xb6, 0x24, 0x17, 0xd9, 0xbe, + /*59b0:*/ 0x56, 0xd8, 0x23, 0x56, 0x94, 0xe5, 0x72, 0xdd, 0xb3, 0xc7, 0x30, 0x76, 0x66, 0xc8, 0x79, 0xd6, + /*59c0:*/ 0xda, 0xa0, 0x85, 0x20, 0x75, 0xd4, 0x17, 0x65, 0x68, 0xb2, 0x47, 0xe7, 0xae, 0xfc, 0xe8, 0x40, + /*59d0:*/ 0xf0, 0x10, 0x64, 0xa8, 0x56, 0x29, 0x92, 0x4c, 0xe1, 0x8d, 0x80, 0x60, 0x3e, 0x05, 0x3d, 0xaa, + /*59e0:*/ 0x46, 0x9b, 0x4b, 0xa8, 0x80, 0xd7, 0xb0, 0x81, 0xa4, 0x5c, 0xc6, 0x12, 0xef, 0x4b, 0xda, 0x3f, + /*59f0:*/ 0x4b, 0x78, 0xf4, 0x64, 0x17, 0x52, 0xc2, 0xec, 0x4a, 0xc6, 0x44, 0x3b, 0x80, 0xcf, 0xd6, 0xa5, + /*5a00:*/ 0x44, 0xa5, 0x02, 0x3b, 0x05, 0x10, 0xd0, 0x69, 0xdf, 0x7e, 0x27, 0xf0, 0x25, 0x26, 0x09, 0xa8, + /*5a10:*/ 0xa7, 0x38, 0x72, 0xe5, 0x96, 0x62, 0x8a, 0xc7, 0x5e, 0xb1, 0x6a, 0xf6, 0x5a, 0x1a, 0x08, 0x88, + /*5a20:*/ 0xe4, 0x18, 0x42, 0xff, 0x53, 0xbb, 0x93, 0x7c, 0xc5, 0x34, 0x65, 0x29, 0xcc, 0xbe, 0xfa, 0xb2, + /*5a30:*/ 0xec, 0x59, 0x23, 0xd8, 0xb2, 0x31, 0xe4, 0xe1, 0xe1, 0xb7, 0xd9, 0x40, 0xbd, 0xb6, 0x1b, 0x29, + /*5a40:*/ 0xba, 0x10, 0x60, 0x3d, 0x93, 0x68, 0x2f, 0x08, 0x17, 0xf3, 0x43, 0xa8, 0x0c, 0x1e, 0xda, 0x76, + /*5a50:*/ 0x60, 0x8a, 0xb0, 0x2d, 0x44, 0x09, 0x24, 0xf2, 0xca, 0xa8, 0xf5, 0xd4, 0x4e, 0x2a, 0xbd, 0xd7, + /*5a60:*/ 0xed, 0x37, 0x24, 0x20, 0xfa, 0x00, 0x0a, 0x01, 0x4d, 0xc1, 0xfe, 0x71, 0x26, 0x76, 0xf0, 0x2f, + /*5a70:*/ 0x2b, 0xe9, 0xb5, 0xfe, 0xd9, 0x18, 0x96, 0x84, 0x51, 0xc1, 0x39, 0xf3, 0x1a, 0x87, 0x1c, 0xf6, + /*5a80:*/ 0x62, 0xed, 0xcd, 0xa7, 0x7e, 0x57, 0x6d, 0x08, 0xc6, 0x90, 0x6d, 0xe5, 0x6e, 0xee, 0x8f, 0x88, + /*5a90:*/ 0x07, 0x71, 0xab, 0x55, 0x66, 0xfc, 0xf7, 0x0b, 0x90, 0x97, 0xc9, 0xe9, 0xf0, 0xe5, 0x30, 0x9a, + /*5aa0:*/ 0xd0, 0x5a, 0x00, 0x9c, 0x1c, 0x3c, 0x49, 0x2a, 0x3e, 0x72, 0xb8, 0xfe, 0xab, 0x20, 0xc8, 0xf5, + /*5ab0:*/ 0xd7, 0xf9, 0x76, 0xbe, 0x33, 0x45, 0xac, 0x6b, 0x81, 0x50, 0x66, 0x9c, 0x24, 0xa0, 0x47, 0xe0, + /*5ac0:*/ 0xbe, 0x7f, 0xa2, 0x85, 0xb0, 0x8a, 0xfb, 0x42, 0x04, 0xe0, 0xed, 0xd6, 0xfd, 0xcc, 0x59, 0x6f, + /*5ad0:*/ 0xe7, 0x57, 0x63, 0x52, 0x03, 0x75, 0x28, 0x2d, 0x07, 0x7b, 0xe3, 0xf9, 0xfb, 0xa1, 0xef, 0x85, + /*5ae0:*/ 0x51, 0xf0, 0xf8, 0x76, 0x11, 0xa6, 0x80, 0xe4, 0x4b, 0x24, 0xfd, 0x1f, 0xc7, 0x68, 0x05, 0x8f, + /*5af0:*/ 0xd8, 0xdb, 0x52, 0xbd, 0x09, 0x85, 0x75, 0x5e, 0xe1, 0x61, 0x14, 0x60, 0xaf, 0xfd, 0xd2, 0xdf, + /*5b00:*/ 0xa3, 0x80, 0xc9, 0xa2, 0x80, 0x69, 0x47, 0xe9, 0xb7, 0xcd, 0xbb, 0xae, 0x53, 0xbd, 0xa8, 0xf6, + /*5b10:*/ 0x86, 0x88, 0x4c, 0xdb, 0xfc, 0xa7, 0xd1, 0x42, 0xfc, 0xb8, 0x9f, 0xe9, 0xf3, 0x7e, 0xeb, 0x13, + /*5b20:*/ 0x4f, 0xb0, 0xfa, 0xe0, 0x40, 0x42, 0xa6, 0x3b, 0x35, 0xf9, 0x72, 0x2f, 0x21, 0x17, 0x2d, 0xdd, + /*5b30:*/ 0xa2, 0x39, 0xa5, 0x88, 0xb2, 0x9b, 0xdb, 0x65, 0x3b, 0x70, 0x97, 0xb1, 0xe4, 0x4c, 0xda, 0x69, + /*5b40:*/ 0x88, 0x5c, 0xde, 0x5b, 0x89, 0x42, 0xe5, 0x13, 0x29, 0x73, 0x71, 0xe6, 0x37, 0x8a, 0x3e, 0x69, + /*5b50:*/ 0x66, 0xfd, 0xb2, 0x4b, 0x85, 0xa9, 0x29, 0x11, 0xce, 0x9b, 0x5a, 0x77, 0x48, 0xc8, 0x45, 0x19, + /*5b60:*/ 0x22, 0x07, 0x84, 0x91, 0xa0, 0x91, 0x5d, 0x7b, 0xde, 0x37, 0xd5, 0xcf, 0x62, 0x4e, 0x01, 0xd1, + /*5b70:*/ 0x87, 0x1f, 0xf9, 0x2d, 0xe6, 0x35, 0x67, 0x45, 0x69, 0x5a, 0x50, 0xaf, 0xae, 0xa8, 0x5b, 0x62, + /*5b80:*/ 0xbb, 0x03, 0x86, 0x97, 0x7f, 0x84, 0xe2, 0xbf, 0xc3, 0x04, 0x06, 0x1d, 0x08, 0xbc, 0x6d, 0x8e, + /*5b90:*/ 0xb9, 0x7a, 0x0d, 0xf1, 0x6c, 0xc6, 0x25, 0xd2, 0x17, 0x26, 0x05, 0x4c, 0xe3, 0xd6, 0x52, 0x19, + /*5ba0:*/ 0xf3, 0xd0, 0xb1, 0x0b, 0x62, 0x4d, 0x6c, 0x8e, 0xb8, 0x34, 0x1e, 0xd8, 0x0e, 0x88, 0xe2, 0x91, + /*5bb0:*/ 0xa8, 0xf0, 0xdf, 0x13, 0xb7, 0x5e, 0x12, 0xae, 0x21, 0x6b, 0x0c, 0x60, 0xa4, 0x40, 0xee, 0x1d, + /*5bc0:*/ 0x75, 0xfa, 0xd2, 0x0e, 0x21, 0x57, 0x15, 0x87, 0x0c, 0x30, 0x9f, 0x8a, 0x1c, 0xc6, 0xde, 0x93, + /*5bd0:*/ 0xb9, 0xc5, 0x3f, 0x48, 0x81, 0x07, 0xc0, 0xcb, 0x2f, 0xd3, 0x79, 0x60, 0x99, 0xab, 0x22, 0xa2, + /*5be0:*/ 0xcd, 0xc1, 0x6a, 0x6e, 0x87, 0xdf, 0xf9, 0x32, 0xba, 0x53, 0x25, 0xab, 0x0d, 0x3a, 0xcc, 0x31, + /*5bf0:*/ 0x61, 0x0e, 0xa7, 0x16, 0x4b, 0x2e, 0x1d, 0x94, 0xc5, 0x45, 0x80, 0x0c, 0x16, 0x93, 0x7c, 0xfd, + /*5c00:*/ 0x1f, 0xa1, 0x01, 0x20, 0xfb, 0xe3, 0x93, 0x92, 0x81, 0x38, 0x78, 0xd2, 0xda, 0xbd, 0xcd, 0xf0, + /*5c10:*/ 0xe6, 0x55, 0x6e, 0x33, 0x24, 0x06, 0xcb, 0xf1, 0xb3, 0x14, 0x90, 0x28, 0xe4, 0x33, 0xd7, 0xc8, + /*5c20:*/ 0x0d, 0xbb, 0x79, 0xcc, 0xe5, 0x9f, 0xcd, 0x78, 0x99, 0xb4, 0xab, 0xe1, 0x97, 0x30, 0x26, 0x62, + /*5c30:*/ 0xbe, 0x36, 0xfe, 0x00, 0x4d, 0xdf, 0x68, 0x50, 0x67, 0x63, 0xb6, 0xe2, 0x3b, 0xef, 0xbe, 0x2f, + /*5c40:*/ 0xca, 0xa2, 0xec, 0xc8, 0x79, 0x51, 0x56, 0x8c, 0xae, 0x14, 0xf8, 0xfc, 0x3f, 0x5f, 0x94, 0xdd, + /*5c50:*/ 0xb7, 0x0a, 0x1c, 0x79, 0xea, 0x22, 0x73, 0x33, 0x66, 0x7f, 0x4b, 0x0a, 0xb4, 0x51, 0xbd, 0xa7, + /*5c60:*/ 0xed, 0x46, 0x8f, 0xf9, 0x86, 0x65, 0x31, 0xfd, 0xf0, 0xdc, 0x2e, 0xee, 0xcf, 0xa7, 0x13, 0x9f, + /*5c70:*/ 0x07, 0x78, 0xc6, 0xc6, 0x07, 0x7b, 0x51, 0xda, 0x8f, 0x0b, 0xdb, 0xba, 0xd2, 0xde, 0xc6, 0x63, + /*5c80:*/ 0xbe, 0xd5, 0x92, 0xc6, 0xcb, 0xd3, 0xb3, 0xbb, 0x26, 0xe6, 0x10, 0x1f, 0x83, 0x69, 0x0e, 0x0a, + /*5c90:*/ 0xeb, 0xd5, 0x35, 0x71, 0xed, 0xa8, 0x77, 0x7a, 0x5a, 0x07, 0xaf, 0xd1, 0x3a, 0x00, 0xf6, 0x83, + /*5ca0:*/ 0x7e, 0x0d, 0x6c, 0xed, 0xd8, 0xc6, 0x3c, 0x15, 0x9d, 0xad, 0x5b, 0x1c, 0xb6, 0xfb, 0x4d, 0x89, + /*5cb0:*/ 0x0f, 0xa2, 0x8f, 0xf9, 0x3e, 0x48, 0x77, 0xeb, 0xd0, 0x8a, 0x0e, 0xfe, 0xd2, 0x15, 0x38, 0x1e, + /*5cc0:*/ 0x9c, 0x08, 0x60, 0xd8, 0xbf, 0x95, 0xb9, 0xe9, 0x5d, 0x6d, 0x7b, 0x8c, 0x86, 0x33, 0xe4, 0xb1, + /*5cd0:*/ 0x10, 0xf6, 0x0b, 0x1c, 0x2a, 0xcc, 0xe7, 0x3b, 0xc1, 0x18, 0x14, 0xf5, 0x8b, 0xf4, 0x50, 0x5b, + /*5ce0:*/ 0x64, 0x46, 0x8f, 0xc3, 0x70, 0xfb, 0x68, 0xe6, 0x9a, 0x73, 0x4e, 0x23, 0xc6, 0x21, 0x96, 0xf1, + /*5cf0:*/ 0x9f, 0xca, 0x75, 0xc4, 0xaf, 0xb2, 0xde, 0xd6, 0xa9, 0x5c, 0xa5, 0x18, 0x5d, 0x84, 0x79, 0xe3, + /*5d00:*/ 0xc5, 0xf5, 0x44, 0x5e, 0x63, 0xf0, 0xc8, 0x35, 0x15, 0xe3, 0xff, 0x04, 0x8a, 0x31, 0xd0, 0xee, + /*5d10:*/ 0xc6, 0xe4, 0x77, 0x30, 0xb8, 0x77, 0x49, 0x68, 0x1c, 0x33, 0x99, 0x2d, 0x7e, 0xf5, 0x45, 0xa9, + /*5d20:*/ 0x13, 0x69, 0xc2, 0xab, 0x3f, 0xea, 0x49, 0x07, 0x4b, 0xc9, 0x9d, 0x8a, 0x1f, 0x41, 0x7f, 0xf7, + /*5d30:*/ 0x98, 0x2d, 0x75, 0x11, 0x10, 0x23, 0xb7, 0xab, 0x26, 0x79, 0x04, 0x9c, 0x10, 0x2a, 0x75, 0xef, + /*5d40:*/ 0x54, 0xe6, 0xc7, 0xab, 0x2d, 0xe7, 0xb3, 0xf4, 0xdd, 0x9e, 0xb5, 0xda, 0xbd, 0x7b, 0xe9, 0xbd, + /*5d50:*/ 0x6b, 0xd8, 0xf3, 0x4b, 0x05, 0x76, 0xdb, 0x03, 0xa4, 0x2b, 0x37, 0x20, 0x8b, 0x3e, 0x2b, 0xa2, + /*5d60:*/ 0x18, 0x01, 0x8e, 0xcf, 0xf9, 0x3e, 0x8b, 0xf1, 0x80, 0x24, 0xde, 0x31, 0xd1, 0x81, 0x70, 0xaf, + /*5d70:*/ 0x82, 0xd7, 0x58, 0xa8, 0xdc, 0xce, 0x2b, 0x55, 0x44, 0x21, 0x2b, 0xe1, 0xac, 0x0e, 0x23, 0xe7, + /*5d80:*/ 0xb2, 0x0b, 0x5e, 0x12, 0x3c, 0x4e, 0x6e, 0x3b, 0xf7, 0xbb, 0xce, 0x72, 0x5a, 0x5d, 0x54, 0xa0, + /*5d90:*/ 0xf5, 0x2e, 0xce, 0x9f, 0x76, 0xbf, 0x25, 0xb1, 0xeb, 0x5a, 0xa6, 0x61, 0x7d, 0x98, 0x33, 0x2f, + /*5da0:*/ 0x49, 0x3d, 0xec, 0xdf, 0xef, 0xed, 0xa1, 0x90, 0xeb, 0xde, 0xc3, 0x89, 0xd0, 0x04, 0xa7, 0xa0, + /*5db0:*/ 0xaa, 0xb3, 0xed, 0x54, 0x13, 0xc4, 0x70, 0x90, 0xfa, 0x2a, 0xfd, 0x24, 0x87, 0xf5, 0x12, 0x82, + /*5dc0:*/ 0xf0, 0x39, 0xfd, 0x1a, 0xd5, 0x0f, 0x26, 0x4a, 0xaf, 0x40, 0xb4, 0x2e, 0x3f, 0x9c, 0xa7, 0x35, + /*5dd0:*/ 0xcb, 0x5d, 0xf3, 0x21, 0xea, 0xbf, 0xb9, 0x14, 0x01, 0x06, 0x36, 0xcc, 0x06, 0xba, 0xa9, 0x8a, + /*5de0:*/ 0x32, 0x22, 0x12, 0x22, 0x19, 0xff, 0x64, 0xd2, 0x33, 0x98, 0x90, 0xb0, 0x57, 0xcb, 0xe7, 0x6a, + /*5df0:*/ 0x58, 0xc9, 0x1d, 0x85, 0x08, 0x4e, 0x18, 0x57, 0x4b, 0x20, 0xd6, 0xbe, 0xaa, 0x8c, 0x44, 0xad, + /*5e00:*/ 0x83, 0x78, 0xe5, 0x79, 0x72, 0xc6, 0xa8, 0xf1, 0xe5, 0x09, 0x9d, 0x4f, 0x54, 0xd5, 0xb9, 0x7d, + /*5e10:*/ 0x5b, 0xe8, 0x9f, 0xb1, 0x45, 0xc2, 0xe3, 0xe3, 0xe2, 0xbf, 0x4d, 0xb4, 0x5b, 0x88, 0x15, 0x70, + /*5e20:*/ 0x94, 0xf0, 0xe6, 0x2c, 0x3c, 0x66, 0x15, 0xf2, 0xab, 0xdf, 0x57, 0x74, 0x59, 0x8e, 0x30, 0x0a, + /*5e30:*/ 0x52, 0xe0, 0x96, 0x54, 0x84, 0xbd, 0x28, 0x94, 0x80, 0x4d, 0xac, 0x0a, 0xc1, 0xf6, 0x36, 0x8b, + /*5e40:*/ 0x7b, 0x11, 0xce, 0x6e, 0x43, 0x50, 0xbc, 0x94, 0x93, 0x96, 0x29, 0xe3, 0xf3, 0x28, 0x1b, 0x88, + /*5e50:*/ 0x23, 0xb8, 0x7d, 0x0e, 0xd0, 0xb9, 0x46, 0x81, 0xa1, 0xb3, 0xba, 0xb9, 0x67, 0x48, 0xe6, 0xc5, + /*5e60:*/ 0x11, 0x12, 0xa3, 0xaa, 0xf3, 0x1d, 0xe0, 0x64, 0x20, 0x09, 0x31, 0xe4, 0x21, 0xd1, 0xbb, 0x6c, + /*5e70:*/ 0x67, 0x83, 0x43, 0xd1, 0x9b, 0x91, 0x3d, 0xdf, 0xea, 0xf3, 0xaf, 0x77, 0x4d, 0x58, 0x16, 0xe8, + /*5e80:*/ 0xce, 0xd6, 0x60, 0xaa, 0xa9, 0x40, 0x6d, 0x44, 0xbc, 0xb2, 0x46, 0x27, 0xc3, 0xa3, 0x5c, 0x18, + /*5e90:*/ 0xcd, 0xd9, 0xe5, 0xef, 0x91, 0x14, 0x3b, 0xff, 0xb2, 0xbd, 0x65, 0x9a, 0xf8, 0x75, 0x76, 0x7b, + /*5ea0:*/ 0x0f, 0xf8, 0xad, 0x0b, 0xbf, 0x4b, 0xdf, 0x2e, 0xa8, 0x45, 0xac, 0x4c, 0x3b, 0xb0, 0x18, 0x8e, + /*5eb0:*/ 0xb5, 0x85, 0x23, 0x1b, 0x63, 0xed, 0xaa, 0x09, 0x52, 0xb6, 0x36, 0xe0, 0xb8, 0x15, 0xa8, 0x8b, + /*5ec0:*/ 0x51, 0x4c, 0xa3, 0xca, 0x09, 0x3c, 0xec, 0x83, 0x91, 0xfb, 0x4f, 0x3b, 0xc5, 0x35, 0x4c, 0x13, + /*5ed0:*/ 0x0a, 0x8f, 0x58, 0xb5, 0x19, 0x29, 0xdd, 0x46, 0x53, 0xbd, 0xf4, 0x15, 0xdf, 0x29, 0xf5, 0xa4, + /*5ee0:*/ 0x25, 0x45, 0x85, 0xa3, 0x00, 0x75, 0x4d, 0x38, 0xfb, 0xfe, 0x53, 0xed, 0x1f, 0x14, 0xf2, 0x0e, + /*5ef0:*/ 0xb7, 0x40, 0x62, 0x88, 0x92, 0x54, 0x6e, 0xd2, 0xa5, 0x8d, 0x7a, 0x9b, 0x2b, 0xee, 0x74, 0xb0, + /*5f00:*/ 0xb0, 0x17, 0x2b, 0xd3, 0x46, 0x6a, 0x3d, 0xcb, 0xdc, 0x93, 0x00, 0xfc, 0xf1, 0x3d, 0x4d, 0x25, + /*5f10:*/ 0xe9, 0x8d, 0xdf, 0x8d, 0x0d, 0x4a, 0x3e, 0xcb, 0x58, 0xc2, 0x33, 0x72, 0x0b, 0xd2, 0x8d, 0x55, + /*5f20:*/ 0x74, 0x63, 0x66, 0x3f, 0x9b, 0xeb, 0x77, 0x17, 0xb9, 0x18, 0x9c, 0xc8, 0xb7, 0x9b, 0x52, 0x1c, + /*5f30:*/ 0xbd, 0xa9, 0xa1, 0x3d, 0x51, 0x7e, 0x9a, 0xf8, 0x94, 0x14, 0xb8, 0x59, 0xec, 0xe2, 0x2f, 0xf6, + /*5f40:*/ 0xdd, 0x8a, 0x44, 0x55, 0x72, 0xc8, 0x7b, 0xaf, 0xce, 0xd2, 0x85, 0xb8, 0x71, 0x2d, 0x2e, 0x9e, + /*5f50:*/ 0xcb, 0x22, 0xbf, 0xdb, 0xd3, 0x85, 0x08, 0x7c, 0x48, 0x06, 0xd7, 0xbe, 0x5a, 0xa6, 0x5a, 0xe5, + /*5f60:*/ 0x83, 0x6f, 0xbc, 0xc2, 0xf0, 0xce, 0xc1, 0x8c, 0x54, 0x5e, 0x01, 0x93, 0xc4, 0x48, 0x62, 0x29, + /*5f70:*/ 0xef, 0x74, 0x0a, 0x80, 0xb8, 0x03, 0x61, 0x67, 0x13, 0x38, 0xd5, 0x55, 0x89, 0xc1, 0x51, 0x06, + /*5f80:*/ 0x2f, 0xb6, 0x24, 0x34, 0xbe, 0x92, 0xc9, 0x9b, 0xa4, 0xc8, 0x50, 0x50, 0xb4, 0xf3, 0xba, 0xd3, + /*5f90:*/ 0x77, 0x18, 0xd1, 0x8d, 0x95, 0x11, 0x48, 0x0d, 0xbc, 0x2b, 0x0f, 0xee, 0x04, 0x6a, 0xd8, 0xa0, + /*5fa0:*/ 0x6a, 0xfb, 0x6e, 0xae, 0xac, 0x6c, 0xad, 0x4b, 0x66, 0x61, 0x35, 0x00, 0x29, 0x19, 0x31, 0x7d, + /*5fb0:*/ 0x67, 0x58, 0xd0, 0x95, 0x81, 0xfe, 0x31, 0x46, 0x91, 0xd8, 0xac, 0xb4, 0x5e, 0xbf, 0xf3, 0xfc, + /*5fc0:*/ 0x4a, 0xcc, 0x67, 0xc6, 0xbf, 0x89, 0xb9, 0x9a, 0x83, 0x3a, 0x6a, 0x00, 0xe3, 0x8e, 0x7f, 0x03, + /*5fd0:*/ 0xa2, 0xc6, 0x6e, 0x81, 0x9a, 0xd3, 0xf9, 0x9e, 0xb9, 0xe1, 0x15, 0x01, 0xb3, 0x6d, 0xc4, 0xea, + /*5fe0:*/ 0xa1, 0x3a, 0x29, 0x38, 0x64, 0x07, 0xeb, 0x7c, 0x96, 0x3c, 0x05, 0xc9, 0xee, 0x2c, 0x13, 0x91, + /*5ff0:*/ 0x30, 0x33, 0x84, 0x01, 0x31, 0xe0, 0xef, 0xe9, 0x31, 0x07, 0x59, 0x9b, 0xca, 0xc2, 0x73, 0xc1, + /*6000:*/ 0xbc, 0x1c, 0xd8, 0xc0, 0xce, 0x1d, 0xf4, 0x25, 0x2e, 0x88, 0xa1, 0xc1, 0x48, 0x98, 0x0c, 0xae, + /*6010:*/ 0x01, 0x9f, 0xe0, 0x94, 0x38, 0x4f, 0xd0, 0x8c, 0x36, 0x6b, 0x4d, 0xd5, 0x0b, 0x03, 0x8a, 0x5d, + /*6020:*/ 0x15, 0x3c, 0x3a, 0x09, 0x32, 0x95, 0xd8, 0xdb, 0x9f, 0xcf, 0x71, 0x67, 0x9b, 0xc6, 0xab, 0x87, + /*6030:*/ 0xd4, 0xfe, 0xad, 0xc2, 0xde, 0x17, 0x9c, 0xba, 0x4b, 0x1c, 0x73, 0x69, 0xe4, 0xa5, 0xc1, 0x90, + /*6040:*/ 0x2c, 0x25, 0xec, 0x91, 0x2e, 0xd9, 0x18, 0xe5, 0xa4, 0xfb, 0x4d, 0x6b, 0x31, 0x5d, 0xbb, 0xb5, + /*6050:*/ 0xb9, 0xe1, 0xdc, 0xf6, 0xcd, 0x88, 0x15, 0xbe, 0x82, 0xf7, 0x7e, 0x74, 0x9f, 0x67, 0x84, 0x38, + /*6060:*/ 0x60, 0x25, 0xa6, 0x22, 0x8a, 0xfa, 0xd1, 0x54, 0x9d, 0x4a, 0xab, 0x80, 0x8e, 0xf3, 0x46, 0x92, + /*6070:*/ 0x93, 0xd3, 0x56, 0xdf, 0x3c, 0xed, 0xfe, 0x16, 0x90, 0x7f, 0x22, 0xe8, 0xda, 0x79, 0xe3, 0x4d, + /*6080:*/ 0x32, 0x34, 0x05, 0xa4, 0x1e, 0xf8, 0xa1, 0xa4, 0x73, 0xe8, 0x3b, 0x94, 0xcc, 0xc5, 0x56, 0x86, + /*6090:*/ 0xd5, 0xc5, 0x52, 0x23, 0xf1, 0x3e, 0xbb, 0x73, 0x5f, 0x2e, 0xa4, 0x53, 0x18, 0x1d, 0xeb, 0xbc, + /*60a0:*/ 0xab, 0x38, 0x61, 0x83, 0x15, 0xcf, 0xbc, 0xff, 0xb7, 0x3e, 0x43, 0xa7, 0x48, 0x10, 0x64, 0x52, + /*60b0:*/ 0x3c, 0xae, 0x7c, 0x8f, 0xf0, 0x21, 0x96, 0x99, 0xc4, 0xc5, 0xaa, 0xfe, 0x96, 0xc0, 0x13, 0xa9, + /*60c0:*/ 0x91, 0xe2, 0xb3, 0x6b, 0x52, 0xea, 0x5f, 0xfa, 0xcd, 0xe3, 0x48, 0xd8, 0x8e, 0x8a, 0x8d, 0x8f, + /*60d0:*/ 0x89, 0x45, 0xf0, 0xcb, 0xc8, 0xc7, 0x21, 0x44, 0x22, 0xb3, 0xad, 0x68, 0x55, 0xd1, 0x59, 0xa6, + /*60e0:*/ 0xd0, 0x7e, 0xb2, 0xd3, 0xf1, 0xd1, 0x0a, 0x25, 0xc2, 0x3f, 0x3b, 0x40, 0x34, 0x03, 0x1e, 0xc3, + /*60f0:*/ 0x3c, 0x71, 0x70, 0xf8, 0x3a, 0x6a, 0x9d, 0x7c, 0x46, 0xbb, 0xd7, 0x79, 0x66, 0x6a, 0x3d, 0xb6, + /*6100:*/ 0x6f, 0x57, 0xa8, 0x22, 0xf3, 0x1e, 0x8c, 0x91, 0x44, 0x86, 0xa5, 0x91, 0xce, 0x11, 0x14, 0xc0, + /*6110:*/ 0x13, 0xaa, 0xaa, 0xbe, 0xb0, 0x7f, 0x2b, 0x6b, 0x12, 0x53, 0x75, 0x82, 0xcb, 0x1b, 0x56, 0xf8, + /*6120:*/ 0xc6, 0x1b, 0x83, 0x8c, 0x94, 0xd4, 0xfa, 0x0b, 0x2f, 0x90, 0x0d, 0xf0, 0x05, 0x80, 0xac, 0x2d, + /*6130:*/ 0xf2, 0x1c, 0x7a, 0x53, 0xce, 0x2a, 0xd2, 0xc8, 0xd7, 0x0c, 0x84, 0x60, 0xe1, 0x4d, 0xb1, 0x75, + /*6140:*/ 0x56, 0xc8, 0xf8, 0xab, 0x4d, 0x49, 0x16, 0x87, 0x41, 0x71, 0x1b, 0x0f, 0xed, 0x3a, 0xa6, 0xe4, + /*6150:*/ 0x92, 0x9e, 0xe7, 0xad, 0xb5, 0xb3, 0x0c, 0xa1, 0x7d, 0x00, 0x3d, 0x54, 0x11, 0xc6, 0x34, 0xb8, + /*6160:*/ 0x87, 0x2a, 0xb7, 0xf7, 0x56, 0xd1, 0x3e, 0x18, 0xa1, 0xcc, 0xc0, 0x71, 0x5d, 0xe3, 0x66, 0xf0, + /*6170:*/ 0xea, 0x05, 0xa4, 0xe2, 0x55, 0x77, 0x8c, 0x5c, 0xa5, 0xca, 0xb1, 0xae, 0xf4, 0x0f, 0xb3, 0x9d, + /*6180:*/ 0xb8, 0x0f, 0x1e, 0x0f, 0x8e, 0x5e, 0xbb, 0x0e, 0x26, 0x5e, 0x3a, 0xdc, 0xca, 0xb5, 0xa2, 0xad, + /*6190:*/ 0x1d, 0xfe, 0x65, 0x89, 0x4e, 0x67, 0x8c, 0xe3, 0xc6, 0x61, 0x0f, 0x28, 0x8c, 0x7a, 0xf0, 0x18, + /*61a0:*/ 0x26, 0xbd, 0x05, 0x5f, 0x08, 0xba, 0x7b, 0x76, 0xb3, 0xc0, 0x76, 0x52, 0xfe, 0xda, 0x9b, 0x79, + /*61b0:*/ 0xb9, 0x2b, 0x12, 0x05, 0xdf, 0x3f, 0xa3, 0x92, 0xff, 0x2f, 0x82, 0x65, 0x0c, 0xe6, 0x10, 0x26, + /*61c0:*/ 0x20, 0x3a, 0xbf, 0x49, 0x70, 0x40, 0x94, 0xd3, 0xc2, 0xd9, 0xf1, 0x66, 0xc4, 0x79, 0x57, 0xe6, + /*61d0:*/ 0xcd, 0x93, 0xd8, 0xc7, 0x21, 0xd0, 0x4d, 0x71, 0x39, 0x4c, 0xaf, 0xdf, 0xb8, 0x34, 0xa7, 0xdc, + /*61e0:*/ 0x94, 0x78, 0x2e, 0x1a, 0x6c, 0x1b, 0xb6, 0xe7, 0x18, 0x45, 0xb7, 0x05, 0xe9, 0x12, 0x20, 0x95, + /*61f0:*/ 0xa2, 0x6c, 0x35, 0x27, 0xaf, 0xdf, 0xed, 0x1f, 0x70, 0xd5, 0x74, 0x44, 0x65, 0x54, 0x38, 0x12, + /*6200:*/ 0x9c, 0xe8, 0x59, 0x3f, 0x9a, 0x07, 0x44, 0x32, 0xa7, 0x4b, 0x0a, 0xe5, 0x1d, 0x08, 0x82, 0x86, + /*6210:*/ 0xcf, 0x99, 0x47, 0x8d, 0xb4, 0x29, 0xa4, 0x96, 0x3f, 0x65, 0x8e, 0xaf, 0xb4, 0x44, 0xe9, 0x69, + /*6220:*/ 0x1e, 0xe8, 0xc8, 0xcb, 0x67, 0xd9, 0x78, 0x2e, 0xbb, 0x11, 0x72, 0xed, 0x4f, 0xe5, 0x95, 0xad, + /*6230:*/ 0x13, 0xc9, 0x68, 0x0c, 0x0e, 0xe4, 0xde, 0xcf, 0xb1, 0x65, 0xc5, 0x36, 0xe9, 0xeb, 0x25, 0xe7, + /*6240:*/ 0xdf, 0xe5, 0x02, 0x09, 0x31, 0x37, 0x99, 0x7a, 0xe3, 0xe5, 0x34, 0xf6, 0xea, 0x6e, 0xcc, 0x39, + /*6250:*/ 0x64, 0xbe, 0xb3, 0xd3, 0x0f, 0xf2, 0x7e, 0x18, 0xba, 0x53, 0x35, 0x19, 0x3f, 0x9f, 0x5a, 0x80, + /*6260:*/ 0x2a, 0xbb, 0x7e, 0x92, 0x31, 0xfd, 0x2a, 0x66, 0xee, 0x54, 0xd0, 0x32, 0xa3, 0x53, 0x2d, 0xfc, + /*6270:*/ 0xf5, 0x59, 0x13, 0xe1, 0xb0, 0xe9, 0x31, 0x07, 0x19, 0xe5, 0x08, 0x8e, 0x24, 0x87, 0x39, 0x8b, + /*6280:*/ 0xb2, 0xa8, 0xde, 0x81, 0xaa, 0x47, 0x5b, 0x9a, 0x41, 0xd5, 0xda, 0xb9, 0x61, 0x59, 0x4f, 0x30, + /*6290:*/ 0x25, 0xa3, 0x56, 0x4f, 0x9b, 0x9e, 0x63, 0x96, 0x75, 0xba, 0xfd, 0xf0, 0x4b, 0x64, 0x73, 0xbb, + /*62a0:*/ 0xa2, 0x96, 0x5b, 0xbf, 0xce, 0xc3, 0xa1, 0xa8, 0x90, 0xc9, 0x19, 0xf7, 0xb1, 0x82, 0xb7, 0xcc, + /*62b0:*/ 0xb1, 0x57, 0xa0, 0x13, 0x7c, 0x60, 0x34, 0x32, 0x65, 0xba, 0xf2, 0x5f, 0x41, 0xdc, 0x00, 0xd1, + /*62c0:*/ 0x5a, 0x38, 0xb6, 0x4f, 0x4d, 0xec, 0x18, 0x31, 0xc3, 0x8b, 0xaa, 0x06, 0xda, 0x2f, 0x2e, 0x7c, + /*62d0:*/ 0x2b, 0x57, 0x29, 0x81, 0x43, 0xb2, 0xca, 0xb9, 0x61, 0x2c, 0x94, 0x5e, 0x8e, 0xa2, 0x33, 0x80, + /*62e0:*/ 0x0a, 0x4b, 0x58, 0xa7, 0x1c, 0xf7, 0x0d, 0xc0, 0x1a, 0x61, 0x14, 0xf8, 0x82, 0x57, 0x5b, 0x0d, + /*62f0:*/ 0x17, 0x71, 0x8d, 0xf9, 0x42, 0x9a, 0x41, 0x1f, 0x84, 0x98, 0xcb, 0x38, 0x25, 0x4a, 0xb9, 0x0a, + /*6300:*/ 0xf1, 0xfc, 0x94, 0x14, 0x21, 0x51, 0xe3, 0xe5, 0x1a, 0xd9, 0x70, 0x31, 0x1a, 0x84, 0xaf, 0x08, + /*6310:*/ 0x20, 0x9f, 0x96, 0x61, 0x84, 0xf5, 0xfb, 0xfc, 0x4f, 0xf0, 0xb7, 0xcc, 0xef, 0x99, 0xb9, 0x6d, + /*6320:*/ 0x95, 0x11, 0x57, 0x20, 0x62, 0x62, 0xa8, 0xfb, 0xec, 0xf1, 0x0f, 0xcc, 0xc9, 0xf0, 0x63, 0xb8, + /*6330:*/ 0x59, 0xa4, 0xf8, 0xb0, 0xfd, 0xf6, 0xe2, 0x61, 0x45, 0x9b, 0xb4, 0x18, 0xf5, 0xe5, 0x9f, 0x3e, + /*6340:*/ 0x97, 0xe7, 0x3f, 0x08, 0xf7, 0x63, 0x9b, 0x71, 0x4f, 0x06, 0x95, 0x66, 0xa7, 0x2e, 0xa1, 0xa3, + /*6350:*/ 0xef, 0x22, 0xf7, 0x82, 0x00, 0xf8, 0xc6, 0x04, 0x03, 0xf6, 0x90, 0x4d, 0xd2, 0xe7, 0xb2, 0xda, + /*6360:*/ 0xeb, 0x4b, 0xff, 0x40, 0x33, 0x28, 0xed, 0x33, 0x81, 0x9e, 0xfa, 0x18, 0x43, 0xac, 0x82, 0x99, + /*6370:*/ 0x09, 0xa5, 0x7c, 0xd7, 0xc0, 0xf2, 0x9a, 0xeb, 0xb4, 0xb6, 0x18, 0x9a, 0x9c, 0x8e, 0x5e, 0xed, + /*6380:*/ 0x49, 0x18, 0xb6, 0x14, 0x74, 0x3b, 0x19, 0x2d, 0xa0, 0xdf, 0xc0, 0xa3, 0x56, 0x6b, 0x17, 0x80, + /*6390:*/ 0x40, 0x36, 0x2f, 0x5b, 0xf8, 0xc0, 0x39, 0x0b, 0x64, 0x73, 0x31, 0x15, 0x0f, 0x54, 0x3d, 0x52, + /*63a0:*/ 0x39, 0x99, 0xe3, 0x37, 0xaf, 0xae, 0xaa, 0xf2, 0x1e, 0xc4, 0x53, 0x41, 0xa8, 0x41, 0x82, 0x5c, + /*63b0:*/ 0xde, 0x4a, 0xef, 0xa9, 0x4b, 0x31, 0xfe, 0xdb, 0x5a, 0x2d, 0x55, 0xa2, 0x5a, 0x84, 0xda, 0xfc, + /*63c0:*/ 0x47, 0xbc, 0x8c, 0x5f, 0x6c, 0x30, 0x6f, 0xb7, 0xb0, 0x57, 0xe2, 0xe3, 0x30, 0x75, 0xae, 0x9d, + /*63d0:*/ 0x78, 0xd5, 0x98, 0x44, 0xee, 0x86, 0x44, 0x3c, 0xfd, 0x18, 0x0d, 0x5c, 0x16, 0x86, 0x04, 0xdb, + /*63e0:*/ 0x8a, 0xda, 0x0c, 0x37, 0xef, 0xb1, 0xea, 0xe5, 0x7c, 0x10, 0x6a, 0x17, 0x01, 0xd4, 0x44, 0x4e, + /*63f0:*/ 0xf3, 0xb3, 0x47, 0xce, 0x10, 0x78, 0x6e, 0x69, 0x98, 0x3e, 0x61, 0x21, 0xde, 0x65, 0x50, 0xb4, + /*6400:*/ 0x2e, 0x08, 0x08, 0x6b, 0xef, 0x25, 0x1b, 0x9d, 0x68, 0xee, 0xd0, 0xce, 0xd5, 0x36, 0xb0, 0xcd, + /*6410:*/ 0x4e, 0x0c, 0x19, 0x59, 0x57, 0xd8, 0xa1, 0x69, 0xe5, 0x1f, 0xba, 0x8d, 0x28, 0xa4, 0xe0, 0x56, + /*6420:*/ 0xdf, 0xab, 0xd0, 0x2a, 0x27, 0x60, 0xd3, 0xa1, 0x69, 0xbb, 0x77, 0xe5, 0xef, 0xa8, 0x99, 0xb4, + /*6430:*/ 0x3f, 0xc1, 0x09, 0x72, 0x69, 0xe9, 0x73, 0x5b, 0x59, 0x48, 0x4c, 0x1d, 0x9d, 0x73, 0xb6, 0x8e, + /*6440:*/ 0x2a, 0x66, 0x7e, 0xf5, 0xaf, 0x12, 0x69, 0xcf, 0x61, 0xbd, 0xd3, 0x84, 0xd3, 0x3a, 0xe4, 0xbf, + /*6450:*/ 0x7f, 0xeb, 0x21, 0x59, 0x72, 0x7c, 0xa6, 0x89, 0x6b, 0x2e, 0xc9, 0x46, 0xa8, 0x05, 0xc9, 0xf9, + /*6460:*/ 0x7a, 0x25, 0x27, 0xb8, 0xda, 0x80, 0xf6, 0xa7, 0x69, 0x28, 0x06, 0x5d, 0x8e, 0xa6, 0x0d, 0x3c, + /*6470:*/ 0x7b, 0x2a, 0xce, 0x1a, 0x13, 0x53, 0x98, 0x85, 0x1f, 0xc9, 0xce, 0xd0, 0xd4, 0x76, 0x6d, 0x6e, + /*6480:*/ 0xa9, 0x4e, 0x5a, 0x44, 0xc2, 0xb4, 0x6f, 0x5e, 0xe8, 0x8c, 0x88, 0xfb, 0xe2, 0x1e, 0x4b, 0x1a, + /*6490:*/ 0xa9, 0x55, 0x09, 0x70, 0x73, 0xf9, 0x4f, 0xd4, 0x4a, 0x53, 0xaa, 0x7e, 0x67, 0xe5, 0x61, 0x13, + /*64a0:*/ 0x53, 0xfc, 0xef, 0xe6, 0x82, 0x6a, 0xdf, 0x82, 0x87, 0x93, 0x8f, 0x85, 0x7a, 0x8e, 0x7a, 0xb9, + /*64b0:*/ 0xd8, 0xf9, 0xac, 0x79, 0x2c, 0x87, 0x9f, 0x40, 0x9a, 0xe3, 0x8b, 0xbd, 0x15, 0xaf, 0x70, 0xfb, + /*64c0:*/ 0x7f, 0x80, 0x74, 0x6c, 0x94, 0x02, 0x0d, 0xd2, 0x41, 0x7f, 0xe2, 0x38, 0xcb, 0xfe, 0x99, 0xef, + /*64d0:*/ 0xd7, 0x0e, 0x74, 0x93, 0x66, 0xae, 0xa7, 0x10, 0x42, 0x10, 0xf6, 0x77, 0x5e, 0x16, 0xe7, 0x4c, + /*64e0:*/ 0x41, 0x51, 0xc8, 0x80, 0x6c, 0xaf, 0xb9, 0xb6, 0x91, 0x17, 0xb3, 0xba, 0x00, 0x07, 0xe4, 0xd1, + /*64f0:*/ 0x89, 0x05, 0x31, 0xc9, 0x6c, 0x5a, 0x8f, 0x4c, 0xd2, 0x03, 0xe7, 0x79, 0x65, 0xfb, 0x6a, 0x60, + /*6500:*/ 0x6c, 0x1d, 0x88, 0x94, 0xf3, 0xc0, 0x15, 0xd0, 0xc3, 0xad, 0x93, 0x81, 0xee, 0x3e, 0x48, 0x9b, + /*6510:*/ 0xa7, 0xe8, 0x9b, 0x26, 0x55, 0x97, 0xcd, 0x15, 0xc1, 0xf0, 0x97, 0xb0, 0x47, 0x42, 0xba, 0xea, + /*6520:*/ 0x04, 0x2e, 0x31, 0xf8, 0xb3, 0xf5, 0xcb, 0xa4, 0xec, 0xf5, 0x59, 0xe4, 0x8f, 0x03, 0x69, 0x85, + /*6530:*/ 0x94, 0x55, 0x00, 0xeb, 0xa5, 0x15, 0xca, 0xe2, 0xac, 0xc7, 0xfb, 0x79, 0x23, 0xbc, 0x60, 0x2b, + /*6540:*/ 0x87, 0xcc, 0x55, 0xc5, 0xe8, 0x79, 0xd0, 0x1e, 0x4b, 0xde, 0xf6, 0xf0, 0x26, 0x87, 0x88, 0x29, + /*6550:*/ 0xf4, 0x78, 0x77, 0x42, 0xaf, 0x38, 0x53, 0xc4, 0x91, 0x7b, 0xf0, 0x2d, 0x12, 0x2d, 0xa3, 0x15, + /*6560:*/ 0xaf, 0x2d, 0x0d, 0xd1, 0xc5, 0x07, 0x55, 0x03, 0x8c, 0x1a, 0x51, 0x5d, 0x1c, 0xcb, 0xd2, 0xd5, + /*6570:*/ 0x6a, 0x9b, 0x6e, 0x48, 0x35, 0x7d, 0xd0, 0xc0, 0x45, 0x8f, 0x14, 0xca, 0x74, 0x9f, 0x84, 0xf8, + /*6580:*/ 0xd3, 0xd3, 0xe6, 0x14, 0x66, 0xc6, 0x8c, 0xde, 0x3b, 0x54, 0x33, 0x69, 0x20, 0x23, 0x60, 0x3d, + /*6590:*/ 0xc4, 0xd5, 0x7c, 0xc6, 0xa9, 0xd9, 0xf0, 0xbd, 0x4b, 0xbd, 0x0d, 0x5c, 0xea, 0x74, 0x0a, 0x6a, + /*65a0:*/ 0x17, 0x0d, 0x71, 0xfd, 0x9b, 0xa9, 0x0a, 0x1c, 0x80, 0xf6, 0x2a, 0xd9, 0xf7, 0x2f, 0x1b, 0x41, + /*65b0:*/ 0x06, 0x09, 0x10, 0x95, 0xfc, 0xbd, 0xe4, 0x81, 0x54, 0x47, 0x0e, 0xfd, 0xca, 0xe5, 0x6f, 0x49, + /*65c0:*/ 0x39, 0xe7, 0xb4, 0xea, 0x75, 0x3c, 0x02, 0x76, 0xb5, 0xa8, 0x0e, 0x4b, 0x81, 0x2d, 0xbc, 0x9d, + /*65d0:*/ 0xc9, 0x88, 0xea, 0x8f, 0xde, 0x8d, 0xdb, 0x69, 0x91, 0x6b, 0x30, 0xbf, 0xdb, 0x43, 0x57, 0xa3, + /*65e0:*/ 0xd2, 0xde, 0x8b, 0x8e, 0xaa, 0xc0, 0x46, 0xb5, 0x09, 0x61, 0xfd, 0x92, 0x11, 0x78, 0x73, 0xed, + /*65f0:*/ 0x89, 0xa3, 0xf9, 0x33, 0xd8, 0x5f, 0xbe, 0x1c, 0x82, 0x6c, 0xd1, 0xd0, 0x58, 0xb5, 0x72, 0x43, + /*6600:*/ 0x37, 0xd6, 0xca, 0x98, 0x30, 0x9c, 0x29, 0xae, 0x11, 0x14, 0x73, 0x17, 0x6d, 0x10, 0xea, 0xa6, + /*6610:*/ 0x2d, 0xf3, 0x1b, 0xe4, 0xd2, 0xba, 0x01, 0x52, 0x4b, 0xe9, 0x54, 0xb5, 0x3f, 0x9c, 0xb4, 0x9e, + /*6620:*/ 0xac, 0xe0, 0x93, 0x6d, 0xdc, 0x1d, 0xfa, 0xf7, 0x04, 0x8f, 0x4a, 0x7e, 0x97, 0xf3, 0x01, 0x38, + /*6630:*/ 0x2f, 0xa2, 0x3d, 0xcf, 0xd1, 0x4c, 0x6c, 0x57, 0xb5, 0x8e, 0xb3, 0x59, 0xdd, 0x84, 0x8c, 0x1a, + /*6640:*/ 0xaa, 0xc4, 0x9a, 0x6d, 0x7d, 0xd2, 0xf3, 0x5f, 0x60, 0x2d, 0xd3, 0xc3, 0xdb, 0x3c, 0xef, 0xea, + /*6650:*/ 0x0c, 0x99, 0x3a, 0xd0, 0xb5, 0xbb, 0xda, 0xcc, 0x35, 0xce, 0x81, 0xc1, 0x15, 0x61, 0x2d, 0x7c, + /*6660:*/ 0x20, 0xb1, 0x2a, 0x4c, 0x19, 0x79, 0xff, 0xe7, 0xfd, 0xa2, 0x7c, 0xd4, 0x81, 0xef, 0xd6, 0xc7, + /*6670:*/ 0x89, 0xfd, 0x67, 0x8f, 0xa0, 0x64, 0xb9, 0x84, 0x68, 0x87, 0xa2, 0x7d, 0x21, 0xa9, 0xd4, 0x28, + /*6680:*/ 0x89, 0x0d, 0x62, 0x08, 0x25, 0xb6, 0x41, 0x9f, 0x0c, 0x3b, 0xdf, 0x0d, 0x86, 0x9c, 0xbd, 0x16, + /*6690:*/ 0x6f, 0x03, 0x1b, 0xd8, 0x1c, 0x00, 0x91, 0x14, 0xc1, 0x3a, 0x45, 0x96, 0xa4, 0x4c, 0xa3, 0x27, + /*66a0:*/ 0x31, 0x4d, 0xf7, 0x8b, 0x69, 0xdc, 0xab, 0x4e, 0x91, 0xb7, 0x68, 0x46, 0x52, 0x04, 0xb4, 0xf0, + /*66b0:*/ 0xa3, 0x7d, 0xf2, 0xa3, 0x14, 0xb4, 0x12, 0xda, 0xa1, 0xb4, 0xa9, 0x6b, 0x22, 0x49, 0x0c, 0xaa, + /*66c0:*/ 0x1a, 0x95, 0x57, 0x4c, 0x6c, 0x0b, 0x72, 0x36, 0xf9, 0x02, 0x41, 0x17, 0xc9, 0x70, 0x7e, 0x10, + /*66d0:*/ 0xce, 0x4c, 0xd2, 0xa0, 0x46, 0xac, 0x64, 0x5a, 0x53, 0x12, 0x5a, 0xd1, 0x4b, 0x5c, 0x87, 0xa0, + /*66e0:*/ 0xb6, 0xc9, 0xf5, 0x6e, 0xa2, 0xbb, 0x3b, 0x6c, 0x55, 0x67, 0x73, 0xe2, 0x01, 0x5d, 0xac, 0x26, + /*66f0:*/ 0xad, 0x79, 0xc4, 0x56, 0x2c, 0x33, 0x66, 0x7b, 0xb9, 0xdf, 0x4f, 0x9e, 0xe5, 0x13, 0xb8, 0xf0, + /*6700:*/ 0x70, 0x53, 0x59, 0xa0, 0xc2, 0x74, 0xc5, 0xeb, 0x76, 0x4e, 0x1c, 0x0d, 0xfe, 0x98, 0x05, 0x57, + /*6710:*/ 0xd5, 0xbe, 0x81, 0xb2, 0x67, 0x0a, 0xcc, 0xde, 0xc1, 0x4e, 0x07, 0x80, 0x34, 0xee, 0x20, 0x93, + /*6720:*/ 0xbd, 0xc1, 0xd6, 0x72, 0x47, 0x17, 0xe0, 0x27, 0x90, 0xca, 0x97, 0x0e, 0x0f, 0x6c, 0xcc, 0xe2, + /*6730:*/ 0x97, 0x47, 0x49, 0x0c, 0x73, 0xaf, 0x47, 0x8d, 0x8a, 0x2a, 0x6e, 0xfb, 0x79, 0x81, 0xe2, 0xc8, + /*6740:*/ 0x97, 0x9f, 0x7e, 0x9b, 0xf4, 0x9a, 0x8f, 0x10, 0x75, 0x23, 0x4a, 0xb9, 0xbd, 0x0d, 0x25, 0xa1, + /*6750:*/ 0x50, 0xdf, 0x40, 0x23, 0xbf, 0x1c, 0x83, 0xcd, 0x4c, 0xb7, 0xa3, 0x51, 0x7f, 0xca, 0x44, 0x23, + /*6760:*/ 0xbe, 0xd8, 0x74, 0x8a, 0x4c, 0xb3, 0x72, 0x93, 0xaa, 0x9a, 0x32, 0x11, 0xc1, 0x4b, 0x9b, 0x96, + /*6770:*/ 0x88, 0x61, 0xc7, 0x22, 0xa3, 0x6c, 0x28, 0xf1, 0x17, 0xa5, 0x02, 0x5e, 0x6d, 0x71, 0x44, 0xe7, + /*6780:*/ 0xa6, 0x63, 0x9e, 0xee, 0xc6, 0xef, 0xc0, 0x18, 0xf8, 0xea, 0xf8, 0x78, 0x73, 0x8f, 0xae, 0xed, + /*6790:*/ 0xb3, 0x5b, 0x80, 0x12, 0x5b, 0x47, 0x48, 0x54, 0x3a, 0xf3, 0xaf, 0x37, 0x14, 0xc3, 0x8c, 0x09, + /*67a0:*/ 0x1e, 0x11, 0xb5, 0xc2, 0x82, 0xef, 0x31, 0x36, 0xe6, 0x73, 0xbe, 0xea, 0x98, 0x4f, 0x14, 0x17, + /*67b0:*/ 0x1d, 0xbb, 0x89, 0xba, 0x95, 0xf6, 0x79, 0xa9, 0x71, 0xc0, 0x47, 0xf1, 0x86, 0x18, 0x7c, 0x74, + /*67c0:*/ 0x18, 0x27, 0xb7, 0x28, 0x27, 0xf6, 0x2a, 0x4a, 0xcc, 0x8e, 0x7a, 0x0f, 0x90, 0x65, 0x9a, 0xc0, + /*67d0:*/ 0xd1, 0xba, 0xf3, 0xd8, 0x49, 0x6a, 0x88, 0x68, 0x41, 0xaa, 0xb9, 0x28, 0xfe, 0x4f, 0xe4, 0x3e, + /*67e0:*/ 0x1b, 0xc8, 0xa2, 0x0f, 0x38, 0x8d, 0x7b, 0x63, 0xee, 0x46, 0xbd, 0xa2, 0x75, 0xb3, 0x27, 0x35, + /*67f0:*/ 0x72, 0xa7, 0xd4, 0xdd, 0xea, 0xdb, 0xb6, 0x1a, 0x65, 0x39, 0xce, 0xc3, 0x83, 0x65, 0x2d, 0x83, + /*6800:*/ 0xb0, 0xf1, 0xd9, 0xa1, 0xb0, 0x48, 0x0f, 0x55, 0x48, 0x3b, 0x78, 0x98, 0xc9, 0x3a, 0x93, 0xbc, + /*6810:*/ 0xdb, 0x43, 0x32, 0x27, 0xf6, 0xba, 0xb7, 0xb7, 0x99, 0x11, 0x04, 0xa9, 0x4f, 0x8f, 0x89, 0x30, + /*6820:*/ 0x19, 0xad, 0x0d, 0x30, 0xfd, 0x02, 0xfa, 0x87, 0x73, 0xc1, 0x18, 0x07, 0x51, 0x54, 0x1b, 0xdf, + /*6830:*/ 0xae, 0xfd, 0x6f, 0x62, 0x23, 0x0b, 0x7b, 0xfb, 0x8a, 0xf8, 0x2b, 0xcc, 0x69, 0x0e, 0x56, 0x6d, + /*6840:*/ 0x35, 0x9d, 0xbd, 0x71, 0x51, 0xa7, 0xd9, 0xeb, 0x34, 0x9a, 0x95, 0x9d, 0x52, 0x71, 0x3e, 0x04, + /*6850:*/ 0x9f, 0x20, 0xfb, 0xf8, 0x6a, 0xf7, 0x7d, 0x3e, 0x1f, 0xeb, 0x71, 0xe4, 0xf1, 0xbf, 0xb8, 0xb9, + /*6860:*/ 0x62, 0x70, 0x84, 0x87, 0xdc, 0x9e, 0xaf, 0x21, 0xd7, 0xa3, 0x58, 0x03, 0x90, 0x9e, 0xcb, 0x9f, + /*6870:*/ 0x5d, 0x48, 0xfb, 0xb7, 0xa6, 0x0e, 0x94, 0xb2, 0xaa, 0x4a, 0xb5, 0x7e, 0xfc, 0x6b, 0xd1, 0x59, + /*6880:*/ 0x80, 0xec, 0xb0, 0x91, 0x68, 0x62, 0xd1, 0x93, 0x25, 0x70, 0xf7, 0x47, 0x31, 0x69, 0xc9, 0x05, + /*6890:*/ 0x31, 0x5b, 0x97, 0x48, 0x28, 0xee, 0xb0, 0x77, 0xac, 0x56, 0xde, 0xb0, 0x5f, 0x14, 0x19, 0x58, + /*68a0:*/ 0x1f, 0xd1, 0x31, 0xf6, 0x02, 0xcb, 0x81, 0x6a, 0xac, 0x57, 0x62, 0xea, 0xb9, 0xf0, 0x8f, 0xfd, + /*68b0:*/ 0x78, 0xbf, 0xbc, 0x3b, 0xf2, 0x41, 0x2c, 0xff, 0x6e, 0x83, 0x5d, 0xde, 0x22, 0x7b, 0x48, 0x65, + /*68c0:*/ 0xac, 0x72, 0xce, 0x12, 0xcf, 0x0c, 0x27, 0x9b, 0xd5, 0x8d, 0xf3, 0x32, 0x1a, 0x4f, 0x67, 0xa6, + /*68d0:*/ 0xeb, 0x6a, 0x4c, 0xc8, 0x81, 0x35, 0xd0, 0x22, 0x75, 0xc9, 0xd1, 0x29, 0x8e, 0x42, 0x73, 0x99, + /*68e0:*/ 0xdd, 0x50, 0x7e, 0x3c, 0xcb, 0x5f, 0xca, 0xbf, 0x8d, 0x66, 0x13, 0x0e, 0x19, 0x01, 0x58, 0x2d, + /*68f0:*/ 0x16, 0x91, 0xb4, 0x40, 0xba, 0xed, 0x9a, 0x02, 0x04, 0xa3, 0x82, 0x14, 0x9d, 0x8b, 0xcc, 0xd5, + /*6900:*/ 0xf5, 0x6f, 0x78, 0x60, 0xe5, 0x8b, 0x06, 0xc7, 0xf0, 0xb0, 0x5d, 0xd7, 0x2e, 0x0f, 0xa0, 0x6b, + /*6910:*/ 0x39, 0xcd, 0xb4, 0x2a, 0x2d, 0x81, 0x97, 0xa1, 0xab, 0x07, 0x8c, 0x7e, 0xbc, 0x68, 0x13, 0x38, + /*6920:*/ 0x85, 0x0a, 0x88, 0x17, 0xf3, 0xba, 0xbf, 0x58, 0x9c, 0xbe, 0x43, 0x3d, 0x36, 0xc3, 0x92, 0x8c, + /*6930:*/ 0x31, 0x90, 0xe3, 0x05, 0x3f, 0x6a, 0x25, 0x6e, 0x65, 0xd7, 0x62, 0x60, 0x6e, 0x79, 0x02, 0x62, + /*6940:*/ 0xec, 0xd5, 0x9b, 0x99, 0xe4, 0x30, 0xd8, 0xf1, 0x99, 0x45, 0x9d, 0xfb, 0x62, 0x5a, 0x3f, 0x3e, + /*6950:*/ 0x2d, 0x75, 0x94, 0x5c, 0x04, 0x31, 0xc0, 0x56, 0xeb, 0x37, 0x29, 0x60, 0x3c, 0x29, 0x63, 0x54, + /*6960:*/ 0x24, 0x1f, 0x34, 0xd3, 0x81, 0x5c, 0x2b, 0x07, 0x78, 0x6a, 0xab, 0x85, 0x02, 0x50, 0xd3, 0x0f, + /*6970:*/ 0x0f, 0x94, 0x3b, 0x33, 0x9a, 0xcc, 0x99, 0xad, 0xcc, 0xfc, 0xa3, 0xdf, 0xc9, 0xe7, 0x90, 0xb7, + /*6980:*/ 0xc1, 0x76, 0xb5, 0x01, 0x66, 0xa1, 0x33, 0x38, 0x26, 0xa6, 0xbb, 0xff, 0xaf, 0x10, 0x27, 0x0a, + /*6990:*/ 0x96, 0x6b, 0x1d, 0x74, 0xb1, 0x7d, 0xa9, 0x17, 0x5c, 0x4f, 0x2d, 0x2e, 0x69, 0xaa, 0xb6, 0x4f, + /*69a0:*/ 0x95, 0xa7, 0x90, 0xcd, 0x1b, 0x60, 0xb0, 0x68, 0x93, 0x91, 0xba, 0x34, 0xa8, 0x2d, 0xe4, 0xfe, + /*69b0:*/ 0xa0, 0x8b, 0x9e, 0x82, 0x77, 0x7a, 0xe3, 0x32, 0xc1, 0x8c, 0x50, 0xdf, 0x49, 0x5f, 0x57, 0xd4, + /*69c0:*/ 0x55, 0xe4, 0x25, 0xf0, 0x07, 0x91, 0xaa, 0x77, 0x9b, 0xf9, 0x99, 0xfb, 0x98, 0xd0, 0x01, 0xf8, + /*69d0:*/ 0x6b, 0x14, 0xd3, 0xc1, 0x2d, 0xcb, 0x3e, 0xb7, 0xd5, 0xe8, 0x61, 0x20, 0xbd, 0xa5, 0xe3, 0xe0, + /*69e0:*/ 0x11, 0x6e, 0x3b, 0xe5, 0x6e, 0xe0, 0xdc, 0x2f, 0x4c, 0x8b, 0x14, 0xa7, 0x08, 0x93, 0xcd, 0xf3, + /*69f0:*/ 0x5c, 0x8e, 0x30, 0xab, 0x09, 0x36, 0x70, 0xe9, 0x0c, 0x09, 0x93, 0x45, 0xad, 0x2a, 0x6c, 0xdf, + /*6a00:*/ 0x30, 0xe9, 0x50, 0xae, 0x8b, 0x94, 0x5f, 0x20, 0x52, 0xf1, 0x91, 0x22, 0x07, 0xb6, 0x3a, 0x14, + /*6a10:*/ 0xa1, 0x33, 0x78, 0x80, 0xa6, 0x49, 0x08, 0xbf, 0xfc, 0xc2, 0x4c, 0x49, 0xee, 0x93, 0x33, 0x77, + /*6a20:*/ 0xfd, 0x7d, 0xb6, 0x3d, 0x23, 0x8f, 0x5a, 0x90, 0xa0, 0xe0, 0x3c, 0xc9, 0x93, 0x97, 0x00, 0x16, + /*6a30:*/ 0xc2, 0xeb, 0x9b, 0xfa, 0x24, 0x04, 0xc7, 0x9e, 0x46, 0xbf, 0x14, 0xa7, 0x97, 0x03, 0x5d, 0x25, + /*6a40:*/ 0x08, 0xb2, 0xf4, 0xa0, 0x1e, 0xe5, 0x47, 0x36, 0x64, 0x7e, 0xab, 0x5d, 0xa8, 0x04, 0x18, 0x84, + /*6a50:*/ 0x8e, 0x3d, 0x96, 0xa8, 0xc9, 0xfb, 0xe0, 0x1f, 0x8d, 0xa8, 0x77, 0x73, 0xe5, 0x6c, 0xcf, 0xbf, + /*6a60:*/ 0x65, 0x9c, 0x73, 0x73, 0xed, 0x36, 0x18, 0xbd, 0xcb, 0xd0, 0xb2, 0x87, 0xea, 0x0a, 0x18, 0xf5, + /*6a70:*/ 0x7c, 0x0f, 0xf7, 0x6b, 0x35, 0x4f, 0xd9, 0x07, 0x8a, 0xa1, 0xa4, 0x21, 0x40, 0x81, 0x75, 0xff, + /*6a80:*/ 0x73, 0xeb, 0xcb, 0xda, 0x30, 0x09, 0xd5, 0x2a, 0x30, 0x5c, 0xd7, 0x86, 0x72, 0xe5, 0xc9, 0x31, + /*6a90:*/ 0xca, 0x91, 0xc9, 0x90, 0x48, 0xae, 0x14, 0x59, 0xc3, 0x7e, 0x82, 0xb6, 0x9d, 0x56, 0x10, 0x59, + /*6aa0:*/ 0xd7, 0x14, 0xbb, 0x47, 0x61, 0xd8, 0x53, 0x2b, 0x56, 0x62, 0xf2, 0x8f, 0x84, 0x58, 0x1b, 0xfb, + /*6ab0:*/ 0x95, 0x8d, 0x29, 0x78, 0xf5, 0x35, 0xeb, 0xe0, 0xe1, 0x1e, 0x9b, 0x66, 0x5f, 0xbd, 0xf9, 0x8f, + /*6ac0:*/ 0x3d, 0x12, 0x95, 0xb2, 0xbb, 0x75, 0x84, 0x36, 0x51, 0x33, 0xfa, 0x5a, 0x32, 0x16, 0x93, 0x12, + /*6ad0:*/ 0x12, 0x31, 0xb5, 0x48, 0x14, 0xb4, 0xdc, 0xcb, 0xb3, 0x38, 0xa7, 0x0b, 0x60, 0x56, 0xfa, 0x73, + /*6ae0:*/ 0x28, 0x5d, 0xcf, 0x1b, 0x56, 0x4d, 0x6f, 0xea, 0xea, 0xbd, 0xfc, 0xe6, 0x3c, 0x5c, 0x41, 0x8a, + /*6af0:*/ 0x3f, 0x6c, 0xfc, 0x7d, 0x8b, 0x66, 0x4d, 0x51, 0x8d, 0x71, 0x0e, 0xbf, 0xdd, 0xa1, 0x1e, 0x92, + /*6b00:*/ 0x7c, 0x4e, 0xd4, 0x6e, 0x0c, 0xaa, 0x50, 0x96, 0xce, 0x90, 0x55, 0xcb, 0x86, 0x24, 0xf2, 0x33, + /*6b10:*/ 0xab, 0x9b, 0xc6, 0x60, 0x0d, 0x7f, 0x5b, 0x94, 0x16, 0xd3, 0x55, 0xb7, 0xb4, 0x9e, 0xfe, 0xf0, + /*6b20:*/ 0xdc, 0xae, 0x2c, 0xc5, 0x24, 0x0f, 0x7e, 0x99, 0xe4, 0x77, 0x0e, 0x96, 0x90, 0xe8, 0x39, 0xac, + /*6b30:*/ 0x8a, 0x53, 0xfb, 0xe8, 0x75, 0x24, 0x69, 0x6f, 0xb2, 0x11, 0x2a, 0x45, 0x2d, 0x2f, 0x87, 0xac, + /*6b40:*/ 0xfa, 0xea, 0xd5, 0x70, 0x98, 0x39, 0xdb, 0x81, 0xcd, 0x56, 0xdd, 0x4f, 0xdf, 0x78, 0xe1, 0x2c, + /*6b50:*/ 0xab, 0x35, 0x54, 0x37, 0x11, 0xf7, 0x23, 0x31, 0xda, 0xb1, 0xd8, 0x76, 0x2e, 0x86, 0xaa, 0xc7, + /*6b60:*/ 0x8e, 0x73, 0x6a, 0xba, 0x2a, 0x98, 0xd3, 0x6b, 0x8a, 0x1f, 0x1d, 0xd3, 0xe9, 0x04, 0x3f, 0xf0, + /*6b70:*/ 0xdb, 0xb8, 0x06, 0xd9, 0xae, 0x7e, 0xcb, 0xbf, 0x3d, 0x85, 0xa6, 0x10, 0x30, 0xbc, 0x04, 0x96, + /*6b80:*/ 0x2a, 0xc8, 0x89, 0xa9, 0xa6, 0x14, 0xdc, 0x75, 0x4d, 0x5a, 0xe5, 0x4a, 0x89, 0x49, 0x58, 0x1a, + /*6b90:*/ 0x4a, 0x07, 0x55, 0x28, 0xd8, 0x5a, 0x12, 0xa0, 0x97, 0x0e, 0xcb, 0x3b, 0x70, 0xb1, 0xa9, 0xaf, + /*6ba0:*/ 0x3a, 0xd3, 0x5b, 0xbb, 0x07, 0x4a, 0x3e, 0x04, 0xa7, 0x2f, 0x1e, 0xb7, 0xa3, 0x80, 0xa5, 0x5d, + /*6bb0:*/ 0x52, 0x1c, 0x45, 0xd4, 0x11, 0xdf, 0x1a, 0xc0, 0x8d, 0xf6, 0xe4, 0x87, 0x07, 0xa3, 0xb3, 0xa1, + /*6bc0:*/ 0xe0, 0x5d, 0x68, 0x0a, 0x2f, 0x94, 0xc3, 0xab, 0x98, 0x76, 0x5e, 0x71, 0xf3, 0x75, 0xb2, 0xcd, + /*6bd0:*/ 0x38, 0x38, 0x8e, 0xa3, 0x10, 0xb8, 0xc3, 0x83, 0x71, 0xde, 0x20, 0xa2, 0x62, 0xa9, 0x5f, 0x28, + /*6be0:*/ 0xbb, 0xfd, 0x14, 0x11, 0x6c, 0x9f, 0x90, 0x0e, 0x47, 0x0d, 0xf0, 0x28, 0x52, 0x55, 0x1c, 0x5e, + /*6bf0:*/ 0xf2, 0x8d, 0x70, 0x81, 0x73, 0x6b, 0x7a, 0x7d, 0x21, 0x3e, 0x8e, 0x4c, 0x80, 0x38, 0x8e, 0x4c, + /*6c00:*/ 0x7e, 0x29, 0x99, 0x07, 0x05, 0x25, 0x81, 0x66, 0x64, 0x34, 0x95, 0x45, 0x8c, 0xf3, 0x00, 0x81, + /*6c10:*/ 0x81, 0xb8, 0x91, 0xb4, 0xfc, 0x83, 0xc4, 0xac, 0x60, 0xfd, 0x01, 0x04, 0x7a, 0xff, 0x87, 0x04, + /*6c20:*/ 0x79, 0x40, 0xc0, 0x93, 0x72, 0x66, 0x32, 0xc6, 0xc1, 0x42, 0xe5, 0x5e, 0x74, 0xd5, 0x3b, 0xb8, + /*6c30:*/ 0xde, 0xca, 0xbd, 0x17, 0xc0, 0x5f, 0x93, 0xe5, 0xdc, 0xe7, 0xdb, 0xf8, 0x53, 0x70, 0x01, 0x4d, + /*6c40:*/ 0x7a, 0x78, 0x1f, 0xc9, 0xa8, 0x96, 0xbb, 0xde, 0x29, 0xf8, 0x0b, 0x32, 0xd2, 0x9b, 0x00, 0x33, + /*6c50:*/ 0x96, 0xa5, 0xd6, 0x7f, 0x88, 0x78, 0x3d, 0x03, 0x39, 0x8b, 0x82, 0x48, 0x88, 0xd6, 0x2d, 0x3d, + /*6c60:*/ 0xc5, 0x13, 0xee, 0x2b, 0x61, 0x54, 0xf2, 0x10, 0xec, 0xd2, 0x8d, 0x4a, 0xc4, 0xbe, 0xef, 0x36, + /*6c70:*/ 0x39, 0x4f, 0xdc, 0x63, 0xb7, 0x0c, 0x40, 0x38, 0x47, 0x85, 0x40, 0xc7, 0x8b, 0xfa, 0x1f, 0x69, + /*6c80:*/ 0x9f, 0xd9, 0xf7, 0x4f, 0x68, 0x7f, 0x34, 0x23, 0xfc, 0x95, 0xee, 0xb2, 0x1c, 0x18, 0xda, 0x2a, + /*6c90:*/ 0x2b, 0x78, 0x53, 0x53, 0xa4, 0x32, 0x01, 0x83, 0xf6, 0x3e, 0xf5, 0x40, 0xb2, 0xae, 0x0f, 0x1f, + /*6ca0:*/ 0xf7, 0x1f, 0x7f, 0x69, 0x4e, 0x44, 0x54, 0x24, 0x2d, 0x82, 0x32, 0xd3, 0x71, 0x8f, 0xf4, 0x68, + /*6cb0:*/ 0x79, 0xc0, 0xdc, 0x98, 0xa6, 0xfb, 0x9b, 0xde, 0xa5, 0xb3, 0xea, 0xbd, 0x02, 0x64, 0xcc, 0xd9, + /*6cc0:*/ 0xa2, 0x25, 0x1c, 0x42, 0x15, 0xa8, 0xf0, 0xe5, 0x43, 0x94, 0x39, 0xaf, 0x10, 0xc3, 0x20, 0xa9, + /*6cd0:*/ 0x49, 0x2d, 0x12, 0x9f, 0x8e, 0xe5, 0x10, 0x5f, 0x67, 0xb4, 0x55, 0x7a, 0x58, 0x7c, 0xfd, 0xf0, + /*6ce0:*/ 0x13, 0x8a, 0xfe, 0xff, 0x5e, 0xfc, 0xc1, 0x93, 0x57, 0xa8, 0x7f, 0xe0, 0x5e, 0xad, 0x63, 0xa8, + /*6cf0:*/ 0x38, 0x0c, 0xa3, 0xfa, 0xb3, 0xab, 0x67, 0x4a, 0x09, 0xb8, 0xe5, 0xb2, 0xbd, 0x52, 0xa6, 0xb2, + /*6d00:*/ 0x9f, 0x07, 0xe7, 0xce, 0x31, 0xe3, 0x14, 0x82, 0x99, 0xca, 0xad, 0x55, 0x9b, 0xb6, 0x9e, 0x2f, + /*6d10:*/ 0xa4, 0x4f, 0xc7, 0xaa, 0x84, 0xfb, 0x22, 0x0a, 0x45, 0x7d, 0xab, 0x24, 0xd5, 0xe3, 0xd2, 0xb1, + /*6d20:*/ 0x12, 0xc7, 0xda, 0x73, 0xe8, 0xd4, 0x43, 0x56, 0xaa, 0x9d, 0xc9, 0x0a, 0x9a, 0x19, 0x12, 0x08, + /*6d30:*/ 0x89, 0x6f, 0x37, 0x59, 0xfe, 0x67, 0x0f, 0x3c, 0x7b, 0xae, 0x30, 0xa7, 0x1b, 0x6e, 0x8d, 0xb9, + /*6d40:*/ 0xd1, 0x6f, 0x94, 0x03, 0x95, 0x22, 0x90, 0xdd, 0x2a, 0xb2, 0xc2, 0x7a, 0x12, 0xe6, 0xad, 0x41, + /*6d50:*/ 0xe6, 0xeb, 0x85, 0x8e, 0x98, 0xc0, 0xe1, 0xeb, 0x87, 0xaa, 0xf0, 0xd4, 0xde, 0x5e, 0x32, 0xdb, + /*6d60:*/ 0x73, 0xca, 0xc8, 0x5f, 0x87, 0xca, 0x00, 0x3b, 0xfe, 0x3d, 0x0f, 0x90, 0x75, 0xe1, 0x8b, 0xf6, + /*6d70:*/ 0x73, 0x46, 0x86, 0x87, 0x98, 0xbf, 0x7d, 0x6d, 0x21, 0xec, 0xa3, 0x8c, 0x5a, 0x53, 0x48, 0x06, + /*6d80:*/ 0x56, 0x9a, 0x3d, 0x2b, 0x0a, 0xd7, 0x85, 0x14, 0x0f, 0x12, 0x19, 0x91, 0xcb, 0xb1, 0x9e, 0x6d, + /*6d90:*/ 0x9c, 0x27, 0xb2, 0x4e, 0x36, 0xeb, 0xa6, 0x25, 0x22, 0x4a, 0x15, 0x21, 0xd6, 0x23, 0xcf, 0xf1, + /*6da0:*/ 0xdf, 0xba, 0x0a, 0xb0, 0x6b, 0xd9, 0xd1, 0x43, 0xfd, 0x0a, 0xa8, 0xf3, 0xf0, 0x34, 0x78, 0x41, + /*6db0:*/ 0x7e, 0x70, 0xf4, 0x40, 0xbf, 0x82, 0x37, 0x79, 0xef, 0xe5, 0x80, 0x48, 0x1f, 0x91, 0x47, 0xd6, + /*6dc0:*/ 0x7e, 0x41, 0x92, 0x1e, 0x59, 0x28, 0x05, 0xcc, 0xa6, 0xd2, 0xb8, 0xe0, 0x2c, 0xc0, 0x23, 0x58, + /*6dd0:*/ 0x50, 0x3a, 0x96, 0x83, 0xd5, 0xa8, 0xa1, 0x82, 0x88, 0x43, 0xab, 0x0b, 0x88, 0xbe, 0xb7, 0x2d, + /*6de0:*/ 0x6f, 0x19, 0x74, 0x41, 0x6f, 0xb9, 0xd4, 0xea, 0x25, 0xe1, 0xc5, 0x62, 0x87, 0xb6, 0x0c, 0x2a, + /*6df0:*/ 0x5b, 0x9b, 0xa4, 0xa2, 0xcf, 0x9c, 0xb7, 0x60, 0x3a, 0x99, 0x1a, 0x37, 0xf9, 0xf9, 0xce, 0x49, + /*6e00:*/ 0x64, 0x2f, 0x3a, 0xc2, 0x35, 0x1b, 0x48, 0x99, 0x64, 0xdb, 0x26, 0xb4, 0x96, 0x74, 0x48, 0x2a, + /*6e10:*/ 0x98, 0x39, 0x51, 0x6b, 0x95, 0xb8, 0xaa, 0x47, 0xaf, 0xba, 0xc9, 0x75, 0x3a, 0x83, 0xf4, 0x6b, + /*6e20:*/ 0xc2, 0xe2, 0x9d, 0x35, 0x04, 0x4a, 0x7c, 0x2c, 0xa4, 0xac, 0xaf, 0xd4, 0xb6, 0x9c, 0x8c, 0xb1, + /*6e30:*/ 0xf7, 0xff, 0xca, 0xab, 0xda, 0x74, 0x70, 0xaf, 0xfc, 0x79, 0x64, 0x0f, 0x24, 0xb6, 0xab, 0x66, + /*6e40:*/ 0x0c, 0x31, 0x15, 0xaa, 0x1e, 0xa8, 0x52, 0xc2, 0x19, 0x93, 0x8c, 0x46, 0xbb, 0x66, 0x66, 0xa0, + /*6e50:*/ 0xfb, 0xc8, 0x1d, 0x39, 0x89, 0xed, 0xcc, 0x6c, 0x16, 0x88, 0x4d, 0xc4, 0x28, 0x98, 0x1b, 0x6d, + /*6e60:*/ 0xa4, 0x42, 0x67, 0x00, 0x06, 0xf8, 0xd5, 0x2b, 0xc2, 0xe3, 0xc7, 0xa7, 0x19, 0x32, 0xcf, 0x79, + /*6e70:*/ 0xce, 0x4b, 0x5f, 0x7f, 0xfe, 0xd6, 0xb1, 0xc8, 0xec, 0xe6, 0x96, 0x8b, 0x6a, 0xf6, 0xa4, 0x2b, + /*6e80:*/ 0xa7, 0x8f, 0xd8, 0xb1, 0x1f, 0xc5, 0xce, 0x24, 0xfe, 0xd0, 0xd7, 0xd7, 0xd9, 0xfb, 0x8e, 0x19, + /*6e90:*/ 0xfd, 0x6f, 0x54, 0x3a, 0x73, 0xbe, 0x0a, 0x5c, 0xd0, 0x1e, 0xf2, 0x85, 0x7c, 0x1e, 0x18, 0xc9, + /*6ea0:*/ 0x4f, 0x86, 0x9b, 0x71, 0x1f, 0x0a, 0x75, 0xc4, 0x5d, 0x68, 0xac, 0x1a, 0xef, 0xce, 0xdf, 0xb0, + /*6eb0:*/ 0x23, 0x4b, 0x79, 0xa1, 0x64, 0x86, 0x07, 0xa2, 0x91, 0x0d, 0x00, 0x36, 0xf1, 0xbe, 0xe7, 0x4a, + /*6ec0:*/ 0x03, 0x13, 0xf2, 0xc0, 0x40, 0x8a, 0x82, 0x49, 0xa8, 0x80, 0x9c, 0xda, 0x0c, 0xe8, 0xf9, 0xb3, + /*6ed0:*/ 0x5c, 0xbb, 0x5c, 0x2b, 0x8b, 0xf7, 0xdd, 0x8f, 0x7a, 0x7a, 0xac, 0x29, 0x65, 0x36, 0xb5, 0xc9, + /*6ee0:*/ 0xac, 0x60, 0x77, 0x12, 0xe3, 0x2e, 0xbf, 0x7c, 0xdd, 0x3a, 0x99, 0xe9, 0x79, 0xed, 0x36, 0x85, + /*6ef0:*/ 0x0b, 0xc5, 0xe7, 0x0d, 0xdb, 0x4d, 0x5e, 0x8c, 0x3a, 0xb5, 0xc2, 0x09, 0x52, 0xf9, 0xf8, 0x90, + /*6f00:*/ 0xbd, 0x35, 0x94, 0x27, 0x21, 0xe1, 0xbf, 0xa7, 0xb6, 0x1d, 0x31, 0x23, 0x55, 0x5c, 0xec, 0x78, + /*6f10:*/ 0xe6, 0x86, 0xd0, 0x3a, 0x32, 0x14, 0x2a, 0x20, 0x20, 0x59, 0x78, 0x24, 0xab, 0x27, 0xb5, 0xa0, + /*6f20:*/ 0x13, 0xfc, 0xf5, 0x5b, 0x1e, 0xad, 0x3a, 0x36, 0x40, 0x18, 0x4a, 0x73, 0x5b, 0xdd, 0x8d, 0xb2, + /*6f30:*/ 0xc3, 0xb9, 0xe4, 0x15, 0xf0, 0xd6, 0xf6, 0xf3, 0x5c, 0x26, 0x00, 0x22, 0xde, 0x9a, 0xa4, 0xe1, + /*6f40:*/ 0x36, 0xa6, 0xd9, 0xe7, 0xc9, 0x9e, 0xd7, 0xb2, 0x64, 0xfb, 0x24, 0xe9, 0xb0, 0xba, 0xa1, 0xa6, + /*6f50:*/ 0xc5, 0xc6, 0x7f, 0xbe, 0x22, 0x28, 0x02, 0x62, 0xb5, 0xf4, 0x38, 0xaa, 0x2d, 0x85, 0x45, 0xac, + /*6f60:*/ 0xe8, 0xcc, 0xfc, 0x2f, 0x75, 0xec, 0x09, 0xd2, 0xf5, 0x63, 0x64, 0xd0, 0x1a, 0xec, 0xfc, 0xfb, + /*6f70:*/ 0x59, 0xea, 0x70, 0x42, 0x09, 0xae, 0xe9, 0xd0, 0x4f, 0xbb, 0x34, 0xa8, 0x9e, 0x76, 0x2b, 0x13, + /*6f80:*/ 0x00, 0xe0, 0xde, 0x26, 0x12, 0x49, 0x6c, 0x1c, 0x52, 0xc1, 0x8d, 0xb9, 0x47, 0xaa, 0xff, 0xb3, + /*6f90:*/ 0x06, 0x54, 0x5e, 0x5f, 0x77, 0x82, 0x93, 0x8f, 0xd0, 0x62, 0xd6, 0xde, 0xd2, 0x00, 0xb2, 0xc2, + /*6fa0:*/ 0x7e, 0x08, 0x34, 0x9b, 0xc5, 0x2e, 0x6d, 0x3d, 0xbf, 0x06, 0xc8, 0xce, 0x3c, 0x96, 0x9b, 0x9c, + /*6fb0:*/ 0xe5, 0x94, 0x0c, 0x56, 0x4e, 0x54, 0xcf, 0xee, 0xff, 0xb3, 0x61, 0x66, 0xf3, 0x4a, 0xe0, 0x6b, + /*6fc0:*/ 0x20, 0xda, 0xe3, 0x5f, 0x04, 0xf7, 0xef, 0xc6, 0x27, 0x85, 0xb0, 0xf8, 0xf0, 0xf5, 0x37, 0x50, + /*6fd0:*/ 0x34, 0x5d, 0xde, 0x5e, 0x20, 0x57, 0x95, 0xe4, 0x30, 0x0d, 0xa9, 0xe8, 0x05, 0xb8, 0x5e, 0xbe, + /*6fe0:*/ 0x2d, 0x74, 0x7b, 0x4b, 0xff, 0x5a, 0x88, 0x31, 0xe5, 0x11, 0xe3, 0x90, 0xef, 0xb3, 0xd1, 0x28, + /*6ff0:*/ 0x92, 0x24, 0x4d, 0x93, 0xd3, 0x9c, 0xbf, 0xfc, 0x9d, 0x1f, 0x80, 0x4c, 0xdb, 0xbc, 0x82, 0x3f, + /*7000:*/ 0x0d, 0xc9, 0xa6, 0xf5, 0x90, 0x95, 0x0c, 0x18, 0x9b, 0x5a, 0x08, 0xe4, 0x6d, 0xed, 0x36, 0x63, + /*7010:*/ 0x78, 0x36, 0x56, 0xfc, 0x40, 0xa9, 0xbb, 0x23, 0xbe, 0x39, 0x16, 0xae, 0xe9, 0x3d, 0x2c, 0xc8, + /*7020:*/ 0x3f, 0x70, 0xfc, 0x9d, 0x6d, 0x3b, 0xc8, 0x75, 0xb5, 0x62, 0x8a, 0x80, 0xea, 0x90, 0x25, 0x1b, + /*7030:*/ 0xc2, 0x6c, 0x24, 0xc8, 0xab, 0x99, 0x6e, 0x32, 0x59, 0x3e, 0x03, 0xd1, 0xab, 0x20, 0xab, 0x64, + /*7040:*/ 0x55, 0xf5, 0x98, 0x31, 0x92, 0xc5, 0xcd, 0x26, 0x97, 0xe0, 0x80, 0xc5, 0xfe, 0x65, 0xd4, 0x21, + /*7050:*/ 0x45, 0x9e, 0xee, 0xad, 0x59, 0xd5, 0x32, 0x61, 0x62, 0x6b, 0x86, 0x53, 0xeb, 0xed, 0x36, 0x4c, + /*7060:*/ 0x59, 0x1e, 0x0f, 0xc7, 0xcf, 0xf4, 0x9b, 0x8c, 0x43, 0x08, 0x2f, 0x9a, 0x5e, 0x2c, 0x1f, 0xdb, + /*7070:*/ 0x5e, 0xd7, 0x0b, 0xe8, 0x4e, 0xe5, 0x76, 0x67, 0x18, 0xdc, 0xd9, 0x6e, 0x64, 0xf4, 0x8f, 0x98, + /*7080:*/ 0x47, 0x2f, 0x8d, 0x85, 0xbe, 0x9c, 0xd7, 0xaf, 0x2e, 0x56, 0x82, 0x9d, 0x71, 0x91, 0xbd, 0x7d, + /*7090:*/ 0xdd, 0x40, 0x85, 0xd9, 0x40, 0x7b, 0x2d, 0x51, 0xd6, 0xf4, 0xc9, 0x49, 0x1d, 0x5f, 0x1a, 0x23, + /*70a0:*/ 0xdc, 0xa7, 0x67, 0x16, 0xe4, 0xde, 0x7b, 0xd9, 0xf0, 0xd6, 0x0d, 0x0f, 0x20, 0x06, 0x22, 0x70, + /*70b0:*/ 0xcb, 0x63, 0x94, 0xab, 0xdb, 0xc8, 0x3c, 0xa6, 0x20, 0x70, 0xf4, 0xf4, 0x01, 0xac, 0x8e, 0xc7, + /*70c0:*/ 0x5a, 0x3c, 0x38, 0x5f, 0x39, 0x06, 0x47, 0x35, 0x5c, 0x98, 0xbf, 0x9c, 0x59, 0xd0, 0x8d, 0x2f, + /*70d0:*/ 0x73, 0x13, 0x06, 0x14, 0x5c, 0x10, 0xc6, 0x17, 0x87, 0xc6, 0x4d, 0x1e, 0x54, 0x67, 0x94, 0x2c, + /*70e0:*/ 0xf2, 0xfc, 0x9f, 0x8a, 0x55, 0x8e, 0xd4, 0x16, 0x76, 0xe2, 0x4f, 0x94, 0x29, 0xc9, 0x27, 0xd4, + /*70f0:*/ 0x84, 0xd1, 0xc3, 0x33, 0xc7, 0xf3, 0x5c, 0x82, 0x11, 0x95, 0x4f, 0xfb, 0x7b, 0xa1, 0x4d, 0xb4, + /*7100:*/ 0x8c, 0x83, 0xec, 0xb6, 0xb2, 0x27, 0xaf, 0xeb, 0x31, 0x07, 0x52, 0x40, 0xd0, 0xc4, 0x75, 0x78, + /*7110:*/ 0xf5, 0xcf, 0x28, 0xce, 0x4d, 0xcb, 0x72, 0x87, 0x97, 0x48, 0x7c, 0xc2, 0x76, 0xc7, 0x43, 0x36, + /*7120:*/ 0xa5, 0x95, 0x0f, 0x90, 0x8b, 0x0a, 0x90, 0xf0, 0xb3, 0x37, 0x59, 0x9d, 0x0a, 0xde, 0x1a, 0x3a, + /*7130:*/ 0x6e, 0xcd, 0xff, 0x66, 0x15, 0xef, 0xcc, 0x5b, 0x83, 0x84, 0x76, 0x9d, 0x07, 0xb3, 0xe4, 0x1c, + /*7140:*/ 0x36, 0xb3, 0x99, 0xf6, 0x62, 0x6c, 0x96, 0x5d, 0x56, 0xa7, 0xd7, 0xf2, 0xe2, 0x39, 0x9e, 0x63, + /*7150:*/ 0x54, 0x2b, 0x45, 0xc4, 0x4e, 0x55, 0x92, 0x80, 0xd7, 0x24, 0x4d, 0x05, 0x3a, 0x86, 0x34, 0x17, + /*7160:*/ 0xb1, 0x09, 0xb4, 0xaf, 0x34, 0x35, 0x69, 0x4f, 0x74, 0x1e, 0x9e, 0x8f, 0x9f, 0x7d, 0x89, 0x7d, + /*7170:*/ 0x7e, 0x5a, 0x0a, 0x38, 0xe1, 0x53, 0x73, 0x9a, 0x80, 0xdc, 0xea, 0x3f, 0x79, 0xf0, 0xd8, 0x48, + /*7180:*/ 0x7f, 0xf7, 0xc8, 0x73, 0x20, 0x3f, 0xbe, 0x71, 0xec, 0xc5, 0x8a, 0x65, 0x17, 0x16, 0xd0, 0xf4, + /*7190:*/ 0x7f, 0x21, 0x33, 0x94, 0xe1, 0xa5, 0x93, 0x32, 0x02, 0x0f, 0x3b, 0x74, 0x97, 0x88, 0x59, 0xcb, + /*71a0:*/ 0x12, 0xc5, 0x80, 0xd8, 0x7a, 0xe5, 0x89, 0x0c, 0x09, 0x62, 0x2b, 0x58, 0x9b, 0xef, 0xb5, 0x21, + /*71b0:*/ 0xed, 0xb2, 0x70, 0x45, 0x9e, 0x17, 0x87, 0x3b, 0x1b, 0xef, 0xb1, 0xee, 0xea, 0x0f, 0x6f, 0x70, + /*71c0:*/ 0x7d, 0x4d, 0xf9, 0x40, 0x11, 0x81, 0x97, 0xe7, 0x08, 0x94, 0x64, 0xd3, 0xe1, 0xbe, 0x76, 0xec, + /*71d0:*/ 0x95, 0x29, 0x5a, 0x83, 0xb3, 0x75, 0xd7, 0x10, 0xb1, 0x55, 0x7f, 0xc5, 0xd2, 0x57, 0xe3, 0xf8, + /*71e0:*/ 0xf0, 0x78, 0xef, 0xd9, 0x9a, 0xa5, 0xa8, 0xf6, 0x3d, 0xc8, 0xf2, 0xce, 0x58, 0xf0, 0x4b, 0x5a, + /*71f0:*/ 0xf3, 0xb7, 0xb3, 0xc8, 0x94, 0xe8, 0x1f, 0xef, 0x4b, 0x1d, 0x03, 0x0b, 0xc2, 0x51, 0xbf, 0x48, + /*7200:*/ 0xa7, 0xcf, 0xbe, 0x93, 0x5d, 0x93, 0x21, 0xfc, 0x33, 0x45, 0x6d, 0x79, 0xee, 0xb1, 0x8a, 0x60, + /*7210:*/ 0x70, 0xce, 0x7c, 0xbc, 0x58, 0x0b, 0x34, 0xb3, 0x8c, 0xd6, 0x8f, 0x94, 0x50, 0xbf, 0x0b, 0x50, + /*7220:*/ 0xc4, 0xf9, 0x9a, 0xd7, 0x95, 0x1e, 0xb0, 0x53, 0xe8, 0xd8, 0x14, 0x9e, 0x13, 0x5b, 0x9c, 0x9f, + /*7230:*/ 0xb4, 0xf5, 0x0d, 0x65, 0xfa, 0xe2, 0xaf, 0x04, 0x94, 0xda, 0x9f, 0x8e, 0x31, 0x0e, 0x66, 0xb6, + /*7240:*/ 0x45, 0x8b, 0xa5, 0xb5, 0xbc, 0x10, 0x30, 0xcf, 0xf7, 0x77, 0x79, 0x87, 0xd4, 0xe4, 0x32, 0xe3, + /*7250:*/ 0xce, 0x97, 0x4d, 0x63, 0xe8, 0xe5, 0x06, 0xf1, 0x3b, 0x30, 0x29, 0x35, 0xab, 0xe4, 0x46, 0x68, + /*7260:*/ 0x77, 0x94, 0xf7, 0x0d, 0x82, 0xf7, 0x61, 0xcb, 0x84, 0x2f, 0x2f, 0xfe, 0x5d, 0xe1, 0x25, 0x93, + /*7270:*/ 0xe2, 0xb3, 0xd2, 0x35, 0xf0, 0x3d, 0x43, 0x20, 0x1d, 0x4e, 0x9f, 0x35, 0x8c, 0x44, 0x95, 0xc5, + /*7280:*/ 0x71, 0x12, 0xd2, 0xc7, 0x8b, 0xf1, 0x30, 0x4a, 0x49, 0x51, 0xe4, 0xe9, 0x03, 0x9b, 0x14, 0x51, + /*7290:*/ 0x90, 0xbd, 0xbb, 0x9c, 0x21, 0xb8, 0xe0, 0x51, 0xe3, 0xca, 0xf4, 0xb4, 0x10, 0xd5, 0xa4, 0x8d, + /*72a0:*/ 0x9d, 0x3f, 0x28, 0x73, 0x7e, 0x5b, 0x6c, 0xe7, 0xca, 0x57, 0x66, 0x8d, 0x5b, 0x34, 0xe9, 0xaa, + /*72b0:*/ 0xb4, 0x2f, 0x56, 0x49, 0x1e, 0xa9, 0x14, 0xed, 0x2b, 0xee, 0x43, 0xa1, 0x3e, 0x10, 0xa4, 0xed, + /*72c0:*/ 0x1a, 0x13, 0xad, 0x78, 0x7a, 0xf2, 0x6e, 0xad, 0xca, 0x30, 0x2a, 0xa1, 0xd8, 0xf8, 0xe1, 0xd1, + /*72d0:*/ 0x91, 0x68, 0x5f, 0x6e, 0xd9, 0x06, 0x91, 0xd2, 0x8b, 0x2a, 0x9e, 0x29, 0x8c, 0xca, 0x5f, 0x46, + /*72e0:*/ 0x77, 0x6c, 0x19, 0xdc, 0x92, 0xf9, 0x8f, 0xc9, 0x68, 0x21, 0xe7, 0x6b, 0x89, 0xf5, 0x83, 0xa8, + /*72f0:*/ 0x6b, 0x9d, 0xe0, 0x1d, 0x77, 0x20, 0x16, 0x66, 0xe6, 0x53, 0xda, 0x32, 0x02, 0x39, 0x09, 0xcf, + /*7300:*/ 0xed, 0x34, 0xec, 0x87, 0xf7, 0xc0, 0x8d, 0xc7, 0xfc, 0x05, 0x7f, 0xc0, 0x6c, 0x78, 0x7c, 0xd9, + /*7310:*/ 0xa3, 0x30, 0xe3, 0xa2, 0x14, 0x0f, 0x42, 0xd6, 0x16, 0x62, 0xcb, 0xb6, 0x4a, 0xf4, 0xab, 0xee, + /*7320:*/ 0x29, 0x7e, 0xf3, 0xc1, 0x8e, 0xb9, 0xdd, 0x61, 0x44, 0x82, 0x2f, 0x1f, 0xc0, 0x28, 0x36, 0xb8, + /*7330:*/ 0x2c, 0xec, 0x2a, 0x4c, 0xe7, 0x50, 0x37, 0x9b, 0x6f, 0xb3, 0xb3, 0xc2, 0x1b, 0xf4, 0x91, 0x88, + /*7340:*/ 0x46, 0xb8, 0x2a, 0xbe, 0xc9, 0x56, 0x4e, 0x74, 0x16, 0xd7, 0x1f, 0x49, 0x3b, 0x50, 0xf2, 0x60, + /*7350:*/ 0xbe, 0x0f, 0x3d, 0x79, 0x4b, 0xae, 0x5d, 0xe5, 0x8b, 0xea, 0xd9, 0xe6, 0xca, 0x84, 0x85, 0x93, + /*7360:*/ 0x84, 0x98, 0x10, 0x0b, 0xa6, 0xfb, 0xb2, 0xa5, 0x3c, 0xc2, 0x79, 0x75, 0x56, 0x69, 0x26, 0x55, + /*7370:*/ 0x61, 0x6e, 0xf3, 0x3d, 0xb3, 0xfa, 0xdc, 0xd1, 0xe4, 0x57, 0x8f, 0x8f, 0x04, 0x61, 0xec, 0x42, + /*7380:*/ 0x6b, 0xe2, 0x89, 0xe2, 0x22, 0xc4, 0xde, 0x2e, 0xae, 0x0f, 0x78, 0x73, 0x0a, 0x7f, 0x33, 0x4a, + /*7390:*/ 0x26, 0x13, 0x11, 0x73, 0x32, 0x7f, 0x30, 0x28, 0x02, 0x40, 0x19, 0xfc, 0xaf, 0xf0, 0x12, 0x0c, + /*73a0:*/ 0x64, 0xcd, 0x83, 0x47, 0x66, 0x7e, 0xa5, 0x45, 0x0c, 0x91, 0xd4, 0x13, 0x45, 0x83, 0xd2, 0xbe, + /*73b0:*/ 0x1e, 0x7b, 0x00, 0x43, 0xd8, 0x12, 0x6c, 0xfe, 0xc4, 0x15, 0x34, 0x6e, 0x17, 0xb0, 0x18, 0x72, + /*73c0:*/ 0xc1, 0x08, 0x8d, 0x8c, 0x25, 0x24, 0x1a, 0xce, 0x06, 0xdb, 0x34, 0x8d, 0xec, 0xcb, 0x95, 0xf0, + /*73d0:*/ 0x09, 0x72, 0xa5, 0x5a, 0x22, 0x99, 0x0a, 0x93, 0x88, 0xea, 0x6e, 0x50, 0x80, 0x35, 0x0a, 0x12, + /*73e0:*/ 0x3f, 0x88, 0x4e, 0xe9, 0x64, 0x70, 0xc9, 0xea, 0x5a, 0xe1, 0x43, 0xe7, 0xb3, 0xd0, 0x32, 0x16, + /*73f0:*/ 0x58, 0xbf, 0x4b, 0xa0, 0x40, 0x26, 0xad, 0x4f, 0x83, 0xbe, 0x44, 0xbd, 0x29, 0xb2, 0x11, 0xd7, + /*7400:*/ 0x7a, 0x23, 0xe5, 0xc5, 0xda, 0xfc, 0xa6, 0xf8, 0xa1, 0x26, 0x99, 0xb3, 0xbb, 0x3d, 0xe6, 0x37, + /*7410:*/ 0x24, 0x36, 0x89, 0xa3, 0x67, 0x9b, 0x16, 0x46, 0xdf, 0x9c, 0x09, 0x07, 0x00, 0xf7, 0x14, 0xac, + /*7420:*/ 0x6c, 0x88, 0x2f, 0xfe, 0x3a, 0x88, 0xf2, 0xbf, 0x88, 0x87, 0x4e, 0xe5, 0x1a, 0xad, 0x70, 0x79, + /*7430:*/ 0x85, 0x2c, 0xa4, 0x2c, 0xf7, 0x8c, 0x2c, 0x9c, 0x16, 0x07, 0x3b, 0x64, 0x62, 0x94, 0x6b, 0xca, + /*7440:*/ 0x30, 0x6f, 0xe6, 0x86, 0x71, 0x82, 0x32, 0xd5, 0x22, 0xb7, 0x69, 0x44, 0x82, 0xab, 0xaa, 0xe1, + /*7450:*/ 0x5e, 0xf3, 0xd6, 0xb3, 0xf9, 0xe0, 0x1a, 0xfa, 0xf5, 0x54, 0x11, 0x7d, 0xf7, 0x38, 0xdb, 0x31, + /*7460:*/ 0x38, 0xfb, 0xf4, 0x3b, 0x47, 0x90, 0x1c, 0x57, 0xbf, 0x66, 0x4e, 0x68, 0xd9, 0x67, 0x03, 0x5a, + /*7470:*/ 0xa8, 0xd9, 0xe9, 0x91, 0xee, 0x66, 0x9c, 0x5f, 0xeb, 0x18, 0x12, 0xaf, 0x90, 0xf7, 0x58, 0x13, + /*7480:*/ 0x41, 0x5e, 0xa9, 0x66, 0xd7, 0x8a, 0xe7, 0x0c, 0xe9, 0x47, 0xa8, 0x96, 0x25, 0x7c, 0x5c, 0x38, + /*7490:*/ 0x46, 0xbc, 0x5a, 0x3d, 0x7f, 0xed, 0x9e, 0xc2, 0xc0, 0xde, 0x93, 0xcb, 0xfc, 0x19, 0x47, 0x5c, + /*74a0:*/ 0x5a, 0xca, 0x38, 0xd1, 0x88, 0xac, 0x7f, 0xf9, 0xad, 0x6f, 0x90, 0x62, 0x80, 0x6a, 0xac, 0x5e, + /*74b0:*/ 0x5c, 0x58, 0xfd, 0xa2, 0x62, 0xf8, 0x05, 0xbb, 0x5d, 0x63, 0x32, 0x74, 0x74, 0xc9, 0x1e, 0x28, + /*74c0:*/ 0xb6, 0x0e, 0x16, 0xa7, 0x4e, 0xc1, 0x51, 0x8e, 0x0d, 0xad, 0x1c, 0x8d, 0x3e, 0x86, 0x2b, 0x99, + /*74d0:*/ 0x77, 0x7c, 0x97, 0x70, 0xe9, 0xdf, 0x15, 0x83, 0xa9, 0x9c, 0x92, 0x7a, 0xf5, 0x54, 0x98, 0x7b, + /*74e0:*/ 0x33, 0xdf, 0xfb, 0xac, 0xde, 0xe8, 0x89, 0xda, 0x49, 0x77, 0x99, 0x22, 0xac, 0x52, 0x21, 0xf6, + /*74f0:*/ 0x7c, 0xf5, 0xa1, 0x67, 0x21, 0xc1, 0x7f, 0x65, 0x96, 0xcb, 0x84, 0x67, 0x1e, 0x87, 0x0f, 0x19, + /*7500:*/ 0x92, 0x53, 0x19, 0xce, 0x4f, 0xc5, 0x26, 0xef, 0x5b, 0xe6, 0xee, 0x9e, 0xe0, 0x4e, 0x26, 0xbc, + /*7510:*/ 0xa7, 0xe7, 0x06, 0x2d, 0x20, 0xd6, 0x5b, 0xe9, 0x57, 0x05, 0x50, 0xc1, 0x53, 0x3d, 0x0c, 0x29, + /*7520:*/ 0xc3, 0xb3, 0xd1, 0xe4, 0x20, 0x0f, 0xe1, 0xad, 0x1d, 0x0d, 0xe8, 0xd9, 0x8f, 0x32, 0xf8, 0x85, + /*7530:*/ 0xf4, 0xac, 0x21, 0x01, 0x5a, 0x64, 0xc8, 0x8c, 0x40, 0x2f, 0xf8, 0x52, 0xc8, 0x4d, 0x41, 0x2e, + /*7540:*/ 0x6d, 0x97, 0x57, 0x37, 0xca, 0xef, 0xba, 0x0a, 0xb2, 0x15, 0x38, 0x4c, 0xa1, 0xe1, 0x94, 0x1e, + /*7550:*/ 0xc2, 0x8e, 0x58, 0xe4, 0x8b, 0x6d, 0x52, 0x1d, 0x15, 0x7b, 0x10, 0x4b, 0x50, 0x32, 0x7b, 0xff, + /*7560:*/ 0x7b, 0xd4, 0xd9, 0xc6, 0x26, 0x21, 0x76, 0xf7, 0x4f, 0x9d, 0x35, 0x56, 0x50, 0x5a, 0x0b, 0x94, + /*7570:*/ 0x8d, 0x60, 0x84, 0x4d, 0xb2, 0xb3, 0x75, 0x9d, 0x34, 0xf6, 0x8f, 0x2d, 0xc9, 0x48, 0xd9, 0x16, + /*7580:*/ 0x20, 0xb4, 0xfa, 0xd4, 0x03, 0x1c, 0x0b, 0x6f, 0x56, 0x4a, 0x7b, 0x5b, 0x00, 0x4d, 0x09, 0x98, + /*7590:*/ 0x73, 0xd2, 0x14, 0xe7, 0xef, 0xc6, 0xba, 0x03, 0xab, 0xf9, 0xc4, 0x49, 0xa1, 0xc2, 0x56, 0xa5, + /*75a0:*/ 0x6b, 0xbc, 0x91, 0x76, 0x80, 0xc8, 0x85, 0x39, 0xd1, 0x05, 0x81, 0x7a, 0x78, 0x91, 0x7c, 0x4e, + /*75b0:*/ 0x15, 0x5a, 0x67, 0x76, 0x08, 0xa5, 0x76, 0xf1, 0x6f, 0xc4, 0x6d, 0x36, 0x40, 0xc1, 0x0a, 0x2b, + /*75c0:*/ 0xa3, 0x03, 0x6a, 0xf3, 0x20, 0xcc, 0x39, 0x24, 0x15, 0x21, 0x0d, 0xff, 0x0d, 0x75, 0x38, 0x93, + /*75d0:*/ 0x5a, 0x5b, 0xb0, 0x95, 0x27, 0x16, 0x4a, 0xd2, 0xf2, 0x44, 0x76, 0x1d, 0x01, 0xef, 0xf2, 0x9e, + /*75e0:*/ 0x92, 0xad, 0xe9, 0x00, 0x96, 0x51, 0x59, 0x9e, 0x03, 0xf8, 0xc4, 0xe8, 0xbb, 0xec, 0xa8, 0xce, + /*75f0:*/ 0x38, 0xb2, 0xc6, 0x7d, 0x8f, 0x08, 0xc8, 0xb1, 0x94, 0x41, 0xa8, 0xa0, 0x33, 0xcd, 0x6e, 0x85, + /*7600:*/ 0x56, 0x54, 0xf8, 0x93, 0xec, 0x92, 0x43, 0xee, 0xed, 0xac, 0xa6, 0x1a, 0xa6, 0xcd, 0x2a, 0xe5, + /*7610:*/ 0x78, 0xf5, 0x2e, 0x44, 0xaf, 0x5b, 0x21, 0x55, 0x12, 0x75, 0xf3, 0xb6, 0x09, 0x9c, 0x1a, 0x79, + /*7620:*/ 0xc3, 0xf4, 0x5c, 0x5f, 0xb9, 0xb9, 0xf1, 0x0b, 0x90, 0xf1, 0xc9, 0x81, 0x2c, 0x1f, 0xea, 0x57, + /*7630:*/ 0xfb, 0xce, 0x80, 0x90, 0xbc, 0x2b, 0x6b, 0x19, 0xaa, 0x6e, 0xef, 0xc3, 0xff, 0x04, 0x5a, 0x46, + /*7640:*/ 0x1a, 0x31, 0x58, 0x59, 0x90, 0x51, 0x5b, 0x6e, 0x8d, 0x0e, 0x03, 0xd9, 0x1f, 0x97, 0xdd, 0xdf, + /*7650:*/ 0x8c, 0xc7, 0xf7, 0x9c, 0x35, 0xfb, 0x11, 0xb1, 0x46, 0x93, 0x50, 0x93, 0xa4, 0xab, 0x2a, 0x9c, + /*7660:*/ 0xc9, 0x05, 0x67, 0x82, 0x4c, 0xa9, 0x5f, 0x12, 0xf0, 0xb4, 0x09, 0xe5, 0x95, 0x16, 0xa4, 0xd2, + /*7670:*/ 0x49, 0x01, 0x37, 0xb8, 0x69, 0xdf, 0x89, 0xbc, 0xe5, 0x9a, 0x0c, 0x6a, 0xfd, 0xae, 0xd9, 0xa0, + /*7680:*/ 0x3c, 0xeb, 0xb6, 0x4c, 0xe9, 0xcb, 0xc2, 0x88, 0xc6, 0x67, 0x8e, 0xa7, 0x69, 0xf5, 0xfc, 0xb6, + /*7690:*/ 0xb7, 0x26, 0xf1, 0x13, 0x9f, 0x30, 0xd2, 0x0f, 0xb0, 0x45, 0x39, 0x32, 0xc7, 0x37, 0xb2, 0xc4, + /*76a0:*/ 0x0c, 0xbd, 0x8b, 0xff, 0x2f, 0x79, 0x0c, 0x2a, 0xbe, 0x7b, 0xf5, 0x8e, 0x23, 0xb9, 0x83, 0xe2, + /*76b0:*/ 0xbe, 0x90, 0xcd, 0xa3, 0x81, 0x81, 0x64, 0x24, 0xf4, 0x09, 0x27, 0x58, 0xf5, 0x9e, 0x96, 0x1a, + /*76c0:*/ 0xd6, 0x75, 0x92, 0x63, 0x18, 0xd8, 0xe6, 0x5e, 0x83, 0x9e, 0x1a, 0xaf, 0xcf, 0x68, 0x72, 0xdc, + /*76d0:*/ 0xc3, 0x7b, 0xcb, 0x32, 0x28, 0x84, 0xfd, 0x6c, 0x39, 0x1d, 0xc9, 0x9c, 0x17, 0x2d, 0x28, 0x75, + /*76e0:*/ 0xba, 0xa4, 0x00, 0xea, 0xe6, 0x04, 0x1e, 0x70, 0x27, 0x67, 0xff, 0x5b, 0xdd, 0xd1, 0x8f, 0xfc, + /*76f0:*/ 0x71, 0x27, 0xd1, 0x53, 0xf3, 0xc6, 0xb3, 0x52, 0x47, 0x43, 0x6a, 0x01, 0x07, 0xf6, 0x0a, 0x21, + /*7700:*/ 0x2a, 0xda, 0x4e, 0x03, 0x41, 0x2f, 0xee, 0x85, 0xae, 0x7f, 0x3b, 0xe6, 0x38, 0xf7, 0x97, 0xde, + /*7710:*/ 0xf5, 0x67, 0x10, 0x52, 0xd5, 0x20, 0x73, 0x1b, 0xd9, 0x6b, 0x5c, 0x9a, 0x00, 0x90, 0xbc, 0xd3, + /*7720:*/ 0x9c, 0x8d, 0x26, 0x87, 0x97, 0x94, 0x8f, 0x6f, 0x05, 0x64, 0x8d, 0x7b, 0x6f, 0x51, 0xf1, 0xf1, + /*7730:*/ 0x43, 0xd2, 0xa3, 0x5e, 0xd5, 0x93, 0x4a, 0xe1, 0x83, 0x84, 0x7c, 0xde, 0xcf, 0x65, 0x1f, 0x6a, + /*7740:*/ 0x45, 0xba, 0x07, 0xa6, 0x8e, 0xe4, 0x01, 0x4d, 0x22, 0xdf, 0x00, 0x22, 0x39, 0x75, 0x3e, 0x0d, + /*7750:*/ 0x8d, 0x3c, 0x68, 0x5b, 0x7c, 0x81, 0xd1, 0xc6, 0x79, 0x2b, 0x54, 0xb7, 0xc1, 0x86, 0x2e, 0x03, + /*7760:*/ 0x44, 0xa6, 0xc0, 0xe0, 0x17, 0x59, 0x3a, 0xed, 0x0b, 0x6b, 0x0c, 0x08, 0x0a, 0xce, 0x9a, 0x31, + /*7770:*/ 0xa5, 0x94, 0x3c, 0x96, 0x29, 0x8f, 0xc7, 0xb0, 0xa3, 0x54, 0x91, 0x0d, 0xd5, 0x5e, 0xb3, 0x73, + /*7780:*/ 0x1a, 0xf6, 0x69, 0xb4, 0xb0, 0x16, 0xc1, 0x28, 0xdc, 0xbd, 0x4e, 0x2f, 0x89, 0x9d, 0xd2, 0xfe, + /*7790:*/ 0x4f, 0xb9, 0x7b, 0x81, 0xcb, 0xf3, 0x67, 0x99, 0x85, 0x44, 0x62, 0xb0, 0x77, 0xd8, 0x3b, 0x2b, + /*77a0:*/ 0xda, 0x8d, 0xcd, 0xa2, 0xf5, 0x00, 0x35, 0x98, 0xc2, 0xb0, 0x1f, 0x8d, 0x24, 0xac, 0x42, 0x1b, + /*77b0:*/ 0x8b, 0xe7, 0xc0, 0x66, 0xa8, 0x91, 0xf0, 0x68, 0x0b, 0x21, 0xe2, 0x0d, 0x71, 0x7f, 0x10, 0x7f, + /*77c0:*/ 0x54, 0x0d, 0x77, 0x01, 0x21, 0x48, 0xde, 0x35, 0x7d, 0x3d, 0x7d, 0xde, 0xc1, 0x3a, 0x18, 0x27, + /*77d0:*/ 0x63, 0xb2, 0x81, 0x34, 0x6f, 0x6f, 0x61, 0x8f, 0xd4, 0xcb, 0x95, 0x14, 0x13, 0xc5, 0x62, 0xf2, + /*77e0:*/ 0x53, 0xed, 0xad, 0x38, 0x92, 0x7d, 0xd5, 0x1b, 0x10, 0x45, 0x42, 0x78, 0xd1, 0x85, 0x2c, 0x42, + /*77f0:*/ 0xcb, 0x72, 0x74, 0x0b, 0x8a, 0x08, 0x39, 0x7b, 0x7b, 0xdb, 0x97, 0x69, 0xcc, 0x22, 0xc7, 0x6e, + /*7800:*/ 0x13, 0x5a, 0x2b, 0x90, 0x4b, 0xd7, 0xb3, 0x54, 0x7b, 0x64, 0xf4, 0x4e, 0x3e, 0xd2, 0xd1, 0xf0, + /*7810:*/ 0xbb, 0xa5, 0xab, 0xd4, 0xd7, 0x5d, 0xb4, 0x4b, 0x43, 0x8b, 0xe4, 0x0b, 0x27, 0xcb, 0x4c, 0xf9, + /*7820:*/ 0xe8, 0x9c, 0x24, 0x68, 0x42, 0x57, 0x9f, 0xa6, 0xc9, 0xc7, 0x53, 0xfc, 0x94, 0x1b, 0x18, 0x97, + /*7830:*/ 0xd5, 0xeb, 0x24, 0xbc, 0xb9, 0xaa, 0xc8, 0xe0, 0x01, 0x30, 0xc5, 0x01, 0x49, 0xc3, 0x61, 0x8a, + /*7840:*/ 0x47, 0x7a, 0x8d, 0x5b, 0x74, 0x0d, 0x48, 0xbf, 0x0c, 0xb3, 0xec, 0xe9, 0xe0, 0x1f, 0x6c, 0x36, + /*7850:*/ 0x67, 0xb7, 0xa1, 0xec, 0x9d, 0x51, 0x00, 0x4e, 0x2f, 0x58, 0xae, 0x7f, 0x61, 0x2e, 0x79, 0x24, + /*7860:*/ 0x50, 0x38, 0xe2, 0x3e, 0xc4, 0x00, 0xbb, 0xf2, 0x25, 0x5b, 0xa8, 0xf6, 0x75, 0x58, 0x30, 0xd9, + /*7870:*/ 0x63, 0x46, 0x4a, 0x62, 0xfc, 0x47, 0x83, 0xb5, 0xb7, 0xb0, 0x21, 0xf1, 0xfb, 0xaa, 0x6b, 0x17, + /*7880:*/ 0xb9, 0xa9, 0xea, 0xd0, 0x98, 0xfc, 0xd5, 0x76, 0x4f, 0x7f, 0x04, 0x69, 0x70, 0x49, 0xcc, 0x34, + /*7890:*/ 0x1f, 0x88, 0x0f, 0x63, 0x29, 0x47, 0x15, 0x56, 0x30, 0xfc, 0x99, 0xa9, 0xb9, 0x1a, 0x42, 0xe3, + /*78a0:*/ 0x0f, 0x28, 0x7a, 0xed, 0xca, 0xad, 0x55, 0x0f, 0xd7, 0xca, 0x5a, 0xae, 0x61, 0x4b, 0x24, 0xd2, + /*78b0:*/ 0x77, 0x68, 0xcc, 0xd2, 0x4f, 0x97, 0xc2, 0xeb, 0x79, 0x5c, 0x0a, 0xfe, 0x90, 0x5a, 0x31, 0xcb, + /*78c0:*/ 0x26, 0xa4, 0x73, 0x1e, 0xea, 0x43, 0xd4, 0x64, 0x6e, 0x0c, 0x07, 0x9d, 0xea, 0x6c, 0x91, 0x3c, + /*78d0:*/ 0x86, 0x72, 0xa6, 0xf2, 0xcd, 0x87, 0xc8, 0xbb, 0xfd, 0xef, 0x05, 0xa1, 0xf7, 0xff, 0x5f, 0x08, + /*78e0:*/ 0xc3, 0xc6, 0x55, 0x92, 0xb6, 0xf3, 0x3a, 0x87, 0x2b, 0x40, 0x3e, 0xe0, 0x37, 0x1f, 0xe2, 0xd4, + /*78f0:*/ 0x1e, 0x67, 0xc3, 0x87, 0xb6, 0x93, 0x76, 0x99, 0x22, 0x79, 0xfd, 0x1d, 0xbc, 0xf8, 0x2c, 0x54, + /*7900:*/ 0x10, 0x03, 0x2f, 0x36, 0xdb, 0x8c, 0x63, 0xba, 0x91, 0xbc, 0xca, 0xe1, 0xd7, 0xc7, 0x8e, 0x32, + /*7910:*/ 0x02, 0xb1, 0x77, 0x4d, 0x1d, 0x70, 0x2b, 0x3a, 0x84, 0xea, 0x1f, 0x78, 0xcc, 0xe8, 0x85, 0x30, + /*7920:*/ 0xbc, 0xe5, 0xb6, 0x15, 0x31, 0x4f, 0x61, 0xb2, 0x18, 0x5e, 0x36, 0xad, 0x70, 0x75, 0xd8, 0xe4, + /*7930:*/ 0x65, 0xdf, 0xac, 0xa1, 0xcc, 0x51, 0x1a, 0x0e, 0x8d, 0x45, 0xc4, 0x46, 0x73, 0x69, 0x2c, 0xc9, + /*7940:*/ 0xb3, 0x96, 0x4e, 0x58, 0x5d, 0x57, 0x68, 0x4e, 0x60, 0x48, 0x16, 0x74, 0x5e, 0xc3, 0xd8, 0x61, + /*7950:*/ 0x22, 0x30, 0x3b, 0x63, 0x96, 0x02, 0x35, 0x2a, 0x15, 0x21, 0x62, 0x92, 0x66, 0x7b, 0xfa, 0x90, + /*7960:*/ 0xfd, 0x63, 0x3c, 0xa7, 0x5a, 0x72, 0xd4, 0x95, 0x63, 0xb8, 0x57, 0x2e, 0x3a, 0x71, 0xa7, 0xd4, + /*7970:*/ 0xff, 0xf9, 0x02, 0xd4, 0xc1, 0xfe, 0xeb, 0x3e, 0x8c, 0xbf, 0xab, 0x16, 0x42, 0x2c, 0x0c, 0x57, + /*7980:*/ 0x12, 0xf0, 0x5a, 0x64, 0xf5, 0x09, 0x1c, 0x46, 0x7c, 0xfb, 0xe0, 0x68, 0x94, 0x97, 0x2c, 0x70, + /*7990:*/ 0x57, 0x13, 0xed, 0xec, 0xdc, 0xd8, 0xab, 0xba, 0x8e, 0x49, 0x87, 0x7c, 0x03, 0x6a, 0x5e, 0xf5, + /*79a0:*/ 0xca, 0x09, 0x96, 0x2c, 0x4b, 0xfb, 0x55, 0xb6, 0x1a, 0x04, 0xf0, 0xb0, 0xbc, 0x71, 0x4f, 0x68, + /*79b0:*/ 0x7c, 0xd4, 0x04, 0xd8, 0x16, 0x6d, 0xae, 0xa9, 0x62, 0xa7, 0xc0, 0xdd, 0x6c, 0xf5, 0x6a, 0x81, + /*79c0:*/ 0x56, 0xb9, 0x09, 0xed, 0x6a, 0xe1, 0x86, 0x44, 0xf7, 0x94, 0xbf, 0xda, 0xcc, 0xf6, 0x9c, 0x7a, + /*79d0:*/ 0xe8, 0x11, 0x1f, 0xdc, 0x7d, 0x22, 0xf2, 0xf1, 0xd2, 0x29, 0x28, 0x02, 0x90, 0x08, 0xb3, 0xdc, + /*79e0:*/ 0x13, 0xe5, 0x57, 0x6b, 0xd1, 0xd5, 0x4c, 0xc6, 0xed, 0xf2, 0x7f, 0x45, 0x38, 0x74, 0xd2, 0xe5, + /*79f0:*/ 0xb3, 0x38, 0x15, 0xc8, 0x55, 0xbe, 0x3c, 0x3d, 0x4e, 0x0c, 0xdd, 0x52, 0x4f, 0xea, 0x31, 0x26, + /*7a00:*/ 0x66, 0x93, 0x37, 0x93, 0x2b, 0x0e, 0x3b, 0x36, 0xd7, 0xd5, 0xc4, 0x9b, 0x3d, 0x0a, 0x25, 0x34, + /*7a10:*/ 0xcd, 0x7f, 0xea, 0x96, 0x9c, 0x34, 0x8f, 0xb8, 0x4a, 0x22, 0x4d, 0x64, 0x33, 0xc8, 0x79, 0x2d, + /*7a20:*/ 0xed, 0xe0, 0x63, 0x19, 0xac, 0xed, 0xf4, 0x95, 0x9e, 0x82, 0x87, 0x6d, 0xdd, 0x13, 0x7f, 0x00, + /*7a30:*/ 0xfe, 0x0a, 0xf8, 0x23, 0x1c, 0x6f, 0x53, 0xa4, 0xcd, 0x64, 0xe2, 0xae, 0xb8, 0x27, 0xff, 0x9f, + /*7a40:*/ 0xe9, 0x1e, 0xd7, 0x3e, 0x62, 0xc2, 0x3b, 0xfb, 0x2c, 0x93, 0x06, 0xcf, 0x21, 0xdb, 0x65, 0x8c, + /*7a50:*/ 0xc5, 0xe0, 0xfa, 0x99, 0x71, 0xf6, 0x55, 0x17, 0x64, 0xc9, 0xd6, 0x79, 0x0f, 0x0d, 0x4b, 0xdc, + /*7a60:*/ 0xcf, 0x24, 0x5d, 0x52, 0xed, 0x41, 0xe8, 0x06, 0x31, 0x87, 0x76, 0xdc, 0x4f, 0x79, 0x8e, 0x10, + /*7a70:*/ 0xa5, 0x5c, 0x37, 0x8c, 0xd4, 0xf7, 0x72, 0x77, 0xd9, 0x69, 0x24, 0x54, 0xdc, 0xf6, 0x35, 0x97, + /*7a80:*/ 0x0d, 0xe4, 0x14, 0xdd, 0xc7, 0x1c, 0x75, 0x5f, 0x2c, 0x33, 0xbe, 0xaa, 0x62, 0xbc, 0x53, 0x04, + /*7a90:*/ 0x18, 0xe0, 0x56, 0x8b, 0xdb, 0xcd, 0xcf, 0x98, 0xb5, 0x1b, 0xb4, 0xa9, 0x84, 0xb3, 0x89, 0xcf, + /*7aa0:*/ 0x5c, 0x57, 0x2d, 0x3d, 0xea, 0x89, 0xd7, 0x14, 0x1e, 0x3b, 0x1e, 0xfb, 0x2e, 0xf6, 0xa7, 0x62, + /*7ab0:*/ 0xd5, 0x21, 0x6f, 0xd2, 0x73, 0xd8, 0x3e, 0xde, 0x1a, 0x65, 0x9f, 0xd0, 0xeb, 0x90, 0x0b, 0x9d, + /*7ac0:*/ 0x21, 0xe5, 0x62, 0x5f, 0x31, 0x8c, 0x8e, 0x55, 0x8b, 0x85, 0x38, 0xa3, 0x16, 0xe8, 0x85, 0x48, + /*7ad0:*/ 0xce, 0xc9, 0xf3, 0x6e, 0x1c, 0x36, 0xd4, 0x38, 0x44, 0x92, 0x9b, 0xf0, 0xc4, 0x6a, 0x44, 0x13, + /*7ae0:*/ 0xfa, 0xde, 0x91, 0x4e, 0x04, 0xeb, 0x70, 0x2d, 0xb4, 0x5f, 0xc5, 0xe0, 0x49, 0x1c, 0x42, 0x4c, + /*7af0:*/ 0xca, 0xa2, 0x70, 0xc3, 0x5f, 0x38, 0x9c, 0x3b, 0xed, 0x96, 0xdf, 0x8d, 0x7f, 0x8c, 0xf9, 0x29, + /*7b00:*/ 0xe6, 0x5d, 0x4e, 0x0e, 0x9d, 0x47, 0x12, 0x37, 0x0c, 0x59, 0xf7, 0x01, 0xa9, 0xab, 0x4a, 0x08, + /*7b10:*/ 0x31, 0x9e, 0x5d, 0x7a, 0xbb, 0xe3, 0x69, 0x03, 0x53, 0xaf, 0xca, 0x96, 0x2e, 0x98, 0x12, 0xfd, + /*7b20:*/ 0x30, 0xab, 0xed, 0x90, 0xa2, 0x08, 0xd5, 0x2d, 0xcc, 0xda, 0xc3, 0x1b, 0xf9, 0x4c, 0x83, 0x71, + /*7b30:*/ 0xb0, 0x40, 0xc9, 0xe6, 0x1f, 0x03, 0x38, 0xc7, 0x6a, 0x85, 0xe1, 0xae, 0x1f, 0xca, 0x12, 0xe4, + /*7b40:*/ 0x6e, 0x9c, 0x1d, 0x6f, 0x6d, 0xa8, 0x2b, 0x9b, 0x46, 0x47, 0x8c, 0xba, 0x32, 0x3d, 0x98, 0x5d, + /*7b50:*/ 0x1e, 0xea, 0x08, 0xa6, 0x6d, 0xd8, 0x8a, 0x1c, 0x1c, 0xeb, 0x61, 0x0d, 0xc2, 0x9a, 0x3f, 0x79, + /*7b60:*/ 0xf4, 0x73, 0x8f, 0x30, 0xb7, 0x73, 0x06, 0x0c, 0xfc, 0x74, 0xf9, 0x60, 0x05, 0x46, 0xe9, 0x10, + /*7b70:*/ 0x1f, 0x8d, 0x01, 0x46, 0xd7, 0xc3, 0x72, 0x19, 0x7f, 0x45, 0x09, 0xe7, 0xe2, 0x9f, 0x7e, 0x57, + /*7b80:*/ 0x65, 0x0a, 0x4b, 0x02, 0x51, 0x20, 0xda, 0x6d, 0x09, 0xbf, 0x10, 0x02, 0xbc, 0xb9, 0x57, 0x5a, + /*7b90:*/ 0x4d, 0x49, 0x51, 0x9d, 0xb5, 0x1d, 0xb1, 0xf0, 0x1d, 0x31, 0xe1, 0xac, 0x27, 0x28, 0x6f, 0xc2, + /*7ba0:*/ 0x2f, 0xd2, 0x2e, 0xb6, 0xe8, 0xa9, 0xaa, 0xfd, 0x48, 0x61, 0x1a, 0xcc, 0x06, 0x33, 0x43, 0x42, + /*7bb0:*/ 0x5b, 0x37, 0x63, 0x31, 0xbc, 0x08, 0x0b, 0xea, 0x64, 0x64, 0xbf, 0x64, 0x48, 0xd6, 0x67, 0x02, + /*7bc0:*/ 0xda, 0xb3, 0xd4, 0x7b, 0xac, 0x59, 0x47, 0xde, 0x5a, 0x69, 0xac, 0xf4, 0xbc, 0x92, 0x5f, 0x23, + /*7bd0:*/ 0x0c, 0xd8, 0x07, 0x48, 0xd4, 0x7a, 0x7e, 0x5b, 0x09, 0xff, 0xc6, 0xc8, 0x6d, 0x64, 0xcb, 0x36, + /*7be0:*/ 0x0f, 0x71, 0xe9, 0x8a, 0xa2, 0xbe, 0xee, 0xaa, 0x21, 0xf5, 0xfe, 0xe6, 0xdc, 0x05, 0x19, 0x26, + /*7bf0:*/ 0x58, 0x85, 0x09, 0x62, 0x18, 0x96, 0x37, 0x0d, 0xde, 0xf5, 0xbf, 0xe6, 0x96, 0x15, 0xea, 0x51, + /*7c00:*/ 0x88, 0x63, 0x2e, 0x1d, 0x08, 0xad, 0xa2, 0x48, 0x0b, 0x93, 0x89, 0xb0, 0xfc, 0x89, 0xa7, 0x64, + /*7c10:*/ 0x85, 0x42, 0x55, 0x64, 0x67, 0x76, 0xb9, 0x88, 0x94, 0xa0, 0x4a, 0x6a, 0xf2, 0x5e, 0x02, 0xa8, + /*7c20:*/ 0x06, 0xd1, 0x43, 0x8b, 0xfa, 0xe7, 0x99, 0x3b, 0xdc, 0x61, 0xbe, 0x3e, 0x9a, 0xd7, 0xea, 0x8f, + /*7c30:*/ 0x67, 0xd4, 0xdd, 0x46, 0x5a, 0x87, 0xed, 0x92, 0x25, 0xe7, 0x0e, 0x27, 0x08, 0x49, 0xfc, 0x5c, + /*7c40:*/ 0x22, 0x35, 0xa8, 0x2f, 0xcd, 0x9a, 0xa2, 0x2a, 0x54, 0xf5, 0xdb, 0x0e, 0x2c, 0x77, 0xf6, 0x5d, + /*7c50:*/ 0xa3, 0x1f, 0xf5, 0xa3, 0x9a, 0xa7, 0x74, 0xce, 0x58, 0xb0, 0xbd, 0x88, 0x8e, 0x4f, 0x97, 0xff, + /*7c60:*/ 0x78, 0x0c, 0x9c, 0x7d, 0x5c, 0x65, 0x6c, 0x24, 0x7c, 0xe3, 0x7f, 0xee, 0x2f, 0x50, 0xf3, 0x1f, + /*7c70:*/ 0x7d, 0x6b, 0xd4, 0xc3, 0xe3, 0x3a, 0x88, 0x81, 0x8d, 0x61, 0x7f, 0xdc, 0xa9, 0x4b, 0xac, 0x0e, + /*7c80:*/ 0x76, 0x1e, 0x4e, 0xd8, 0xf7, 0x5b, 0x2c, 0x03, 0x37, 0xa6, 0x93, 0x78, 0xb0, 0xad, 0x96, 0xff, + /*7c90:*/ 0xf1, 0xaf, 0x9a, 0x1c, 0xa4, 0x9d, 0x04, 0x5a, 0xbd, 0x85, 0x1b, 0xd9, 0xad, 0x92, 0x1a, 0x28, + /*7ca0:*/ 0xe7, 0x7e, 0x08, 0x25, 0x67, 0xb8, 0x0c, 0x83, 0x2f, 0x3d, 0x92, 0xd7, 0xfe, 0xcf, 0x18, 0xee, + /*7cb0:*/ 0xd8, 0xd3, 0x2d, 0xec, 0x6f, 0x56, 0x3c, 0x6a, 0x69, 0x4b, 0x31, 0x8b, 0x7e, 0x9d, 0x18, 0x26, + /*7cc0:*/ 0xdc, 0xdd, 0x89, 0xc2, 0x1d, 0x32, 0x49, 0x27, 0xf7, 0x78, 0x46, 0x8e, 0xbf, 0x47, 0x37, 0x9d, + /*7cd0:*/ 0x45, 0xad, 0x46, 0x63, 0x9e, 0x70, 0xd7, 0xd9, 0xdd, 0x0f, 0x2f, 0xe1, 0x11, 0xe9, 0x93, 0xa2, + /*7ce0:*/ 0x99, 0x6e, 0xc4, 0x98, 0x6a, 0xf3, 0x31, 0x33, 0xe9, 0x54, 0x84, 0x6e, 0xc7, 0xe5, 0x7b, 0x79, + /*7cf0:*/ 0x4f, 0x06, 0x69, 0x36, 0x64, 0x23, 0x7e, 0xc5, 0xdc, 0x95, 0x1c, 0x34, 0x86, 0x93, 0x9e, 0xa9, + /*7d00:*/ 0x5f, 0xab, 0x6c, 0xff, 0xee, 0x8e, 0x80, 0x0b, 0x66, 0x76, 0xc0, 0x12, 0x75, 0x6d, 0x96, 0xb1, + /*7d10:*/ 0xaf, 0xb2, 0xe9, 0x96, 0x34, 0xcc, 0x99, 0x89, 0x59, 0xbc, 0xe0, 0xd5, 0xde, 0x1e, 0x7b, 0x3b, + /*7d20:*/ 0x88, 0xd3, 0xe4, 0x27, 0x06, 0x93, 0x4c, 0xf4, 0x8b, 0xdb, 0xef, 0xd3, 0x23, 0x85, 0x30, 0x37, + /*7d30:*/ 0x47, 0x54, 0x7e, 0x7d, 0xe7, 0x21, 0xeb, 0xc5, 0x55, 0x93, 0x1f, 0xd4, 0xf1, 0x8c, 0x7d, 0xd4, + /*7d40:*/ 0x3b, 0xfe, 0x83, 0x4a, 0xc8, 0x9a, 0xd4, 0x2a, 0x69, 0x52, 0x73, 0x81, 0x77, 0x8f, 0x7c, 0x98, + /*7d50:*/ 0xa0, 0x01, 0x7e, 0x7e, 0x34, 0x91, 0xb1, 0xea, 0x5b, 0x05, 0xa4, 0x0d, 0x41, 0x8c, 0x38, 0x0c, + /*7d60:*/ 0xfe, 0x32, 0x81, 0xee, 0x1a, 0x54, 0xcf, 0x01, 0x8e, 0xb3, 0x6e, 0xa0, 0x41, 0xa1, 0xa5, 0xa3, + /*7d70:*/ 0xc0, 0x18, 0x5e, 0x06, 0x32, 0x04, 0x85, 0x72, 0x60, 0x07, 0xb5, 0x30, 0xce, 0xfc, 0x21, 0xb4, + /*7d80:*/ 0xaa, 0xaa, 0xd9, 0xaf, 0xb1, 0x7e, 0xbd, 0x03, 0x32, 0x56, 0x55, 0x5c, 0xdb, 0xe3, 0x05, 0x06, + /*7d90:*/ 0x6b, 0x39, 0x67, 0x81, 0xcd, 0xd0, 0xc8, 0x5d, 0xb8, 0xae, 0xb6, 0x13, 0x3b, 0x6e, 0x4c, 0x4b, + /*7da0:*/ 0x8f, 0x12, 0x5f, 0x21, 0x61, 0x6c, 0xfc, 0x3f, 0x96, 0x1b, 0x82, 0x57, 0xf9, 0xbe, 0x5a, 0x91, + /*7db0:*/ 0x19, 0xac, 0xdd, 0x54, 0x2a, 0xd6, 0x8b, 0xa6, 0x0b, 0xb8, 0x7e, 0xeb, 0xaa, 0x86, 0x3a, 0x44, + /*7dc0:*/ 0x96, 0x7a, 0xec, 0x6a, 0x3e, 0xa0, 0x94, 0x3e, 0xb3, 0xe0, 0xc1, 0xf9, 0xd4, 0xff, 0xa4, 0x10, + /*7dd0:*/ 0x79, 0x8e, 0x83, 0x65, 0x2e, 0xd9, 0x90, 0xec, 0x00, 0xca, 0x2a, 0x86, 0xb8, 0x85, 0xf1, 0xa1, + /*7de0:*/ 0xdc, 0xfe, 0x54, 0x11, 0x67, 0xcf, 0x6d, 0x42, 0x6c, 0x2d, 0xf7, 0x8e, 0x9c, 0x5e, 0x0f, 0x62, + /*7df0:*/ 0x49, 0xf8, 0xb2, 0x4c, 0xc8, 0x7a, 0x47, 0x40, 0x59, 0xba, 0xa3, 0x8b, 0xad, 0x61, 0x8e, 0xd6, + /*7e00:*/ 0xbf, 0xd1, 0xf4, 0x3e, 0xb9, 0x80, 0x47, 0xd5, 0x94, 0xa9, 0xb9, 0xc1, 0x4d, 0xf4, 0x35, 0xa6, + /*7e10:*/ 0xa4, 0x13, 0x90, 0xcb, 0x7f, 0x9d, 0x08, 0xb7, 0x5a, 0x5e, 0x1f, 0x5a, 0x5c, 0x19, 0xc2, 0xce, + /*7e20:*/ 0xa2, 0xe4, 0xc1, 0x2c, 0xdb, 0xb9, 0x84, 0xb4, 0x7a, 0xa4, 0x0c, 0xaf, 0xf0, 0xdc, 0x7e, 0xe4, + /*7e30:*/ 0x27, 0x94, 0x69, 0x07, 0x6d, 0xc2, 0xaa, 0xc4, 0x95, 0x80, 0xb5, 0x94, 0xf8, 0x57, 0x0e, 0x97, + /*7e40:*/ 0x4d, 0x9a, 0x3e, 0x5c, 0x63, 0x44, 0x1b, 0x61, 0x22, 0xd8, 0x47, 0x4c, 0x35, 0x39, 0xa0, 0xfd, + /*7e50:*/ 0x52, 0x3c, 0x3f, 0x2f, 0x2d, 0x15, 0x19, 0x7b, 0xd9, 0x17, 0xa7, 0x90, 0x0f, 0xbe, 0x21, 0xf6, + /*7e60:*/ 0x7b, 0x58, 0x8f, 0x48, 0x77, 0x0e, 0xac, 0x66, 0xa3, 0x2f, 0x80, 0xee, 0xe6, 0x23, 0x72, 0x03, + /*7e70:*/ 0x8e, 0x56, 0x54, 0x13, 0x1e, 0x06, 0xbc, 0x5d, 0xdf, 0x78, 0xf5, 0x1f, 0x1e, 0x2f, 0xd6, 0x68, + /*7e80:*/ 0x50, 0x1d, 0xaf, 0x61, 0x5d, 0x4b, 0x38, 0x31, 0x2c, 0xef, 0x54, 0x3c, 0x5f, 0xfc, 0xb5, 0x5e, + /*7e90:*/ 0xd9, 0x96, 0x08, 0x31, 0x25, 0x20, 0x42, 0xfb, 0x19, 0xba, 0xc8, 0xf2, 0x0f, 0xe3, 0xfd, 0x5b, + /*7ea0:*/ 0xae, 0x65, 0xba, 0x26, 0xfa, 0x7a, 0xfd, 0x79, 0xfd, 0xda, 0x2b, 0xab, 0xb2, 0x0b, 0x40, 0x55, + /*7eb0:*/ 0x87, 0x81, 0x6d, 0xc1, 0x02, 0xa4, 0xbc, 0x94, 0x89, 0x81, 0x42, 0xe7, 0x40, 0xf0, 0xd0, 0xfe, + /*7ec0:*/ 0x54, 0x56, 0xf8, 0xfa, 0x0c, 0x53, 0xce, 0xac, 0x04, 0xe3, 0xfb, 0xc6, 0x2f, 0x87, 0x6b, 0xde, + /*7ed0:*/ 0x74, 0x0f, 0x7a, 0x5b, 0xb8, 0xf2, 0x0a, 0x66, 0xf0, 0xb2, 0x1e, 0xd8, 0x2f, 0x37, 0xe0, 0xc1, + /*7ee0:*/ 0x45, 0x62, 0x6b, 0x0b, 0xab, 0xe8, 0x1f, 0x31, 0x7a, 0x28, 0xca, 0x54, 0x6f, 0x36, 0x10, 0xd6, + /*7ef0:*/ 0x43, 0xc1, 0xe1, 0x0a, 0x2e, 0xb6, 0xce, 0xaf, 0x45, 0xdc, 0x18, 0x9e, 0xcf, 0x5a, 0xdd, 0xea, + /*7f00:*/ 0x2e, 0xd7, 0xe5, 0x55, 0x49, 0x3e, 0x08, 0x15, 0xf7, 0xe3, 0xf7, 0x78, 0x8e, 0x41, 0xd1, 0xf8, + /*7f10:*/ 0xf4, 0x7a, 0x59, 0x93, 0xc8, 0xdf, 0xdb, 0xe1, 0x88, 0x66, 0x21, 0x84, 0xb7, 0x4d, 0xd6, 0x4a, + /*7f20:*/ 0x61, 0x2c, 0x5b, 0x8b, 0xf4, 0xc3, 0x64, 0xcc, 0x73, 0x69, 0xca, 0x0b, 0x55, 0x38, 0xbd, 0x2a, + /*7f30:*/ 0x6d, 0x1f, 0xad, 0xe4, 0xfe, 0x3a, 0xbf, 0x4a, 0xff, 0x18, 0x5f, 0x9c, 0x5d, 0xa7, 0x2f, 0xbc, + /*7f40:*/ 0x71, 0x8a, 0xe0, 0x82, 0x4a, 0xd8, 0x92, 0xdb, 0xb6, 0x80, 0x29, 0xa4, 0xed, 0x65, 0x3f, 0x72, + /*7f50:*/ 0xc4, 0xbc, 0x05, 0x4f, 0x3a, 0x97, 0x5d, 0x3c, 0x24, 0x50, 0xa4, 0x5b, 0x4e, 0x75, 0xab, 0x20, + /*7f60:*/ 0x96, 0x42, 0xa3, 0x5b, 0x36, 0x74, 0x79, 0xb0, 0xd2, 0xce, 0x49, 0x23, 0xa2, 0x22, 0xd7, 0x21, + /*7f70:*/ 0x66, 0xbe, 0xc4, 0xa9, 0x0c, 0x9d, 0xb3, 0xfc, 0x18, 0x81, 0x48, 0x7e, 0x1b, 0xfa, 0xdf, 0xb8, + /*7f80:*/ 0xba, 0xae, 0x15, 0x16, 0xdf, 0xee, 0x6c, 0x53, 0xf9, 0x6a, 0x80, 0xbb, 0xe0, 0x5e, 0x98, 0x2d, + /*7f90:*/ 0x18, 0xf1, 0x45, 0x99, 0x2d, 0xb8, 0xc6, 0xff, 0x74, 0xf4, 0xaa, 0x0b, 0x94, 0x42, 0x09, 0xb8, + /*7fa0:*/ 0x26, 0x5f, 0x7c, 0x15, 0x17, 0xe0, 0x90, 0x04, 0x96, 0x1e, 0x8d, 0xa9, 0xc3, 0x59, 0xcb, 0x5a, + /*7fb0:*/ 0xc2, 0x22, 0x78, 0x9c, 0xbe, 0xb1, 0xc8, 0x5b, 0x84, 0xda, 0x24, 0x3f, 0x3b, 0xc9, 0x9b, 0x7a, + /*7fc0:*/ 0xbb, 0xfd, 0xe7, 0x4b, 0x23, 0x43, 0xd1, 0x04, 0x98, 0x14, 0x5e, 0x23, 0xdb, 0xb9, 0x18, 0x3c, + /*7fd0:*/ 0x4f, 0xdb, 0xe1, 0x14, 0x1e, 0x30, 0x19, 0xd6, 0xb6, 0x70, 0xd4, 0xe1, 0xe1, 0x40, 0xad, 0xff, + /*7fe0:*/ 0xe9, 0xcc, 0xd5, 0xfa, 0xc1, 0x2b, 0x66, 0x07, 0xde, 0x05, 0x6d, 0xe7, 0x97, 0x75, 0xb9, 0x3f, + /*7ff0:*/ 0x5f, 0xd2, 0xdf, 0xd2, 0xd1, 0x27, 0xfe, 0x29, 0xb7, 0xc5, 0xfa, 0x41, 0xfd, 0x39, 0x39, 0x45, + /*8000:*/ 0xc6, 0x96, 0xa2, 0xd5, 0x25, 0xab, 0x00, 0xe4, 0x4c, 0xc8, 0x48, 0xe5, 0x89, 0xa5, 0x0b, 0x13, + /*8010:*/ 0x82, 0xb5, 0x53, 0xd6, 0x4c, 0x47, 0x7d, 0x28, 0x39, 0xe5, 0xad, 0x94, 0xc4, 0x6d, 0x21, 0x1e, + /*8020:*/ 0xb0, 0x73, 0xd9, 0xcc, 0xa6, 0x2f, 0x0b, 0xf0, 0x9c, 0xd7, 0x5c, 0x5f, 0x99, 0xf6, 0x09, 0x6e, + /*8030:*/ 0x64, 0xb1, 0xce, 0xcc, 0xee, 0x55, 0xd9, 0xeb, 0x51, 0x5f, 0x03, 0x03, 0x6f, 0xc2, 0xea, 0x70, + /*8040:*/ 0xc3, 0x4c, 0xd1, 0x9e, 0x26, 0x06, 0x0f, 0x80, 0x2d, 0xf0, 0x43, 0x75, 0x09, 0x8c, 0x52, 0x6a, + /*8050:*/ 0xbb, 0x76, 0xda, 0x09, 0x2f, 0x00, 0x45, 0xad, 0x9a, 0x24, 0x12, 0x4c, 0x29, 0x58, 0x67, 0x4f, + /*8060:*/ 0xd8, 0xdd, 0xe9, 0x62, 0xd4, 0x95, 0x0d, 0x83, 0x62, 0xfe, 0x66, 0xad, 0x12, 0x06, 0xe1, 0x16, + /*8070:*/ 0xb8, 0x89, 0xb4, 0x9f, 0xa6, 0xb6, 0x4f, 0xa7, 0xfe, 0x72, 0xd5, 0xbc, 0x7c, 0x84, 0x62, 0xe2, + /*8080:*/ 0xb1, 0xfb, 0x0c, 0x54, 0xed, 0x69, 0x96, 0x68, 0x5c, 0x1b, 0xcf, 0xa3, 0x56, 0xdd, 0x0b, 0x78, + /*8090:*/ 0x9c, 0x5d, 0x7d, 0x9d, 0x05, 0x79, 0x72, 0xb9, 0xa9, 0x6e, 0xd1, 0xfb, 0x0c, 0x28, 0x2b, 0xa9, + /*80a0:*/ 0xf4, 0xb3, 0x41, 0xb1, 0x12, 0xe0, 0xe3, 0xf4, 0xf0, 0x6c, 0x86, 0x50, 0xf0, 0xaf, 0x23, 0x87, + /*80b0:*/ 0x67, 0x91, 0xe2, 0x07, 0x6c, 0x77, 0x16, 0xf9, 0x5f, 0x83, 0x8a, 0x46, 0xb6, 0xe3, 0x02, 0x59, + /*80c0:*/ 0x77, 0xaf, 0x3e, 0x98, 0x33, 0x3f, 0xb6, 0xf4, 0x02, 0x23, 0x50, 0xd8, 0x4b, 0xc9, 0x4e, 0xd9, + /*80d0:*/ 0x00, 0xe9, 0x68, 0x13, 0x44, 0xed, 0x2c, 0x4d, 0xd7, 0x60, 0xb4, 0x69, 0xc6, 0xd4, 0xe7, 0xc6, + /*80e0:*/ 0x57, 0xe4, 0xb0, 0x5d, 0x74, 0x51, 0xb5, 0x09, 0x54, 0x11, 0x58, 0x1b, 0xab, 0xf6, 0x54, 0xfb, + /*80f0:*/ 0xe4, 0xaa, 0x99, 0xb0, 0xc2, 0xa8, 0xc3, 0x2d, 0x52, 0x95, 0x39, 0x51, 0x4b, 0x18, 0x83, 0xe6, + /*8100:*/ 0xfc, 0x55, 0xd5, 0x0a, 0xae, 0x93, 0x70, 0x97, 0x60, 0x65, 0x63, 0x61, 0x72, 0x65, 0x9a, 0xe8, + /*8110:*/ 0x13, 0x86, 0x99, 0x14, 0x75, 0xca, 0xe2, 0x9b, 0x40, 0xaf, 0x63, 0x49, 0x50, 0xfc, 0x1d, 0x9b, + /*8120:*/ 0x2a, 0x26, 0xee, 0xbc, 0x88, 0x78, 0x1d, 0xd8, 0xd6, 0x51, 0x8b, 0x8f, 0x45, 0xf9, 0xe0, 0x4b, + /*8130:*/ 0x70, 0xb4, 0x6b, 0x84, 0x42, 0xe5, 0x7b, 0x26, 0xf0, 0xb4, 0xff, 0x15, 0x70, 0x23, 0xc7, 0xd6, + /*8140:*/ 0xd7, 0xa0, 0x22, 0x84, 0x8f, 0x3d, 0xd6, 0x25, 0x26, 0x22, 0x3e, 0xcf, 0x81, 0x67, 0x1e, 0xdc, + /*8150:*/ 0x23, 0xc7, 0x2a, 0xe7, 0x2e, 0x68, 0x65, 0x06, 0x2f, 0xe0, 0x57, 0xe0, 0x89, 0x27, 0x5f, 0xc6, + /*8160:*/ 0x81, 0x85, 0x04, 0xb0, 0xa3, 0xc9, 0xde, 0xe3, 0x4f, 0x68, 0x4d, 0xc7, 0xa2, 0xc9, 0xc2, 0x6c, + /*8170:*/ 0x42, 0x37, 0x7d, 0x94, 0xe4, 0x61, 0x26, 0x39, 0x26, 0xc7, 0x30, 0xd9, 0xfc, 0x5a, 0x82, 0x44, + /*8180:*/ 0xee, 0x2c, 0x82, 0x2f, 0xa3, 0x66, 0xfc, 0x7a, 0x6b, 0xde, 0x3a, 0xf8, 0xad, 0xc4, 0xcc, 0xdf, + /*8190:*/ 0x4f, 0x38, 0xf0, 0x1e, 0xd8, 0x0d, 0x7d, 0x98, 0x6b, 0x74, 0xa5, 0xd7, 0x10, 0xce, 0xa0, 0x53, + /*81a0:*/ 0x72, 0x51, 0xf1, 0x5a, 0xa0, 0x01, 0x2c, 0x33, 0xe5, 0xfe, 0x25, 0xeb, 0x6c, 0xe3, 0x79, 0x02, + /*81b0:*/ 0x87, 0x5a, 0x56, 0xe9, 0xb6, 0xd0, 0xd1, 0x41, 0xe4, 0x2f, 0x53, 0xed, 0xbd, 0x22, 0x14, 0xe0, + /*81c0:*/ 0x2d, 0x48, 0x8c, 0xb9, 0x67, 0xd8, 0x7b, 0x27, 0x58, 0x7a, 0x7c, 0xc8, 0xd6, 0x48, 0xec, 0xd9, + /*81d0:*/ 0xba, 0xcf, 0xd1, 0xc4, 0xbd, 0x7f, 0x38, 0xb7, 0xdf, 0x4a, 0xff, 0x99, 0xd8, 0xf4, 0xaa, 0xbf, + /*81e0:*/ 0x68, 0x9a, 0xcb, 0x63, 0xcd, 0x01, 0x05, 0x53, 0xfd, 0xae, 0xcd, 0xd7, 0xfe, 0xa7, 0x79, 0x42, + /*81f0:*/ 0x85, 0x63, 0x40, 0x44, 0x65, 0x1b, 0x83, 0x70, 0x16, 0x1f, 0xc0, 0xf1, 0xb2, 0x49, 0x0f, 0x99, + /*8200:*/ 0x40, 0xbe, 0x21, 0xfa, 0x8e, 0x85, 0xb7, 0x9d, 0xee, 0x28, 0xbc, 0xac, 0x2b, 0x85, 0x3b, 0xdf, + /*8210:*/ 0x4a, 0x72, 0x81, 0x6d, 0x0e, 0x75, 0x58, 0x34, 0x41, 0x5b, 0xa3, 0x0f, 0x00, 0x1b, 0x28, 0xcf, + /*8220:*/ 0xa7, 0x57, 0x4e, 0x78, 0x41, 0x7c, 0xf9, 0x4e, 0x44, 0xcb, 0x6f, 0x4b, 0x88, 0x84, 0x73, 0x4f, + /*8230:*/ 0xfa, 0x4a, 0xc4, 0xa9, 0xad, 0xd7, 0xeb, 0x1d, 0x52, 0xe4, 0xd7, 0xa3, 0xdc, 0x37, 0xae, 0x23, + /*8240:*/ 0xe3, 0xa6, 0x91, 0x02, 0x75, 0xf0, 0x16, 0xbb, 0x24, 0x09, 0x15, 0xa3, 0x79, 0xe2, 0xd9, 0x66, + /*8250:*/ 0x25, 0x27, 0xe8, 0x5e, 0x72, 0x7d, 0xc6, 0x38, 0xac, 0xfb, 0x62, 0x3b, 0x7d, 0x23, 0xe6, 0xbf, + /*8260:*/ 0x94, 0x12, 0x15, 0xcb, 0xd7, 0x73, 0xd7, 0xc9, 0x02, 0xff, 0xa5, 0xae, 0x15, 0x45, 0xc7, 0xfd, + /*8270:*/ 0x82, 0x77, 0x54, 0xd3, 0xc0, 0xcb, 0xc6, 0x1c, 0x8d, 0x58, 0x51, 0xd2, 0x82, 0x66, 0x03, 0x84, + /*8280:*/ 0x5a, 0x16, 0xad, 0x90, 0x0b, 0x29, 0x98, 0x6c, 0xa1, 0x53, 0xc3, 0x8e, 0x9e, 0x30, 0x61, 0x6f, + /*8290:*/ 0xc0, 0xc1, 0x8e, 0x61, 0x67, 0x82, 0x32, 0xb8, 0xa7, 0x4c, 0xa6, 0x78, 0x28, 0x72, 0xed, 0xc9, + /*82a0:*/ 0x17, 0x6d, 0xf4, 0xe1, 0x83, 0x9c, 0xa3, 0xc8, 0x57, 0x47, 0xf6, 0x0f, 0xa5, 0x43, 0x36, 0x78, + /*82b0:*/ 0x53, 0xd2, 0xf7, 0x75, 0xc2, 0x93, 0xb5, 0x4b, 0x5a, 0xbf, 0xa0, 0xfe, 0x09, 0xb3, 0xa4, 0x69, + /*82c0:*/ 0x3e, 0xee, 0x5e, 0xb1, 0xe6, 0x2b, 0xca, 0x21, 0x62, 0xed, 0xf5, 0x3a, 0xa6, 0x3c, 0x41, 0x44, + /*82d0:*/ 0x75, 0x03, 0xc8, 0x1e, 0x7f, 0x82, 0x5c, 0x9f, 0x77, 0x72, 0x73, 0xcf, 0xf4, 0x9e, 0x20, 0x63, + /*82e0:*/ 0x60, 0xe1, 0x4b, 0x42, 0xb4, 0xa1, 0xdf, 0xda, 0xdc, 0x2e, 0xda, 0x4f, 0xba, 0xf2, 0x2a, 0x44, + /*82f0:*/ 0x7a, 0x82, 0x40, 0xb9, 0x5d, 0xa2, 0x61, 0x1e, 0xea, 0xff, 0x9a, 0xd7, 0x85, 0x8b, 0x2a, 0x88, + /*8300:*/ 0x6a, 0xbc, 0xdb, 0x16, 0x1b, 0x43, 0x02, 0xbd, 0x36, 0xa1, 0x9e, 0x86, 0x45, 0x15, 0x4b, 0x07, + /*8310:*/ 0x05, 0xe0, 0x64, 0x85, 0xda, 0xc3, 0x61, 0xdd, 0xc6, 0xf7, 0xf1, 0x6b, 0xe0, 0xf0, 0x0b, 0xcd, + /*8320:*/ 0x6d, 0x6e, 0x33, 0x05, 0xdf, 0x4e, 0x18, 0x79, 0xfc, 0x85, 0x30, 0xf1, 0x04, 0xa8, 0x7a, 0x9a, + /*8330:*/ 0xbe, 0x72, 0x8f, 0x92, 0x30, 0xd8, 0x04, 0x19, 0xbc, 0x26, 0xc5, 0xe6, 0x71, 0xd3, 0x4d, 0xfc, + /*8340:*/ 0xe8, 0x44, 0xca, 0x60, 0xb6, 0x0a, 0x2f, 0x8a, 0x36, 0x83, 0x54, 0x6f, 0x68, 0xcd, 0xa6, 0x60, + /*8350:*/ 0x64, 0xdc, 0xcd, 0xde, 0xeb, 0x92, 0x47, 0x61, 0xce, 0xc7, 0xa9, 0x99, 0xd9, 0xad, 0x4e, 0x4d, + /*8360:*/ 0x11, 0xb5, 0x10, 0x46, 0x31, 0x91, 0x66, 0x42, 0xad, 0xe1, 0xb9, 0x79, 0x93, 0x62, 0xde, 0x40, + /*8370:*/ 0xd5, 0x1b, 0x74, 0x70, 0x73, 0xb1, 0xa7, 0xa3, 0x85, 0xcd, 0x55, 0x62, 0x8b, 0x2c, 0xf9, 0xcf, + /*8380:*/ 0xa5, 0x7f, 0x02, 0x3f, 0x58, 0x04, 0x7c, 0x02, 0x6f, 0x4d, 0xd4, 0x67, 0x95, 0x94, 0xf5, 0x42, + /*8390:*/ 0x57, 0xf9, 0xa1, 0x65, 0xc6, 0x2e, 0xb6, 0x7d, 0x1b, 0x93, 0x5b, 0xa3, 0x2d, 0x32, 0x77, 0x6b, + /*83a0:*/ 0xb0, 0xcd, 0xd6, 0x9b, 0xd6, 0x11, 0x7b, 0x5b, 0xc5, 0x10, 0x86, 0xc9, 0x74, 0x35, 0xfa, 0x67, + /*83b0:*/ 0xbc, 0xea, 0x5d, 0x46, 0x5c, 0xf6, 0x4f, 0xb7, 0x86, 0x58, 0xda, 0x5c, 0x38, 0xf5, 0x68, 0xb8, + /*83c0:*/ 0xcf, 0xbb, 0x7e, 0x76, 0x0d, 0xdd, 0x1b, 0x28, 0xcd, 0x4f, 0xb3, 0x99, 0x8c, 0x11, 0xef, 0x6e, + /*83d0:*/ 0x1b, 0xf0, 0x81, 0xb4, 0x6b, 0xb9, 0x34, 0xa4, 0x93, 0x5d, 0xf1, 0xca, 0xef, 0x45, 0x60, 0xc2, + /*83e0:*/ 0x35, 0xdf, 0x01, 0xcf, 0x2b, 0x3a, 0xb6, 0x1f, 0xd1, 0x8d, 0x3d, 0xe7, 0x12, 0x60, 0xed, 0xc4, + /*83f0:*/ 0x0b, 0x36, 0x84, 0xe3, 0x6b, 0x75, 0x09, 0x2a, 0x95, 0xad, 0xa5, 0x37, 0x4f, 0x75, 0xc5, 0x13, + /*8400:*/ 0x61, 0x74, 0x17, 0x83, 0x86, 0x94, 0x94, 0xfe, 0x0e, 0x7d, 0xc1, 0x54, 0x6b, 0x13, 0x3b, 0xd9, + /*8410:*/ 0x7c, 0xf7, 0x90, 0x56, 0x7d, 0x30, 0x42, 0xd0, 0x82, 0x42, 0xc3, 0x3a, 0x52, 0xdf, 0x70, 0x24, + /*8420:*/ 0xb3, 0xcb, 0x25, 0x15, 0x2d, 0x4e, 0xa9, 0xd4, 0x56, 0x33, 0xb9, 0x79, 0xca, 0xbd, 0xcc, 0x56, + /*8430:*/ 0x9f, 0x13, 0xc0, 0x44, 0xe4, 0x71, 0xdf, 0x2d, 0xf2, 0x55, 0x49, 0xae, 0x0f, 0x10, 0x4d, 0x03, + /*8440:*/ 0x08, 0x59, 0x6d, 0xf9, 0xb1, 0xd8, 0x14, 0x88, 0xdd, 0x0e, 0x0f, 0xa9, 0xbc, 0x5d, 0x74, 0xff, + /*8450:*/ 0x9b, 0xf8, 0x8c, 0xbb, 0xdf, 0xb4, 0x60, 0x64, 0x2f, 0x7b, 0x5e, 0x83, 0x52, 0xf5, 0x7a, 0xf7, + /*8460:*/ 0x33, 0x50, 0x08, 0x07, 0xb0, 0x2e, 0x7e, 0x88, 0xa8, 0x4b, 0xd2, 0xe5, 0xbc, 0x9c, 0xf2, 0x1b, + /*8470:*/ 0x64, 0xe9, 0x1c, 0x65, 0xb4, 0xec, 0x97, 0x0d, 0xd3, 0xa0, 0x8e, 0x02, 0xe9, 0x2b, 0xb1, 0x05, + /*8480:*/ 0x74, 0xe9, 0x8c, 0x18, 0x27, 0xcd, 0x6c, 0x59, 0x5d, 0xfd, 0xf3, 0x56, 0x5e, 0x56, 0xd7, 0xf0, + /*8490:*/ 0xa4, 0x0a, 0xc0, 0x16, 0x81, 0x07, 0x41, 0xc7, 0xf0, 0xe1, 0x08, 0x1a, 0xf8, 0xa8, 0x0f, 0xa7, + /*84a0:*/ 0x23, 0x95, 0xaa, 0x49, 0x3c, 0x5e, 0xb2, 0x7f, 0x69, 0xf3, 0x3d, 0xdd, 0xb4, 0x56, 0x96, 0xdb, + /*84b0:*/ 0xea, 0xf2, 0x34, 0xa8, 0xd0, 0xb7, 0x72, 0x98, 0x47, 0x15, 0x93, 0xf6, 0x57, 0x9c, 0xb1, 0x26, + /*84c0:*/ 0xf1, 0x00, 0xdf, 0xe8, 0xfb, 0x81, 0x15, 0x0f, 0x8d, 0x33, 0x9e, 0x79, 0x0e, 0x41, 0xf4, 0x16, + /*84d0:*/ 0x31, 0xdd, 0xfd, 0xec, 0x7d, 0x4b, 0x7e, 0x3b, 0xd7, 0x71, 0xf1, 0x1c, 0xb2, 0x53, 0x2b, 0x6f, + /*84e0:*/ 0xc5, 0x58, 0xf1, 0x50, 0xfe, 0xc3, 0x29, 0x82, 0xd2, 0xf4, 0x7c, 0xd7, 0x42, 0x8a, 0x7a, 0x83, + /*84f0:*/ 0x79, 0x42, 0x62, 0xde, 0x92, 0x64, 0x58, 0x6e, 0x9b, 0x24, 0x8d, 0x16, 0xb8, 0xf9, 0x83, 0xf9, + /*8500:*/ 0x8a, 0x35, 0x67, 0xf7, 0x07, 0xd5, 0x43, 0xd0, 0xc6, 0x71, 0x35, 0xfb, 0xb5, 0x9f, 0x0d, 0x84, + /*8510:*/ 0x9e, 0xa9, 0x69, 0x3b, 0x4e, 0x3c, 0xa3, 0x72, 0xd7, 0x48, 0xaf, 0xae, 0xba, 0xae, 0x4a, 0xf7, + /*8520:*/ 0x06, 0xce, 0xf6, 0xc8, 0x41, 0x0a, 0x7e, 0xfb, 0x76, 0xc6, 0xb0, 0xcc, 0xa9, 0xd9, 0xd3, 0xb6, + /*8530:*/ 0xfe, 0xc5, 0x62, 0x99, 0x28, 0x03, 0xdb, 0xa8, 0x10, 0xe9, 0xd2, 0x3b, 0x1b, 0xe2, 0xf5, 0x1b, + /*8540:*/ 0x81, 0xea, 0xfd, 0xd2, 0x9f, 0x34, 0xc8, 0xca, 0x58, 0x6d, 0x74, 0xbf, 0x2b, 0x53, 0x17, 0xf2, + /*8550:*/ 0x64, 0x15, 0xc0, 0x31, 0x77, 0x7a, 0x00, 0xcd, 0x28, 0x72, 0x56, 0x82, 0x81, 0xb8, 0xd8, 0x56, + /*8560:*/ 0x0f, 0xe1, 0xa3, 0xc2, 0xf8, 0x78, 0x01, 0x9f, 0x76, 0xd8, 0x77, 0xf6, 0x06, 0x78, 0x4c, 0xf4, + /*8570:*/ 0xf8, 0xab, 0x09, 0x9f, 0x81, 0x7c, 0xdf, 0x6c, 0x79, 0x0f, 0xb8, 0xed, 0xec, 0x92, 0x68, 0xb1, + /*8580:*/ 0x0d, 0xed, 0x5c, 0x62, 0xe1, 0x94, 0x91, 0xfd, 0x39, 0xbe, 0x65, 0x59, 0x45, 0xfb, 0x59, 0xe1, + /*8590:*/ 0xbd, 0xad, 0xbc, 0x41, 0xa0, 0x94, 0x49, 0xec, 0x29, 0x06, 0xe9, 0xd8, 0x64, 0x04, 0xe1, 0x70, + /*85a0:*/ 0x31, 0xb9, 0xe4, 0xdf, 0x23, 0xf9, 0x7d, 0x0f, 0x5d, 0x9a, 0xa6, 0x67, 0x4c, 0xde, 0xdd, 0xb6, + /*85b0:*/ 0xb2, 0xc5, 0x33, 0x87, 0xee, 0xb8, 0x36, 0xaa, 0x32, 0xdb, 0xc4, 0x90, 0x9b, 0xe0, 0xc2, 0x6c, + /*85c0:*/ 0xcd, 0xae, 0xff, 0x7e, 0x9a, 0x35, 0xa7, 0x4e, 0x48, 0xe2, 0x62, 0x1b, 0x0e, 0x7d, 0x9b, 0x44, + /*85d0:*/ 0x43, 0xbd, 0x55, 0x82, 0x88, 0x1a, 0x9c, 0x83, 0xfc, 0x1e, 0x3d, 0x8b, 0x6b, 0x29, 0x23, 0xf8, + /*85e0:*/ 0x1e, 0xba, 0xb4, 0x5b, 0xc5, 0x80, 0x12, 0x70, 0x48, 0x9b, 0x41, 0xfb, 0xe6, 0xc8, 0xf3, 0x19, + /*85f0:*/ 0x15, 0x7b, 0xc0, 0x8d, 0xb0, 0x49, 0x67, 0xcc, 0xf4, 0xe0, 0x12, 0x41, 0xf9, 0xfb, 0xd4, 0x1a, + /*8600:*/ 0xe8, 0x72, 0x1b, 0xfc, 0x02, 0xbe, 0x6d, 0x34, 0x96, 0xaf, 0xba, 0x96, 0x44, 0x7d, 0xce, 0x3f, + /*8610:*/ 0x0e, 0x58, 0x7b, 0xb1, 0x0d, 0xb7, 0x00, 0x43, 0x6d, 0x81, 0xaa, 0xa6, 0xe4, 0x5c, 0xf1, 0xa4, + /*8620:*/ 0x1f, 0xe4, 0xa8, 0x30, 0x2b, 0x0c, 0xbf, 0xdd, 0x69, 0xfa, 0xe7, 0xf7, 0x44, 0xff, 0x50, 0x2b, + /*8630:*/ 0x39, 0x73, 0xbd, 0x03, 0x22, 0x84, 0xef, 0x14, 0x08, 0x74, 0xa8, 0x85, 0x05, 0x64, 0xd4, 0xc7, + /*8640:*/ 0x30, 0xa4, 0x84, 0x2e, 0xbd, 0x8d, 0x0c, 0xee, 0xfc, 0x11, 0x0f, 0x0c, 0x3f, 0xb1, 0x48, 0x6e, + /*8650:*/ 0xb6, 0x09, 0x01, 0xc8, 0x54, 0x6a, 0xe7, 0x1b, 0x46, 0x90, 0x5b, 0x79, 0x64, 0x08, 0xa8, 0xda, + /*8660:*/ 0xb0, 0x7e, 0x1f, 0xc3, 0x8c, 0xee, 0x9e, 0x9f, 0x8b, 0x9b, 0xc2, 0x80, 0x2f, 0x4f, 0x0d, 0x3a, + /*8670:*/ 0x97, 0x3b, 0xcd, 0xfa, 0xde, 0xa0, 0xaf, 0x6d, 0x1e, 0xd2, 0x47, 0x31, 0xe0, 0xf3, 0xcf, 0x15, + /*8680:*/ 0x12, 0xae, 0x45, 0xbb, 0x28, 0x04, 0x5e, 0xf6, 0x2e, 0xab, 0xa5, 0x8f, 0xea, 0xd0, 0xa4, 0xbf, + /*8690:*/ 0xbe, 0xa7, 0x77, 0x5d, 0x7b, 0xab, 0x48, 0x5f, 0x1a, 0xe4, 0xc6, 0xb3, 0x62, 0x70, 0xdf, 0x82, + /*86a0:*/ 0x24, 0x59, 0xd6, 0x88, 0x5c, 0x36, 0xd6, 0x0c, 0xbe, 0xbc, 0xbd, 0xc6, 0x1a, 0xcb, 0x93, 0xfa, + /*86b0:*/ 0xff, 0x16, 0x26, 0xea, 0xd2, 0xd3, 0x41, 0x5a, 0x49, 0x00, 0x99, 0x12, 0x48, 0xbe, 0xa8, 0xc7, + /*86c0:*/ 0xe3, 0x5d, 0x3b, 0xb1, 0x40, 0x35, 0xee, 0xfe, 0xc3, 0x78, 0x2b, 0xfe, 0x10, 0x20, 0xc9, 0x96, + /*86d0:*/ 0x28, 0xc2, 0xb2, 0x17, 0x03, 0x69, 0x85, 0x74, 0xf5, 0xac, 0x28, 0x02, 0xd0, 0x97, 0x74, 0xf2, + /*86e0:*/ 0x22, 0x12, 0x80, 0xf1, 0x1b, 0xd8, 0x49, 0x1d, 0x70, 0x79, 0x56, 0x7a, 0xbb, 0x2e, 0x5b, 0x35, + /*86f0:*/ 0x17, 0x34, 0x9b, 0xef, 0xf8, 0x58, 0x8d, 0x4b, 0xf3, 0x9a, 0x7a, 0xb3, 0xf7, 0x8c, 0x08, 0x4c, + /*8700:*/ 0x1f, 0xe4, 0x47, 0x30, 0xa2, 0x16, 0x9e, 0xe3, 0x5f, 0xb6, 0x57, 0xb3, 0x93, 0x8f, 0xd0, 0x5e, + /*8710:*/ 0x3b, 0x8d, 0x64, 0x70, 0x7c, 0xbc, 0x6e, 0xc0, 0x12, 0x4b, 0x1e, 0xcd, 0x0b, 0x58, 0x5c, 0xed, + /*8720:*/ 0x19, 0x2f, 0x72, 0x39, 0xaf, 0x03, 0xaf, 0x8f, 0xe0, 0xc1, 0x3f, 0xcc, 0x8a, 0x9a, 0x95, 0x12, + /*8730:*/ 0x7c, 0x88, 0x38, 0x7d, 0x82, 0xdb, 0xbe, 0x58, 0xbb, 0xa8, 0x9b, 0x05, 0x5f, 0x81, 0xe4, 0xaa, + /*8740:*/ 0x58, 0x81, 0xdc, 0x5f, 0x8a, 0x7c, 0xc0, 0xbc, 0x57, 0xa8, 0x48, 0xa4, 0x7e, 0xd5, 0x6d, 0xc4, + /*8750:*/ 0x04, 0x62, 0xbd, 0x28, 0x0e, 0x5c, 0x97, 0x3b, 0xf2, 0x6f, 0xee, 0xe9, 0x0d, 0x5a, 0x9c, 0x79, + /*8760:*/ 0x17, 0xfe, 0xac, 0x66, 0xb0, 0xa6, 0x6e, 0x11, 0x9b, 0xbe, 0x0b, 0xb4, 0x32, 0x67, 0x47, 0x14, + /*8770:*/ 0x70, 0xd6, 0x1c, 0x8c, 0x8f, 0x95, 0x96, 0xa8, 0x46, 0x10, 0x82, 0x49, 0xb7, 0x69, 0xb7, 0x40, + /*8780:*/ 0x83, 0xad, 0xfa, 0x1f, 0x89, 0x05, 0x8a, 0x16, 0x58, 0xee, 0x9c, 0xfd, 0x9f, 0x0c, 0xc6, 0xca, + /*8790:*/ 0xaf, 0x47, 0x5a, 0x00, 0xcd, 0xd6, 0x83, 0x8d, 0x04, 0xf6, 0x18, 0xc7, 0xf3, 0xd2, 0x4c, 0x7c, + /*87a0:*/ 0xdf, 0xc8, 0x61, 0xa9, 0x82, 0x96, 0xf3, 0x18, 0x77, 0xe2, 0x0a, 0x2c, 0x77, 0x67, 0x3c, 0x65, + /*87b0:*/ 0xd4, 0x56, 0xb0, 0xa6, 0x57, 0x0e, 0x74, 0xc9, 0xb5, 0x5e, 0xde, 0xe3, 0x09, 0x69, 0x53, 0x77, + /*87c0:*/ 0xdf, 0xd6, 0x20, 0xba, 0x19, 0xd6, 0x16, 0xbd, 0x4c, 0x95, 0x94, 0x00, 0x4a, 0xf8, 0x72, 0x83, + /*87d0:*/ 0x4c, 0xf2, 0x96, 0xa7, 0x1e, 0xf9, 0x62, 0x98, 0x64, 0x1a, 0xa5, 0x40, 0xb1, 0xbe, 0xd5, 0xb6, + /*87e0:*/ 0x53, 0x5f, 0xb9, 0xce, 0xa3, 0xcf, 0x03, 0x46, 0x94, 0x85, 0xd8, 0xc4, 0x86, 0x23, 0x85, 0x08, + /*87f0:*/ 0x1a, 0x13, 0xa2, 0x41, 0xf6, 0x9d, 0x52, 0xc6, 0xb2, 0x67, 0xe3, 0x30, 0x23, 0xcb, 0x3a, 0x4b, + /*8800:*/ 0x41, 0x57, 0x5f, 0xd2, 0x75, 0x8b, 0x5f, 0x44, 0x39, 0x40, 0x34, 0x25, 0xf1, 0xda, 0x0a, 0xb0, + /*8810:*/ 0xf0, 0xac, 0x15, 0x8d, 0xee, 0x68, 0x5c, 0x39, 0xbf, 0x48, 0x9a, 0x82, 0xfd, 0x81, 0x45, 0x7e, + /*8820:*/ 0xce, 0x81, 0xe6, 0x97, 0x3d, 0xf4, 0x21, 0x8c, 0x9b, 0x36, 0xe6, 0xd0, 0xbf, 0xcc, 0xf2, 0x33, + /*8830:*/ 0x4e, 0x98, 0x70, 0x3f, 0x08, 0x52, 0x9f, 0xd4, 0x48, 0xf3, 0x0a, 0xd8, 0x51, 0xfb, 0x39, 0x9b, + /*8840:*/ 0x8a, 0xf1, 0x32, 0x55, 0xf0, 0x59, 0x68, 0x17, 0xc8, 0x35, 0xe3, 0x38, 0x8c, 0x40, 0xd4, 0xf7, + /*8850:*/ 0xd3, 0xe7, 0x20, 0x07, 0x84, 0xf8, 0xc0, 0x9a, 0x2c, 0x56, 0x6d, 0xaa, 0xae, 0xca, 0x16, 0x82, + /*8860:*/ 0x9a, 0xd1, 0x72, 0x2e, 0xd4, 0x12, 0xda, 0x65, 0xe6, 0x78, 0x01, 0x79, 0x16, 0xa2, 0x05, 0x45, + /*8870:*/ 0x0b, 0xbc, 0x65, 0xd4, 0xf5, 0x19, 0x9d, 0x1f, 0xa4, 0x49, 0x02, 0xe3, 0x0f, 0x1a, 0x82, 0x49, + /*8880:*/ 0x2c, 0xd2, 0x22, 0xdf, 0x97, 0x7d, 0xe6, 0xaf, 0x14, 0x03, 0xdf, 0x69, 0xe6, 0xf3, 0x07, 0x50, + /*8890:*/ 0x48, 0xe5, 0x42, 0xfe, 0xe3, 0x59, 0x91, 0x6d, 0xbc, 0xf6, 0xd1, 0xf0, 0x2a, 0xbd, 0x0a, 0x4d, + /*88a0:*/ 0x4f, 0x51, 0x6e, 0x0f, 0x76, 0xef, 0xa8, 0xb5, 0xa7, 0x8b, 0x49, 0xf3, 0xd5, 0x8e, 0xf4, 0x41, + /*88b0:*/ 0xf9, 0x57, 0x26, 0x2f, 0xcf, 0xa8, 0xd7, 0x76, 0x36, 0xd1, 0xf1, 0xb9, 0x26, 0x79, 0x92, 0xaf, + /*88c0:*/ 0xcc, 0xf6, 0xe9, 0xab, 0xf2, 0x96, 0xec, 0x5e, 0xbb, 0xcc, 0xf0, 0x89, 0x39, 0xc1, 0x83, 0x8f, + /*88d0:*/ 0xf5, 0x07, 0xb6, 0x17, 0x61, 0x17, 0x1c, 0xcd, 0xb6, 0x3b, 0xcc, 0x68, 0x8d, 0x52, 0x96, 0x18, + /*88e0:*/ 0xbf, 0x18, 0x00, 0xcf, 0xf5, 0x9c, 0x81, 0x20, 0xb0, 0xed, 0x63, 0xef, 0x1e, 0xa2, 0xac, 0x84, + /*88f0:*/ 0x19, 0xd8, 0x9a, 0x28, 0x68, 0x27, 0xb1, 0x99, 0x54, 0x4b, 0xe4, 0x0b, 0xcc, 0x55, 0x9e, 0x49, + /*8900:*/ 0xdb, 0xbc, 0x4d, 0x85, 0x1d, 0x83, 0x83, 0x46, 0x64, 0x27, 0xe1, 0x6d, 0x25, 0x24, 0x72, 0xfe, + /*8910:*/ 0xfb, 0x37, 0x67, 0x48, 0xf0, 0x7f, 0x7a, 0xbc, 0x9c, 0x9b, 0xa6, 0xe0, 0x55, 0xa4, 0x98, 0x3b, + /*8920:*/ 0x8e, 0xbe, 0x5b, 0x92, 0x29, 0x5e, 0xcd, 0x46, 0xcd, 0x83, 0x43, 0xfb, 0x8a, 0xaf, 0x68, 0x89, + /*8930:*/ 0xc6, 0x68, 0x32, 0x83, 0x7c, 0x33, 0x6e, 0xf9, 0x8f, 0x53, 0x40, 0xda, 0x2c, 0x6f, 0xcc, 0x7a, + /*8940:*/ 0xd7, 0x90, 0xd7, 0xc0, 0x29, 0x9d, 0xb7, 0x08, 0xe0, 0xa4, 0x41, 0x25, 0x7e, 0x39, 0x04, 0xf3, + /*8950:*/ 0x02, 0xb8, 0x4e, 0x3e, 0xee, 0x80, 0x07, 0x20, 0xdc, 0x49, 0x16, 0x9e, 0xab, 0xb0, 0x81, 0xd3, + /*8960:*/ 0x33, 0x00, 0xfe, 0xf6, 0x85, 0xcd, 0xf8, 0xe6, 0x79, 0x87, 0x1a, 0x5b, 0x1e, 0x11, 0x1b, 0xca, + /*8970:*/ 0x89, 0x35, 0xa5, 0x3a, 0x98, 0x0f, 0x4d, 0x20, 0x25, 0xe4, 0xbf, 0x48, 0x6d, 0x2c, 0x03, 0x97, + /*8980:*/ 0xff, 0xbb, 0x85, 0x3b, 0x1f, 0x17, 0x4f, 0xd6, 0xf4, 0xd4, 0xb8, 0x80, 0x49, 0x1a, 0x52, 0x26, + /*8990:*/ 0xbd, 0x81, 0x41, 0xe8, 0xc3, 0x63, 0x67, 0xf3, 0xe5, 0xeb, 0x57, 0xbe, 0x28, 0x83, 0xef, 0x3f, + /*89a0:*/ 0xcc, 0xff, 0x4f, 0xed, 0x19, 0xce, 0xe9, 0xe5, 0x0d, 0x1e, 0x0c, 0xd3, 0x8d, 0xed, 0xa3, 0x47, + /*89b0:*/ 0xb7, 0x1d, 0x63, 0x61, 0xc7, 0xfe, 0x36, 0xfa, 0x05, 0x30, 0xd9, 0x36, 0x04, 0xb8, 0x05, 0x1b, + /*89c0:*/ 0x89, 0xf3, 0xc0, 0x81, 0x07, 0xd5, 0xdf, 0x7f, 0x17, 0x5c, 0xaf, 0x75, 0x35, 0xeb, 0x2b, 0xac, + /*89d0:*/ 0x48, 0xd6, 0x07, 0xe7, 0x72, 0x3e, 0xa6, 0x30, 0x75, 0x77, 0x03, 0x74, 0x31, 0xe5, 0x8b, 0x10, + /*89e0:*/ 0xd0, 0x2a, 0x3c, 0xc7, 0x7d, 0xd4, 0x4e, 0xa5, 0xc9, 0xc7, 0xd1, 0xb8, 0xdb, 0x9d, 0x34, 0xbb, + /*89f0:*/ 0xce, 0x26, 0x16, 0x60, 0x38, 0x95, 0x28, 0x78, 0x60, 0xcb, 0x3f, 0xbd, 0xaa, 0x93, 0xed, 0xb3, + /*8a00:*/ 0x0d, 0xd0, 0x8c, 0xf4, 0x69, 0x24, 0x35, 0x84, 0x60, 0x2b, 0x48, 0x5b, 0x9a, 0x7e, 0xb8, 0xe1, + /*8a10:*/ 0xec, 0x6a, 0x17, 0x17, 0xb9, 0xdc, 0x5d, 0xa9, 0xf2, 0x95, 0x7f, 0xf5, 0xe7, 0x6c, 0x79, 0x93, + /*8a20:*/ 0xab, 0xb2, 0x52, 0x1a, 0x39, 0x5b, 0x3e, 0x49, 0x18, 0x19, 0x3c, 0xe7, 0x7e, 0xf4, 0x95, 0x96, + /*8a30:*/ 0x79, 0x30, 0xc0, 0x3f, 0x7a, 0xde, 0x28, 0xd9, 0x95, 0xe3, 0x69, 0x5b, 0xa5, 0x10, 0xb3, 0xe6, + /*8a40:*/ 0x1c, 0x01, 0xcc, 0xd4, 0xf2, 0x58, 0x76, 0x52, 0x9b, 0x1e, 0xa1, 0x90, 0xb0, 0xa4, 0x8e, 0x3e, + /*8a50:*/ 0x9f, 0x46, 0x9e, 0xa8, 0x75, 0x15, 0xe7, 0xfb, 0xf8, 0x5b, 0xb4, 0x55, 0x92, 0x12, 0x1b, 0x07, + /*8a60:*/ 0xb0, 0xe9, 0x0e, 0xf7, 0xf6, 0x1c, 0x7b, 0x31, 0x35, 0x2c, 0x3f, 0x12, 0x08, 0x1f, 0xe5, 0xf7, + /*8a70:*/ 0x7c, 0x9a, 0x32, 0xa2, 0xa5, 0x5c, 0x49, 0x54, 0x52, 0x0d, 0xca, 0xeb, 0x2c, 0x5e, 0x0d, 0xf2, + /*8a80:*/ 0x54, 0x10, 0x6b, 0x8f, 0x81, 0x1d, 0x56, 0x6e, 0x62, 0x7b, 0xfa, 0xe5, 0x65, 0x85, 0x71, 0xde, + /*8a90:*/ 0x53, 0x5e, 0x8a, 0x39, 0xed, 0x01, 0x3d, 0xe0, 0x37, 0x22, 0x1d, 0xd5, 0x6d, 0x94, 0xee, 0x8b, + /*8aa0:*/ 0x26, 0x8b, 0xe4, 0xf9, 0x2e, 0x14, 0xe8, 0x33, 0x59, 0xd1, 0x91, 0x32, 0x4a, 0x57, 0x4b, 0x8a, + /*8ab0:*/ 0x81, 0xbc, 0x57, 0x87, 0xe4, 0xa2, 0x73, 0x27, 0xd5, 0x25, 0x7b, 0x25, 0x09, 0x58, 0x29, 0xd5, + /*8ac0:*/ 0xb2, 0x7a, 0x3b, 0x59, 0x00, 0xf3, 0xba, 0x38, 0x72, 0xa2, 0xd3, 0x0e, 0x92, 0x0f, 0xbd, 0x9d, + /*8ad0:*/ 0x08, 0xbb, 0xe1, 0xdd, 0x55, 0x7c, 0xd7, 0xaa, 0xf6, 0x23, 0x2f, 0x21, 0xba, 0x7a, 0x4c, 0xe6, + /*8ae0:*/ 0xf6, 0x21, 0x8a, 0x3f, 0x28, 0xfa, 0x5d, 0x78, 0x4a, 0xba, 0x36, 0x1f, 0xdc, 0xeb, 0xa4, 0x25, + /*8af0:*/ 0x4a, 0x5c, 0x19, 0xab, 0xaf, 0x78, 0x25, 0x85, 0x5d, 0x2c, 0x56, 0x91, 0xb2, 0xc2, 0x4c, 0xd1, + /*8b00:*/ 0x12, 0x1b, 0x0f, 0xcf, 0x71, 0x79, 0x3f, 0x39, 0xd4, 0x0c, 0x02, 0xef, 0x4c, 0x77, 0x61, 0xb2, + /*8b10:*/ 0x3e, 0x7e, 0x2e, 0x89, 0x23, 0x88, 0x61, 0xd2, 0xb7, 0x7b, 0xe0, 0xfa, 0x91, 0xa6, 0x7b, 0x20, + /*8b20:*/ 0x26, 0x37, 0xbd, 0xd0, 0xaa, 0x0c, 0x6b, 0x9a, 0x12, 0x3a, 0xf6, 0xff, 0x39, 0x7f, 0x41, 0xee, + /*8b30:*/ 0x8b, 0xd3, 0xc6, 0x0e, 0x0e, 0xc1, 0x73, 0x60, 0x7e, 0xd0, 0x65, 0x4b, 0x47, 0x16, 0x17, 0xcd, + /*8b40:*/ 0x6d, 0x4d, 0x6e, 0x24, 0xdd, 0x1f, 0x24, 0x4c, 0x2a, 0xb1, 0x09, 0xf7, 0x77, 0xb6, 0x18, 0xe2, + /*8b50:*/ 0xa6, 0xd7, 0x2f, 0x41, 0xf8, 0x87, 0xb2, 0x89, 0x86, 0x60, 0xdc, 0x55, 0x0f, 0xbe, 0x68, 0xa9, + /*8b60:*/ 0x3c, 0x3e, 0xc1, 0xd9, 0x2b, 0x92, 0x1e, 0xb1, 0xe9, 0x97, 0xfc, 0xc8, 0xe9, 0x0a, 0xdc, 0xa6, + /*8b70:*/ 0x43, 0xe8, 0xc1, 0xeb, 0x02, 0x54, 0x9f, 0x94, 0xaa, 0xf2, 0xef, 0x72, 0xa3, 0x5b, 0x96, 0xfe, + /*8b80:*/ 0x33, 0xc5, 0x04, 0x0f, 0x37, 0x1c, 0x77, 0x5d, 0x53, 0x7c, 0xa3, 0x42, 0x0c, 0x40, 0x4a, 0x50, + /*8b90:*/ 0xc6, 0x44, 0x1e, 0xdd, 0x1c, 0x27, 0x87, 0x8f, 0x79, 0x8f, 0x2b, 0x7e, 0x2c, 0x2c, 0x08, 0xaf, + /*8ba0:*/ 0xc6, 0xcb, 0x68, 0xbe, 0xc7, 0x41, 0x9e, 0x01, 0xf5, 0x51, 0x04, 0xa2, 0x52, 0xb0, 0x58, 0xa6, + /*8bb0:*/ 0xc3, 0xd9, 0xf8, 0xe5, 0xe5, 0x60, 0x5a, 0x42, 0x1c, 0x92, 0x71, 0x27, 0x2b, 0x1b, 0x7b, 0xad, + /*8bc0:*/ 0x32, 0x24, 0x3e, 0x75, 0xa2, 0x64, 0xaa, 0x8e, 0xe1, 0x96, 0x6e, 0x80, 0xf7, 0x6f, 0xdb, 0xce, + /*8bd0:*/ 0xa8, 0xd5, 0x4a, 0x8b, 0xd4, 0x29, 0x10, 0x03, 0x17, 0x38, 0x5f, 0xdc, 0xca, 0xd7, 0xeb, 0xac, + /*8be0:*/ 0x45, 0x3d, 0xb8, 0x1b, 0x20, 0xae, 0x91, 0x6b, 0x63, 0xc7, 0xe4, 0x69, 0x94, 0xb9, 0x41, 0xe8, + /*8bf0:*/ 0xdc, 0x67, 0xb8, 0x0a, 0xfa, 0x72, 0x4e, 0x23, 0x12, 0xd9, 0xb1, 0x13, 0xf7, 0x53, 0xf6, 0x2b, + /*8c00:*/ 0x89, 0x06, 0x80, 0x67, 0x02, 0xc5, 0x4b, 0xbd, 0xaf, 0x60, 0x73, 0x90, 0x00, 0xd3, 0xfc, 0x9e, + /*8c10:*/ 0x59, 0x76, 0xaf, 0x70, 0x44, 0xd9, 0xae, 0x1a, 0x6b, 0xa7, 0x56, 0xad, 0x1b, 0xc2, 0xe6, 0xd5, + /*8c20:*/ 0xbc, 0x6f, 0x4a, 0xd9, 0x59, 0x11, 0xc1, 0xc5, 0xaf, 0x36, 0x26, 0x93, 0xd6, 0x20, 0x72, 0x61, + /*8c30:*/ 0x8e, 0xb6, 0x84, 0xab, 0x54, 0xcb, 0x7c, 0xf6, 0x84, 0x3b, 0x09, 0x3a, 0x46, 0x2f, 0xc6, 0x95, + /*8c40:*/ 0x07, 0x5f, 0xda, 0xf6, 0x8b, 0x30, 0x6d, 0xd9, 0xbb, 0x6f, 0x13, 0xea, 0x81, 0xa3, 0xd5, 0x72, + /*8c50:*/ 0x46, 0x43, 0x53, 0xe5, 0xbd, 0x02, 0x9c, 0x1d, 0x29, 0x94, 0x97, 0x01, 0xce, 0x6a, 0x76, 0x7b, + /*8c60:*/ 0xc3, 0xa5, 0x2f, 0xcf, 0xe4, 0x81, 0x32, 0xb5, 0x9f, 0xa1, 0x98, 0xea, 0xab, 0xe9, 0x6c, 0x8a, + /*8c70:*/ 0x37, 0x4e, 0x9e, 0x10, 0x1b, 0x87, 0xbd, 0x06, 0x77, 0xd5, 0x79, 0x79, 0xe3, 0x6d, 0x4e, 0x96, + /*8c80:*/ 0x51, 0x56, 0xd6, 0x18, 0x93, 0xe8, 0x69, 0xb4, 0x50, 0xf6, 0x61, 0xfc, 0x67, 0xdf, 0x82, 0xd4, + /*8c90:*/ 0x99, 0x06, 0x16, 0x97, 0x95, 0xd6, 0x43, 0xd6, 0x31, 0x4f, 0xb7, 0xeb, 0x2f, 0x3a, 0x3b, 0x1a, + /*8ca0:*/ 0xd9, 0xe2, 0xa1, 0xca, 0xbb, 0x76, 0x48, 0xe3, 0x47, 0xcc, 0xbe, 0x67, 0x24, 0xa2, 0xd0, 0x9a, + /*8cb0:*/ 0x7c, 0x30, 0x4f, 0x1b, 0x85, 0x08, 0xc9, 0xec, 0x98, 0x65, 0xb0, 0x93, 0x10, 0x1c, 0xca, 0x83, + /*8cc0:*/ 0x2d, 0x00, 0x68, 0x96, 0x39, 0x3f, 0x3f, 0x7c, 0x42, 0x6b, 0x6f, 0x41, 0x3f, 0xf3, 0x29, 0x66, + /*8cd0:*/ 0x98, 0xfb, 0x14, 0x3c, 0x8b, 0xd9, 0x5f, 0xdd, 0xe7, 0x8d, 0xbd, 0x40, 0x5a, 0x12, 0x41, 0x0c, + /*8ce0:*/ 0xd8, 0x02, 0x89, 0xc1, 0x65, 0x1b, 0xb2, 0x79, 0x6b, 0x98, 0x50, 0xff, 0xc8, 0xf0, 0x67, 0x66, + /*8cf0:*/ 0x51, 0xb8, 0x05, 0xc9, 0x1a, 0xcc, 0x7e, 0x28, 0x22, 0xc7, 0x11, 0xf6, 0xfc, 0x71, 0xeb, 0x97, + /*8d00:*/ 0x4b, 0x51, 0x53, 0x25, 0x88, 0xc9, 0x5e, 0x11, 0x84, 0x79, 0x4e, 0xf2, 0x02, 0x2f, 0xa6, 0x7e, + /*8d10:*/ 0x82, 0x65, 0x34, 0xfa, 0xd6, 0x33, 0xfe, 0xaa, 0x95, 0xe5, 0xb3, 0xd1, 0x5e, 0xf6, 0xdf, 0x96, + /*8d20:*/ 0x20, 0x29, 0xd6, 0xd4, 0xc1, 0x5c, 0x53, 0x2b, 0x4c, 0x32, 0xf4, 0xae, 0xfc, 0x69, 0x53, 0xfc, + /*8d30:*/ 0x2a, 0x7e, 0x83, 0xfb, 0x8f, 0x35, 0xe2, 0xd9, 0x5c, 0x12, 0x22, 0x5c, 0xc0, 0x75, 0x8a, 0x23, + /*8d40:*/ 0x8d, 0x63, 0xc8, 0xa9, 0x69, 0x40, 0x9c, 0x29, 0x22, 0xe9, 0x6a, 0x2b, 0x0c, 0xb7, 0xc8, 0x79, + /*8d50:*/ 0xb6, 0xcd, 0xaf, 0xac, 0x91, 0x96, 0x78, 0xb6, 0x29, 0x0b, 0xbd, 0x76, 0xd5, 0x2e, 0xcc, 0x39, + /*8d60:*/ 0x3b, 0xcc, 0xb1, 0xff, 0x91, 0xb9, 0xab, 0xcb, 0x34, 0xfb, 0xcf, 0xaf, 0xe3, 0xde, 0xb2, 0x37, + /*8d70:*/ 0xb5, 0x79, 0x47, 0xb3, 0xac, 0x9b, 0x20, 0xc4, 0xda, 0x7d, 0x6f, 0x49, 0x6f, 0x8b, 0xe3, 0x4b, + /*8d80:*/ 0x31, 0x23, 0x28, 0x63, 0x08, 0x59, 0x23, 0xf1, 0xa5, 0xea, 0x64, 0x08, 0x88, 0x34, 0xf3, 0x39, + /*8d90:*/ 0x62, 0xe8, 0x7a, 0x18, 0xed, 0x25, 0xa4, 0x68, 0x3d, 0xa6, 0x64, 0x0d, 0xdc, 0x99, 0x05, 0xc9, + /*8da0:*/ 0xb0, 0x9e, 0xc3, 0xe3, 0xa2, 0x9e, 0xc7, 0x92, 0x7a, 0xe1, 0xdd, 0x0e, 0x9d, 0x71, 0x6c, 0xf5, + /*8db0:*/ 0x73, 0xa5, 0xf9, 0xdf, 0x94, 0x49, 0xa3, 0x23, 0x73, 0xe0, 0x51, 0x6d, 0x0f, 0x9e, 0x1a, 0x87, + /*8dc0:*/ 0x3a, 0xef, 0xa4, 0x63, 0x13, 0x79, 0x7a, 0x2d, 0x0f, 0x7c, 0x88, 0x8b, 0xb1, 0x65, 0xbf, 0x0a, + /*8dd0:*/ 0xb5, 0x21, 0xc4, 0x7c, 0x65, 0xe3, 0x52, 0x1d, 0xa2, 0xf6, 0x1d, 0x93, 0x84, 0x86, 0x7a, 0xe8, + /*8de0:*/ 0x5f, 0x72, 0x4b, 0x85, 0x48, 0x8f, 0x23, 0x93, 0x7f, 0xdd, 0xef, 0x17, 0x46, 0x5d, 0xbe, 0xc0, + /*8df0:*/ 0x67, 0xbd, 0xe4, 0xd7, 0xc9, 0xca, 0x2e, 0xc6, 0x8b, 0xc3, 0x82, 0x28, 0x0f, 0xa6, 0x22, 0x9c, + /*8e00:*/ 0xaf, 0x0c, 0xa2, 0x5f, 0xe6, 0x91, 0x72, 0x6b, 0x43, 0x44, 0xd5, 0x8c, 0xd5, 0x55, 0xc2, 0x6a, + /*8e10:*/ 0x95, 0xe0, 0x42, 0x22, 0x41, 0xe7, 0xd5, 0x2a, 0xfa, 0xf7, 0xaa, 0x74, 0x29, 0x4f, 0x87, 0x2c, + /*8e20:*/ 0x38, 0x6a, 0x4a, 0x07, 0x38, 0xfd, 0x8c, 0xe2, 0x8d, 0xd8, 0x2b, 0x2e, 0xe7, 0x2b, 0xbc, 0x02, + /*8e30:*/ 0x22, 0xa1, 0x26, 0xce, 0x57, 0xab, 0x9b, 0x20, 0x02, 0x43, 0xaf, 0xb5, 0x73, 0x95, 0xc1, 0x5a, + /*8e40:*/ 0xe2, 0xe3, 0x7f, 0x60, 0x04, 0xab, 0xa3, 0x21, 0xf8, 0x18, 0xdb, 0x6b, 0x01, 0xdf, 0x6a, 0xac, + /*8e50:*/ 0xdb, 0x37, 0xa4, 0xdd, 0x4b, 0x0e, 0xfa, 0x39, 0xed, 0x64, 0xfb, 0xfc, 0x98, 0xe7, 0x71, 0x02, + /*8e60:*/ 0xdd, 0xbb, 0xa5, 0x62, 0x7e, 0x18, 0x16, 0xe1, 0x6e, 0xbd, 0x1d, 0xb3, 0xc5, 0x11, 0xd2, 0xdb, + /*8e70:*/ 0x20, 0x1f, 0x3a, 0x84, 0xda, 0x08, 0x7d, 0x58, 0x50, 0xc3, 0x3c, 0x5c, 0x7c, 0xc9, 0xb8, 0x78, + /*8e80:*/ 0x03, 0x57, 0x93, 0x71, 0x71, 0x28, 0xaf, 0x84, 0xd6, 0x89, 0xa2, 0xd4, 0x01, 0xcb, 0x26, 0x1b, + /*8e90:*/ 0x0a, 0x35, 0x38, 0xf8, 0x77, 0xb1, 0x09, 0x03, 0xb7, 0x1a, 0x0d, 0xb2, 0x82, 0x90, 0x22, 0x05, + /*8ea0:*/ 0x19, 0x63, 0x66, 0x58, 0x4a, 0xf9, 0x2f, 0x2f, 0xe2, 0xbb, 0x2b, 0x31, 0xca, 0xdc, 0x96, 0x47, + /*8eb0:*/ 0x88, 0x7d, 0x62, 0x75, 0xe6, 0x96, 0xf3, 0xa2, 0x1e, 0x62, 0x59, 0xff, 0x24, 0xbe, 0x2f, 0x8f, + /*8ec0:*/ 0xdf, 0xd5, 0x72, 0xfc, 0x0f, 0xc8, 0x10, 0x48, 0xa2, 0x90, 0xe0, 0x1a, 0xa2, 0x0c, 0x80, 0x80, + /*8ed0:*/ 0xda, 0xb8, 0x2f, 0x8c, 0xc4, 0x07, 0x49, 0x7a, 0x29, 0xf5, 0xbb, 0x02, 0x49, 0xc0, 0xa5, 0x5c, + /*8ee0:*/ 0x54, 0x6f, 0x05, 0xb6, 0x48, 0x1c, 0x41, 0xc9, 0xa2, 0x19, 0xab, 0xc4, 0x39, 0x6d, 0xf7, 0x7b, + /*8ef0:*/ 0x22, 0xc0, 0xbd, 0xbf, 0xd7, 0x88, 0x46, 0xe4, 0x18, 0x42, 0x06, 0xea, 0x45, 0xcb, 0x6a, 0xe1, + /*8f00:*/ 0x23, 0xe6, 0x93, 0x32, 0x7a, 0x56, 0x90, 0x80, 0xa9, 0xb1, 0xe3, 0x47, 0x6f, 0x71, 0x17, 0xb2, + /*8f10:*/ 0x6f, 0x5b, 0x23, 0x7a, 0x22, 0xea, 0xeb, 0xd1, 0x52, 0xed, 0x41, 0x71, 0xf5, 0x16, 0x98, 0x3a, + /*8f20:*/ 0x57, 0x79, 0x86, 0x99, 0xbf, 0xbe, 0xd2, 0x6b, 0x9d, 0x2a, 0x14, 0x61, 0x03, 0x5e, 0x4b, 0x5f, + /*8f30:*/ 0x02, 0x59, 0x22, 0x37, 0x13, 0x79, 0x7d, 0x47, 0xca, 0xc4, 0xe9, 0xa9, 0x0f, 0x33, 0x89, 0x72, + /*8f40:*/ 0x86, 0x3a, 0x79, 0x68, 0x17, 0x63, 0x6a, 0x0d, 0x50, 0x59, 0xd3, 0xb8, 0x3f, 0x32, 0x84, 0x6a, + /*8f50:*/ 0x7c, 0x11, 0x65, 0xb1, 0x34, 0xb6, 0x6a, 0x9f, 0x59, 0x28, 0xdd, 0xe8, 0xef, 0x10, 0x2a, 0x65, + /*8f60:*/ 0xde, 0x73, 0x8e, 0x15, 0x64, 0xcf, 0x99, 0xa9, 0x01, 0xdb, 0x79, 0x12, 0x99, 0x9b, 0x66, 0x0c, + /*8f70:*/ 0x5b, 0x2f, 0x31, 0xd4, 0xdd, 0x74, 0x8b, 0x64, 0x3e, 0x7e, 0xee, 0x85, 0xac, 0xcb, 0x94, 0x8a, + /*8f80:*/ 0xfb, 0xc8, 0x87, 0xce, 0xeb, 0x18, 0x23, 0xd4, 0x13, 0x4c, 0x22, 0xeb, 0x2d, 0x71, 0x7e, 0xd6, + /*8f90:*/ 0x4f, 0x06, 0x85, 0xf2, 0xf7, 0x4d, 0x39, 0xc3, 0x11, 0x33, 0x2a, 0x9e, 0xf8, 0x3c, 0xde, 0xef, + /*8fa0:*/ 0x06, 0xbe, 0xcd, 0x77, 0x21, 0xeb, 0xb0, 0xd6, 0xcf, 0x41, 0xd2, 0xd9, 0xb5, 0x8c, 0xa9, 0x51, + /*8fb0:*/ 0xae, 0x17, 0xe0, 0xb0, 0x60, 0x3f, 0x62, 0x82, 0x71, 0x28, 0x7e, 0xb9, 0x6d, 0x17, 0x26, 0xde, + /*8fc0:*/ 0xb0, 0x98, 0xeb, 0x35, 0x28, 0xb9, 0x1e, 0xd5, 0x82, 0xf7, 0xaf, 0xa2, 0x3b, 0xb7, 0xbe, 0xfd, + /*8fd0:*/ 0x4d, 0x68, 0x6a, 0x20, 0x61, 0x50, 0x47, 0xb2, 0x4a, 0x42, 0x7a, 0xfa, 0x29, 0xcc, 0x9e, 0x2f, + /*8fe0:*/ 0xd9, 0x50, 0x5b, 0xac, 0x1d, 0x02, 0x90, 0xd9, 0xe5, 0xe8, 0x51, 0x12, 0xe8, 0x3b, 0xb9, 0x06, + /*8ff0:*/ 0x93, 0xb5, 0x3c, 0xa3, 0xdf, 0x96, 0xd1, 0x07, 0xb5, 0xf7, 0x6d, 0xcd, 0x6e, 0x2c, 0xd3, 0x89, + /*9000:*/ 0xcd, 0x97, 0xfb, 0x6a, 0x85, 0xcf, 0x10, 0x46, 0xdc, 0xc6, 0xde, 0x2d, 0x28, 0x1a, 0xe7, 0x1a, + /*9010:*/ 0x6a, 0x19, 0x84, 0x67, 0x2d, 0x47, 0xb2, 0x05, 0xca, 0xe2, 0x74, 0xf6, 0xbc, 0x62, 0x15, 0x74, + /*9020:*/ 0x19, 0x15, 0x04, 0x73, 0xd1, 0x52, 0xe6, 0x57, 0xbf, 0x05, 0x0b, 0xe4, 0x38, 0x0c, 0x7c, 0x7b, + /*9030:*/ 0x87, 0x7c, 0xa0, 0xd3, 0x14, 0x94, 0xcc, 0x4d, 0x73, 0x12, 0xac, 0x5e, 0x7d, 0x74, 0xb3, 0x43, + /*9040:*/ 0xe1, 0x88, 0xca, 0x1d, 0x3d, 0x1c, 0xa1, 0x11, 0x83, 0xea, 0xf0, 0x72, 0x29, 0xda, 0xbe, 0xd3, + /*9050:*/ 0x98, 0xd2, 0xd8, 0xd6, 0x71, 0x9c, 0x7b, 0x44, 0xb8, 0x3c, 0xf6, 0x04, 0xc5, 0x32, 0xb8, 0x4e, + /*9060:*/ 0xb9, 0xcd, 0x59, 0x36, 0xe8, 0xd1, 0x63, 0x70, 0xd6, 0x5d, 0x0d, 0x49, 0xc8, 0x0e, 0xb6, 0x28, + /*9070:*/ 0x68, 0x67, 0xe8, 0x0c, 0x8c, 0x2f, 0x74, 0xfd, 0x56, 0x1d, 0x65, 0xaf, 0x33, 0xba, 0xf4, 0xe0, + /*9080:*/ 0x8c, 0xff, 0x5e, 0x96, 0x4c, 0xa9, 0x25, 0xde, 0x03, 0x8d, 0x38, 0xc6, 0xba, 0x40, 0xf8, 0xdf, + /*9090:*/ 0x93, 0xb4, 0x50, 0x58, 0x42, 0x73, 0x91, 0xad, 0xb4, 0x6f, 0x25, 0x0b, 0x7f, 0x5a, 0xd0, 0x69, + /*90a0:*/ 0x0e, 0x44, 0xbc, 0x27, 0xcc, 0x14, 0x07, 0xeb, 0x11, 0x20, 0x05, 0x3b, 0xf0, 0x73, 0x51, 0xc2, + /*90b0:*/ 0x3e, 0xbb, 0x85, 0xc9, 0xd7, 0xea, 0xd0, 0x0e, 0x25, 0xa1, 0x41, 0xe1, 0x70, 0xbd, 0xae, 0x81, + /*90c0:*/ 0xcc, 0x2b, 0x19, 0x39, 0x3b, 0xb3, 0x65, 0x2b, 0xd7, 0x9d, 0x94, 0xb3, 0xe1, 0xe7, 0xa5, 0xde, + /*90d0:*/ 0xd5, 0xe8, 0xb7, 0xc3, 0x4d, 0xbb, 0x32, 0x71, 0xa3, 0xfc, 0xb0, 0x6c, 0x8e, 0x20, 0xe7, 0xeb, + /*90e0:*/ 0x88, 0xc8, 0xa4, 0x76, 0xe8, 0xd5, 0xb1, 0x24, 0xbb, 0xa4, 0x35, 0xc8, 0x74, 0xb5, 0x3b, 0xba, + /*90f0:*/ 0x08, 0xbc, 0xbd, 0xcd, 0xe6, 0x0e, 0x71, 0x32, 0x0e, 0x88, 0x52, 0xfa, 0x45, 0xe7, 0x02, 0x3b, + /*9100:*/ 0x11, 0x5d, 0x8c, 0x07, 0x14, 0xc1, 0x68, 0x05, 0xc2, 0x4f, 0x03, 0x1c, 0x17, 0xa6, 0x38, 0xa1, + /*9110:*/ 0x9d, 0x07, 0xb0, 0xb3, 0x00, 0xab, 0x98, 0x89, 0x79, 0xd3, 0x8b, 0xb2, 0x93, 0x6b, 0x30, 0xf4, + /*9120:*/ 0x0c, 0xbd, 0xe3, 0x79, 0x3d, 0x1e, 0x3a, 0x75, 0xf8, 0x67, 0x3f, 0xd9, 0x20, 0x07, 0x22, 0xe6, + /*9130:*/ 0xc1, 0x4f, 0x85, 0x56, 0x68, 0xaa, 0xd1, 0x70, 0xd9, 0x3c, 0x24, 0xee, 0xdf, 0xcc, 0x1c, 0xda, + /*9140:*/ 0x76, 0xf5, 0x18, 0xd1, 0x53, 0x43, 0x3c, 0x1a, 0x51, 0xa4, 0x34, 0xce, 0xde, 0x4d, 0xfb, 0xee, + /*9150:*/ 0x8e, 0xca, 0xb7, 0x36, 0xae, 0x68, 0xcc, 0x22, 0x8b, 0xec, 0x66, 0xba, 0xcd, 0x93, 0x41, 0x75, + /*9160:*/ 0xc5, 0xba, 0x92, 0x23, 0xde, 0x1b, 0xc4, 0xc8, 0x75, 0xcb, 0xcc, 0x14, 0x2b, 0x99, 0x06, 0x43, + /*9170:*/ 0xd1, 0x9d, 0xae, 0xd5, 0x54, 0xda, 0x5f, 0x6f, 0x9c, 0x96, 0x52, 0x1c, 0xca, 0xf6, 0xab, 0x58, + /*9180:*/ 0xe4, 0xbd, 0x83, 0x35, 0xc6, 0x32, 0xae, 0xd7, 0x54, 0x59, 0x53, 0xb3, 0x33, 0xe6, 0xd9, 0x7c, + /*9190:*/ 0x72, 0xb5, 0xcb, 0x02, 0x92, 0xd8, 0xf2, 0x68, 0xd1, 0xdb, 0x93, 0xd8, 0x2e, 0xc9, 0xda, 0x87, + /*91a0:*/ 0x50, 0xf2, 0x6c, 0xf9, 0x58, 0x2e, 0x6a, 0x6a, 0xfc, 0x08, 0x56, 0x9c, 0x6e, 0xe1, 0xdf, 0xe2, + /*91b0:*/ 0x90, 0x38, 0xbe, 0xb9, 0xbc, 0x2e, 0xb9, 0x2c, 0xcc, 0xd9, 0x0d, 0x25, 0xe2, 0x37, 0xf4, 0x28, + /*91c0:*/ 0xe1, 0xc1, 0xf2, 0xc9, 0x68, 0xd3, 0xff, 0xa3, 0xf0, 0x28, 0x67, 0x48, 0xfb, 0x91, 0xfe, 0x46, + /*91d0:*/ 0xc4, 0xbf, 0x60, 0xe7, 0x97, 0x37, 0x3f, 0xd2, 0x7e, 0xdf, 0x3d, 0x27, 0x6d, 0x3e, 0x69, 0xa5, + /*91e0:*/ 0x7f, 0x2f, 0x57, 0xeb, 0x82, 0x7e, 0x94, 0x85, 0x69, 0xb2, 0x9d, 0xa6, 0x66, 0x16, 0xa7, 0xc2, + /*91f0:*/ 0x87, 0xe8, 0x72, 0x7c, 0x99, 0xd4, 0xb1, 0x43, 0xa8, 0x06, 0x32, 0x32, 0x1e, 0xb2, 0x6e, 0x2f, + /*9200:*/ 0xd0, 0xca, 0xe7, 0x10, 0xd5, 0xc2, 0xe5, 0x6b, 0x91, 0xac, 0xb4, 0x79, 0x6f, 0x23, 0xcc, 0xfc, + /*9210:*/ 0x09, 0xe4, 0x62, 0x5e, 0xb6, 0x58, 0xd1, 0x53, 0xd4, 0x10, 0x0b, 0x01, 0xf5, 0x26, 0x5f, 0x5a, + /*9220:*/ 0xcf, 0xf6, 0x44, 0x93, 0xad, 0xed, 0x64, 0xd2, 0xfd, 0x2c, 0x6a, 0xfe, 0x3c, 0x37, 0x44, 0xf0, + /*9230:*/ 0x0d, 0x21, 0xd3, 0x7b, 0x8d, 0x8a, 0xfe, 0x0c, 0xf9, 0x5a, 0x0a, 0x86, 0xed, 0xfb, 0x5b, 0x6b, + /*9240:*/ 0xbe, 0x39, 0xb9, 0x85, 0xf8, 0x76, 0xde, 0x5f, 0xd8, 0x6e, 0x95, 0xb6, 0xd5, 0x4b, 0x40, 0x32, + /*9250:*/ 0x4a, 0xf1, 0x1c, 0xa8, 0x48, 0xe2, 0xf3, 0x10, 0xa6, 0x51, 0xee, 0x2a, 0xbb, 0x65, 0xaa, 0xe6, + /*9260:*/ 0x4b, 0x9c, 0x5f, 0x30, 0xcc, 0xbe, 0xae, 0xe3, 0x0f, 0xbe, 0x34, 0x44, 0xf5, 0x3c, 0xb2, 0x6d, + /*9270:*/ 0xd5, 0x2f, 0x3b, 0x59, 0xc8, 0x7f, 0x48, 0xfa, 0x53, 0x6f, 0x85, 0x7b, 0xaa, 0x6d, 0xf5, 0x2c, + /*9280:*/ 0x0f, 0x23, 0x8a, 0x25, 0xee, 0x4f, 0x08, 0x00, 0xc9, 0x1d, 0x53, 0xdb, 0xad, 0x37, 0x35, 0x41, + /*9290:*/ 0x6c, 0x9f, 0xe2, 0x79, 0x6a, 0x21, 0x04, 0x05, 0xe6, 0x6f, 0x74, 0x9e, 0x9a, 0x1c, 0x33, 0xd6, + /*92a0:*/ 0x44, 0x5c, 0x09, 0x40, 0xcb, 0x0e, 0xe4, 0x27, 0xa3, 0xf8, 0xf7, 0xd4, 0xed, 0x09, 0x33, 0x71, + /*92b0:*/ 0x5d, 0x5c, 0x95, 0x25, 0x67, 0x0a, 0x5c, 0x2e, 0xb6, 0xe7, 0xb0, 0x10, 0x9c, 0x19, 0xb4, 0x39, + /*92c0:*/ 0x99, 0x11, 0xbd, 0x82, 0x87, 0x28, 0x6d, 0x75, 0x9d, 0x4e, 0x66, 0xbb, 0x1f, 0x01, 0x6b, 0x33, + /*92d0:*/ 0xf5, 0x01, 0x20, 0x9f, 0x69, 0x09, 0x99, 0x29, 0xda, 0x12, 0x5a, 0xa5, 0x47, 0xe2, 0x4d, 0x3c, + /*92e0:*/ 0x39, 0x54, 0x5e, 0x69, 0xa4, 0x54, 0x14, 0x1f, 0x3f, 0x75, 0xfc, 0x25, 0xa3, 0x3d, 0xc1, 0x65, + /*92f0:*/ 0xc6, 0xd0, 0xdb, 0x44, 0xbe, 0xe9, 0x6d, 0x3d, 0x00, 0x81, 0x3b, 0xed, 0xb5, 0xfd, 0xa6, 0x19, + /*9300:*/ 0x63, 0xa2, 0xf0, 0xd8, 0x86, 0xeb, 0x86, 0x20, 0xe2, 0xaa, 0x98, 0xf9, 0x21, 0x51, 0x40, 0x63, + /*9310:*/ 0x84, 0x80, 0x6d, 0x18, 0x84, 0x3c, 0x91, 0x6a, 0x93, 0x85, 0x25, 0x5b, 0x5a, 0x12, 0x61, 0xf3, + /*9320:*/ 0x20, 0x02, 0x6e, 0x52, 0x08, 0xcf, 0x9a, 0xda, 0xd0, 0xbc, 0xd5, 0x70, 0xca, 0x73, 0x28, 0xcb, + /*9330:*/ 0x6c, 0x97, 0xc1, 0xb0, 0x0e, 0xb7, 0xa2, 0xd7, 0xb8, 0xb2, 0xe3, 0x98, 0xf7, 0x9e, 0x60, 0xc6, + /*9340:*/ 0x54, 0x2d, 0x04, 0x98, 0x6f, 0x29, 0xbe, 0xdc, 0x67, 0xad, 0xfd, 0x2d, 0xf5, 0x0e, 0x11, 0xfb, + /*9350:*/ 0x00, 0xac, 0xef, 0x9d, 0x6c, 0x12, 0x26, 0xf4, 0xf0, 0xaf, 0x05, 0xe4, 0xbf, 0x07, 0x50, 0x17, + /*9360:*/ 0x9e, 0xf9, 0xfe, 0x37, 0x35, 0xa2, 0xb5, 0xff, 0x98, 0xd7, 0x05, 0xa2, 0xb2, 0xa7, 0x5c, 0x2a, + /*9370:*/ 0x3f, 0x67, 0x01, 0x06, 0xa9, 0x3e, 0xdc, 0x76, 0x97, 0xfb, 0x36, 0x72, 0x30, 0xb7, 0xe4, 0x30, + /*9380:*/ 0x51, 0xe3, 0xe7, 0xeb, 0xcc, 0xd3, 0x3d, 0x6f, 0x9e, 0x7e, 0x00, 0xc6, 0x7c, 0x14, 0xb0, 0xae, + /*9390:*/ 0x79, 0x1c, 0x0b, 0x55, 0xcc, 0x61, 0xaf, 0xfc, 0x96, 0xcf, 0xcc, 0xe1, 0x99, 0x4b, 0x85, 0xe7, + /*93a0:*/ 0xa8, 0x9b, 0x40, 0xa9, 0xf8, 0xe8, 0x68, 0xe7, 0x9d, 0xde, 0xf4, 0xdc, 0x93, 0x57, 0x0a, 0x54, + /*93b0:*/ 0x5e, 0x4a, 0x1c, 0xd7, 0x2f, 0xc4, 0x5d, 0x37, 0x98, 0xbc, 0x63, 0xf6, 0x5c, 0x9a, 0xc0, 0xf4, + /*93c0:*/ 0x5e, 0x07, 0xc5, 0xab, 0xe5, 0x51, 0xf1, 0xe9, 0x8d, 0xcd, 0x48, 0x54, 0xce, 0x87, 0x69, 0x51, + /*93d0:*/ 0x10, 0xb9, 0xe6, 0x47, 0x8c, 0x2f, 0x2f, 0xe1, 0x9b, 0xcd, 0x05, 0x55, 0x9c, 0xa7, 0x0f, 0x18, + /*93e0:*/ 0x76, 0xee, 0xc3, 0x7e, 0xfa, 0x69, 0xa3, 0x7f, 0xc2, 0xa9, 0xff, 0xaa, 0x7a, 0x2d, 0x13, 0xd1, + /*93f0:*/ 0xde, 0x8b, 0x1c, 0xd8, 0xe6, 0x6f, 0x12, 0xfc, 0x4c, 0xec, 0x79, 0x02, 0x17, 0x6f, 0xc3, 0xd1, + /*9400:*/ 0xb5, 0x6e, 0xff, 0x06, 0xf1, 0x06, 0xd6, 0xbe, 0xbf, 0x02, 0x04, 0x72, 0x48, 0xed, 0x80, 0x58, + /*9410:*/ 0xf0, 0x5f, 0x31, 0xcf, 0x4d, 0xec, 0xe0, 0x1b, 0x6d, 0x33, 0x69, 0xfd, 0x2f, 0x62, 0xb8, 0x93, + /*9420:*/ 0xac, 0x31, 0x56, 0x8e, 0x61, 0xde, 0x88, 0xea, 0x3f, 0xc4, 0x6b, 0xff, 0xcc, 0x6f, 0x10, 0x26, + /*9430:*/ 0x85, 0x04, 0x98, 0xe4, 0x3a, 0xda, 0x18, 0xa2, 0x99, 0x59, 0x73, 0x58, 0x91, 0x7c, 0x22, 0x7e, + /*9440:*/ 0x16, 0xd4, 0xd3, 0x20, 0x4c, 0x82, 0x21, 0x81, 0x43, 0x83, 0x36, 0x73, 0x04, 0x0e, 0x07, 0x79, + /*9450:*/ 0x81, 0xd7, 0x8e, 0x44, 0x50, 0x9f, 0x33, 0x68, 0x0c, 0x67, 0x18, 0xd3, 0xba, 0xbe, 0xc9, 0xb7, + /*9460:*/ 0xed, 0x8f, 0xb0, 0xdc, 0xc6, 0xab, 0x17, 0x84, 0xa0, 0x79, 0x78, 0xf9, 0x87, 0x8a, 0x21, 0xdf, + /*9470:*/ 0xe7, 0x4d, 0xfa, 0x3b, 0xd8, 0xf4, 0x00, 0x85, 0x00, 0x0d, 0x8e, 0x68, 0x7a, 0x5a, 0x1a, 0x6a, + /*9480:*/ 0x3a, 0x6d, 0x36, 0x12, 0xf4, 0xd4, 0x09, 0xf9, 0xc5, 0x50, 0x1c, 0xe6, 0xe0, 0x58, 0x25, 0xfa, + /*9490:*/ 0xbc, 0xea, 0xfe, 0x6e, 0x1f, 0x1a, 0x16, 0x8f, 0x2f, 0x0f, 0xb2, 0xf3, 0x85, 0xe0, 0x11, 0x9e, + /*94a0:*/ 0x90, 0xf1, 0xab, 0x01, 0xea, 0x9e, 0x03, 0xbe, 0xaa, 0x73, 0x8c, 0x96, 0xf2, 0x1c, 0x74, 0x46, + /*94b0:*/ 0xdd, 0x4c, 0xff, 0x63, 0x18, 0x4b, 0xee, 0x7d, 0xed, 0xff, 0x16, 0xc8, 0x8d, 0xac, 0x0e, 0xe1, + /*94c0:*/ 0x3b, 0x21, 0x1a, 0x5b, 0x69, 0x16, 0xb9, 0xb7, 0xbd, 0x97, 0x02, 0xb6, 0x29, 0xba, 0xd7, 0x0c, + /*94d0:*/ 0xb0, 0x33, 0xba, 0x5a, 0x0d, 0xd2, 0xe6, 0x32, 0x70, 0xd9, 0x71, 0xa3, 0x59, 0xce, 0xe0, 0xac, + /*94e0:*/ 0x9f, 0x3d, 0xd3, 0xba, 0x2e, 0x3d, 0x70, 0x1c, 0x19, 0x9e, 0xa5, 0x34, 0xef, 0xf7, 0x93, 0xcd, + /*94f0:*/ 0x6f, 0xd1, 0xfd, 0x72, 0x76, 0x3a, 0x33, 0x5c, 0x54, 0xd9, 0x85, 0xbf, 0x72, 0xfd, 0x13, 0xf0, + /*9500:*/ 0x5d, 0x37, 0x35, 0x42, 0x1c, 0xd2, 0x41, 0x66, 0x1d, 0xcb, 0xf9, 0x76, 0xd9, 0x26, 0x3b, 0xb7, + /*9510:*/ 0xe7, 0xf6, 0x32, 0xa9, 0x26, 0xba, 0x25, 0x9c, 0x35, 0xa5, 0x80, 0x11, 0x3d, 0x0d, 0x43, 0x80, + /*9520:*/ 0xd1, 0x90, 0xba, 0xe1, 0xc8, 0x1c, 0xe4, 0x83, 0x08, 0xaa, 0xaf, 0x66, 0x8e, 0x33, 0x9a, 0x4a, + /*9530:*/ 0xdd, 0x79, 0xf6, 0xa7, 0xfa, 0x15, 0x59, 0x61, 0xf6, 0x35, 0xd8, 0x0b, 0xe4, 0x86, 0xbb, 0x74, + /*9540:*/ 0xfa, 0x6b, 0xa5, 0x4e, 0xf8, 0x41, 0xa7, 0xb4, 0x37, 0x82, 0x8e, 0x5b, 0x1c, 0x71, 0xe2, 0xe1, + /*9550:*/ 0x57, 0xa8, 0xa1, 0xc3, 0x18, 0x6f, 0xcb, 0x31, 0x2e, 0x28, 0x9d, 0x09, 0x33, 0x67, 0x9b, 0xaf, + /*9560:*/ 0x6f, 0x07, 0x18, 0x49, 0xd1, 0x78, 0x5d, 0x87, 0xdf, 0xb7, 0x62, 0x14, 0x00, 0x7e, 0xc7, 0xe8, + /*9570:*/ 0x7f, 0xbc, 0x6a, 0xd4, 0x4c, 0x91, 0xc6, 0xde, 0xd3, 0x89, 0xc8, 0xbf, 0x90, 0xda, 0x84, 0x0f, + /*9580:*/ 0x56, 0xdd, 0x95, 0xae, 0x92, 0x78, 0xf3, 0x93, 0xf0, 0x6c, 0x9e, 0xab, 0xf5, 0xb7, 0xb5, 0x99, + /*9590:*/ 0xf6, 0xb3, 0x94, 0x57, 0xd1, 0x96, 0x91, 0x60, 0x31, 0x0d, 0xa9, 0xf4, 0x67, 0x62, 0xa4, 0xd5, + /*95a0:*/ 0xf1, 0x5e, 0x15, 0xd8, 0xba, 0x27, 0x4c, 0x2d, 0x1f, 0x92, 0x0e, 0x8a, 0x51, 0x74, 0xdd, 0x8f, + /*95b0:*/ 0x27, 0x89, 0x9b, 0xba, 0x1b, 0x1a, 0x01, 0x1e, 0x9a, 0xb5, 0x77, 0x72, 0x8e, 0xde, 0x73, 0xbb, + /*95c0:*/ 0xe9, 0x6a, 0xa1, 0xeb, 0xa2, 0xab, 0x70, 0x7a, 0x34, 0x34, 0x4f, 0x86, 0x2f, 0x26, 0x4f, 0x39, + /*95d0:*/ 0xab, 0x57, 0x4f, 0x76, 0xed, 0xf8, 0x30, 0xc0, 0x21, 0xb5, 0x17, 0x03, 0x8e, 0xf1, 0x4c, 0xe2, + /*95e0:*/ 0x50, 0x6e, 0xf8, 0x95, 0xee, 0x19, 0xc9, 0xf0, 0x7c, 0x06, 0x9e, 0x3d, 0x69, 0xdf, 0x90, 0x03, + /*95f0:*/ 0xae, 0xfb, 0xc4, 0x34, 0x9e, 0x0a, 0x7d, 0x2e, 0x4d, 0xc5, 0x97, 0x18, 0x01, 0xb7, 0xfb, 0xd7, + /*9600:*/ 0x89, 0x81, 0xd8, 0xd7, 0x2c, 0x12, 0x29, 0xd4, 0x3f, 0xa7, 0xcc, 0x67, 0x9a, 0xed, 0x17, 0xb9, + /*9610:*/ 0xd8, 0x74, 0x27, 0x54, 0xa0, 0x11, 0x44, 0xe0, 0x64, 0xfe, 0xa2, 0x57, 0xf5, 0x63, 0x55, 0xdd, + /*9620:*/ 0x7b, 0x45, 0xea, 0xc2, 0x19, 0xad, 0x3d, 0x68, 0xb7, 0x94, 0x89, 0xa6, 0x6e, 0x28, 0xd2, 0xbc, + /*9630:*/ 0x09, 0xe4, 0x75, 0x37, 0xd4, 0x26, 0x4e, 0xf1, 0x6c, 0x8b, 0x5d, 0x16, 0x12, 0xfc, 0x10, 0xff, + /*9640:*/ 0x12, 0x33, 0xdb, 0xd9, 0x7b, 0x22, 0x55, 0x7b, 0xe7, 0xc4, 0x9c, 0xd7, 0x50, 0x87, 0xc5, 0xde, + /*9650:*/ 0x8d, 0xe0, 0x74, 0xc7, 0x03, 0x9f, 0x64, 0x7f, 0xf4, 0xfd, 0xbd, 0xed, 0x0c, 0x14, 0x8c, 0x2a, + /*9660:*/ 0xf9, 0x2e, 0x06, 0x6e, 0xb7, 0x2a, 0x3e, 0x61, 0x02, 0xce, 0x84, 0xd4, 0xb6, 0x02, 0xee, 0x47, + /*9670:*/ 0x13, 0x01, 0x8c, 0x78, 0x6d, 0x2b, 0xea, 0xa2, 0x74, 0x3f, 0x87, 0x2d, 0x42, 0xa1, 0x7a, 0x63, + /*9680:*/ 0x25, 0x81, 0x88, 0x65, 0x0a, 0x42, 0x52, 0xa1, 0x8f, 0xba, 0xf5, 0x32, 0x27, 0xdd, 0x87, 0x68, + /*9690:*/ 0x95, 0x0e, 0x6e, 0xb3, 0x04, 0xbb, 0x40, 0x5e, 0x65, 0x0e, 0x51, 0x4c, 0x2a, 0x9c, 0x5a, 0x2e, + /*96a0:*/ 0xc9, 0xed, 0xc0, 0xe1, 0xb5, 0x7e, 0x69, 0xcf, 0x4e, 0x16, 0xe3, 0x11, 0x8e, 0xef, 0xb9, 0x44, + /*96b0:*/ 0x6b, 0x79, 0x1a, 0xf2, 0x7a, 0x58, 0xe7, 0xd3, 0xbb, 0x95, 0x9e, 0x9a, 0x63, 0xa2, 0x3c, 0x8c, + /*96c0:*/ 0xd3, 0x4f, 0x7e, 0x08, 0xd5, 0x48, 0x8f, 0x6f, 0x6d, 0x14, 0x44, 0x9d, 0x82, 0x1e, 0x27, 0x1c, + /*96d0:*/ 0xb7, 0x0d, 0xb5, 0xc8, 0x4a, 0x9e, 0x1d, 0x45, 0x6c, 0x69, 0x8d, 0x8b, 0x46, 0x21, 0x36, 0x51, + /*96e0:*/ 0xb8, 0x41, 0x18, 0x2f, 0x3c, 0x1f, 0xe1, 0xeb, 0x34, 0xc3, 0x09, 0xb5, 0xe8, 0xd7, 0x78, 0x60, + /*96f0:*/ 0xd5, 0x6f, 0xe4, 0xb1, 0x01, 0x3e, 0xac, 0xbf, 0xaa, 0xfd, 0x1a, 0x33, 0x75, 0xc7, 0x11, 0x66, + /*9700:*/ 0xed, 0x08, 0x5e, 0xbc, 0xa4, 0xc2, 0x12, 0x3e, 0x9f, 0xac, 0xc4, 0xee, 0xfe, 0xb2, 0xdb, 0x0f, + /*9710:*/ 0x0d, 0x6a, 0x03, 0x63, 0xe8, 0x9a, 0xfe, 0xde, 0xe1, 0x30, 0xba, 0x98, 0x1d, 0x33, 0x5c, 0x94, + /*9720:*/ 0x07, 0x88, 0x25, 0x84, 0xbe, 0x9c, 0x01, 0x21, 0xc3, 0x27, 0x98, 0xdb, 0x69, 0xb4, 0xec, 0x17, + /*9730:*/ 0x21, 0x15, 0x40, 0xbc, 0x54, 0xb3, 0xda, 0x62, 0x73, 0x09, 0x64, 0x6a, 0x41, 0x23, 0x8d, 0x47, + /*9740:*/ 0x19, 0xf7, 0x30, 0xe7, 0xb4, 0x2c, 0x60, 0xcb, 0x8c, 0xf3, 0xc4, 0xd8, 0xc5, 0x38, 0xba, 0xf7, + /*9750:*/ 0xf7, 0xe8, 0x1a, 0x07, 0x9c, 0xde, 0x82, 0x1c, 0x0f, 0xf9, 0x38, 0x4f, 0x32, 0xc0, 0x6c, 0x3d, + /*9760:*/ 0x4d, 0x90, 0x04, 0x0a, 0xe6, 0x34, 0xa9, 0x1d, 0xf6, 0x00, 0x97, 0xd8, 0x07, 0x8b, 0xfa, 0x3d, + /*9770:*/ 0x65, 0x0f, 0x31, 0x24, 0xd9, 0xf9, 0xdb, 0xc4, 0xbd, 0x6d, 0x14, 0xc5, 0x97, 0xdf, 0x6d, 0x22, + /*9780:*/ 0x82, 0x7b, 0x9d, 0x2e, 0x40, 0x53, 0x71, 0x0c, 0xde, 0x63, 0xe3, 0xf0, 0x50, 0xb9, 0x00, 0x99, + /*9790:*/ 0x76, 0x75, 0x3c, 0x90, 0x2d, 0x17, 0xb9, 0xed, 0x04, 0xcf, 0x14, 0x78, 0x8b, 0xe2, 0xcc, 0x7f, + /*97a0:*/ 0xa9, 0x49, 0xb0, 0x5d, 0x04, 0x64, 0xe4, 0x72, 0x55, 0x39, 0x1a, 0x9e, 0x88, 0xd4, 0x23, 0x9c, + /*97b0:*/ 0x04, 0xbf, 0xe0, 0x9b, 0xdf, 0xeb, 0x68, 0x6c, 0xc7, 0x04, 0xef, 0x6c, 0xb7, 0x6f, 0xd6, 0xff, + /*97c0:*/ 0xfe, 0x63, 0xeb, 0x9c, 0xc9, 0x7b, 0xfe, 0x30, 0x15, 0xce, 0x6c, 0xd2, 0x6f, 0xcc, 0x64, 0x5c, + /*97d0:*/ 0x76, 0x65, 0x45, 0xa6, 0x17, 0x85, 0x6c, 0xc5, 0x27, 0x2f, 0xd7, 0x16, 0x9e, 0xb7, 0x56, 0xb2, + /*97e0:*/ 0xb0, 0x72, 0x83, 0x5e, 0xde, 0xba, 0x80, 0xf1, 0x06, 0xe3, 0xaf, 0xcb, 0xad, 0xd8, 0x6b, 0xdd, + /*97f0:*/ 0x4a, 0xa9, 0xb6, 0x19, 0x48, 0x10, 0x50, 0xb7, 0xeb, 0x0a, 0x85, 0xa8, 0x9e, 0xbd, 0x10, 0x63, + /*9800:*/ 0x6c, 0x14, 0x33, 0x0a, 0x90, 0x63, 0x1f, 0xda, 0x0b, 0x1d, 0x19, 0xee, 0xf6, 0x20, 0xc5, 0x0c, + /*9810:*/ 0x79, 0x2d, 0x38, 0xbb, 0xdc, 0x38, 0x86, 0x4e, 0xce, 0x64, 0x1e, 0xfb, 0xfd, 0xbf, 0x8e, 0xa6, + /*9820:*/ 0x16, 0xec, 0xd9, 0x7b, 0x69, 0xb9, 0xc3, 0x96, 0x4a, 0x86, 0x43, 0x02, 0xf6, 0x74, 0xb5, 0x5f, + /*9830:*/ 0xb8, 0x39, 0xb1, 0x83, 0x40, 0x45, 0x72, 0xd8, 0xe9, 0x64, 0x81, 0x6a, 0xeb, 0x19, 0xbb, 0x42, + /*9840:*/ 0x61, 0xba, 0x45, 0x42, 0x47, 0x81, 0xe9, 0x19, 0x34, 0xdd, 0x80, 0x3e, 0xb9, 0x2c, 0x00, 0xad, + /*9850:*/ 0x0e, 0x3c, 0x71, 0x0b, 0xea, 0x1f, 0xf8, 0xa5, 0x38, 0x68, 0x66, 0x01, 0xa0, 0x70, 0xf4, 0x41, + /*9860:*/ 0x96, 0xa7, 0xb1, 0xae, 0x3c, 0xd9, 0xfd, 0x10, 0xb8, 0x4a, 0x70, 0x7b, 0x94, 0x00, 0xe8, 0xb6, + /*9870:*/ 0xa5, 0x24, 0xac, 0xa3, 0x5a, 0xd8, 0x6f, 0xa5, 0x48, 0x26, 0xd8, 0x7b, 0x4c, 0x5c, 0x30, 0x8b, + /*9880:*/ 0x6b, 0x55, 0x8a, 0x7b, 0x1b, 0xc8, 0xce, 0x9b, 0x7a, 0xc1, 0x36, 0xe7, 0x9a, 0x58, 0xe8, 0xc7, + /*9890:*/ 0x14, 0x8b, 0x01, 0x5f, 0x13, 0x04, 0x4c, 0x10, 0x43, 0x44, 0x33, 0x44, 0xe2, 0x60, 0xb6, 0x47, + /*98a0:*/ 0xca, 0x0a, 0x2e, 0x90, 0xa7, 0x49, 0xfc, 0x06, 0x3d, 0xf2, 0x4f, 0xd2, 0x69, 0x69, 0x6c, 0x0b, + /*98b0:*/ 0xe4, 0x37, 0x2a, 0x60, 0x8a, 0x8c, 0x0f, 0x33, 0xa9, 0xb1, 0xb3, 0xc8, 0xe6, 0x82, 0xa8, 0xaf, + /*98c0:*/ 0x56, 0x17, 0xc7, 0x77, 0xf6, 0xc9, 0xb2, 0x27, 0x79, 0x7e, 0xec, 0x3c, 0xba, 0xc4, 0x3b, 0x0f, + /*98d0:*/ 0x4f, 0xf4, 0x22, 0x13, 0x4c, 0x20, 0xda, 0xfb, 0xaf, 0x56, 0xae, 0x51, 0x27, 0x54, 0x15, 0x80, + /*98e0:*/ 0x85, 0x94, 0xb7, 0x97, 0x82, 0x8b, 0xef, 0xcf, 0x4a, 0xbf, 0xb8, 0x18, 0x2c, 0x37, 0x59, 0x8d, + /*98f0:*/ 0x32, 0xed, 0x94, 0x78, 0x56, 0x01, 0x05, 0xc0, 0xfe, 0x6f, 0x8c, 0x60, 0x7e, 0x77, 0xee, 0xc0, + /*9900:*/ 0xa8, 0x3f, 0x8d, 0xb9, 0x7d, 0x19, 0x8e, 0x95, 0xf8, 0xbe, 0xc5, 0xe8, 0x57, 0xbd, 0x3c, 0xfc, + /*9910:*/ 0x9b, 0xfd, 0x72, 0x44, 0xf4, 0x42, 0x2d, 0xcb, 0x8c, 0x81, 0x8c, 0x3b, 0x0c, 0xfe, 0x05, 0x42, + /*9920:*/ 0x55, 0xeb, 0xb9, 0x30, 0x27, 0xc5, 0x4c, 0x1b, 0x79, 0xd5, 0x9e, 0x2e, 0x50, 0x25, 0x08, 0x62, + /*9930:*/ 0xcc, 0x75, 0x72, 0x33, 0x26, 0xc3, 0xcd, 0x86, 0xb0, 0xe4, 0xee, 0xea, 0xd6, 0x2d, 0x57, 0xd3, + /*9940:*/ 0x80, 0x9c, 0xef, 0x9d, 0x78, 0x6d, 0x96, 0x28, 0xac, 0xed, 0x27, 0xea, 0x62, 0xbd, 0x8d, 0x9e, + /*9950:*/ 0x20, 0x2b, 0xc4, 0xe4, 0x3d, 0x61, 0x68, 0xff, 0x5c, 0x5d, 0x47, 0x44, 0x40, 0x4c, 0x9a, 0x47, + /*9960:*/ 0xa0, 0x24, 0x16, 0x1e, 0x88, 0xd5, 0x86, 0x29, 0x96, 0x0c, 0x4f, 0x13, 0x1f, 0x2c, 0x03, 0x98, + /*9970:*/ 0x56, 0xd9, 0x46, 0xe5, 0x18, 0x83, 0xed, 0x85, 0xd9, 0x8a, 0x8a, 0x88, 0xe6, 0x19, 0xf2, 0x7b, + /*9980:*/ 0xe4, 0x68, 0x3d, 0xfc, 0xbd, 0x71, 0x27, 0x22, 0xf4, 0x60, 0x51, 0x30, 0x52, 0x99, 0x43, 0x88, + /*9990:*/ 0x42, 0xa4, 0xe8, 0x16, 0xf2, 0x17, 0x3a, 0xd7, 0x2b, 0x85, 0x49, 0x53, 0x50, 0x14, 0x51, 0xd3, + /*99a0:*/ 0x4c, 0x85, 0xcc, 0x80, 0x1e, 0x49, 0x18, 0xb8, 0x3c, 0x3e, 0x1c, 0xbe, 0x56, 0x07, 0xf7, 0xc7, + /*99b0:*/ 0x9f, 0xda, 0xce, 0x00, 0x93, 0xe6, 0xa1, 0xda, 0xf1, 0x45, 0x7b, 0x3f, 0x26, 0x9c, 0xb6, 0xe8, + /*99c0:*/ 0xfb, 0xce, 0x3b, 0x85, 0x64, 0xf5, 0x85, 0x9c, 0x34, 0x4f, 0x89, 0x44, 0x52, 0x69, 0x99, 0xc9, + /*99d0:*/ 0x5d, 0x87, 0x52, 0x2c, 0xd3, 0x3a, 0x6e, 0x5c, 0x02, 0x41, 0x5c, 0x03, 0xa8, 0xfb, 0xcd, 0x82, + /*99e0:*/ 0xe6, 0xd7, 0xe2, 0x90, 0x06, 0x9e, 0x4f, 0xbc, 0x53, 0x79, 0x24, 0xd9, 0x20, 0xb6, 0x5f, 0xa6, + /*99f0:*/ 0x0d, 0x88, 0x85, 0xbe, 0x19, 0xe4, 0x1f, 0x95, 0xf8, 0x94, 0x6e, 0x01, 0x9d, 0xc0, 0xef, 0x18, + /*9a00:*/ 0xaf, 0xda, 0xac, 0x64, 0x8c, 0x7a, 0x84, 0x6d, 0x45, 0xa4, 0x34, 0x66, 0x9b, 0x81, 0xab, 0x69, + /*9a10:*/ 0x19, 0x49, 0x6c, 0xa8, 0xc6, 0x8b, 0x3b, 0xbd, 0xff, 0x27, 0x23, 0x48, 0xa6, 0x6b, 0xa9, 0x30, + /*9a20:*/ 0xf0, 0xbb, 0xe4, 0x08, 0x3d, 0x52, 0x21, 0x70, 0xbc, 0x42, 0x45, 0x92, 0xf7, 0x0c, 0x83, 0x33, + /*9a30:*/ 0x9f, 0x38, 0x28, 0x1b, 0xb3, 0xf2, 0xc4, 0x38, 0x24, 0x03, 0xfd, 0xa9, 0x18, 0x60, 0x54, 0xcc, + /*9a40:*/ 0xc1, 0xb0, 0x78, 0x8e, 0x99, 0x64, 0x9c, 0xeb, 0x02, 0xbc, 0x63, 0x7b, 0xd6, 0x03, 0x6d, 0xcb, + /*9a50:*/ 0x1f, 0x6f, 0x34, 0x59, 0xe6, 0x7e, 0xb0, 0x10, 0xbb, 0x5d, 0xe6, 0xfa, 0x66, 0xbe, 0x14, 0x10, + /*9a60:*/ 0xca, 0xd1, 0x3f, 0x99, 0x4c, 0x04, 0xfb, 0x56, 0x64, 0xec, 0x2e, 0x07, 0x61, 0x05, 0x9c, 0x8c, + /*9a70:*/ 0x1a, 0xc4, 0x34, 0x1d, 0xbf, 0x33, 0x69, 0x38, 0x9f, 0xa4, 0x9e, 0xbd, 0xc6, 0x4d, 0x49, 0xe4, + /*9a80:*/ 0xf3, 0xc5, 0x38, 0xb4, 0xb7, 0xa3, 0x0a, 0x49, 0x67, 0x9e, 0x79, 0xf0, 0xa7, 0x4c, 0x91, 0xf7, + /*9a90:*/ 0x42, 0x88, 0xc1, 0x4f, 0x01, 0xa0, 0x43, 0x6e, 0x39, 0xbd, 0x96, 0x07, 0x3e, 0xab, 0x70, 0x56, + /*9aa0:*/ 0x54, 0xe1, 0xc9, 0xa2, 0x9a, 0x98, 0xb9, 0xd6, 0x3c, 0x17, 0xa9, 0xbe, 0xc5, 0xe2, 0x36, 0x18, + /*9ab0:*/ 0xf4, 0x15, 0x9d, 0x0b, 0xa2, 0x66, 0x87, 0x79, 0x45, 0x6d, 0x24, 0x09, 0xa0, 0xcd, 0x87, 0xdc, + /*9ac0:*/ 0x3d, 0x69, 0x16, 0x6b, 0xef, 0xf4, 0x3b, 0x04, 0x34, 0x84, 0xf1, 0x19, 0x8c, 0x73, 0x90, 0xf0, + /*9ad0:*/ 0xde, 0xfb, 0xcf, 0x48, 0x44, 0x41, 0xf9, 0x81, 0xb3, 0xa7, 0x0a, 0xc2, 0xd4, 0x8c, 0x84, 0x9a, + /*9ae0:*/ 0x6a, 0x1c, 0x34, 0x63, 0x96, 0x0a, 0xe0, 0xc6, 0x10, 0x88, 0x8f, 0x8e, 0xac, 0x96, 0xee, 0xc0, + /*9af0:*/ 0x86, 0x16, 0x61, 0x8f, 0x35, 0xec, 0x47, 0x4e, 0x75, 0x17, 0x49, 0x0e, 0x3f, 0x34, 0x68, 0x7e, + /*9b00:*/ 0xae, 0x61, 0x0e, 0x7e, 0xd2, 0x81, 0x53, 0xd1, 0x53, 0x7a, 0x20, 0x7a, 0x40, 0x7a, 0x2e, 0xbc, + /*9b10:*/ 0x43, 0x3a, 0x66, 0x39, 0x0f, 0xc1, 0x85, 0xc0, 0x71, 0xe0, 0x15, 0x28, 0x47, 0xb5, 0xd1, 0x99, + /*9b20:*/ 0x6e, 0xd3, 0x48, 0xe0, 0x41, 0xa7, 0xf3, 0x27, 0x8f, 0xda, 0x55, 0x5f, 0x89, 0x0f, 0x9b, 0x91, + /*9b30:*/ 0xe9, 0x1f, 0x9b, 0x5e, 0x32, 0x53, 0x3e, 0x8c, 0x65, 0xd5, 0x92, 0x0b, 0x8c, 0x5f, 0x73, 0xcc, + /*9b40:*/ 0x0d, 0xc5, 0xa7, 0x1c, 0x80, 0x85, 0xca, 0xbc, 0x00, 0xf6, 0x73, 0x07, 0x9b, 0xb4, 0x93, 0x48, + /*9b50:*/ 0x22, 0xe3, 0xf9, 0x63, 0x9d, 0xe5, 0x82, 0x17, 0x3e, 0x65, 0x2b, 0x4f, 0x68, 0xc3, 0xc3, 0x6d, + /*9b60:*/ 0x8d, 0x9a, 0x5e, 0x47, 0xe6, 0x1f, 0x99, 0x94, 0xab, 0xd6, 0xc2, 0xeb, 0x05, 0x70, 0x23, 0x7a, + /*9b70:*/ 0x6b, 0xbd, 0xc0, 0x1d, 0xe2, 0x22, 0xa9, 0xb5, 0x56, 0xcb, 0x93, 0x2c, 0x88, 0xed, 0xd9, 0xbf, + /*9b80:*/ 0x14, 0x44, 0xb3, 0x99, 0xe2, 0x58, 0x2d, 0x78, 0x53, 0xc3, 0xbf, 0x94, 0xd0, 0x57, 0x95, 0xec, + /*9b90:*/ 0x25, 0xe2, 0x51, 0xb4, 0x6f, 0x2d, 0xf9, 0xb4, 0x15, 0x32, 0xa4, 0x20, 0xf8, 0x7e, 0x47, 0x65, + /*9ba0:*/ 0xc8, 0xb2, 0x95, 0xad, 0x41, 0xd5, 0x91, 0xbb, 0xd7, 0x66, 0x2c, 0x96, 0x7d, 0x78, 0x85, 0x3c, + /*9bb0:*/ 0x72, 0x21, 0x9d, 0xe4, 0x4a, 0x4a, 0x4f, 0x29, 0x76, 0x24, 0x82, 0x83, 0xb8, 0x19, 0x1b, 0x5a, + /*9bc0:*/ 0x1f, 0x13, 0x76, 0xc2, 0xe3, 0x69, 0x75, 0xea, 0x4a, 0xb0, 0xbd, 0x34, 0x87, 0x0c, 0xe3, 0xda, + /*9bd0:*/ 0x14, 0xce, 0x42, 0x65, 0x42, 0xed, 0x9a, 0x7f, 0x69, 0x83, 0x55, 0xa4, 0xbf, 0xd5, 0x91, 0xa9, + /*9be0:*/ 0x00, 0x57, 0xa1, 0x24, 0x8d, 0xd8, 0x01, 0xf7, 0x5a, 0x76, 0xf8, 0x15, 0x14, 0x80, 0xd0, 0x8e, + /*9bf0:*/ 0x26, 0xbb, 0x5c, 0x5b, 0x6b, 0x62, 0x5c, 0xa4, 0x75, 0xe2, 0x01, 0xd1, 0x46, 0x9b, 0x7f, 0x7f, + /*9c00:*/ 0x16, 0xd1, 0xa0, 0xfa, 0x4f, 0x8e, 0x3d, 0xe4, 0xe0, 0xab, 0xc4, 0x25, 0x7f, 0x3a, 0x1b, 0x17, + /*9c10:*/ 0x3a, 0x99, 0xff, 0xa6, 0x54, 0xce, 0x8d, 0x7c, 0xa6, 0x4a, 0xce, 0x6f, 0x98, 0xe3, 0x1d, 0x84, + /*9c20:*/ 0x8b, 0x74, 0xf7, 0x01, 0x99, 0x05, 0x21, 0xce, 0x4d, 0x0f, 0x4c, 0x91, 0x40, 0x24, 0xf4, 0x78, + /*9c30:*/ 0xec, 0x90, 0xc9, 0xca, 0xc2, 0x63, 0x97, 0x84, 0x56, 0x21, 0x88, 0x57, 0xc2, 0xc0, 0x9d, 0xbd, + /*9c40:*/ 0x78, 0xc8, 0x69, 0x9a, 0x00, 0xd0, 0xaa, 0x65, 0x9a, 0x74, 0x06, 0xf1, 0x66, 0x15, 0xcc, 0xf2, + /*9c50:*/ 0x2a, 0x6a, 0xc1, 0xf3, 0x02, 0x6e, 0x08, 0xc4, 0xea, 0x54, 0x55, 0x05, 0x86, 0xeb, 0x19, 0x4a, + /*9c60:*/ 0xa3, 0xee, 0xa7, 0x1a, 0x3c, 0x93, 0x34, 0x07, 0x91, 0x72, 0x36, 0xbd, 0xb7, 0x54, 0xc5, 0x05, + /*9c70:*/ 0xdb, 0xe3, 0xe6, 0x5d, 0x48, 0x58, 0x16, 0x23, 0xed, 0x21, 0x9e, 0xe6, 0xed, 0xb4, 0x8f, 0x75, + /*9c80:*/ 0x8d, 0x5b, 0x9a, 0x16, 0x65, 0x9e, 0x5f, 0xb9, 0xff, 0xc9, 0xcd, 0xd0, 0xa8, 0xd3, 0x36, 0x3e, + /*9c90:*/ 0x36, 0x67, 0x30, 0xf5, 0xd8, 0xbe, 0x1c, 0xe3, 0x30, 0x9e, 0x0c, 0x1b, 0x06, 0x6d, 0x34, 0x07, + /*9ca0:*/ 0x73, 0x56, 0x08, 0xff, 0xaa, 0x12, 0x5b, 0x46, 0x54, 0x57, 0xb5, 0x3d, 0x56, 0x95, 0x09, 0x9f, + /*9cb0:*/ 0x40, 0x99, 0x96, 0x83, 0x58, 0xbb, 0xcc, 0x88, 0x1a, 0x62, 0xbd, 0xb7, 0xaa, 0x27, 0x9a, 0xf7, + /*9cc0:*/ 0xd1, 0x23, 0x3c, 0xa7, 0x5f, 0x82, 0x20, 0x91, 0x0c, 0xa5, 0x4c, 0xda, 0x74, 0xf8, 0x0e, 0x59, + /*9cd0:*/ 0x68, 0x13, 0xd6, 0x07, 0xe2, 0x4e, 0x57, 0x5c, 0xd3, 0xb5, 0xb9, 0x11, 0xaa, 0x45, 0x74, 0xf2, + /*9ce0:*/ 0xf4, 0x37, 0x37, 0xff, 0x45, 0x6c, 0x51, 0x1d, 0xfe, 0xf0, 0x12, 0x40, 0x57, 0x6f, 0x41, 0x93, + /*9cf0:*/ 0xb0, 0x7c, 0xd3, 0x5d, 0xe4, 0x10, 0x0c, 0xe2, 0xfa, 0x90, 0xa9, 0x68, 0xf9, 0x41, 0xd4, 0x71, + /*9d00:*/ 0x2e, 0x46, 0xfb, 0x78, 0xca, 0xa6, 0x44, 0xec, 0xbf, 0xfb, 0x33, 0xea, 0xcd, 0x46, 0x64, 0xf0, + /*9d10:*/ 0x1e, 0x5a, 0x3a, 0x3a, 0xbe, 0x7f, 0x83, 0x94, 0xb2, 0x11, 0xb1, 0x32, 0x14, 0x05, 0xc0, 0xa0, + /*9d20:*/ 0x87, 0x7f, 0xb7, 0xf2, 0xe9, 0x08, 0xcb, 0x1f, 0x5d, 0x87, 0x30, 0xec, 0x05, 0xcf, 0xaa, 0x01, + /*9d30:*/ 0x2f, 0x23, 0x0d, 0x81, 0xde, 0x30, 0x8e, 0x03, 0x0e, 0x44, 0x6e, 0x62, 0xb9, 0x6e, 0x7c, 0x0e, + /*9d40:*/ 0x0a, 0x00, 0x63, 0xea, 0xb9, 0xbd, 0x9b, 0x8e, 0x1a, 0x3c, 0xb4, 0xff, 0xae, 0xd4, 0x15, 0x18, + /*9d50:*/ 0xe6, 0x0f, 0xfe, 0x28, 0x6e, 0xdc, 0x76, 0x2a, 0xf5, 0xd4, 0x14, 0xd8, 0x8c, 0x76, 0x35, 0xa8, + /*9d60:*/ 0x85, 0x38, 0x55, 0xfe, 0xc3, 0x83, 0xd5, 0xaa, 0x58, 0x92, 0xb8, 0x82, 0x45, 0x9c, 0xe5, 0x92, + /*9d70:*/ 0xd4, 0x11, 0xc9, 0xf9, 0xab, 0x5b, 0x9c, 0x77, 0xb3, 0xbe, 0x3f, 0x65, 0x89, 0xbd, 0x1d, 0xdf, + /*9d80:*/ 0x89, 0x64, 0xe3, 0x0b, 0xf4, 0xc8, 0xf2, 0xe1, 0x23, 0xbf, 0x13, 0x81, 0x33, 0x92, 0x94, 0x75, + /*9d90:*/ 0x1b, 0xd1, 0xfc, 0x34, 0xee, 0x54, 0xdc, 0x3c, 0x40, 0xf4, 0x5d, 0xdd, 0x64, 0xd5, 0xb0, 0xdf, + /*9da0:*/ 0x6a, 0xb6, 0x3b, 0x92, 0x71, 0x06, 0x33, 0xf7, 0xba, 0x9b, 0x4a, 0x79, 0x91, 0x31, 0x17, 0x86, + /*9db0:*/ 0x35, 0x37, 0x8f, 0x62, 0x57, 0x43, 0xe7, 0x72, 0x32, 0x56, 0x91, 0x41, 0xd5, 0xc9, 0x27, 0x54, + /*9dc0:*/ 0x7e, 0x61, 0x7b, 0x36, 0x15, 0x2d, 0xbd, 0x4d, 0x9f, 0x51, 0xfd, 0x85, 0x8d, 0x00, 0x91, 0xe3, + /*9dd0:*/ 0x64, 0xb1, 0x8b, 0x51, 0xbe, 0x0e, 0x5d, 0xdb, 0x41, 0x79, 0xec, 0x11, 0x95, 0xa7, 0xfa, 0x4b, + /*9de0:*/ 0xd3, 0x55, 0x98, 0xb2, 0xd2, 0x51, 0xfe, 0x51, 0x35, 0x9c, 0x22, 0x3e, 0x25, 0x91, 0x42, 0xc3, + /*9df0:*/ 0xb0, 0x75, 0x05, 0xeb, 0xf2, 0xcb, 0x7d, 0xaa, 0xb6, 0x4b, 0x82, 0x12, 0xc2, 0x88, 0xf9, 0x78, + /*9e00:*/ 0xf6, 0x01, 0x30, 0x50, 0x38, 0x6a, 0xcb, 0xb1, 0xf1, 0x27, 0xcb, 0xf7, 0xd3, 0xe1, 0x43, 0xf3, + /*9e10:*/ 0x9e, 0x8c, 0x92, 0xab, 0xcd, 0xa7, 0x03, 0xc3, 0xd0, 0x9c, 0x91, 0x8b, 0x2d, 0xde, 0xbc, 0x50, + /*9e20:*/ 0x63, 0x95, 0x4b, 0x7e, 0xda, 0xf4, 0x72, 0xe3, 0xcc, 0x2c, 0x35, 0x5d, 0x2c, 0xd0, 0x4b, 0x54, + /*9e30:*/ 0xaf, 0xf4, 0x42, 0x0e, 0xd4, 0x8a, 0x66, 0x56, 0x83, 0xd9, 0x5e, 0x1d, 0x81, 0xd3, 0xce, 0xad, + /*9e40:*/ 0x61, 0xca, 0x20, 0xe6, 0xc3, 0x17, 0xef, 0x4b, 0xbe, 0xf0, 0xbc, 0xda, 0xb3, 0x79, 0xb5, 0xcb, + /*9e50:*/ 0x38, 0x67, 0x2a, 0x17, 0x4f, 0xda, 0xfc, 0x1a, 0x87, 0x8d, 0xc3, 0x73, 0x87, 0x65, 0xf6, 0x03, + /*9e60:*/ 0xc9, 0xf0, 0xab, 0x2c, 0x6f, 0xae, 0x90, 0x15, 0x10, 0xf1, 0x8d, 0x90, 0x05, 0x1a, 0x27, 0x72, + /*9e70:*/ 0x2d, 0x2d, 0xfb, 0x1b, 0xec, 0x9a, 0x90, 0x21, 0x08, 0xb6, 0x58, 0x57, 0xb3, 0x3d, 0xb1, 0x29, + /*9e80:*/ 0x00, 0x62, 0x95, 0x68, 0x6b, 0x5b, 0xfb, 0x98, 0x6e, 0xbb, 0x9c, 0x53, 0x03, 0xd3, 0xda, 0x91, + /*9e90:*/ 0xac, 0xec, 0x1c, 0x4e, 0x56, 0xbb, 0x50, 0xe3, 0x23, 0xc0, 0x01, 0x63, 0x45, 0x01, 0xff, 0x30, + /*9ea0:*/ 0x6e, 0x6f, 0xe9, 0x60, 0xed, 0xab, 0x89, 0x5c, 0xcf, 0x0a, 0x89, 0x13, 0x39, 0x2a, 0xa6, 0x93, + /*9eb0:*/ 0x18, 0xc8, 0x26, 0xd3, 0x23, 0x8c, 0x22, 0xa4, 0x3c, 0xde, 0xe7, 0x7d, 0x9c, 0x5c, 0x35, 0x4c, + /*9ec0:*/ 0xb1, 0x6e, 0xfc, 0x19, 0xaa, 0x5a, 0x17, 0xad, 0x22, 0x75, 0x3e, 0x83, 0xa7, 0x7e, 0x72, 0xe0, + /*9ed0:*/ 0xaa, 0x75, 0x37, 0x2a, 0xd0, 0xd3, 0x8f, 0xbf, 0x20, 0x0b, 0x3e, 0xff, 0xea, 0x0b, 0x3c, 0x20, + /*9ee0:*/ 0x33, 0x6b, 0x28, 0xc8, 0x67, 0x85, 0x97, 0x61, 0x5f, 0x48, 0xaf, 0x38, 0x38, 0x07, 0x41, 0x6a, + /*9ef0:*/ 0x5e, 0x5a, 0x39, 0x4e, 0x45, 0xc6, 0xb5, 0x8f, 0xea, 0x78, 0x47, 0x51, 0x83, 0xb2, 0x98, 0xd1, + /*9f00:*/ 0x43, 0x0f, 0xc4, 0xaf, 0xad, 0xf4, 0x95, 0xe5, 0xc8, 0x6f, 0x48, 0x50, 0x83, 0x7c, 0xd4, 0xb9, + /*9f10:*/ 0x13, 0x7b, 0x60, 0x41, 0xf9, 0x2f, 0xe0, 0x31, 0x5f, 0x3f, 0x20, 0xce, 0x6f, 0xcd, 0x94, 0x0a, + /*9f20:*/ 0xd5, 0x0b, 0x01, 0x09, 0x5f, 0x1d, 0x43, 0x0a, 0x35, 0x05, 0x6b, 0xe6, 0x0a, 0x48, 0xb1, 0xa7, + /*9f30:*/ 0xe5, 0x03, 0x7f, 0x6b, 0xfe, 0xcc, 0xdf, 0x88, 0xbc, 0xde, 0x8f, 0x1f, 0xad, 0x77, 0xb0, 0xe9, + /*9f40:*/ 0x53, 0x1f, 0xad, 0xb0, 0x81, 0x9f, 0xa6, 0x9f, 0x7e, 0x36, 0x8e, 0xed, 0xba, 0xa9, 0x07, 0x78, + /*9f50:*/ 0x2f, 0xea, 0xdb, 0x66, 0x63, 0x32, 0x47, 0xbf, 0x38, 0xfe, 0x6b, 0xa8, 0x29, 0x27, 0x0a, 0x41, + /*9f60:*/ 0x0b, 0x84, 0x11, 0xcf, 0x5c, 0x57, 0x0f, 0x2a, 0xbc, 0x6f, 0xc8, 0xa8, 0x55, 0x19, 0xd8, 0xd0, + /*9f70:*/ 0x7c, 0xec, 0x19, 0x72, 0x50, 0xfa, 0x86, 0xf8, 0xa9, 0x1e, 0xb7, 0xa3, 0x96, 0xe2, 0x58, 0x17, + /*9f80:*/ 0x1c, 0xc9, 0x95, 0x38, 0x9e, 0x94, 0x9e, 0x16, 0xe1, 0x69, 0xe7, 0xea, 0xf2, 0x49, 0x5f, 0x9a, + /*9f90:*/ 0x64, 0x42, 0x5e, 0x7b, 0xb5, 0x4b, 0x5c, 0x29, 0x23, 0x84, 0xaf, 0xa3, 0x41, 0x54, 0xd2, 0x9e, + /*9fa0:*/ 0x25, 0x1d, 0x19, 0x1a, 0x86, 0x1d, 0xa5, 0xb4, 0xc6, 0x8f, 0x81, 0x1f, 0x06, 0xed, 0xb8, 0xee, + /*9fb0:*/ 0x1b, 0xf0, 0xb6, 0x78, 0xd1, 0x00, 0x85, 0x81, 0xff, 0xde, 0xdb, 0xc1, 0x6c, 0xb9, 0xdc, 0xb3, + /*9fc0:*/ 0x45, 0x16, 0x5f, 0xaf, 0x54, 0x17, 0xef, 0x0b, 0x98, 0x33, 0x29, 0xb5, 0x4a, 0xfb, 0x3d, 0x19, + /*9fd0:*/ 0x0d, 0x74, 0x8b, 0xee, 0x20, 0x94, 0x80, 0x59, 0xac, 0x93, 0xba, 0x50, 0x8a, 0x7b, 0xff, 0xd1, + /*9fe0:*/ 0xad, 0x7e, 0x91, 0x79, 0xcb, 0xb1, 0x64, 0x58, 0x55, 0x2a, 0xf8, 0xc4, 0xcd, 0x9b, 0xdc, 0x4c, + /*9ff0:*/ 0x17, 0x61, 0x19, 0x99, 0x54, 0x30, 0x20, 0x6b, 0xe9, 0xc8, 0xad, 0x1f, 0xcf, 0x61, 0x18, 0x5f, + /*a000:*/ 0x1d, 0x2d, 0xb1, 0xb6, 0xbf, 0xd9, 0xee, 0x38, 0x22, 0xd1, 0xd4, 0xad, 0xe7, 0xe4, 0xb3, 0xcd, + /*a010:*/ 0x65, 0x9c, 0x45, 0xcf, 0x2b, 0xe0, 0xde, 0x2c, 0x3a, 0x53, 0x1f, 0x98, 0x10, 0xf5, 0x15, 0xd8, + /*a020:*/ 0x53, 0xa4, 0x3c, 0x46, 0x00, 0x53, 0xab, 0x9b, 0x4f, 0x92, 0xb8, 0x70, 0x84, 0x24, 0xa7, 0xaf, + /*a030:*/ 0xe3, 0x0a, 0x5f, 0x89, 0x10, 0xa1, 0x72, 0x3d, 0x68, 0x14, 0x1d, 0xb9, 0x16, 0x4e, 0x6c, 0x19, + /*a040:*/ 0x43, 0x95, 0x83, 0xb8, 0x18, 0x61, 0x4d, 0x20, 0x6d, 0xb9, 0x97, 0x6b, 0x44, 0xe4, 0x9b, 0x2c, + /*a050:*/ 0xb5, 0x5a, 0xdd, 0xd5, 0xd1, 0x6a, 0xdf, 0x19, 0xf7, 0xb0, 0x5a, 0x09, 0xc1, 0x55, 0x3e, 0x88, + /*a060:*/ 0xbe, 0xa5, 0x49, 0x20, 0x95, 0x7f, 0xcb, 0x97, 0x5b, 0x51, 0x4d, 0xb0, 0x77, 0x89, 0xab, 0x4d, + /*a070:*/ 0xfc, 0x88, 0x20, 0x25, 0x68, 0x38, 0x6a, 0xb9, 0x5d, 0x0b, 0x9a, 0xe6, 0x96, 0xeb, 0x64, 0x66, + /*a080:*/ 0x1f, 0x7b, 0xb0, 0x2f, 0x35, 0xb6, 0x45, 0x25, 0x46, 0x09, 0x70, 0x98, 0xf8, 0xdc, 0x47, 0x14, + /*a090:*/ 0x7d, 0x61, 0xfa, 0x6e, 0x4e, 0x7c, 0x4f, 0x42, 0xe3, 0xaa, 0x1a, 0xf7, 0x44, 0xa8, 0x4a, 0x85, + /*a0a0:*/ 0xa5, 0xcc, 0x07, 0x7c, 0x2a, 0x23, 0xab, 0x1d, 0xf7, 0xa0, 0xd5, 0xd9, 0x9b, 0xfc, 0xf9, 0x9b, + /*a0b0:*/ 0xec, 0x93, 0xd4, 0x03, 0x86, 0x1d, 0x0b, 0x02, 0x82, 0xde, 0x06, 0xb3, 0xd1, 0x58, 0x03, 0xf1, + /*a0c0:*/ 0xbd, 0x8f, 0xf8, 0xc9, 0x39, 0x9d, 0xce, 0x16, 0x54, 0xb0, 0x42, 0x8b, 0xac, 0x08, 0x5c, 0xfb, + /*a0d0:*/ 0x0c, 0xcb, 0x79, 0xfc, 0x65, 0xe0, 0xe6, 0x54, 0xcd, 0x39, 0x6d, 0x3d, 0x67, 0x69, 0xf4, 0xb6, + /*a0e0:*/ 0x0d, 0x51, 0xb2, 0x3b, 0xc0, 0x61, 0x97, 0xde, 0xbd, 0x7f, 0x0a, 0xe0, 0xb0, 0xd7, 0x46, 0x21, + /*a0f0:*/ 0xb4, 0xa5, 0x9b, 0x96, 0x3c, 0xf5, 0x75, 0x39, 0x44, 0xb9, 0x06, 0xf2, 0xf7, 0x51, 0xc8, 0xfa, + /*a100:*/ 0x6f, 0x1c, 0x06, 0x3c, 0x90, 0xf0, 0xf6, 0x67, 0x17, 0xe8, 0xb2, 0x0c, 0x75, 0x40, 0x92, 0x4d, + /*a110:*/ 0x41, 0x08, 0x39, 0xf9, 0x71, 0xb8, 0xe5, 0xbf, 0x8f, 0xad, 0x90, 0x84, 0x29, 0x48, 0x8e, 0x75, + /*a120:*/ 0x4f, 0xb3, 0xf3, 0xe3, 0xc3, 0xf5, 0x3d, 0xe6, 0x95, 0xfb, 0x14, 0x5b, 0x89, 0xe4, 0xd8, 0xf3, + /*a130:*/ 0x16, 0x26, 0x76, 0xf5, 0x76, 0x43, 0x1f, 0xe3, 0x0b, 0xe4, 0xb7, 0x5a, 0x1a, 0x2c, 0x71, 0xb0, + /*a140:*/ 0xd4, 0xd0, 0x09, 0x8c, 0x64, 0x70, 0x57, 0x98, 0xe6, 0xa6, 0x10, 0x6f, 0xde, 0xe1, 0xa5, 0x45, + /*a150:*/ 0x9e, 0x41, 0x35, 0x3f, 0x78, 0x8e, 0xf1, 0x3c, 0x30, 0x32, 0xe2, 0xe1, 0xa6, 0xd8, 0x58, 0xc0, + /*a160:*/ 0xa4, 0x69, 0x1a, 0x5a, 0xb2, 0x56, 0x7f, 0x33, 0x3f, 0x10, 0x77, 0x92, 0xa7, 0xc0, 0xb2, 0xc0, + /*a170:*/ 0xf8, 0x27, 0xa5, 0xcd, 0xfa, 0x27, 0x9f, 0xe3, 0x28, 0x59, 0x54, 0xb3, 0x43, 0xf8, 0xd7, 0x20, + /*a180:*/ 0x25, 0xee, 0x34, 0x3d, 0x66, 0xa1, 0x48, 0x83, 0x61, 0x03, 0x29, 0xcb, 0xbb, 0x72, 0x56, 0x1d, + /*a190:*/ 0x66, 0xfc, 0xcf, 0x6e, 0x28, 0x22, 0xed, 0x3a, 0x2f, 0xdb, 0x4a, 0x0b, 0xa6, 0xbe, 0xb2, 0xe4, + /*a1a0:*/ 0x26, 0x40, 0x82, 0xd0, 0xab, 0xfa, 0x95, 0x03, 0x4d, 0xdb, 0x5b, 0x97, 0x65, 0x36, 0x4a, 0x5e, + /*a1b0:*/ 0xd9, 0x63, 0xc8, 0x9c, 0xbe, 0x70, 0x76, 0xee, 0xa0, 0xcf, 0x34, 0xad, 0xcd, 0xa1, 0x81, 0x19, + /*a1c0:*/ 0x71, 0x49, 0xb7, 0xc9, 0x47, 0xec, 0x92, 0x32, 0xc8, 0xf0, 0xe0, 0x30, 0xee, 0x9a, 0xbb, 0x11, + /*a1d0:*/ 0x8e, 0xe4, 0xa8, 0xdb, 0x1f, 0x29, 0xf5, 0xcf, 0x16, 0x82, 0x7b, 0xcf, 0x10, 0x48, 0xaa, 0x55, + /*a1e0:*/ 0x75, 0x9e, 0x8b, 0xc1, 0x34, 0xd2, 0x91, 0xd1, 0x56, 0x51, 0xee, 0xcb, 0xc5, 0x8b, 0xeb, 0x30, + /*a1f0:*/ 0xa9, 0x0c, 0xcd, 0x05, 0x7c, 0xd0, 0x64, 0x8b, 0x66, 0xba, 0x59, 0xd2, 0x0d, 0x87, 0x8f, 0xf6, + /*a200:*/ 0x67, 0x8b, 0x85, 0x44, 0x7f, 0xd9, 0x02, 0xfd, 0x75, 0x0b, 0x11, 0x45, 0xa5, 0x1d, 0x2a, 0x37, + /*a210:*/ 0xd8, 0xe7, 0xde, 0x33, 0xcf, 0xdb, 0xdb, 0x31, 0xe4, 0xf5, 0x41, 0xae, 0x33, 0x6e, 0x0e, 0x02, + /*a220:*/ 0x02, 0x38, 0xd7, 0x67, 0xb5, 0x24, 0xe9, 0x31, 0x91, 0x0f, 0x5f, 0x24, 0xd3, 0x2f, 0x41, 0xe7, + /*a230:*/ 0x8a, 0xb0, 0x5c, 0x88, 0x32, 0x4e, 0xff, 0xf1, 0xa4, 0xaf, 0xa8, 0x6b, 0x04, 0x5d, 0x0e, 0xb2, + /*a240:*/ 0xd8, 0x69, 0x74, 0x5b, 0xbc, 0x91, 0xf3, 0x59, 0x98, 0xf5, 0x13, 0xdd, 0x10, 0x45, 0x02, 0x6d, + /*a250:*/ 0xcb, 0x3e, 0x01, 0x31, 0xa0, 0x29, 0x07, 0x67, 0x3b, 0x04, 0x4a, 0xc3, 0x9c, 0x9e, 0x90, 0xa0, + /*a260:*/ 0x1d, 0xc1, 0x6a, 0x9e, 0xef, 0xd5, 0xf2, 0x1f, 0x91, 0xd0, 0xe7, 0xe2, 0x76, 0x83, 0xaa, 0x85, + /*a270:*/ 0xd6, 0x29, 0x8a, 0x74, 0x09, 0x94, 0xed, 0x4e, 0x2b, 0xd9, 0x6a, 0x55, 0x70, 0x3d, 0x16, 0x57, + /*a280:*/ 0xd4, 0x9e, 0x31, 0x66, 0x8b, 0xf4, 0x6a, 0x70, 0xce, 0xe5, 0x33, 0xc0, 0xb4, 0xcf, 0x41, 0xf7, + /*a290:*/ 0xb2, 0xbf, 0x95, 0xa1, 0xe3, 0x8b, 0x2e, 0x46, 0x1f, 0x44, 0xe5, 0xd0, 0x5e, 0x99, 0x4a, 0xb6, + /*a2a0:*/ 0x65, 0x90, 0x74, 0x2a, 0x8e, 0xbc, 0x1f, 0x17, 0x6a, 0x01, 0x05, 0xb7, 0xb5, 0xd2, 0xab, 0xf6, + /*a2b0:*/ 0xe6, 0x90, 0x5a, 0x07, 0xa1, 0x7c, 0x68, 0x9d, 0x7a, 0x88, 0x1c, 0x10, 0xa4, 0xe3, 0x7b, 0xbb, + /*a2c0:*/ 0xf4, 0xb0, 0x1f, 0x59, 0x96, 0x31, 0xea, 0xc5, 0xf2, 0x7e, 0x1e, 0x31, 0xa2, 0x94, 0x84, 0x3a, + /*a2d0:*/ 0xbd, 0x08, 0x8a, 0x3a, 0xa5, 0x6d, 0x0e, 0x45, 0x63, 0xd8, 0xe5, 0xf4, 0x53, 0xd5, 0x04, 0x64, + /*a2e0:*/ 0x43, 0x14, 0xed, 0x45, 0x96, 0x31, 0xdd, 0x73, 0xf8, 0xe5, 0x1f, 0x4f, 0xd7, 0x41, 0x9e, 0xed, + /*a2f0:*/ 0x87, 0xb0, 0x20, 0x8a, 0x51, 0xcf, 0x9e, 0x42, 0xe4, 0xb8, 0xce, 0x61, 0xbe, 0x3f, 0x03, 0xf6, + /*a300:*/ 0xdd, 0x55, 0x57, 0x17, 0x89, 0xe3, 0x11, 0x2f, 0x75, 0x54, 0x8f, 0xcc, 0x69, 0xc8, 0xd9, 0xd0, + /*a310:*/ 0x17, 0xfc, 0x6a, 0x4f, 0x11, 0x08, 0xc5, 0x67, 0xd4, 0xdd, 0x6e, 0x9c, 0xae, 0x18, 0x05, 0x50, + /*a320:*/ 0xd9, 0xb0, 0x75, 0x8c, 0x4a, 0x0a, 0xb9, 0x37, 0x91, 0x38, 0xab, 0x5e, 0xbc, 0xe0, 0x15, 0x07, + /*a330:*/ 0x10, 0xdd, 0x4c, 0xb2, 0xc7, 0x62, 0x57, 0x51, 0x72, 0xe9, 0x23, 0x50, 0x47, 0xf9, 0xc2, 0x31, + /*a340:*/ 0x40, 0x47, 0xfd, 0xe3, 0xf6, 0x45, 0xc4, 0xd8, 0x3b, 0x42, 0x47, 0xed, 0xd6, 0x36, 0x0a, 0x66, + /*a350:*/ 0x96, 0x1d, 0x3a, 0x27, 0x59, 0xa3, 0x51, 0xa6, 0xc0, 0x6c, 0xdb, 0x43, 0x0f, 0x86, 0xcb, 0xe6, + /*a360:*/ 0x01, 0x2d, 0x42, 0xcd, 0xa7, 0x63, 0x27, 0x0e, 0xd0, 0xdb, 0xa9, 0x39, 0xbe, 0x43, 0x78, 0x16, + /*a370:*/ 0x54, 0xcc, 0xff, 0x0d, 0x4c, 0x44, 0x22, 0x9e, 0xbf, 0x33, 0xbb, 0xb6, 0xd5, 0x9b, 0xe1, 0x80, + /*a380:*/ 0x26, 0x54, 0x76, 0xe7, 0xcb, 0x8b, 0x36, 0x9c, 0x85, 0xb7, 0xee, 0x62, 0x26, 0xa0, 0xd9, 0x99, + /*a390:*/ 0x1d, 0x8e, 0xfc, 0x66, 0xb8, 0x80, 0x64, 0x74, 0xc7, 0x5a, 0x51, 0x4e, 0x27, 0xac, 0x53, 0xb5, + /*a3a0:*/ 0x94, 0xf8, 0xab, 0xd9, 0xf9, 0x7b, 0xdd, 0xda, 0xac, 0xd6, 0xf8, 0x81, 0x8b, 0x1e, 0xd2, 0x11, + /*a3b0:*/ 0xc3, 0x2a, 0xc2, 0x32, 0xb5, 0x96, 0x11, 0xae, 0xa5, 0x44, 0xe8, 0xe3, 0x37, 0x2e, 0xe5, 0x46, + /*a3c0:*/ 0x89, 0xc1, 0x4a, 0x18, 0xdd, 0x0d, 0x08, 0x7c, 0x54, 0x4e, 0xe6, 0x48, 0x76, 0x74, 0x19, 0x7e, + /*a3d0:*/ 0x40, 0xf4, 0xf4, 0xe6, 0x04, 0x1c, 0xe2, 0x19, 0x2a, 0x87, 0x1d, 0x07, 0x3b, 0xf9, 0xf5, 0x72, + /*a3e0:*/ 0x67, 0xc5, 0xd5, 0x53, 0x5d, 0xa2, 0x6f, 0x87, 0x38, 0xe6, 0x3d, 0x7c, 0xf5, 0xcd, 0x02, 0xfc, + /*a3f0:*/ 0xf2, 0x74, 0x27, 0x62, 0x62, 0x71, 0x45, 0xaa, 0x1f, 0xbd, 0x49, 0x8c, 0xa3, 0xb8, 0xf7, 0x14, + /*a400:*/ 0xac, 0x49, 0xeb, 0xb3, 0x8f, 0x5f, 0x12, 0x46, 0x07, 0x28, 0x32, 0x4a, 0x50, 0x0e, 0x98, 0xb3, + /*a410:*/ 0x8f, 0x63, 0x38, 0x45, 0x76, 0xf1, 0xcf, 0x04, 0x86, 0x16, 0x2f, 0x10, 0xbd, 0xa0, 0xb1, 0xd1, + /*a420:*/ 0xe4, 0x32, 0x09, 0xa3, 0x0c, 0x4c, 0xf3, 0xb0, 0x3b, 0x7d, 0xa8, 0x9b, 0xf7, 0x6c, 0x11, 0xce, + /*a430:*/ 0xe4, 0x19, 0x8c, 0xbb, 0x27, 0x12, 0x73, 0x9f, 0xe9, 0x46, 0x4a, 0x82, 0xf9, 0x26, 0x30, 0x4e, + /*a440:*/ 0xef, 0x11, 0x55, 0x98, 0x2c, 0xa4, 0xf4, 0xa9, 0x42, 0x56, 0x67, 0x36, 0xbf, 0x8c, 0xe4, 0x8c, + /*a450:*/ 0xf8, 0x47, 0x8f, 0x73, 0x3a, 0x0c, 0xdd, 0xe6, 0x49, 0x29, 0x12, 0xf4, 0xc2, 0x7d, 0x72, 0x0f, + /*a460:*/ 0xa5, 0x5b, 0xb9, 0x19, 0xfe, 0x24, 0x65, 0xfd, 0x5a, 0xe6, 0x3f, 0xb0, 0x2c, 0x78, 0xec, 0x3f, + /*a470:*/ 0x1f, 0xc2, 0xa8, 0xd0, 0xdf, 0x1b, 0xa1, 0x9b, 0x47, 0x0b, 0x16, 0xb2, 0x1d, 0x75, 0xba, 0x23, + /*a480:*/ 0x20, 0x5a, 0x88, 0xca, 0x99, 0x54, 0x00, 0x8e, 0xd4, 0x9e, 0x31, 0x71, 0xdf, 0xb8, 0xf9, 0x23, + /*a490:*/ 0xc7, 0x88, 0x2a, 0x40, 0xc5, 0x5f, 0x17, 0x07, 0xe5, 0xab, 0x70, 0xff, 0xac, 0x79, 0xe8, 0x51, + /*a4a0:*/ 0x9c, 0x9f, 0x06, 0x43, 0x31, 0x7a, 0x0f, 0xa1, 0x12, 0x5a, 0x50, 0x86, 0x7a, 0x0f, 0xf9, 0xf2, + /*a4b0:*/ 0x13, 0x7d, 0x11, 0x72, 0x56, 0xa5, 0x54, 0x52, 0xb4, 0xcf, 0xb0, 0xdb, 0xce, 0xe1, 0x02, 0x8e, + /*a4c0:*/ 0xeb, 0xf8, 0xc6, 0xdd, 0xcf, 0x7f, 0x48, 0xa6, 0x18, 0xc1, 0x8e, 0xeb, 0xf7, 0xf0, 0x59, 0x2e, + /*a4d0:*/ 0xb5, 0xb0, 0x29, 0x7c, 0x46, 0x88, 0xfb, 0xf8, 0x5e, 0xb8, 0xd1, 0x96, 0x23, 0x8e, 0xaf, 0x06, + /*a4e0:*/ 0x44, 0x1b, 0xe0, 0xac, 0xf9, 0x5c, 0xa0, 0x2a, 0x05, 0xfc, 0x8f, 0x74, 0x4d, 0x42, 0x4c, 0xca, + /*a4f0:*/ 0xe8, 0x98, 0x96, 0x8c, 0x9b, 0x59, 0x92, 0xb1, 0x9a, 0x19, 0xed, 0x41, 0xc7, 0xe7, 0x61, 0x9b, + /*a500:*/ 0x30, 0x3c, 0x5b, 0x45, 0xcf, 0x90, 0xfb, 0xf4, 0x9f, 0xce, 0xc3, 0x83, 0x82, 0x70, 0xc2, 0xfd, + /*a510:*/ 0xb6, 0xcd, 0x94, 0x6a, 0x15, 0xa5, 0x30, 0x39, 0xa3, 0xbb, 0x0a, 0x70, 0x18, 0x69, 0x93, 0x7b, + /*a520:*/ 0x21, 0x1f, 0x7f, 0x71, 0x61, 0xb7, 0xa3, 0x21, 0xb1, 0xba, 0x65, 0x1d, 0x84, 0x39, 0xc7, 0x4e, + /*a530:*/ 0x21, 0x2f, 0xfe, 0x8a, 0x0f, 0xdf, 0x81, 0xbb, 0xb2, 0x72, 0x71, 0x25, 0xfa, 0xc2, 0xc5, 0xff, + /*a540:*/ 0x99, 0x6d, 0x1f, 0xa3, 0xfc, 0xf3, 0xec, 0x32, 0x92, 0xd3, 0x28, 0xf2, 0xc6, 0x26, 0x1f, 0xa0, + /*a550:*/ 0xe6, 0xdf, 0xc5, 0xb2, 0x6b, 0x17, 0x69, 0x64, 0xe1, 0xda, 0x68, 0x38, 0x14, 0xf5, 0x2e, 0xf5, + /*a560:*/ 0xaf, 0x57, 0x74, 0x44, 0xe1, 0x28, 0x6e, 0x2e, 0x28, 0x7f, 0x99, 0x1c, 0x23, 0x26, 0x96, 0x38, + /*a570:*/ 0xcb, 0x70, 0x62, 0x53, 0x1b, 0x70, 0xb3, 0x1b, 0xbb, 0x9a, 0x9e, 0x31, 0xfd, 0x6f, 0x74, 0x84, + /*a580:*/ 0x5c, 0xd5, 0xf7, 0x10, 0xf7, 0x76, 0xd4, 0x22, 0xe6, 0x5e, 0x4b, 0xad, 0x41, 0xe6, 0x23, 0xe5, + /*a590:*/ 0x36, 0xf1, 0x2b, 0x57, 0x87, 0x97, 0x60, 0x46, 0x9d, 0xea, 0x18, 0x25, 0xcf, 0x33, 0x4f, 0x68, + /*a5a0:*/ 0x4d, 0x9f, 0x61, 0x59, 0x09, 0xf4, 0x45, 0xa3, 0x03, 0x76, 0x68, 0x24, 0x18, 0x36, 0xbe, 0xb7, + /*a5b0:*/ 0x78, 0xf7, 0xdc, 0x21, 0xce, 0x36, 0x28, 0xd2, 0x79, 0xb9, 0xda, 0xf3, 0x7f, 0xc0, 0x74, 0x55, + /*a5c0:*/ 0x00, 0x38, 0x57, 0x73, 0x9b, 0x1e, 0x80, 0x84, 0x55, 0xfc, 0x35, 0x1c, 0xbd, 0x8c, 0x27, 0xf0, + /*a5d0:*/ 0x6d, 0xef, 0x8a, 0x6a, 0x3a, 0x76, 0x77, 0xd1, 0xf3, 0xf7, 0xbc, 0xdd, 0x97, 0x0b, 0x68, 0xcc, + /*a5e0:*/ 0x2b, 0xdc, 0x1f, 0xde, 0x52, 0x66, 0x67, 0x7d, 0x72, 0x4c, 0x2c, 0xa8, 0xf1, 0x8d, 0x6d, 0xa3, + /*a5f0:*/ 0x4c, 0x33, 0xcf, 0xa9, 0x25, 0x6b, 0x6e, 0xe0, 0x48, 0x81, 0x51, 0x85, 0xf4, 0x33, 0xda, 0x32, + /*a600:*/ 0x7b, 0xdd, 0xa8, 0x0e, 0x94, 0x08, 0xc2, 0x16, 0xd0, 0xdd, 0x93, 0x22, 0xdc, 0x90, 0x04, 0xc9, + /*a610:*/ 0xee, 0x2a, 0xcd, 0x58, 0xac, 0xf7, 0x9a, 0xe2, 0xd9, 0x0a, 0x7b, 0x18, 0x9f, 0x85, 0xfc, 0x8e, + /*a620:*/ 0xb6, 0x5c, 0x05, 0x46, 0x94, 0x55, 0xd5, 0x28, 0x84, 0x0a, 0xb1, 0x35, 0x8d, 0x38, 0x34, 0xd5, + /*a630:*/ 0xd6, 0x2b, 0x66, 0xd6, 0xc1, 0x19, 0x5d, 0x99, 0x2f, 0xbe, 0x7f, 0xd9, 0x53, 0xa5, 0x6f, 0xa0, + /*a640:*/ 0x18, 0xb5, 0x77, 0x12, 0x56, 0xdd, 0x64, 0x4c, 0x84, 0x43, 0xa6, 0x05, 0x29, 0xf2, 0x70, 0x88, + /*a650:*/ 0x64, 0x1e, 0x28, 0x35, 0x31, 0x2d, 0x9a, 0xa0, 0x1e, 0x05, 0x53, 0xa2, 0xf1, 0xa9, 0xa8, 0xae, + /*a660:*/ 0x6d, 0x93, 0x13, 0x2d, 0xeb, 0x94, 0xe9, 0x7f, 0x9e, 0x05, 0x52, 0x18, 0xa0, 0xaa, 0x4d, 0x25, + /*a670:*/ 0xf2, 0x1c, 0xa6, 0xf4, 0x38, 0x14, 0x36, 0xb6, 0x0c, 0x5f, 0xb3, 0x26, 0x1f, 0x35, 0x3d, 0x6d, + /*a680:*/ 0xa2, 0xa1, 0x06, 0x41, 0x44, 0xf2, 0xc2, 0xee, 0x8a, 0xf0, 0x5b, 0x4c, 0x15, 0xa2, 0x1d, 0xd1, + /*a690:*/ 0xd3, 0x44, 0x89, 0x49, 0x92, 0xe3, 0x1c, 0x15, 0x69, 0x43, 0xab, 0x10, 0xce, 0x16, 0xcf, 0x82, + /*a6a0:*/ 0x5b, 0x81, 0x1b, 0x86, 0x8b, 0x71, 0x79, 0x47, 0x49, 0x87, 0x8f, 0x73, 0x7a, 0xc2, 0xda, 0xb6, + /*a6b0:*/ 0x68, 0x45, 0x4d, 0x41, 0xbc, 0xec, 0x5c, 0x4a, 0xb1, 0x8b, 0x2d, 0xc2, 0x1f, 0x62, 0xd8, 0x8c, + /*a6c0:*/ 0x9e, 0x0d, 0x00, 0x5b, 0x20, 0x23, 0x39, 0xfe, 0x8c, 0x1c, 0x1d, 0xf6, 0xb8, 0x86, 0xb4, 0x2b, + /*a6d0:*/ 0xe2, 0xe9, 0x79, 0xc4, 0x30, 0xcf, 0xd8, 0xc4, 0x9d, 0xcf, 0x9d, 0xb2, 0xd3, 0x50, 0x2b, 0xdc, + /*a6e0:*/ 0xae, 0xfb, 0x67, 0x50, 0x73, 0x86, 0x0c, 0x01, 0x31, 0x8e, 0xb0, 0x98, 0x96, 0xe9, 0x3c, 0x58, + /*a6f0:*/ 0x08, 0x68, 0x0a, 0x63, 0xd2, 0xdf, 0xc7, 0x2e, 0xd5, 0xed, 0x14, 0xeb, 0x61, 0x56, 0x63, 0xa1, + /*a700:*/ 0xc1, 0xa9, 0x26, 0x25, 0xe8, 0x6c, 0xea, 0xa0, 0x5a, 0x8e, 0xaf, 0x5d, 0xca, 0x06, 0xa4, 0x64, + /*a710:*/ 0xad, 0xf8, 0xbd, 0x90, 0xbb, 0xbf, 0xb7, 0xb6, 0x25, 0x5d, 0x09, 0x39, 0x82, 0x01, 0x7d, 0xfb, + /*a720:*/ 0x31, 0x3c, 0x82, 0x2b, 0x40, 0x63, 0x01, 0x80, 0x4e, 0x7c, 0xe8, 0x6c, 0x9b, 0xef, 0x12, 0x2c, + /*a730:*/ 0x8d, 0x63, 0xff, 0xf5, 0xad, 0x77, 0x59, 0x39, 0x20, 0x99, 0x85, 0x51, 0xe7, 0x75, 0x07, 0xac, + /*a740:*/ 0xe8, 0x30, 0xa4, 0xc9, 0xbf, 0x9f, 0xa4, 0x1f, 0x11, 0x98, 0x01, 0x9b, 0xfb, 0x96, 0x7d, 0xa3, + /*a750:*/ 0xaf, 0x73, 0x15, 0x7b, 0xce, 0x7a, 0xce, 0x2c, 0x00, 0xa1, 0x0f, 0x3c, 0x49, 0x6c, 0x62, 0x4c, + /*a760:*/ 0x7c, 0xec, 0xbb, 0x44, 0xb5, 0xed, 0x16, 0x9d, 0x57, 0x2b, 0x76, 0x56, 0x57, 0x54, 0x8d, 0xd7, + /*a770:*/ 0xa1, 0x6c, 0xd8, 0x0f, 0xb5, 0x13, 0xe0, 0x56, 0xb6, 0xea, 0xaf, 0x60, 0x13, 0xd1, 0xf8, 0xbc, + /*a780:*/ 0x58, 0xa8, 0x52, 0x5e, 0x42, 0x1b, 0x70, 0x7d, 0x63, 0x7d, 0x8b, 0x69, 0x82, 0xc3, 0xab, 0x38, + /*a790:*/ 0x64, 0x82, 0xef, 0x3f, 0xa9, 0xd9, 0x51, 0x5c, 0x4b, 0x88, 0x35, 0x17, 0xc4, 0xd2, 0x2d, 0xa5, + /*a7a0:*/ 0x46, 0xb0, 0x11, 0xcf, 0x6d, 0x94, 0xa3, 0x93, 0x93, 0xb7, 0xa7, 0xf8, 0x09, 0x39, 0x03, 0x1c, + /*a7b0:*/ 0x15, 0xba, 0x34, 0x3e, 0xe0, 0x08, 0xda, 0x0a, 0x93, 0xa2, 0x35, 0x23, 0x9b, 0xa0, 0x49, 0x7e, + /*a7c0:*/ 0x58, 0xe4, 0x6d, 0xef, 0x21, 0xbd, 0xfb, 0x15, 0xe5, 0xb2, 0x26, 0xb9, 0xd9, 0xab, 0xef, 0x0e, + /*a7d0:*/ 0x12, 0xfc, 0x24, 0xd6, 0x5c, 0xfd, 0x0e, 0xf2, 0x00, 0x12, 0x0f, 0x22, 0x0c, 0x53, 0x54, 0xdd, + /*a7e0:*/ 0xe6, 0x04, 0x61, 0xcb, 0xf5, 0x4b, 0xd0, 0x91, 0x24, 0x7e, 0x91, 0x95, 0x07, 0x41, 0x4c, 0x32, + /*a7f0:*/ 0x64, 0x44, 0x4e, 0xdc, 0x0b, 0xf4, 0x8a, 0xb5, 0x75, 0xc8, 0x73, 0xee, 0xc3, 0x7d, 0xb0, 0xbf, + /*a800:*/ 0x63, 0x7d, 0x69, 0x96, 0x58, 0x9c, 0x10, 0xed, 0xe6, 0x5a, 0x55, 0xf7, 0x20, 0xda, 0xbd, 0x1b, + /*a810:*/ 0xba, 0x0a, 0xab, 0x36, 0x1f, 0xe3, 0xe0, 0x3c, 0x20, 0xae, 0x90, 0x60, 0xcd, 0xe0, 0x29, 0xe7, + /*a820:*/ 0x41, 0x27, 0x68, 0x1c, 0xf3, 0xcc, 0xb7, 0x79, 0xfb, 0x06, 0x48, 0x89, 0x61, 0xb2, 0x02, 0xb2, + /*a830:*/ 0xcf, 0x61, 0xe9, 0x77, 0x9f, 0x8d, 0x7e, 0x19, 0x2b, 0xd0, 0x2d, 0xf9, 0x61, 0x29, 0xc9, 0x46, + /*a840:*/ 0x84, 0xd1, 0x54, 0x4d, 0x83, 0xb0, 0x8c, 0x33, 0x4f, 0xa5, 0xeb, 0x98, 0xa0, 0x41, 0x5b, 0xa0, + /*a850:*/ 0x04, 0x09, 0x37, 0xc2, 0xa7, 0x5f, 0xdf, 0x63, 0xa8, 0x82, 0x78, 0xf9, 0xea, 0xfc, 0xde, 0xa5, + /*a860:*/ 0x5c, 0xe4, 0xd9, 0x80, 0x54, 0x78, 0x34, 0x77, 0x59, 0x2b, 0xbb, 0x38, 0x6e, 0xdd, 0x57, 0x9e, + /*a870:*/ 0xd7, 0xe3, 0x9c, 0x67, 0x2e, 0xc1, 0xa1, 0x9d, 0xf2, 0xa1, 0xb8, 0x99, 0xc0, 0x89, 0x83, 0x2c, + /*a880:*/ 0x03, 0xfc, 0xc0, 0x03, 0x77, 0x06, 0xc9, 0xbe, 0x8a, 0xe6, 0xaa, 0x42, 0x95, 0x43, 0x57, 0x30, + /*a890:*/ 0xdf, 0xc0, 0x71, 0x9b, 0x42, 0x39, 0x67, 0x35, 0xc1, 0xa8, 0xb0, 0x16, 0xe3, 0xc3, 0xa8, 0x20, + /*a8a0:*/ 0xd6, 0x11, 0xed, 0x12, 0x42, 0x62, 0x2e, 0x2b, 0x17, 0x43, 0x3a, 0x27, 0x0d, 0x83, 0xd6, 0x87, + /*a8b0:*/ 0x70, 0x0e, 0x84, 0x01, 0xfd, 0xa1, 0xd9, 0x2b, 0x5c, 0xdb, 0xf9, 0xbe, 0x27, 0xd3, 0x05, 0x7a, + /*a8c0:*/ 0x89, 0x77, 0x23, 0x7a, 0x0c, 0x4c, 0x3f, 0xb3, 0xbc, 0xc1, 0x80, 0xde, 0x88, 0x68, 0x6c, 0xbe, + /*a8d0:*/ 0x6b, 0xa0, 0xf4, 0xfe, 0x9d, 0xde, 0xa4, 0x8d, 0xc8, 0xfe, 0x8f, 0x0d, 0xf8, 0xfb, 0xe3, 0x33, + /*a8e0:*/ 0xd9, 0x9f, 0x38, 0x44, 0xf0, 0x1e, 0x13, 0x87, 0x4a, 0x35, 0x79, 0xbd, 0x56, 0x77, 0x4d, 0x2e, + /*a8f0:*/ 0xed, 0x44, 0x05, 0x70, 0xcb, 0xee, 0x56, 0xb8, 0x40, 0xc4, 0x29, 0x1a, 0xaf, 0x14, 0xd3, 0xd3, + /*a900:*/ 0x18, 0x34, 0x77, 0x79, 0x7c, 0x69, 0x36, 0xbc, 0x18, 0xea, 0xc8, 0x5e, 0xdf, 0x17, 0xfe, 0xf0, + /*a910:*/ 0x22, 0xd7, 0x5c, 0xa7, 0x24, 0xd8, 0xe9, 0x85, 0x2f, 0x08, 0xef, 0x68, 0x9a, 0xe9, 0x81, 0x80, + /*a920:*/ 0xe2, 0xb2, 0x5d, 0x11, 0x30, 0xf0, 0xa9, 0xab, 0x6b, 0xee, 0x2c, 0x62, 0x0a, 0xde, 0xec, 0x4e, + /*a930:*/ 0xd0, 0x25, 0xbb, 0xd5, 0xc5, 0x2d, 0xa8, 0xea, 0x1e, 0x7b, 0xfc, 0x84, 0x4b, 0x38, 0xb8, 0x90, + /*a940:*/ 0x8d, 0x4b, 0x3d, 0x7c, 0xa6, 0x8d, 0x1a, 0x73, 0x0f, 0x72, 0xb9, 0x2a, 0xc2, 0x31, 0x3c, 0xa5, + /*a950:*/ 0x18, 0xfe, 0x02, 0xb6, 0x2f, 0xfa, 0x3c, 0x23, 0x99, 0x73, 0x93, 0xcf, 0x14, 0x06, 0xb8, 0x76, + /*a960:*/ 0xf5, 0x66, 0xb2, 0xb8, 0x04, 0xd0, 0x10, 0x13, 0x38, 0x41, 0x17, 0x59, 0x20, 0x63, 0x09, 0xee, + /*a970:*/ 0x1b, 0xae, 0xc0, 0xea, 0xf3, 0xbf, 0xca, 0x9f, 0x25, 0x94, 0x0c, 0x96, 0x3f, 0x2d, 0x99, 0xc3, + /*a980:*/ 0x42, 0xe4, 0xe0, 0x92, 0x9c, 0x13, 0x0d, 0xb6, 0x87, 0xd6, 0x42, 0xbd, 0x35, 0xb2, 0x72, 0x57, + /*a990:*/ 0xb4, 0x52, 0x16, 0xa3, 0x86, 0x82, 0x21, 0x67, 0x5f, 0xff, 0x3d, 0x58, 0xcd, 0xb1, 0x9e, 0xbd, + /*a9a0:*/ 0x15, 0x87, 0x1e, 0x2f, 0x8d, 0x98, 0xcf, 0x4b, 0x93, 0x7b, 0x3f, 0xdd, 0x7c, 0x2b, 0xc5, 0x57, + /*a9b0:*/ 0x9b, 0x98, 0xfb, 0xc7, 0x53, 0xc3, 0x1f, 0xae, 0x9d, 0xd6, 0xed, 0xc8, 0xd0, 0xb6, 0x34, 0x21, + /*a9c0:*/ 0x94, 0xf3, 0x95, 0xfb, 0xf0, 0x80, 0x24, 0x98, 0x0f, 0xd1, 0xd3, 0xe0, 0xfd, 0xc5, 0xcd, 0xa6, + /*a9d0:*/ 0xda, 0xfb, 0x58, 0xb0, 0x1b, 0x9a, 0x24, 0x59, 0xaf, 0x55, 0xa6, 0x82, 0xab, 0x21, 0x40, 0x4a, + /*a9e0:*/ 0xaa, 0x4e, 0xcd, 0x23, 0x7d, 0x2b, 0xa3, 0x01, 0x18, 0x63, 0xfd, 0x2f, 0x12, 0xd3, 0x2b, 0x25, + /*a9f0:*/ 0xbd, 0xb0, 0x10, 0x59, 0x7c, 0x85, 0x5d, 0xdb, 0x28, 0x34, 0xd1, 0x1d, 0x9d, 0x50, 0x78, 0xef, + /*aa00:*/ 0x84, 0x97, 0x1a, 0x49, 0x1a, 0x8b, 0xd3, 0x88, 0xbe, 0x67, 0xac, 0x4a, 0x1f, 0x1b, 0x15, 0x21, + /*aa10:*/ 0x61, 0x85, 0xf3, 0x74, 0x48, 0x20, 0xe1, 0x55, 0x16, 0x2a, 0xf3, 0xdd, 0x5c, 0x9e, 0xc9, 0x13, + /*aa20:*/ 0x55, 0x70, 0xf7, 0xc1, 0x07, 0xcb, 0xa2, 0xa5, 0x7d, 0x7d, 0xcb, 0xbb, 0x56, 0x07, 0x7a, 0x5a, + /*aa30:*/ 0xa4, 0xf7, 0x1b, 0x28, 0x0a, 0x89, 0xef, 0x5a, 0x28, 0x01, 0xe0, 0xbb, 0x67, 0x9d, 0xab, 0x2f, + /*aa40:*/ 0xb8, 0x71, 0x48, 0x6c, 0x6e, 0x98, 0xc5, 0x7d, 0x81, 0xcd, 0xba, 0xc2, 0x70, 0x63, 0x9e, 0x87, + /*aa50:*/ 0x14, 0x54, 0xbb, 0xbb, 0xd6, 0x7b, 0xb1, 0xaa, 0xae, 0x22, 0xba, 0x87, 0x80, 0x59, 0x6f, 0x23, + /*aa60:*/ 0x06, 0x5c, 0x6c, 0x1d, 0x34, 0x70, 0xce, 0xfd, 0x37, 0x73, 0xff, 0x85, 0x92, 0xae, 0x13, 0xb7, + /*aa70:*/ 0x67, 0x5d, 0x32, 0xff, 0x39, 0x8e, 0x52, 0xaa, 0x3c, 0x99, 0xa7, 0xe9, 0x27, 0x4e, 0xbb, 0x58, + /*aa80:*/ 0x78, 0xa2, 0x85, 0x36, 0xad, 0xa5, 0xbe, 0xa9, 0x78, 0xc4, 0xae, 0x78, 0xef, 0xea, 0x18, 0x24, + /*aa90:*/ 0x50, 0x4a, 0x56, 0x85, 0x6c, 0xdc, 0x69, 0x14, 0xe2, 0xe0, 0xb3, 0x8d, 0x2e, 0xdf, 0x62, 0x47, + /*aaa0:*/ 0xcf, 0xf2, 0xee, 0xe2, 0x0b, 0xab, 0x08, 0xf0, 0x89, 0x29, 0x91, 0x12, 0xfc, 0x9f, 0x4c, 0xb9, + /*aab0:*/ 0x0c, 0x92, 0xd3, 0x0d, 0x41, 0x72, 0xce, 0x67, 0xbf, 0x72, 0x4a, 0xd5, 0x10, 0x3b, 0x7b, 0xa0, + /*aac0:*/ 0x6e, 0xf4, 0x51, 0x63, 0x47, 0x74, 0xd9, 0x5e, 0x0b, 0xb3, 0x3e, 0x56, 0xb9, 0x90, 0x30, 0xd8, + /*aad0:*/ 0xa6, 0x54, 0xf3, 0x87, 0x87, 0xf2, 0xca, 0xa8, 0x81, 0x72, 0xea, 0x07, 0x34, 0x2f, 0xb2, 0x11, + /*aae0:*/ 0x23, 0x49, 0xf5, 0x9d, 0x6c, 0x52, 0xd6, 0x41, 0x71, 0xe4, 0x2c, 0xc1, 0x4c, 0x30, 0x9e, 0xf3, + /*aaf0:*/ 0xb2, 0x21, 0x21, 0x3e, 0x1f, 0x12, 0x7b, 0x6b, 0xd1, 0xc7, 0xe8, 0xd0, 0x74, 0x1c, 0xf2, 0x46, + /*ab00:*/ 0xcc, 0x12, 0x89, 0x97, 0x9e, 0x92, 0x7f, 0x89, 0xdb, 0x82, 0x1c, 0xd4, 0xe8, 0xcd, 0x36, 0x76, + /*ab10:*/ 0x6c, 0x09, 0xe3, 0x15, 0x2e, 0x6a, 0xbf, 0x46, 0x28, 0x95, 0x2f, 0x01, 0x92, 0x00, 0x68, 0x6e, + /*ab20:*/ 0x5d, 0xbf, 0x3d, 0xc1, 0x29, 0xbf, 0x09, 0x4a, 0x08, 0x74, 0x79, 0x48, 0xb4, 0x5e, 0x5f, 0x52, + /*ab30:*/ 0x55, 0x0c, 0x41, 0x69, 0x3d, 0x48, 0xf6, 0xf0, 0x9b, 0x63, 0x1f, 0xaa, 0x6e, 0xfd, 0x7f, 0x0f, + /*ab40:*/ 0x83, 0x29, 0x68, 0xd7, 0xb5, 0xa6, 0x12, 0x05, 0x8f, 0x43, 0x07, 0xbc, 0x25, 0xd2, 0xec, 0xb3, + /*ab50:*/ 0xab, 0xc9, 0xf3, 0x1f, 0xbb, 0xc2, 0xe3, 0x78, 0x4e, 0xb6, 0x35, 0xfb, 0x94, 0xde, 0xf0, 0xd9, + /*ab60:*/ 0xe6, 0xec, 0xf8, 0xae, 0xf8, 0x46, 0x1a, 0x83, 0xd3, 0xdb, 0xfe, 0xbc, 0x80, 0x65, 0x4d, 0xc7, + /*ab70:*/ 0x83, 0x75, 0xb2, 0xdd, 0x77, 0xc3, 0x46, 0xd4, 0x32, 0xa4, 0x54, 0xef, 0x9b, 0xa3, 0x76, 0xb7, + /*ab80:*/ 0x9e, 0x60, 0x14, 0x6d, 0xd7, 0xb1, 0x47, 0x82, 0xef, 0x2c, 0xcf, 0x88, 0x17, 0x5c, 0xa1, 0xe6, + /*ab90:*/ 0x60, 0x22, 0xdb, 0x85, 0x18, 0x11, 0x08, 0xd0, 0x59, 0xc6, 0xe9, 0x19, 0x55, 0x3c, 0x81, 0xf4, + /*aba0:*/ 0x6d, 0xec, 0x1b, 0x88, 0xd6, 0xb6, 0x7a, 0x62, 0x5d, 0x7a, 0xc4, 0xf1, 0xf0, 0xa0, 0x09, 0x1a, + /*abb0:*/ 0xbc, 0xdf, 0x3c, 0xb0, 0x4f, 0x2b, 0xe1, 0x2e, 0x44, 0x3d, 0x9d, 0x0a, 0xb1, 0x1d, 0x66, 0x62, + /*abc0:*/ 0xbe, 0xbf, 0xe2, 0x2b, 0x66, 0xae, 0xa1, 0x35, 0x04, 0x63, 0x77, 0x97, 0xc9, 0x0b, 0xab, 0xeb, + /*abd0:*/ 0xf0, 0x61, 0xf2, 0x1f, 0xdb, 0x60, 0x51, 0x6f, 0xda, 0xd6, 0x19, 0xdf, 0x5b, 0xad, 0x6e, 0x02, + /*abe0:*/ 0x9c, 0xc8, 0xce, 0x0c, 0xa7, 0xcb, 0x93, 0x3d, 0x3c, 0xff, 0x9e, 0x88, 0xfa, 0xf9, 0x9c, 0x73, + /*abf0:*/ 0x9f, 0x3e, 0xbb, 0xa9, 0x40, 0x2c, 0x88, 0x4f, 0x19, 0x59, 0x1a, 0x42, 0x13, 0xca, 0x47, 0xb8, + /*ac00:*/ 0x46, 0x77, 0x49, 0xa0, 0xb7, 0xec, 0x73, 0x72, 0xb1, 0x9b, 0x61, 0x07, 0x8a, 0x61, 0x08, 0x1a, + /*ac10:*/ 0x4a, 0x59, 0x63, 0x60, 0x2a, 0x0f, 0x5a, 0xdf, 0x3c, 0x23, 0x83, 0x47, 0x32, 0x37, 0xde, 0x8a, + /*ac20:*/ 0x30, 0x10, 0x24, 0x3f, 0x31, 0x93, 0xcb, 0xca, 0xfa, 0x5c, 0xf0, 0xf9, 0x28, 0x50, 0x40, 0x2a, + /*ac30:*/ 0x62, 0xfd, 0x0b, 0x22, 0x52, 0x0b, 0xa4, 0x4d, 0xc4, 0xbc, 0x88, 0x32, 0x0f, 0x85, 0xab, 0xc9, + /*ac40:*/ 0x5c, 0x55, 0xc5, 0x63, 0xbb, 0x2f, 0xfb, 0x41, 0xf6, 0x52, 0xd7, 0x67, 0x35, 0x96, 0x0e, 0xf6, + /*ac50:*/ 0x46, 0x10, 0xaa, 0x92, 0x0a, 0xdf, 0xdf, 0xcb, 0x9b, 0xa7, 0xaa, 0x71, 0xe1, 0xd8, 0xfe, 0x03, + /*ac60:*/ 0xef, 0x25, 0x22, 0x72, 0x86, 0x42, 0x72, 0x00, 0xfc, 0xd2, 0x13, 0xbe, 0x03, 0x1c, 0x4c, 0x4d, + /*ac70:*/ 0x48, 0xb3, 0xaf, 0x7b, 0xb4, 0xa0, 0xe7, 0x0f, 0xc0, 0x40, 0x2b, 0x99, 0xfe, 0x6a, 0x8d, 0x82, + /*ac80:*/ 0x72, 0xef, 0x2b, 0x76, 0xdf, 0x82, 0x74, 0xd2, 0x17, 0xd0, 0xbc, 0xcf, 0x54, 0xb3, 0x6f, 0x34, + /*ac90:*/ 0xd7, 0x86, 0x90, 0x63, 0x1f, 0xdc, 0x54, 0xa6, 0xa7, 0x77, 0x4d, 0x84, 0x0d, 0x5a, 0x02, 0xc1, + /*aca0:*/ 0x3c, 0xd2, 0xc0, 0xc6, 0x1d, 0xa5, 0x60, 0x9b, 0x22, 0x08, 0x44, 0x01, 0xb8, 0x1a, 0xe4, 0x59, + /*acb0:*/ 0x63, 0x2b, 0x48, 0xed, 0xf1, 0x1f, 0x86, 0x18, 0x9c, 0x27, 0xe3, 0x11, 0xb8, 0x03, 0x1a, 0x28, + /*acc0:*/ 0xbb, 0x16, 0x90, 0x80, 0x8e, 0xc9, 0xd7, 0x57, 0x33, 0x82, 0x06, 0x44, 0x2b, 0x3f, 0xee, 0xbc, + /*acd0:*/ 0x4a, 0x19, 0x73, 0x96, 0x09, 0xb9, 0x26, 0x08, 0x57, 0xe9, 0x66, 0x86, 0x33, 0xfe, 0xf0, 0xad, + /*ace0:*/ 0xeb, 0x5f, 0x46, 0xd3, 0x8c, 0x6e, 0xa9, 0xeb, 0x0f, 0x58, 0x27, 0x1d, 0x37, 0x42, 0xd9, 0xbb, + /*acf0:*/ 0x65, 0x6d, 0xf0, 0x75, 0x89, 0xfb, 0x5e, 0x4d, 0xd7, 0x6d, 0x09, 0xb4, 0x42, 0x7e, 0x7c, 0x94, + /*ad00:*/ 0xa5, 0x34, 0x36, 0x13, 0x88, 0x1a, 0x12, 0x2b, 0x02, 0xd4, 0x38, 0x00, 0x25, 0xc4, 0x95, 0xe6, + /*ad10:*/ 0x3c, 0x9b, 0xbe, 0x55, 0x5d, 0x58, 0x6c, 0xef, 0x36, 0xbf, 0xeb, 0x90, 0x74, 0x93, 0x14, 0x07, + /*ad20:*/ 0xad, 0xfa, 0x42, 0x13, 0x7b, 0x13, 0x17, 0x1a, 0x9b, 0x0f, 0x36, 0xee, 0x61, 0x76, 0xe2, 0x85, + /*ad30:*/ 0x99, 0x42, 0x29, 0x50, 0x20, 0x7e, 0x3f, 0x09, 0xaf, 0x3a, 0xe5, 0x3f, 0x53, 0xf6, 0x76, 0x79, + /*ad40:*/ 0xfb, 0x8c, 0x73, 0xc9, 0x83, 0xf6, 0x1c, 0x21, 0xec, 0x05, 0x07, 0x10, 0xbc, 0x16, 0x8e, 0x65, + /*ad50:*/ 0x7f, 0xfe, 0x4a, 0x3e, 0xbe, 0xf7, 0x74, 0x47, 0x51, 0x89, 0x5f, 0xad, 0xc1, 0x9e, 0xa1, 0x6a, + /*ad60:*/ 0x69, 0x33, 0x5c, 0x10, 0x48, 0x10, 0xbb, 0x49, 0x98, 0x63, 0x04, 0xe4, 0x19, 0xfa, 0x45, 0x93, + /*ad70:*/ 0x09, 0x0d, 0xda, 0x37, 0x2e, 0xff, 0x4f, 0xaf, 0xdc, 0x3d, 0x71, 0x3e, 0x0c, 0x97, 0x3b, 0x8f, + /*ad80:*/ 0x80, 0xfc, 0x34, 0x24, 0x4e, 0x37, 0xaa, 0x11, 0xd0, 0x4a, 0x57, 0x9b, 0xa6, 0x6c, 0x4d, 0xc1, + /*ad90:*/ 0x65, 0x07, 0x6d, 0x1c, 0x9e, 0x06, 0xd9, 0xe3, 0x1a, 0x3f, 0xe0, 0xf1, 0x36, 0x9e, 0x74, 0x65, + /*ada0:*/ 0x5c, 0x75, 0xd2, 0xf5, 0xd9, 0xbc, 0x3c, 0x4f, 0x24, 0x4e, 0x04, 0x62, 0x04, 0x97, 0x3e, 0x6e, + /*adb0:*/ 0xc4, 0x01, 0x4c, 0x88, 0xfb, 0xb0, 0xdf, 0x7d, 0x45, 0xcd, 0xa0, 0xca, 0x91, 0x96, 0x11, 0x6e, + /*adc0:*/ 0x56, 0x5d, 0xe5, 0xd1, 0xf3, 0x2c, 0x4a, 0xf6, 0x07, 0xb3, 0x6d, 0xb6, 0x6b, 0x98, 0x7b, 0x9b, + /*add0:*/ 0x80, 0x7a, 0x02, 0x83, 0xc7, 0xef, 0x0e, 0x00, 0x81, 0xfc, 0x95, 0x64, 0xe4, 0xc0, 0xb3, 0xc1, + /*ade0:*/ 0x2f, 0xfe, 0x4a, 0x97, 0xa1, 0x1c, 0x68, 0xde, 0xee, 0xc6, 0xcc, 0x23, 0x33, 0x5c, 0x2b, 0xcd, + /*adf0:*/ 0xa1, 0x4b, 0xff, 0x97, 0x08, 0x01, 0x51, 0x5a, 0xc1, 0x69, 0x6a, 0xbc, 0xac, 0x3f, 0xc4, 0xf3, + /*ae00:*/ 0x5d, 0x75, 0x53, 0x23, 0x8d, 0xb5, 0x43, 0x8d, 0x2f, 0x41, 0x05, 0xd2, 0x7f, 0x88, 0xdd, 0x9e, + /*ae10:*/ 0xb8, 0x5b, 0x13, 0x34, 0x1a, 0x74, 0x5c, 0x6e, 0x81, 0xd3, 0x65, 0x6e, 0x02, 0xcf, 0xf1, 0xf2, + /*ae20:*/ 0xf2, 0x87, 0xca, 0xab, 0x11, 0x6e, 0xea, 0xf6, 0xa4, 0xa8, 0x82, 0xa8, 0x00, 0xbd, 0xc7, 0x80, + /*ae30:*/ 0x4f, 0xeb, 0x73, 0xbc, 0x9f, 0xbb, 0xc4, 0x17, 0x58, 0x68, 0x1f, 0x36, 0xfb, 0x3c, 0xda, 0xf4, + /*ae40:*/ 0xf4, 0xea, 0x6a, 0xce, 0x79, 0xe9, 0xb1, 0x83, 0x6d, 0x27, 0x22, 0xdc, 0x01, 0xf8, 0xec, 0x58, + /*ae50:*/ 0x6b, 0x58, 0x03, 0x24, 0x50, 0xeb, 0xed, 0xa9, 0x1c, 0x01, 0x1a, 0x7c, 0x50, 0xe3, 0x5e, 0x78, + /*ae60:*/ 0x90, 0xe8, 0x50, 0xfd, 0xe8, 0x34, 0xfc, 0x7c, 0x3e, 0x7b, 0x61, 0xd5, 0x93, 0x65, 0x47, 0xed, + /*ae70:*/ 0xfe, 0x63, 0xc1, 0xd1, 0x31, 0x86, 0x78, 0xa1, 0x68, 0xee, 0xfa, 0x4f, 0x5c, 0xf2, 0x45, 0x90, + /*ae80:*/ 0x7c, 0xb9, 0x6d, 0x98, 0x89, 0x3f, 0x3e, 0xc8, 0x0d, 0x02, 0xa2, 0x2e, 0xfd, 0x96, 0x3e, 0x16, + /*ae90:*/ 0xd6, 0xc8, 0x46, 0x89, 0xf5, 0x82, 0x71, 0xe7, 0x93, 0xcb, 0x57, 0x14, 0xce, 0xef, 0x51, 0x53, + /*aea0:*/ 0xaa, 0x3d, 0xe7, 0xdc, 0xbf, 0x14, 0xc1, 0x14, 0xdc, 0x24, 0xd1, 0xc9, 0x61, 0xb3, 0x0a, 0x9d, + /*aeb0:*/ 0xca, 0xcb, 0x00, 0x49, 0xc0, 0x9a, 0xbe, 0x59, 0x10, 0x9a, 0x0a, 0x75, 0x0a, 0x7a, 0x2d, 0xe2, + /*aec0:*/ 0x87, 0xe5, 0xb1, 0x32, 0x55, 0x8d, 0xd2, 0x3a, 0x0b, 0x3b, 0xd9, 0x16, 0xb1, 0x78, 0xa8, 0x83, + /*aed0:*/ 0x13, 0x30, 0x2f, 0xf8, 0xa0, 0x91, 0x55, 0xc5, 0x0b, 0x5e, 0x4a, 0x90, 0x1c, 0x10, 0x7c, 0x5a, + /*aee0:*/ 0x8e, 0x4b, 0x4b, 0xea, 0x12, 0xe2, 0x51, 0xfa, 0xc4, 0x5a, 0x52, 0x33, 0xff, 0xf9, 0x18, 0xc1, + /*aef0:*/ 0x5b, 0xa1, 0x29, 0xeb, 0x3f, 0xab, 0xf8, 0x1c, 0xa2, 0x7e, 0x97, 0xfd, 0x59, 0x04, 0x1a, 0x0c, + /*af00:*/ 0x60, 0x5e, 0x3d, 0x23, 0x5e, 0x0b, 0x8e, 0x2b, 0xf5, 0x57, 0xe7, 0x06, 0x71, 0x11, 0x68, 0xb6, + /*af10:*/ 0x5a, 0xc4, 0x49, 0xfa, 0x24, 0x17, 0xe7, 0xf7, 0xd2, 0xca, 0xc8, 0xbf, 0x5c, 0x5a, 0x98, 0xe5, + /*af20:*/ 0xb8, 0x72, 0x85, 0xb0, 0x8c, 0x4c, 0x49, 0xbc, 0x5f, 0xd5, 0xb3, 0x36, 0xa0, 0xc9, 0x59, 0xbc, + /*af30:*/ 0xc8, 0x5e, 0x00, 0xa4, 0x09, 0x95, 0x48, 0x31, 0x96, 0x76, 0x80, 0xee, 0x49, 0x9a, 0xac, 0xe4, + /*af40:*/ 0xbe, 0x94, 0xa5, 0xc6, 0x6c, 0xd0, 0xce, 0xcf, 0xa8, 0xdf, 0x61, 0xbb, 0xe5, 0x7a, 0x59, 0xe3, + /*af50:*/ 0x7d, 0xad, 0x3b, 0xa9, 0xcc, 0x26, 0xe7, 0x4e, 0x29, 0x5b, 0xed, 0x59, 0x43, 0x70, 0xdd, 0xb6, + /*af60:*/ 0xbf, 0x6c, 0xa6, 0x12, 0x87, 0xd0, 0xa2, 0x33, 0xf2, 0x9a, 0x8a, 0x39, 0xca, 0x63, 0x1e, 0x6a, + /*af70:*/ 0xf4, 0xf7, 0x4a, 0x97, 0xc6, 0x62, 0x85, 0xb1, 0x98, 0xf4, 0xbd, 0x2d, 0x2c, 0xf7, 0xe8, 0x47, + /*af80:*/ 0x73, 0x61, 0xda, 0x0b, 0xca, 0xc7, 0xa8, 0x37, 0x72, 0xdd, 0x08, 0xed, 0xfe, 0xb2, 0xc2, 0xa7, + /*af90:*/ 0x1f, 0x30, 0xce, 0x3a, 0x2e, 0xd8, 0x73, 0x77, 0xbf, 0xe1, 0x53, 0xab, 0xcf, 0xbf, 0x1d, 0xa2, + /*afa0:*/ 0x7b, 0xe6, 0x93, 0xa8, 0x0b, 0x1d, 0x7b, 0xdb, 0xaa, 0x83, 0x91, 0x76, 0x0b, 0xda, 0x09, 0x17, + /*afb0:*/ 0xe6, 0x8a, 0x25, 0x89, 0x1e, 0x9e, 0xe3, 0xec, 0xed, 0x9e, 0xfd, 0x5e, 0xb1, 0x47, 0x78, 0xd9, + /*afc0:*/ 0x1e, 0x2a, 0xfe, 0x92, 0x9b, 0x73, 0x70, 0x16, 0x2d, 0xdf, 0x76, 0x18, 0x35, 0x84, 0x40, 0xed, + /*afd0:*/ 0x42, 0xb5, 0xa6, 0x89, 0x52, 0x75, 0xf0, 0xbb, 0x20, 0xea, 0xea, 0xec, 0xa2, 0x40, 0xc8, 0x32, + /*afe0:*/ 0x82, 0xfb, 0x84, 0x0b, 0x99, 0x22, 0x39, 0x22, 0x0a, 0xde, 0x4f, 0x92, 0x96, 0xd1, 0xa5, 0xf1, + /*aff0:*/ 0x6b, 0xf4, 0x01, 0x04, 0x3d, 0x65, 0x70, 0x82, 0xe2, 0x2e, 0x76, 0xfc, 0x25, 0x81, 0x24, 0x59, + /*b000:*/ 0x7c, 0x77, 0x24, 0xab, 0x00, 0x06, 0x74, 0x9e, 0xa7, 0x6c, 0xaa, 0x04, 0x30, 0xed, 0x9d, 0xb3, + /*b010:*/ 0x56, 0xfc, 0x85, 0x8d, 0xa2, 0x90, 0xc3, 0xcd, 0x08, 0xd2, 0x71, 0xd7, 0xf2, 0x2e, 0x28, 0xfb, + /*b020:*/ 0x13, 0x28, 0xfc, 0x43, 0x40, 0x56, 0x80, 0xc4, 0x56, 0xd1, 0x39, 0x96, 0x1f, 0xdc, 0xa8, 0x70, + /*b030:*/ 0x32, 0x84, 0x40, 0xa1, 0x98, 0xb6, 0x1e, 0x7f, 0xbc, 0x05, 0xb8, 0x2c, 0x95, 0x26, 0xfd, 0x41, + /*b040:*/ 0x20, 0xbb, 0x88, 0x9f, 0x26, 0xf6, 0x4e, 0x99, 0x0e, 0x9c, 0xd9, 0xac, 0xc9, 0xcf, 0x71, 0x31, + /*b050:*/ 0xab, 0x6e, 0x05, 0xfd, 0x20, 0x69, 0x50, 0x93, 0x54, 0xe5, 0xc4, 0x0b, 0xc6, 0xa4, 0xd4, 0x00, + /*b060:*/ 0xcb, 0x58, 0x27, 0x33, 0x07, 0x01, 0xd6, 0xce, 0x25, 0xdf, 0xf9, 0x36, 0x54, 0x94, 0xf1, 0x40, + /*b070:*/ 0x61, 0x69, 0x12, 0x79, 0x5c, 0xb0, 0xf1, 0xba, 0xd2, 0x01, 0x9a, 0xd7, 0x96, 0xbe, 0x34, 0x95, + /*b080:*/ 0x06, 0xe7, 0x05, 0xc3, 0x13, 0x58, 0x4e, 0x85, 0xb6, 0xdb, 0x72, 0xba, 0x5e, 0x15, 0xc9, 0x0a, + /*b090:*/ 0x62, 0x60, 0x53, 0x3f, 0xad, 0x29, 0x3f, 0xe3, 0xe1, 0xbb, 0x23, 0xcc, 0x13, 0xb9, 0xbd, 0x85, + /*b0a0:*/ 0x5d, 0x84, 0x0b, 0x5f, 0x7c, 0x4d, 0x2e, 0x64, 0x41, 0x06, 0x39, 0x71, 0x2b, 0x30, 0x14, 0x59, + /*b0b0:*/ 0xfe, 0x18, 0x80, 0x37, 0x17, 0x9e, 0x40, 0xa8, 0x55, 0xf2, 0xf6, 0xcc, 0x4c, 0xad, 0x10, 0x88, + /*b0c0:*/ 0x70, 0x6d, 0xcc, 0x69, 0xc9, 0xfd, 0x11, 0xa3, 0xba, 0xd0, 0x6a, 0xe0, 0x65, 0xd1, 0xb8, 0x38, + /*b0d0:*/ 0x55, 0xec, 0x1a, 0x81, 0xd0, 0x51, 0x33, 0x31, 0x3b, 0x5a, 0xc9, 0x26, 0xc6, 0xf2, 0x78, 0x2d, + /*b0e0:*/ 0x8e, 0x4e, 0x22, 0x8b, 0x0d, 0x74, 0x4d, 0x36, 0x18, 0x45, 0xdc, 0x41, 0x44, 0x35, 0x6a, 0x3b, + /*b0f0:*/ 0x66, 0x2c, 0xd4, 0x61, 0x92, 0xb8, 0x48, 0xab, 0xa2, 0xb6, 0x09, 0x7f, 0xa7, 0x91, 0xe9, 0x97, + /*b100:*/ 0x53, 0x59, 0x04, 0x03, 0x00, 0x3f, 0x03, 0x1e, 0x05, 0x0e, 0x88, 0x00, 0x01, 0x01, 0xff, 0x0a, + /*b110:*/ 0x1f, 0x03, 0xff, 0x04, 0x1e, 0x06, 0x2d, 0x5c, 0x0f, 0x8d, 0x03, 0x01, 0x34, 0xfe, 0x33, 0xff, + /*b120:*/ 0x78, 0x43, 0xfd, 0x43, 0x50, 0xc3, 0x38, 0xc7, 0x00, 0x18, 0x20, 0x20, 0x20, 0x20, 0x14, 0x02, + /*b130:*/ 0x0c, 0x32, 0xe3, 0xbc, 0x00, 0x00, 0x05, 0x28, 0x0a, 0x2d, 0x00, 0x28, 0x0a, 0x32, 0x00, 0xc4, + /*b140:*/ 0x09, 0x3c, 0x00, 0xf0, 0x0a, 0x50, 0x00, 0x1e, 0x1e, 0x8c, 0x00, 0x96, 0x00, 0x14, 0x0a, 0x04, + /*b150:*/ 0x29, 0x1a, 0x64, 0x07, 0x66, 0x64, 0xc0, 0x20, 0x02, 0xaf, 0x00, 0x03, 0x0e, 0x1f, 0x08, 0x2a, + /*b160:*/ 0x00, 0x20, 0x04, 0x1b, 0x00, 0x80, 0x14, 0xc0, 0xc8, 0xc8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0x38, + /*b170:*/ 0x37, 0x35, 0x34, 0x32, 0x31, 0x2f, 0x2d, 0x01, 0x04, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x13, 0x00, + /*b180:*/ 0x00, 0x00, 0x40, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x20, 0x20, 0x20, 0x20, + /*b190:*/ 0x20, 0x20, 0x20, 0x10, 0x5a, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d, 0x39, 0x00, 0x0a, 0x00, 0x10, + /*b1a0:*/ 0x27, 0x66, 0x12, 0xd4, 0x10, 0xff, 0x1a, 0x00, 0x28, 0x28, 0x1c, 0x26, 0x66, 0x66, 0x66, 0x66, + /*b1b0:*/ 0x66, 0x66, 0x66, 0xff, 0xc8, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, + /*b1c0:*/ 0x04, 0x20, 0x40, 0x03, 0x00, 0x1f, 0x00, 0x1d, 0x2d, 0x1d, 0x2b, 0x1d, 0x28, 0x1d, 0x2c, 0x1d, + /*b1d0:*/ 0x20, 0xd9, 0x73, 0xca, 0x73, 0xd9, 0xcd, 0x0d, 0x04, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + /*b1e0:*/ 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + /*b1f0:*/ 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + /*b200:*/ 0x27, 0x29, 0x2a, 0x2d, 0x2b, 0x28, 0x2c, 0x20, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x14, + /*b210:*/ 0x12, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, + /*b220:*/ 0x01, 0x00, 0x1d, 0x66, 0x66, 0x6d, 0x6d, 0x73, 0x73, 0x7a, 0x7a, 0x80, 0x80, 0x86, 0x86, 0x8d, + /*b230:*/ 0x8d, 0x93, 0x93, 0x9a, 0x9a, 0xa0, 0xa0, 0xa6, 0xa6, 0xad, 0xad, 0xb3, 0xb3, 0x80, 0x80, 0x80, + /*b240:*/ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /*b250:*/ 0x80, 0x0a, 0x1c, 0x2b, 0x1e, 0x0a, 0x80, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b260:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b270:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b280:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b290:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xb8, 0x19, 0xcc, + /*b300:*/ 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b310:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b320:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b330:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b340:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b350:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b360:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b370:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b380:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b390:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b400:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b410:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b420:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b430:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b440:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + /*b450:*/ 0x3f, 0x03, 0x1e, 0x05, 0x0e, 0x08, 0x00, 0x19, 0x19, 0x00, 0x10, 0xe2, 0x04, 0xb6, 0x08, 0x1e, + /*b460:*/ 0x05, 0x28, 0xf5, 0x28, 0x1e, 0x05, 0x01, 0x30, 0x00, 0x30, 0x00, 0x00, 0x50, 0x00, 0x50, 0xf0, + /*b470:*/ 0xd2, 0xf0, 0xd2, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x04, 0xc0, 0x32, 0x70, 0x00, 0x00, + /*b480:*/ 0x00, 0x80, 0x04, 0x2e, 0x1b, 0x64, 0x07, 0x00, 0x00, 0x56, 0x35, 0x05, 0x10, 0x00, 0x00, 0x0b, + /*b490:*/ 0x20, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x37, 0x33, + /*b4a0:*/ 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x03, 0x0f, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf0, + /*b4b0:*/ 0x15, 0x1b, 0x2e, 0x49, 0x40, 0xff, 0x0b, 0x20, 0x0c, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + /*b4c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b4d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x88, 0x55, + /*b4e0:*/ 0x15, 0x21, 0x11, 0x92, 0x87, 0x4f, 0x13, 0x01, 0x01, 0x89, 0x00, 0x4b, 0x00, 0x01, 0x34, 0x00, + /*b4f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b500:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b510:*/ 0x00, 0x02, 0x5e, 0x01, 0x03, 0x0e, 0x1f, 0x00, 0xde, 0x01, 0x19, 0x04, 0x1b, 0x00, 0x10, 0x0a, + /*b520:*/ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b530:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x05, 0x00, 0x00, + /*b540:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, + /*b550:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x28, 0x00, 0x77, 0x18, 0x80, 0x18, 0x80, 0x1a, + /*b560:*/ 0x01, 0x19, 0x3f, 0x4d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x10, 0x0a, 0x00, 0x00, + /*b570:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x04, 0x40, 0x40, 0x03, 0x00, 0x2e, 0x1b, + /*b580:*/ 0x44, 0x00, 0x19, 0x01, 0x00, 0xbe, 0x00, 0xde, 0x3f, 0xd0, 0x80, 0x08, 0x03, 0x00, 0x00, 0x00, + /*b590:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7d, 0x10, 0x00, 0x01, 0x54, 0x00, + /*b5f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b600:*/ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x51, 0x51, + /*b610:*/ 0x51, 0x51, 0x51, 0xcd, 0x0d, 0x04, 0x00, 0x00, 0x1c, 0x80, 0x00, 0x04, 0xff, 0x2e, 0x1b, 0x05, + /*b620:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b630:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b640:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b650:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b660:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b670:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b680:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b690:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6e0:*/ 0x00, 0x00, 0x00, 0x1d, 0x1a, 0x16, 0x00, 0x01, 0x55, 0x1b, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x00, + /*b6f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b700:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b710:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b720:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x32, 0x00, 0x1e, 0x04, 0x80, 0xc0, 0x04, + /*b730:*/ 0x28, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b740:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b750:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b760:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b770:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b780:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b790:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x28, 0x00, 0x00, 0x51, 0x00, + /*b7f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b800:*/ 0xff}; +#else +const u8 rmi_fw_button[] = { + /*0000:*/ 0xaf, 0xee, 0x17, 0x5c, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + /*0010:*/ 0x53, 0x37, 0x33, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0020:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0030:*/ 0x44, 0x53, 0x34, 0x20, 0x52, 0x33, 0x2e, 0x35, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0040:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0050:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0060:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0070:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0080:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0090:*/ 0x49, 0x32, 0x43, 0x00, 0x04, 0x00, 0xff, 0x00, 0x0c, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + /*00a0:*/ 0x49, 0x32, 0x43, 0x00, 0x04, 0x00, 0xff, 0x00, 0x0c, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + /*00b0:*/ 0x69, 0x96, 0x7e, 0xd0, 0x20, 0x5a, 0x00, 0x20, 0xc5, 0xc0, 0x2a, 0x79, 0xac, 0x74, 0x2e, 0x45, + /*00c0:*/ 0x57, 0x05, 0x48, 0x7c, 0xd7, 0x03, 0xb0, 0x50, 0xe0, 0x77, 0x3c, 0x8b, 0x79, 0xf6, 0x71, 0x75, + /*00d0:*/ 0xca, 0xec, 0xb0, 0x31, 0x53, 0xaa, 0x37, 0xe9, 0x19, 0x47, 0x46, 0x84, 0xba, 0x28, 0x18, 0xe9, + /*00e0:*/ 0x51, 0x89, 0xe7, 0xce, 0x3e, 0x64, 0x26, 0xa6, 0x25, 0x31, 0xc5, 0x0d, 0x9a, 0xa9, 0x93, 0xfa, + /*00f0:*/ 0x7c, 0x9a, 0x20, 0x17, 0x1a, 0x92, 0x35, 0xa6, 0x9a, 0x75, 0xa0, 0x23, 0x4f, 0xb1, 0xec, 0x1e, + /*0100:*/ 0x64, 0xce, 0x5c, 0x97, 0x6f, 0xf6, 0x36, 0x81, 0xf8, 0x90, 0x17, 0xb0, 0x0d, 0x0c, 0xd3, 0x50, + /*0110:*/ 0x2b, 0xb3, 0x37, 0x31, 0xe9, 0x03, 0x0c, 0x63, 0xf1, 0x9e, 0x52, 0x2d, 0xf5, 0xd3, 0x44, 0x87, + /*0120:*/ 0xa3, 0xef, 0xc0, 0x55, 0xf3, 0xca, 0x62, 0x4f, 0xc8, 0x13, 0xbd, 0x20, 0xe6, 0x3a, 0xac, 0xcd, + /*0130:*/ 0x2b, 0x4b, 0x2c, 0x18, 0x21, 0x16, 0xf3, 0xb6, 0xaa, 0x41, 0xe2, 0x66, 0xfc, 0x6f, 0x1f, 0xce, + /*0140:*/ 0x7f, 0x17, 0xdd, 0xfd, 0x49, 0xde, 0x8b, 0x2b, 0xec, 0xf9, 0xe4, 0xed, 0xaf, 0x8c, 0x26, 0xe0, + /*0150:*/ 0xb5, 0x30, 0xde, 0x4b, 0xb9, 0x9e, 0x4d, 0xfe, 0x43, 0x86, 0xce, 0x9e, 0x0b, 0x6f, 0xb9, 0xc8, + /*0160:*/ 0x1e, 0xcb, 0x83, 0xee, 0xdb, 0xf3, 0xcb, 0x5f, 0xa2, 0x9b, 0xba, 0x53, 0x3d, 0xde, 0x85, 0xce, + /*0170:*/ 0xda, 0xdc, 0xfd, 0x86, 0xe6, 0xdc, 0xb0, 0x14, 0xc0, 0x87, 0x68, 0x6d, 0x15, 0x39, 0x99, 0x81, + /*0180:*/ 0xf4, 0x8f, 0xfa, 0x4b, 0x47, 0x53, 0x99, 0x05, 0xe8, 0x9f, 0xd7, 0x8c, 0x0a, 0xdd, 0x12, 0x95, + /*0190:*/ 0xc6, 0xd0, 0xe3, 0xf9, 0x2c, 0xb0, 0xee, 0x4f, 0x50, 0x51, 0x9e, 0x2c, 0x7f, 0x07, 0xd7, 0xd7, + /*01a0:*/ 0xa6, 0xfc, 0x58, 0x56, 0x65, 0x04, 0x49, 0x73, 0x05, 0x3e, 0xd2, 0xe9, 0x37, 0xb8, 0xd7, 0xbc, + /*01b0:*/ 0x79, 0x5f, 0x8c, 0xc7, 0x28, 0xe6, 0x39, 0xef, 0x29, 0x7f, 0x26, 0x52, 0xd8, 0xda, 0x99, 0x4c, + /*01c0:*/ 0x6b, 0x6e, 0x7a, 0xd3, 0x9e, 0x75, 0xca, 0x55, 0xb2, 0x29, 0x88, 0xb8, 0x0b, 0x1d, 0x1c, 0x81, + /*01d0:*/ 0x98, 0x15, 0xf7, 0x59, 0x1d, 0x73, 0xc3, 0x8d, 0x42, 0x5e, 0xce, 0x78, 0x9b, 0x36, 0x49, 0xbe, + /*01e0:*/ 0xad, 0xc9, 0x81, 0xa4, 0x7e, 0x4c, 0xcb, 0x35, 0x52, 0x17, 0xd7, 0x73, 0x29, 0x4e, 0x81, 0xdf, + /*01f0:*/ 0x66, 0x04, 0x1d, 0x49, 0x3f, 0xa0, 0xf2, 0x2f, 0x42, 0xd0, 0xf4, 0xe9, 0x49, 0xae, 0x52, 0xf7, + /*0200:*/ 0xce, 0x67, 0x45, 0x5c, 0x59, 0x91, 0xb0, 0x83, 0xc0, 0x2e, 0xf4, 0x77, 0xcb, 0x65, 0xb5, 0xd3, + /*0210:*/ 0x18, 0x15, 0x9e, 0x05, 0x30, 0x8f, 0xb7, 0xb8, 0x40, 0x1f, 0x71, 0xb1, 0x0f, 0x81, 0x03, 0x89, + /*0220:*/ 0xb7, 0x6d, 0xef, 0x46, 0x6e, 0x45, 0x46, 0xc5, 0xd3, 0x94, 0x92, 0x41, 0xca, 0xc5, 0x32, 0xac, + /*0230:*/ 0x34, 0x10, 0x2b, 0x1a, 0x4f, 0xec, 0x94, 0xcf, 0x91, 0xd9, 0x80, 0xf1, 0x60, 0x9d, 0xe7, 0x63, + /*0240:*/ 0x51, 0xa7, 0xec, 0xe6, 0x1d, 0xf8, 0x38, 0xc7, 0xec, 0xe7, 0x69, 0x08, 0x02, 0x7b, 0x09, 0x89, + /*0250:*/ 0x84, 0x9a, 0xbd, 0x1f, 0x04, 0x9f, 0xf3, 0x20, 0xc8, 0x23, 0x4c, 0xd7, 0x0a, 0x64, 0x47, 0x43, + /*0260:*/ 0xb6, 0xc8, 0xad, 0xb7, 0xd5, 0xa4, 0xb0, 0xea, 0x57, 0x8d, 0xe9, 0x4e, 0x18, 0x81, 0x08, 0x26, + /*0270:*/ 0x68, 0x66, 0xe6, 0x0b, 0xb2, 0x5d, 0xf5, 0xc3, 0xc1, 0xc1, 0x25, 0x84, 0xdd, 0x00, 0x34, 0x10, + /*0280:*/ 0x94, 0xb6, 0xaf, 0x9f, 0x6a, 0xd5, 0x34, 0x1e, 0x9a, 0x42, 0xd0, 0xa7, 0xc9, 0xd7, 0x3f, 0xc3, + /*0290:*/ 0x43, 0xf2, 0x80, 0x94, 0x2e, 0xb9, 0xdb, 0x60, 0x76, 0xc5, 0xf5, 0x6f, 0xe8, 0x83, 0x96, 0x1b, + /*02a0:*/ 0x96, 0x80, 0xed, 0xb4, 0x0b, 0xc3, 0x34, 0x92, 0xa3, 0xe7, 0xb8, 0x07, 0x23, 0x1b, 0x1b, 0x44, + /*02b0:*/ 0x4a, 0x09, 0xf5, 0xb9, 0x50, 0x75, 0xf2, 0xd6, 0x75, 0xae, 0xef, 0xfa, 0x29, 0x4f, 0x7a, 0xf0, + /*02c0:*/ 0xfa, 0x01, 0xf4, 0x0c, 0x67, 0x2c, 0x2d, 0x36, 0x75, 0xfb, 0xe9, 0xaa, 0xf5, 0x4b, 0x87, 0xbb, + /*02d0:*/ 0xb8, 0xe7, 0x62, 0x4f, 0xbb, 0xc1, 0xc7, 0xd6, 0xa4, 0x10, 0xa3, 0xca, 0xb9, 0x80, 0x7a, 0x1e, + /*02e0:*/ 0xb0, 0xc5, 0xaa, 0x84, 0x0e, 0xe8, 0x10, 0x25, 0xa4, 0xd5, 0x1d, 0xc3, 0x2f, 0x11, 0x8e, 0xdc, + /*02f0:*/ 0xae, 0x9d, 0x51, 0x75, 0x40, 0x9e, 0x92, 0xec, 0x94, 0xff, 0x24, 0xbd, 0x00, 0x51, 0x43, 0x15, + /*0300:*/ 0x22, 0x7f, 0x7e, 0x22, 0xfa, 0x57, 0x2b, 0x1c, 0xf3, 0xb1, 0x11, 0x62, 0x0d, 0xb3, 0x68, 0x1a, + /*0310:*/ 0x6f, 0x2c, 0xb1, 0x6a, 0x0a, 0xb6, 0xc0, 0x8e, 0x14, 0x2f, 0x49, 0xd6, 0x65, 0x77, 0xb9, 0xfb, + /*0320:*/ 0x62, 0x78, 0xbf, 0x05, 0x1d, 0x37, 0xc7, 0x59, 0xa0, 0x1a, 0x8e, 0xb3, 0x08, 0x07, 0x69, 0x12, + /*0330:*/ 0x8b, 0xa1, 0x36, 0xd2, 0x42, 0xfe, 0x5a, 0xf7, 0xa6, 0xfd, 0x8b, 0x27, 0x6d, 0x1d, 0x3b, 0x8b, + /*0340:*/ 0xcb, 0xe9, 0x2b, 0x3f, 0xdd, 0xe0, 0xa4, 0x4e, 0x97, 0x41, 0x72, 0x15, 0xfc, 0x7a, 0x40, 0x84, + /*0350:*/ 0x24, 0x56, 0x76, 0xdd, 0x7b, 0xb8, 0xf6, 0xdc, 0x15, 0x01, 0x4a, 0x5f, 0x21, 0xae, 0xc0, 0xbd, + /*0360:*/ 0x14, 0x83, 0x35, 0x64, 0x54, 0x7d, 0xb5, 0x8b, 0xc6, 0x8d, 0xe0, 0x6a, 0xe4, 0x2b, 0x69, 0x49, + /*0370:*/ 0xd1, 0x0b, 0x17, 0x27, 0x09, 0x9a, 0x52, 0x82, 0x57, 0x90, 0x2f, 0x24, 0x43, 0xc3, 0x9d, 0x7d, + /*0380:*/ 0x31, 0x26, 0x6f, 0x54, 0x7d, 0xb6, 0x51, 0x15, 0x47, 0x4e, 0x9e, 0x96, 0x81, 0x29, 0xcb, 0xaa, + /*0390:*/ 0x01, 0xee, 0x77, 0x57, 0xc0, 0xf6, 0xb4, 0xe0, 0xd7, 0x90, 0xa9, 0x44, 0x2c, 0xe3, 0xa9, 0x32, + /*03a0:*/ 0x17, 0x3d, 0x5c, 0xe3, 0xc9, 0x82, 0xb2, 0x56, 0xb3, 0x9b, 0xda, 0xd6, 0x7c, 0x7d, 0x64, 0xd4, + /*03b0:*/ 0xe4, 0x39, 0x0d, 0xcc, 0xf3, 0x02, 0x59, 0xbe, 0x4b, 0x58, 0x4e, 0x1f, 0x47, 0x46, 0x55, 0x97, + /*03c0:*/ 0x67, 0xe7, 0xdc, 0x2f, 0xb1, 0x91, 0x81, 0x0b, 0x46, 0x97, 0x78, 0x25, 0x29, 0xb0, 0x7f, 0xa2, + /*03d0:*/ 0xb9, 0xfa, 0xf4, 0x20, 0x19, 0xab, 0xae, 0xf4, 0x7e, 0x74, 0x92, 0xf3, 0x63, 0x97, 0x05, 0xf4, + /*03e0:*/ 0x8c, 0xc8, 0xfb, 0xa7, 0x6f, 0xdf, 0x2d, 0xa8, 0x80, 0x17, 0x0c, 0x37, 0x6d, 0xe4, 0x97, 0x5b, + /*03f0:*/ 0xa4, 0x1d, 0xda, 0xb7, 0x45, 0xf0, 0xce, 0x7d, 0x31, 0xcc, 0xc2, 0x29, 0x37, 0xd1, 0x8c, 0x3d, + /*0400:*/ 0xcc, 0xa2, 0xf0, 0x70, 0x16, 0x9b, 0x87, 0xc6, 0x97, 0x20, 0x99, 0x8b, 0xb4, 0xb5, 0x39, 0xf7, + /*0410:*/ 0x7c, 0x7f, 0x86, 0x37, 0x79, 0x6e, 0x8b, 0x1b, 0xbf, 0xfb, 0x68, 0xd3, 0xf4, 0x61, 0x58, 0xe5, + /*0420:*/ 0x8a, 0xb0, 0xee, 0x70, 0x06, 0x18, 0x0c, 0x6b, 0x64, 0xf3, 0xb0, 0x64, 0x30, 0xee, 0xd3, 0xd1, + /*0430:*/ 0xa8, 0xe1, 0x30, 0xfc, 0x82, 0x36, 0x67, 0x93, 0x05, 0x6b, 0x4a, 0x33, 0x93, 0x5b, 0x8d, 0xdf, + /*0440:*/ 0xf4, 0x19, 0x3b, 0x85, 0xf0, 0x36, 0xf7, 0x50, 0xaa, 0x5e, 0xf7, 0x83, 0x93, 0x67, 0x78, 0x33, + /*0450:*/ 0x77, 0x3f, 0x9e, 0x34, 0x06, 0x6c, 0xcb, 0xc3, 0x00, 0x7f, 0xea, 0x39, 0x6d, 0xc5, 0x5e, 0x91, + /*0460:*/ 0xb1, 0x00, 0xbe, 0x6f, 0x08, 0x96, 0x01, 0xe4, 0xcb, 0x9f, 0x92, 0x79, 0x50, 0xaa, 0xda, 0x1e, + /*0470:*/ 0xec, 0x12, 0x2b, 0x4b, 0x0a, 0xa3, 0xcf, 0x8c, 0x1f, 0x4b, 0x15, 0xee, 0xec, 0x18, 0xa6, 0xfe, + /*0480:*/ 0xd5, 0x73, 0x82, 0x1d, 0x6e, 0x21, 0x8c, 0xe5, 0xf4, 0x36, 0x83, 0x9e, 0x00, 0x7b, 0x60, 0x9f, + /*0490:*/ 0x0d, 0xb4, 0x60, 0x70, 0xe0, 0x99, 0xc6, 0x55, 0xb9, 0xee, 0x3e, 0x24, 0x06, 0x15, 0x79, 0x0d, + /*04a0:*/ 0xa6, 0xc7, 0x79, 0x97, 0x01, 0x5c, 0x52, 0x38, 0xfa, 0x5b, 0x71, 0x38, 0xfa, 0xbf, 0xa0, 0x2c, + /*04b0:*/ 0x2c, 0x9d, 0x25, 0xfa, 0x70, 0xd7, 0x32, 0xb1, 0x33, 0xb6, 0xcd, 0xcd, 0xcd, 0xf6, 0x97, 0x3b, + /*04c0:*/ 0x3b, 0x0a, 0x33, 0xbb, 0x7a, 0xa5, 0x89, 0x14, 0xa6, 0x15, 0x44, 0xdb, 0x91, 0x07, 0x75, 0x48, + /*04d0:*/ 0xd5, 0x45, 0x46, 0x71, 0x1c, 0xf2, 0x12, 0xbc, 0x61, 0x70, 0x50, 0x56, 0xd3, 0x21, 0x5d, 0xc4, + /*04e0:*/ 0x29, 0x9f, 0x04, 0xfe, 0xe8, 0xdb, 0x77, 0x42, 0xde, 0xf3, 0xef, 0x2b, 0xfb, 0x34, 0xe7, 0x00, + /*04f0:*/ 0x8a, 0x50, 0x40, 0x3f, 0x62, 0x3d, 0x94, 0x49, 0xd2, 0x95, 0x27, 0xec, 0x86, 0xcd, 0xa2, 0x05, + /*0500:*/ 0xac, 0xfe, 0xb0, 0x83, 0xee, 0x52, 0x05, 0x7c, 0x40, 0x27, 0x4b, 0xc7, 0x93, 0xaa, 0x92, 0xce, + /*0510:*/ 0x72, 0x70, 0x8d, 0x9a, 0x5b, 0x88, 0x6b, 0x59, 0xa7, 0x61, 0xf7, 0x12, 0xe8, 0x61, 0xb6, 0x23, + /*0520:*/ 0xe8, 0xd3, 0xfc, 0x6a, 0xec, 0x4a, 0x05, 0xcd, 0x49, 0x74, 0xf4, 0xcb, 0x0e, 0xe3, 0x95, 0x95, + /*0530:*/ 0x0e, 0xc3, 0xd7, 0x9e, 0xb6, 0x6e, 0xcb, 0x4f, 0xdc, 0xe3, 0x3d, 0x87, 0x23, 0x3a, 0xc8, 0x8d, + /*0540:*/ 0x4f, 0x7b, 0xd8, 0xe9, 0x12, 0x46, 0x92, 0x0c, 0x75, 0xe0, 0x6b, 0x35, 0xf1, 0x82, 0xbc, 0xbb, + /*0550:*/ 0x09, 0x3f, 0xf9, 0xa7, 0xb6, 0x29, 0x62, 0x64, 0x09, 0x02, 0x5b, 0xf7, 0x47, 0xac, 0x69, 0xe5, + /*0560:*/ 0xb9, 0x7a, 0x6a, 0x7b, 0xb1, 0xad, 0xf4, 0x5f, 0xa4, 0x2c, 0x31, 0x06, 0x69, 0x63, 0x25, 0x32, + /*0570:*/ 0x75, 0x35, 0x95, 0x06, 0x41, 0xf8, 0x40, 0xce, 0x35, 0x2c, 0xad, 0x9b, 0xfb, 0xc0, 0x87, 0xed, + /*0580:*/ 0xe9, 0xd9, 0xe1, 0x65, 0x45, 0xc1, 0x98, 0x87, 0x0f, 0x2d, 0xc9, 0x38, 0xbc, 0x24, 0xdb, 0xa7, + /*0590:*/ 0x51, 0xae, 0x04, 0xa8, 0x3e, 0x1f, 0xab, 0xd4, 0xbb, 0x00, 0x08, 0x93, 0xc3, 0xcf, 0x15, 0x94, + /*05a0:*/ 0x2c, 0xd9, 0xa4, 0x0f, 0xb1, 0xc4, 0xda, 0xc6, 0xac, 0x24, 0x17, 0x8a, 0xda, 0xab, 0x4e, 0xa7, + /*05b0:*/ 0xeb, 0xeb, 0xc2, 0xdd, 0x01, 0x51, 0xfd, 0xc2, 0xf9, 0x3a, 0x2b, 0x97, 0x19, 0x3f, 0x1a, 0x84, + /*05c0:*/ 0x65, 0x14, 0xd6, 0xac, 0xf8, 0xbd, 0xe5, 0xa3, 0xb4, 0x19, 0x4b, 0xbe, 0x02, 0xe7, 0x71, 0xff, + /*05d0:*/ 0x14, 0xbe, 0xfa, 0x49, 0x20, 0x50, 0x74, 0x43, 0x68, 0x23, 0x86, 0x4b, 0xe3, 0xbe, 0x4d, 0x16, + /*05e0:*/ 0x93, 0xd0, 0xcf, 0xa5, 0x5a, 0x56, 0x0a, 0x4e, 0x05, 0xf0, 0x24, 0xf0, 0xe9, 0xbb, 0xf3, 0xd2, + /*05f0:*/ 0xcf, 0xaa, 0x1d, 0x6b, 0x99, 0x31, 0x79, 0xd8, 0x26, 0xc8, 0x0a, 0xa4, 0x32, 0xb1, 0xe2, 0x0c, + /*0600:*/ 0xaa, 0xb4, 0xe0, 0x05, 0xc4, 0x60, 0xb9, 0xdf, 0xad, 0x95, 0x51, 0x29, 0xbc, 0xa8, 0xcb, 0xae, + /*0610:*/ 0xc3, 0x75, 0xbf, 0x42, 0x8f, 0x02, 0xe8, 0xf1, 0x74, 0x2a, 0x93, 0x98, 0xce, 0x7e, 0x13, 0xd5, + /*0620:*/ 0xd6, 0x2c, 0xd5, 0x08, 0x45, 0xe2, 0x6d, 0xe1, 0x2a, 0x63, 0x8d, 0xa4, 0x3e, 0xab, 0x73, 0x6d, + /*0630:*/ 0x4c, 0x06, 0xf8, 0x44, 0x5a, 0xb1, 0x65, 0x0f, 0x1d, 0xf3, 0xcd, 0xf2, 0x3e, 0xde, 0xa2, 0x12, + /*0640:*/ 0xe6, 0x1c, 0xbd, 0x84, 0x65, 0x13, 0xb5, 0x3c, 0x9a, 0xa8, 0x17, 0xc3, 0x9e, 0xb4, 0xab, 0x52, + /*0650:*/ 0x30, 0x4c, 0x0a, 0xc2, 0xff, 0x20, 0x4b, 0xb4, 0x8e, 0xf9, 0x4a, 0xb6, 0x21, 0xaa, 0x47, 0x68, + /*0660:*/ 0x61, 0x6f, 0x81, 0x0e, 0x36, 0xe7, 0x19, 0x2f, 0x68, 0xbb, 0x18, 0x29, 0xdd, 0xf1, 0xc3, 0x57, + /*0670:*/ 0x9a, 0xe0, 0x66, 0x47, 0xda, 0xe2, 0x24, 0x27, 0xb7, 0x75, 0x6d, 0x99, 0x5f, 0x94, 0x5b, 0xae, + /*0680:*/ 0x60, 0xde, 0xc2, 0x2a, 0xd5, 0x36, 0x24, 0x61, 0x6a, 0x39, 0x08, 0x32, 0x18, 0x04, 0x41, 0x0f, + /*0690:*/ 0x24, 0xc2, 0x4a, 0x5f, 0xa2, 0x32, 0xf6, 0x8a, 0xe4, 0x03, 0x9e, 0x85, 0xb0, 0xe6, 0x5b, 0xeb, + /*06a0:*/ 0x15, 0x21, 0xce, 0xc7, 0xdc, 0x90, 0xfb, 0x22, 0x94, 0xf1, 0x77, 0x1b, 0x60, 0x17, 0x97, 0x6e, + /*06b0:*/ 0x19, 0x51, 0xde, 0xf6, 0x73, 0xa5, 0xf1, 0xf5, 0x71, 0xc5, 0xa2, 0x44, 0x61, 0x20, 0xe3, 0x08, + /*06c0:*/ 0x82, 0xd6, 0x9f, 0xfe, 0xdb, 0x11, 0x10, 0xfb, 0x38, 0x72, 0x9e, 0x3a, 0x1b, 0xa2, 0x28, 0xdb, + /*06d0:*/ 0x37, 0xef, 0xaf, 0x13, 0x6b, 0xde, 0x35, 0xa3, 0xc0, 0x42, 0x2c, 0xd3, 0xe0, 0x11, 0xe9, 0xe4, + /*06e0:*/ 0x94, 0x9c, 0x1e, 0xe4, 0x01, 0x02, 0x22, 0x8c, 0x13, 0x27, 0xda, 0xe6, 0x30, 0x61, 0x67, 0xca, + /*06f0:*/ 0x40, 0x87, 0x06, 0xce, 0x72, 0xa7, 0x14, 0x15, 0xa7, 0xe6, 0xa3, 0x7c, 0x51, 0xb7, 0xdd, 0x3e, + /*0700:*/ 0x2b, 0x8c, 0x7d, 0x56, 0x86, 0xb8, 0x3e, 0x17, 0xe8, 0x73, 0xce, 0xe8, 0x4a, 0xd9, 0xac, 0x9b, + /*0710:*/ 0x2b, 0x09, 0x3a, 0xb0, 0xb3, 0x96, 0xad, 0x98, 0xfd, 0x55, 0xdc, 0x0f, 0xf0, 0x1c, 0xaa, 0x8a, + /*0720:*/ 0xba, 0x6a, 0xfb, 0xf1, 0xac, 0x36, 0x35, 0x02, 0x42, 0x85, 0x6a, 0x81, 0x41, 0x78, 0xe1, 0x75, + /*0730:*/ 0xc2, 0x55, 0x5e, 0x15, 0x4c, 0x99, 0x22, 0xcc, 0x19, 0xc4, 0x91, 0x32, 0x80, 0x70, 0xa6, 0x7a, + /*0740:*/ 0x76, 0xa4, 0xfb, 0xfb, 0xa3, 0x94, 0x5d, 0xc7, 0x01, 0x92, 0x9a, 0xc7, 0xc1, 0x6f, 0x0e, 0x20, + /*0750:*/ 0xbc, 0x3d, 0x84, 0xf7, 0xa9, 0xe5, 0x6d, 0x72, 0x8c, 0x8a, 0x82, 0xfc, 0x53, 0x80, 0xdf, 0x34, + /*0760:*/ 0x82, 0xff, 0x69, 0xcb, 0x33, 0xbc, 0xeb, 0x6c, 0xe4, 0xbd, 0x9d, 0xc4, 0x67, 0xdc, 0x25, 0x55, + /*0770:*/ 0x51, 0xb5, 0x5f, 0xf5, 0x5c, 0xe4, 0x35, 0xfc, 0x55, 0xe5, 0x2d, 0xdf, 0x51, 0x2c, 0xcc, 0x28, + /*0780:*/ 0xaa, 0xe4, 0x7b, 0x5f, 0x87, 0x2a, 0x79, 0x48, 0xf3, 0xf6, 0xaf, 0x22, 0xf1, 0xe3, 0x62, 0x29, + /*0790:*/ 0x31, 0x65, 0x87, 0xef, 0x97, 0xa7, 0x18, 0xf6, 0xf4, 0xc7, 0x71, 0x5d, 0x53, 0xd5, 0x1b, 0x20, + /*07a0:*/ 0x4f, 0x15, 0x4b, 0x20, 0x3a, 0x5d, 0x37, 0xbb, 0x90, 0x80, 0xf3, 0xc2, 0xd0, 0x37, 0xb0, 0xe9, + /*07b0:*/ 0xad, 0xab, 0x28, 0xf4, 0x20, 0x23, 0x3d, 0x53, 0x68, 0xff, 0x00, 0x39, 0x99, 0x17, 0xde, 0xd1, + /*07c0:*/ 0x0d, 0x8d, 0xd9, 0x84, 0x03, 0xb9, 0x2b, 0x20, 0x8c, 0x98, 0x00, 0xbf, 0x59, 0x9c, 0xe8, 0xba, + /*07d0:*/ 0x29, 0x3f, 0xf8, 0x5c, 0x5b, 0xd2, 0xf3, 0x76, 0xf6, 0xac, 0x0b, 0x9e, 0x8d, 0xf4, 0x2a, 0xb2, + /*07e0:*/ 0x4e, 0xaf, 0xb9, 0xe9, 0xd1, 0xb3, 0x40, 0xa6, 0x08, 0xc5, 0x1a, 0x31, 0xb4, 0xd8, 0x05, 0x24, + /*07f0:*/ 0xdf, 0x29, 0xf0, 0xc0, 0xf6, 0x90, 0x0f, 0x0c, 0x72, 0xdb, 0x4d, 0x32, 0xbe, 0xd6, 0x72, 0x57, + /*0800:*/ 0xe3, 0xc3, 0xaa, 0x3c, 0x4b, 0x12, 0xea, 0xc8, 0xf6, 0xb8, 0x0f, 0xdf, 0xa9, 0x21, 0x8a, 0x20, + /*0810:*/ 0xfc, 0x2a, 0x14, 0xa0, 0x9d, 0xb4, 0xea, 0xbf, 0x09, 0xbe, 0xca, 0x32, 0xff, 0xd8, 0xfc, 0x91, + /*0820:*/ 0x2c, 0xf4, 0x58, 0x67, 0x79, 0x4a, 0xb7, 0x0f, 0x9d, 0x30, 0xf9, 0x8d, 0xbd, 0xaf, 0x28, 0x3b, + /*0830:*/ 0xdf, 0x8b, 0xa2, 0x83, 0xb1, 0xef, 0x3a, 0x1a, 0x8e, 0xff, 0x59, 0x1b, 0x25, 0xf7, 0x0f, 0x30, + /*0840:*/ 0x34, 0xc4, 0xbe, 0x4a, 0x41, 0xc4, 0x37, 0xf9, 0x59, 0x07, 0x42, 0x20, 0x28, 0xac, 0xca, 0x32, + /*0850:*/ 0xed, 0xd2, 0x03, 0x06, 0xa7, 0x96, 0x69, 0xb7, 0xe9, 0xde, 0xc8, 0x28, 0x06, 0xd8, 0x4d, 0xe7, + /*0860:*/ 0xab, 0xd5, 0xef, 0x00, 0x0f, 0x45, 0x50, 0xfb, 0x50, 0xbf, 0x79, 0x7d, 0xdc, 0x50, 0xa9, 0xec, + /*0870:*/ 0xbb, 0x92, 0x31, 0xce, 0x44, 0x9c, 0x06, 0x33, 0x8f, 0x39, 0x74, 0x74, 0xf4, 0x6c, 0xd6, 0xa6, + /*0880:*/ 0x8f, 0x50, 0x2b, 0x09, 0x1e, 0xeb, 0x31, 0x98, 0xc6, 0xfc, 0xfc, 0x40, 0x45, 0x45, 0x85, 0x82, + /*0890:*/ 0xa9, 0x4d, 0xd0, 0xfa, 0xd1, 0xe6, 0x0c, 0xda, 0x0a, 0x59, 0x2b, 0x7d, 0x9e, 0x93, 0x4e, 0x41, + /*08a0:*/ 0xce, 0x96, 0xc9, 0x9a, 0x7b, 0xd4, 0x83, 0xe8, 0x43, 0xdb, 0xb5, 0x6d, 0xe8, 0x1a, 0xa6, 0xe8, + /*08b0:*/ 0xf0, 0x5f, 0x7f, 0xf3, 0x40, 0x2c, 0x86, 0xbb, 0x7e, 0xfc, 0xa2, 0x64, 0xef, 0x99, 0xc8, 0xb7, + /*08c0:*/ 0x71, 0x9a, 0x4e, 0xd8, 0xe8, 0x16, 0x5d, 0x29, 0x7d, 0x76, 0x08, 0xdf, 0x0d, 0xde, 0x6b, 0x16, + /*08d0:*/ 0x29, 0xbd, 0xce, 0x46, 0x65, 0x85, 0xc8, 0xcd, 0xf4, 0x39, 0xa5, 0xa6, 0x87, 0xa8, 0x18, 0x85, + /*08e0:*/ 0x6b, 0x60, 0xd7, 0x94, 0xcd, 0x21, 0x04, 0x18, 0x73, 0x58, 0xb3, 0xd4, 0x88, 0x0a, 0xd0, 0x33, + /*08f0:*/ 0x70, 0xe7, 0x80, 0x18, 0x22, 0x48, 0xc4, 0xce, 0x53, 0xac, 0x96, 0x2d, 0xb3, 0x65, 0xd3, 0x6b, + /*0900:*/ 0x1f, 0xb9, 0xb4, 0xd9, 0x24, 0xf0, 0x13, 0x4d, 0xcc, 0x5e, 0x6d, 0xe8, 0x80, 0xce, 0xc8, 0xe4, + /*0910:*/ 0xb3, 0x56, 0x91, 0x7a, 0x27, 0xb0, 0x1a, 0x32, 0x55, 0x49, 0xa0, 0xc4, 0xa5, 0x44, 0xf0, 0xb4, + /*0920:*/ 0x8a, 0x35, 0x0b, 0x45, 0x37, 0xf5, 0x3c, 0xe4, 0x89, 0x46, 0x1a, 0x56, 0xea, 0xc0, 0xd3, 0x8e, + /*0930:*/ 0x65, 0x90, 0x7b, 0x8d, 0x32, 0x65, 0x51, 0x89, 0x8d, 0x96, 0xab, 0x98, 0xb1, 0xd6, 0x71, 0x6e, + /*0940:*/ 0x46, 0xf2, 0x33, 0xe9, 0x37, 0x14, 0xf7, 0x11, 0xd4, 0xa8, 0xbf, 0x2a, 0x22, 0xe9, 0xc7, 0xbd, + /*0950:*/ 0xad, 0x08, 0x95, 0x73, 0xb4, 0x5e, 0x1f, 0x92, 0xfa, 0x9a, 0x1a, 0xe9, 0x77, 0x22, 0xce, 0xa6, + /*0960:*/ 0xd2, 0xc5, 0xa3, 0xf9, 0x41, 0xd8, 0x88, 0x0b, 0xe2, 0x28, 0xf1, 0x7c, 0xda, 0x84, 0x71, 0xd1, + /*0970:*/ 0x00, 0x30, 0x6d, 0x6e, 0x6c, 0xba, 0x38, 0xcd, 0x51, 0x20, 0xe2, 0x85, 0x30, 0xc1, 0x4f, 0xba, + /*0980:*/ 0x8a, 0x89, 0xf2, 0x50, 0x43, 0xf6, 0x1b, 0x4a, 0xa7, 0x2e, 0x8b, 0x67, 0xc4, 0x6d, 0x32, 0x9a, + /*0990:*/ 0xba, 0xfb, 0xa7, 0xb2, 0x3f, 0xa3, 0x2d, 0xc6, 0x7c, 0x64, 0x94, 0xde, 0xcf, 0x27, 0x86, 0x90, + /*09a0:*/ 0xc7, 0xd5, 0xa3, 0x36, 0xa6, 0x10, 0xcb, 0xcd, 0x58, 0x53, 0x0b, 0xa6, 0xb4, 0x46, 0x2a, 0xf7, + /*09b0:*/ 0x28, 0x63, 0x6a, 0x4f, 0x0e, 0xd6, 0x48, 0x3f, 0x93, 0x09, 0x12, 0xb6, 0xd7, 0x4f, 0x59, 0x96, + /*09c0:*/ 0xf9, 0xa7, 0x31, 0x0f, 0x59, 0xe1, 0x27, 0xf1, 0x66, 0x99, 0xe7, 0xb4, 0x04, 0xdb, 0xb0, 0xa0, + /*09d0:*/ 0x41, 0x1c, 0x98, 0x4c, 0xed, 0x04, 0x19, 0x06, 0xd0, 0x4a, 0x94, 0xef, 0x17, 0xf0, 0x65, 0x5b, + /*09e0:*/ 0x47, 0x2e, 0x64, 0x59, 0xb4, 0x45, 0x26, 0x37, 0x21, 0x5a, 0x8a, 0x11, 0xda, 0x41, 0x71, 0x87, + /*09f0:*/ 0x43, 0x3d, 0xe7, 0xb9, 0xaf, 0x7e, 0x81, 0x81, 0xc9, 0xd1, 0xf1, 0x0f, 0x62, 0xcc, 0x35, 0xef, + /*0a00:*/ 0x8d, 0xee, 0x9d, 0x7a, 0x57, 0xa0, 0xad, 0x9b, 0x40, 0xc8, 0x28, 0xbf, 0xa8, 0xf4, 0xf5, 0x37, + /*0a10:*/ 0x60, 0xdb, 0xdb, 0xc8, 0xe5, 0xd1, 0x7b, 0xbc, 0x53, 0x43, 0x8b, 0xf8, 0x10, 0xbe, 0x9d, 0x56, + /*0a20:*/ 0x14, 0x75, 0xcc, 0x66, 0x5b, 0x8c, 0x2b, 0x33, 0xaf, 0xa6, 0xe4, 0x08, 0x29, 0xf6, 0x50, 0x7a, + /*0a30:*/ 0x0d, 0x11, 0xa1, 0xea, 0x30, 0x49, 0x98, 0x8b, 0xa6, 0x4d, 0x29, 0x73, 0x7d, 0xfa, 0x87, 0xc9, + /*0a40:*/ 0x6a, 0x13, 0xfa, 0x75, 0xa0, 0x5a, 0x89, 0xc0, 0xb4, 0x64, 0x96, 0x79, 0x42, 0x6f, 0x30, 0xef, + /*0a50:*/ 0x13, 0x1b, 0xe7, 0x44, 0xec, 0x55, 0xb1, 0x77, 0xa6, 0xd9, 0x63, 0x09, 0xc3, 0x29, 0x95, 0x5f, + /*0a60:*/ 0xee, 0x92, 0xb6, 0x6e, 0xb4, 0xfd, 0xf2, 0x48, 0x35, 0x13, 0x2c, 0xb7, 0x34, 0xd8, 0x2d, 0x6e, + /*0a70:*/ 0xce, 0x21, 0xda, 0xe8, 0x71, 0x86, 0x3a, 0x34, 0x80, 0x5d, 0x59, 0xd5, 0x32, 0x99, 0x95, 0x52, + /*0a80:*/ 0x83, 0xd5, 0x7b, 0xd5, 0xa7, 0xa3, 0x52, 0x48, 0x92, 0xdc, 0x1f, 0x34, 0x84, 0x72, 0x08, 0x5a, + /*0a90:*/ 0xce, 0xb7, 0x02, 0xea, 0xd1, 0x75, 0x39, 0xe2, 0xa5, 0xae, 0x72, 0x56, 0x2b, 0xcc, 0xd1, 0xc8, + /*0aa0:*/ 0x95, 0x54, 0x34, 0x35, 0x94, 0x80, 0xdb, 0x62, 0xbf, 0x1f, 0xe0, 0xbc, 0x0f, 0x43, 0xce, 0xce, + /*0ab0:*/ 0x64, 0xfe, 0xbe, 0x7d, 0xe1, 0xc6, 0x81, 0xfe, 0xa6, 0x2b, 0xd7, 0x02, 0x10, 0x83, 0x03, 0xb6, + /*0ac0:*/ 0x4d, 0x59, 0x5f, 0x12, 0x39, 0x90, 0x2d, 0x0c, 0xd8, 0x29, 0xbc, 0xae, 0xed, 0x41, 0x66, 0x37, + /*0ad0:*/ 0x2c, 0x90, 0xf7, 0xba, 0xf8, 0x09, 0x20, 0x3f, 0x38, 0xd4, 0x7a, 0x24, 0x7b, 0x1a, 0x8b, 0xc6, + /*0ae0:*/ 0x69, 0x2b, 0x4d, 0x15, 0xb3, 0xd7, 0x79, 0x5f, 0x87, 0xe5, 0x48, 0x5d, 0x2a, 0x89, 0x85, 0xd7, + /*0af0:*/ 0x96, 0xf9, 0x39, 0x91, 0xdb, 0x3d, 0x9e, 0x5b, 0x39, 0xe8, 0x3a, 0x29, 0x4c, 0xd1, 0x22, 0xce, + /*0b00:*/ 0x3f, 0xa4, 0xf3, 0xad, 0x28, 0xc2, 0xee, 0xa3, 0x27, 0x19, 0x0a, 0x86, 0x13, 0xeb, 0xcc, 0xc8, + /*0b10:*/ 0x69, 0xbf, 0x46, 0xf7, 0xe4, 0x6d, 0xf8, 0x31, 0xbb, 0xd7, 0x45, 0xfd, 0x0a, 0x68, 0xee, 0x2b, + /*0b20:*/ 0xb5, 0x71, 0xb2, 0xad, 0x5b, 0x80, 0x5e, 0x69, 0x58, 0x11, 0x6a, 0xea, 0x30, 0x88, 0x33, 0xec, + /*0b30:*/ 0xa9, 0xed, 0x2f, 0x8c, 0x95, 0x30, 0xec, 0x4a, 0xc1, 0x47, 0xbd, 0xd0, 0x60, 0x8c, 0x23, 0x0f, + /*0b40:*/ 0x9e, 0x11, 0x62, 0xc6, 0xc2, 0xb4, 0xc6, 0x43, 0x4c, 0xa6, 0x66, 0xe8, 0xbc, 0xed, 0x57, 0xfb, + /*0b50:*/ 0x6d, 0x73, 0x80, 0xd3, 0x5f, 0xe1, 0x90, 0x27, 0xd5, 0x32, 0x20, 0x9d, 0x1f, 0x72, 0x5d, 0xad, + /*0b60:*/ 0xdc, 0xb3, 0x3d, 0x86, 0x75, 0x95, 0x1b, 0x34, 0x52, 0x46, 0x66, 0x58, 0xf6, 0x9a, 0xd7, 0x06, + /*0b70:*/ 0xf0, 0x40, 0x64, 0x55, 0x74, 0xa5, 0x70, 0x56, 0x17, 0x71, 0xe7, 0xee, 0xf8, 0x18, 0x77, 0xdd, + /*0b80:*/ 0x23, 0x78, 0x01, 0xde, 0x3d, 0x5b, 0x97, 0xd1, 0x35, 0x00, 0x94, 0xd9, 0x12, 0xe3, 0x7b, 0x66, + /*0b90:*/ 0xac, 0x58, 0xdb, 0xe8, 0xb0, 0x41, 0x83, 0x3e, 0x7c, 0xdc, 0x04, 0x41, 0x2f, 0xf5, 0x89, 0xce, + /*0ba0:*/ 0xbd, 0xf6, 0xa9, 0x95, 0x20, 0x62, 0x66, 0x5d, 0x6a, 0x1d, 0x08, 0xca, 0x44, 0x80, 0x7e, 0xb0, + /*0bb0:*/ 0xfd, 0x45, 0x82, 0x92, 0x80, 0x52, 0x99, 0x90, 0x16, 0x59, 0xd1, 0x29, 0xa1, 0xf2, 0x56, 0x84, + /*0bc0:*/ 0xa4, 0x5d, 0xdd, 0x82, 0x27, 0x80, 0x17, 0x84, 0x1f, 0x6e, 0x71, 0xb0, 0x7c, 0xb8, 0x39, 0xf6, + /*0bd0:*/ 0x9e, 0x55, 0xe6, 0x85, 0xa6, 0x20, 0x56, 0x6b, 0x8e, 0x4e, 0xd5, 0xd1, 0x93, 0xa3, 0xf8, 0x01, + /*0be0:*/ 0xc5, 0x04, 0x73, 0x76, 0xdd, 0x79, 0x03, 0x50, 0xc3, 0x6f, 0x89, 0x53, 0x97, 0x3e, 0xf9, 0xa4, + /*0bf0:*/ 0xfa, 0xf8, 0xd6, 0x43, 0xcd, 0x98, 0x0d, 0x69, 0xf0, 0xff, 0xa3, 0xd6, 0xb9, 0xa6, 0x0a, 0x59, + /*0c00:*/ 0x87, 0x45, 0x5e, 0x1c, 0x0d, 0x5c, 0xc3, 0x30, 0x1c, 0x69, 0xd0, 0x26, 0xc4, 0x64, 0x9f, 0xd9, + /*0c10:*/ 0xd3, 0xad, 0xbe, 0x19, 0xfd, 0x77, 0x71, 0xdb, 0xa4, 0x60, 0x93, 0x6c, 0x7e, 0xc5, 0x11, 0x41, + /*0c20:*/ 0xab, 0x40, 0xa7, 0x57, 0x70, 0x4b, 0xac, 0x56, 0x21, 0x3e, 0xb7, 0xc3, 0x1e, 0x25, 0xf9, 0xab, + /*0c30:*/ 0x86, 0x8b, 0x56, 0xf1, 0x62, 0x37, 0x24, 0xe3, 0x38, 0xb3, 0x51, 0xa8, 0xcb, 0xaa, 0x09, 0xe8, + /*0c40:*/ 0x81, 0xa2, 0x9e, 0xc6, 0x4e, 0xbe, 0x7b, 0xfd, 0x96, 0x13, 0xb5, 0x2d, 0x7c, 0xf1, 0xa8, 0xf6, + /*0c50:*/ 0x3d, 0x01, 0x2d, 0x8a, 0x8d, 0xf7, 0x8c, 0x0e, 0x6a, 0xf0, 0x00, 0x32, 0xe0, 0x8a, 0xe8, 0xa6, + /*0c60:*/ 0x7a, 0x78, 0xad, 0xcb, 0xef, 0xc8, 0xfe, 0x06, 0x74, 0x04, 0x00, 0xf5, 0xc7, 0xf5, 0x00, 0xca, + /*0c70:*/ 0x9d, 0x50, 0x57, 0x95, 0x29, 0x13, 0x34, 0xe0, 0xa6, 0xad, 0x81, 0x09, 0x9f, 0x76, 0xc1, 0xde, + /*0c80:*/ 0x1b, 0x17, 0xd4, 0x9d, 0xa0, 0x68, 0x1e, 0x6d, 0xd8, 0x3a, 0xe3, 0xa8, 0x9b, 0xfd, 0x55, 0x37, + /*0c90:*/ 0xb9, 0xfb, 0x04, 0x17, 0x8c, 0x91, 0xcc, 0x51, 0xdf, 0x96, 0x51, 0x8d, 0x26, 0x1c, 0x38, 0x0c, + /*0ca0:*/ 0x74, 0x42, 0x6a, 0x48, 0xdb, 0xb0, 0xed, 0xca, 0x95, 0xa5, 0x07, 0x76, 0x39, 0xaa, 0x9d, 0xc1, + /*0cb0:*/ 0xf0, 0xe3, 0x71, 0xce, 0x8c, 0x09, 0x88, 0x63, 0x15, 0x6d, 0x15, 0x3a, 0xdb, 0xaf, 0xad, 0x8f, + /*0cc0:*/ 0x63, 0x64, 0x37, 0x65, 0x63, 0x19, 0x7f, 0x63, 0x8a, 0xb6, 0x21, 0xc9, 0x0b, 0xd3, 0x78, 0x0d, + /*0cd0:*/ 0x21, 0x08, 0x6e, 0x66, 0xf7, 0xd8, 0xfa, 0xdf, 0x1e, 0x67, 0xae, 0xa3, 0x0b, 0xa8, 0xfb, 0xab, + /*0ce0:*/ 0xa6, 0xcb, 0x28, 0x74, 0x47, 0x8e, 0x76, 0xb7, 0xf5, 0xe5, 0x8b, 0xe9, 0x90, 0x26, 0x78, 0xe8, + /*0cf0:*/ 0x88, 0x1a, 0x9b, 0xd6, 0x07, 0xe1, 0x4d, 0xe9, 0xc6, 0xc2, 0x3c, 0x42, 0xa5, 0x7c, 0x03, 0xb1, + /*0d00:*/ 0x40, 0xd8, 0xec, 0xdf, 0x63, 0x90, 0x38, 0x13, 0x17, 0x9a, 0x34, 0x93, 0x93, 0x7d, 0x17, 0x82, + /*0d10:*/ 0xac, 0x78, 0x36, 0x21, 0x8b, 0x13, 0x33, 0xe0, 0xb7, 0xc7, 0xf3, 0x35, 0xff, 0xd7, 0xf5, 0x18, + /*0d20:*/ 0xdc, 0x8f, 0xe9, 0xd3, 0x63, 0xf4, 0x69, 0x5a, 0xc2, 0xf7, 0x70, 0x1d, 0xd6, 0x2e, 0x24, 0x31, + /*0d30:*/ 0x03, 0x3f, 0x71, 0xc5, 0x1b, 0xa1, 0x0a, 0xa0, 0xaa, 0xfb, 0xd3, 0xc4, 0x2d, 0x0c, 0x5d, 0xb4, + /*0d40:*/ 0xf4, 0x69, 0xa2, 0x82, 0xe5, 0xd7, 0x2b, 0x2c, 0xf6, 0x08, 0x1d, 0xb2, 0x14, 0x98, 0x66, 0xc1, + /*0d50:*/ 0x15, 0x0d, 0xc9, 0xcc, 0x1d, 0xc2, 0x54, 0x9b, 0x80, 0x27, 0xec, 0x27, 0x70, 0x4b, 0x5c, 0xee, + /*0d60:*/ 0xc0, 0xd3, 0x3c, 0x68, 0x50, 0x00, 0xf5, 0x80, 0x56, 0x46, 0xc3, 0x30, 0x97, 0xca, 0x5e, 0x72, + /*0d70:*/ 0x50, 0x1d, 0xb2, 0x82, 0x22, 0x73, 0x6f, 0x01, 0xf9, 0xcc, 0x98, 0xf6, 0xc5, 0xdc, 0x75, 0x2e, + /*0d80:*/ 0xa6, 0x96, 0x75, 0x75, 0xf1, 0x61, 0x58, 0x2c, 0x9f, 0x7e, 0x5f, 0xba, 0x7b, 0xe3, 0xfa, 0x47, + /*0d90:*/ 0xf7, 0x8e, 0xc1, 0x0f, 0xeb, 0xf2, 0x7a, 0x4e, 0x35, 0x09, 0x60, 0xf0, 0x38, 0xeb, 0x57, 0x5e, + /*0da0:*/ 0xa3, 0x3f, 0x77, 0x3f, 0xc4, 0xcc, 0xf4, 0xf8, 0xc5, 0x33, 0x19, 0x8e, 0xc8, 0x4a, 0xd1, 0xe5, + /*0db0:*/ 0x17, 0x70, 0xdb, 0xf7, 0x7d, 0xbc, 0x7d, 0xe0, 0x2b, 0x7e, 0x10, 0x66, 0x51, 0x47, 0x64, 0xf9, + /*0dc0:*/ 0x62, 0xcf, 0x37, 0xbb, 0x92, 0xf5, 0xb3, 0xdf, 0x11, 0x37, 0x93, 0x81, 0x6f, 0xd8, 0xb4, 0x74, + /*0dd0:*/ 0x09, 0xcb, 0x36, 0x9e, 0x44, 0xe5, 0xce, 0x3e, 0xfb, 0x3b, 0xaa, 0x1b, 0xfc, 0x46, 0x7b, 0xe6, + /*0de0:*/ 0xb0, 0x86, 0x46, 0xbf, 0xf5, 0xc2, 0xa2, 0xdc, 0x5c, 0x91, 0xa7, 0x9f, 0x1b, 0xdd, 0x9f, 0x58, + /*0df0:*/ 0x12, 0x44, 0xfe, 0x55, 0x85, 0xc3, 0xfc, 0x12, 0x13, 0x3e, 0xf3, 0x7b, 0xd7, 0x47, 0x4d, 0x26, + /*0e00:*/ 0x93, 0x32, 0x45, 0x16, 0xd0, 0x03, 0x66, 0x23, 0xe2, 0x4f, 0x92, 0x21, 0x3c, 0x18, 0x9f, 0x2e, + /*0e10:*/ 0xdd, 0xec, 0x8f, 0xeb, 0x3b, 0xef, 0x26, 0xef, 0x35, 0x98, 0xf3, 0x26, 0x90, 0x3d, 0x01, 0x46, + /*0e20:*/ 0xc4, 0x3d, 0x49, 0x19, 0xc2, 0xc7, 0xc5, 0x57, 0xf1, 0xd4, 0x1d, 0x63, 0xb3, 0xe3, 0xec, 0x29, + /*0e30:*/ 0xb7, 0x8c, 0xa6, 0xb7, 0xae, 0x63, 0x79, 0x5e, 0xc8, 0x02, 0xde, 0x38, 0x4d, 0xee, 0x6e, 0x7e, + /*0e40:*/ 0x0f, 0x70, 0xe2, 0xc0, 0x23, 0x83, 0xf6, 0xd7, 0x9e, 0x53, 0xd5, 0x44, 0x96, 0xb1, 0xfe, 0x0c, + /*0e50:*/ 0xbb, 0x00, 0x6a, 0xb3, 0xab, 0xeb, 0x31, 0xae, 0x6e, 0x63, 0xed, 0x91, 0x16, 0x44, 0x43, 0xd4, + /*0e60:*/ 0x2d, 0xf3, 0x7a, 0x95, 0x5c, 0x93, 0xa9, 0x44, 0x91, 0x7c, 0xb0, 0xc7, 0xdd, 0x92, 0x1c, 0xde, + /*0e70:*/ 0xa6, 0xc3, 0xf1, 0x58, 0x4d, 0x25, 0xcd, 0x88, 0x1a, 0x54, 0xbe, 0x50, 0x2b, 0x9a, 0xfb, 0xbc, + /*0e80:*/ 0xd6, 0x4d, 0x59, 0x2d, 0xcd, 0x76, 0x16, 0x3c, 0x1c, 0xfd, 0x7a, 0xae, 0x41, 0xae, 0xfa, 0x95, + /*0e90:*/ 0xd6, 0xb8, 0x8b, 0xac, 0xa9, 0xee, 0x93, 0x2a, 0x55, 0x21, 0x4b, 0x6c, 0x1a, 0x28, 0x2f, 0x8d, + /*0ea0:*/ 0x9c, 0x42, 0xd0, 0xb0, 0x21, 0x90, 0x0a, 0xce, 0xa5, 0x55, 0x6d, 0x52, 0x8e, 0xb7, 0x98, 0xad, + /*0eb0:*/ 0xd4, 0xdf, 0x48, 0x48, 0x71, 0x7a, 0x66, 0x4a, 0xb2, 0x45, 0x17, 0xab, 0x5b, 0x91, 0x05, 0x7f, + /*0ec0:*/ 0x72, 0xf3, 0xd3, 0x89, 0x1f, 0x81, 0x1f, 0xd4, 0xe8, 0x38, 0x5d, 0x68, 0x24, 0xca, 0x5e, 0xe1, + /*0ed0:*/ 0xd4, 0x9e, 0xac, 0x17, 0x09, 0x0e, 0x88, 0x70, 0x7a, 0xae, 0xc1, 0xc8, 0x94, 0xf5, 0x6b, 0x21, + /*0ee0:*/ 0x69, 0xc5, 0xd2, 0xb6, 0x0b, 0xc7, 0x2e, 0x27, 0x0b, 0xf2, 0xfd, 0x74, 0x8b, 0xd6, 0xd9, 0x7d, + /*0ef0:*/ 0xcd, 0x58, 0x38, 0x20, 0xc8, 0x68, 0x48, 0x08, 0xbd, 0x18, 0x69, 0x0a, 0x4f, 0x04, 0x4e, 0xcf, + /*0f00:*/ 0x43, 0x7c, 0x6f, 0x11, 0x86, 0x5b, 0xbb, 0x5b, 0x25, 0x76, 0x77, 0xf0, 0x7b, 0xbd, 0xc7, 0xd2, + /*0f10:*/ 0x2c, 0x47, 0xf3, 0x13, 0x3c, 0xfd, 0xbc, 0xa3, 0x80, 0x22, 0xcf, 0x18, 0x92, 0x36, 0x09, 0x9a, + /*0f20:*/ 0x96, 0x72, 0x05, 0xb3, 0x67, 0xa2, 0x2a, 0xee, 0x1c, 0x7c, 0x84, 0x37, 0x1c, 0x0d, 0xaa, 0x02, + /*0f30:*/ 0xcd, 0xf6, 0xc6, 0x65, 0x14, 0x2d, 0xcd, 0x18, 0x42, 0xc2, 0x3f, 0xee, 0x09, 0xcd, 0x57, 0xf9, + /*0f40:*/ 0xdd, 0xa9, 0xd4, 0xf1, 0xb3, 0x97, 0x9f, 0xf7, 0xb7, 0x4a, 0x39, 0x9c, 0xb5, 0x64, 0xd2, 0x66, + /*0f50:*/ 0x58, 0x78, 0x69, 0x65, 0xfa, 0x21, 0xfd, 0x1e, 0x0f, 0xe2, 0x37, 0x57, 0xf9, 0x8d, 0x56, 0x34, + /*0f60:*/ 0x76, 0xb4, 0x07, 0xa4, 0x9b, 0xf4, 0x27, 0xf0, 0x26, 0x95, 0x23, 0xf5, 0x6a, 0x35, 0x99, 0x52, + /*0f70:*/ 0xac, 0x40, 0x51, 0xd2, 0xf2, 0x2b, 0x22, 0x54, 0xff, 0x45, 0xda, 0x84, 0x1e, 0x72, 0x53, 0xa3, + /*0f80:*/ 0xb2, 0x9e, 0xc0, 0x6e, 0x68, 0x62, 0xa1, 0x8a, 0x74, 0xa9, 0x90, 0xfa, 0x19, 0xd0, 0x25, 0x13, + /*0f90:*/ 0xd0, 0x3b, 0x59, 0xcd, 0x85, 0x5e, 0xc4, 0x4b, 0x7b, 0x3c, 0xd4, 0xc1, 0x91, 0xa9, 0xc0, 0xce, + /*0fa0:*/ 0x5a, 0xa6, 0xc0, 0x84, 0x0c, 0xea, 0xd5, 0xeb, 0xad, 0x6c, 0x81, 0x12, 0xb4, 0x3d, 0xac, 0x20, + /*0fb0:*/ 0xcc, 0x4c, 0x82, 0xa0, 0xc3, 0x77, 0x01, 0x20, 0xeb, 0xc0, 0xd5, 0x86, 0xa0, 0x79, 0x1f, 0x75, + /*0fc0:*/ 0x27, 0xf6, 0xd4, 0xae, 0x45, 0x0f, 0x42, 0x36, 0x7f, 0x96, 0x8a, 0x9a, 0x6d, 0x65, 0xa7, 0xa3, + /*0fd0:*/ 0x8b, 0x6a, 0xea, 0xb6, 0x72, 0xb8, 0x37, 0x3f, 0x3f, 0x64, 0x64, 0x84, 0xa3, 0x68, 0x44, 0x7a, + /*0fe0:*/ 0x10, 0xe6, 0x9c, 0x54, 0x54, 0x6b, 0xc9, 0x83, 0x88, 0x49, 0x71, 0x25, 0x7a, 0x01, 0x36, 0x15, + /*0ff0:*/ 0x8e, 0x84, 0x8c, 0x41, 0x8a, 0x07, 0xc3, 0x9a, 0x87, 0x16, 0x52, 0xe8, 0xe7, 0x49, 0xd3, 0xc8, + /*1000:*/ 0x8c, 0x4a, 0xfe, 0xd9, 0xd2, 0x8c, 0xac, 0x45, 0xf2, 0xc5, 0x57, 0x73, 0xf7, 0x47, 0x1c, 0x1d, + /*1010:*/ 0x33, 0x2a, 0x16, 0x87, 0xf2, 0xfc, 0xec, 0xcd, 0x41, 0x8f, 0x5e, 0xa4, 0x40, 0x75, 0x75, 0x33, + /*1020:*/ 0xcd, 0x40, 0x13, 0x77, 0xa6, 0xb7, 0x3a, 0xf4, 0xd5, 0x5c, 0x3d, 0x9e, 0xdc, 0xd2, 0x31, 0x4f, + /*1030:*/ 0x6a, 0x4f, 0xae, 0x9b, 0xa4, 0xe7, 0xb6, 0xb9, 0x3c, 0x87, 0x02, 0x5f, 0x48, 0xbe, 0x87, 0xa7, + /*1040:*/ 0x92, 0x52, 0x8f, 0x72, 0x15, 0xbe, 0xce, 0x65, 0xfe, 0x1d, 0x9e, 0xf8, 0x9f, 0xc3, 0x8e, 0x57, + /*1050:*/ 0xbf, 0xa7, 0xe6, 0x8f, 0xb1, 0x50, 0x8c, 0x19, 0x42, 0x8a, 0x4b, 0x6f, 0x4f, 0xcf, 0xe6, 0xd5, + /*1060:*/ 0x0d, 0xa3, 0xe7, 0x02, 0x2a, 0x35, 0x17, 0xc5, 0x74, 0xab, 0xa0, 0x6d, 0xee, 0x58, 0x35, 0x10, + /*1070:*/ 0xc6, 0xb6, 0xf1, 0x9b, 0xe2, 0x1e, 0xfc, 0xb8, 0x95, 0xcb, 0xbb, 0xb2, 0x0a, 0xc2, 0x1c, 0x67, + /*1080:*/ 0xa3, 0x1d, 0x62, 0x44, 0x96, 0xdb, 0x36, 0xf0, 0xfd, 0xd2, 0x48, 0x98, 0x92, 0xdc, 0xec, 0xf4, + /*1090:*/ 0x44, 0x81, 0xf8, 0x3a, 0x6f, 0x1e, 0x24, 0x14, 0x26, 0x0c, 0x15, 0x74, 0xf1, 0x45, 0x8d, 0xfb, + /*10a0:*/ 0xee, 0x32, 0x61, 0x72, 0x28, 0x41, 0xc4, 0x12, 0xc0, 0x37, 0xca, 0x7f, 0x70, 0x86, 0xce, 0xf5, + /*10b0:*/ 0x34, 0xcf, 0xc6, 0x99, 0x5a, 0x74, 0xc9, 0xad, 0xce, 0x7d, 0x35, 0x80, 0x00, 0x47, 0xbf, 0xdd, + /*10c0:*/ 0x49, 0x42, 0xde, 0x17, 0xf1, 0xf2, 0x77, 0x1f, 0x3e, 0x47, 0x7e, 0x18, 0x2a, 0xb5, 0xae, 0x43, + /*10d0:*/ 0x46, 0x7d, 0xa9, 0x10, 0xfa, 0x0a, 0xca, 0x54, 0xf6, 0x03, 0xe0, 0xa2, 0xd3, 0xe5, 0x2b, 0xca, + /*10e0:*/ 0xe5, 0x3b, 0x46, 0xb6, 0xe2, 0x0e, 0x36, 0x71, 0x68, 0xaf, 0x51, 0xc3, 0xd9, 0xeb, 0x64, 0x60, + /*10f0:*/ 0x78, 0x2c, 0xfc, 0x5f, 0x73, 0x1f, 0xa0, 0x8a, 0xa5, 0xe5, 0xc3, 0x90, 0x3e, 0xc8, 0x83, 0x56, + /*1100:*/ 0xda, 0x17, 0xee, 0x23, 0x3b, 0x7a, 0x6d, 0xfe, 0xef, 0xa9, 0xe8, 0x92, 0xc5, 0xa5, 0xd7, 0x5e, + /*1110:*/ 0x11, 0x18, 0xd8, 0xf5, 0x1c, 0xd8, 0x1d, 0x9b, 0x0b, 0x79, 0x91, 0xa3, 0x02, 0x7d, 0xa3, 0x0f, + /*1120:*/ 0xc2, 0xcc, 0xb0, 0x0d, 0xfc, 0x7e, 0xbd, 0x1b, 0xee, 0x42, 0x90, 0x65, 0x20, 0xd8, 0xad, 0x41, + /*1130:*/ 0x6b, 0xba, 0xb0, 0xeb, 0xaa, 0xa4, 0x1b, 0x80, 0x97, 0xa7, 0x88, 0x2e, 0xdc, 0xfd, 0x55, 0x65, + /*1140:*/ 0xe9, 0xf1, 0xb6, 0x9a, 0x27, 0xca, 0x23, 0x30, 0x46, 0x3e, 0x6f, 0x0c, 0x57, 0xc3, 0xd7, 0xca, + /*1150:*/ 0xe3, 0x99, 0xe6, 0x09, 0xa1, 0x5c, 0x72, 0xd8, 0x65, 0x08, 0x21, 0xfe, 0xb0, 0x48, 0xc9, 0xf9, + /*1160:*/ 0x42, 0xad, 0xda, 0x11, 0x70, 0x56, 0x0a, 0xa5, 0x3b, 0xd9, 0xee, 0xc7, 0x30, 0x9b, 0x23, 0xd9, + /*1170:*/ 0xa0, 0x82, 0x8d, 0xe0, 0x77, 0x67, 0x4a, 0x85, 0x8b, 0x52, 0x9a, 0x16, 0xf1, 0x6a, 0x74, 0x96, + /*1180:*/ 0xf7, 0xfe, 0xa6, 0x83, 0x72, 0xb6, 0x82, 0x78, 0x44, 0xd7, 0x51, 0x70, 0x92, 0x8e, 0x64, 0xc3, + /*1190:*/ 0x8c, 0x92, 0x18, 0xc9, 0x7a, 0x4d, 0x7e, 0xd1, 0x11, 0x53, 0xa6, 0x14, 0xed, 0x9c, 0x04, 0x01, + /*11a0:*/ 0xdb, 0x9f, 0xfd, 0x38, 0xc7, 0xf0, 0xb0, 0x70, 0x96, 0x7a, 0x67, 0xdc, 0x19, 0xeb, 0xaf, 0xf9, + /*11b0:*/ 0x25, 0x1f, 0xbc, 0xc0, 0xa4, 0xa8, 0x05, 0x7b, 0x9e, 0xd5, 0xe8, 0x1c, 0xe3, 0x71, 0xab, 0x92, + /*11c0:*/ 0xc9, 0xb4, 0xac, 0xb0, 0xe0, 0xf1, 0x59, 0x0b, 0x58, 0x3e, 0xca, 0x9d, 0x3e, 0xd0, 0xae, 0xeb, + /*11d0:*/ 0x51, 0xf0, 0x3c, 0xc0, 0xb9, 0x0b, 0xda, 0xba, 0x6b, 0xd8, 0x1f, 0x97, 0x68, 0x75, 0xbc, 0x88, + /*11e0:*/ 0x44, 0x5c, 0x37, 0xc7, 0x0c, 0xd7, 0xf1, 0x1d, 0x03, 0xe8, 0x0e, 0xa6, 0xae, 0xd0, 0x66, 0xa4, + /*11f0:*/ 0xd1, 0xf5, 0x52, 0xc8, 0x7b, 0x1e, 0xfe, 0x4b, 0x5d, 0xdd, 0xca, 0xad, 0x21, 0xde, 0x28, 0xf4, + /*1200:*/ 0x98, 0x98, 0x9c, 0xd2, 0x62, 0xd7, 0x00, 0xde, 0x6a, 0xf1, 0xa1, 0xe4, 0x1c, 0xaf, 0x1f, 0x9b, + /*1210:*/ 0x90, 0x8a, 0x40, 0x9d, 0x78, 0x64, 0x75, 0x60, 0xaa, 0xc7, 0xce, 0x63, 0x65, 0x1e, 0x65, 0x74, + /*1220:*/ 0x9b, 0x37, 0xb2, 0xb7, 0x54, 0xc5, 0x6d, 0xce, 0x1d, 0x08, 0x3a, 0x01, 0x07, 0xc1, 0x80, 0x21, + /*1230:*/ 0x1e, 0x25, 0xbe, 0x97, 0xbb, 0x53, 0x3f, 0x8a, 0xcf, 0x1c, 0xfe, 0x7f, 0x93, 0xfb, 0x0c, 0x5a, + /*1240:*/ 0x52, 0xf2, 0x63, 0xba, 0xd0, 0xa5, 0x5b, 0xd8, 0x98, 0xb8, 0x95, 0xd4, 0xc8, 0xb1, 0x04, 0x99, + /*1250:*/ 0x83, 0xb4, 0xcb, 0xe4, 0x3a, 0xea, 0x02, 0x5e, 0x88, 0x6e, 0xfd, 0xf8, 0x79, 0x5f, 0x03, 0x99, + /*1260:*/ 0x56, 0xea, 0x25, 0xc8, 0x08, 0x1b, 0x6a, 0x8d, 0x28, 0xe6, 0x08, 0x47, 0x67, 0xf5, 0xc7, 0x52, + /*1270:*/ 0x60, 0x08, 0x42, 0x5f, 0x58, 0x01, 0x0a, 0xf2, 0xa3, 0xa3, 0x1e, 0x91, 0x17, 0x5d, 0xe8, 0xe4, + /*1280:*/ 0x14, 0x10, 0x67, 0xc3, 0x1c, 0x3e, 0x71, 0x23, 0x45, 0xf3, 0xc9, 0x73, 0xc9, 0xc5, 0x94, 0x67, + /*1290:*/ 0x51, 0x22, 0xa5, 0xf9, 0x45, 0xce, 0x35, 0x20, 0xf7, 0xf7, 0x1a, 0xea, 0x52, 0x25, 0x17, 0xb1, + /*12a0:*/ 0xec, 0xc5, 0x4e, 0xe9, 0x03, 0x8f, 0xc2, 0x0c, 0xa3, 0x00, 0xd9, 0xe8, 0xe8, 0xb2, 0xbe, 0xaf, + /*12b0:*/ 0xcb, 0xda, 0xf8, 0xbe, 0x2d, 0x2e, 0x92, 0x23, 0x3b, 0x9b, 0x27, 0x65, 0x7f, 0x03, 0xc7, 0x8e, + /*12c0:*/ 0x9c, 0x86, 0x66, 0xf4, 0x67, 0xb4, 0x7b, 0x7d, 0x44, 0x73, 0x8e, 0x7e, 0x32, 0x87, 0x58, 0xa9, + /*12d0:*/ 0xcf, 0x92, 0xc8, 0x07, 0x41, 0xc5, 0x41, 0x17, 0x34, 0xed, 0x3b, 0xd6, 0x30, 0xca, 0x66, 0x50, + /*12e0:*/ 0x4a, 0x1e, 0x68, 0xcc, 0x91, 0xe2, 0x78, 0x38, 0xfc, 0x04, 0x72, 0xfb, 0xbb, 0x63, 0x4f, 0x30, + /*12f0:*/ 0xc2, 0xbb, 0x4a, 0xd5, 0xc9, 0x0e, 0x53, 0xc7, 0x5c, 0x83, 0x1d, 0xc0, 0x42, 0x22, 0xfa, 0xba, + /*1300:*/ 0x31, 0xfa, 0x85, 0x75, 0x8e, 0x7b, 0x1b, 0x63, 0x2a, 0x13, 0x2a, 0x33, 0x01, 0x86, 0xc0, 0xdd, + /*1310:*/ 0xfd, 0x14, 0xc5, 0x84, 0x9b, 0xcc, 0xa5, 0x89, 0x31, 0x27, 0x6e, 0x3b, 0xc6, 0xb0, 0xf2, 0x23, + /*1320:*/ 0x61, 0x52, 0x5b, 0x3a, 0xf2, 0x63, 0x3a, 0xc2, 0x6e, 0xaf, 0x98, 0x97, 0x5c, 0xbc, 0xd4, 0xf3, + /*1330:*/ 0xd4, 0x98, 0x25, 0x73, 0xc6, 0xbb, 0x64, 0x85, 0x88, 0x95, 0x0d, 0xcb, 0xaa, 0xfd, 0x57, 0x9c, + /*1340:*/ 0xa8, 0x4f, 0x32, 0xa4, 0xce, 0xf0, 0x0d, 0x1c, 0xac, 0x9a, 0x53, 0x84, 0xb8, 0x4e, 0x48, 0xc0, + /*1350:*/ 0xfb, 0xc2, 0x48, 0x1e, 0x76, 0xb4, 0xf2, 0x7c, 0xde, 0xe1, 0xc4, 0xf4, 0xb7, 0x09, 0x19, 0x7e, + /*1360:*/ 0x0d, 0x40, 0x92, 0xa3, 0x4e, 0x14, 0xcf, 0x15, 0x17, 0x6c, 0x81, 0x55, 0xaa, 0xce, 0xa6, 0x8b, + /*1370:*/ 0xbf, 0xd6, 0x30, 0x06, 0xa0, 0x1b, 0x18, 0x40, 0xca, 0x69, 0xab, 0xe2, 0x3e, 0xa5, 0xf2, 0x85, + /*1380:*/ 0x43, 0x54, 0x76, 0x5d, 0xe3, 0x96, 0xd4, 0x39, 0x47, 0x70, 0x1a, 0x71, 0x94, 0xcd, 0x9d, 0xfa, + /*1390:*/ 0xb0, 0x89, 0xab, 0x7a, 0x2e, 0x49, 0xb5, 0x34, 0x66, 0xbb, 0xdc, 0x6e, 0x5a, 0x1d, 0x65, 0x20, + /*13a0:*/ 0xce, 0x49, 0x1d, 0xeb, 0x73, 0x83, 0x00, 0x05, 0xb0, 0x5a, 0x56, 0xc3, 0xa5, 0x0f, 0x03, 0xb0, + /*13b0:*/ 0xdb, 0xb5, 0xf0, 0x61, 0x2c, 0xfd, 0x37, 0x38, 0x7d, 0xf8, 0xc4, 0x09, 0xd0, 0xf3, 0xdc, 0x62, + /*13c0:*/ 0xca, 0x29, 0x71, 0xb9, 0x44, 0xc4, 0x24, 0x21, 0xc5, 0xfe, 0x9c, 0xd9, 0xd4, 0x89, 0x44, 0x00, + /*13d0:*/ 0x20, 0xae, 0xd9, 0xae, 0xd6, 0xea, 0x5d, 0x04, 0x35, 0x4c, 0x09, 0x47, 0xfa, 0x85, 0x7f, 0x1e, + /*13e0:*/ 0x52, 0x62, 0xb7, 0x8a, 0x05, 0xc5, 0x47, 0x39, 0x2d, 0xe8, 0xf0, 0xf7, 0x57, 0x67, 0xf5, 0xda, + /*13f0:*/ 0x47, 0xe9, 0x10, 0x84, 0xb4, 0xf9, 0x3f, 0x8d, 0xae, 0xdd, 0xce, 0x76, 0xc9, 0xfe, 0x0b, 0x52, + /*1400:*/ 0x63, 0x1d, 0xde, 0x2a, 0x25, 0x54, 0x9c, 0xab, 0x2b, 0x52, 0x30, 0x8c, 0x80, 0xe8, 0x50, 0xe0, + /*1410:*/ 0x2b, 0x6b, 0xf5, 0x42, 0xbc, 0x26, 0x85, 0x9f, 0xd3, 0x9a, 0xbe, 0x41, 0xd2, 0xf1, 0xa6, 0xd7, + /*1420:*/ 0xf2, 0xcd, 0x72, 0xab, 0x8d, 0x4c, 0x46, 0x7b, 0xaf, 0x82, 0x58, 0xd7, 0x2f, 0x16, 0x07, 0x28, + /*1430:*/ 0xf0, 0x3a, 0x7e, 0x85, 0xc3, 0xf3, 0xe8, 0xe5, 0x00, 0x06, 0x00, 0xb5, 0x97, 0x19, 0x9f, 0xde, + /*1440:*/ 0x99, 0x1f, 0xf5, 0x08, 0x97, 0x02, 0x6e, 0x60, 0xc5, 0xa7, 0x77, 0x99, 0xcf, 0x04, 0xa6, 0x2f, + /*1450:*/ 0xb5, 0xca, 0xff, 0x4b, 0xd7, 0xee, 0xcc, 0x90, 0x6c, 0x77, 0xac, 0x95, 0x3f, 0x24, 0xa5, 0x50, + /*1460:*/ 0x00, 0x9d, 0xf5, 0x7e, 0xed, 0x37, 0xa8, 0xd6, 0xd7, 0xf2, 0xf7, 0x14, 0xb8, 0x2e, 0x7e, 0x1f, + /*1470:*/ 0xa3, 0x02, 0xec, 0x4c, 0xf5, 0xc6, 0x7b, 0x03, 0x99, 0x3b, 0x9d, 0xaf, 0xad, 0xe2, 0x44, 0x7c, + /*1480:*/ 0x89, 0xd6, 0xd3, 0x09, 0x0c, 0xed, 0x48, 0x17, 0x3e, 0xcc, 0xce, 0x08, 0x1d, 0x2d, 0x47, 0x36, + /*1490:*/ 0xf8, 0x6c, 0x37, 0xcd, 0x7c, 0xc7, 0xf3, 0x06, 0x17, 0x8c, 0xca, 0xfe, 0x36, 0x4c, 0xb8, 0x10, + /*14a0:*/ 0x08, 0xe6, 0xd5, 0xa8, 0x99, 0x56, 0x48, 0xe0, 0x18, 0x44, 0x72, 0x63, 0x3d, 0x09, 0xd5, 0xd9, + /*14b0:*/ 0x5a, 0xe1, 0x4c, 0x38, 0xd1, 0xdc, 0x0b, 0x47, 0xd3, 0x8a, 0x1a, 0xf8, 0xe8, 0x75, 0x3b, 0x1a, + /*14c0:*/ 0x9c, 0xcb, 0x89, 0x37, 0xc4, 0xa6, 0xa3, 0xbe, 0xf6, 0xe5, 0x40, 0xd3, 0x44, 0x1d, 0xea, 0x92, + /*14d0:*/ 0xfa, 0xf2, 0xd6, 0x0d, 0x52, 0xf0, 0x8c, 0x0b, 0x3a, 0x55, 0x75, 0x7a, 0xfc, 0xef, 0x81, 0xdb, + /*14e0:*/ 0xc5, 0x97, 0x81, 0xe3, 0x32, 0xd8, 0x8a, 0x49, 0xf0, 0x14, 0x28, 0x14, 0xac, 0x7a, 0xc6, 0x21, + /*14f0:*/ 0xe2, 0xa9, 0x61, 0xc4, 0xa5, 0xd2, 0x8d, 0xd6, 0x36, 0xba, 0x4f, 0x20, 0x43, 0xeb, 0xac, 0xef, + /*1500:*/ 0x6a, 0x81, 0x0a, 0x54, 0x37, 0x35, 0x34, 0x09, 0xce, 0xdc, 0x78, 0x43, 0x00, 0xc5, 0x46, 0x0e, + /*1510:*/ 0x17, 0xb1, 0x7a, 0x51, 0x96, 0x54, 0xee, 0x24, 0x32, 0xf9, 0x09, 0x66, 0xff, 0xf6, 0xb9, 0x9f, + /*1520:*/ 0x06, 0xa4, 0x55, 0x8c, 0x3b, 0x9d, 0xcd, 0x31, 0x01, 0x33, 0x61, 0xeb, 0xd3, 0x45, 0x49, 0x34, + /*1530:*/ 0x2e, 0xff, 0xa3, 0x7f, 0xf5, 0xb0, 0x37, 0x00, 0x31, 0x84, 0xb1, 0xa1, 0x9f, 0xa4, 0xdb, 0xc7, + /*1540:*/ 0xa2, 0xd9, 0x23, 0x4c, 0xf0, 0x09, 0x57, 0x9b, 0x4b, 0xbc, 0x6b, 0xe4, 0x15, 0x55, 0x9f, 0x3d, + /*1550:*/ 0x97, 0xa6, 0xab, 0x0a, 0x86, 0xde, 0xd3, 0x83, 0xd2, 0x81, 0x21, 0x75, 0x60, 0x66, 0xd8, 0xa1, + /*1560:*/ 0xd0, 0xdb, 0x08, 0x42, 0xe6, 0xf1, 0xeb, 0x6f, 0x59, 0xe2, 0x0f, 0xd1, 0x00, 0x3a, 0x09, 0x86, + /*1570:*/ 0x61, 0x8f, 0x3c, 0x6d, 0x02, 0x48, 0x41, 0x1a, 0x9b, 0xcd, 0x33, 0xd6, 0xbe, 0x15, 0x88, 0x2a, + /*1580:*/ 0x94, 0xf9, 0xc9, 0xda, 0x03, 0xb3, 0x1c, 0xaa, 0x22, 0x19, 0xa9, 0x9e, 0xdd, 0xe7, 0x7e, 0x92, + /*1590:*/ 0xdf, 0x06, 0xd7, 0x0c, 0xe0, 0x19, 0xa8, 0xec, 0x9a, 0x33, 0xfa, 0x30, 0xa7, 0xe9, 0xc9, 0x3d, + /*15a0:*/ 0x6a, 0x14, 0x89, 0x5b, 0xe9, 0x19, 0xfd, 0xf5, 0xdb, 0xfe, 0x70, 0x4a, 0x09, 0x18, 0x9a, 0x90, + /*15b0:*/ 0x16, 0x88, 0xb2, 0x60, 0x6e, 0x34, 0xa5, 0x22, 0x7e, 0x2d, 0x5a, 0x37, 0x0e, 0xbe, 0x71, 0x7e, + /*15c0:*/ 0x5a, 0xd4, 0x38, 0x0b, 0x25, 0x49, 0x4d, 0x07, 0x47, 0xee, 0x3d, 0xfe, 0x8f, 0x81, 0xdb, 0xb2, + /*15d0:*/ 0xda, 0x0d, 0x71, 0xbc, 0x10, 0x36, 0x69, 0xd5, 0xec, 0xdd, 0x57, 0xc4, 0xeb, 0x52, 0xd6, 0x2c, + /*15e0:*/ 0xce, 0xaf, 0xe7, 0xae, 0xfa, 0xf6, 0x22, 0x8e, 0x72, 0x39, 0xcb, 0x48, 0x0f, 0x76, 0x9c, 0x51, + /*15f0:*/ 0x54, 0x7b, 0x7c, 0x2d, 0x5d, 0x4e, 0x54, 0x82, 0xf4, 0xfd, 0x6b, 0xdf, 0x97, 0xed, 0xec, 0x68, + /*1600:*/ 0xb7, 0x03, 0x26, 0x74, 0x46, 0xcc, 0x3f, 0x6d, 0x49, 0x52, 0xce, 0xe2, 0x82, 0x12, 0x79, 0x85, + /*1610:*/ 0x95, 0xb6, 0x4c, 0x9e, 0x61, 0xd9, 0xc4, 0xaa, 0xd6, 0xcd, 0x0b, 0xad, 0x78, 0xd8, 0xed, 0x07, + /*1620:*/ 0x5c, 0x8b, 0xe4, 0x1c, 0x86, 0x85, 0xf2, 0xee, 0x98, 0x81, 0x4f, 0xa9, 0x74, 0x22, 0xd5, 0x7f, + /*1630:*/ 0xf3, 0x48, 0xec, 0x30, 0xde, 0x23, 0x10, 0xa8, 0x6e, 0x1e, 0xbb, 0x6b, 0x31, 0xd1, 0x26, 0x48, + /*1640:*/ 0xac, 0x4a, 0x19, 0x66, 0xef, 0x2e, 0x5f, 0xd9, 0x7a, 0xc6, 0xfa, 0xc3, 0x06, 0xf0, 0xfe, 0x6c, + /*1650:*/ 0xd3, 0xf5, 0xdd, 0x6b, 0x09, 0x39, 0x17, 0x99, 0x29, 0xff, 0x24, 0x51, 0x3b, 0x06, 0x35, 0x92, + /*1660:*/ 0xda, 0x9f, 0x9f, 0x32, 0x40, 0x5c, 0x05, 0x60, 0x18, 0xd5, 0xb4, 0xd7, 0x9d, 0x7f, 0xd8, 0x5b, + /*1670:*/ 0x3e, 0x67, 0xee, 0xaa, 0x12, 0xd0, 0xd1, 0x61, 0x78, 0x60, 0x28, 0x63, 0xd8, 0x91, 0xe1, 0x86, + /*1680:*/ 0x78, 0x01, 0x62, 0x55, 0xa8, 0x5c, 0x7d, 0xf5, 0x80, 0x97, 0x16, 0xaa, 0xcc, 0x62, 0xec, 0x35, + /*1690:*/ 0x18, 0x53, 0xda, 0xfc, 0x3b, 0x5b, 0x2f, 0xe5, 0xd0, 0xb9, 0xba, 0x31, 0xed, 0xbe, 0xe0, 0xf1, + /*16a0:*/ 0xfa, 0x54, 0x8f, 0x1d, 0x1a, 0xfc, 0xfb, 0xe0, 0xbb, 0x30, 0x0c, 0x6a, 0xf7, 0x80, 0x27, 0xbb, + /*16b0:*/ 0xb2, 0xc3, 0x38, 0xb9, 0x01, 0x2c, 0x93, 0x00, 0xac, 0xb0, 0xef, 0x9a, 0x44, 0x7d, 0xfb, 0x0b, + /*16c0:*/ 0x91, 0x36, 0xac, 0xb7, 0x0a, 0xe9, 0x29, 0xdc, 0x82, 0x8a, 0x76, 0x75, 0x12, 0xec, 0x81, 0x20, + /*16d0:*/ 0x55, 0x2b, 0x67, 0x28, 0xa6, 0x1a, 0x73, 0xde, 0x82, 0xac, 0x0f, 0xa6, 0xd8, 0xa6, 0x96, 0xf7, + /*16e0:*/ 0xe6, 0x27, 0x33, 0xa3, 0x4d, 0x37, 0x66, 0xbd, 0xcf, 0xa3, 0x70, 0x4f, 0xae, 0xb3, 0x55, 0x92, + /*16f0:*/ 0x8b, 0x7c, 0x5f, 0xd3, 0x5e, 0x8a, 0x84, 0xf8, 0x30, 0x95, 0x16, 0xb5, 0xfc, 0xc2, 0x23, 0x25, + /*1700:*/ 0x65, 0xdb, 0x48, 0xcd, 0xfc, 0xc4, 0xbf, 0xca, 0xa3, 0xd3, 0x8b, 0xe4, 0x5c, 0x7a, 0x97, 0x5d, + /*1710:*/ 0xa8, 0xc5, 0xf9, 0x1a, 0x91, 0x60, 0x3b, 0x20, 0x77, 0xe7, 0x35, 0x99, 0x43, 0x47, 0x1c, 0x96, + /*1720:*/ 0x54, 0xeb, 0x9f, 0xc0, 0x7e, 0xb0, 0xcd, 0x9f, 0x62, 0xec, 0x5c, 0xd9, 0x37, 0xc8, 0x4d, 0x92, + /*1730:*/ 0xc0, 0x76, 0xfa, 0x3b, 0xbd, 0x4b, 0xd1, 0x1f, 0x43, 0xd9, 0x55, 0x7a, 0xb8, 0x7c, 0x7b, 0xa3, + /*1740:*/ 0x0c, 0x26, 0x5f, 0x6b, 0x7c, 0x38, 0xc2, 0x72, 0x36, 0xd7, 0xc0, 0x5c, 0x57, 0x69, 0xd1, 0x1a, + /*1750:*/ 0xc6, 0xda, 0x20, 0x3a, 0x2a, 0x43, 0x2b, 0x32, 0x86, 0x37, 0x8d, 0x44, 0x20, 0x0c, 0xcf, 0xb4, + /*1760:*/ 0xe8, 0x7b, 0x38, 0xc2, 0xea, 0x4f, 0xd2, 0xf3, 0xe0, 0x44, 0x11, 0xa4, 0x60, 0x11, 0xea, 0x09, + /*1770:*/ 0x3a, 0x04, 0x0b, 0xe8, 0xcc, 0x55, 0xbf, 0xa2, 0xe7, 0xee, 0x4e, 0xbf, 0xc6, 0x10, 0xbf, 0x0c, + /*1780:*/ 0xb9, 0x24, 0xa9, 0x8c, 0x46, 0x81, 0xc7, 0x44, 0x3e, 0x63, 0x50, 0xce, 0x4c, 0x91, 0xfc, 0xe8, + /*1790:*/ 0x2e, 0x97, 0x76, 0xc5, 0xf4, 0xd0, 0x36, 0x5a, 0x6c, 0x30, 0xfe, 0xc1, 0x02, 0x86, 0x07, 0xd3, + /*17a0:*/ 0xeb, 0x57, 0x6d, 0x43, 0xf9, 0xfa, 0xc7, 0x39, 0xd5, 0xfa, 0x70, 0xa4, 0x55, 0x7c, 0x4e, 0x93, + /*17b0:*/ 0xca, 0xd9, 0x78, 0xcb, 0xa2, 0x1d, 0x79, 0x96, 0x55, 0x16, 0x94, 0x8d, 0x74, 0xda, 0xa5, 0x1c, + /*17c0:*/ 0xf6, 0xa3, 0xcc, 0x33, 0x0e, 0x3a, 0x29, 0xa0, 0xf9, 0x7d, 0x8b, 0x13, 0x6e, 0x7f, 0x02, 0x4a, + /*17d0:*/ 0x50, 0xd3, 0x7c, 0x1e, 0x09, 0x3c, 0xd0, 0x03, 0xad, 0x0d, 0xb2, 0xfa, 0xa1, 0x8b, 0xd3, 0x69, + /*17e0:*/ 0x91, 0x7a, 0x6a, 0xe2, 0x66, 0x1a, 0xe4, 0x3d, 0xdf, 0xab, 0x3f, 0xfa, 0x39, 0xb3, 0x66, 0x0a, + /*17f0:*/ 0x80, 0x1a, 0x07, 0x75, 0xe6, 0xfd, 0x9b, 0x9b, 0xfe, 0xf0, 0x9c, 0x3f, 0x9e, 0x43, 0xc8, 0xe3, + /*1800:*/ 0xbd, 0xb4, 0x32, 0x25, 0x4f, 0x96, 0x8f, 0xba, 0x46, 0x34, 0xdc, 0x9e, 0x18, 0xe8, 0x16, 0x9a, + /*1810:*/ 0xc1, 0x8c, 0x41, 0x16, 0x2d, 0x88, 0x0b, 0x1d, 0x6f, 0x2a, 0xbf, 0x99, 0x85, 0x14, 0xa3, 0x89, + /*1820:*/ 0x86, 0xac, 0xf6, 0xe3, 0x7b, 0xcf, 0x48, 0xec, 0xe0, 0x74, 0xbc, 0x96, 0x95, 0x4d, 0x76, 0x1d, + /*1830:*/ 0x5e, 0x76, 0x49, 0x63, 0x62, 0x75, 0x21, 0x87, 0x4d, 0x62, 0xb3, 0xfe, 0x0b, 0xf5, 0xed, 0x8c, + /*1840:*/ 0x95, 0x9c, 0xd3, 0xc5, 0x5f, 0x14, 0xd8, 0x4e, 0x41, 0xaa, 0xd9, 0x1f, 0xb3, 0x67, 0x35, 0xaf, + /*1850:*/ 0x0d, 0x3a, 0xcb, 0xe5, 0xcc, 0x84, 0xc4, 0xab, 0x45, 0x38, 0xa9, 0x45, 0x66, 0x12, 0x75, 0x93, + /*1860:*/ 0xc0, 0x36, 0x42, 0x88, 0xb6, 0x5e, 0x3f, 0xae, 0x67, 0xe5, 0x5f, 0xe2, 0xc1, 0x93, 0xca, 0x84, + /*1870:*/ 0x55, 0xa1, 0xda, 0xec, 0x53, 0xe8, 0x74, 0xc2, 0xdb, 0x25, 0xdf, 0x8a, 0xfb, 0xfa, 0xf0, 0x14, + /*1880:*/ 0xf7, 0x92, 0x67, 0xbb, 0x0a, 0x5e, 0xfa, 0x53, 0x4f, 0x5f, 0xf9, 0x05, 0x7b, 0xbd, 0x02, 0x3e, + /*1890:*/ 0x30, 0xdf, 0x90, 0xef, 0x3d, 0x84, 0x0b, 0x71, 0x8b, 0x08, 0xc3, 0xae, 0xb7, 0xdb, 0xe1, 0x19, + /*18a0:*/ 0x56, 0x85, 0x65, 0x98, 0x53, 0x32, 0x4b, 0xe7, 0xd5, 0x01, 0x4f, 0x02, 0xf2, 0xa1, 0xb6, 0x61, + /*18b0:*/ 0xf9, 0xa2, 0xd1, 0xb0, 0xb7, 0x87, 0x21, 0x62, 0x60, 0x7a, 0x91, 0x14, 0x7a, 0x11, 0x6d, 0xb4, + /*18c0:*/ 0x79, 0x40, 0xa4, 0x9a, 0x6d, 0xcf, 0xe2, 0x6d, 0x8a, 0xd2, 0x7d, 0xfb, 0x2b, 0x11, 0xfa, 0x92, + /*18d0:*/ 0xe3, 0x6f, 0x47, 0x7f, 0xa2, 0x41, 0x3b, 0x90, 0x36, 0x68, 0x90, 0x96, 0xf3, 0xf5, 0x27, 0xeb, + /*18e0:*/ 0x99, 0x6b, 0x31, 0x5b, 0x94, 0x7d, 0xa6, 0x2d, 0xdf, 0xfd, 0xee, 0x2c, 0x54, 0x59, 0x1c, 0xb7, + /*18f0:*/ 0xa9, 0xd0, 0x9a, 0x43, 0x82, 0x05, 0x47, 0xba, 0x26, 0xe3, 0x7d, 0x98, 0xd9, 0x4e, 0xe9, 0xed, + /*1900:*/ 0xbb, 0x30, 0x27, 0xb0, 0xed, 0xc4, 0x95, 0xb5, 0x64, 0x98, 0x66, 0xe6, 0x44, 0x9d, 0x63, 0x3f, + /*1910:*/ 0xb8, 0xdd, 0x35, 0xed, 0x79, 0x9c, 0x30, 0xd0, 0x5a, 0xfc, 0x14, 0xcf, 0x6b, 0x05, 0x48, 0x5d, + /*1920:*/ 0x35, 0xd7, 0xd6, 0x8c, 0xce, 0xee, 0x21, 0x73, 0x01, 0xeb, 0x8a, 0x14, 0x01, 0x1c, 0xee, 0x8a, + /*1930:*/ 0xbc, 0x7a, 0xbb, 0xbb, 0x7b, 0x89, 0x8a, 0xfa, 0x6a, 0xf8, 0x90, 0x6f, 0x07, 0xba, 0x77, 0x7b, + /*1940:*/ 0x27, 0x01, 0xfd, 0x67, 0x52, 0xcf, 0xf5, 0xc2, 0xa7, 0x2d, 0x79, 0xbf, 0x50, 0x7a, 0xc9, 0x1c, + /*1950:*/ 0x6a, 0x6f, 0x38, 0xa1, 0x76, 0x80, 0x22, 0x01, 0xa8, 0x4e, 0x6c, 0x8d, 0x64, 0x55, 0x63, 0x89, + /*1960:*/ 0xf8, 0xe4, 0x59, 0x37, 0xf7, 0xae, 0x6b, 0x61, 0x98, 0x7e, 0x43, 0xdd, 0xba, 0xf0, 0x07, 0x28, + /*1970:*/ 0x91, 0xe7, 0x8a, 0xf7, 0xe4, 0xaa, 0x86, 0x0b, 0x26, 0x1e, 0x3c, 0x45, 0x9b, 0x84, 0xd0, 0xe0, + /*1980:*/ 0xcf, 0x81, 0x1b, 0x61, 0x9b, 0xef, 0xde, 0x8c, 0xc0, 0xa4, 0x83, 0xe7, 0x31, 0x18, 0xf1, 0x66, + /*1990:*/ 0x2d, 0x65, 0x6f, 0x2e, 0xfb, 0x60, 0x99, 0xa4, 0xbd, 0x20, 0x6b, 0x83, 0xe6, 0x2d, 0x93, 0xbc, + /*19a0:*/ 0x9b, 0xce, 0xa5, 0x1e, 0x9b, 0xda, 0xb4, 0x69, 0x89, 0xb9, 0x42, 0x3a, 0x1a, 0xcc, 0x13, 0x7f, + /*19b0:*/ 0x5e, 0xc6, 0xa2, 0x4c, 0x8a, 0x82, 0xc0, 0x19, 0x2f, 0xe0, 0xac, 0x58, 0xb4, 0xbc, 0x69, 0x2f, + /*19c0:*/ 0x11, 0xa2, 0x85, 0x0b, 0x72, 0x32, 0x74, 0x83, 0x11, 0x58, 0xe0, 0x7a, 0xce, 0x55, 0xda, 0x6e, + /*19d0:*/ 0x2f, 0xe9, 0x6c, 0x62, 0xdc, 0xbd, 0x89, 0x0d, 0xfd, 0x7a, 0x32, 0xb9, 0x28, 0x7a, 0xc2, 0xb6, + /*19e0:*/ 0x10, 0x67, 0xf1, 0x6a, 0xe2, 0x04, 0x17, 0x9d, 0x2d, 0xe0, 0xde, 0xc3, 0xad, 0xff, 0xb6, 0x4b, + /*19f0:*/ 0x11, 0x3d, 0x53, 0x21, 0x6a, 0xe6, 0x30, 0xad, 0x15, 0x7d, 0x13, 0x28, 0x3c, 0xea, 0x29, 0x32, + /*1a00:*/ 0xa7, 0xb6, 0x67, 0x07, 0x1f, 0x0e, 0x72, 0xe8, 0xd7, 0xcf, 0x59, 0xb5, 0x68, 0xf4, 0xb6, 0x81, + /*1a10:*/ 0xed, 0xf5, 0xb8, 0xab, 0xfb, 0xee, 0x6c, 0x94, 0xff, 0x03, 0xa9, 0xc8, 0x1a, 0x30, 0x9b, 0x16, + /*1a20:*/ 0xff, 0x9b, 0x40, 0x57, 0x70, 0x9f, 0xb9, 0xcb, 0xf6, 0x79, 0x88, 0xee, 0x3f, 0xf1, 0xa0, 0x8d, + /*1a30:*/ 0x67, 0x26, 0x90, 0x71, 0x84, 0x34, 0xce, 0x7b, 0xaa, 0x83, 0xd1, 0x00, 0x33, 0xfd, 0x4d, 0x86, + /*1a40:*/ 0x55, 0x53, 0xc0, 0x6b, 0x3a, 0x44, 0xd8, 0xdb, 0x40, 0x24, 0xb8, 0xef, 0x7d, 0x2b, 0x7d, 0x03, + /*1a50:*/ 0x79, 0xaf, 0x0f, 0x86, 0x21, 0x4e, 0x41, 0xc6, 0x60, 0x21, 0x8e, 0x58, 0x26, 0x1b, 0x72, 0xfe, + /*1a60:*/ 0x71, 0x21, 0x0e, 0xa1, 0xd6, 0xf7, 0x41, 0x50, 0x68, 0xca, 0x3f, 0x62, 0xdf, 0xd1, 0x41, 0xe1, + /*1a70:*/ 0xdc, 0xc2, 0x7f, 0x82, 0xd8, 0x6e, 0x3e, 0xf9, 0x30, 0xee, 0x71, 0xcd, 0x1f, 0x0f, 0x4f, 0xb3, + /*1a80:*/ 0x03, 0xfb, 0x20, 0x75, 0x91, 0x1a, 0xbf, 0xb0, 0xc1, 0xc4, 0x65, 0x4b, 0x65, 0x52, 0x2a, 0x13, + /*1a90:*/ 0xb1, 0xb1, 0xc8, 0xe1, 0x9e, 0xc5, 0x78, 0x40, 0xae, 0xf6, 0x57, 0x12, 0xc9, 0x49, 0x24, 0xee, + /*1aa0:*/ 0x87, 0x6b, 0xa0, 0x0c, 0x0f, 0xb1, 0xbe, 0xac, 0xcb, 0x8b, 0xe9, 0x3f, 0x1b, 0xaa, 0x79, 0x9f, + /*1ab0:*/ 0xc4, 0xff, 0xac, 0xf9, 0xf7, 0x53, 0xab, 0xa8, 0xf2, 0x00, 0xc0, 0xa4, 0x24, 0x22, 0x97, 0x58, + /*1ac0:*/ 0x0c, 0x39, 0x96, 0xe2, 0xe9, 0xcf, 0x62, 0xcb, 0x8f, 0xdb, 0xa8, 0xdd, 0x5a, 0x5c, 0xb2, 0xce, + /*1ad0:*/ 0xae, 0x84, 0x2a, 0x68, 0x7c, 0x38, 0x56, 0x78, 0xe1, 0xa6, 0x7c, 0x6b, 0x8b, 0x47, 0x07, 0xe4, + /*1ae0:*/ 0xc7, 0x54, 0x9a, 0x76, 0x34, 0xe5, 0xf5, 0x23, 0x49, 0x15, 0x90, 0x73, 0xa3, 0x0a, 0x5c, 0x4b, + /*1af0:*/ 0x99, 0x6f, 0x7b, 0x0f, 0x61, 0x9e, 0xf9, 0xa5, 0x95, 0x42, 0xbd, 0x19, 0xa5, 0x31, 0x08, 0xdd, + /*1b00:*/ 0x9a, 0x23, 0xdb, 0x2c, 0x19, 0x50, 0xbb, 0xc3, 0x3b, 0x51, 0xec, 0xd9, 0x38, 0x5b, 0x1b, 0x58, + /*1b10:*/ 0x79, 0xfb, 0xa2, 0x94, 0x6a, 0xe1, 0xd9, 0x03, 0x58, 0xd2, 0xb7, 0xfe, 0xc2, 0x99, 0xf4, 0x45, + /*1b20:*/ 0x28, 0x00, 0x11, 0x41, 0x67, 0x09, 0x1a, 0x82, 0x48, 0x11, 0x25, 0x82, 0x66, 0xd9, 0x08, 0xe4, + /*1b30:*/ 0xf3, 0x4f, 0xf1, 0x4c, 0x40, 0x78, 0xb7, 0x40, 0x5f, 0x16, 0xd6, 0x4d, 0x9d, 0x25, 0xcb, 0xff, + /*1b40:*/ 0xe1, 0xe7, 0xaf, 0x0c, 0x5b, 0x9a, 0x57, 0xf6, 0xc1, 0xd0, 0x1c, 0x20, 0x68, 0x9a, 0x51, 0x7a, + /*1b50:*/ 0xbd, 0xcb, 0x96, 0x21, 0x57, 0xe4, 0x70, 0x9d, 0x9c, 0xda, 0xaa, 0x89, 0x0d, 0xc2, 0x53, 0xa9, + /*1b60:*/ 0x6b, 0x78, 0x12, 0xeb, 0x77, 0x4d, 0x5c, 0xe4, 0x5e, 0x2b, 0x30, 0x0f, 0xb3, 0x08, 0x9f, 0x68, + /*1b70:*/ 0xf1, 0xb4, 0x37, 0xac, 0xed, 0x39, 0x0e, 0x59, 0xfa, 0xc4, 0xa8, 0xfa, 0xcc, 0x76, 0x77, 0xba, + /*1b80:*/ 0x15, 0xae, 0xbe, 0x0f, 0x89, 0xb7, 0x3c, 0xf5, 0x27, 0x2c, 0xfc, 0x05, 0xb2, 0x32, 0x40, 0x61, + /*1b90:*/ 0x0d, 0xdd, 0x0a, 0x8a, 0x0c, 0xa5, 0x7e, 0x2c, 0x5e, 0x50, 0x6b, 0xa1, 0x3b, 0x87, 0x23, 0xa0, + /*1ba0:*/ 0xa9, 0x4c, 0x46, 0x4c, 0xfb, 0xe2, 0x39, 0x3a, 0x3b, 0x43, 0x9b, 0x24, 0x8b, 0x4c, 0xae, 0x25, + /*1bb0:*/ 0x81, 0x72, 0x5e, 0xaf, 0xe3, 0x3f, 0x8c, 0x5b, 0x2f, 0xfd, 0x48, 0x61, 0x29, 0x9e, 0xba, 0x76, + /*1bc0:*/ 0x73, 0x3c, 0xeb, 0xeb, 0x30, 0x18, 0xa9, 0x89, 0x4c, 0xbc, 0x09, 0xb6, 0xd7, 0x46, 0x27, 0x76, + /*1bd0:*/ 0x51, 0x41, 0x52, 0x29, 0x2a, 0x73, 0x2d, 0xf0, 0x13, 0x9c, 0x00, 0x38, 0xe1, 0xe6, 0xc7, 0x9c, + /*1be0:*/ 0x7b, 0x07, 0xab, 0xf0, 0xf9, 0x0f, 0xc0, 0xce, 0x6a, 0xba, 0x10, 0x03, 0xfa, 0x55, 0x8b, 0x1a, + /*1bf0:*/ 0xfc, 0xd4, 0xdf, 0x8d, 0xf5, 0x98, 0x7e, 0xf1, 0x70, 0xff, 0x41, 0x9d, 0x66, 0xa3, 0x3a, 0x99, + /*1c00:*/ 0x5e, 0xe2, 0x9f, 0x29, 0x3b, 0xc8, 0xe9, 0x32, 0xb7, 0x1a, 0xb3, 0x47, 0xde, 0x42, 0x2d, 0x37, + /*1c10:*/ 0x2f, 0x13, 0xe6, 0x4a, 0xd8, 0x4d, 0xfc, 0x65, 0x6b, 0xaa, 0xd7, 0x58, 0xab, 0x86, 0x95, 0x88, + /*1c20:*/ 0x36, 0xf8, 0xf9, 0xa6, 0xd6, 0x66, 0xf3, 0xa7, 0x18, 0x62, 0x7d, 0xa3, 0x5f, 0xbe, 0xac, 0xba, + /*1c30:*/ 0x9f, 0x02, 0x3b, 0xa7, 0x43, 0x2a, 0xb5, 0x48, 0x70, 0x76, 0xda, 0xa2, 0x06, 0xb4, 0x67, 0x48, + /*1c40:*/ 0x33, 0xd9, 0x2d, 0xce, 0xd2, 0xe0, 0xd5, 0x3b, 0x81, 0xbb, 0x7a, 0x6a, 0xa9, 0xe5, 0xac, 0x82, + /*1c50:*/ 0x7c, 0x05, 0x7d, 0x93, 0x03, 0x15, 0xc2, 0x8f, 0x14, 0x44, 0xf9, 0xe2, 0xb2, 0x85, 0xfd, 0xe4, + /*1c60:*/ 0x7f, 0xaf, 0x3f, 0x36, 0x1e, 0xdc, 0x0f, 0x81, 0x29, 0x22, 0xfd, 0xb6, 0xf4, 0xa1, 0xef, 0xe2, + /*1c70:*/ 0x28, 0x82, 0xcb, 0x1c, 0x50, 0x4b, 0x68, 0x92, 0xc5, 0x40, 0xba, 0x8f, 0xb0, 0x13, 0x1e, 0xb7, + /*1c80:*/ 0xc4, 0x89, 0x78, 0x90, 0x52, 0x4a, 0x0d, 0xa9, 0x21, 0x25, 0x46, 0x65, 0x6c, 0x3f, 0x44, 0xb6, + /*1c90:*/ 0x6c, 0x6b, 0x91, 0xe2, 0x84, 0x75, 0x33, 0x58, 0x67, 0xf1, 0x19, 0x91, 0xd2, 0x18, 0xdb, 0x6c, + /*1ca0:*/ 0x80, 0x06, 0x8f, 0xb4, 0x13, 0xde, 0x16, 0x1b, 0x70, 0x8e, 0x11, 0x92, 0xfd, 0xa5, 0x38, 0xbf, + /*1cb0:*/ 0x3b, 0x88, 0x8a, 0xec, 0x26, 0xe7, 0x04, 0x47, 0x34, 0x63, 0xcc, 0xcb, 0x57, 0x35, 0x2d, 0xe7, + /*1cc0:*/ 0x77, 0x7c, 0xe3, 0x84, 0xfc, 0xdd, 0x45, 0x3b, 0x45, 0x9e, 0x7c, 0xf8, 0x78, 0x5d, 0x42, 0x09, + /*1cd0:*/ 0x23, 0x9c, 0xf5, 0x8e, 0x95, 0x0a, 0xac, 0x64, 0x35, 0x20, 0x78, 0xca, 0x3e, 0x2b, 0x5f, 0xd5, + /*1ce0:*/ 0xb0, 0x22, 0xc6, 0x3a, 0x9a, 0x6f, 0xa7, 0x57, 0xf6, 0x83, 0xb4, 0xad, 0xe9, 0xd7, 0x0f, 0xaa, + /*1cf0:*/ 0x93, 0x49, 0x6b, 0x04, 0xf9, 0x35, 0x16, 0x37, 0x7f, 0x82, 0xac, 0x7e, 0x87, 0x32, 0x84, 0xef, + /*1d00:*/ 0x1c, 0x06, 0x6a, 0xdc, 0x26, 0x23, 0xcd, 0x39, 0x3c, 0x71, 0xae, 0x7d, 0x08, 0x6d, 0x76, 0xa4, + /*1d10:*/ 0xf0, 0x68, 0xd6, 0x6c, 0xec, 0xc4, 0x10, 0x6c, 0xaf, 0x8e, 0x50, 0x2c, 0xd8, 0x06, 0xcd, 0x19, + /*1d20:*/ 0x05, 0xf8, 0x16, 0x3a, 0x28, 0xb9, 0x2e, 0x00, 0x0b, 0xf9, 0xa9, 0x1b, 0x5a, 0xa5, 0x34, 0x9c, + /*1d30:*/ 0xbe, 0x65, 0xb5, 0xe6, 0xb4, 0xc1, 0x8a, 0xfe, 0x1c, 0x24, 0x0f, 0x7e, 0x91, 0x8c, 0x65, 0x3d, + /*1d40:*/ 0xaa, 0x26, 0x13, 0x91, 0x8b, 0xee, 0xd9, 0x0c, 0xdc, 0xc7, 0x08, 0x21, 0x8c, 0xc4, 0xb7, 0x86, + /*1d50:*/ 0x45, 0xf7, 0x11, 0x35, 0x9d, 0x76, 0x38, 0x81, 0x6c, 0xc5, 0x49, 0x87, 0xe2, 0xe9, 0x48, 0x5c, + /*1d60:*/ 0xf9, 0x15, 0x30, 0x10, 0x2e, 0xee, 0x6e, 0x4d, 0x9b, 0xd3, 0xb8, 0x10, 0xff, 0xdd, 0x5d, 0xe1, + /*1d70:*/ 0x2c, 0x38, 0xfe, 0x0f, 0xae, 0x14, 0xb9, 0x21, 0x74, 0x6a, 0xc0, 0xf8, 0x29, 0x2e, 0xa1, 0xb0, + /*1d80:*/ 0xf9, 0x3c, 0x72, 0x46, 0x1b, 0xe7, 0xa2, 0xef, 0x18, 0x0b, 0xe3, 0xc7, 0x6b, 0x60, 0x6a, 0x7f, + /*1d90:*/ 0x60, 0x36, 0xa5, 0xa9, 0x3b, 0x13, 0x97, 0xd4, 0xee, 0x5a, 0x23, 0xd0, 0xc9, 0x2d, 0x3a, 0x1f, + /*1da0:*/ 0x84, 0x86, 0x42, 0xc5, 0x94, 0xf0, 0x6f, 0x9e, 0xd7, 0xa9, 0xa0, 0x63, 0xd0, 0xc2, 0xa2, 0x57, + /*1db0:*/ 0x3a, 0xe5, 0x14, 0xc9, 0xce, 0x7a, 0x77, 0xfc, 0x72, 0x99, 0xf7, 0x02, 0x92, 0xdb, 0x95, 0xf3, + /*1dc0:*/ 0x66, 0x17, 0xb0, 0xe1, 0x83, 0xe3, 0x13, 0x55, 0xe4, 0xf2, 0xb7, 0x45, 0x35, 0x34, 0x5e, 0x3b, + /*1dd0:*/ 0x1d, 0x68, 0x0a, 0x38, 0x94, 0x43, 0x7b, 0xc0, 0x21, 0x77, 0x3e, 0x11, 0x51, 0xba, 0x1b, 0x0c, + /*1de0:*/ 0x1f, 0x0b, 0x28, 0x23, 0xca, 0x79, 0x5b, 0x3c, 0xc8, 0x4b, 0x84, 0xd8, 0xa0, 0xfc, 0x9d, 0x7f, + /*1df0:*/ 0xad, 0xce, 0x6a, 0xe4, 0x7b, 0xbd, 0xbc, 0xbe, 0x9c, 0xef, 0x2c, 0x5e, 0x5c, 0x64, 0x1e, 0x5d, + /*1e00:*/ 0x97, 0x83, 0x20, 0x63, 0x5b, 0x4d, 0x18, 0xdd, 0xe3, 0x08, 0x7a, 0xfd, 0x7a, 0xb0, 0xb4, 0x89, + /*1e10:*/ 0xfe, 0x5d, 0x59, 0x5a, 0x50, 0x91, 0x6a, 0xe3, 0xd8, 0xe4, 0x4c, 0x74, 0x06, 0x1e, 0xb8, 0xcb, + /*1e20:*/ 0x27, 0x0e, 0x57, 0x76, 0x4c, 0x31, 0x76, 0x86, 0xd4, 0x37, 0x93, 0x6c, 0x13, 0x45, 0x6d, 0x79, + /*1e30:*/ 0xef, 0xab, 0xb6, 0x07, 0x7b, 0x07, 0xc0, 0x26, 0xa1, 0x61, 0x40, 0xa0, 0x67, 0x36, 0xfc, 0xb5, + /*1e40:*/ 0x8b, 0x75, 0x02, 0xd8, 0x4d, 0x60, 0x40, 0xeb, 0xf4, 0x02, 0xb2, 0xe3, 0x5e, 0x22, 0x13, 0xf5, + /*1e50:*/ 0xb4, 0x71, 0xb9, 0x64, 0x3a, 0x71, 0xba, 0xdb, 0x4e, 0xbe, 0x8e, 0x35, 0x18, 0xe1, 0xf3, 0xf1, + /*1e60:*/ 0xde, 0xd9, 0xba, 0x88, 0x1e, 0x08, 0xd7, 0x79, 0x54, 0xdd, 0x1c, 0xda, 0xa3, 0xcd, 0x18, 0x7b, + /*1e70:*/ 0x84, 0x17, 0xc7, 0x0a, 0x17, 0x9f, 0x14, 0x58, 0x6c, 0xce, 0x7f, 0x1b, 0x7c, 0x0b, 0xcd, 0x82, + /*1e80:*/ 0xee, 0x1a, 0x9f, 0x24, 0x94, 0x01, 0x76, 0xbe, 0x68, 0xb5, 0xc5, 0x9e, 0x6f, 0x3c, 0x90, 0x02, + /*1e90:*/ 0x2b, 0x58, 0xc3, 0x2e, 0x9d, 0xc0, 0x4e, 0xa2, 0x78, 0xf2, 0x2d, 0x8a, 0x07, 0x82, 0xbe, 0xd4, + /*1ea0:*/ 0xbf, 0x4a, 0x08, 0xa3, 0xa5, 0x89, 0xe0, 0x3f, 0x28, 0x0b, 0xec, 0xac, 0x77, 0xdd, 0xac, 0x52, + /*1eb0:*/ 0x7a, 0x58, 0x65, 0x59, 0x48, 0x03, 0xf9, 0x27, 0xd1, 0xa9, 0x7b, 0x37, 0xbe, 0x4c, 0x6c, 0x6b, + /*1ec0:*/ 0x73, 0x15, 0x74, 0xfc, 0x83, 0x1e, 0xbd, 0x67, 0x20, 0x14, 0xe9, 0xad, 0x93, 0x13, 0xd5, 0x45, + /*1ed0:*/ 0x2a, 0xdc, 0x6c, 0xa3, 0x04, 0xe7, 0x5f, 0x58, 0xea, 0x95, 0x25, 0x25, 0xe8, 0xb5, 0x32, 0x26, + /*1ee0:*/ 0xd8, 0xa1, 0x16, 0x0c, 0xbe, 0x63, 0xee, 0xc3, 0x52, 0xba, 0x01, 0xbe, 0xfd, 0xc1, 0x9b, 0x5c, + /*1ef0:*/ 0xf4, 0x6d, 0x1c, 0x08, 0x0a, 0xd9, 0xd9, 0xa6, 0xd2, 0x24, 0x05, 0x7c, 0x05, 0x8c, 0x4a, 0x7a, + /*1f00:*/ 0xfe, 0x35, 0x11, 0x82, 0xb6, 0x94, 0xe1, 0x3e, 0xc3, 0xd1, 0xad, 0x88, 0x3c, 0x2f, 0xb2, 0x2c, + /*1f10:*/ 0x75, 0xef, 0x37, 0xd8, 0x33, 0x9a, 0xf6, 0x65, 0x8f, 0x58, 0xa7, 0x64, 0x52, 0xb8, 0x95, 0x19, + /*1f20:*/ 0xe6, 0xee, 0x39, 0x03, 0xdd, 0x8d, 0x33, 0x47, 0xb5, 0xb7, 0x4b, 0x6f, 0x55, 0xb6, 0x8e, 0xca, + /*1f30:*/ 0x3d, 0x6f, 0xc7, 0x39, 0x1f, 0x56, 0xa1, 0xa8, 0xef, 0x0b, 0xcb, 0x52, 0xea, 0x2d, 0x1f, 0x11, + /*1f40:*/ 0xee, 0x6b, 0x6a, 0x26, 0x84, 0xce, 0x02, 0x5a, 0x10, 0x2d, 0x6f, 0xd6, 0x8f, 0xf9, 0x68, 0xd8, + /*1f50:*/ 0x0a, 0x67, 0xeb, 0x09, 0x7c, 0xd0, 0xa8, 0xfd, 0x47, 0x40, 0x49, 0x6f, 0xb1, 0xcd, 0x01, 0xaa, + /*1f60:*/ 0x2d, 0x85, 0xb8, 0xc7, 0x81, 0x3e, 0xc7, 0xa9, 0xbe, 0xc5, 0xc6, 0x20, 0xf2, 0x4d, 0x61, 0xff, + /*1f70:*/ 0x64, 0x45, 0xed, 0xa0, 0xa0, 0xa8, 0xbb, 0xb4, 0x78, 0x44, 0x1c, 0x7f, 0xe8, 0x87, 0x7b, 0xc1, + /*1f80:*/ 0x29, 0xc2, 0x71, 0x0d, 0x9a, 0xa7, 0x9c, 0xc4, 0x03, 0x1b, 0x6c, 0x25, 0x2f, 0x9f, 0xc4, 0xd1, + /*1f90:*/ 0x67, 0x19, 0x81, 0x3f, 0x71, 0x94, 0xcd, 0xed, 0x84, 0x9d, 0x0f, 0x42, 0xae, 0x38, 0xdf, 0xbd, + /*1fa0:*/ 0xc3, 0x92, 0x6b, 0xa8, 0x8b, 0x18, 0x45, 0xe2, 0xf3, 0x1c, 0x7c, 0xe6, 0x06, 0xeb, 0x41, 0x48, + /*1fb0:*/ 0xe1, 0x44, 0x79, 0x28, 0xa2, 0xfe, 0x46, 0x85, 0x9d, 0x1a, 0x83, 0x1d, 0x9c, 0xe3, 0xe2, 0xc9, + /*1fc0:*/ 0x33, 0x68, 0xa8, 0xa9, 0x07, 0x9c, 0x7f, 0x71, 0xe7, 0xf0, 0x4e, 0x21, 0x90, 0x80, 0xc1, 0x3e, + /*1fd0:*/ 0x1f, 0xae, 0xdd, 0xb8, 0x5a, 0x17, 0x86, 0x9a, 0xdf, 0xec, 0xde, 0xaa, 0x48, 0x99, 0x4b, 0xd9, + /*1fe0:*/ 0xa8, 0x9b, 0xbc, 0x34, 0x65, 0x30, 0x1a, 0x72, 0xf4, 0x69, 0xee, 0x81, 0x06, 0x86, 0xbe, 0x65, + /*1ff0:*/ 0x74, 0x22, 0xdc, 0x45, 0x61, 0x4d, 0x11, 0x16, 0x94, 0xc3, 0xaf, 0x31, 0xf2, 0x2e, 0x7e, 0x0a, + /*2000:*/ 0xe9, 0xcc, 0x15, 0x55, 0xdd, 0x5c, 0x4b, 0xc8, 0xe6, 0x54, 0x65, 0x71, 0x96, 0xb6, 0x05, 0xa1, + /*2010:*/ 0xf6, 0x12, 0xf5, 0x2e, 0xbd, 0x04, 0x7d, 0xc9, 0xb6, 0xe1, 0x40, 0x64, 0x35, 0x33, 0x2e, 0x1e, + /*2020:*/ 0xfd, 0xcb, 0x48, 0x03, 0xc1, 0x90, 0x27, 0x65, 0x2c, 0xa5, 0x3b, 0xba, 0x99, 0x89, 0x1d, 0x63, + /*2030:*/ 0x27, 0x31, 0xa4, 0x45, 0x7a, 0x5d, 0xbb, 0x67, 0xea, 0x3e, 0x3d, 0x03, 0x71, 0x8b, 0xda, 0x94, + /*2040:*/ 0xc6, 0x09, 0xb6, 0xfb, 0x87, 0x2e, 0x50, 0x67, 0x04, 0x3d, 0xf0, 0x54, 0xd8, 0xcb, 0xee, 0x74, + /*2050:*/ 0x59, 0x15, 0x9a, 0x40, 0xb2, 0xf1, 0xae, 0xa2, 0x9c, 0x76, 0x6b, 0x2b, 0x70, 0xc8, 0xe9, 0x20, + /*2060:*/ 0x95, 0x16, 0xb8, 0xb2, 0x7e, 0x43, 0xd7, 0x5b, 0x3d, 0xce, 0x82, 0x22, 0x61, 0xff, 0x64, 0x14, + /*2070:*/ 0xcc, 0x7e, 0xf8, 0x73, 0x5e, 0x72, 0xf3, 0xfc, 0xea, 0xbf, 0x44, 0xc4, 0x1b, 0x25, 0xd1, 0xbd, + /*2080:*/ 0x95, 0x3a, 0xb0, 0x1b, 0x1f, 0xfa, 0x7b, 0xbe, 0x52, 0x80, 0x21, 0xb6, 0x22, 0x0b, 0x9c, 0x38, + /*2090:*/ 0x3d, 0xbb, 0xae, 0x2f, 0xd8, 0xaf, 0x45, 0x00, 0x47, 0x44, 0xcd, 0x6a, 0x66, 0x8c, 0xc5, 0x35, + /*20a0:*/ 0xfd, 0x6d, 0xe4, 0xf5, 0xfa, 0xfa, 0x00, 0xff, 0x96, 0xdb, 0x91, 0xad, 0x00, 0x05, 0xbe, 0x99, + /*20b0:*/ 0xa0, 0x15, 0x4d, 0xb6, 0xb5, 0x26, 0xc4, 0x82, 0xa9, 0xd4, 0xbc, 0x2f, 0xe1, 0x85, 0x18, 0xd0, + /*20c0:*/ 0xa7, 0xdc, 0xbe, 0x53, 0x84, 0xac, 0x2a, 0xc3, 0xf9, 0x8c, 0x01, 0x6e, 0xdb, 0x3e, 0x7a, 0xf4, + /*20d0:*/ 0x0b, 0xf3, 0x82, 0x34, 0x4d, 0x8a, 0x67, 0x0a, 0x68, 0x5c, 0x87, 0xd5, 0x12, 0x11, 0xf7, 0xd0, + /*20e0:*/ 0xf2, 0xd7, 0x3c, 0x2c, 0x7a, 0xf6, 0xee, 0x3a, 0x7f, 0xa3, 0x66, 0xb4, 0x76, 0x5e, 0x2b, 0x14, + /*20f0:*/ 0x17, 0xdc, 0x28, 0x89, 0xa4, 0xba, 0x8e, 0x66, 0x82, 0x18, 0xfe, 0x04, 0xcc, 0x44, 0xf8, 0xd9, + /*2100:*/ 0x76, 0x30, 0x30, 0xad, 0x4c, 0xa0, 0x5f, 0x8a, 0x7b, 0x59, 0x07, 0xb9, 0x1f, 0xdc, 0x88, 0xac, + /*2110:*/ 0xbf, 0xcb, 0x8d, 0x64, 0x34, 0x01, 0xd6, 0xb1, 0x03, 0xd7, 0xa8, 0x0b, 0x2f, 0xee, 0x98, 0x8d, + /*2120:*/ 0x18, 0x9f, 0x19, 0xf4, 0xc3, 0x9c, 0x44, 0x9a, 0x2b, 0xdf, 0x88, 0x79, 0xad, 0x0f, 0x13, 0x3e, + /*2130:*/ 0xd7, 0xb9, 0x5c, 0x50, 0xed, 0x0c, 0xda, 0xb0, 0xb6, 0x6e, 0xdb, 0x6d, 0x03, 0x31, 0xc6, 0x97, + /*2140:*/ 0xac, 0x8f, 0x9c, 0x2d, 0x16, 0x88, 0x72, 0x49, 0x82, 0x99, 0xc0, 0x71, 0x59, 0x27, 0xb6, 0x39, + /*2150:*/ 0xc8, 0x30, 0x56, 0x8e, 0x8f, 0xa2, 0xa5, 0xbe, 0xc4, 0x01, 0x1e, 0x12, 0x42, 0xab, 0xd1, 0x9c, + /*2160:*/ 0x4c, 0x34, 0xef, 0x87, 0x36, 0xf2, 0xce, 0xde, 0xf5, 0x23, 0x71, 0x12, 0x7e, 0xb6, 0x8e, 0x25, + /*2170:*/ 0x82, 0x7d, 0xd6, 0xac, 0x07, 0xbb, 0x01, 0xfc, 0x9d, 0x14, 0xdf, 0x24, 0x38, 0x7c, 0xd8, 0x42, + /*2180:*/ 0x3a, 0xf9, 0xb1, 0xfd, 0x66, 0x9f, 0x7c, 0x47, 0x9d, 0x57, 0x3b, 0x75, 0x44, 0x63, 0xe8, 0x4c, + /*2190:*/ 0x7c, 0xf2, 0xfc, 0xec, 0x43, 0x83, 0x87, 0xd3, 0x13, 0x73, 0x33, 0x98, 0x7d, 0x33, 0x0b, 0x4b, + /*21a0:*/ 0x44, 0xb2, 0xc1, 0x9c, 0xb3, 0x03, 0x67, 0x80, 0xef, 0x95, 0x06, 0xe0, 0xbb, 0xe1, 0xe5, 0x33, + /*21b0:*/ 0x21, 0x73, 0x1f, 0x91, 0xf1, 0x14, 0xdc, 0x9e, 0x53, 0xe3, 0x14, 0x85, 0x43, 0x1e, 0xaa, 0x5d, + /*21c0:*/ 0x08, 0x7b, 0x28, 0x8d, 0x43, 0x27, 0xec, 0x2d, 0xab, 0xe7, 0xe2, 0x09, 0xc9, 0x15, 0x1a, 0x87, + /*21d0:*/ 0x58, 0xa6, 0xfe, 0x35, 0xd0, 0xd9, 0x87, 0x39, 0x7e, 0xae, 0xc2, 0x91, 0x0a, 0x0f, 0xf3, 0x48, + /*21e0:*/ 0xe2, 0x5d, 0x4c, 0x1a, 0x56, 0xbb, 0x74, 0x8e, 0x9f, 0x25, 0xf0, 0x90, 0x46, 0xcf, 0x50, 0x35, + /*21f0:*/ 0x7a, 0x59, 0xe1, 0x6a, 0xd4, 0x24, 0x97, 0x4a, 0xca, 0xdb, 0xbd, 0x83, 0xd9, 0xa9, 0x6a, 0xae, + /*2200:*/ 0xea, 0x46, 0x97, 0x14, 0xdd, 0xaf, 0x46, 0x79, 0x98, 0xb7, 0x20, 0xf2, 0x3e, 0x98, 0xd8, 0x6c, + /*2210:*/ 0xc5, 0x57, 0x5d, 0xed, 0x08, 0xda, 0x0f, 0x98, 0x06, 0xd8, 0xdc, 0x2c, 0x28, 0x8d, 0xc5, 0x21, + /*2220:*/ 0x33, 0xc1, 0xc4, 0x2d, 0x1e, 0x85, 0x7b, 0x82, 0x12, 0x74, 0x78, 0x2b, 0xf5, 0x0b, 0x77, 0xeb, + /*2230:*/ 0xc8, 0x6f, 0x42, 0x83, 0xe2, 0x19, 0x25, 0x6b, 0xff, 0x92, 0xb7, 0x63, 0x82, 0xae, 0xc9, 0x0d, + /*2240:*/ 0xa0, 0xc3, 0x64, 0x6f, 0x13, 0x8c, 0xf2, 0x8a, 0xa2, 0xb6, 0x57, 0x99, 0x2e, 0x92, 0xa6, 0x3c, + /*2250:*/ 0xa1, 0x86, 0x05, 0x76, 0x4f, 0x55, 0x5d, 0x2b, 0x3c, 0x28, 0x30, 0x00, 0x51, 0x5e, 0xa1, 0x90, + /*2260:*/ 0x35, 0x0b, 0x78, 0xb6, 0x04, 0x82, 0xca, 0xe0, 0x3e, 0xb9, 0xe0, 0x12, 0x19, 0x62, 0xfd, 0x05, + /*2270:*/ 0x81, 0xd7, 0x78, 0xb9, 0x23, 0x14, 0xe3, 0xb3, 0x4d, 0xac, 0x97, 0x80, 0xac, 0x4c, 0x98, 0xea, + /*2280:*/ 0x60, 0x89, 0x62, 0x8b, 0xc0, 0xd2, 0x37, 0x5c, 0x5a, 0x63, 0xcf, 0x7a, 0x55, 0x3a, 0x67, 0xeb, + /*2290:*/ 0xec, 0xcb, 0xd6, 0xf7, 0x39, 0x33, 0xf0, 0x6e, 0x4c, 0x8c, 0x0f, 0x75, 0x60, 0x5a, 0x5f, 0x08, + /*22a0:*/ 0x52, 0x93, 0x86, 0x50, 0xf3, 0xf1, 0x99, 0x9f, 0x3a, 0x02, 0x9e, 0xe8, 0xca, 0xe7, 0x95, 0x47, + /*22b0:*/ 0xb0, 0x37, 0x4e, 0xa1, 0x53, 0xc8, 0xaf, 0xb6, 0x6e, 0x55, 0xdf, 0xf8, 0x7d, 0xf2, 0xe7, 0x36, + /*22c0:*/ 0xc2, 0xf8, 0xbc, 0x54, 0xe7, 0x01, 0x13, 0x6b, 0x3f, 0xcc, 0xd0, 0x84, 0xe4, 0xac, 0xd8, 0x0a, + /*22d0:*/ 0x26, 0x2f, 0x82, 0xe1, 0xce, 0x3d, 0x60, 0xe4, 0xb9, 0xb2, 0xad, 0xd9, 0x9c, 0x4c, 0x2f, 0xa3, + /*22e0:*/ 0x2b, 0x37, 0x8f, 0x0d, 0x65, 0x38, 0xc5, 0x76, 0xca, 0x97, 0xa1, 0x64, 0xca, 0x3c, 0x14, 0xb6, + /*22f0:*/ 0xb3, 0x68, 0xaf, 0xb2, 0x47, 0x66, 0x4b, 0x85, 0x21, 0x1e, 0xa2, 0x60, 0xd7, 0x85, 0x8a, 0x9b, + /*2300:*/ 0x35, 0x0e, 0xd8, 0x20, 0x12, 0x8b, 0xca, 0x25, 0x17, 0xc4, 0x57, 0xb8, 0x6a, 0x6f, 0xac, 0xa9, + /*2310:*/ 0xf4, 0xe9, 0x3c, 0xc1, 0x05, 0x4a, 0x8c, 0x5c, 0xba, 0xbb, 0x82, 0xe7, 0xa7, 0xd0, 0x58, 0x44, + /*2320:*/ 0x13, 0x86, 0xac, 0x3c, 0x63, 0x9b, 0xa8, 0xb5, 0x56, 0x13, 0x55, 0xce, 0xc3, 0xd3, 0x29, 0xec, + /*2330:*/ 0x96, 0x27, 0x17, 0xde, 0x8a, 0xec, 0x31, 0x56, 0x6e, 0x3b, 0xfa, 0x4e, 0xa9, 0x51, 0x9c, 0x1c, + /*2340:*/ 0x67, 0x70, 0xbb, 0xc7, 0x50, 0x2d, 0xfb, 0xc9, 0x21, 0x64, 0x4c, 0xdd, 0xe7, 0xd2, 0x57, 0xfe, + /*2350:*/ 0x09, 0x12, 0x0d, 0xe7, 0x5b, 0x0f, 0x81, 0x21, 0x13, 0x44, 0x2f, 0x57, 0xab, 0xe8, 0xac, 0xf6, + /*2360:*/ 0x02, 0x23, 0x3d, 0xa1, 0x4f, 0xf5, 0x54, 0x20, 0xe2, 0x82, 0x4d, 0xf4, 0x22, 0x15, 0xc5, 0x70, + /*2370:*/ 0xf7, 0x9d, 0xd7, 0x3b, 0xb5, 0x30, 0x82, 0x94, 0x47, 0x26, 0xba, 0xb1, 0x15, 0xe6, 0x7c, 0xba, + /*2380:*/ 0xb0, 0xcd, 0xd2, 0xe6, 0x69, 0x52, 0x35, 0x0b, 0x77, 0x78, 0xd2, 0x65, 0x7c, 0xa3, 0xba, 0x56, + /*2390:*/ 0x61, 0xa0, 0xb1, 0x93, 0x83, 0xa1, 0x28, 0x23, 0x37, 0xb5, 0x1f, 0x56, 0x64, 0xdc, 0x66, 0x02, + /*23a0:*/ 0x22, 0x2d, 0xa7, 0x14, 0x77, 0x3e, 0xc0, 0xdb, 0x5c, 0x84, 0x63, 0x0f, 0xea, 0x37, 0x36, 0x34, + /*23b0:*/ 0xab, 0xab, 0x99, 0x5b, 0x81, 0x37, 0x22, 0xa5, 0x94, 0xe5, 0xf2, 0x79, 0x2f, 0x45, 0xc7, 0xc9, + /*23c0:*/ 0xa7, 0xfa, 0x6d, 0xbe, 0x02, 0x99, 0x2e, 0xeb, 0x6c, 0xc8, 0xc3, 0x24, 0x48, 0xbc, 0x9b, 0x4e, + /*23d0:*/ 0x13, 0x05, 0xfe, 0x9f, 0x67, 0xe7, 0x62, 0xc3, 0x74, 0x6d, 0x24, 0xf9, 0x42, 0x71, 0x77, 0x85, + /*23e0:*/ 0x4f, 0xb4, 0xba, 0x77, 0xbc, 0xdc, 0x49, 0x94, 0x73, 0x24, 0xe1, 0x62, 0xe1, 0xee, 0x8f, 0xd1, + /*23f0:*/ 0xa1, 0x7a, 0x72, 0x40, 0xba, 0x5e, 0x8c, 0x60, 0x31, 0x6e, 0x5d, 0x71, 0x15, 0x42, 0xf9, 0x70, + /*2400:*/ 0x61, 0x88, 0x08, 0x72, 0xa7, 0x03, 0x92, 0x3d, 0xc0, 0x0f, 0xed, 0x11, 0xf9, 0x32, 0xbe, 0x42, + /*2410:*/ 0x03, 0xb3, 0xb9, 0x15, 0xe1, 0x50, 0x00, 0xcf, 0xcd, 0x19, 0x19, 0x82, 0x32, 0x39, 0x43, 0x1a, + /*2420:*/ 0x54, 0xbd, 0xf4, 0xd8, 0x47, 0xe1, 0x01, 0x7a, 0xf5, 0xdb, 0x6f, 0xae, 0xad, 0xd4, 0x52, 0x6a, + /*2430:*/ 0xe0, 0x98, 0xa8, 0x8e, 0x1b, 0x1c, 0x54, 0x75, 0x6f, 0x71, 0x53, 0xbd, 0xea, 0x26, 0x78, 0x50, + /*2440:*/ 0x7b, 0x10, 0xe5, 0x5b, 0x56, 0xe4, 0xd8, 0x47, 0x20, 0xf8, 0x39, 0xb5, 0x29, 0xab, 0x99, 0x66, + /*2450:*/ 0xe9, 0xc9, 0xa2, 0x30, 0x8e, 0x14, 0xfc, 0x2c, 0x14, 0xdc, 0xba, 0xc9, 0x8a, 0xa1, 0x06, 0xab, + /*2460:*/ 0xfd, 0xc8, 0x93, 0x52, 0x26, 0x44, 0xf6, 0x0d, 0xc9, 0x46, 0x8a, 0x4e, 0x0b, 0x96, 0x98, 0x4d, + /*2470:*/ 0xf3, 0x71, 0x8f, 0xdf, 0x02, 0x2a, 0xa6, 0x8b, 0xe7, 0x6d, 0x6c, 0x80, 0x18, 0x21, 0x3c, 0x7c, + /*2480:*/ 0x6f, 0xc0, 0xb6, 0xea, 0x5d, 0x78, 0xb5, 0x46, 0xf9, 0x27, 0xfa, 0x4f, 0xd3, 0xbe, 0x83, 0xe2, + /*2490:*/ 0xaa, 0x26, 0xee, 0x71, 0x86, 0x5d, 0xf1, 0x05, 0x15, 0x97, 0x98, 0x0a, 0xdd, 0xa3, 0x67, 0x93, + /*24a0:*/ 0x50, 0xc1, 0x1a, 0xa7, 0xd1, 0xa0, 0xcd, 0xa4, 0xfe, 0xfa, 0x5a, 0x0e, 0x34, 0x64, 0x4c, 0x00, + /*24b0:*/ 0x41, 0xfc, 0x6e, 0x8c, 0x65, 0x60, 0xa5, 0xe9, 0xea, 0xc1, 0xd2, 0xed, 0x27, 0xd1, 0x3c, 0x87, + /*24c0:*/ 0xbb, 0xdd, 0xc8, 0xfa, 0x10, 0xa4, 0x90, 0x68, 0x4d, 0x8c, 0x9f, 0x3d, 0x47, 0x41, 0x1e, 0x38, + /*24d0:*/ 0x55, 0x7a, 0x02, 0xb5, 0xfc, 0xea, 0xcc, 0x33, 0x15, 0x62, 0xa3, 0x0c, 0x16, 0x39, 0x3a, 0x1d, + /*24e0:*/ 0xfd, 0x6d, 0x89, 0xb2, 0x93, 0x18, 0xb1, 0xfb, 0x74, 0x2b, 0x58, 0x6e, 0x2e, 0xa3, 0x0a, 0xfc, + /*24f0:*/ 0xed, 0x5e, 0xc9, 0xfc, 0xda, 0xdc, 0x61, 0xf1, 0x1b, 0xdc, 0x8b, 0xd6, 0x19, 0x3d, 0x3f, 0x68, + /*2500:*/ 0x90, 0x83, 0x19, 0x79, 0xe7, 0xfe, 0x11, 0x14, 0xf7, 0xe7, 0x3d, 0x94, 0x08, 0x60, 0xbd, 0xaa, + /*2510:*/ 0xdd, 0x87, 0xd0, 0xf4, 0xd2, 0xf5, 0xe4, 0x90, 0xa8, 0x73, 0xae, 0xb6, 0xb3, 0x8a, 0xc1, 0x36, + /*2520:*/ 0xa1, 0x1a, 0x03, 0x7c, 0xbe, 0x9d, 0xcb, 0xbc, 0x3a, 0x0f, 0x16, 0x54, 0xdb, 0xd6, 0xb4, 0x84, + /*2530:*/ 0x79, 0xe3, 0x95, 0xee, 0x5a, 0x65, 0x88, 0x1a, 0x68, 0x82, 0xc1, 0x32, 0x47, 0x94, 0x4a, 0x8b, + /*2540:*/ 0xb8, 0x1b, 0xa4, 0x77, 0x49, 0x65, 0x51, 0xbb, 0xbd, 0x0c, 0xd2, 0x7b, 0xbd, 0xff, 0xd9, 0x72, + /*2550:*/ 0x2e, 0x37, 0xc2, 0xc0, 0xf0, 0x03, 0xc7, 0x13, 0x46, 0xef, 0x7b, 0xa1, 0xf1, 0xa5, 0xbd, 0x1f, + /*2560:*/ 0x0e, 0x2f, 0x4e, 0x20, 0x51, 0xc7, 0x54, 0x57, 0x84, 0x78, 0xac, 0x7b, 0xc9, 0xe1, 0x8d, 0x66, + /*2570:*/ 0x51, 0x12, 0x79, 0x7c, 0x9c, 0x3d, 0xe2, 0xf3, 0x8e, 0x6b, 0x77, 0x84, 0x47, 0x14, 0x4d, 0x87, + /*2580:*/ 0xac, 0xa0, 0x9a, 0x5f, 0xd7, 0x4f, 0x18, 0x44, 0x8e, 0x96, 0x6f, 0xf4, 0xf0, 0x45, 0x73, 0x36, + /*2590:*/ 0x34, 0xa5, 0xaa, 0x24, 0xec, 0xde, 0x68, 0xa3, 0xda, 0x9e, 0xfc, 0x19, 0xba, 0x0e, 0x31, 0x80, + /*25a0:*/ 0x20, 0xad, 0x73, 0x0c, 0x35, 0x2d, 0x5f, 0x50, 0x41, 0x58, 0x02, 0xb6, 0x4c, 0xeb, 0xcf, 0xa1, + /*25b0:*/ 0x6e, 0x54, 0x66, 0xf9, 0xfb, 0xfa, 0x73, 0x48, 0x53, 0x9d, 0xbc, 0x7b, 0xe4, 0x6e, 0xad, 0xa7, + /*25c0:*/ 0x68, 0x6c, 0x3a, 0xed, 0xd9, 0x01, 0x49, 0xbe, 0xe8, 0x03, 0x36, 0xb6, 0x06, 0x2f, 0xfc, 0xfa, + /*25d0:*/ 0x5c, 0xd1, 0xe2, 0x4d, 0x62, 0xdc, 0x1c, 0xb8, 0x9b, 0xfc, 0x6e, 0x26, 0x3c, 0x38, 0xc3, 0x3d, + /*25e0:*/ 0xe0, 0x52, 0x61, 0x10, 0x34, 0x97, 0x15, 0x3f, 0xa9, 0xdc, 0xc2, 0xad, 0x32, 0xf7, 0x3d, 0x70, + /*25f0:*/ 0xe7, 0xf1, 0x2e, 0xe8, 0x1e, 0xbd, 0x8e, 0x90, 0xfb, 0x22, 0x73, 0xde, 0xe7, 0xb8, 0x9c, 0xce, + /*2600:*/ 0x9b, 0x89, 0xd3, 0x51, 0xfd, 0xe9, 0x07, 0xbe, 0x32, 0x14, 0x04, 0x22, 0xf8, 0x73, 0x75, 0x39, + /*2610:*/ 0x6d, 0x77, 0x21, 0x58, 0x5e, 0x64, 0x98, 0x36, 0x67, 0xc4, 0xed, 0x70, 0x25, 0xf7, 0x79, 0x12, + /*2620:*/ 0x53, 0xa8, 0xff, 0x59, 0x0b, 0xb7, 0xe0, 0x78, 0x35, 0xe5, 0x47, 0x70, 0xd9, 0xc5, 0x13, 0xe7, + /*2630:*/ 0xda, 0xa9, 0x09, 0xc9, 0x17, 0x68, 0x58, 0xb8, 0xbc, 0xa3, 0xf3, 0xf6, 0x02, 0xda, 0x35, 0x93, + /*2640:*/ 0x7f, 0xf2, 0x4e, 0x5f, 0x2f, 0xf2, 0x30, 0xca, 0xce, 0x23, 0xb3, 0x13, 0xff, 0xa3, 0xd6, 0x76, + /*2650:*/ 0xf8, 0xd5, 0xb8, 0xad, 0x52, 0xe3, 0x55, 0x15, 0x6e, 0x3b, 0x61, 0x5e, 0x25, 0x97, 0xda, 0x62, + /*2660:*/ 0xe6, 0x5a, 0x1a, 0xc3, 0x2e, 0x5d, 0xcd, 0xb9, 0x41, 0xe3, 0x72, 0x0b, 0x12, 0x94, 0x95, 0x08, + /*2670:*/ 0x06, 0x86, 0x45, 0xf9, 0x38, 0x8d, 0x41, 0xf6, 0x3e, 0x84, 0x6d, 0x06, 0xfb, 0x41, 0x55, 0x0d, + /*2680:*/ 0x8e, 0x31, 0x8d, 0x8d, 0x7c, 0x9b, 0x1e, 0x54, 0x5a, 0xac, 0xe1, 0x3e, 0xc0, 0x03, 0x36, 0x23, + /*2690:*/ 0x81, 0x13, 0xe7, 0xcc, 0x1b, 0xc3, 0x9c, 0x6a, 0xc1, 0xfc, 0xe9, 0x9c, 0x20, 0xa0, 0x4a, 0x84, + /*26a0:*/ 0x0f, 0x17, 0xcc, 0xf1, 0xb6, 0xcc, 0xf9, 0x5e, 0x52, 0x0a, 0x70, 0x03, 0x24, 0x73, 0x65, 0x5b, + /*26b0:*/ 0x28, 0x8d, 0xe5, 0x99, 0x8e, 0x47, 0xfd, 0x75, 0x63, 0xd6, 0x6a, 0x16, 0xe7, 0xa8, 0x27, 0x44, + /*26c0:*/ 0x76, 0xf6, 0x81, 0xf9, 0xec, 0x37, 0x49, 0x5b, 0x50, 0x19, 0x11, 0x8e, 0xe4, 0x21, 0x6f, 0xca, + /*26d0:*/ 0xd3, 0x91, 0xb7, 0x2d, 0x91, 0x1b, 0x99, 0x19, 0xb6, 0xfb, 0xcd, 0xb6, 0xe4, 0x11, 0xd3, 0x26, + /*26e0:*/ 0x70, 0xa9, 0x3f, 0x3e, 0x81, 0x66, 0x8c, 0x97, 0xce, 0xe8, 0x98, 0x0a, 0x55, 0x57, 0x7f, 0x14, + /*26f0:*/ 0x8b, 0x9d, 0xb5, 0x81, 0x3b, 0x61, 0x25, 0x5e, 0xa0, 0xda, 0xcc, 0x64, 0xf1, 0xe2, 0xe4, 0xa0, + /*2700:*/ 0x86, 0xdb, 0xec, 0x17, 0x94, 0x06, 0xe8, 0xa3, 0x6d, 0x65, 0xd7, 0x0e, 0xda, 0x42, 0xfa, 0x65, + /*2710:*/ 0x2f, 0x86, 0xde, 0xb3, 0x0c, 0x85, 0x46, 0xb2, 0x5f, 0x43, 0x40, 0xc7, 0x06, 0xfc, 0xd7, 0xbc, + /*2720:*/ 0x13, 0x3d, 0x1e, 0x7c, 0xfe, 0x21, 0x92, 0x51, 0xcd, 0xb6, 0xf2, 0xdd, 0xf2, 0xf1, 0x63, 0x3d, + /*2730:*/ 0x23, 0x81, 0xd4, 0x82, 0x2e, 0x7b, 0x7d, 0x9b, 0xa4, 0x45, 0x30, 0xf5, 0xbf, 0x32, 0x01, 0xbd, + /*2740:*/ 0xda, 0x6e, 0xb6, 0x43, 0xbc, 0xb3, 0xf2, 0xbb, 0x7c, 0x99, 0xcc, 0x84, 0xc2, 0x32, 0x89, 0xe9, + /*2750:*/ 0xfa, 0xeb, 0x75, 0x52, 0x77, 0xc2, 0xf4, 0x18, 0x1f, 0x16, 0xef, 0x3a, 0xcd, 0xef, 0xce, 0x7f, + /*2760:*/ 0x69, 0xcf, 0x0d, 0x50, 0xa4, 0xc6, 0x17, 0xf8, 0x00, 0x28, 0xed, 0xa6, 0x98, 0x97, 0xb8, 0x42, + /*2770:*/ 0xae, 0xc1, 0x43, 0x4d, 0x00, 0x0c, 0x41, 0x67, 0xf1, 0xe5, 0xed, 0x28, 0x75, 0x64, 0x27, 0x57, + /*2780:*/ 0x0a, 0x42, 0xa0, 0x9f, 0x81, 0x6b, 0xf4, 0xa8, 0x4a, 0x92, 0xe4, 0xf4, 0xe2, 0x02, 0x5d, 0xf1, + /*2790:*/ 0x2c, 0xe6, 0x61, 0x2d, 0xc8, 0x73, 0x24, 0x58, 0xb9, 0x52, 0x8c, 0x3d, 0x69, 0x5f, 0xc4, 0xc5, + /*27a0:*/ 0x7c, 0x76, 0x40, 0x0f, 0x27, 0x98, 0x30, 0x34, 0xc7, 0xb3, 0x9f, 0x8c, 0xa2, 0x59, 0x90, 0x60, + /*27b0:*/ 0xe5, 0xbe, 0x1c, 0x06, 0xc5, 0x7e, 0x3b, 0xce, 0x8c, 0x18, 0x19, 0x52, 0xe5, 0x20, 0xc9, 0x58, + /*27c0:*/ 0xea, 0x6b, 0x24, 0x44, 0x8f, 0x8d, 0x41, 0xbc, 0xb7, 0xd9, 0x7d, 0x38, 0xc5, 0xf9, 0xe4, 0x8d, + /*27d0:*/ 0xf6, 0x7a, 0x01, 0x3d, 0x0f, 0x9c, 0xf3, 0x55, 0x54, 0x78, 0xa8, 0xb8, 0x2e, 0x4f, 0xfd, 0x4e, + /*27e0:*/ 0xc7, 0xea, 0x78, 0xbc, 0xa3, 0x35, 0xa6, 0x8a, 0x70, 0xfb, 0xef, 0xb0, 0x5e, 0x72, 0x91, 0x3e, + /*27f0:*/ 0x43, 0xc0, 0xb0, 0x1e, 0x7a, 0x3a, 0xcd, 0xa1, 0xfd, 0x02, 0x6b, 0x55, 0xc1, 0xd2, 0x3a, 0xd1, + /*2800:*/ 0x65, 0x71, 0x5d, 0x2c, 0x57, 0xce, 0x15, 0xec, 0x08, 0xb0, 0x83, 0xf0, 0xac, 0x4f, 0x10, 0xa0, + /*2810:*/ 0x80, 0xc3, 0x64, 0x82, 0x87, 0xb4, 0x99, 0x83, 0xd3, 0x3b, 0x21, 0x03, 0xbc, 0xa3, 0x8a, 0x4f, + /*2820:*/ 0xcb, 0x72, 0x0f, 0x13, 0x55, 0xb8, 0x50, 0x30, 0x8a, 0xc7, 0x3e, 0xc8, 0x1b, 0xd2, 0x80, 0xec, + /*2830:*/ 0x87, 0x25, 0x4f, 0x9f, 0x19, 0xd6, 0x3f, 0xfc, 0x7b, 0xed, 0x1b, 0x8b, 0xa8, 0x27, 0x82, 0xa2, + /*2840:*/ 0x67, 0xae, 0xed, 0xd9, 0x1d, 0xba, 0x29, 0x2c, 0xd2, 0x11, 0x6a, 0xbd, 0x98, 0x0a, 0xca, 0x16, + /*2850:*/ 0xaf, 0xe6, 0x80, 0x10, 0xe4, 0x3c, 0x0e, 0xd2, 0xd2, 0xfe, 0x4a, 0x71, 0x1f, 0x6e, 0x6e, 0xf4, + /*2860:*/ 0xf5, 0x4a, 0x27, 0xf8, 0xb8, 0x6a, 0xf1, 0x47, 0xbe, 0xfe, 0x48, 0x31, 0x87, 0xd1, 0x31, 0x1d, + /*2870:*/ 0x6e, 0x64, 0xde, 0x2a, 0x50, 0xb6, 0x47, 0xf2, 0x35, 0xd7, 0x97, 0x70, 0x2a, 0xf7, 0xf1, 0xa7, + /*2880:*/ 0x14, 0x57, 0x09, 0x45, 0xa9, 0x64, 0x6b, 0x3f, 0x98, 0xc7, 0xe9, 0xf4, 0x5f, 0x74, 0xe4, 0x44, + /*2890:*/ 0x34, 0xce, 0x4a, 0x60, 0x80, 0x6c, 0xe7, 0x88, 0xc9, 0xab, 0x26, 0x5a, 0xc4, 0x5f, 0xe3, 0x09, + /*28a0:*/ 0x2d, 0xc8, 0x95, 0xae, 0xfc, 0x8e, 0xdf, 0xc9, 0x3c, 0x65, 0x5c, 0xf5, 0x7c, 0x04, 0x20, 0xcb, + /*28b0:*/ 0x22, 0xb7, 0x6b, 0x91, 0xc3, 0x2d, 0xa0, 0x25, 0xc2, 0x69, 0x7b, 0x3d, 0x86, 0x1a, 0x20, 0x49, + /*28c0:*/ 0x8d, 0x42, 0xc1, 0xc4, 0x9a, 0x1f, 0xf3, 0x3f, 0x52, 0xf0, 0xf1, 0xe2, 0x5c, 0xf0, 0x37, 0x12, + /*28d0:*/ 0x99, 0x13, 0x21, 0x70, 0x39, 0x7c, 0x74, 0x22, 0xff, 0xc6, 0xc6, 0x0c, 0xbc, 0xf6, 0x8d, 0x72, + /*28e0:*/ 0xeb, 0xa4, 0x13, 0x79, 0xd7, 0x23, 0xa8, 0xdb, 0x59, 0x7b, 0x70, 0xfd, 0x06, 0xf5, 0x6c, 0x53, + /*28f0:*/ 0xe5, 0x04, 0x74, 0xa7, 0xc8, 0xb6, 0xe6, 0x95, 0x99, 0x95, 0x89, 0x55, 0xc7, 0xdd, 0xc9, 0x45, + /*2900:*/ 0xb5, 0x88, 0xc7, 0xbd, 0x0d, 0x52, 0xf0, 0x08, 0x03, 0x87, 0x9e, 0x8b, 0xe6, 0x68, 0x57, 0xde, + /*2910:*/ 0x81, 0x77, 0x92, 0x91, 0x45, 0x41, 0x3a, 0xfe, 0x2f, 0xf0, 0x2c, 0x3b, 0xed, 0x9d, 0x3e, 0xbf, + /*2920:*/ 0x4a, 0x8e, 0x7f, 0x54, 0xaa, 0x5c, 0x08, 0x84, 0x86, 0xf3, 0xc3, 0x04, 0x86, 0x2a, 0xab, 0xaf, + /*2930:*/ 0xcc, 0xac, 0xd8, 0x59, 0x7d, 0xa1, 0xd3, 0x70, 0x4f, 0xb1, 0x1b, 0x05, 0xbb, 0x61, 0x85, 0xd7, + /*2940:*/ 0x3b, 0xaf, 0x3c, 0x80, 0x2a, 0xae, 0x1b, 0xfe, 0x24, 0xb6, 0x1d, 0x23, 0x3d, 0xae, 0x39, 0x5a, + /*2950:*/ 0xe5, 0xc4, 0x23, 0x39, 0x4f, 0x4c, 0x7e, 0x83, 0x4e, 0x8a, 0x8a, 0x89, 0x5f, 0x9e, 0x28, 0x1b, + /*2960:*/ 0xd8, 0xdf, 0xb8, 0xf7, 0x0e, 0x9d, 0x83, 0x23, 0x33, 0x77, 0x09, 0x96, 0x4b, 0x3c, 0xd3, 0x34, + /*2970:*/ 0x32, 0x75, 0x8b, 0x57, 0xd0, 0x75, 0xa1, 0xbe, 0xbf, 0xaa, 0x47, 0xfd, 0x34, 0xe1, 0x8d, 0xb2, + /*2980:*/ 0x15, 0x23, 0xdb, 0x9e, 0x68, 0x87, 0x98, 0xf4, 0x50, 0xc2, 0x43, 0xaf, 0x3a, 0x76, 0xcb, 0xb8, + /*2990:*/ 0x3f, 0x8f, 0x5c, 0x0d, 0x82, 0x4d, 0x86, 0xfe, 0x53, 0x51, 0xea, 0xba, 0xf7, 0x47, 0x9f, 0xbd, + /*29a0:*/ 0xb9, 0xf3, 0xe7, 0x5c, 0x21, 0x05, 0x9f, 0xa0, 0x51, 0x53, 0xec, 0xda, 0xce, 0x5d, 0xd7, 0x54, + /*29b0:*/ 0xbb, 0x95, 0xb8, 0xf0, 0x81, 0xf5, 0x80, 0x72, 0x6c, 0x11, 0xf6, 0x50, 0x7e, 0xb6, 0x7b, 0x17, + /*29c0:*/ 0xd4, 0xd9, 0xca, 0x9f, 0x2a, 0x42, 0xef, 0x81, 0x72, 0x68, 0x21, 0x4a, 0x32, 0x41, 0xa8, 0x2b, + /*29d0:*/ 0x6b, 0xf7, 0xc2, 0x9d, 0xdc, 0x14, 0x0e, 0xfa, 0x35, 0x95, 0x7d, 0x9c, 0xb5, 0x2c, 0x52, 0xac, + /*29e0:*/ 0xf3, 0x4a, 0x82, 0x9a, 0x6b, 0xa6, 0x5a, 0x53, 0xbe, 0x75, 0x7e, 0xd7, 0x62, 0x28, 0xe1, 0x42, + /*29f0:*/ 0x1b, 0x44, 0x8c, 0xb3, 0xf7, 0x59, 0x60, 0xb4, 0x6d, 0x87, 0x89, 0xf3, 0x5b, 0xe9, 0x02, 0xee, + /*2a00:*/ 0x38, 0xdb, 0xcb, 0x3f, 0x5a, 0x99, 0x68, 0x43, 0x13, 0x62, 0x6b, 0x05, 0xd7, 0xc0, 0x81, 0x10, + /*2a10:*/ 0xbf, 0x56, 0x4e, 0x2a, 0x21, 0xe2, 0x17, 0x64, 0xfa, 0x2c, 0xc1, 0xee, 0xa0, 0xee, 0x91, 0xcb, + /*2a20:*/ 0x12, 0xaa, 0x14, 0x08, 0xc1, 0x29, 0x23, 0xb4, 0xc6, 0xaf, 0xff, 0xf8, 0x4d, 0x05, 0x6c, 0xe8, + /*2a30:*/ 0x20, 0x11, 0xdf, 0xc4, 0x0f, 0x2c, 0x49, 0xc9, 0xd3, 0xf2, 0x7d, 0x37, 0x9c, 0xc0, 0xc1, 0x99, + /*2a40:*/ 0xf5, 0xa1, 0x91, 0x10, 0x45, 0x6a, 0xf4, 0x61, 0x3e, 0x0f, 0x08, 0x4f, 0x84, 0xe9, 0x22, 0x0d, + /*2a50:*/ 0x1e, 0x78, 0x44, 0xd8, 0x31, 0x49, 0x6a, 0x31, 0x2a, 0x43, 0x5c, 0x64, 0x66, 0x43, 0x10, 0x9d, + /*2a60:*/ 0xa2, 0x74, 0x84, 0x28, 0xbf, 0x78, 0x5a, 0xfd, 0xbe, 0x2d, 0x01, 0xeb, 0x55, 0xa9, 0x41, 0x94, + /*2a70:*/ 0xd1, 0x7b, 0x72, 0x62, 0x82, 0x92, 0x64, 0xef, 0x05, 0xe9, 0xd0, 0x35, 0x3d, 0x46, 0x4d, 0xb4, + /*2a80:*/ 0x9f, 0x1e, 0x09, 0x38, 0x8c, 0x37, 0x70, 0x9e, 0xfb, 0x04, 0xa0, 0xd1, 0x49, 0x92, 0x85, 0x74, + /*2a90:*/ 0x23, 0x19, 0x41, 0xc3, 0x56, 0xf0, 0x89, 0xdf, 0x00, 0x83, 0x4b, 0xcb, 0xf1, 0x66, 0x9b, 0x8d, + /*2aa0:*/ 0x61, 0xf0, 0x6d, 0xee, 0x6b, 0x34, 0xc3, 0x88, 0x7e, 0xbf, 0x62, 0x3f, 0xe7, 0x4d, 0x85, 0x70, + /*2ab0:*/ 0xba, 0x7c, 0xe4, 0x78, 0x8f, 0xa1, 0x01, 0x58, 0x68, 0x67, 0x05, 0x36, 0x17, 0x0c, 0x4f, 0xe3, + /*2ac0:*/ 0xd4, 0x85, 0x39, 0x93, 0x8f, 0xf6, 0xd6, 0x93, 0x16, 0xd9, 0x19, 0x7c, 0xa6, 0x94, 0x76, 0xad, + /*2ad0:*/ 0xf4, 0xec, 0x5b, 0x63, 0x3d, 0x3e, 0x65, 0x29, 0x39, 0x6c, 0xa7, 0xe0, 0xbf, 0xe5, 0x64, 0x17, + /*2ae0:*/ 0xa9, 0xcb, 0xb9, 0x96, 0x58, 0x85, 0xdb, 0x55, 0x33, 0x31, 0x70, 0xac, 0x89, 0x01, 0x54, 0x83, + /*2af0:*/ 0x8d, 0x52, 0xa6, 0x6d, 0x71, 0x5f, 0x7b, 0xb6, 0x43, 0x8b, 0x44, 0x4e, 0xe4, 0x38, 0x67, 0x32, + /*2b00:*/ 0x4b, 0x5b, 0xea, 0xfd, 0xe5, 0x4c, 0x44, 0x15, 0x80, 0xde, 0x1c, 0x5d, 0x8c, 0xa5, 0xa1, 0x03, + /*2b10:*/ 0x56, 0x81, 0x78, 0x9b, 0xcc, 0x2f, 0xbb, 0x98, 0x55, 0xc8, 0x2b, 0x2c, 0x3d, 0x5a, 0x9c, 0x01, + /*2b20:*/ 0x73, 0x9f, 0x25, 0x24, 0x2a, 0xf9, 0xf0, 0x69, 0x59, 0x11, 0x7f, 0x0e, 0xa9, 0xfc, 0x14, 0x2d, + /*2b30:*/ 0x75, 0xa1, 0x24, 0xa0, 0x02, 0x29, 0x81, 0x04, 0x79, 0xfe, 0x7e, 0x99, 0x45, 0x01, 0xc0, 0xd4, + /*2b40:*/ 0x38, 0x9c, 0x9c, 0x24, 0xe8, 0x02, 0x26, 0xae, 0x10, 0x3d, 0x37, 0x33, 0xe3, 0x74, 0xd4, 0xfc, + /*2b50:*/ 0xe3, 0x82, 0x8e, 0xa2, 0x1c, 0x22, 0x8d, 0xd7, 0x94, 0xb3, 0xb3, 0x3c, 0xfc, 0xeb, 0xa9, 0x9c, + /*2b60:*/ 0xc6, 0x1c, 0x9e, 0x39, 0xaf, 0xb9, 0xfb, 0x65, 0x9a, 0xc7, 0xa3, 0xaa, 0x65, 0x23, 0x14, 0xb3, + /*2b70:*/ 0x30, 0x9f, 0x26, 0x3d, 0x44, 0x94, 0xe8, 0x44, 0xe1, 0xa8, 0x48, 0xb2, 0x6a, 0x1d, 0x2c, 0x49, + /*2b80:*/ 0xff, 0x90, 0x82, 0x9b, 0x21, 0xa9, 0xee, 0x51, 0x32, 0xfc, 0xa3, 0x77, 0x87, 0xf5, 0x1d, 0xc5, + /*2b90:*/ 0xd3, 0xb3, 0x1c, 0x25, 0x36, 0xa7, 0x23, 0xaf, 0xbf, 0x16, 0x25, 0x73, 0x91, 0x02, 0x04, 0xf7, + /*2ba0:*/ 0x4d, 0xe0, 0xa1, 0x12, 0x68, 0xa8, 0x89, 0xbe, 0x16, 0xed, 0x84, 0x18, 0x68, 0x17, 0x7b, 0x27, + /*2bb0:*/ 0x73, 0xc2, 0x07, 0xcf, 0x89, 0xdd, 0x18, 0x3c, 0x0f, 0x0c, 0x94, 0x2e, 0x9c, 0x44, 0xba, 0xf5, + /*2bc0:*/ 0x4f, 0x3b, 0xd4, 0xb7, 0x3a, 0x61, 0xd3, 0x4c, 0x1a, 0x09, 0x3c, 0x37, 0x29, 0x49, 0x8a, 0x38, + /*2bd0:*/ 0x91, 0xda, 0xb9, 0x64, 0x3c, 0xdd, 0xfe, 0x2a, 0x84, 0xb3, 0x56, 0x8c, 0xdb, 0x27, 0x73, 0x96, + /*2be0:*/ 0x5b, 0xfa, 0x89, 0x4d, 0xda, 0xd8, 0x0e, 0x72, 0x44, 0x6c, 0x66, 0x4f, 0x1a, 0x18, 0xa3, 0xf3, + /*2bf0:*/ 0xdc, 0xc0, 0x55, 0xa5, 0x25, 0x61, 0xd6, 0xf7, 0x09, 0xe1, 0xb6, 0x43, 0x4e, 0x1c, 0x6c, 0xd4, + /*2c00:*/ 0x49, 0xfe, 0x6c, 0xd1, 0xda, 0x1d, 0x53, 0xf7, 0x4e, 0x4d, 0xb2, 0x43, 0x0d, 0x98, 0x2e, 0x29, + /*2c10:*/ 0x9f, 0xd5, 0xfc, 0x21, 0x31, 0xd8, 0x74, 0x1a, 0x3b, 0xf7, 0x50, 0x06, 0x57, 0x6c, 0xbe, 0x5e, + /*2c20:*/ 0x5a, 0x29, 0xef, 0xac, 0xde, 0xf2, 0xe3, 0xad, 0x69, 0x6f, 0x67, 0x78, 0xce, 0x9f, 0xc4, 0x42, + /*2c30:*/ 0xb0, 0xac, 0xeb, 0x30, 0x7f, 0x23, 0x93, 0x86, 0xe7, 0x7d, 0x35, 0x32, 0xe3, 0x6b, 0x0e, 0x8b, + /*2c40:*/ 0x58, 0x83, 0x50, 0xe3, 0x5f, 0x12, 0xd4, 0xa7, 0xf2, 0x1b, 0xfb, 0xb1, 0xf9, 0x7e, 0x1e, 0x05, + /*2c50:*/ 0x7f, 0xec, 0x88, 0x2e, 0xd3, 0xda, 0x49, 0x3f, 0x3a, 0xc9, 0xb7, 0x3f, 0x44, 0xc5, 0xb6, 0x01, + /*2c60:*/ 0xb0, 0x6f, 0xa1, 0x3c, 0x9e, 0x44, 0x02, 0xf1, 0x11, 0x92, 0xf1, 0xd1, 0x7d, 0x2a, 0xa7, 0xc2, + /*2c70:*/ 0x7f, 0x5b, 0xc3, 0x0e, 0x03, 0xe1, 0x86, 0xf4, 0x63, 0x19, 0x15, 0xad, 0x1b, 0x0d, 0x9b, 0x04, + /*2c80:*/ 0x55, 0x49, 0xcb, 0x89, 0x85, 0x98, 0x6a, 0xd0, 0x18, 0x4d, 0xa2, 0x3e, 0x8c, 0x8b, 0x6c, 0x5b, + /*2c90:*/ 0xcf, 0xd1, 0xcb, 0xf3, 0x1a, 0x7b, 0x7b, 0x97, 0xe1, 0xa9, 0xd3, 0xcd, 0xc1, 0xbd, 0x25, 0x99, + /*2ca0:*/ 0x51, 0xde, 0x67, 0x08, 0x13, 0xa2, 0x91, 0x52, 0x4e, 0xf3, 0xca, 0xe7, 0xf3, 0xdc, 0x94, 0x1e, + /*2cb0:*/ 0x00, 0x60, 0x69, 0xfe, 0x98, 0xe9, 0x06, 0xc4, 0xf9, 0x9f, 0xdd, 0x2b, 0x25, 0x11, 0x41, 0x4f, + /*2cc0:*/ 0x7a, 0x75, 0x62, 0x4e, 0xbe, 0x00, 0x7b, 0xee, 0x38, 0x57, 0xd3, 0x5a, 0xf7, 0xc2, 0x33, 0x37, + /*2cd0:*/ 0x59, 0xe3, 0xd5, 0x20, 0x4e, 0xb1, 0x8d, 0xcf, 0x43, 0x03, 0xf3, 0x65, 0xca, 0xb6, 0xd1, 0x52, + /*2ce0:*/ 0x36, 0x8e, 0xdd, 0xb0, 0x30, 0x6c, 0xcf, 0xec, 0xe1, 0x04, 0xc1, 0x5b, 0x40, 0x7b, 0x4d, 0x02, + /*2cf0:*/ 0x91, 0x46, 0x3c, 0x90, 0x87, 0x60, 0xe4, 0x1b, 0xe0, 0xe1, 0x2c, 0xeb, 0x16, 0x6f, 0x6c, 0x72, + /*2d00:*/ 0xda, 0x71, 0x1f, 0x55, 0x3a, 0xe7, 0x52, 0x15, 0xff, 0x09, 0x4a, 0x84, 0x0c, 0xc5, 0x92, 0x69, + /*2d10:*/ 0x94, 0x5c, 0xb2, 0x15, 0x7f, 0x00, 0xe3, 0xf1, 0x43, 0x8b, 0x06, 0xa3, 0x51, 0xdf, 0xd1, 0x3c, + /*2d20:*/ 0x14, 0xe0, 0xe4, 0x18, 0xae, 0xe2, 0x56, 0x00, 0x6d, 0x04, 0xa0, 0xef, 0x21, 0xfe, 0x0e, 0xd6, + /*2d30:*/ 0x19, 0x78, 0x19, 0x98, 0xa4, 0x86, 0x6c, 0xc2, 0x39, 0x3b, 0x61, 0x33, 0xf9, 0xd9, 0xed, 0xcb, + /*2d40:*/ 0x8b, 0x14, 0x4e, 0xc2, 0x0f, 0x5d, 0xf0, 0x19, 0x0b, 0x21, 0x25, 0x61, 0x79, 0x93, 0x3d, 0x0d, + /*2d50:*/ 0xed, 0x6f, 0x1a, 0xa0, 0x19, 0xab, 0xb6, 0x56, 0xce, 0xa5, 0x51, 0xa4, 0x09, 0xf6, 0xc5, 0x95, + /*2d60:*/ 0x63, 0x85, 0x5f, 0x24, 0xd7, 0xd4, 0xba, 0x07, 0xa3, 0x62, 0x55, 0xe7, 0x3f, 0x7c, 0x3a, 0x8b, + /*2d70:*/ 0xc3, 0xc8, 0xe9, 0x94, 0x59, 0x59, 0xc9, 0x87, 0xc9, 0xc1, 0xdb, 0xb9, 0xc0, 0x13, 0xa1, 0x1e, + /*2d80:*/ 0xd4, 0x49, 0x32, 0xa3, 0x31, 0x42, 0xb4, 0x32, 0xed, 0x0a, 0xfd, 0xf4, 0xf8, 0x76, 0x01, 0x28, + /*2d90:*/ 0xaf, 0x1e, 0x7b, 0xd6, 0x7e, 0xf7, 0x05, 0x4c, 0x15, 0xee, 0x50, 0x74, 0x15, 0xbf, 0x19, 0xc7, + /*2da0:*/ 0x5e, 0xa6, 0x8d, 0xb9, 0x0d, 0xfc, 0x4a, 0xf1, 0x55, 0x4f, 0x2a, 0xea, 0x1c, 0x91, 0xdf, 0x47, + /*2db0:*/ 0xf2, 0x3a, 0xab, 0x09, 0x3a, 0x96, 0x92, 0x4b, 0xdd, 0xf7, 0x13, 0x82, 0xa1, 0x77, 0x44, 0x96, + /*2dc0:*/ 0xe2, 0x7b, 0x9d, 0xcb, 0xdd, 0x3b, 0x10, 0xf6, 0x45, 0x5b, 0xd0, 0x9e, 0xfb, 0x50, 0x10, 0x86, + /*2dd0:*/ 0x31, 0x05, 0x5c, 0x8e, 0x77, 0xb2, 0x49, 0x86, 0xe1, 0x35, 0x45, 0x65, 0x28, 0x5b, 0x05, 0xce, + /*2de0:*/ 0x4b, 0xef, 0xf2, 0x62, 0xde, 0xa3, 0x89, 0xf9, 0x8f, 0x68, 0x2a, 0x2c, 0xcd, 0x06, 0xd0, 0xb5, + /*2df0:*/ 0xb4, 0x4d, 0xa2, 0x38, 0xd1, 0x3c, 0x01, 0x13, 0x3c, 0x98, 0x8b, 0x72, 0x80, 0x4a, 0x22, 0x73, + /*2e00:*/ 0x45, 0x15, 0x5a, 0xaf, 0x27, 0x76, 0x7e, 0xd0, 0x5e, 0xad, 0x37, 0xdb, 0x59, 0xac, 0xd1, 0x11, + /*2e10:*/ 0x9e, 0xca, 0x10, 0x59, 0x29, 0x7d, 0x2f, 0xc4, 0xcb, 0x83, 0xdb, 0x96, 0x54, 0x7d, 0xa7, 0x4c, + /*2e20:*/ 0x61, 0x0b, 0x0e, 0xa1, 0xcd, 0xa5, 0x5d, 0x9c, 0x5d, 0xc7, 0x5a, 0x5d, 0x10, 0xfc, 0x43, 0x7b, + /*2e30:*/ 0x91, 0xd0, 0x2a, 0xdc, 0x9f, 0x4b, 0xeb, 0xaa, 0x53, 0xf3, 0x5a, 0x54, 0x16, 0x78, 0xd2, 0x67, + /*2e40:*/ 0x28, 0x1a, 0x39, 0x2e, 0x9a, 0x5b, 0xae, 0x7e, 0x2f, 0xc2, 0xf6, 0xa7, 0xaf, 0x8a, 0x84, 0xdf, + /*2e50:*/ 0x6b, 0xdb, 0xbc, 0xdf, 0xd7, 0x2e, 0xd5, 0x27, 0xbb, 0x31, 0x40, 0xb9, 0x54, 0xb1, 0xf9, 0x08, + /*2e60:*/ 0xdb, 0x69, 0xff, 0x2e, 0x40, 0xa9, 0x98, 0x36, 0x02, 0x24, 0x52, 0x27, 0x48, 0x5b, 0x16, 0x56, + /*2e70:*/ 0x8a, 0x2c, 0x7d, 0x15, 0xd1, 0xd8, 0xb2, 0x74, 0xbf, 0x2e, 0x65, 0x61, 0xe8, 0x1c, 0x53, 0x99, + /*2e80:*/ 0x54, 0x0a, 0xc0, 0x53, 0xc4, 0xdd, 0x62, 0x38, 0x49, 0x1a, 0xb7, 0xf1, 0xc0, 0xee, 0xf7, 0x58, + /*2e90:*/ 0xa9, 0xcd, 0xd2, 0x49, 0xcc, 0x6d, 0xee, 0x43, 0xd0, 0x0c, 0xd4, 0x4b, 0x15, 0x3d, 0x00, 0x7f, + /*2ea0:*/ 0x08, 0x29, 0x25, 0x1e, 0x13, 0xc4, 0xfa, 0x84, 0x9a, 0xbd, 0x22, 0xd9, 0xf8, 0x0f, 0xa9, 0xb6, + /*2eb0:*/ 0x13, 0x6f, 0x03, 0xd1, 0x91, 0xf7, 0x88, 0x36, 0xbd, 0xb3, 0xb1, 0x67, 0xca, 0x39, 0x4e, 0x1d, + /*2ec0:*/ 0xc7, 0xbc, 0xdf, 0xbb, 0x25, 0x1c, 0xcc, 0x59, 0xd1, 0x69, 0x9e, 0x56, 0xe3, 0x93, 0x63, 0xd5, + /*2ed0:*/ 0x44, 0xdd, 0x6b, 0x69, 0x1e, 0x51, 0xd0, 0x22, 0x69, 0x3f, 0x04, 0x43, 0xa5, 0xd6, 0x8f, 0x2f, + /*2ee0:*/ 0x6d, 0xe8, 0xd6, 0x0e, 0x3d, 0x58, 0x2a, 0x83, 0xd2, 0xee, 0x0e, 0x9d, 0x2c, 0xa8, 0xb5, 0xfa, + /*2ef0:*/ 0x65, 0x19, 0x04, 0x2d, 0x19, 0x8c, 0x07, 0xf5, 0x2f, 0x01, 0xf8, 0xc5, 0x38, 0x24, 0xd4, 0x6e, + /*2f00:*/ 0xfd, 0xd6, 0xad, 0xf6, 0xac, 0xcd, 0x92, 0x27, 0x93, 0x0b, 0xf9, 0x60, 0x22, 0x2b, 0xa2, 0xae, + /*2f10:*/ 0x86, 0x79, 0xd7, 0xd6, 0xb6, 0xad, 0x64, 0x59, 0x69, 0xe0, 0x83, 0xf3, 0xf9, 0x49, 0x19, 0x08, + /*2f20:*/ 0x9a, 0xa3, 0xfd, 0xf5, 0x92, 0x2d, 0x35, 0x06, 0x44, 0x32, 0xe7, 0xdf, 0x5e, 0x83, 0x93, 0x42, + /*2f30:*/ 0xe4, 0xf8, 0x24, 0xad, 0x65, 0x6d, 0x37, 0x58, 0x87, 0x80, 0x2b, 0xac, 0xc7, 0x27, 0xce, 0x2d, + /*2f40:*/ 0x07, 0x10, 0x7e, 0x1d, 0xa4, 0x80, 0x2c, 0x16, 0xf0, 0x3b, 0x66, 0x3d, 0x74, 0x15, 0x25, 0xe0, + /*2f50:*/ 0x46, 0xf3, 0x08, 0xbd, 0x0b, 0x6e, 0x44, 0x5a, 0xc5, 0x0e, 0x53, 0x01, 0x4b, 0x80, 0x16, 0x91, + /*2f60:*/ 0x07, 0x94, 0x8f, 0x66, 0xb9, 0x38, 0xa1, 0x44, 0xed, 0xd4, 0x44, 0x58, 0x36, 0xd2, 0x12, 0xf3, + /*2f70:*/ 0xb0, 0x41, 0x7a, 0xfa, 0xaa, 0xca, 0x35, 0xf2, 0xd6, 0x4e, 0xf7, 0x8b, 0xce, 0x9b, 0x7d, 0x67, + /*2f80:*/ 0xdc, 0xbb, 0x46, 0xc8, 0x19, 0xbf, 0x0d, 0xd0, 0x7a, 0xee, 0x10, 0xb7, 0x9c, 0x85, 0x94, 0xb4, + /*2f90:*/ 0xfd, 0x49, 0x0d, 0x77, 0x9e, 0x95, 0x0b, 0xe2, 0xd5, 0xef, 0x28, 0x08, 0xee, 0xbf, 0xf9, 0x4b, + /*2fa0:*/ 0x39, 0x74, 0x02, 0x96, 0x1a, 0x8f, 0x34, 0x8b, 0x3a, 0xd9, 0x3f, 0x63, 0xa4, 0xfd, 0x63, 0xbd, + /*2fb0:*/ 0xc6, 0xfd, 0x8f, 0x02, 0x97, 0x44, 0xbc, 0xb1, 0xe5, 0x95, 0xd0, 0x5b, 0xa8, 0x3c, 0x11, 0xd9, + /*2fc0:*/ 0x93, 0xbf, 0x66, 0x82, 0xdc, 0xdd, 0xd5, 0x99, 0xee, 0x92, 0x09, 0x8e, 0x06, 0x0e, 0x7e, 0x67, + /*2fd0:*/ 0x00, 0xb5, 0x93, 0xb3, 0x39, 0x00, 0xe2, 0xe2, 0xb7, 0xe3, 0xe0, 0x1f, 0x3e, 0xd7, 0x8a, 0xc7, + /*2fe0:*/ 0x7e, 0xa6, 0xce, 0x8b, 0x08, 0xaa, 0x9a, 0xde, 0x27, 0xd2, 0xaf, 0xca, 0x72, 0x41, 0xb0, 0x4f, + /*2ff0:*/ 0xea, 0xf5, 0x7b, 0x85, 0x46, 0x03, 0xa6, 0x1f, 0x50, 0x7f, 0x74, 0xba, 0x01, 0xae, 0x88, 0x1e, + /*3000:*/ 0x0a, 0x50, 0x71, 0xb9, 0xcc, 0x78, 0x5a, 0xdd, 0x4c, 0xad, 0x30, 0xbd, 0xe8, 0x34, 0x8a, 0xe1, + /*3010:*/ 0xaf, 0xa9, 0xeb, 0xb9, 0x22, 0x69, 0xd7, 0x30, 0x45, 0xa6, 0x06, 0xf3, 0xd6, 0x4e, 0xac, 0x19, + /*3020:*/ 0xcf, 0x12, 0x66, 0x1d, 0xd2, 0x11, 0xe1, 0xcf, 0x3c, 0x12, 0x21, 0xcd, 0x74, 0xd2, 0xba, 0x62, + /*3030:*/ 0xcc, 0x6c, 0xb9, 0x67, 0xfd, 0xc4, 0x5a, 0x94, 0xc5, 0x6f, 0x1e, 0xb7, 0x49, 0x8c, 0x24, 0x96, + /*3040:*/ 0xf1, 0x8c, 0x30, 0xb9, 0xfc, 0x2f, 0xdf, 0x9d, 0xb7, 0x6c, 0x81, 0x63, 0xf5, 0x0f, 0x1c, 0xfd, + /*3050:*/ 0x15, 0xbe, 0x0b, 0x36, 0xff, 0xa2, 0xc9, 0x07, 0x40, 0x85, 0x70, 0xe4, 0x4f, 0xb0, 0xa9, 0x11, + /*3060:*/ 0x8b, 0x8d, 0x6f, 0x74, 0x17, 0x7d, 0x4c, 0xf9, 0xc6, 0x23, 0x81, 0x56, 0x21, 0xcb, 0x99, 0x1c, + /*3070:*/ 0x31, 0x03, 0xa1, 0x05, 0x5a, 0x29, 0x9a, 0xf1, 0x2e, 0xf5, 0x07, 0xb1, 0x8b, 0x6b, 0xea, 0xb6, + /*3080:*/ 0xd0, 0xe8, 0x78, 0x93, 0xb3, 0x2d, 0xcf, 0xa6, 0xb8, 0x7e, 0xfe, 0x7c, 0x91, 0x25, 0xa6, 0xf1, + /*3090:*/ 0xc8, 0xaa, 0xff, 0xcd, 0x4a, 0xf3, 0x22, 0x62, 0x98, 0xbb, 0x95, 0xa7, 0x9e, 0xff, 0x23, 0x37, + /*30a0:*/ 0x88, 0x79, 0xbe, 0x02, 0x8e, 0x85, 0xd3, 0x8e, 0x38, 0x50, 0xab, 0x9a, 0x47, 0xa8, 0xa7, 0x1a, + /*30b0:*/ 0x22, 0x06, 0xd2, 0xcb, 0xa9, 0x49, 0xd0, 0xfc, 0xa2, 0x3f, 0xb5, 0x8c, 0x80, 0xa4, 0x65, 0xf0, + /*30c0:*/ 0x7a, 0xe0, 0xf5, 0x05, 0xf8, 0x1f, 0x75, 0x8b, 0x03, 0xa8, 0xd7, 0x45, 0xd1, 0x17, 0xf4, 0x85, + /*30d0:*/ 0x94, 0x85, 0x5a, 0xb3, 0x26, 0x52, 0x4d, 0x24, 0x45, 0x93, 0xd2, 0x19, 0x04, 0x3d, 0xb9, 0x4e, + /*30e0:*/ 0xe7, 0xac, 0x7c, 0xd3, 0x38, 0x2e, 0x13, 0xce, 0x72, 0xf7, 0x26, 0x49, 0x04, 0xd0, 0xe4, 0x9b, + /*30f0:*/ 0x0f, 0x4c, 0x91, 0x27, 0x37, 0x89, 0x20, 0x54, 0x8b, 0xf9, 0xbc, 0x46, 0xab, 0x97, 0x5d, 0xf3, + /*3100:*/ 0x8c, 0xf4, 0xdf, 0x79, 0x3d, 0x13, 0x84, 0xb1, 0x12, 0x33, 0x2d, 0x83, 0xc0, 0xb0, 0xc8, 0x77, + /*3110:*/ 0xb7, 0x2e, 0x24, 0x9d, 0xdd, 0x10, 0x31, 0x6f, 0x1b, 0xef, 0x9c, 0x20, 0xcd, 0x8d, 0x90, 0x07, + /*3120:*/ 0xbf, 0x1c, 0x6f, 0x46, 0xb6, 0x6e, 0xdd, 0x90, 0x8a, 0xf8, 0xf7, 0x14, 0xc0, 0xbe, 0xd4, 0x9b, + /*3130:*/ 0x6f, 0x2a, 0xf5, 0x37, 0xf5, 0xc9, 0x5a, 0x80, 0x5d, 0xef, 0x76, 0x99, 0x7c, 0xfd, 0xd7, 0x04, + /*3140:*/ 0xa5, 0x7b, 0xe5, 0x1e, 0x45, 0x20, 0x82, 0xaa, 0xf6, 0x4f, 0x6a, 0x34, 0xfd, 0xbe, 0x61, 0xc2, + /*3150:*/ 0x2d, 0xbc, 0x5f, 0xcc, 0x56, 0xc4, 0x4d, 0x62, 0x08, 0xcb, 0xf2, 0x2b, 0x1b, 0x79, 0xd6, 0xe3, + /*3160:*/ 0xb6, 0xc2, 0xb0, 0x98, 0xaa, 0xde, 0xb9, 0xf8, 0xf8, 0x26, 0x5e, 0xf1, 0x74, 0x61, 0x5e, 0x10, + /*3170:*/ 0xa6, 0xa7, 0x45, 0x50, 0x2b, 0x94, 0x6d, 0x0d, 0x03, 0x66, 0x81, 0xed, 0x6c, 0x30, 0x48, 0x96, + /*3180:*/ 0x56, 0xda, 0x29, 0x3d, 0x9a, 0xb1, 0xa3, 0x64, 0x1f, 0xcd, 0xc9, 0x63, 0x42, 0x01, 0x08, 0x34, + /*3190:*/ 0x1d, 0x0e, 0x92, 0xca, 0xec, 0x3f, 0x9f, 0x87, 0xda, 0x68, 0xbb, 0xf1, 0x7c, 0x47, 0xc5, 0x26, + /*31a0:*/ 0x72, 0xee, 0x46, 0x90, 0x5c, 0xa7, 0x49, 0xd8, 0xd8, 0xba, 0xd6, 0xc9, 0x52, 0x9f, 0x48, 0x38, + /*31b0:*/ 0x16, 0xd9, 0xe2, 0x99, 0x88, 0xab, 0x1f, 0xca, 0xd9, 0x63, 0xd4, 0xf2, 0x48, 0x07, 0x92, 0x45, + /*31c0:*/ 0xc9, 0xe7, 0x97, 0xdf, 0x7b, 0xf7, 0x4b, 0x69, 0x5b, 0x19, 0x3b, 0x3f, 0x79, 0xc2, 0x23, 0x90, + /*31d0:*/ 0xff, 0x84, 0x5a, 0x8a, 0xe8, 0xdf, 0xcb, 0xaf, 0x3d, 0xa0, 0x15, 0x81, 0x43, 0xc6, 0xb5, 0xd9, + /*31e0:*/ 0x68, 0xc7, 0x83, 0x0b, 0x8a, 0x77, 0x16, 0xb6, 0x75, 0x23, 0x98, 0x9d, 0x0a, 0x08, 0x47, 0x4f, + /*31f0:*/ 0x0b, 0x84, 0x21, 0xdf, 0x61, 0xd5, 0x75, 0x6a, 0x2e, 0x3d, 0x82, 0x58, 0xc6, 0xa8, 0x21, 0xa1, + /*3200:*/ 0xa6, 0x39, 0x33, 0x68, 0x31, 0x70, 0x73, 0x84, 0x15, 0x0e, 0xb5, 0x4f, 0xc4, 0x80, 0x9f, 0x10, + /*3210:*/ 0x34, 0xf5, 0x6d, 0xa6, 0x49, 0x8f, 0x85, 0x36, 0xb4, 0x4c, 0x2f, 0x1e, 0x60, 0xa6, 0xfc, 0xd6, + /*3220:*/ 0xb2, 0x48, 0x2c, 0x7b, 0xdc, 0x02, 0xc7, 0x21, 0x24, 0x47, 0x20, 0x45, 0xd6, 0xbb, 0x29, 0xf6, + /*3230:*/ 0x0d, 0x25, 0x12, 0x58, 0xfe, 0xec, 0x88, 0x29, 0x9d, 0x83, 0xe5, 0x24, 0xac, 0xa3, 0x9b, 0x1f, + /*3240:*/ 0x35, 0x58, 0xe2, 0x3a, 0xf0, 0x85, 0xe1, 0x37, 0xd4, 0x91, 0xe2, 0xbf, 0xd7, 0xf4, 0x03, 0xf2, + /*3250:*/ 0xe4, 0x9d, 0x09, 0x27, 0x95, 0x3f, 0x0e, 0x3d, 0xfd, 0xf7, 0x41, 0xee, 0xb1, 0x76, 0xe1, 0xaf, + /*3260:*/ 0xed, 0x68, 0x37, 0xd5, 0xea, 0xe8, 0x6e, 0xc6, 0x11, 0xe6, 0xd7, 0xb0, 0x59, 0x19, 0x4a, 0x83, + /*3270:*/ 0x3d, 0xec, 0x38, 0xc9, 0x5b, 0xed, 0xe8, 0xe3, 0x76, 0x03, 0xcd, 0x4a, 0x90, 0xa9, 0x21, 0xd5, + /*3280:*/ 0xf4, 0x89, 0xc2, 0x7a, 0xb7, 0xa6, 0x02, 0x40, 0x5c, 0xb7, 0xe7, 0xea, 0x3e, 0xb4, 0x3e, 0x42, + /*3290:*/ 0x81, 0x6e, 0x88, 0x87, 0x7c, 0xa1, 0x71, 0xd5, 0x08, 0x7f, 0x87, 0xa0, 0x34, 0x74, 0x4a, 0x73, + /*32a0:*/ 0x8b, 0xf6, 0xfe, 0x41, 0xc8, 0xd4, 0x1d, 0x3a, 0x1e, 0xae, 0xff, 0xf4, 0x7e, 0xfe, 0xdd, 0x44, + /*32b0:*/ 0x9a, 0x3e, 0x8f, 0x5e, 0xf1, 0xdd, 0xd2, 0x38, 0x61, 0x58, 0x1e, 0xf7, 0xcd, 0x30, 0x3d, 0x88, + /*32c0:*/ 0xc4, 0x14, 0x56, 0xb3, 0x1b, 0x68, 0x0a, 0x02, 0x58, 0x47, 0x42, 0xc6, 0xf0, 0x0c, 0x6a, 0xe9, + /*32d0:*/ 0xa4, 0x20, 0x32, 0x74, 0x5a, 0xf5, 0x54, 0xa4, 0x48, 0x61, 0x6a, 0xa8, 0x12, 0x6b, 0xd9, 0xa7, + /*32e0:*/ 0x0c, 0x6c, 0xcf, 0x74, 0x1c, 0x22, 0xe4, 0x7e, 0x94, 0xe6, 0xf6, 0x9f, 0x0f, 0x17, 0x2b, 0xb1, + /*32f0:*/ 0xf0, 0xb4, 0x3b, 0x6a, 0x98, 0xfd, 0x33, 0x56, 0x6b, 0x10, 0x3e, 0x75, 0xa8, 0x0e, 0x4a, 0x99, + /*3300:*/ 0x1c, 0xfb, 0xe4, 0x70, 0x94, 0x6f, 0xbd, 0xd9, 0x40, 0x68, 0x46, 0x1f, 0x42, 0xac, 0x6c, 0x2d, + /*3310:*/ 0x0d, 0x45, 0xb0, 0x63, 0x81, 0x15, 0xdc, 0x59, 0x54, 0x73, 0xd7, 0xcd, 0xf5, 0x39, 0x93, 0x0a, + /*3320:*/ 0x09, 0xc1, 0x6f, 0x26, 0xc2, 0x33, 0xdd, 0x31, 0x87, 0xab, 0xff, 0x93, 0x96, 0xa4, 0x27, 0xda, + /*3330:*/ 0xd3, 0x5e, 0x30, 0xb4, 0x04, 0x93, 0xd5, 0xdd, 0x83, 0x4b, 0x19, 0x36, 0xb4, 0xdd, 0xeb, 0x45, + /*3340:*/ 0x70, 0x7c, 0xe7, 0x0b, 0x53, 0xda, 0x85, 0x6f, 0x66, 0xcc, 0x88, 0x3d, 0xfe, 0x7f, 0x54, 0xe2, + /*3350:*/ 0x12, 0x18, 0xc8, 0xed, 0x0b, 0x49, 0xc3, 0x4e, 0x88, 0x24, 0xae, 0x50, 0x38, 0xed, 0x78, 0x69, + /*3360:*/ 0x0d, 0x2d, 0x31, 0x46, 0xce, 0x89, 0xcc, 0x3b, 0x34, 0x8e, 0x12, 0xf4, 0xa4, 0x84, 0x6b, 0xc1, + /*3370:*/ 0x2f, 0x69, 0x3a, 0x35, 0x67, 0xb7, 0x13, 0x9d, 0x14, 0x59, 0x2c, 0x73, 0xac, 0x97, 0x1c, 0xc9, + /*3380:*/ 0x23, 0xe0, 0xec, 0xf5, 0x84, 0xb6, 0x30, 0x8a, 0x7f, 0xe6, 0x9b, 0x0d, 0xad, 0xdc, 0xa4, 0x9e, + /*3390:*/ 0xe4, 0x9f, 0x92, 0xae, 0x05, 0xd7, 0xf3, 0x74, 0x54, 0x24, 0xf8, 0x9f, 0x09, 0xa4, 0xc9, 0x3c, + /*33a0:*/ 0x6d, 0xda, 0x01, 0xeb, 0x25, 0x06, 0x66, 0xdd, 0xc0, 0x2d, 0x73, 0xfd, 0x45, 0xd1, 0xe4, 0x34, + /*33b0:*/ 0x73, 0xb4, 0x62, 0x11, 0xaf, 0x82, 0x2d, 0xcb, 0xaa, 0xb7, 0x9c, 0x83, 0xc5, 0x57, 0x86, 0xc3, + /*33c0:*/ 0xdd, 0xa0, 0xf1, 0x6d, 0xf3, 0x5a, 0xbe, 0xa8, 0xb6, 0x9f, 0x66, 0x9c, 0x7b, 0x48, 0xf1, 0x71, + /*33d0:*/ 0x83, 0x94, 0x54, 0x8d, 0x85, 0xb5, 0x03, 0xd1, 0x88, 0xb9, 0xe6, 0xcb, 0x78, 0xab, 0xea, 0x24, + /*33e0:*/ 0x54, 0x7e, 0x3f, 0x66, 0xa0, 0x3e, 0x63, 0x9b, 0x8c, 0x57, 0x2c, 0xa9, 0x97, 0xba, 0xfd, 0x6e, + /*33f0:*/ 0x05, 0xbb, 0xda, 0x9f, 0x1c, 0x9d, 0x6d, 0xea, 0x04, 0x84, 0x8c, 0x07, 0x78, 0xa2, 0x80, 0x1e, + /*3400:*/ 0x1e, 0xe0, 0x0b, 0x8f, 0x89, 0xf3, 0x84, 0x23, 0x17, 0x71, 0xff, 0x15, 0x64, 0x49, 0x2e, 0x90, + /*3410:*/ 0x0e, 0x50, 0x20, 0x2f, 0xf1, 0x9b, 0xb9, 0xb3, 0xe6, 0xf0, 0xee, 0xbb, 0x5f, 0x6d, 0xa6, 0xa2, + /*3420:*/ 0x10, 0x8f, 0xaf, 0x2f, 0x4e, 0xe9, 0x27, 0xa0, 0x04, 0x48, 0xda, 0x9a, 0x03, 0x64, 0x33, 0x42, + /*3430:*/ 0x0e, 0x02, 0x2e, 0x1f, 0x0e, 0x87, 0x0c, 0xd7, 0xe7, 0x09, 0xac, 0x79, 0x42, 0x93, 0xd7, 0x4a, + /*3440:*/ 0xaa, 0x5f, 0x07, 0xed, 0xb1, 0xaf, 0x0c, 0x22, 0x63, 0x2a, 0x9c, 0x9d, 0x4b, 0x6c, 0xf6, 0x80, + /*3450:*/ 0x0a, 0x1e, 0x4a, 0x50, 0x07, 0x64, 0xc6, 0xcc, 0x3a, 0x2a, 0x64, 0x9e, 0xde, 0x5b, 0x2d, 0x6c, + /*3460:*/ 0xe3, 0x48, 0xb5, 0x11, 0x9d, 0x3c, 0xf0, 0x8f, 0x5c, 0x0d, 0xd7, 0x02, 0xf5, 0xce, 0xff, 0x71, + /*3470:*/ 0x06, 0xc4, 0x4b, 0x7d, 0x67, 0x7e, 0xef, 0xc4, 0x78, 0x60, 0xba, 0x58, 0x0f, 0xbc, 0x84, 0x7b, + /*3480:*/ 0xc5, 0xba, 0xde, 0x8b, 0xdc, 0x60, 0x78, 0xab, 0xf2, 0xde, 0xd4, 0xed, 0x00, 0x22, 0x6b, 0xa4, + /*3490:*/ 0x4a, 0x79, 0x43, 0x79, 0xba, 0x03, 0x84, 0x25, 0x0c, 0x41, 0x1d, 0x1f, 0x19, 0x23, 0x7c, 0xf7, + /*34a0:*/ 0x20, 0xa3, 0xfd, 0xa1, 0x4f, 0xff, 0xfe, 0x8c, 0x7e, 0xb9, 0x07, 0x7d, 0xbe, 0x79, 0x18, 0xa8, + /*34b0:*/ 0x24, 0x2a, 0x95, 0x01, 0xf3, 0x3f, 0xb1, 0xa6, 0xe4, 0xda, 0xcf, 0x68, 0x42, 0x08, 0x2c, 0x4d, + /*34c0:*/ 0x2a, 0xd7, 0xb3, 0x6f, 0x4a, 0xb4, 0x6b, 0xe9, 0x0b, 0xfb, 0x73, 0xb1, 0x21, 0x0a, 0x44, 0xab, + /*34d0:*/ 0x47, 0x02, 0xdb, 0xb5, 0x0b, 0x13, 0x6f, 0x0c, 0x78, 0x40, 0xbd, 0x73, 0x04, 0xf2, 0x7e, 0x54, + /*34e0:*/ 0x85, 0x35, 0x78, 0x52, 0x6d, 0xf4, 0x05, 0x70, 0x51, 0xa2, 0xb9, 0x6f, 0x34, 0x8c, 0x4b, 0x7b, + /*34f0:*/ 0xb8, 0x6c, 0x3b, 0xa5, 0xe7, 0x22, 0xc6, 0x46, 0xa8, 0x09, 0xc3, 0x6b, 0x19, 0x01, 0x50, 0xa5, + /*3500:*/ 0x58, 0xef, 0x4d, 0xfa, 0xee, 0x20, 0xbd, 0xcb, 0xd1, 0x56, 0xae, 0x7e, 0xc3, 0x6f, 0x61, 0x52, + /*3510:*/ 0xde, 0x9e, 0x59, 0xc4, 0x41, 0x52, 0x78, 0x39, 0x97, 0x30, 0x24, 0x9e, 0x92, 0xea, 0xbc, 0x69, + /*3520:*/ 0xf9, 0x8d, 0x1d, 0x1a, 0xce, 0x74, 0x52, 0x4f, 0x04, 0x5f, 0x0e, 0xd8, 0xb7, 0xb4, 0xf5, 0x5b, + /*3530:*/ 0xa9, 0x1c, 0xc0, 0x0d, 0xf3, 0xbc, 0x27, 0xde, 0x37, 0xe6, 0x26, 0x11, 0xd4, 0x9b, 0x25, 0x42, + /*3540:*/ 0xd7, 0xc1, 0xf6, 0xde, 0xb5, 0xae, 0x24, 0x59, 0x2a, 0x83, 0xb5, 0xa6, 0x8f, 0x03, 0xd3, 0xbf, + /*3550:*/ 0xcb, 0x58, 0x76, 0xe0, 0xf7, 0xdb, 0x63, 0xa4, 0x18, 0xbc, 0xfb, 0x0c, 0x76, 0x3e, 0x73, 0x71, + /*3560:*/ 0x4a, 0xdc, 0x5a, 0x0e, 0xf8, 0x59, 0x88, 0xc1, 0xc9, 0x55, 0x13, 0xc7, 0xab, 0x57, 0x85, 0x5b, + /*3570:*/ 0x46, 0x4d, 0x19, 0x14, 0x0c, 0xb0, 0x43, 0xd2, 0x92, 0xef, 0x6f, 0x8b, 0xd9, 0x06, 0xd3, 0x2f, + /*3580:*/ 0xaf, 0xf3, 0xa5, 0x09, 0x71, 0x96, 0x97, 0x5a, 0xfd, 0x03, 0x65, 0xad, 0x8e, 0x62, 0xce, 0x91, + /*3590:*/ 0x96, 0xd3, 0x91, 0x11, 0xb2, 0x85, 0xc7, 0xcb, 0x29, 0x79, 0x8d, 0x37, 0xd7, 0xec, 0x13, 0x43, + /*35a0:*/ 0x20, 0x08, 0x40, 0x8f, 0xa2, 0xee, 0xa5, 0x1f, 0xed, 0xa5, 0x78, 0x4b, 0x59, 0x50, 0x60, 0x09, + /*35b0:*/ 0x66, 0x0b, 0x0a, 0x5a, 0xc1, 0xd6, 0xe3, 0x96, 0xcd, 0xa2, 0x61, 0x26, 0x57, 0xa0, 0x51, 0x7e, + /*35c0:*/ 0x11, 0x21, 0xad, 0xce, 0xf5, 0x26, 0xdc, 0x8c, 0x3e, 0xd0, 0x61, 0xd8, 0x11, 0x2c, 0x7a, 0x68, + /*35d0:*/ 0xca, 0x95, 0x26, 0xde, 0x3c, 0xb4, 0xf1, 0x4b, 0x1e, 0xb8, 0x21, 0x83, 0x1e, 0xdb, 0xd9, 0x9d, + /*35e0:*/ 0x73, 0x60, 0xfa, 0x26, 0x2b, 0x41, 0xd1, 0x55, 0x16, 0x7b, 0x9f, 0xa8, 0xa4, 0x1f, 0x18, 0x5b, + /*35f0:*/ 0x6d, 0x22, 0xab, 0x73, 0x71, 0x7c, 0x04, 0xa8, 0xef, 0x3f, 0x1d, 0x2c, 0x9a, 0x98, 0x4e, 0xff, + /*3600:*/ 0xc7, 0xef, 0x7b, 0x63, 0x4d, 0x79, 0xe2, 0x33, 0x0a, 0xd8, 0x26, 0x30, 0xfc, 0xa3, 0x24, 0x5e, + /*3610:*/ 0x2f, 0xd7, 0xb3, 0x90, 0x1e, 0x45, 0x30, 0x41, 0x00, 0x59, 0x92, 0x62, 0x20, 0xb3, 0xff, 0x5d, + /*3620:*/ 0x47, 0x31, 0x6e, 0x87, 0xe5, 0x7e, 0x9d, 0x73, 0x8d, 0x3d, 0x74, 0x9c, 0x4b, 0xf7, 0xc8, 0x86, + /*3630:*/ 0xe4, 0xa7, 0xac, 0x4c, 0xf9, 0x51, 0x2f, 0x4d, 0xd2, 0x02, 0x9b, 0xcf, 0xb7, 0x68, 0x7f, 0x25, + /*3640:*/ 0xc7, 0x22, 0xfa, 0x75, 0xe5, 0xdd, 0x7e, 0xd3, 0x28, 0x07, 0x87, 0x78, 0x62, 0x20, 0x0e, 0xa1, + /*3650:*/ 0xab, 0x3e, 0xfd, 0xd0, 0x04, 0xe6, 0xd8, 0xf0, 0xa3, 0x1e, 0x05, 0xf5, 0x7e, 0x5e, 0xd8, 0xee, + /*3660:*/ 0x62, 0xc2, 0x71, 0xf7, 0x4a, 0x05, 0x84, 0x90, 0x15, 0x0a, 0x4a, 0x25, 0x32, 0x3c, 0x1c, 0xfe, + /*3670:*/ 0x14, 0xe2, 0x19, 0x3b, 0x97, 0xe4, 0x38, 0x8b, 0x7d, 0x30, 0x4b, 0x00, 0x62, 0x01, 0x68, 0x0f, + /*3680:*/ 0x01, 0xe3, 0xbb, 0x7d, 0x1a, 0x74, 0x0d, 0x09, 0x8e, 0x7a, 0xfe, 0x00, 0xc3, 0xb8, 0x23, 0xe7, + /*3690:*/ 0x98, 0xf5, 0xd7, 0x2b, 0x32, 0x2a, 0x4a, 0xbf, 0xe2, 0x21, 0x5f, 0xd8, 0x7a, 0x7c, 0x65, 0x0a, + /*36a0:*/ 0xba, 0x46, 0xfb, 0x66, 0x27, 0xdb, 0xd2, 0xa6, 0x52, 0x49, 0x7a, 0xb2, 0xee, 0x58, 0xe0, 0xc2, + /*36b0:*/ 0x90, 0x76, 0x90, 0x4a, 0x6f, 0xa1, 0x04, 0x44, 0xba, 0x9e, 0x40, 0x33, 0x16, 0x27, 0xa3, 0x0e, + /*36c0:*/ 0x6b, 0xed, 0x26, 0x0a, 0xaa, 0xc2, 0x09, 0x6a, 0xd6, 0x7c, 0x86, 0x9d, 0x3c, 0x57, 0x66, 0x01, + /*36d0:*/ 0xf0, 0x59, 0xd1, 0x2a, 0xf4, 0x5e, 0xa8, 0x4f, 0xff, 0x1a, 0xb2, 0xc6, 0xc6, 0xaa, 0x1e, 0x0d, + /*36e0:*/ 0x8d, 0x32, 0x05, 0x6d, 0x97, 0x25, 0xea, 0x32, 0x14, 0x4b, 0x6b, 0x20, 0x2a, 0x8c, 0x2b, 0xc1, + /*36f0:*/ 0x58, 0xcb, 0xa6, 0x87, 0x50, 0x96, 0xdb, 0x48, 0x3b, 0xcf, 0x6a, 0x41, 0x30, 0x72, 0x2d, 0x00, + /*3700:*/ 0x54, 0x6c, 0x03, 0x86, 0x88, 0x1a, 0x67, 0x8f, 0xa1, 0x4c, 0xdc, 0xf5, 0x7c, 0x16, 0xcf, 0x6f, + /*3710:*/ 0xa1, 0x5c, 0x59, 0x83, 0xb2, 0xca, 0xc3, 0xa4, 0x86, 0xa3, 0x0b, 0xab, 0x45, 0xeb, 0xf0, 0x21, + /*3720:*/ 0x8d, 0x06, 0x7f, 0x44, 0xa2, 0x4f, 0xeb, 0x63, 0x6f, 0x41, 0x11, 0x45, 0x7d, 0x00, 0xe9, 0x80, + /*3730:*/ 0x98, 0x25, 0xe3, 0x9c, 0x5f, 0x21, 0x9e, 0x3c, 0xfa, 0x8f, 0x0c, 0x35, 0x29, 0xce, 0x6e, 0xd6, + /*3740:*/ 0x48, 0x2c, 0x30, 0x90, 0xce, 0x35, 0x9d, 0x23, 0x10, 0x7d, 0x21, 0x0e, 0xc2, 0x93, 0x93, 0x8c, + /*3750:*/ 0xc5, 0xfc, 0xc6, 0x33, 0x05, 0x56, 0xa3, 0x53, 0x28, 0xd5, 0x3f, 0xc2, 0x80, 0x22, 0x9d, 0x5f, + /*3760:*/ 0xaa, 0x97, 0x06, 0x0b, 0xa1, 0xa7, 0x7b, 0x12, 0x7f, 0xcc, 0xca, 0xbc, 0x3e, 0x72, 0xd2, 0x17, + /*3770:*/ 0xb0, 0xd0, 0xe2, 0x0e, 0x36, 0xe4, 0xeb, 0xd5, 0x25, 0xc7, 0x94, 0xc4, 0x36, 0xa5, 0x2f, 0xee, + /*3780:*/ 0x03, 0xe3, 0x99, 0x3b, 0x9a, 0x57, 0x81, 0x71, 0xc6, 0xdc, 0x18, 0xea, 0x88, 0x10, 0x59, 0xfd, + /*3790:*/ 0x9d, 0x31, 0x71, 0x79, 0x55, 0x5d, 0x65, 0xf1, 0x20, 0x81, 0x9e, 0x0e, 0x42, 0x91, 0x2a, 0xa7, + /*37a0:*/ 0x0a, 0x79, 0xa8, 0x33, 0xd5, 0x00, 0x1d, 0x55, 0xb2, 0x47, 0xc6, 0xda, 0x47, 0x1e, 0x55, 0x7a, + /*37b0:*/ 0xb5, 0x16, 0xe9, 0x16, 0x75, 0x1c, 0x1a, 0x6e, 0x57, 0x30, 0xf4, 0xe1, 0xf0, 0x92, 0x2d, 0x28, + /*37c0:*/ 0xfa, 0x30, 0xc5, 0xc2, 0x6e, 0x6b, 0x0b, 0x98, 0x64, 0xd7, 0x3f, 0x6e, 0x73, 0x20, 0xb1, 0xda, + /*37d0:*/ 0x9a, 0xc4, 0x04, 0xe9, 0xc8, 0x8c, 0x09, 0xb3, 0x0f, 0x06, 0xa8, 0x07, 0x11, 0xc2, 0x15, 0x27, + /*37e0:*/ 0x08, 0xeb, 0x42, 0x29, 0xfb, 0x7c, 0xb2, 0xd5, 0x2c, 0x25, 0x85, 0x6b, 0x07, 0x51, 0xdc, 0x0a, + /*37f0:*/ 0x6b, 0xd4, 0xdb, 0x1d, 0xf7, 0x21, 0x59, 0xa0, 0xb5, 0xd9, 0xdf, 0x62, 0x34, 0xd0, 0xce, 0xad, + /*3800:*/ 0xfc, 0xad, 0x16, 0xcc, 0x01, 0x9d, 0x55, 0x5e, 0x84, 0xdd, 0x5f, 0xad, 0x3a, 0x36, 0x81, 0x5c, + /*3810:*/ 0xaf, 0x48, 0xce, 0x4d, 0xb7, 0x39, 0x02, 0x47, 0x20, 0x55, 0xd6, 0xbd, 0x4e, 0xf8, 0xe8, 0x78, + /*3820:*/ 0x74, 0xb3, 0x8e, 0x76, 0xbf, 0x71, 0x1e, 0x46, 0x5b, 0x33, 0x74, 0x23, 0xe1, 0x8b, 0xee, 0x89, + /*3830:*/ 0x38, 0xdb, 0xde, 0xb7, 0xae, 0x06, 0x3c, 0x51, 0x1b, 0xaf, 0xf6, 0x32, 0x61, 0x5b, 0xe2, 0xf6, + /*3840:*/ 0x7e, 0x0e, 0x78, 0xe8, 0xcf, 0x1a, 0x4a, 0x39, 0xf8, 0xda, 0x4f, 0x1b, 0xb5, 0xe4, 0x25, 0x3e, + /*3850:*/ 0x41, 0xef, 0x28, 0xcb, 0x17, 0x2f, 0xa4, 0x55, 0xd6, 0xf9, 0x88, 0x48, 0x26, 0x66, 0x56, 0xfe, + /*3860:*/ 0x30, 0x4d, 0x7d, 0x6b, 0xf8, 0x61, 0x80, 0x0f, 0x3d, 0x36, 0xb3, 0x7d, 0x73, 0x40, 0x17, 0x92, + /*3870:*/ 0x51, 0x58, 0x05, 0x49, 0x4b, 0x83, 0x13, 0x2a, 0x24, 0xd5, 0x92, 0xac, 0x40, 0x67, 0xe3, 0xa8, + /*3880:*/ 0xe9, 0xa6, 0x85, 0x58, 0xd7, 0xf4, 0xfc, 0x1d, 0xb5, 0x68, 0x19, 0xa7, 0xf8, 0xd8, 0xa5, 0x75, + /*3890:*/ 0xe0, 0x6d, 0xc6, 0x5a, 0xa6, 0xa3, 0x1c, 0x16, 0xd3, 0xf3, 0x61, 0xbb, 0x3c, 0x61, 0xb1, 0x3d, + /*38a0:*/ 0x58, 0xb9, 0x3f, 0x8a, 0xb2, 0x61, 0x6d, 0x78, 0x92, 0x20, 0x6e, 0xff, 0x69, 0x5e, 0x3e, 0xe2, + /*38b0:*/ 0x16, 0xb2, 0xc4, 0x44, 0x8d, 0xb9, 0x86, 0xa5, 0xcf, 0xc7, 0x97, 0xc1, 0x10, 0xed, 0xe7, 0x76, + /*38c0:*/ 0xe3, 0xa6, 0x51, 0x8f, 0x01, 0xb5, 0xd0, 0x34, 0xe2, 0xab, 0x7d, 0x45, 0xb6, 0x1f, 0x7c, 0xde, + /*38d0:*/ 0x5a, 0xa7, 0x59, 0x9e, 0xd2, 0x4b, 0x6d, 0xc8, 0xf4, 0x29, 0xb4, 0x73, 0x20, 0x0a, 0xc5, 0x60, + /*38e0:*/ 0xd1, 0x6e, 0xad, 0x8f, 0xb7, 0x56, 0xd3, 0xaa, 0xf9, 0xff, 0x16, 0xcc, 0x7b, 0x87, 0x2c, 0x3a, + /*38f0:*/ 0xa1, 0x1c, 0x57, 0x24, 0x5f, 0xb5, 0xb0, 0x99, 0x9c, 0xdb, 0xef, 0xdc, 0x4f, 0x6c, 0xea, 0x39, + /*3900:*/ 0x6d, 0x3d, 0x75, 0x65, 0x90, 0x79, 0xb5, 0x4b, 0xa9, 0x86, 0x74, 0xc5, 0xe6, 0x60, 0x7c, 0x2e, + /*3910:*/ 0xa4, 0x64, 0x93, 0xc8, 0x24, 0x54, 0x9b, 0xbf, 0x08, 0x07, 0xd1, 0x94, 0x87, 0xea, 0x9d, 0x88, + /*3920:*/ 0x19, 0x52, 0x32, 0xa4, 0xb5, 0x09, 0xf1, 0xb8, 0xee, 0x33, 0xc9, 0xff, 0x17, 0x9e, 0xbc, 0xb9, + /*3930:*/ 0xb4, 0x53, 0x93, 0xf4, 0x76, 0xa2, 0xd0, 0x87, 0xce, 0x22, 0xea, 0xee, 0xe3, 0xeb, 0x88, 0x58, + /*3940:*/ 0xb5, 0xb2, 0xd8, 0xed, 0x4c, 0x01, 0x2a, 0x8c, 0x25, 0x6f, 0xbf, 0xb1, 0xe5, 0x23, 0xf1, 0x7a, + /*3950:*/ 0x78, 0x2b, 0x32, 0x37, 0x99, 0xc3, 0xb0, 0x23, 0xa2, 0x9f, 0x72, 0xb6, 0x71, 0x88, 0x92, 0x32, + /*3960:*/ 0x52, 0x77, 0xd1, 0xb6, 0x0d, 0xbe, 0x6e, 0xd4, 0xdc, 0xf9, 0xb2, 0x0f, 0xcc, 0x8d, 0x8a, 0x96, + /*3970:*/ 0xce, 0x7f, 0x8f, 0xa4, 0x0e, 0x8f, 0x5f, 0x4c, 0x35, 0x54, 0xcb, 0xe2, 0xfa, 0xad, 0x5d, 0xd5, + /*3980:*/ 0x5d, 0x70, 0xf2, 0x82, 0x78, 0x27, 0xb9, 0xf9, 0x02, 0x15, 0x53, 0x00, 0xae, 0x29, 0x85, 0xf4, + /*3990:*/ 0xba, 0xc6, 0x0e, 0x6c, 0xb6, 0xe9, 0xef, 0xe1, 0x88, 0x42, 0xc5, 0x1a, 0x23, 0x5f, 0x19, 0xaf, + /*39a0:*/ 0x15, 0x9e, 0x26, 0x48, 0x42, 0x91, 0xc5, 0xc0, 0xfe, 0xfb, 0x72, 0x0c, 0x98, 0x98, 0xfa, 0xed, + /*39b0:*/ 0x94, 0x12, 0x1f, 0xc5, 0x14, 0x00, 0x55, 0xa5, 0x10, 0xc6, 0xf6, 0x3e, 0x64, 0x8c, 0xa7, 0x4e, + /*39c0:*/ 0x11, 0x84, 0x16, 0xeb, 0x48, 0x90, 0x49, 0xc2, 0xbf, 0x3c, 0xab, 0x54, 0xe4, 0x28, 0x59, 0x43, + /*39d0:*/ 0x77, 0xad, 0x1a, 0x14, 0xd8, 0xc3, 0x3e, 0x88, 0x3f, 0x7f, 0x38, 0xbf, 0xe2, 0x65, 0x89, 0x6d, + /*39e0:*/ 0x9e, 0x4e, 0x91, 0x5f, 0x6a, 0x70, 0x48, 0x17, 0xa0, 0x87, 0x68, 0x0d, 0x4b, 0x7c, 0x56, 0x1f, + /*39f0:*/ 0x57, 0xb0, 0x4d, 0x54, 0x78, 0x3e, 0x2b, 0xdb, 0x12, 0xed, 0x1d, 0x69, 0x7a, 0x48, 0x03, 0x46, + /*3a00:*/ 0x3c, 0xa8, 0x45, 0xff, 0xc7, 0x23, 0x17, 0x2d, 0xdd, 0x6b, 0xad, 0x4a, 0xff, 0x9d, 0x8d, 0xa2, + /*3a10:*/ 0x9e, 0x3d, 0x5b, 0xe6, 0x7a, 0x0f, 0x31, 0x6e, 0x0a, 0xca, 0xc4, 0x48, 0x91, 0xe5, 0xd2, 0x38, + /*3a20:*/ 0xfe, 0x87, 0x1b, 0x4a, 0xa1, 0xca, 0xd6, 0xad, 0x4d, 0x90, 0xff, 0x65, 0x93, 0xc1, 0x22, 0xdd, + /*3a30:*/ 0x46, 0x16, 0x89, 0x08, 0x6e, 0x6d, 0x35, 0x5e, 0x13, 0x95, 0x6d, 0x0e, 0xce, 0xd1, 0x3c, 0x98, + /*3a40:*/ 0x15, 0x0a, 0xee, 0xaa, 0xbb, 0x7e, 0xba, 0x21, 0x1c, 0x1d, 0x52, 0x6d, 0xaa, 0x86, 0xcd, 0x42, + /*3a50:*/ 0x52, 0xf4, 0xdf, 0xca, 0x57, 0xf8, 0x26, 0x7b, 0xc7, 0x31, 0x37, 0xec, 0xbb, 0x5b, 0x61, 0xe5, + /*3a60:*/ 0xda, 0xa9, 0x93, 0xd6, 0xe1, 0xd7, 0xcf, 0xdc, 0xeb, 0x3a, 0xcb, 0x19, 0x73, 0x40, 0xf3, 0xde, + /*3a70:*/ 0x5d, 0x4a, 0xaf, 0x46, 0x62, 0xbb, 0xf7, 0x4b, 0x4c, 0xe1, 0x50, 0xa7, 0xc5, 0x14, 0x71, 0xbf, + /*3a80:*/ 0x3a, 0x03, 0x8a, 0xd2, 0xaa, 0x9a, 0x44, 0x91, 0xaf, 0xd1, 0x44, 0x24, 0xa4, 0x0e, 0x47, 0x32, + /*3a90:*/ 0x51, 0x62, 0x14, 0x10, 0x8d, 0x21, 0x2d, 0x7e, 0x62, 0x12, 0x5d, 0xc1, 0x46, 0xcc, 0x9d, 0xd0, + /*3aa0:*/ 0xa0, 0xa2, 0x35, 0x33, 0xcb, 0x4c, 0xc0, 0x5a, 0x20, 0x2e, 0xc8, 0x49, 0x03, 0x12, 0x00, 0xc9, + /*3ab0:*/ 0x5c, 0xc8, 0xc3, 0xff, 0xfa, 0x1f, 0x85, 0x18, 0x78, 0xe4, 0x7f, 0x95, 0x07, 0xce, 0xb3, 0xf3, + /*3ac0:*/ 0xb1, 0x75, 0x76, 0xf3, 0xd8, 0x82, 0xc8, 0xc9, 0x5e, 0xb5, 0x30, 0xa6, 0xbf, 0xcb, 0x0a, 0x21, + /*3ad0:*/ 0x1e, 0x98, 0x06, 0x8e, 0x4c, 0x7a, 0xb4, 0x72, 0x36, 0xf5, 0xca, 0x07, 0xce, 0x90, 0xf2, 0x1f, + /*3ae0:*/ 0xcd, 0x68, 0xac, 0x7f, 0x12, 0x8a, 0x19, 0x2c, 0x60, 0x3a, 0x9a, 0x65, 0x79, 0x48, 0x01, 0x89, + /*3af0:*/ 0x9e, 0x61, 0xff, 0xe4, 0x36, 0x4f, 0x0d, 0x9b, 0x69, 0xaa, 0x9f, 0x01, 0x87, 0x53, 0x13, 0x0c, + /*3b00:*/ 0x93, 0x20, 0x21, 0x87, 0x41, 0x48, 0xfc, 0x82, 0xe9, 0x12, 0x4c, 0x17, 0xd0, 0xee, 0xdc, 0x68, + /*3b10:*/ 0xf9, 0xdd, 0x28, 0x13, 0xa4, 0x28, 0x12, 0x97, 0x38, 0xe9, 0xb9, 0x7c, 0x0e, 0xfe, 0xc3, 0xd3, + /*3b20:*/ 0x86, 0x7d, 0xb3, 0x82, 0x66, 0xb8, 0x98, 0xeb, 0xdd, 0x24, 0x82, 0xa6, 0x26, 0x82, 0xd0, 0xf0, + /*3b30:*/ 0x44, 0xd1, 0x1e, 0x49, 0xee, 0xf5, 0x48, 0x75, 0x87, 0xca, 0xe2, 0xdf, 0x81, 0x9a, 0x5b, 0x83, + /*3b40:*/ 0xfd, 0xa1, 0xef, 0x87, 0x83, 0x95, 0xe5, 0x8c, 0x74, 0x35, 0x38, 0xd9, 0x7c, 0x56, 0x5f, 0xf0, + /*3b50:*/ 0xd4, 0x60, 0xb8, 0x97, 0xe2, 0x96, 0x06, 0xd3, 0xc9, 0xc9, 0x88, 0x31, 0x02, 0x2a, 0xb2, 0x28, + /*3b60:*/ 0xb2, 0xcc, 0x91, 0xcb, 0x01, 0xec, 0xb5, 0x9d, 0x09, 0x6e, 0xd0, 0xde, 0xf0, 0xce, 0x72, 0x93, + /*3b70:*/ 0x6c, 0xcb, 0xaa, 0x2b, 0x29, 0x84, 0xbe, 0xab, 0xff, 0x42, 0x2e, 0x4f, 0xc1, 0x65, 0x22, 0x91, + /*3b80:*/ 0xac, 0xb3, 0xfb, 0x53, 0x98, 0x56, 0x8f, 0x16, 0xbe, 0x1d, 0x7f, 0x29, 0x17, 0xdc, 0x9d, 0xf8, + /*3b90:*/ 0x59, 0x8b, 0xa9, 0x76, 0x01, 0xa8, 0x24, 0xa7, 0x00, 0xdd, 0xa3, 0xe5, 0x6e, 0x27, 0x66, 0x2f, + /*3ba0:*/ 0xe7, 0x1d, 0x0d, 0x2a, 0x75, 0x80, 0x10, 0x38, 0xf6, 0x3d, 0x45, 0x18, 0xb0, 0x31, 0xcb, 0xe0, + /*3bb0:*/ 0x8e, 0x73, 0x14, 0xbc, 0x36, 0x16, 0xf3, 0xa8, 0xd5, 0x3e, 0xf6, 0xdc, 0xa7, 0x33, 0xcb, 0x49, + /*3bc0:*/ 0xb6, 0x45, 0x00, 0xb6, 0xcc, 0x9d, 0x40, 0xbc, 0x1d, 0x12, 0xbb, 0xe4, 0xd0, 0x3f, 0xa6, 0x28, + /*3bd0:*/ 0x5d, 0x0f, 0xa2, 0x90, 0xbe, 0x1f, 0x90, 0x6a, 0xb8, 0x22, 0x89, 0xf9, 0x3a, 0xdd, 0x7a, 0xe8, + /*3be0:*/ 0x63, 0x1f, 0x1f, 0x15, 0xa1, 0xbd, 0x72, 0x6d, 0x83, 0x02, 0x5e, 0x95, 0x5c, 0x33, 0x20, 0xb4, + /*3bf0:*/ 0xe5, 0x39, 0x87, 0xd9, 0x57, 0xd7, 0xb6, 0x86, 0x21, 0xff, 0xfa, 0x67, 0x7e, 0x94, 0xac, 0xda, + /*3c00:*/ 0xf0, 0xe0, 0x4e, 0xc4, 0x88, 0x84, 0x01, 0xcc, 0xfa, 0x37, 0x27, 0xbe, 0x63, 0x8f, 0x41, 0x94, + /*3c10:*/ 0x75, 0x06, 0x8c, 0x10, 0xd5, 0xf7, 0xe1, 0x2c, 0x92, 0xe1, 0x4f, 0xda, 0xdf, 0xac, 0x64, 0xe8, + /*3c20:*/ 0x8e, 0xbb, 0x8b, 0x9a, 0x70, 0x57, 0x50, 0xb3, 0x63, 0x77, 0xcf, 0xa6, 0xb0, 0x91, 0x13, 0xa4, + /*3c30:*/ 0x29, 0xf1, 0x27, 0x1d, 0x4e, 0x37, 0x6b, 0x81, 0xd3, 0x0d, 0x3c, 0xb6, 0x91, 0x42, 0xf4, 0x70, + /*3c40:*/ 0x64, 0x86, 0x2f, 0xee, 0xec, 0xc2, 0x97, 0xb7, 0xb6, 0xf2, 0x86, 0x8a, 0x7a, 0x2d, 0x6c, 0x06, + /*3c50:*/ 0x5d, 0x24, 0xd9, 0xf9, 0xc8, 0xd2, 0xd6, 0xb5, 0xb8, 0xd7, 0x0a, 0x1e, 0x31, 0x4f, 0x04, 0x9c, + /*3c60:*/ 0x4b, 0xe0, 0x21, 0xdf, 0xb3, 0x8d, 0xdf, 0xc7, 0x9d, 0x57, 0x62, 0xa4, 0xff, 0x88, 0x07, 0x0e, + /*3c70:*/ 0xad, 0x7f, 0x39, 0xe8, 0x8a, 0x04, 0x64, 0xde, 0x94, 0xc3, 0xa3, 0xd0, 0xc8, 0x40, 0x27, 0x63, + /*3c80:*/ 0x76, 0x4b, 0xa0, 0xe1, 0xdc, 0xf1, 0xec, 0x93, 0xd3, 0xa2, 0x69, 0x8a, 0xa7, 0xe2, 0x33, 0x97, + /*3c90:*/ 0x58, 0xff, 0x7e, 0x66, 0x24, 0x2c, 0x61, 0x7f, 0x3a, 0xdf, 0x92, 0x31, 0x4b, 0x66, 0x52, 0x7e, + /*3ca0:*/ 0xa3, 0x88, 0x7e, 0x57, 0xe6, 0x51, 0xf6, 0x7f, 0x98, 0x93, 0x6b, 0xd7, 0x7d, 0x7d, 0xee, 0x72, + /*3cb0:*/ 0xc6, 0x15, 0xe1, 0x30, 0x2a, 0xeb, 0x48, 0x8f, 0x8d, 0xed, 0x62, 0x0c, 0x53, 0x93, 0x62, 0x1e, + /*3cc0:*/ 0x61, 0x1a, 0x2e, 0x34, 0xad, 0xd2, 0x47, 0x0d, 0x08, 0x8e, 0xae, 0x35, 0x77, 0x25, 0x67, 0x00, + /*3cd0:*/ 0x9a, 0xf0, 0x51, 0x5e, 0x16, 0x94, 0x31, 0xd7, 0x24, 0x17, 0xa5, 0xe5, 0x2e, 0x92, 0x36, 0xcb, + /*3ce0:*/ 0x36, 0xf8, 0x16, 0xb7, 0x7b, 0xff, 0x2d, 0x25, 0x02, 0x00, 0xb3, 0x75, 0x78, 0xd5, 0xb2, 0x69, + /*3cf0:*/ 0xae, 0x95, 0xd8, 0xc4, 0x4e, 0xa1, 0x6f, 0x93, 0x20, 0xae, 0x74, 0x56, 0x7a, 0xed, 0x24, 0xbb, + /*3d00:*/ 0xc7, 0x8d, 0x0a, 0xbe, 0x9f, 0x5c, 0xd4, 0xa2, 0x20, 0xe9, 0x5e, 0x01, 0x6d, 0x16, 0xe1, 0x59, + /*3d10:*/ 0x05, 0x65, 0xa7, 0x5b, 0xdc, 0x3f, 0x15, 0xf0, 0x43, 0x97, 0x0f, 0x72, 0x60, 0x47, 0xf8, 0x1c, + /*3d20:*/ 0xff, 0xdc, 0xcf, 0xb1, 0xc3, 0x2a, 0x44, 0x9d, 0x37, 0xec, 0x8b, 0x0d, 0x7d, 0x37, 0xa5, 0x2f, + /*3d30:*/ 0x3c, 0x74, 0xca, 0x90, 0x2c, 0x0c, 0x8f, 0x88, 0x01, 0x48, 0x81, 0x0b, 0x8b, 0xf8, 0xc7, 0xb8, + /*3d40:*/ 0x96, 0x45, 0x06, 0x4e, 0x60, 0x04, 0xd8, 0xae, 0x30, 0xcb, 0x6b, 0xf9, 0xdd, 0x0a, 0x31, 0x8d, + /*3d50:*/ 0xde, 0x60, 0x42, 0xf3, 0xf1, 0x87, 0x31, 0x85, 0x25, 0x62, 0xcc, 0x92, 0x54, 0x49, 0x96, 0xd5, + /*3d60:*/ 0x72, 0xc7, 0xb7, 0xf1, 0x01, 0x0b, 0x30, 0xe5, 0x8b, 0xba, 0x49, 0x05, 0xe0, 0xa2, 0x54, 0xee, + /*3d70:*/ 0x45, 0xae, 0xd3, 0x75, 0x35, 0x61, 0x9a, 0x10, 0xee, 0x1f, 0x2a, 0x83, 0xfe, 0x81, 0x0d, 0xc4, + /*3d80:*/ 0xc2, 0x35, 0xc9, 0xf0, 0xed, 0x01, 0xf3, 0x5f, 0x9b, 0x66, 0x41, 0xc1, 0x10, 0x04, 0xc3, 0x57, + /*3d90:*/ 0x04, 0x74, 0x31, 0x72, 0xd9, 0x15, 0x9d, 0xe6, 0xc9, 0x2e, 0xb9, 0xd0, 0x2c, 0xe5, 0x27, 0x85, + /*3da0:*/ 0xa8, 0xe8, 0x8b, 0x44, 0x20, 0x99, 0x1e, 0x12, 0x33, 0xff, 0x4c, 0xa1, 0x59, 0x2c, 0x44, 0xd2, + /*3db0:*/ 0x51, 0x94, 0xa1, 0xc1, 0x65, 0xe8, 0x77, 0xad, 0xf7, 0x2c, 0x3c, 0x1b, 0xeb, 0x85, 0x31, 0x7e, + /*3dc0:*/ 0x7a, 0x3d, 0xe3, 0x49, 0xc3, 0xe7, 0x8f, 0xe1, 0x39, 0x88, 0x33, 0xd1, 0x8d, 0xf5, 0xec, 0x2c, + /*3dd0:*/ 0x43, 0x6a, 0x63, 0x8a, 0xad, 0x7b, 0x61, 0x8c, 0x55, 0x10, 0x89, 0x2e, 0x50, 0x0c, 0x72, 0x49, + /*3de0:*/ 0xad, 0xaf, 0xc4, 0x3f, 0x34, 0xdb, 0xc9, 0x23, 0x90, 0x18, 0xd6, 0x8c, 0xe9, 0xab, 0x5b, 0x01, + /*3df0:*/ 0x9c, 0x5d, 0x05, 0x65, 0x5c, 0x14, 0x27, 0x28, 0xa7, 0x42, 0x93, 0xbe, 0xde, 0xd2, 0x3a, 0x1f, + /*3e00:*/ 0x3f, 0x32, 0xaf, 0x89, 0x34, 0xfa, 0x7a, 0x0d, 0xdd, 0x66, 0xdc, 0x16, 0x60, 0x69, 0x24, 0x04, + /*3e10:*/ 0x1e, 0x9e, 0x55, 0x09, 0x3c, 0x98, 0xb3, 0x95, 0xcc, 0xa4, 0x51, 0xb4, 0x17, 0x80, 0x3a, 0x74, + /*3e20:*/ 0x2c, 0x2f, 0x54, 0x28, 0x83, 0xf9, 0xc4, 0x8a, 0x6b, 0x42, 0x57, 0x6c, 0x14, 0xba, 0xca, 0x51, + /*3e30:*/ 0x27, 0xeb, 0x90, 0x98, 0x59, 0x84, 0x0c, 0xea, 0x90, 0x6e, 0xf3, 0xb2, 0xc3, 0x50, 0xd2, 0x4e, + /*3e40:*/ 0xa0, 0xb3, 0xc0, 0x09, 0x41, 0x59, 0xb5, 0x18, 0x0e, 0x14, 0x27, 0xb1, 0x95, 0x21, 0x0c, 0xe7, + /*3e50:*/ 0x24, 0x79, 0x62, 0x9c, 0x90, 0xe5, 0x44, 0x98, 0x7b, 0x5f, 0xba, 0x46, 0x5f, 0x61, 0xbb, 0x25, + /*3e60:*/ 0xd3, 0x3b, 0x63, 0xdf, 0xc4, 0x76, 0xce, 0x55, 0x4d, 0xaf, 0x69, 0xfd, 0xab, 0xaa, 0x2c, 0x52, + /*3e70:*/ 0xaa, 0x20, 0x38, 0x7e, 0x29, 0x4a, 0x7d, 0x09, 0xee, 0xa8, 0x77, 0xe0, 0xed, 0x54, 0x64, 0x50, + /*3e80:*/ 0x19, 0x1f, 0xc7, 0x34, 0x79, 0xbf, 0x06, 0xf9, 0xac, 0x61, 0x6a, 0xd7, 0x8e, 0xb0, 0x65, 0x4d, + /*3e90:*/ 0xa0, 0xc1, 0x9a, 0xbb, 0x44, 0xbd, 0x30, 0xa0, 0xfb, 0xf5, 0x35, 0x91, 0xa7, 0x09, 0xbb, 0x48, + /*3ea0:*/ 0x4f, 0x94, 0x33, 0xe2, 0x3d, 0x79, 0xc0, 0x0b, 0x27, 0x42, 0x9f, 0x7c, 0x4c, 0x1a, 0xe5, 0x17, + /*3eb0:*/ 0xb2, 0xdf, 0xa3, 0x87, 0x4b, 0x76, 0xd3, 0x78, 0x24, 0x6b, 0xd4, 0x54, 0x7e, 0x73, 0x37, 0x2b, + /*3ec0:*/ 0xe1, 0xbe, 0xba, 0xbd, 0x6b, 0xb4, 0x5c, 0x7b, 0xba, 0xbc, 0x98, 0x65, 0xcb, 0xdf, 0xb9, 0x99, + /*3ed0:*/ 0x25, 0xeb, 0xe5, 0x93, 0xff, 0x8f, 0x82, 0x6c, 0x5f, 0x6b, 0xde, 0x47, 0xb7, 0x16, 0x92, 0x81, + /*3ee0:*/ 0x7c, 0x77, 0xe3, 0x0b, 0x6f, 0xf2, 0x9a, 0xa0, 0x98, 0xf4, 0xf5, 0xcd, 0x6e, 0xf4, 0x64, 0x65, + /*3ef0:*/ 0xc2, 0x87, 0x85, 0x54, 0x32, 0x11, 0x37, 0xde, 0xfb, 0x7e, 0x51, 0x64, 0x4b, 0x7f, 0x57, 0x34, + /*3f00:*/ 0x1c, 0xa3, 0x37, 0x11, 0x1e, 0x66, 0x43, 0xf5, 0x6d, 0x4d, 0x08, 0x94, 0x7c, 0x79, 0xb7, 0xfe, + /*3f10:*/ 0x20, 0x78, 0x2e, 0x19, 0x49, 0xf6, 0x3b, 0x86, 0xe4, 0xa1, 0xc5, 0x65, 0xef, 0xa9, 0x97, 0x55, + /*3f20:*/ 0x37, 0xed, 0x23, 0xd2, 0x5a, 0x14, 0x5a, 0xde, 0x6c, 0xda, 0x50, 0xfb, 0xcb, 0x56, 0x56, 0x8e, + /*3f30:*/ 0xf1, 0xd1, 0x18, 0x0d, 0x17, 0x7f, 0x3a, 0xb3, 0x07, 0x25, 0x1a, 0x76, 0x1f, 0xd8, 0x67, 0x97, + /*3f40:*/ 0x43, 0xfa, 0x02, 0xa8, 0x7c, 0x6d, 0x56, 0xb1, 0xd4, 0xba, 0x1d, 0x06, 0x60, 0x86, 0x66, 0xd6, + /*3f50:*/ 0xd5, 0x1b, 0x5e, 0x64, 0xf5, 0x02, 0x44, 0xa4, 0x8d, 0x21, 0x27, 0xd2, 0x16, 0xe4, 0xd9, 0xad, + /*3f60:*/ 0xac, 0x08, 0x12, 0x81, 0xd6, 0xe4, 0x4e, 0x68, 0xe4, 0xaf, 0x62, 0x8c, 0x7e, 0xef, 0x42, 0xa9, + /*3f70:*/ 0xff, 0x3f, 0x3b, 0x6c, 0x9f, 0xec, 0xa5, 0x9c, 0xf5, 0xf8, 0x4f, 0xa9, 0x37, 0x79, 0x86, 0x92, + /*3f80:*/ 0x2b, 0x6d, 0x75, 0xbc, 0x50, 0x5e, 0x78, 0x1c, 0xbe, 0x03, 0xcf, 0x7d, 0x37, 0x21, 0xcf, 0x43, + /*3f90:*/ 0x4e, 0x2b, 0x68, 0x7b, 0x77, 0x44, 0x39, 0x85, 0x1b, 0x1c, 0x4a, 0x1f, 0x75, 0x68, 0xa6, 0x9c, + /*3fa0:*/ 0x8c, 0x0f, 0x35, 0x78, 0x20, 0x1a, 0xe5, 0xa6, 0x2b, 0xbf, 0x4a, 0x08, 0x04, 0xe5, 0x9d, 0x08, + /*3fb0:*/ 0x4f, 0x03, 0x11, 0xc9, 0x08, 0x1a, 0xde, 0xd1, 0x9d, 0x7c, 0x74, 0x49, 0x5d, 0x09, 0xff, 0x38, + /*3fc0:*/ 0x29, 0x76, 0xa6, 0xf8, 0x9a, 0xda, 0xda, 0x9a, 0xb6, 0xc9, 0x39, 0x59, 0x62, 0xe1, 0x4b, 0x7f, + /*3fd0:*/ 0x11, 0xac, 0xa6, 0x21, 0x85, 0x0b, 0x2a, 0x0e, 0xa6, 0x89, 0x61, 0x00, 0xdc, 0xb0, 0x5a, 0x9b, + /*3fe0:*/ 0x1b, 0xbd, 0x44, 0x74, 0x01, 0xbc, 0x31, 0x7f, 0xbb, 0x2f, 0x4c, 0x83, 0x8d, 0xe2, 0x99, 0xea, + /*3ff0:*/ 0xad, 0xbb, 0xb4, 0xe5, 0xb6, 0x4d, 0xa8, 0xf6, 0x99, 0xe2, 0x85, 0x27, 0x08, 0x70, 0x84, 0x05, + /*4000:*/ 0xed, 0x8d, 0x0e, 0x89, 0x9a, 0x03, 0xc3, 0xe6, 0xa6, 0xe1, 0x8d, 0xc3, 0x2e, 0xdd, 0xc8, 0x53, + /*4010:*/ 0xb8, 0xd7, 0x88, 0xf6, 0x88, 0xb2, 0xb4, 0x38, 0xa6, 0xc4, 0xc1, 0x2c, 0x71, 0x41, 0x8f, 0xc3, + /*4020:*/ 0x51, 0x77, 0x20, 0x0c, 0xa6, 0x4c, 0xac, 0xcd, 0xf5, 0xae, 0x4c, 0x37, 0x57, 0xf5, 0x1c, 0x09, + /*4030:*/ 0xe3, 0xcf, 0x5c, 0x69, 0xed, 0x92, 0x5e, 0xce, 0xf1, 0x83, 0x41, 0xf7, 0xa1, 0x05, 0x3f, 0x56, + /*4040:*/ 0x5e, 0x76, 0x06, 0x63, 0xb7, 0x73, 0x2a, 0xe4, 0x83, 0x10, 0xe6, 0x30, 0x7e, 0x9a, 0xd6, 0xc5, + /*4050:*/ 0x8d, 0x7f, 0xf8, 0xeb, 0xf6, 0x05, 0x32, 0x24, 0xf1, 0x70, 0xa9, 0x85, 0x69, 0x5c, 0x37, 0x02, + /*4060:*/ 0x4a, 0x7e, 0x23, 0xee, 0x91, 0xa2, 0xdd, 0xaa, 0x51, 0x6b, 0x1b, 0x39, 0x76, 0x28, 0x9e, 0xbf, + /*4070:*/ 0xe5, 0xd9, 0xfe, 0x0b, 0x89, 0x63, 0xff, 0x47, 0x50, 0x8f, 0x66, 0x0e, 0x96, 0x0f, 0x3d, 0x8c, + /*4080:*/ 0xdd, 0x55, 0xfd, 0xae, 0x37, 0x18, 0x71, 0x0e, 0x08, 0x48, 0x65, 0x53, 0xb8, 0x1b, 0x9d, 0xc5, + /*4090:*/ 0x1f, 0x0f, 0x9e, 0x9a, 0xcf, 0xfb, 0x37, 0xf0, 0x6e, 0x5c, 0x8b, 0xec, 0x3b, 0x3a, 0xd3, 0xce, + /*40a0:*/ 0xc5, 0x94, 0x24, 0x88, 0x0b, 0x6a, 0x03, 0x4c, 0x52, 0xf7, 0xb2, 0x1d, 0x07, 0xae, 0x81, 0x3d, + /*40b0:*/ 0xf1, 0xfd, 0x8e, 0xcc, 0x3a, 0x47, 0x6e, 0xa9, 0x19, 0xf7, 0x16, 0x8e, 0x15, 0x93, 0x56, 0x20, + /*40c0:*/ 0x7e, 0x67, 0xd3, 0x17, 0xcb, 0xfa, 0x4b, 0xf1, 0x63, 0x02, 0x81, 0x14, 0x1e, 0xbd, 0x73, 0x95, + /*40d0:*/ 0xcc, 0xfd, 0x70, 0xa6, 0x30, 0x3e, 0x41, 0x64, 0x5a, 0x12, 0xc6, 0x50, 0x28, 0xf0, 0x83, 0x60, + /*40e0:*/ 0xd7, 0xb9, 0x72, 0x1d, 0x87, 0xab, 0x74, 0xf5, 0xb7, 0x30, 0xa1, 0xae, 0x89, 0x76, 0xfe, 0x92, + /*40f0:*/ 0x07, 0x34, 0x78, 0x8e, 0x8b, 0xb1, 0x44, 0x85, 0x37, 0xcf, 0xe8, 0x56, 0xe7, 0xaa, 0xa9, 0x70, + /*4100:*/ 0xe9, 0x79, 0x59, 0xa6, 0x3c, 0x9d, 0xad, 0xc5, 0x0f, 0x7d, 0x3c, 0x8e, 0xb9, 0xdc, 0xd4, 0xf7, + /*4110:*/ 0xe4, 0xcd, 0xa7, 0x27, 0xfd, 0x20, 0x33, 0x9d, 0x64, 0xcd, 0xcc, 0xaf, 0xb9, 0x43, 0xc6, 0x6b, + /*4120:*/ 0xcd, 0xaa, 0xf8, 0x8a, 0x97, 0x30, 0x95, 0xcc, 0xf2, 0x9f, 0x70, 0x25, 0x3f, 0x7b, 0x27, 0x0f, + /*4130:*/ 0xc2, 0x0f, 0xd7, 0x33, 0xde, 0x08, 0x90, 0xc2, 0x5d, 0xb5, 0xc0, 0x1a, 0x39, 0x86, 0xb3, 0x62, + /*4140:*/ 0xeb, 0x19, 0xee, 0x4c, 0x10, 0xe6, 0x75, 0x40, 0x7a, 0x9d, 0x8f, 0x80, 0x39, 0x75, 0x77, 0x37, + /*4150:*/ 0x27, 0x4e, 0x36, 0xa6, 0xc6, 0x7a, 0xb9, 0x0d, 0x7c, 0x5c, 0x7f, 0xbc, 0xe5, 0x9c, 0xe2, 0x13, + /*4160:*/ 0xfe, 0x3f, 0xc6, 0x30, 0xf8, 0xbb, 0xe6, 0x19, 0xcf, 0x2e, 0xfb, 0x6c, 0x10, 0x38, 0x61, 0x72, + /*4170:*/ 0xe3, 0x32, 0xfc, 0xcb, 0x72, 0x88, 0x6b, 0x62, 0x20, 0x32, 0x0b, 0xbc, 0xc3, 0xfd, 0x23, 0x9c, + /*4180:*/ 0xad, 0x96, 0xa7, 0xa4, 0x4e, 0x40, 0xfc, 0xac, 0x04, 0xbc, 0x8e, 0x17, 0x43, 0xba, 0x2b, 0xbf, + /*4190:*/ 0x0a, 0x5f, 0x2b, 0xaa, 0x74, 0x06, 0x1f, 0x75, 0x8e, 0xa4, 0x57, 0xdf, 0x1e, 0x4c, 0xfa, 0xb9, + /*41a0:*/ 0xb4, 0x33, 0x72, 0xd7, 0x88, 0x6b, 0x19, 0xb0, 0x36, 0x76, 0x07, 0xb2, 0x79, 0x77, 0x50, 0xc1, + /*41b0:*/ 0xb9, 0xa5, 0x28, 0x8d, 0xc8, 0x70, 0x3d, 0xdf, 0xe9, 0x96, 0x49, 0xf4, 0xbd, 0xed, 0x62, 0x3c, + /*41c0:*/ 0xe0, 0x63, 0x41, 0x84, 0x55, 0xef, 0x54, 0x2f, 0xb4, 0x94, 0x7d, 0x32, 0x56, 0x01, 0x04, 0x40, + /*41d0:*/ 0x73, 0x43, 0xdd, 0x84, 0xbe, 0xe6, 0x2f, 0xa1, 0xa7, 0xec, 0xed, 0x6f, 0x45, 0xd3, 0x74, 0x58, + /*41e0:*/ 0x5f, 0xae, 0x10, 0x4a, 0xe3, 0x7e, 0xc9, 0xca, 0xee, 0xe0, 0x05, 0xc5, 0x95, 0x34, 0xff, 0x5e, + /*41f0:*/ 0xda, 0x21, 0xf3, 0x49, 0x80, 0xf8, 0xd8, 0x33, 0x3a, 0x93, 0xab, 0xdd, 0x76, 0xdc, 0x77, 0x06, + /*4200:*/ 0x83, 0x9b, 0x67, 0x8a, 0xa0, 0x72, 0x2a, 0x32, 0x24, 0x00, 0x85, 0x1e, 0x27, 0x22, 0x91, 0x85, + /*4210:*/ 0xde, 0xb0, 0x9b, 0xc0, 0xa8, 0x03, 0x90, 0x9e, 0xe3, 0x18, 0x64, 0x91, 0x2c, 0xaa, 0x21, 0xbb, + /*4220:*/ 0xca, 0x34, 0x42, 0x9c, 0xcd, 0x73, 0x5e, 0xff, 0x7a, 0x9a, 0xc0, 0x1c, 0x6e, 0xb2, 0x45, 0xec, + /*4230:*/ 0x09, 0xe4, 0xed, 0x3f, 0xa2, 0xf2, 0x82, 0xa8, 0xa3, 0xc0, 0xd3, 0x4e, 0xbc, 0xe5, 0x11, 0x9b, + /*4240:*/ 0x5e, 0x3d, 0x0e, 0x1e, 0xcc, 0x85, 0x4c, 0x5d, 0x97, 0xa6, 0xa2, 0xe7, 0x90, 0xad, 0x0a, 0xf5, + /*4250:*/ 0x83, 0x65, 0xc6, 0xcc, 0x4f, 0x52, 0xe0, 0x38, 0xe9, 0x25, 0xa7, 0x83, 0x03, 0x4a, 0x0f, 0x72, + /*4260:*/ 0xe5, 0xc9, 0x36, 0x32, 0xb9, 0x7d, 0x58, 0xa2, 0x05, 0x0e, 0x30, 0x13, 0xd3, 0xfc, 0x30, 0x86, + /*4270:*/ 0xbd, 0xab, 0x67, 0xcf, 0x86, 0x4d, 0xa5, 0xfe, 0x6d, 0xb5, 0x91, 0x1e, 0xcf, 0x44, 0xc8, 0x40, + /*4280:*/ 0x2b, 0xaa, 0x96, 0x33, 0xb5, 0x8e, 0x32, 0x59, 0x0d, 0x0c, 0x6d, 0x91, 0x24, 0x7a, 0x49, 0x1a, + /*4290:*/ 0x8d, 0x8f, 0x14, 0xa6, 0x25, 0x35, 0xef, 0x8f, 0xb6, 0x53, 0xaf, 0xe2, 0xa5, 0xa4, 0x3d, 0x19, + /*42a0:*/ 0x9e, 0x61, 0x5c, 0x38, 0x60, 0xdc, 0x7a, 0x90, 0xda, 0xb0, 0xc7, 0x78, 0x2d, 0xc9, 0x8e, 0xc4, + /*42b0:*/ 0x2a, 0xe5, 0x9d, 0x10, 0x26, 0xef, 0x4f, 0x79, 0xf2, 0xf7, 0x89, 0x79, 0xdb, 0xc1, 0xf3, 0xc3, + /*42c0:*/ 0x38, 0x6a, 0xd3, 0x59, 0x31, 0x69, 0xfd, 0xd6, 0x9d, 0x26, 0x54, 0x44, 0x0e, 0x2b, 0xc5, 0x9a, + /*42d0:*/ 0x9f, 0x77, 0xb7, 0x73, 0x40, 0xc5, 0xa2, 0x46, 0x3b, 0xb9, 0xb6, 0xab, 0x58, 0x93, 0x88, 0x9c, + /*42e0:*/ 0xe5, 0xae, 0x1b, 0x90, 0xf8, 0xdf, 0xdf, 0xd6, 0x4d, 0x2e, 0x3b, 0xeb, 0x3a, 0x6f, 0xe3, 0x28, + /*42f0:*/ 0x73, 0x32, 0x71, 0xb3, 0x7c, 0xd8, 0x7a, 0xa2, 0xfc, 0x61, 0x56, 0x2c, 0x89, 0x63, 0x16, 0xbd, + /*4300:*/ 0xea, 0xd2, 0x49, 0x1b, 0x43, 0xcf, 0x2a, 0xce, 0xd2, 0x00, 0xe8, 0xef, 0x60, 0xf9, 0x9e, 0x41, + /*4310:*/ 0x23, 0xde, 0x64, 0xa1, 0x05, 0x64, 0x55, 0xdb, 0xb0, 0xac, 0x37, 0xd1, 0x41, 0xd4, 0xfa, 0xde, + /*4320:*/ 0x9c, 0x18, 0x46, 0x59, 0xac, 0x51, 0xc4, 0xd4, 0xb9, 0x4c, 0x35, 0xfa, 0xcd, 0xfd, 0x23, 0xde, + /*4330:*/ 0xa8, 0x5d, 0x7c, 0xdb, 0xa1, 0x1a, 0x99, 0x9d, 0x21, 0x12, 0x81, 0xa8, 0xd1, 0x20, 0xc2, 0xd4, + /*4340:*/ 0x6c, 0xe9, 0x8b, 0x16, 0x22, 0x55, 0x5b, 0x0e, 0x1d, 0xde, 0x36, 0x54, 0x96, 0x76, 0x51, 0x36, + /*4350:*/ 0x13, 0x4a, 0x9f, 0x0f, 0x42, 0x11, 0xb2, 0x8a, 0x69, 0xec, 0x5b, 0xbd, 0xbd, 0xe6, 0x90, 0x1d, + /*4360:*/ 0x6f, 0x36, 0x18, 0x6d, 0x71, 0x18, 0x6b, 0xa0, 0x08, 0x0c, 0x6a, 0xbd, 0xc9, 0xc9, 0x03, 0xbb, + /*4370:*/ 0x2b, 0x13, 0xc4, 0x81, 0xd4, 0x98, 0xaa, 0x33, 0xa7, 0x7c, 0x9d, 0x2a, 0xcf, 0xf4, 0xc8, 0x33, + /*4380:*/ 0xc8, 0x54, 0x80, 0x2e, 0x85, 0x05, 0xf3, 0x67, 0x34, 0x07, 0xe1, 0x5c, 0x49, 0x4a, 0x72, 0x7e, + /*4390:*/ 0x1b, 0x64, 0xc1, 0x66, 0xe8, 0x3d, 0x30, 0x38, 0x8c, 0x58, 0x3c, 0x0f, 0x64, 0x54, 0x9b, 0x1b, + /*43a0:*/ 0x5e, 0xb7, 0x87, 0x95, 0xf7, 0x92, 0xbe, 0x4c, 0x42, 0x03, 0x77, 0x74, 0xea, 0x9e, 0xf3, 0x92, + /*43b0:*/ 0x94, 0x0d, 0x47, 0x33, 0x23, 0x88, 0x74, 0x71, 0x47, 0xab, 0x1d, 0xd5, 0x92, 0x81, 0x73, 0x66, + /*43c0:*/ 0x62, 0xc3, 0x27, 0xe5, 0xe0, 0x84, 0xfa, 0xe4, 0x6a, 0x2e, 0x07, 0xea, 0xdb, 0x44, 0x24, 0xef, + /*43d0:*/ 0x8a, 0xb0, 0x5e, 0xb0, 0x61, 0x03, 0x9c, 0xf8, 0xc7, 0xc8, 0x34, 0x1b, 0x87, 0xc7, 0xf1, 0x3b, + /*43e0:*/ 0xb5, 0x7e, 0xb7, 0x37, 0x4d, 0x3a, 0xb7, 0x4b, 0x2e, 0x21, 0xe2, 0x3e, 0x0d, 0xe7, 0x07, 0x3c, + /*43f0:*/ 0x43, 0xb2, 0x6d, 0x87, 0xa9, 0x79, 0x96, 0x86, 0x0c, 0x0e, 0xbc, 0x0d, 0x5e, 0x5b, 0x9f, 0xbf, + /*4400:*/ 0xc0, 0xfe, 0x4b, 0x81, 0xa2, 0x91, 0x39, 0xf9, 0x59, 0xfa, 0x96, 0x80, 0x2a, 0x90, 0x13, 0x4c, + /*4410:*/ 0x4e, 0x08, 0x1e, 0xcc, 0xfe, 0x1f, 0x94, 0x2b, 0x1b, 0x3f, 0x80, 0xa2, 0x03, 0xc2, 0xee, 0x37, + /*4420:*/ 0x52, 0xa2, 0xb7, 0xfb, 0x2c, 0x42, 0xe6, 0xd9, 0x57, 0xa4, 0xdd, 0x41, 0x02, 0xfc, 0x9f, 0x40, + /*4430:*/ 0x62, 0xb8, 0xc6, 0x4b, 0x42, 0xe4, 0xd8, 0x50, 0x47, 0xad, 0xea, 0x55, 0x21, 0xe7, 0xbb, 0xa4, + /*4440:*/ 0xf5, 0x07, 0x70, 0x6f, 0xba, 0x7e, 0x30, 0x31, 0x03, 0x15, 0x9d, 0x44, 0x29, 0x16, 0xe0, 0x95, + /*4450:*/ 0x67, 0xf0, 0x4b, 0x27, 0x94, 0xaf, 0x48, 0x2f, 0x3d, 0xe8, 0x8c, 0x64, 0x47, 0x32, 0xa0, 0xb7, + /*4460:*/ 0x23, 0x27, 0xbf, 0xca, 0xdf, 0x6a, 0xc1, 0x41, 0x19, 0x82, 0xd4, 0x97, 0xee, 0x24, 0xbc, 0x65, + /*4470:*/ 0xd3, 0x8b, 0x10, 0xf8, 0x1b, 0x70, 0xe1, 0x5c, 0xeb, 0xa2, 0xa9, 0x89, 0x62, 0xec, 0xaa, 0xf6, + /*4480:*/ 0xb1, 0xda, 0xf9, 0xe5, 0x0c, 0x47, 0xa0, 0x06, 0x93, 0x6c, 0x54, 0xea, 0x48, 0x9d, 0x57, 0x90, + /*4490:*/ 0x8f, 0x5f, 0xd0, 0x6f, 0x97, 0x2a, 0x64, 0x46, 0x05, 0x22, 0x5a, 0xda, 0xbd, 0xb0, 0x47, 0x73, + /*44a0:*/ 0x62, 0x2c, 0x75, 0xcb, 0xed, 0x7d, 0x0b, 0x14, 0x30, 0xb3, 0x78, 0x4c, 0xe7, 0x9c, 0xaf, 0x9b, + /*44b0:*/ 0x7a, 0x97, 0xde, 0x12, 0xac, 0x5e, 0x6a, 0x96, 0xd7, 0xfd, 0x8c, 0x3f, 0xe8, 0xed, 0x61, 0x1d, + /*44c0:*/ 0x5e, 0xcf, 0xfb, 0xb9, 0x49, 0x80, 0xde, 0x1b, 0xb8, 0x12, 0x81, 0x5a, 0xdb, 0xd6, 0xb7, 0x0f, + /*44d0:*/ 0x50, 0xf5, 0x7e, 0xf8, 0xa6, 0xcc, 0xfa, 0x86, 0x25, 0xdb, 0xd1, 0xd1, 0xfb, 0x99, 0xbe, 0x28, + /*44e0:*/ 0x60, 0xc9, 0x83, 0xe6, 0x64, 0x56, 0xf6, 0x15, 0x8d, 0xf0, 0xad, 0xd2, 0x3f, 0x6f, 0x18, 0xe8, + /*44f0:*/ 0xee, 0x3c, 0x25, 0x52, 0x3f, 0x32, 0x29, 0x99, 0x36, 0xc2, 0x18, 0xb0, 0xea, 0xc5, 0x87, 0x60, + /*4500:*/ 0xda, 0xe4, 0x78, 0x89, 0xee, 0xaa, 0x9d, 0x4e, 0xfa, 0xca, 0xe1, 0xbe, 0xda, 0x46, 0x22, 0x28, + /*4510:*/ 0x13, 0x0e, 0xf1, 0x8e, 0x15, 0x6d, 0x68, 0x07, 0xc5, 0x0a, 0x41, 0x4f, 0x2d, 0xd6, 0x0c, 0x89, + /*4520:*/ 0x13, 0x5b, 0x79, 0x46, 0x0e, 0x14, 0x4d, 0x8a, 0xb1, 0xe0, 0x6e, 0xcc, 0x46, 0xa2, 0x35, 0xa6, + /*4530:*/ 0xf0, 0x61, 0x80, 0xe8, 0xd0, 0x24, 0xab, 0x1d, 0xa4, 0x28, 0x93, 0xb8, 0x87, 0xa5, 0xd0, 0xe4, + /*4540:*/ 0x9c, 0xfd, 0x29, 0x75, 0x8e, 0x85, 0x20, 0x25, 0xcb, 0xbb, 0x21, 0x20, 0xf9, 0x31, 0x07, 0xaf, + /*4550:*/ 0x5d, 0xf7, 0xc1, 0x7f, 0x89, 0xad, 0xab, 0xbf, 0x65, 0xf8, 0x71, 0xb0, 0x7f, 0xd2, 0xad, 0xd1, + /*4560:*/ 0x51, 0x48, 0x9f, 0xf0, 0xaa, 0xc0, 0xde, 0x60, 0x40, 0xe4, 0x2b, 0xb5, 0x0e, 0x24, 0xdd, 0xfa, + /*4570:*/ 0x0f, 0x52, 0xc3, 0x6e, 0xcc, 0xa2, 0xb9, 0x32, 0x30, 0x92, 0x24, 0x51, 0xb9, 0xff, 0x7d, 0xef, + /*4580:*/ 0x5b, 0x6c, 0xf2, 0xde, 0x08, 0x11, 0x94, 0x52, 0xac, 0x53, 0xd3, 0xc5, 0x97, 0xd6, 0xd2, 0x78, + /*4590:*/ 0x1c, 0x70, 0xea, 0xd8, 0x81, 0x7f, 0xd6, 0x3b, 0x27, 0x6f, 0x94, 0x59, 0x98, 0xcf, 0x5d, 0x06, + /*45a0:*/ 0x9b, 0x97, 0x47, 0xf9, 0x4f, 0x50, 0xb9, 0x56, 0x36, 0xb5, 0xb6, 0xb9, 0xe3, 0xe2, 0xce, 0x63, + /*45b0:*/ 0x0c, 0x3f, 0xc5, 0xe1, 0xde, 0x8f, 0xcb, 0x8b, 0x36, 0x8d, 0x8d, 0xb9, 0xa6, 0xfb, 0x1b, 0xe4, + /*45c0:*/ 0xe9, 0xea, 0xd0, 0xf0, 0x75, 0x2e, 0x75, 0x58, 0xfc, 0x48, 0x49, 0xad, 0x97, 0x3e, 0xc8, 0xdd, + /*45d0:*/ 0x12, 0x78, 0x79, 0xd1, 0xdc, 0xd7, 0x49, 0x05, 0x65, 0x64, 0x26, 0x9e, 0x00, 0xf5, 0x2b, 0xc2, + /*45e0:*/ 0x03, 0x74, 0xb3, 0x23, 0x74, 0xd5, 0xb4, 0x4b, 0xb4, 0x6e, 0x0e, 0x1e, 0xb3, 0xae, 0x14, 0xe2, + /*45f0:*/ 0xe8, 0xfb, 0xc2, 0xf6, 0xd5, 0x99, 0xd2, 0x90, 0x27, 0x13, 0xf9, 0x20, 0x7b, 0xd0, 0x76, 0x95, + /*4600:*/ 0x67, 0x45, 0x7a, 0x9b, 0x3c, 0x41, 0xc0, 0x6e, 0x6c, 0x2f, 0x0a, 0xe9, 0xcc, 0xa5, 0x8b, 0x41, + /*4610:*/ 0x8c, 0x27, 0xd6, 0xce, 0xde, 0x8f, 0x02, 0xd3, 0xad, 0xd5, 0x88, 0x19, 0xbb, 0xeb, 0xb8, 0x3c, + /*4620:*/ 0x45, 0xea, 0xff, 0xe8, 0x10, 0x93, 0xaf, 0xab, 0x24, 0xff, 0x10, 0x8e, 0x60, 0x92, 0x88, 0x0c, + /*4630:*/ 0x42, 0x17, 0xf4, 0x42, 0xbc, 0x7e, 0xfe, 0xbf, 0x14, 0x09, 0x6f, 0xff, 0xa2, 0x42, 0x43, 0x97, + /*4640:*/ 0x5f, 0x24, 0xae, 0xa1, 0xcf, 0x48, 0xe6, 0x35, 0x3f, 0x12, 0x55, 0x38, 0x0a, 0x91, 0x05, 0x46, + /*4650:*/ 0x9d, 0x80, 0xb3, 0x75, 0x24, 0x64, 0x19, 0x8e, 0xea, 0x65, 0x94, 0x22, 0xfe, 0x6c, 0xa4, 0x82, + /*4660:*/ 0x16, 0x96, 0x7f, 0x57, 0x4b, 0x72, 0x54, 0x9e, 0x84, 0x22, 0x06, 0x64, 0x24, 0xe1, 0x50, 0xc7, + /*4670:*/ 0x78, 0xb8, 0xa4, 0xb4, 0xfe, 0x60, 0xa1, 0x0c, 0xf6, 0xba, 0xdd, 0x93, 0x0f, 0xf5, 0x36, 0xe2, + /*4680:*/ 0xb6, 0x9c, 0xd3, 0xc8, 0x96, 0xb4, 0xd2, 0x02, 0x38, 0x42, 0x9a, 0x2f, 0x1b, 0x46, 0xd2, 0x20, + /*4690:*/ 0xc6, 0x90, 0xd5, 0xd4, 0x42, 0xf0, 0xd5, 0x14, 0xd1, 0xb1, 0xec, 0x02, 0x41, 0x25, 0xbb, 0x35, + /*46a0:*/ 0x0b, 0x9a, 0x66, 0x1d, 0xc8, 0xf9, 0xc1, 0x6a, 0x59, 0xfc, 0xc5, 0x57, 0xda, 0xdf, 0xe2, 0x8a, + /*46b0:*/ 0x8b, 0x1b, 0x21, 0x1d, 0x45, 0x76, 0x57, 0x8a, 0x0c, 0xd8, 0x21, 0xa0, 0x34, 0x42, 0xeb, 0xa7, + /*46c0:*/ 0x01, 0x62, 0x5f, 0x5d, 0xf5, 0x12, 0x44, 0x42, 0x4a, 0xb1, 0x2c, 0x9a, 0x44, 0x79, 0x9e, 0x6b, + /*46d0:*/ 0xde, 0xbf, 0x13, 0x8c, 0x22, 0x4f, 0xe7, 0x50, 0xd4, 0x0a, 0x18, 0x4f, 0x50, 0xf0, 0xbb, 0x16, + /*46e0:*/ 0xf5, 0x57, 0x2c, 0xd8, 0x66, 0x3f, 0x83, 0x62, 0xe8, 0x5a, 0xd4, 0x05, 0x67, 0xe0, 0xa7, 0x40, + /*46f0:*/ 0x08, 0xc3, 0x9e, 0x5b, 0xbb, 0x3a, 0xd3, 0x44, 0x15, 0xa6, 0xb3, 0x12, 0xea, 0x89, 0xd9, 0xbc, + /*4700:*/ 0xc1, 0xc8, 0x01, 0x39, 0x1c, 0xc7, 0xc0, 0xfa, 0xea, 0x85, 0xf9, 0x27, 0xe9, 0x10, 0x93, 0x49, + /*4710:*/ 0x5e, 0xa2, 0xb2, 0x40, 0xf3, 0x6f, 0xd1, 0xfb, 0x67, 0xfa, 0x1e, 0x44, 0xc5, 0x7d, 0x49, 0xbe, + /*4720:*/ 0xeb, 0xff, 0x2b, 0x0d, 0xcd, 0x82, 0xd5, 0x42, 0xd1, 0xf2, 0x26, 0x78, 0x8e, 0xec, 0x67, 0x01, + /*4730:*/ 0xb0, 0x5f, 0x0b, 0x28, 0x59, 0x49, 0x8d, 0x2d, 0x77, 0x30, 0x77, 0xfb, 0xf0, 0x1b, 0x1a, 0x83, + /*4740:*/ 0x93, 0x22, 0x0c, 0x92, 0xa5, 0x74, 0xbb, 0xe2, 0xa6, 0xe5, 0x9e, 0x86, 0x6c, 0x34, 0xee, 0x28, + /*4750:*/ 0xec, 0x81, 0xdc, 0x1f, 0x78, 0x54, 0x2c, 0x5a, 0xe6, 0xdf, 0x37, 0x61, 0xd1, 0x9b, 0x75, 0x87, + /*4760:*/ 0xc8, 0xe7, 0x9e, 0x1a, 0x26, 0x82, 0x16, 0xaa, 0x4e, 0x0a, 0xfc, 0xc1, 0xa6, 0xf3, 0xb6, 0xaf, + /*4770:*/ 0x1f, 0xff, 0xc2, 0xb4, 0xb7, 0x33, 0x13, 0xb3, 0xc4, 0xc7, 0x7d, 0xb1, 0xd3, 0x69, 0x5c, 0x8e, + /*4780:*/ 0xe7, 0x49, 0x52, 0x47, 0x16, 0x28, 0x14, 0x4a, 0x54, 0xb5, 0xe3, 0xa8, 0x62, 0x2d, 0x22, 0xb1, + /*4790:*/ 0x78, 0xe2, 0x15, 0x63, 0x6f, 0x0f, 0x7e, 0x5c, 0x3b, 0xc3, 0x12, 0xfd, 0x67, 0x62, 0x24, 0x12, + /*47a0:*/ 0x96, 0x75, 0x30, 0x87, 0x77, 0x81, 0x49, 0xa8, 0x95, 0x3b, 0x94, 0xb8, 0x32, 0x24, 0x65, 0xe5, + /*47b0:*/ 0xd7, 0x05, 0x07, 0xf4, 0xa2, 0xc7, 0x67, 0x1d, 0x0a, 0xc4, 0xee, 0x25, 0xf9, 0x6a, 0xc2, 0xf3, + /*47c0:*/ 0x06, 0xd9, 0xcc, 0x48, 0x0f, 0x85, 0xb0, 0x93, 0xdb, 0x27, 0x46, 0xfe, 0xc7, 0x8d, 0xcb, 0x02, + /*47d0:*/ 0xd5, 0xad, 0x0c, 0x18, 0xc1, 0x19, 0xab, 0xd5, 0xd9, 0xbf, 0x7a, 0xfe, 0xc1, 0x27, 0x80, 0xca, + /*47e0:*/ 0xca, 0x14, 0x1f, 0x4f, 0x64, 0xfb, 0xe5, 0x03, 0x28, 0x16, 0xa2, 0xc9, 0x09, 0x93, 0xdd, 0x40, + /*47f0:*/ 0xc3, 0x2f, 0x46, 0xd5, 0xcf, 0x29, 0xe0, 0x9c, 0xab, 0x0a, 0x5b, 0xab, 0xbd, 0x0e, 0x28, 0x16, + /*4800:*/ 0xc6, 0x5d, 0x3f, 0x5e, 0x41, 0x5a, 0x35, 0xd0, 0x3b, 0x9f, 0x49, 0x25, 0x00, 0x4b, 0x81, 0xda, + /*4810:*/ 0x04, 0xd4, 0x03, 0xe3, 0xd8, 0xb3, 0x51, 0xba, 0x4c, 0xe2, 0x1c, 0xb8, 0x9a, 0xaa, 0x0d, 0x00, + /*4820:*/ 0x21, 0x93, 0x0a, 0xcb, 0xa4, 0x1e, 0xf9, 0x50, 0x9f, 0xf0, 0xa3, 0x01, 0x84, 0xf1, 0xcf, 0x7f, + /*4830:*/ 0x93, 0x19, 0xbd, 0x53, 0x0c, 0xd1, 0x89, 0xe6, 0x2f, 0x10, 0x80, 0x91, 0x33, 0xb7, 0x99, 0xaa, + /*4840:*/ 0xe1, 0x26, 0xf7, 0xde, 0x76, 0x09, 0xf6, 0x45, 0x89, 0x33, 0xd0, 0xf0, 0xf8, 0xf6, 0xd4, 0x59, + /*4850:*/ 0x94, 0xf9, 0x06, 0xe5, 0x7c, 0xb4, 0x61, 0xac, 0x2f, 0x9a, 0x8e, 0x2d, 0x28, 0x37, 0x11, 0x3a, + /*4860:*/ 0x1d, 0xf7, 0x06, 0x79, 0x52, 0x8b, 0xa9, 0xd9, 0xa8, 0x89, 0xfc, 0xb4, 0xbf, 0xbe, 0x56, 0xfd, + /*4870:*/ 0x8a, 0x62, 0x89, 0x21, 0x6a, 0x58, 0x03, 0x22, 0x43, 0x56, 0x33, 0xca, 0x3e, 0x2a, 0x87, 0x66, + /*4880:*/ 0x16, 0xda, 0xb5, 0x96, 0x51, 0x86, 0xb9, 0x7e, 0x6d, 0xb5, 0xb5, 0xb2, 0x57, 0x5b, 0x75, 0xd5, + /*4890:*/ 0xd5, 0xc2, 0x72, 0x7b, 0x9e, 0xa5, 0xab, 0x45, 0x71, 0x77, 0x87, 0xc8, 0xb7, 0x0d, 0xbd, 0xea, + /*48a0:*/ 0x29, 0xd1, 0xc3, 0x15, 0x55, 0xa5, 0x16, 0x4c, 0x38, 0xa8, 0x86, 0x66, 0xd5, 0x7a, 0xf4, 0x47, + /*48b0:*/ 0x63, 0xb5, 0x01, 0x99, 0xec, 0xbb, 0x7e, 0x72, 0x4d, 0x6c, 0x49, 0x55, 0xde, 0xc1, 0xfa, 0xd9, + /*48c0:*/ 0x34, 0x60, 0x48, 0x48, 0x14, 0x9d, 0xb9, 0x9e, 0x5f, 0x2b, 0x7b, 0xbd, 0x68, 0x6a, 0xb2, 0x6d, + /*48d0:*/ 0xc6, 0x0b, 0x89, 0xbb, 0x84, 0xdd, 0x33, 0x5c, 0xc1, 0x36, 0x5e, 0xeb, 0x71, 0x39, 0x32, 0xd3, + /*48e0:*/ 0xdf, 0xdd, 0xd4, 0x46, 0x8d, 0x63, 0xaa, 0xea, 0x47, 0xc4, 0x15, 0x01, 0xe3, 0x37, 0xfc, 0x91, + /*48f0:*/ 0x92, 0xca, 0x90, 0xb5, 0xa0, 0x8d, 0xd7, 0xdb, 0x7a, 0xe2, 0x9d, 0x82, 0x7f, 0xb7, 0x40, 0x72, + /*4900:*/ 0xfb, 0x5e, 0xc9, 0x5a, 0xf9, 0xcf, 0xa8, 0x9f, 0x42, 0xa6, 0x66, 0xa6, 0x91, 0x41, 0x6c, 0xf8, + /*4910:*/ 0x59, 0xbf, 0x9e, 0xbb, 0x62, 0xab, 0x05, 0x1f, 0x19, 0x6e, 0x5f, 0x23, 0x48, 0x85, 0xa7, 0xaf, + /*4920:*/ 0xeb, 0x26, 0x7f, 0xb3, 0x42, 0xfe, 0x37, 0xd6, 0xa0, 0x9f, 0x47, 0xb3, 0x3a, 0x05, 0x6c, 0x78, + /*4930:*/ 0x08, 0x5d, 0xaa, 0x19, 0x37, 0xff, 0x69, 0x0d, 0x96, 0x2a, 0xd2, 0x8a, 0x0d, 0x7f, 0xbf, 0x5b, + /*4940:*/ 0x26, 0x40, 0x3e, 0x47, 0x30, 0xb5, 0xc1, 0x48, 0xa5, 0x4e, 0x76, 0xae, 0x8d, 0xba, 0x5b, 0x0b, + /*4950:*/ 0x22, 0xef, 0xdf, 0xa5, 0x33, 0xc6, 0xe9, 0x79, 0x5d, 0x1e, 0x6a, 0xec, 0xa2, 0xa6, 0xfa, 0x5f, + /*4960:*/ 0xac, 0x42, 0x67, 0x60, 0x06, 0x65, 0x6b, 0xf2, 0x3d, 0xbf, 0x92, 0x54, 0xfb, 0xe8, 0x7e, 0x1a, + /*4970:*/ 0xb5, 0x9b, 0x57, 0x86, 0x21, 0xc4, 0x80, 0x50, 0x54, 0xe7, 0xfc, 0x10, 0x9c, 0xb5, 0xde, 0x50, + /*4980:*/ 0x13, 0x92, 0x3a, 0x85, 0x09, 0xd3, 0x02, 0xa2, 0xf0, 0x38, 0xf0, 0x6d, 0x98, 0x9a, 0x59, 0x92, + /*4990:*/ 0xad, 0x89, 0x0d, 0xfd, 0xdf, 0x84, 0xbb, 0x77, 0x2d, 0x4c, 0xbb, 0x8c, 0xa5, 0xe2, 0xea, 0x45, + /*49a0:*/ 0xfd, 0x40, 0x07, 0xbc, 0xa0, 0xf0, 0x84, 0x48, 0x17, 0xd2, 0x58, 0x94, 0xbf, 0x89, 0x04, 0x7e, + /*49b0:*/ 0x6e, 0xc9, 0x7a, 0xcc, 0x4a, 0x65, 0xf7, 0xb4, 0xf4, 0x2f, 0xae, 0x6e, 0xae, 0x7f, 0x1c, 0xa7, + /*49c0:*/ 0xda, 0xce, 0x73, 0xda, 0x7c, 0x9c, 0xed, 0x7c, 0x5c, 0xc6, 0x56, 0x8b, 0xc7, 0xc1, 0x53, 0xb4, + /*49d0:*/ 0x5a, 0x30, 0x70, 0x09, 0xd7, 0xdd, 0x20, 0xd0, 0x2a, 0x47, 0x82, 0xb2, 0xa1, 0xd5, 0x69, 0x0a, + /*49e0:*/ 0xc1, 0xf8, 0xe9, 0x69, 0x60, 0x17, 0x3f, 0x4c, 0x79, 0x92, 0x33, 0x16, 0x92, 0xbf, 0x4a, 0x73, + /*49f0:*/ 0x7f, 0x0a, 0xd1, 0x96, 0x83, 0x53, 0x1c, 0x01, 0x01, 0x5d, 0xe4, 0xf1, 0xe3, 0xa1, 0xc4, 0x91, + /*4a00:*/ 0x71, 0x14, 0xbf, 0x60, 0x5a, 0xf5, 0x95, 0x0a, 0x45, 0x35, 0x39, 0x81, 0xea, 0xd4, 0x66, 0x69, + /*4a10:*/ 0xa6, 0x12, 0x6d, 0xa8, 0xb8, 0x32, 0x92, 0x1b, 0xa4, 0x59, 0x46, 0x6c, 0x8c, 0xed, 0xc0, 0x4c, + /*4a20:*/ 0x55, 0x99, 0xb3, 0xc1, 0x51, 0xfa, 0x30, 0xf0, 0x54, 0x2f, 0x6e, 0x7d, 0xbc, 0xb3, 0x9a, 0x9d, + /*4a30:*/ 0x27, 0x42, 0x30, 0xbf, 0x0e, 0x41, 0x87, 0x65, 0x70, 0x10, 0xbc, 0xf1, 0x4b, 0x3e, 0x64, 0x48, + /*4a40:*/ 0x88, 0xfb, 0xfa, 0x1b, 0x9a, 0xcb, 0xf5, 0xf7, 0x5c, 0xf8, 0xcc, 0xb2, 0xad, 0xc7, 0x96, 0x16, + /*4a50:*/ 0x36, 0xe4, 0x8c, 0x23, 0x21, 0x38, 0x60, 0x6c, 0x6d, 0xaa, 0xef, 0xc9, 0x26, 0xde, 0x1f, 0x17, + /*4a60:*/ 0xad, 0x4a, 0xa6, 0xbb, 0xcb, 0xce, 0x76, 0x40, 0x5e, 0x86, 0xdb, 0x97, 0x1f, 0x70, 0x86, 0xf7, + /*4a70:*/ 0x8f, 0xf8, 0x11, 0x39, 0x03, 0xc7, 0x0c, 0xcc, 0x71, 0x29, 0x00, 0x2a, 0x4e, 0x62, 0x49, 0xad, + /*4a80:*/ 0xb0, 0xfa, 0xfb, 0x80, 0x2e, 0xe8, 0x70, 0x73, 0x57, 0x42, 0xd3, 0xc0, 0x68, 0x7e, 0xaa, 0x0a, + /*4a90:*/ 0xdb, 0x99, 0x89, 0x07, 0x8a, 0x6d, 0x4c, 0x9c, 0xbc, 0x33, 0x4f, 0xee, 0x7f, 0x27, 0x45, 0x0f, + /*4aa0:*/ 0x7f, 0x16, 0xcb, 0x5b, 0xd7, 0x88, 0x9a, 0xbf, 0x4b, 0x98, 0x01, 0x1c, 0xaf, 0x06, 0x7f, 0x1e, + /*4ab0:*/ 0x4d, 0x07, 0x70, 0xb8, 0x7f, 0xac, 0xbb, 0x79, 0xc3, 0x10, 0x01, 0xbc, 0x43, 0x97, 0x46, 0x38, + /*4ac0:*/ 0x6e, 0x96, 0x82, 0x31, 0xe6, 0x2e, 0xa0, 0x56, 0xd6, 0xfa, 0xce, 0x3c, 0x43, 0xcd, 0xfe, 0x63, + /*4ad0:*/ 0x3d, 0xd8, 0x48, 0x28, 0x8d, 0x80, 0xb8, 0xe3, 0xfd, 0x3b, 0x74, 0x90, 0xbd, 0x64, 0x2d, 0x3f, + /*4ae0:*/ 0x18, 0x94, 0x39, 0x9c, 0x52, 0x8a, 0x6b, 0x88, 0x7b, 0xd2, 0xa7, 0x89, 0x16, 0x7b, 0x89, 0x45, + /*4af0:*/ 0xdd, 0x0e, 0xf1, 0xc7, 0xc4, 0x9b, 0xb8, 0x90, 0xb8, 0x97, 0x93, 0x4f, 0x98, 0x49, 0xef, 0xef, + /*4b00:*/ 0x0a, 0x78, 0xc9, 0xaf, 0xc3, 0xe2, 0xb6, 0x9c, 0x22, 0x69, 0x8b, 0x86, 0xff, 0x76, 0x04, 0x60, + /*4b10:*/ 0xab, 0x35, 0x92, 0x1c, 0xa8, 0xac, 0xdd, 0x99, 0x09, 0xdf, 0x97, 0xfe, 0x25, 0x86, 0x0a, 0x43, + /*4b20:*/ 0xdd, 0x5c, 0xee, 0x40, 0xdf, 0x68, 0x7b, 0x87, 0x70, 0xd0, 0x45, 0xa9, 0x9c, 0xd8, 0x19, 0xca, + /*4b30:*/ 0xfd, 0x08, 0x4a, 0xfc, 0x26, 0xfb, 0xb0, 0x3d, 0xab, 0xf9, 0x04, 0x77, 0x26, 0xc9, 0x18, 0x45, + /*4b40:*/ 0xdf, 0xf5, 0xed, 0x8a, 0xb6, 0x9a, 0x08, 0x2d, 0xa9, 0xb3, 0xd1, 0xea, 0x82, 0xfd, 0x5c, 0xbf, + /*4b50:*/ 0x32, 0x90, 0xc7, 0x2d, 0x01, 0xf9, 0x56, 0xb0, 0x6b, 0xfe, 0x7a, 0xe2, 0x03, 0x90, 0x48, 0x60, + /*4b60:*/ 0xdc, 0x0b, 0xc9, 0x2f, 0x95, 0xe6, 0x0b, 0x73, 0xb5, 0xeb, 0x3d, 0xfe, 0xbe, 0x7e, 0x89, 0x24, + /*4b70:*/ 0x15, 0x68, 0x08, 0x86, 0x38, 0xad, 0x27, 0x55, 0x9a, 0x56, 0x58, 0x06, 0x0a, 0x4b, 0x78, 0xde, + /*4b80:*/ 0x94, 0xb0, 0xa5, 0x95, 0x10, 0x85, 0x63, 0x8e, 0xcb, 0xd2, 0x26, 0x35, 0x14, 0xa3, 0x1d, 0xd8, + /*4b90:*/ 0x62, 0xc0, 0x42, 0x4c, 0xa4, 0xad, 0x9e, 0x59, 0x50, 0xf8, 0xcf, 0x55, 0xb8, 0x01, 0xfe, 0x68, + /*4ba0:*/ 0x92, 0x08, 0x8b, 0x8d, 0xd8, 0xab, 0x1d, 0xed, 0xec, 0x01, 0xbc, 0xf5, 0xe3, 0x7c, 0x5c, 0x13, + /*4bb0:*/ 0xef, 0x7d, 0x14, 0x21, 0xd1, 0x8e, 0x9b, 0xe4, 0x34, 0x78, 0x59, 0x45, 0x9c, 0x86, 0x37, 0xc2, + /*4bc0:*/ 0x24, 0xd1, 0xeb, 0x14, 0x83, 0x0a, 0x80, 0xde, 0x45, 0xa1, 0x17, 0x41, 0xd1, 0x36, 0x1e, 0x95, + /*4bd0:*/ 0x4d, 0x00, 0x13, 0x2d, 0x15, 0x7d, 0x4b, 0x52, 0x90, 0x32, 0x12, 0xc2, 0x7d, 0x72, 0xaa, 0x2a, + /*4be0:*/ 0x16, 0x54, 0x08, 0xb7, 0x2b, 0x86, 0xa5, 0xa6, 0x62, 0x2c, 0x8a, 0x0d, 0xd8, 0x50, 0x89, 0xf9, + /*4bf0:*/ 0xb2, 0x52, 0xd2, 0xd9, 0xa2, 0xa3, 0x21, 0x14, 0x87, 0x89, 0xe1, 0xe7, 0xce, 0xf0, 0x5f, 0xd8, + /*4c00:*/ 0x75, 0x61, 0xd6, 0x66, 0xcf, 0xda, 0x00, 0x21, 0xa6, 0xf0, 0xb4, 0x41, 0xcf, 0xf4, 0x71, 0x51, + /*4c10:*/ 0xba, 0x27, 0x32, 0x7c, 0x3c, 0xb6, 0xc8, 0x29, 0x53, 0x1f, 0xc5, 0xc1, 0xfd, 0x9f, 0xa8, 0x08, + /*4c20:*/ 0x30, 0x51, 0x7f, 0xf6, 0x8b, 0x6a, 0xa2, 0xbe, 0xd4, 0xf5, 0x15, 0xaf, 0x49, 0x19, 0xb9, 0x8e, + /*4c30:*/ 0x19, 0xfc, 0x70, 0x0c, 0x28, 0xdc, 0xee, 0x85, 0xb7, 0x5b, 0xde, 0x02, 0xdd, 0x85, 0x8c, 0x9b, + /*4c40:*/ 0x78, 0x13, 0x35, 0x1b, 0xd2, 0xe8, 0xcf, 0x9a, 0xc1, 0x3d, 0x21, 0xa2, 0xc5, 0x34, 0xdd, 0x9e, + /*4c50:*/ 0x6f, 0xeb, 0xc4, 0x82, 0x18, 0xd8, 0x5a, 0x31, 0x4a, 0x75, 0x45, 0xc9, 0x6f, 0x56, 0x63, 0x1f, + /*4c60:*/ 0xc9, 0x4d, 0x35, 0x74, 0x58, 0x31, 0xf1, 0x3e, 0xd7, 0xc5, 0x95, 0xf7, 0x29, 0x4f, 0x24, 0xf7, + /*4c70:*/ 0xd9, 0xba, 0xb6, 0x43, 0x34, 0x69, 0x34, 0x04, 0xf0, 0xac, 0x4c, 0x08, 0xed, 0xf9, 0xf4, 0xe3, + /*4c80:*/ 0xdc, 0xc5, 0x3e, 0x4f, 0x65, 0xde, 0xba, 0xb3, 0xaf, 0x6f, 0x1a, 0x1f, 0x21, 0x00, 0x80, 0xc2, + /*4c90:*/ 0x7c, 0x54, 0x55, 0x35, 0x05, 0x23, 0x65, 0x8c, 0x1a, 0x19, 0x2e, 0xd8, 0x4f, 0xfb, 0xb9, 0xfa, + /*4ca0:*/ 0x73, 0x5f, 0x33, 0x0e, 0xfb, 0x32, 0xf5, 0x84, 0x5e, 0xd1, 0x5d, 0x0c, 0x6d, 0x6b, 0x06, 0xc6, + /*4cb0:*/ 0x09, 0x5b, 0x14, 0x40, 0x84, 0x68, 0xca, 0x4e, 0xf3, 0xd0, 0xe0, 0x98, 0x86, 0xbe, 0xb8, 0x60, + /*4cc0:*/ 0x8c, 0xf6, 0xf3, 0x0e, 0xec, 0x70, 0xea, 0x53, 0x19, 0x2c, 0xfb, 0x69, 0x00, 0x37, 0x06, 0x36, + /*4cd0:*/ 0x3b, 0xee, 0xf1, 0x9e, 0xcb, 0xdb, 0x03, 0x00, 0x25, 0x35, 0xa1, 0x7b, 0xb2, 0x79, 0xce, 0x53, + /*4ce0:*/ 0xfe, 0xcb, 0x3c, 0x99, 0xde, 0x50, 0x5a, 0x26, 0xa0, 0xe4, 0x28, 0x96, 0xf6, 0x8d, 0x30, 0x97, + /*4cf0:*/ 0xcd, 0x6e, 0xbb, 0xb0, 0x70, 0x29, 0x60, 0xe8, 0x48, 0x1b, 0xe9, 0xfb, 0xa4, 0x29, 0xea, 0x52, + /*4d00:*/ 0x8f, 0x76, 0x77, 0x1a, 0xdb, 0xcd, 0x39, 0x7a, 0xcf, 0x9d, 0x66, 0xf3, 0x06, 0x9a, 0xb9, 0x80, + /*4d10:*/ 0xb7, 0xe7, 0xab, 0xbd, 0xe3, 0xbe, 0x33, 0xb2, 0x3a, 0x4b, 0x43, 0xc5, 0xa8, 0x91, 0x1c, 0xba, + /*4d20:*/ 0x89, 0xd4, 0x2b, 0xba, 0xfb, 0x91, 0xe0, 0x27, 0xf5, 0x57, 0xd8, 0x2d, 0x7b, 0xad, 0x3d, 0x0d, + /*4d30:*/ 0x2c, 0x21, 0xf8, 0x3a, 0x6a, 0x86, 0xbf, 0x66, 0x35, 0xb2, 0x3a, 0x55, 0xb7, 0x41, 0xf2, 0x8c, + /*4d40:*/ 0x82, 0x2f, 0xf9, 0x36, 0x5e, 0x63, 0xfe, 0x15, 0x23, 0x61, 0xa4, 0xee, 0x53, 0x45, 0xd3, 0xdc, + /*4d50:*/ 0xc5, 0x1b, 0xce, 0xb7, 0x3c, 0x23, 0x6d, 0x40, 0xa1, 0x28, 0x05, 0x0f, 0xd0, 0xb8, 0x9b, 0x48, + /*4d60:*/ 0xb3, 0xe1, 0x91, 0xe1, 0x0e, 0xe5, 0xd3, 0x7e, 0xaa, 0x7a, 0xad, 0xa1, 0xcb, 0xa9, 0x06, 0x4a, + /*4d70:*/ 0x22, 0x57, 0xa1, 0x7b, 0xd9, 0xf5, 0x09, 0x48, 0x09, 0x34, 0x88, 0xcf, 0xfd, 0xf8, 0xdd, 0x3d, + /*4d80:*/ 0xc2, 0x7c, 0x5b, 0x36, 0xb0, 0x53, 0x2f, 0x5f, 0x41, 0x3e, 0x15, 0x71, 0xb0, 0x06, 0x18, 0x68, + /*4d90:*/ 0x64, 0xc8, 0xdb, 0xab, 0x4a, 0x1f, 0xc0, 0x24, 0xd1, 0x4c, 0x59, 0xe8, 0x9e, 0xce, 0x10, 0x16, + /*4da0:*/ 0x68, 0x1f, 0x70, 0x1f, 0x31, 0xde, 0xa3, 0xe2, 0x20, 0xbb, 0xfc, 0x93, 0xa6, 0x43, 0x23, 0xea, + /*4db0:*/ 0x3a, 0x45, 0xe5, 0x93, 0x80, 0x92, 0x43, 0x5b, 0x05, 0x3d, 0x65, 0xe2, 0xbf, 0x56, 0x3f, 0x26, + /*4dc0:*/ 0x82, 0x0b, 0x1e, 0xd4, 0x46, 0x3a, 0x7a, 0x5a, 0x44, 0x91, 0x7e, 0x38, 0x3b, 0x6a, 0x17, 0xaf, + /*4dd0:*/ 0xc5, 0x5a, 0xb2, 0x68, 0xce, 0x68, 0x9c, 0x3c, 0x71, 0xc9, 0xde, 0xaa, 0x9b, 0xee, 0xd3, 0x50, + /*4de0:*/ 0x3c, 0xfd, 0xd8, 0x82, 0xc2, 0x6b, 0x92, 0x1a, 0xf9, 0x0c, 0x65, 0x20, 0x96, 0xc2, 0xd4, 0x2c, + /*4df0:*/ 0x0e, 0x89, 0x9d, 0xc7, 0xe0, 0xb9, 0x9b, 0x12, 0xad, 0xea, 0x0d, 0x97, 0x24, 0x99, 0xbe, 0x81, + /*4e00:*/ 0x08, 0x1f, 0x19, 0x70, 0x7f, 0x12, 0x9b, 0x46, 0x6b, 0xe3, 0xaf, 0x0b, 0xbb, 0xdd, 0xf9, 0xee, + /*4e10:*/ 0xfc, 0x40, 0x5b, 0x60, 0xb7, 0x9e, 0x00, 0xfe, 0x83, 0xca, 0x02, 0x31, 0xdb, 0x0a, 0x1a, 0xbe, + /*4e20:*/ 0xf1, 0x5f, 0xf9, 0x4f, 0xce, 0x03, 0x8c, 0xed, 0x31, 0x22, 0xaa, 0xcd, 0xa5, 0x34, 0xf5, 0xb2, + /*4e30:*/ 0x68, 0xad, 0x3e, 0xb4, 0x80, 0xa9, 0x11, 0x32, 0x56, 0x4d, 0xd6, 0x34, 0xe0, 0x3c, 0xf3, 0x49, + /*4e40:*/ 0x67, 0x5c, 0x8a, 0xf2, 0x08, 0xbf, 0x48, 0xac, 0xc1, 0x85, 0xa7, 0xfe, 0xcd, 0x8f, 0x46, 0x3c, + /*4e50:*/ 0xd5, 0x49, 0xfe, 0xf3, 0x9c, 0x61, 0x20, 0xd6, 0x16, 0x53, 0xfe, 0x67, 0x1d, 0x74, 0x44, 0x43, + /*4e60:*/ 0xab, 0x01, 0x7a, 0x1f, 0xdf, 0x83, 0x51, 0xbb, 0x25, 0xfc, 0xd7, 0x22, 0x94, 0x22, 0x03, 0x6c, + /*4e70:*/ 0x66, 0xa3, 0xa4, 0x0e, 0x19, 0x39, 0xd4, 0x9b, 0xfb, 0x4e, 0x37, 0x9d, 0x0d, 0xef, 0x7f, 0x7c, + /*4e80:*/ 0x08, 0x6b, 0xff, 0xbc, 0xab, 0xd9, 0xfe, 0xd9, 0x37, 0xd5, 0x8e, 0x5f, 0x33, 0xa3, 0xf1, 0xa4, + /*4e90:*/ 0x14, 0x77, 0xdb, 0x2b, 0xda, 0x8e, 0x5f, 0xb0, 0x33, 0x70, 0x6d, 0xd7, 0x84, 0xbf, 0xe5, 0x76, + /*4ea0:*/ 0xc3, 0xed, 0x1b, 0x34, 0xaa, 0xc1, 0x8d, 0x91, 0xf9, 0x44, 0x9b, 0xb7, 0x40, 0x92, 0x5d, 0xf3, + /*4eb0:*/ 0x3f, 0xe0, 0xb2, 0x34, 0x6b, 0x43, 0xc2, 0x04, 0xf5, 0x22, 0x95, 0xf5, 0xf6, 0x0a, 0x0d, 0x3c, + /*4ec0:*/ 0x51, 0xde, 0xa5, 0x32, 0x85, 0x29, 0x49, 0xd2, 0x37, 0x97, 0x44, 0x8f, 0x09, 0x49, 0xb7, 0xcb, + /*4ed0:*/ 0x76, 0xb5, 0x5d, 0x27, 0x24, 0x08, 0xb0, 0x73, 0x6d, 0xd5, 0xce, 0x44, 0xe2, 0xbf, 0x5a, 0xa1, + /*4ee0:*/ 0x52, 0x19, 0xdd, 0x09, 0xc1, 0x8c, 0x04, 0x0c, 0x5c, 0x4d, 0x80, 0xeb, 0x28, 0xb2, 0xf6, 0x74, + /*4ef0:*/ 0x98, 0xef, 0xe9, 0xfc, 0x67, 0xb1, 0x6a, 0x4d, 0x99, 0x50, 0xcc, 0x5e, 0x4e, 0x48, 0xaf, 0x3a, + /*4f00:*/ 0x2b, 0xf9, 0xd5, 0x8a, 0xf5, 0x2c, 0xb1, 0x48, 0x24, 0x3c, 0x93, 0xd8, 0xd0, 0x0a, 0x7a, 0x72, + /*4f10:*/ 0x20, 0xe6, 0xe1, 0x38, 0x6b, 0xa5, 0x30, 0x03, 0xaf, 0x3c, 0x52, 0x34, 0xdf, 0x42, 0x0c, 0x62, + /*4f20:*/ 0xfd, 0x7e, 0x11, 0x3a, 0x8b, 0x89, 0x36, 0x34, 0xf4, 0xdb, 0x88, 0xe4, 0xb9, 0x0a, 0xb8, 0x72, + /*4f30:*/ 0x3f, 0x42, 0x13, 0x7e, 0x4b, 0x4e, 0x6d, 0xae, 0x3c, 0x49, 0x26, 0x12, 0x75, 0x70, 0x8f, 0x43, + /*4f40:*/ 0xaa, 0xb3, 0x1a, 0x87, 0x12, 0x99, 0x43, 0x7c, 0x37, 0x52, 0xc6, 0xb1, 0x72, 0x5a, 0xab, 0xc8, + /*4f50:*/ 0x49, 0xd5, 0x30, 0x49, 0x8f, 0xf0, 0x06, 0xae, 0x97, 0x7d, 0x97, 0x57, 0x5e, 0x2b, 0x6a, 0x43, + /*4f60:*/ 0xa2, 0x8d, 0xa8, 0x4e, 0xcf, 0xa3, 0xbb, 0x1a, 0x28, 0x23, 0x06, 0x3d, 0x61, 0x2a, 0x4c, 0x97, + /*4f70:*/ 0x9a, 0xd2, 0x3e, 0xc1, 0x68, 0xc5, 0x3c, 0x81, 0x61, 0x7f, 0x8b, 0xea, 0x0f, 0x42, 0x9c, 0x89, + /*4f80:*/ 0xb8, 0xb1, 0x8a, 0xd1, 0x74, 0x09, 0x6c, 0x13, 0xee, 0x22, 0x8a, 0x3c, 0x59, 0xf6, 0x6c, 0xdb, + /*4f90:*/ 0xfd, 0xe9, 0x12, 0x29, 0xd9, 0x56, 0xdf, 0xe9, 0x9b, 0x4f, 0x30, 0x0e, 0x1c, 0x4c, 0x3f, 0x57, + /*4fa0:*/ 0xea, 0xd2, 0x9a, 0x00, 0x2d, 0x05, 0xfa, 0x0d, 0xcd, 0x2a, 0x6b, 0x7b, 0x12, 0xae, 0xe5, 0xe2, + /*4fb0:*/ 0xb0, 0xa1, 0x3c, 0xfc, 0xcb, 0x41, 0x00, 0x4c, 0x79, 0xbd, 0x02, 0x47, 0x36, 0x1b, 0x2a, 0xbc, + /*4fc0:*/ 0x46, 0x3a, 0x29, 0x68, 0x4b, 0x41, 0x5f, 0x47, 0x2b, 0xdb, 0x4c, 0x0d, 0xba, 0x7d, 0x3e, 0xd8, + /*4fd0:*/ 0x9a, 0x74, 0x62, 0x3d, 0x5d, 0x29, 0xec, 0x52, 0x65, 0x65, 0xdb, 0x95, 0xa5, 0x52, 0xff, 0xbb, + /*4fe0:*/ 0xef, 0xdb, 0xe9, 0xe4, 0xef, 0xb8, 0x0f, 0x94, 0x84, 0xab, 0xcb, 0x2e, 0x3c, 0x07, 0xee, 0xc1, + /*4ff0:*/ 0x26, 0xa5, 0xcd, 0xc4, 0x8f, 0xd7, 0x4c, 0xb5, 0x8c, 0xa8, 0x82, 0xbb, 0xda, 0xfe, 0x18, 0x25, + /*5000:*/ 0x0a, 0x5a, 0x1c, 0x02, 0x5a, 0x84, 0xa7, 0x1e, 0xdb, 0x8a, 0xc3, 0x97, 0xf0, 0x3a, 0x82, 0x06, + /*5010:*/ 0x08, 0x55, 0x93, 0x72, 0x66, 0xec, 0xac, 0x86, 0x3a, 0xb4, 0x27, 0xf4, 0x9d, 0x91, 0x96, 0xe8, + /*5020:*/ 0x6c, 0x06, 0x6c, 0xc0, 0xe4, 0x18, 0x1c, 0x54, 0x72, 0x2e, 0x4c, 0x56, 0xb6, 0x15, 0xe0, 0x72, + /*5030:*/ 0x66, 0xf0, 0xb0, 0xde, 0x53, 0x32, 0x30, 0x6c, 0xe4, 0x3f, 0x6e, 0x6e, 0x6a, 0xa3, 0xc5, 0x30, + /*5040:*/ 0xc8, 0xba, 0x71, 0x11, 0x9c, 0x57, 0x34, 0xb4, 0x92, 0x7d, 0x19, 0x3c, 0xcd, 0x9d, 0x22, 0xa2, + /*5050:*/ 0xf9, 0xdb, 0x99, 0x73, 0xfe, 0xcc, 0x10, 0x2d, 0xdf, 0x96, 0xf6, 0x8b, 0xce, 0x74, 0x91, 0xcb, + /*5060:*/ 0xd8, 0x50, 0x6b, 0x9d, 0x56, 0xec, 0x53, 0x7e, 0x5b, 0xaa, 0x7b, 0xa3, 0x9b, 0xaf, 0xa5, 0x7e, + /*5070:*/ 0xa4, 0xfa, 0x10, 0xdb, 0x73, 0x6e, 0xba, 0x66, 0x66, 0x17, 0xd5, 0x60, 0xa7, 0x9c, 0x4b, 0xdf, + /*5080:*/ 0xa7, 0x5e, 0x45, 0xfe, 0x5f, 0xbe, 0xf1, 0xd2, 0x63, 0x1a, 0x4d, 0x26, 0x22, 0x6e, 0x03, 0xe0, + /*5090:*/ 0x45, 0x89, 0x30, 0x41, 0x43, 0xad, 0x2b, 0xad, 0xf4, 0x0e, 0x0f, 0xa5, 0x33, 0xfc, 0x49, 0x30, + /*50a0:*/ 0x44, 0xf5, 0xc5, 0x8e, 0xe2, 0xa6, 0x32, 0x4b, 0x0c, 0xd5, 0x4d, 0x91, 0xe3, 0x48, 0xe2, 0xb7, + /*50b0:*/ 0xad, 0x24, 0xfb, 0xf9, 0x13, 0xe0, 0x3c, 0x8a, 0x03, 0xc6, 0x35, 0xbc, 0xd6, 0x6e, 0x03, 0x20, + /*50c0:*/ 0xda, 0x2b, 0x95, 0x22, 0x23, 0x55, 0xab, 0x79, 0x58, 0xd0, 0x55, 0x1a, 0x4d, 0xa4, 0xfd, 0x6e, + /*50d0:*/ 0x6b, 0x99, 0xc1, 0xf0, 0xba, 0x5d, 0x51, 0xfe, 0x59, 0xc3, 0x52, 0x19, 0x1b, 0x33, 0x89, 0x60, + /*50e0:*/ 0x07, 0xaf, 0x23, 0xd1, 0x01, 0xcd, 0xc9, 0xfa, 0x58, 0xa6, 0x7d, 0xec, 0x3e, 0x19, 0xc6, 0xc0, + /*50f0:*/ 0xa9, 0x5e, 0x9a, 0xb1, 0xe8, 0x58, 0xcb, 0x05, 0x36, 0x11, 0x98, 0xa3, 0x35, 0x32, 0x87, 0x44, + /*5100:*/ 0x5f, 0x6b, 0xdf, 0x09, 0x15, 0x42, 0xd7, 0xe9, 0x72, 0x56, 0x3f, 0x6b, 0x19, 0x08, 0x46, 0xf0, + /*5110:*/ 0x25, 0x77, 0x96, 0x04, 0x0f, 0x99, 0x4e, 0xa9, 0xbb, 0x7d, 0xad, 0x19, 0x6b, 0x2e, 0x42, 0x41, + /*5120:*/ 0xbc, 0xd2, 0xf0, 0x4b, 0xc6, 0xc5, 0x72, 0xa1, 0x39, 0x22, 0x56, 0x9b, 0x72, 0x34, 0x01, 0x3b, + /*5130:*/ 0x70, 0x33, 0x0f, 0xa3, 0x80, 0xf3, 0x9b, 0xcf, 0x4c, 0x22, 0xb5, 0xce, 0xd7, 0xe1, 0xdd, 0xa9, + /*5140:*/ 0xa0, 0x04, 0x87, 0xd0, 0xe2, 0x76, 0xed, 0xb6, 0x17, 0xb5, 0xf8, 0x20, 0x4c, 0xb2, 0x1c, 0x25, + /*5150:*/ 0x8b, 0x7e, 0x10, 0x65, 0xe3, 0xaa, 0x9b, 0x58, 0xfe, 0x41, 0x68, 0x9b, 0x2e, 0x02, 0x93, 0x86, + /*5160:*/ 0xab, 0xba, 0xb2, 0x70, 0xed, 0x13, 0x21, 0x94, 0xc7, 0x4f, 0xac, 0xb3, 0x77, 0xbb, 0xf1, 0x62, + /*5170:*/ 0x08, 0xfd, 0xe6, 0x53, 0xa0, 0x03, 0xc7, 0xbb, 0xcc, 0xf8, 0x90, 0x93, 0x2d, 0xc7, 0xee, 0xf8, + /*5180:*/ 0xf5, 0x08, 0xf8, 0x70, 0x2b, 0xc7, 0x29, 0x49, 0xc6, 0xc1, 0xbe, 0xc9, 0x48, 0x4b, 0xb4, 0x87, + /*5190:*/ 0xa3, 0xcb, 0x24, 0x88, 0x5f, 0xd7, 0xc0, 0x28, 0x2e, 0x13, 0x12, 0x6c, 0xf5, 0x00, 0x09, 0x12, + /*51a0:*/ 0x59, 0x8d, 0x38, 0x6c, 0xb7, 0x33, 0xda, 0x11, 0x66, 0x06, 0xd5, 0x11, 0x99, 0x1f, 0x3f, 0x44, + /*51b0:*/ 0xf1, 0x5e, 0x58, 0x7f, 0x30, 0xaf, 0x73, 0x8d, 0x24, 0x01, 0x5c, 0x1d, 0x02, 0x4a, 0x15, 0xd9, + /*51c0:*/ 0x8c, 0x6e, 0x12, 0xe6, 0x54, 0x73, 0xe9, 0x62, 0x31, 0xf9, 0x8e, 0x3c, 0x00, 0xff, 0x80, 0x48, + /*51d0:*/ 0xb9, 0x24, 0x18, 0x2f, 0xa7, 0xd8, 0x07, 0xd0, 0x84, 0x64, 0xe6, 0xad, 0x9d, 0xe9, 0xa7, 0xd8, + /*51e0:*/ 0x3c, 0xaa, 0x59, 0x19, 0x5a, 0x29, 0x61, 0xf8, 0x39, 0xcb, 0x16, 0x63, 0x9e, 0x6a, 0xc8, 0xcd, + /*51f0:*/ 0x5d, 0x4f, 0x97, 0x8c, 0xe3, 0xf1, 0x9a, 0xa0, 0x33, 0x24, 0x7c, 0x15, 0x65, 0x95, 0xb3, 0x09, + /*5200:*/ 0xaf, 0x2f, 0x11, 0x6c, 0xac, 0xea, 0x75, 0x33, 0x4b, 0x5a, 0xf3, 0x9f, 0x38, 0xa4, 0x60, 0xd8, + /*5210:*/ 0x0c, 0xff, 0x92, 0x97, 0x35, 0x63, 0xbe, 0x2f, 0x44, 0xa5, 0xc6, 0x4d, 0x61, 0x3e, 0xc5, 0xad, + /*5220:*/ 0xc6, 0x9b, 0x41, 0x02, 0x0c, 0x9d, 0x1e, 0xc5, 0xb1, 0x21, 0x0e, 0xd3, 0x44, 0xd8, 0x36, 0x49, + /*5230:*/ 0x73, 0x20, 0x23, 0xbc, 0x97, 0x99, 0xf0, 0xc2, 0x6f, 0x2c, 0x10, 0x69, 0x9d, 0xfe, 0x4d, 0x85, + /*5240:*/ 0xf7, 0xd6, 0x86, 0x87, 0x05, 0x42, 0x8d, 0xcb, 0xc7, 0x9f, 0xbd, 0x28, 0x0b, 0xdd, 0x8c, 0xe0, + /*5250:*/ 0x60, 0x61, 0x77, 0xb5, 0xca, 0x50, 0x33, 0x3d, 0xd4, 0x82, 0x51, 0x8d, 0x5b, 0x14, 0x28, 0x98, + /*5260:*/ 0x88, 0x90, 0x34, 0x1e, 0x77, 0xf6, 0x7f, 0xc2, 0x00, 0xf8, 0x55, 0x6d, 0xf9, 0xce, 0xb0, 0x3a, + /*5270:*/ 0xec, 0xe5, 0x5f, 0x8b, 0x2b, 0x12, 0x5c, 0x9b, 0x01, 0x33, 0xa6, 0x9b, 0x8b, 0xb1, 0x6a, 0x8d, + /*5280:*/ 0x70, 0xb2, 0x9e, 0x07, 0x27, 0x5a, 0x40, 0x5d, 0xba, 0x7f, 0x8b, 0x4c, 0x99, 0x49, 0x6e, 0x31, + /*5290:*/ 0x1e, 0xe4, 0x7e, 0x4a, 0x5d, 0xc3, 0xd1, 0x04, 0x0a, 0x7a, 0xab, 0x6a, 0x3c, 0x38, 0xa7, 0x7f, + /*52a0:*/ 0xd0, 0xcd, 0x06, 0x6a, 0x81, 0x37, 0x28, 0x25, 0xe9, 0xd2, 0xe6, 0x79, 0x1c, 0x43, 0x36, 0x80, + /*52b0:*/ 0x2b, 0x1d, 0xee, 0xd4, 0x4b, 0x7a, 0x5f, 0x9a, 0x7c, 0x38, 0xc1, 0x08, 0xa9, 0x17, 0x18, 0xd2, + /*52c0:*/ 0x6c, 0x78, 0xf0, 0xaa, 0xb4, 0x62, 0x38, 0x96, 0x6e, 0x96, 0x7b, 0x21, 0xc3, 0x21, 0x9b, 0xb2, + /*52d0:*/ 0x70, 0x5d, 0x7b, 0x2f, 0xb1, 0xc6, 0x96, 0x1a, 0xe0, 0xd7, 0x76, 0x6a, 0x6f, 0x4b, 0x23, 0x38, + /*52e0:*/ 0x9b, 0xc7, 0xac, 0xbf, 0x44, 0x01, 0x0f, 0xb6, 0x66, 0x97, 0xa5, 0xc6, 0xf8, 0xc2, 0xfa, 0x3b, + /*52f0:*/ 0x78, 0x48, 0xd1, 0xac, 0xe8, 0x47, 0xd0, 0x0e, 0x80, 0x0c, 0x52, 0xf0, 0xd4, 0x04, 0x4a, 0xd7, + /*5300:*/ 0x60, 0x49, 0xe5, 0x78, 0xe6, 0xc6, 0x91, 0xbc, 0x67, 0x12, 0x9a, 0x14, 0x39, 0x3a, 0xd5, 0x3a, + /*5310:*/ 0xa4, 0x2c, 0xfc, 0x1c, 0x30, 0x99, 0xdd, 0xf2, 0xba, 0xe6, 0xfa, 0xe3, 0x1d, 0xd9, 0xae, 0x64, + /*5320:*/ 0x11, 0x87, 0x92, 0x51, 0xc9, 0x61, 0x50, 0xb0, 0x82, 0x6d, 0x0b, 0x43, 0x8b, 0xf6, 0xae, 0x8e, + /*5330:*/ 0x83, 0x7d, 0x00, 0xfc, 0xd9, 0xf5, 0x4b, 0x14, 0x36, 0xf1, 0x4a, 0xea, 0x33, 0x92, 0x8c, 0x16, + /*5340:*/ 0x91, 0xb9, 0xf0, 0x44, 0xa2, 0x31, 0xed, 0x0e, 0x6b, 0x45, 0xb3, 0xe2, 0x47, 0xab, 0xc6, 0x70, + /*5350:*/ 0xf8, 0x84, 0xe8, 0xa4, 0x41, 0x9f, 0x32, 0xd5, 0x61, 0x6b, 0x81, 0x38, 0x34, 0x5b, 0x88, 0xf2, + /*5360:*/ 0x82, 0xae, 0x6c, 0x5e, 0xa0, 0x6f, 0xb1, 0x93, 0xaf, 0x6b, 0x04, 0xbe, 0xd5, 0xcb, 0xae, 0xac, + /*5370:*/ 0xd0, 0x09, 0x2a, 0x7d, 0x9f, 0xa6, 0xa9, 0xa2, 0x46, 0x61, 0x82, 0xaa, 0x95, 0x9c, 0xf1, 0x36, + /*5380:*/ 0x57, 0xb5, 0xcf, 0x5a, 0x00, 0x43, 0xac, 0x5c, 0xb4, 0xd9, 0xe2, 0x08, 0x03, 0x5c, 0x88, 0xc4, + /*5390:*/ 0xab, 0x50, 0xa6, 0x72, 0xae, 0xe0, 0x56, 0xba, 0x93, 0x9a, 0x87, 0x20, 0xe1, 0x08, 0x55, 0x2c, + /*53a0:*/ 0xeb, 0xff, 0xfd, 0xc6, 0x31, 0xc0, 0xb2, 0xce, 0x62, 0xe4, 0x8b, 0x31, 0xc3, 0xa9, 0x70, 0xed, + /*53b0:*/ 0x0f, 0x98, 0x04, 0x70, 0x07, 0xa3, 0x17, 0xc5, 0xb6, 0x15, 0x02, 0x2b, 0x62, 0x68, 0xb9, 0x18, + /*53c0:*/ 0xa4, 0x88, 0xf8, 0xad, 0x61, 0x63, 0x9d, 0x4f, 0x71, 0xd5, 0xbc, 0x32, 0x86, 0xa9, 0x2b, 0x6b, + /*53d0:*/ 0xdf, 0x2d, 0x0d, 0x4b, 0x6f, 0x65, 0xe4, 0x57, 0xae, 0x76, 0xac, 0x48, 0xeb, 0xa8, 0x12, 0xc5, + /*53e0:*/ 0x30, 0x93, 0x12, 0xfb, 0x85, 0xa9, 0x76, 0xe4, 0xca, 0x36, 0xbc, 0xb4, 0xd4, 0xa5, 0x6f, 0x3c, + /*53f0:*/ 0x77, 0x16, 0x05, 0x00, 0x3f, 0xd3, 0x0b, 0x93, 0x3e, 0xf0, 0xdd, 0xa3, 0xd9, 0xba, 0xfd, 0x6d, + /*5400:*/ 0x6e, 0x91, 0x64, 0x41, 0xa0, 0x40, 0xd7, 0x1a, 0x25, 0x33, 0xb8, 0x35, 0x50, 0x56, 0xa6, 0xf1, + /*5410:*/ 0x18, 0x19, 0x98, 0x5e, 0x74, 0x4b, 0xb0, 0xc0, 0xf2, 0xbb, 0x5b, 0x06, 0x1c, 0xc7, 0x35, 0x3b, + /*5420:*/ 0x3f, 0x00, 0x58, 0x20, 0x4a, 0x52, 0x25, 0xd2, 0x10, 0x79, 0x3b, 0x78, 0xd3, 0x6b, 0x39, 0x5c, + /*5430:*/ 0xf3, 0x22, 0xde, 0xb8, 0xd6, 0x8b, 0xe9, 0x2c, 0x03, 0x55, 0xd4, 0x82, 0x66, 0x33, 0x6e, 0xa1, + /*5440:*/ 0x68, 0xd8, 0x63, 0x1f, 0xda, 0xf8, 0x14, 0x4c, 0xfd, 0x78, 0x70, 0x3e, 0xdf, 0xdb, 0x83, 0x99, + /*5450:*/ 0x94, 0x61, 0xa5, 0x86, 0x64, 0xae, 0x9c, 0xfe, 0x33, 0xc7, 0x20, 0x04, 0x5a, 0xbe, 0xd4, 0x74, + /*5460:*/ 0xef, 0x19, 0x39, 0xf8, 0xf9, 0xff, 0xcc, 0x96, 0x3a, 0xb6, 0x1c, 0x54, 0xd8, 0xd7, 0xcb, 0xf6, + /*5470:*/ 0xd7, 0x97, 0x51, 0xd2, 0xd8, 0x86, 0x8e, 0x04, 0x5f, 0xc6, 0x5c, 0x3e, 0x71, 0x87, 0xa6, 0x50, + /*5480:*/ 0xeb, 0x41, 0x45, 0x45, 0xba, 0x0f, 0x67, 0x32, 0x44, 0x64, 0xbf, 0xde, 0xbc, 0x4c, 0x11, 0xfe, + /*5490:*/ 0xc2, 0x24, 0xe2, 0xf3, 0x30, 0xb2, 0x87, 0xa1, 0x62, 0xf6, 0xa0, 0x7d, 0xf7, 0xd9, 0x68, 0x83, + /*54a0:*/ 0x7a, 0x1b, 0x00, 0x0d, 0x01, 0xd8, 0xc0, 0xa6, 0x99, 0x2a, 0x95, 0x44, 0x5f, 0xda, 0xf6, 0xc3, + /*54b0:*/ 0xa0, 0x30, 0x0b, 0x1d, 0x88, 0xb4, 0xae, 0xc7, 0x2b, 0xae, 0x06, 0x2a, 0xb1, 0x72, 0x64, 0xec, + /*54c0:*/ 0x0b, 0xdc, 0xc6, 0xba, 0x92, 0xa6, 0xb9, 0x6e, 0x4f, 0x69, 0x12, 0x99, 0xb5, 0x00, 0xcf, 0x8d, + /*54d0:*/ 0x8e, 0x0b, 0x94, 0x75, 0xf2, 0x89, 0xb4, 0x35, 0x48, 0x9d, 0x7f, 0x76, 0x15, 0xb9, 0x92, 0x0b, + /*54e0:*/ 0x82, 0xba, 0x88, 0x8a, 0xff, 0x21, 0x3b, 0xd8, 0x53, 0x02, 0x78, 0x6a, 0x2a, 0x7c, 0x34, 0xb5, + /*54f0:*/ 0xfc, 0xc7, 0xb8, 0x99, 0xe0, 0xed, 0xb8, 0x52, 0xce, 0xc8, 0x68, 0x5e, 0x67, 0x2a, 0x7a, 0x4b, + /*5500:*/ 0x75, 0x78, 0x0f, 0x9d, 0xbe, 0x0e, 0x4c, 0xde, 0x5a, 0x1b, 0xc2, 0x36, 0xf3, 0xe4, 0x8a, 0xfd, + /*5510:*/ 0xf3, 0x72, 0x42, 0x38, 0xac, 0xd3, 0xc4, 0xaa, 0x16, 0xfa, 0x60, 0x8b, 0x4e, 0xd5, 0x87, 0x34, + /*5520:*/ 0x78, 0x01, 0x8b, 0x3b, 0x48, 0x1e, 0x57, 0x46, 0x59, 0x2d, 0x6c, 0xda, 0x80, 0xb2, 0x4b, 0x9c, + /*5530:*/ 0x77, 0xa2, 0x1c, 0xc0, 0x70, 0x63, 0xc1, 0x0e, 0x30, 0xf1, 0x26, 0xd1, 0xdd, 0x75, 0xf8, 0x3f, + /*5540:*/ 0x2c, 0xeb, 0x9d, 0xdf, 0xbc, 0x74, 0xff, 0x46, 0x6e, 0xbc, 0x7f, 0x9b, 0x41, 0xce, 0x20, 0xb0, + /*5550:*/ 0xb7, 0xff, 0x99, 0xc3, 0x13, 0x7c, 0xf6, 0x4b, 0xb3, 0x35, 0x37, 0xaa, 0xf2, 0x9a, 0xad, 0x67, + /*5560:*/ 0x81, 0xe0, 0x9d, 0xa6, 0x4f, 0x48, 0x68, 0xc2, 0x22, 0xaf, 0xf8, 0xdf, 0xf9, 0x2f, 0x08, 0x84, + /*5570:*/ 0x2c, 0xcb, 0xc4, 0x86, 0xe2, 0x5a, 0x38, 0x94, 0x45, 0x4d, 0xd7, 0x30, 0x97, 0x5a, 0xd4, 0x60, + /*5580:*/ 0x3b, 0x20, 0xb5, 0xf8, 0x39, 0x8c, 0x1a, 0x60, 0x05, 0xbb, 0x9e, 0x61, 0x8c, 0x56, 0x96, 0x39, + /*5590:*/ 0xe4, 0x78, 0x10, 0x07, 0x14, 0xb3, 0xbe, 0x0d, 0x24, 0x58, 0x78, 0xa8, 0x79, 0x29, 0xf0, 0xcc, + /*55a0:*/ 0x12, 0x4b, 0x5a, 0x9a, 0xa4, 0x4b, 0xa8, 0x37, 0x5e, 0xc3, 0x1b, 0x13, 0x77, 0x24, 0x09, 0x29, + /*55b0:*/ 0xcc, 0xf9, 0x05, 0xd7, 0x20, 0xe9, 0x16, 0xd5, 0xb0, 0x4d, 0x61, 0x44, 0xd7, 0x29, 0x9b, 0xd7, + /*55c0:*/ 0x6c, 0xaa, 0x82, 0xc9, 0x6e, 0x3a, 0x07, 0x8b, 0x9c, 0xef, 0x6a, 0xc0, 0x91, 0x11, 0x4b, 0x2d, + /*55d0:*/ 0x26, 0xd7, 0x3b, 0x11, 0x88, 0x4d, 0x6f, 0xf4, 0xad, 0xf3, 0xde, 0xdb, 0xa5, 0xb9, 0x7b, 0x64, + /*55e0:*/ 0x60, 0x7b, 0xd8, 0xf2, 0xd3, 0xa3, 0x64, 0x1a, 0x56, 0xc9, 0x5e, 0x6a, 0x86, 0xbd, 0x28, 0xea, + /*55f0:*/ 0x31, 0x28, 0x15, 0x84, 0x5c, 0xe5, 0x0a, 0x89, 0x54, 0x69, 0x14, 0x5b, 0xca, 0x24, 0x56, 0xc2, + /*5600:*/ 0x71, 0x96, 0xdf, 0x31, 0x9b, 0x72, 0x9f, 0xb3, 0xce, 0xd4, 0x87, 0xf6, 0x6f, 0x32, 0x89, 0x72, + /*5610:*/ 0x82, 0x7c, 0x59, 0x5c, 0x57, 0xfa, 0x01, 0x89, 0xd2, 0x2d, 0x45, 0xe3, 0x53, 0x62, 0xc9, 0x40, + /*5620:*/ 0x73, 0xa0, 0xcd, 0x96, 0xe1, 0xe5, 0x42, 0xed, 0x1a, 0x51, 0xb2, 0xb6, 0xc3, 0x18, 0xed, 0xd1, + /*5630:*/ 0x1f, 0x07, 0x69, 0x66, 0xbd, 0x27, 0x78, 0x6e, 0xd9, 0xf0, 0xe5, 0x37, 0x75, 0xbd, 0x67, 0xcf, + /*5640:*/ 0x62, 0x4e, 0xd2, 0xb1, 0xfa, 0xa9, 0x0c, 0x4a, 0xd3, 0x96, 0x96, 0x0f, 0xcd, 0x9b, 0x80, 0x1a, + /*5650:*/ 0x3b, 0x4a, 0x99, 0xdb, 0xd4, 0x16, 0x02, 0x62, 0x15, 0x97, 0xfa, 0xac, 0xd2, 0x04, 0x0b, 0xd5, + /*5660:*/ 0x7b, 0x20, 0x1d, 0xf3, 0x9c, 0xed, 0x32, 0x9b, 0x90, 0x2d, 0x95, 0xb1, 0x7e, 0x2c, 0xf8, 0x27, + /*5670:*/ 0x2c, 0x06, 0x8b, 0x23, 0x93, 0xc5, 0xa2, 0x0d, 0x94, 0xfc, 0xfd, 0x56, 0xe1, 0xe6, 0xa9, 0x81, + /*5680:*/ 0xe2, 0x48, 0x53, 0xee, 0x6d, 0xe9, 0x44, 0x92, 0x1b, 0x73, 0x16, 0xd6, 0x99, 0x12, 0xa4, 0x6a, + /*5690:*/ 0xa1, 0xfc, 0x8b, 0x1a, 0xf0, 0xb4, 0x1c, 0x67, 0xd4, 0x83, 0x65, 0x69, 0x9c, 0x64, 0xb1, 0x9e, + /*56a0:*/ 0x0b, 0x74, 0xbb, 0x0f, 0xa8, 0x7d, 0xb9, 0x39, 0x3b, 0x2c, 0x89, 0xcf, 0x70, 0x74, 0x27, 0xcf, + /*56b0:*/ 0x4a, 0xdd, 0x8a, 0xe5, 0x05, 0x46, 0x6d, 0x84, 0xba, 0x1d, 0x70, 0x78, 0x5a, 0x6f, 0x9a, 0xf1, + /*56c0:*/ 0xb4, 0xf8, 0x11, 0x7b, 0x39, 0xe7, 0x03, 0x67, 0x58, 0x6b, 0x64, 0x8c, 0x8d, 0xa3, 0xd2, 0x7d, + /*56d0:*/ 0xf4, 0x35, 0x4e, 0x48, 0x61, 0xc8, 0xaa, 0x57, 0xb9, 0xf5, 0xcd, 0x9c, 0xaa, 0x38, 0x78, 0x17, + /*56e0:*/ 0xaf, 0x59, 0x11, 0x2b, 0xfa, 0x49, 0x6c, 0xf3, 0xdf, 0x53, 0xb0, 0xb5, 0x3d, 0x1e, 0x37, 0x7e, + /*56f0:*/ 0x11, 0x2c, 0x56, 0xfa, 0xc7, 0x77, 0x6d, 0x6c, 0xd8, 0xd6, 0x12, 0x41, 0x12, 0xa2, 0x02, 0x06, + /*5700:*/ 0xcd, 0x5d, 0x75, 0xba, 0x86, 0xe5, 0xe5, 0x27, 0xdf, 0x8c, 0xd0, 0x06, 0xeb, 0x41, 0xbe, 0x8d, + /*5710:*/ 0xe1, 0xa2, 0x90, 0x8f, 0x4b, 0xbf, 0x76, 0x03, 0x75, 0x33, 0x29, 0x1a, 0x80, 0x57, 0xd6, 0x67, + /*5720:*/ 0x01, 0x72, 0xc1, 0x5a, 0xea, 0xd3, 0xbe, 0xb1, 0xac, 0x6c, 0x13, 0xc5, 0xc2, 0x72, 0x7d, 0x22, + /*5730:*/ 0xb0, 0xa2, 0xab, 0xf6, 0x52, 0x78, 0x37, 0xcf, 0x38, 0x1e, 0x13, 0xb9, 0xee, 0x71, 0x5a, 0xc4, + /*5740:*/ 0xfc, 0x6a, 0x11, 0xe1, 0xd6, 0x6e, 0x01, 0x32, 0x5a, 0x51, 0x35, 0x39, 0x59, 0x30, 0xc5, 0x15, + /*5750:*/ 0x87, 0x52, 0x63, 0xe8, 0x07, 0x39, 0xd8, 0xf0, 0x85, 0xf5, 0x7c, 0x31, 0x6d, 0xbf, 0x24, 0x27, + /*5760:*/ 0xf7, 0x66, 0xca, 0x6a, 0x81, 0xc8, 0x38, 0x02, 0x07, 0x20, 0x49, 0x2e, 0x9e, 0xe6, 0xe9, 0x5e, + /*5770:*/ 0x64, 0x81, 0xed, 0xea, 0xf9, 0x87, 0x53, 0xed, 0x06, 0xe0, 0x27, 0xba, 0x29, 0x0b, 0x00, 0xa0, + /*5780:*/ 0x2c, 0xbf, 0xee, 0x37, 0x44, 0x63, 0xa0, 0xf4, 0xe3, 0x9a, 0xc5, 0xba, 0x6f, 0x50, 0x1c, 0x72, + /*5790:*/ 0x14, 0x89, 0x3c, 0x14, 0xc4, 0xf7, 0x8c, 0x4d, 0x7d, 0x2a, 0xa2, 0xb4, 0x94, 0xfe, 0xfd, 0xce, + /*57a0:*/ 0xcf, 0x07, 0x71, 0x33, 0xe0, 0x46, 0xe0, 0x03, 0x94, 0x42, 0x9d, 0x55, 0x69, 0x2c, 0x3d, 0x74, + /*57b0:*/ 0x6b, 0x74, 0x52, 0x49, 0x34, 0x9c, 0x51, 0xc0, 0x19, 0x0c, 0x5e, 0x74, 0x76, 0xc2, 0x4a, 0x0a, + /*57c0:*/ 0x14, 0x88, 0x4e, 0x2a, 0xa5, 0x9a, 0x9e, 0xc3, 0x99, 0x72, 0x5e, 0xef, 0x9c, 0x94, 0xac, 0xa7, + /*57d0:*/ 0x61, 0x78, 0xc2, 0x36, 0x17, 0x82, 0x2d, 0xce, 0x7d, 0x92, 0xd0, 0x8a, 0x3b, 0x3e, 0x1f, 0x1d, + /*57e0:*/ 0x83, 0xf9, 0xa8, 0x44, 0xdf, 0xce, 0x84, 0x31, 0xdc, 0xf2, 0xd6, 0x0d, 0xb9, 0x0b, 0x89, 0xc5, + /*57f0:*/ 0x77, 0xae, 0xa1, 0x9a, 0x75, 0xc6, 0x93, 0x6e, 0xdb, 0x61, 0xdd, 0x3d, 0x8e, 0x7c, 0x4b, 0x53, + /*5800:*/ 0x14, 0x1d, 0x3c, 0x51, 0x5f, 0x60, 0xfe, 0x6a, 0x1d, 0xef, 0x49, 0x30, 0x03, 0xf3, 0xb2, 0x7c, + /*5810:*/ 0xf5, 0x1c, 0x88, 0x68, 0xf4, 0xb8, 0xf5, 0x36, 0x4f, 0x17, 0x11, 0x39, 0x44, 0xfc, 0xaa, 0xe2, + /*5820:*/ 0x51, 0x20, 0x77, 0xc7, 0xe0, 0xf4, 0x6e, 0x8c, 0xa5, 0x77, 0xc7, 0x66, 0x2c, 0x24, 0xb1, 0xae, + /*5830:*/ 0xc1, 0xbd, 0x1a, 0x64, 0x1c, 0x1e, 0xa3, 0xbb, 0x52, 0xb3, 0x53, 0x1a, 0x5e, 0x94, 0xd6, 0x10, + /*5840:*/ 0xd4, 0x17, 0x6e, 0x36, 0xe8, 0x09, 0x6a, 0x0f, 0x67, 0x73, 0x40, 0xb8, 0xcf, 0xdd, 0xc0, 0xac, + /*5850:*/ 0x3a, 0xfd, 0x08, 0xcd, 0xd2, 0x42, 0xc0, 0xb0, 0x4e, 0xc3, 0xca, 0x66, 0x2b, 0x84, 0x19, 0x6f, + /*5860:*/ 0x2e, 0xf2, 0x22, 0x21, 0x56, 0xb7, 0x17, 0xbe, 0x47, 0xc2, 0x96, 0x6e, 0x60, 0xf2, 0xc7, 0x1f, + /*5870:*/ 0x9b, 0xb5, 0x82, 0xea, 0x02, 0x46, 0x4e, 0x04, 0xca, 0x64, 0xa1, 0x70, 0xd6, 0xd0, 0xd7, 0x3d, + /*5880:*/ 0x15, 0x42, 0x68, 0x17, 0xfd, 0x7f, 0x7f, 0x9a, 0x12, 0x1b, 0xcc, 0x7a, 0x59, 0x85, 0x5e, 0xfd, + /*5890:*/ 0x74, 0x55, 0x8b, 0xc9, 0x55, 0xf7, 0x44, 0x64, 0xa8, 0xff, 0xd3, 0xb5, 0x32, 0x2e, 0xb1, 0x3a, + /*58a0:*/ 0x36, 0xe2, 0x4d, 0x18, 0x35, 0x37, 0x5c, 0x5b, 0x8d, 0x9b, 0x51, 0x51, 0x39, 0xb2, 0xbe, 0x5a, + /*58b0:*/ 0xaf, 0xf6, 0xa4, 0x35, 0xc5, 0x62, 0x26, 0x9e, 0x60, 0xa8, 0xad, 0x12, 0x89, 0xef, 0x23, 0x9a, + /*58c0:*/ 0x54, 0x74, 0xa6, 0x07, 0x40, 0xab, 0x97, 0xf4, 0xcc, 0xa9, 0x37, 0xd2, 0x43, 0xda, 0x9b, 0xdb, + /*58d0:*/ 0x07, 0x3c, 0x6f, 0x33, 0x64, 0x6b, 0xfd, 0xa7, 0x72, 0x5c, 0x61, 0xce, 0xe7, 0x2a, 0x21, 0x96, + /*58e0:*/ 0xac, 0xb4, 0x04, 0x2d, 0x0b, 0x8b, 0x6d, 0xa8, 0xbd, 0x48, 0xab, 0xcd, 0xc9, 0x1f, 0x12, 0xf3, + /*58f0:*/ 0xb6, 0x83, 0xec, 0xa2, 0x89, 0x8b, 0x89, 0x35, 0x62, 0x10, 0x5e, 0xc8, 0x28, 0xcc, 0x2f, 0xfb, + /*5900:*/ 0x85, 0xb4, 0x9a, 0xab, 0x51, 0x1a, 0x78, 0x84, 0x42, 0xec, 0x99, 0xad, 0x5b, 0x53, 0x24, 0x39, + /*5910:*/ 0x68, 0x4c, 0xdb, 0xef, 0xab, 0x5c, 0x89, 0xfa, 0x6f, 0xf7, 0x23, 0x6c, 0x42, 0x7d, 0xbf, 0xe9, + /*5920:*/ 0x29, 0x96, 0x1f, 0x47, 0x39, 0x86, 0x02, 0x36, 0x5a, 0x1a, 0x98, 0xe4, 0x1a, 0x7b, 0x03, 0x3b, + /*5930:*/ 0x6c, 0x5f, 0x41, 0x61, 0x20, 0x26, 0xe2, 0xf2, 0x26, 0x8a, 0xf7, 0x50, 0xe4, 0x50, 0xd2, 0x64, + /*5940:*/ 0xea, 0xec, 0xf5, 0x37, 0xea, 0xf7, 0x68, 0x8b, 0x31, 0x24, 0xc8, 0x78, 0x96, 0x2d, 0xc6, 0x9b, + /*5950:*/ 0x46, 0xa1, 0x9a, 0xe2, 0xdc, 0xbb, 0x26, 0x14, 0xd8, 0x7e, 0x78, 0xb9, 0x60, 0x1d, 0xc4, 0x4b, + /*5960:*/ 0x66, 0xad, 0x2d, 0x11, 0x40, 0x70, 0xcd, 0x41, 0xb5, 0xb5, 0x8d, 0xe1, 0xc2, 0x44, 0x6a, 0xcf, + /*5970:*/ 0x87, 0x28, 0xa8, 0x8a, 0xc6, 0x9b, 0xb4, 0xd8, 0x14, 0xae, 0x0e, 0xae, 0x4e, 0xde, 0x7f, 0xf1, + /*5980:*/ 0x79, 0xec, 0x9c, 0xed, 0x96, 0x33, 0xfd, 0x40, 0xae, 0xbf, 0x34, 0xa2, 0x9c, 0x5a, 0xf7, 0xcd, + /*5990:*/ 0x4b, 0xab, 0xaa, 0xd2, 0xd5, 0xb2, 0x39, 0xcd, 0x4a, 0x23, 0xc7, 0xb9, 0x82, 0x55, 0xa9, 0x00, + /*59a0:*/ 0xf1, 0x6d, 0x29, 0x99, 0x0d, 0xc6, 0x83, 0x5a, 0x21, 0xaa, 0x09, 0xb6, 0x24, 0x17, 0xd9, 0xbe, + /*59b0:*/ 0x56, 0xd8, 0x23, 0x56, 0x94, 0xe5, 0x72, 0xdd, 0xb3, 0xc7, 0x30, 0x76, 0x66, 0xc8, 0x79, 0xd6, + /*59c0:*/ 0xda, 0xa0, 0x85, 0x20, 0x75, 0xd4, 0x17, 0x65, 0x68, 0xb2, 0x47, 0xe7, 0xae, 0xfc, 0xe8, 0x40, + /*59d0:*/ 0xf0, 0x10, 0x64, 0xa8, 0x56, 0x29, 0x92, 0x4c, 0xe1, 0x8d, 0x80, 0x60, 0x3e, 0x05, 0x3d, 0xaa, + /*59e0:*/ 0x46, 0x9b, 0x4b, 0xa8, 0x80, 0xd7, 0xb0, 0x81, 0xa4, 0x5c, 0xc6, 0x12, 0xef, 0x4b, 0xda, 0x3f, + /*59f0:*/ 0x4b, 0x78, 0xf4, 0x64, 0x17, 0x52, 0xc2, 0xec, 0x4a, 0xc6, 0x44, 0x3b, 0x80, 0xcf, 0xd6, 0xa5, + /*5a00:*/ 0x44, 0xa5, 0x02, 0x3b, 0x05, 0x10, 0xd0, 0x69, 0xdf, 0x7e, 0x27, 0xf0, 0x25, 0x26, 0x09, 0xa8, + /*5a10:*/ 0xa7, 0x38, 0x72, 0xe5, 0x96, 0x62, 0x8a, 0xc7, 0x5e, 0xb1, 0x6a, 0xf6, 0x5a, 0x1a, 0x08, 0x88, + /*5a20:*/ 0xe4, 0x18, 0x42, 0xff, 0x53, 0xbb, 0x93, 0x7c, 0xc5, 0x34, 0x65, 0x29, 0xcc, 0xbe, 0xfa, 0xb2, + /*5a30:*/ 0xec, 0x59, 0x23, 0xd8, 0xb2, 0x31, 0xe4, 0xe1, 0xe1, 0xb7, 0xd9, 0x40, 0xbd, 0xb6, 0x1b, 0x29, + /*5a40:*/ 0xba, 0x10, 0x60, 0x3d, 0x93, 0x68, 0x2f, 0x08, 0x17, 0xf3, 0x43, 0xa8, 0x0c, 0x1e, 0xda, 0x76, + /*5a50:*/ 0x60, 0x8a, 0xb0, 0x2d, 0x44, 0x09, 0x24, 0xf2, 0xca, 0xa8, 0xf5, 0xd4, 0x4e, 0x2a, 0xbd, 0xd7, + /*5a60:*/ 0xed, 0x37, 0x24, 0x20, 0xfa, 0x00, 0x0a, 0x01, 0x4d, 0xc1, 0xfe, 0x71, 0x26, 0x76, 0xf0, 0x2f, + /*5a70:*/ 0x2b, 0xe9, 0xb5, 0xfe, 0xd9, 0x18, 0x96, 0x84, 0x51, 0xc1, 0x39, 0xf3, 0x1a, 0x87, 0x1c, 0xf6, + /*5a80:*/ 0x62, 0xed, 0xcd, 0xa7, 0x7e, 0x57, 0x6d, 0x08, 0xc6, 0x90, 0x6d, 0xe5, 0x6e, 0xee, 0x8f, 0x88, + /*5a90:*/ 0x07, 0x71, 0xab, 0x55, 0x66, 0xfc, 0xf7, 0x0b, 0x90, 0x97, 0xc9, 0xe9, 0xf0, 0xe5, 0x30, 0x9a, + /*5aa0:*/ 0xd0, 0x5a, 0x00, 0x9c, 0x1c, 0x3c, 0x49, 0x2a, 0x3e, 0x72, 0xb8, 0xfe, 0xab, 0x20, 0xc8, 0xf5, + /*5ab0:*/ 0xd7, 0xf9, 0x76, 0xbe, 0x33, 0x45, 0xac, 0x6b, 0x81, 0x50, 0x66, 0x9c, 0x24, 0xa0, 0x47, 0xe0, + /*5ac0:*/ 0xbe, 0x7f, 0xa2, 0x85, 0xb0, 0x8a, 0xfb, 0x42, 0x04, 0xe0, 0xed, 0xd6, 0xfd, 0xcc, 0x59, 0x6f, + /*5ad0:*/ 0xe7, 0x57, 0x63, 0x52, 0x03, 0x75, 0x28, 0x2d, 0x07, 0x7b, 0xe3, 0xf9, 0xfb, 0xa1, 0xef, 0x85, + /*5ae0:*/ 0x51, 0xf0, 0xf8, 0x76, 0x11, 0xa6, 0x80, 0xe4, 0x4b, 0x24, 0xfd, 0x1f, 0xc7, 0x68, 0x05, 0x8f, + /*5af0:*/ 0xd8, 0xdb, 0x52, 0xbd, 0x09, 0x85, 0x75, 0x5e, 0xe1, 0x61, 0x14, 0x60, 0xaf, 0xfd, 0xd2, 0xdf, + /*5b00:*/ 0xa3, 0x80, 0xc9, 0xa2, 0x80, 0x69, 0x47, 0xe9, 0xb7, 0xcd, 0xbb, 0xae, 0x53, 0xbd, 0xa8, 0xf6, + /*5b10:*/ 0x86, 0x88, 0x4c, 0xdb, 0xfc, 0xa7, 0xd1, 0x42, 0xfc, 0xb8, 0x9f, 0xe9, 0xf3, 0x7e, 0xeb, 0x13, + /*5b20:*/ 0x4f, 0xb0, 0xfa, 0xe0, 0x40, 0x42, 0xa6, 0x3b, 0x35, 0xf9, 0x72, 0x2f, 0x21, 0x17, 0x2d, 0xdd, + /*5b30:*/ 0xa2, 0x39, 0xa5, 0x88, 0xb2, 0x9b, 0xdb, 0x65, 0x3b, 0x70, 0x97, 0xb1, 0xe4, 0x4c, 0xda, 0x69, + /*5b40:*/ 0x88, 0x5c, 0xde, 0x5b, 0x89, 0x42, 0xe5, 0x13, 0x29, 0x73, 0x71, 0xe6, 0x37, 0x8a, 0x3e, 0x69, + /*5b50:*/ 0x66, 0xfd, 0xb2, 0x4b, 0x85, 0xa9, 0x29, 0x11, 0xce, 0x9b, 0x5a, 0x77, 0x48, 0xc8, 0x45, 0x19, + /*5b60:*/ 0x22, 0x07, 0x84, 0x91, 0xa0, 0x91, 0x5d, 0x7b, 0xde, 0x37, 0xd5, 0xcf, 0x62, 0x4e, 0x01, 0xd1, + /*5b70:*/ 0x87, 0x1f, 0xf9, 0x2d, 0xe6, 0x35, 0x67, 0x45, 0x69, 0x5a, 0x50, 0xaf, 0xae, 0xa8, 0x5b, 0x62, + /*5b80:*/ 0xbb, 0x03, 0x86, 0x97, 0x7f, 0x84, 0xe2, 0xbf, 0xc3, 0x04, 0x06, 0x1d, 0x08, 0xbc, 0x6d, 0x8e, + /*5b90:*/ 0xb9, 0x7a, 0x0d, 0xf1, 0x6c, 0xc6, 0x25, 0xd2, 0x17, 0x26, 0x05, 0x4c, 0xe3, 0xd6, 0x52, 0x19, + /*5ba0:*/ 0xf3, 0xd0, 0xb1, 0x0b, 0x62, 0x4d, 0x6c, 0x8e, 0xb8, 0x34, 0x1e, 0xd8, 0x0e, 0x88, 0xe2, 0x91, + /*5bb0:*/ 0xa8, 0xf0, 0xdf, 0x13, 0xb7, 0x5e, 0x12, 0xae, 0x21, 0x6b, 0x0c, 0x60, 0xa4, 0x40, 0xee, 0x1d, + /*5bc0:*/ 0x75, 0xfa, 0xd2, 0x0e, 0x21, 0x57, 0x15, 0x87, 0x0c, 0x30, 0x9f, 0x8a, 0x1c, 0xc6, 0xde, 0x93, + /*5bd0:*/ 0xb9, 0xc5, 0x3f, 0x48, 0x81, 0x07, 0xc0, 0xcb, 0x2f, 0xd3, 0x79, 0x60, 0x99, 0xab, 0x22, 0xa2, + /*5be0:*/ 0xcd, 0xc1, 0x6a, 0x6e, 0x87, 0xdf, 0xf9, 0x32, 0xba, 0x53, 0x25, 0xab, 0x0d, 0x3a, 0xcc, 0x31, + /*5bf0:*/ 0x61, 0x0e, 0xa7, 0x16, 0x4b, 0x2e, 0x1d, 0x94, 0xc5, 0x45, 0x80, 0x0c, 0x16, 0x93, 0x7c, 0xfd, + /*5c00:*/ 0x1f, 0xa1, 0x01, 0x20, 0xfb, 0xe3, 0x93, 0x92, 0x81, 0x38, 0x78, 0xd2, 0xda, 0xbd, 0xcd, 0xf0, + /*5c10:*/ 0xe6, 0x55, 0x6e, 0x33, 0x24, 0x06, 0xcb, 0xf1, 0xb3, 0x14, 0x90, 0x28, 0xe4, 0x33, 0xd7, 0xc8, + /*5c20:*/ 0x0d, 0xbb, 0x79, 0xcc, 0xe5, 0x9f, 0xcd, 0x78, 0x99, 0xb4, 0xab, 0xe1, 0x97, 0x30, 0x26, 0x62, + /*5c30:*/ 0xbe, 0x36, 0xfe, 0x00, 0x4d, 0xdf, 0x68, 0x50, 0x67, 0x63, 0xb6, 0xe2, 0x3b, 0xef, 0xbe, 0x2f, + /*5c40:*/ 0xca, 0xa2, 0xec, 0xc8, 0x79, 0x51, 0x56, 0x8c, 0xae, 0x14, 0xf8, 0xfc, 0x3f, 0x5f, 0x94, 0xdd, + /*5c50:*/ 0xb7, 0x0a, 0x1c, 0x79, 0xea, 0x22, 0x73, 0x33, 0x66, 0x7f, 0x4b, 0x0a, 0xb4, 0x51, 0xbd, 0xa7, + /*5c60:*/ 0xed, 0x46, 0x8f, 0xf9, 0x86, 0x65, 0x31, 0xfd, 0xf0, 0xdc, 0x2e, 0xee, 0xcf, 0xa7, 0x13, 0x9f, + /*5c70:*/ 0x07, 0x78, 0xc6, 0xc6, 0x07, 0x7b, 0x51, 0xda, 0x8f, 0x0b, 0xdb, 0xba, 0xd2, 0xde, 0xc6, 0x63, + /*5c80:*/ 0xbe, 0xd5, 0x92, 0xc6, 0xcb, 0xd3, 0xb3, 0xbb, 0x26, 0xe6, 0x10, 0x1f, 0x83, 0x69, 0x0e, 0x0a, + /*5c90:*/ 0xeb, 0xd5, 0x35, 0x71, 0xed, 0xa8, 0x77, 0x7a, 0x5a, 0x07, 0xaf, 0xd1, 0x3a, 0x00, 0xf6, 0x83, + /*5ca0:*/ 0x7e, 0x0d, 0x6c, 0xed, 0xd8, 0xc6, 0x3c, 0x15, 0x9d, 0xad, 0x5b, 0x1c, 0xb6, 0xfb, 0x4d, 0x89, + /*5cb0:*/ 0x0f, 0xa2, 0x8f, 0xf9, 0x3e, 0x48, 0x77, 0xeb, 0xd0, 0x8a, 0x0e, 0xfe, 0xd2, 0x15, 0x38, 0x1e, + /*5cc0:*/ 0x9c, 0x08, 0x60, 0xd8, 0xbf, 0x95, 0xb9, 0xe9, 0x5d, 0x6d, 0x7b, 0x8c, 0x86, 0x33, 0xe4, 0xb1, + /*5cd0:*/ 0x10, 0xf6, 0x0b, 0x1c, 0x2a, 0xcc, 0xe7, 0x3b, 0xc1, 0x18, 0x14, 0xf5, 0x8b, 0xf4, 0x50, 0x5b, + /*5ce0:*/ 0x64, 0x46, 0x8f, 0xc3, 0x70, 0xfb, 0x68, 0xe6, 0x9a, 0x73, 0x4e, 0x23, 0xc6, 0x21, 0x96, 0xf1, + /*5cf0:*/ 0x9f, 0xca, 0x75, 0xc4, 0xaf, 0xb2, 0xde, 0xd6, 0xa9, 0x5c, 0xa5, 0x18, 0x5d, 0x84, 0x79, 0xe3, + /*5d00:*/ 0xc5, 0xf5, 0x44, 0x5e, 0x63, 0xf0, 0xc8, 0x35, 0x15, 0xe3, 0xff, 0x04, 0x8a, 0x31, 0xd0, 0xee, + /*5d10:*/ 0xc6, 0xe4, 0x77, 0x30, 0xb8, 0x77, 0x49, 0x68, 0x1c, 0x33, 0x99, 0x2d, 0x7e, 0xf5, 0x45, 0xa9, + /*5d20:*/ 0x13, 0x69, 0xc2, 0xab, 0x3f, 0xea, 0x49, 0x07, 0x4b, 0xc9, 0x9d, 0x8a, 0x1f, 0x41, 0x7f, 0xf7, + /*5d30:*/ 0x98, 0x2d, 0x75, 0x11, 0x10, 0x23, 0xb7, 0xab, 0x26, 0x79, 0x04, 0x9c, 0x10, 0x2a, 0x75, 0xef, + /*5d40:*/ 0x54, 0xe6, 0xc7, 0xab, 0x2d, 0xe7, 0xb3, 0xf4, 0xdd, 0x9e, 0xb5, 0xda, 0xbd, 0x7b, 0xe9, 0xbd, + /*5d50:*/ 0x6b, 0xd8, 0xf3, 0x4b, 0x05, 0x76, 0xdb, 0x03, 0xa4, 0x2b, 0x37, 0x20, 0x8b, 0x3e, 0x2b, 0xa2, + /*5d60:*/ 0x18, 0x01, 0x8e, 0xcf, 0xf9, 0x3e, 0x8b, 0xf1, 0x80, 0x24, 0xde, 0x31, 0xd1, 0x81, 0x70, 0xaf, + /*5d70:*/ 0x82, 0xd7, 0x58, 0xa8, 0xdc, 0xce, 0x2b, 0x55, 0x44, 0x21, 0x2b, 0xe1, 0xac, 0x0e, 0x23, 0xe7, + /*5d80:*/ 0xb2, 0x0b, 0x5e, 0x12, 0x3c, 0x4e, 0x6e, 0x3b, 0xf7, 0xbb, 0xce, 0x72, 0x5a, 0x5d, 0x54, 0xa0, + /*5d90:*/ 0xf5, 0x2e, 0xce, 0x9f, 0x76, 0xbf, 0x25, 0xb1, 0xeb, 0x5a, 0xa6, 0x61, 0x7d, 0x98, 0x33, 0x2f, + /*5da0:*/ 0x49, 0x3d, 0xec, 0xdf, 0xef, 0xed, 0xa1, 0x90, 0xeb, 0xde, 0xc3, 0x89, 0xd0, 0x04, 0xa7, 0xa0, + /*5db0:*/ 0xaa, 0xb3, 0xed, 0x54, 0x13, 0xc4, 0x70, 0x90, 0xfa, 0x2a, 0xfd, 0x24, 0x87, 0xf5, 0x12, 0x82, + /*5dc0:*/ 0xf0, 0x39, 0xfd, 0x1a, 0xd5, 0x0f, 0x26, 0x4a, 0xaf, 0x40, 0xb4, 0x2e, 0x3f, 0x9c, 0xa7, 0x35, + /*5dd0:*/ 0xcb, 0x5d, 0xf3, 0x21, 0xea, 0xbf, 0xb9, 0x14, 0x01, 0x06, 0x36, 0xcc, 0x06, 0xba, 0xa9, 0x8a, + /*5de0:*/ 0x32, 0x22, 0x12, 0x22, 0x19, 0xff, 0x64, 0xd2, 0x33, 0x98, 0x90, 0xb0, 0x57, 0xcb, 0xe7, 0x6a, + /*5df0:*/ 0x58, 0xc9, 0x1d, 0x85, 0x08, 0x4e, 0x18, 0x57, 0x4b, 0x20, 0xd6, 0xbe, 0xaa, 0x8c, 0x44, 0xad, + /*5e00:*/ 0x83, 0x78, 0xe5, 0x79, 0x72, 0xc6, 0xa8, 0xf1, 0xe5, 0x09, 0x9d, 0x4f, 0x54, 0xd5, 0xb9, 0x7d, + /*5e10:*/ 0x5b, 0xe8, 0x9f, 0xb1, 0x45, 0xc2, 0xe3, 0xe3, 0xe2, 0xbf, 0x4d, 0xb4, 0x5b, 0x88, 0x15, 0x70, + /*5e20:*/ 0x94, 0xf0, 0xe6, 0x2c, 0x3c, 0x66, 0x15, 0xf2, 0xab, 0xdf, 0x57, 0x74, 0x59, 0x8e, 0x30, 0x0a, + /*5e30:*/ 0x52, 0xe0, 0x96, 0x54, 0x84, 0xbd, 0x28, 0x94, 0x80, 0x4d, 0xac, 0x0a, 0xc1, 0xf6, 0x36, 0x8b, + /*5e40:*/ 0x7b, 0x11, 0xce, 0x6e, 0x43, 0x50, 0xbc, 0x94, 0x93, 0x96, 0x29, 0xe3, 0xf3, 0x28, 0x1b, 0x88, + /*5e50:*/ 0x23, 0xb8, 0x7d, 0x0e, 0xd0, 0xb9, 0x46, 0x81, 0xa1, 0xb3, 0xba, 0xb9, 0x67, 0x48, 0xe6, 0xc5, + /*5e60:*/ 0x11, 0x12, 0xa3, 0xaa, 0xf3, 0x1d, 0xe0, 0x64, 0x20, 0x09, 0x31, 0xe4, 0x21, 0xd1, 0xbb, 0x6c, + /*5e70:*/ 0x67, 0x83, 0x43, 0xd1, 0x9b, 0x91, 0x3d, 0xdf, 0xea, 0xf3, 0xaf, 0x77, 0x4d, 0x58, 0x16, 0xe8, + /*5e80:*/ 0xce, 0xd6, 0x60, 0xaa, 0xa9, 0x40, 0x6d, 0x44, 0xbc, 0xb2, 0x46, 0x27, 0xc3, 0xa3, 0x5c, 0x18, + /*5e90:*/ 0xcd, 0xd9, 0xe5, 0xef, 0x91, 0x14, 0x3b, 0xff, 0xb2, 0xbd, 0x65, 0x9a, 0xf8, 0x75, 0x76, 0x7b, + /*5ea0:*/ 0x0f, 0xf8, 0xad, 0x0b, 0xbf, 0x4b, 0xdf, 0x2e, 0xa8, 0x45, 0xac, 0x4c, 0x3b, 0xb0, 0x18, 0x8e, + /*5eb0:*/ 0xb5, 0x85, 0x23, 0x1b, 0x63, 0xed, 0xaa, 0x09, 0x52, 0xb6, 0x36, 0xe0, 0xb8, 0x15, 0xa8, 0x8b, + /*5ec0:*/ 0x51, 0x4c, 0xa3, 0xca, 0x09, 0x3c, 0xec, 0x83, 0x91, 0xfb, 0x4f, 0x3b, 0xc5, 0x35, 0x4c, 0x13, + /*5ed0:*/ 0x0a, 0x8f, 0x58, 0xb5, 0x19, 0x29, 0xdd, 0x46, 0x53, 0xbd, 0xf4, 0x15, 0xdf, 0x29, 0xf5, 0xa4, + /*5ee0:*/ 0x25, 0x45, 0x85, 0xa3, 0x00, 0x75, 0x4d, 0x38, 0xfb, 0xfe, 0x53, 0xed, 0x1f, 0x14, 0xf2, 0x0e, + /*5ef0:*/ 0xb7, 0x40, 0x62, 0x88, 0x92, 0x54, 0x6e, 0xd2, 0xa5, 0x8d, 0x7a, 0x9b, 0x2b, 0xee, 0x74, 0xb0, + /*5f00:*/ 0xb0, 0x17, 0x2b, 0xd3, 0x46, 0x6a, 0x3d, 0xcb, 0xdc, 0x93, 0x00, 0xfc, 0xf1, 0x3d, 0x4d, 0x25, + /*5f10:*/ 0xe9, 0x8d, 0xdf, 0x8d, 0x0d, 0x4a, 0x3e, 0xcb, 0x58, 0xc2, 0x33, 0x72, 0x0b, 0xd2, 0x8d, 0x55, + /*5f20:*/ 0x74, 0x63, 0x66, 0x3f, 0x9b, 0xeb, 0x77, 0x17, 0xb9, 0x18, 0x9c, 0xc8, 0xb7, 0x9b, 0x52, 0x1c, + /*5f30:*/ 0xbd, 0xa9, 0xa1, 0x3d, 0x51, 0x7e, 0x9a, 0xf8, 0x94, 0x14, 0xb8, 0x59, 0xec, 0xe2, 0x2f, 0xf6, + /*5f40:*/ 0xdd, 0x8a, 0x44, 0x55, 0x72, 0xc8, 0x7b, 0xaf, 0xce, 0xd2, 0x85, 0xb8, 0x71, 0x2d, 0x2e, 0x9e, + /*5f50:*/ 0xcb, 0x22, 0xbf, 0xdb, 0xd3, 0x85, 0x08, 0x7c, 0x48, 0x06, 0xd7, 0xbe, 0x5a, 0xa6, 0x5a, 0xe5, + /*5f60:*/ 0x83, 0x6f, 0xbc, 0xc2, 0xf0, 0xce, 0xc1, 0x8c, 0x54, 0x5e, 0x01, 0x93, 0xc4, 0x48, 0x62, 0x29, + /*5f70:*/ 0xef, 0x74, 0x0a, 0x80, 0xb8, 0x03, 0x61, 0x67, 0x13, 0x38, 0xd5, 0x55, 0x89, 0xc1, 0x51, 0x06, + /*5f80:*/ 0x2f, 0xb6, 0x24, 0x34, 0xbe, 0x92, 0xc9, 0x9b, 0xa4, 0xc8, 0x50, 0x50, 0xb4, 0xf3, 0xba, 0xd3, + /*5f90:*/ 0x77, 0x18, 0xd1, 0x8d, 0x95, 0x11, 0x48, 0x0d, 0xbc, 0x2b, 0x0f, 0xee, 0x04, 0x6a, 0xd8, 0xa0, + /*5fa0:*/ 0x6a, 0xfb, 0x6e, 0xae, 0xac, 0x6c, 0xad, 0x4b, 0x66, 0x61, 0x35, 0x00, 0x29, 0x19, 0x31, 0x7d, + /*5fb0:*/ 0x67, 0x58, 0xd0, 0x95, 0x81, 0xfe, 0x31, 0x46, 0x91, 0xd8, 0xac, 0xb4, 0x5e, 0xbf, 0xf3, 0xfc, + /*5fc0:*/ 0x4a, 0xcc, 0x67, 0xc6, 0xbf, 0x89, 0xb9, 0x9a, 0x83, 0x3a, 0x6a, 0x00, 0xe3, 0x8e, 0x7f, 0x03, + /*5fd0:*/ 0xa2, 0xc6, 0x6e, 0x81, 0x9a, 0xd3, 0xf9, 0x9e, 0xb9, 0xe1, 0x15, 0x01, 0xb3, 0x6d, 0xc4, 0xea, + /*5fe0:*/ 0xa1, 0x3a, 0x29, 0x38, 0x64, 0x07, 0xeb, 0x7c, 0x96, 0x3c, 0x05, 0xc9, 0xee, 0x2c, 0x13, 0x91, + /*5ff0:*/ 0x30, 0x33, 0x84, 0x01, 0x31, 0xe0, 0xef, 0xe9, 0x31, 0x07, 0x59, 0x9b, 0xca, 0xc2, 0x73, 0xc1, + /*6000:*/ 0xbc, 0x1c, 0xd8, 0xc0, 0xce, 0x1d, 0xf4, 0x25, 0x2e, 0x88, 0xa1, 0xc1, 0x48, 0x98, 0x0c, 0xae, + /*6010:*/ 0x01, 0x9f, 0xe0, 0x94, 0x38, 0x4f, 0xd0, 0x8c, 0x36, 0x6b, 0x4d, 0xd5, 0x0b, 0x03, 0x8a, 0x5d, + /*6020:*/ 0x15, 0x3c, 0x3a, 0x09, 0x32, 0x95, 0xd8, 0xdb, 0x9f, 0xcf, 0x71, 0x67, 0x9b, 0xc6, 0xab, 0x87, + /*6030:*/ 0xd4, 0xfe, 0xad, 0xc2, 0xde, 0x17, 0x9c, 0xba, 0x4b, 0x1c, 0x73, 0x69, 0xe4, 0xa5, 0xc1, 0x90, + /*6040:*/ 0x2c, 0x25, 0xec, 0x91, 0x2e, 0xd9, 0x18, 0xe5, 0xa4, 0xfb, 0x4d, 0x6b, 0x31, 0x5d, 0xbb, 0xb5, + /*6050:*/ 0xb9, 0xe1, 0xdc, 0xf6, 0xcd, 0x88, 0x15, 0xbe, 0x82, 0xf7, 0x7e, 0x74, 0x9f, 0x67, 0x84, 0x38, + /*6060:*/ 0x60, 0x25, 0xa6, 0x22, 0x8a, 0xfa, 0xd1, 0x54, 0x9d, 0x4a, 0xab, 0x80, 0x8e, 0xf3, 0x46, 0x92, + /*6070:*/ 0x93, 0xd3, 0x56, 0xdf, 0x3c, 0xed, 0xfe, 0x16, 0x90, 0x7f, 0x22, 0xe8, 0xda, 0x79, 0xe3, 0x4d, + /*6080:*/ 0x32, 0x34, 0x05, 0xa4, 0x1e, 0xf8, 0xa1, 0xa4, 0x73, 0xe8, 0x3b, 0x94, 0xcc, 0xc5, 0x56, 0x86, + /*6090:*/ 0xd5, 0xc5, 0x52, 0x23, 0xf1, 0x3e, 0xbb, 0x73, 0x5f, 0x2e, 0xa4, 0x53, 0x18, 0x1d, 0xeb, 0xbc, + /*60a0:*/ 0xab, 0x38, 0x61, 0x83, 0x15, 0xcf, 0xbc, 0xff, 0xb7, 0x3e, 0x43, 0xa7, 0x48, 0x10, 0x64, 0x52, + /*60b0:*/ 0x3c, 0xae, 0x7c, 0x8f, 0xf0, 0x21, 0x96, 0x99, 0xc4, 0xc5, 0xaa, 0xfe, 0x96, 0xc0, 0x13, 0xa9, + /*60c0:*/ 0x91, 0xe2, 0xb3, 0x6b, 0x52, 0xea, 0x5f, 0xfa, 0xcd, 0xe3, 0x48, 0xd8, 0x8e, 0x8a, 0x8d, 0x8f, + /*60d0:*/ 0x89, 0x45, 0xf0, 0xcb, 0xc8, 0xc7, 0x21, 0x44, 0x22, 0xb3, 0xad, 0x68, 0x55, 0xd1, 0x59, 0xa6, + /*60e0:*/ 0xd0, 0x7e, 0xb2, 0xd3, 0xf1, 0xd1, 0x0a, 0x25, 0xc2, 0x3f, 0x3b, 0x40, 0x34, 0x03, 0x1e, 0xc3, + /*60f0:*/ 0x3c, 0x71, 0x70, 0xf8, 0x3a, 0x6a, 0x9d, 0x7c, 0x46, 0xbb, 0xd7, 0x79, 0x66, 0x6a, 0x3d, 0xb6, + /*6100:*/ 0x6f, 0x57, 0xa8, 0x22, 0xf3, 0x1e, 0x8c, 0x91, 0x44, 0x86, 0xa5, 0x91, 0xce, 0x11, 0x14, 0xc0, + /*6110:*/ 0x13, 0xaa, 0xaa, 0xbe, 0xb0, 0x7f, 0x2b, 0x6b, 0x12, 0x53, 0x75, 0x82, 0xcb, 0x1b, 0x56, 0xf8, + /*6120:*/ 0xc6, 0x1b, 0x83, 0x8c, 0x94, 0xd4, 0xfa, 0x0b, 0x2f, 0x90, 0x0d, 0xf0, 0x05, 0x80, 0xac, 0x2d, + /*6130:*/ 0xf2, 0x1c, 0x7a, 0x53, 0xce, 0x2a, 0xd2, 0xc8, 0xd7, 0x0c, 0x84, 0x60, 0xe1, 0x4d, 0xb1, 0x75, + /*6140:*/ 0x56, 0xc8, 0xf8, 0xab, 0x4d, 0x49, 0x16, 0x87, 0x41, 0x71, 0x1b, 0x0f, 0xed, 0x3a, 0xa6, 0xe4, + /*6150:*/ 0x92, 0x9e, 0xe7, 0xad, 0xb5, 0xb3, 0x0c, 0xa1, 0x7d, 0x00, 0x3d, 0x54, 0x11, 0xc6, 0x34, 0xb8, + /*6160:*/ 0x87, 0x2a, 0xb7, 0xf7, 0x56, 0xd1, 0x3e, 0x18, 0xa1, 0xcc, 0xc0, 0x71, 0x5d, 0xe3, 0x66, 0xf0, + /*6170:*/ 0xea, 0x05, 0xa4, 0xe2, 0x55, 0x77, 0x8c, 0x5c, 0xa5, 0xca, 0xb1, 0xae, 0xf4, 0x0f, 0xb3, 0x9d, + /*6180:*/ 0xb8, 0x0f, 0x1e, 0x0f, 0x8e, 0x5e, 0xbb, 0x0e, 0x26, 0x5e, 0x3a, 0xdc, 0xca, 0xb5, 0xa2, 0xad, + /*6190:*/ 0x1d, 0xfe, 0x65, 0x89, 0x4e, 0x67, 0x8c, 0xe3, 0xc6, 0x61, 0x0f, 0x28, 0x8c, 0x7a, 0xf0, 0x18, + /*61a0:*/ 0x26, 0xbd, 0x05, 0x5f, 0x08, 0xba, 0x7b, 0x76, 0xb3, 0xc0, 0x76, 0x52, 0xfe, 0xda, 0x9b, 0x79, + /*61b0:*/ 0xb9, 0x2b, 0x12, 0x05, 0xdf, 0x3f, 0xa3, 0x92, 0xff, 0x2f, 0x82, 0x65, 0x0c, 0xe6, 0x10, 0x26, + /*61c0:*/ 0x20, 0x3a, 0xbf, 0x49, 0x70, 0x40, 0x94, 0xd3, 0xc2, 0xd9, 0xf1, 0x66, 0xc4, 0x79, 0x57, 0xe6, + /*61d0:*/ 0xcd, 0x93, 0xd8, 0xc7, 0x21, 0xd0, 0x4d, 0x71, 0x39, 0x4c, 0xaf, 0xdf, 0xb8, 0x34, 0xa7, 0xdc, + /*61e0:*/ 0x94, 0x78, 0x2e, 0x1a, 0x6c, 0x1b, 0xb6, 0xe7, 0x18, 0x45, 0xb7, 0x05, 0xe9, 0x12, 0x20, 0x95, + /*61f0:*/ 0xa2, 0x6c, 0x35, 0x27, 0xaf, 0xdf, 0xed, 0x1f, 0x70, 0xd5, 0x74, 0x44, 0x65, 0x54, 0x38, 0x12, + /*6200:*/ 0x9c, 0xe8, 0x59, 0x3f, 0x9a, 0x07, 0x44, 0x32, 0xa7, 0x4b, 0x0a, 0xe5, 0x1d, 0x08, 0x82, 0x86, + /*6210:*/ 0xcf, 0x99, 0x47, 0x8d, 0xb4, 0x29, 0xa4, 0x96, 0x3f, 0x65, 0x8e, 0xaf, 0xb4, 0x44, 0xe9, 0x69, + /*6220:*/ 0x1e, 0xe8, 0xc8, 0xcb, 0x67, 0xd9, 0x78, 0x2e, 0xbb, 0x11, 0x72, 0xed, 0x4f, 0xe5, 0x95, 0xad, + /*6230:*/ 0x13, 0xc9, 0x68, 0x0c, 0x0e, 0xe4, 0xde, 0xcf, 0xb1, 0x65, 0xc5, 0x36, 0xe9, 0xeb, 0x25, 0xe7, + /*6240:*/ 0xdf, 0xe5, 0x02, 0x09, 0x31, 0x37, 0x99, 0x7a, 0xe3, 0xe5, 0x34, 0xf6, 0xea, 0x6e, 0xcc, 0x39, + /*6250:*/ 0x64, 0xbe, 0xb3, 0xd3, 0x0f, 0xf2, 0x7e, 0x18, 0xba, 0x53, 0x35, 0x19, 0x3f, 0x9f, 0x5a, 0x80, + /*6260:*/ 0x2a, 0xbb, 0x7e, 0x92, 0x31, 0xfd, 0x2a, 0x66, 0xee, 0x54, 0xd0, 0x32, 0xa3, 0x53, 0x2d, 0xfc, + /*6270:*/ 0xf5, 0x59, 0x13, 0xe1, 0xb0, 0xe9, 0x31, 0x07, 0x19, 0xe5, 0x08, 0x8e, 0x24, 0x87, 0x39, 0x8b, + /*6280:*/ 0xb2, 0xa8, 0xde, 0x81, 0xaa, 0x47, 0x5b, 0x9a, 0x41, 0xd5, 0xda, 0xb9, 0x61, 0x59, 0x4f, 0x30, + /*6290:*/ 0x25, 0xa3, 0x56, 0x4f, 0x9b, 0x9e, 0x63, 0x96, 0x75, 0xba, 0xfd, 0xf0, 0x4b, 0x64, 0x73, 0xbb, + /*62a0:*/ 0xa2, 0x96, 0x5b, 0xbf, 0xce, 0xc3, 0xa1, 0xa8, 0x90, 0xc9, 0x19, 0xf7, 0xb1, 0x82, 0xb7, 0xcc, + /*62b0:*/ 0xb1, 0x57, 0xa0, 0x13, 0x7c, 0x60, 0x34, 0x32, 0x65, 0xba, 0xf2, 0x5f, 0x41, 0xdc, 0x00, 0xd1, + /*62c0:*/ 0x5a, 0x38, 0xb6, 0x4f, 0x4d, 0xec, 0x18, 0x31, 0xc3, 0x8b, 0xaa, 0x06, 0xda, 0x2f, 0x2e, 0x7c, + /*62d0:*/ 0x2b, 0x57, 0x29, 0x81, 0x43, 0xb2, 0xca, 0xb9, 0x61, 0x2c, 0x94, 0x5e, 0x8e, 0xa2, 0x33, 0x80, + /*62e0:*/ 0x0a, 0x4b, 0x58, 0xa7, 0x1c, 0xf7, 0x0d, 0xc0, 0x1a, 0x61, 0x14, 0xf8, 0x82, 0x57, 0x5b, 0x0d, + /*62f0:*/ 0x17, 0x71, 0x8d, 0xf9, 0x42, 0x9a, 0x41, 0x1f, 0x84, 0x98, 0xcb, 0x38, 0x25, 0x4a, 0xb9, 0x0a, + /*6300:*/ 0xf1, 0xfc, 0x94, 0x14, 0x21, 0x51, 0xe3, 0xe5, 0x1a, 0xd9, 0x70, 0x31, 0x1a, 0x84, 0xaf, 0x08, + /*6310:*/ 0x20, 0x9f, 0x96, 0x61, 0x84, 0xf5, 0xfb, 0xfc, 0x4f, 0xf0, 0xb7, 0xcc, 0xef, 0x99, 0xb9, 0x6d, + /*6320:*/ 0x95, 0x11, 0x57, 0x20, 0x62, 0x62, 0xa8, 0xfb, 0xec, 0xf1, 0x0f, 0xcc, 0xc9, 0xf0, 0x63, 0xb8, + /*6330:*/ 0x59, 0xa4, 0xf8, 0xb0, 0xfd, 0xf6, 0xe2, 0x61, 0x45, 0x9b, 0xb4, 0x18, 0xf5, 0xe5, 0x9f, 0x3e, + /*6340:*/ 0x97, 0xe7, 0x3f, 0x08, 0xf7, 0x63, 0x9b, 0x71, 0x4f, 0x06, 0x95, 0x66, 0xa7, 0x2e, 0xa1, 0xa3, + /*6350:*/ 0xef, 0x22, 0xf7, 0x82, 0x00, 0xf8, 0xc6, 0x04, 0x03, 0xf6, 0x90, 0x4d, 0xd2, 0xe7, 0xb2, 0xda, + /*6360:*/ 0xeb, 0x4b, 0xff, 0x40, 0x33, 0x28, 0xed, 0x33, 0x81, 0x9e, 0xfa, 0x18, 0x43, 0xac, 0x82, 0x99, + /*6370:*/ 0x09, 0xa5, 0x7c, 0xd7, 0xc0, 0xf2, 0x9a, 0xeb, 0xb4, 0xb6, 0x18, 0x9a, 0x9c, 0x8e, 0x5e, 0xed, + /*6380:*/ 0x49, 0x18, 0xb6, 0x14, 0x74, 0x3b, 0x19, 0x2d, 0xa0, 0xdf, 0xc0, 0xa3, 0x56, 0x6b, 0x17, 0x80, + /*6390:*/ 0x40, 0x36, 0x2f, 0x5b, 0xf8, 0xc0, 0x39, 0x0b, 0x64, 0x73, 0x31, 0x15, 0x0f, 0x54, 0x3d, 0x52, + /*63a0:*/ 0x39, 0x99, 0xe3, 0x37, 0xaf, 0xae, 0xaa, 0xf2, 0x1e, 0xc4, 0x53, 0x41, 0xa8, 0x41, 0x82, 0x5c, + /*63b0:*/ 0xde, 0x4a, 0xef, 0xa9, 0x4b, 0x31, 0xfe, 0xdb, 0x5a, 0x2d, 0x55, 0xa2, 0x5a, 0x84, 0xda, 0xfc, + /*63c0:*/ 0x47, 0xbc, 0x8c, 0x5f, 0x6c, 0x30, 0x6f, 0xb7, 0xb0, 0x57, 0xe2, 0xe3, 0x30, 0x75, 0xae, 0x9d, + /*63d0:*/ 0x78, 0xd5, 0x98, 0x44, 0xee, 0x86, 0x44, 0x3c, 0xfd, 0x18, 0x0d, 0x5c, 0x16, 0x86, 0x04, 0xdb, + /*63e0:*/ 0x8a, 0xda, 0x0c, 0x37, 0xef, 0xb1, 0xea, 0xe5, 0x7c, 0x10, 0x6a, 0x17, 0x01, 0xd4, 0x44, 0x4e, + /*63f0:*/ 0xf3, 0xb3, 0x47, 0xce, 0x10, 0x78, 0x6e, 0x69, 0x98, 0x3e, 0x61, 0x21, 0xde, 0x65, 0x50, 0xb4, + /*6400:*/ 0x2e, 0x08, 0x08, 0x6b, 0xef, 0x25, 0x1b, 0x9d, 0x68, 0xee, 0xd0, 0xce, 0xd5, 0x36, 0xb0, 0xcd, + /*6410:*/ 0x4e, 0x0c, 0x19, 0x59, 0x57, 0xd8, 0xa1, 0x69, 0xe5, 0x1f, 0xba, 0x8d, 0x28, 0xa4, 0xe0, 0x56, + /*6420:*/ 0xdf, 0xab, 0xd0, 0x2a, 0x27, 0x60, 0xd3, 0xa1, 0x69, 0xbb, 0x77, 0xe5, 0xef, 0xa8, 0x99, 0xb4, + /*6430:*/ 0x3f, 0xc1, 0x09, 0x72, 0x69, 0xe9, 0x73, 0x5b, 0x59, 0x48, 0x4c, 0x1d, 0x9d, 0x73, 0xb6, 0x8e, + /*6440:*/ 0x2a, 0x66, 0x7e, 0xf5, 0xaf, 0x12, 0x69, 0xcf, 0x61, 0xbd, 0xd3, 0x84, 0xd3, 0x3a, 0xe4, 0xbf, + /*6450:*/ 0x7f, 0xeb, 0x21, 0x59, 0x72, 0x7c, 0xa6, 0x89, 0x6b, 0x2e, 0xc9, 0x46, 0xa8, 0x05, 0xc9, 0xf9, + /*6460:*/ 0x7a, 0x25, 0x27, 0xb8, 0xda, 0x80, 0xf6, 0xa7, 0x69, 0x28, 0x06, 0x5d, 0x8e, 0xa6, 0x0d, 0x3c, + /*6470:*/ 0x7b, 0x2a, 0xce, 0x1a, 0x13, 0x53, 0x98, 0x85, 0x1f, 0xc9, 0xce, 0xd0, 0xd4, 0x76, 0x6d, 0x6e, + /*6480:*/ 0xa9, 0x4e, 0x5a, 0x44, 0xc2, 0xb4, 0x6f, 0x5e, 0xe8, 0x8c, 0x88, 0xfb, 0xe2, 0x1e, 0x4b, 0x1a, + /*6490:*/ 0xa9, 0x55, 0x09, 0x70, 0x73, 0xf9, 0x4f, 0xd4, 0x4a, 0x53, 0xaa, 0x7e, 0x67, 0xe5, 0x61, 0x13, + /*64a0:*/ 0x53, 0xfc, 0xef, 0xe6, 0x82, 0x6a, 0xdf, 0x82, 0x87, 0x93, 0x8f, 0x85, 0x7a, 0x8e, 0x7a, 0xb9, + /*64b0:*/ 0xd8, 0xf9, 0xac, 0x79, 0x2c, 0x87, 0x9f, 0x40, 0x9a, 0xe3, 0x8b, 0xbd, 0x15, 0xaf, 0x70, 0xfb, + /*64c0:*/ 0x7f, 0x80, 0x74, 0x6c, 0x94, 0x02, 0x0d, 0xd2, 0x41, 0x7f, 0xe2, 0x38, 0xcb, 0xfe, 0x99, 0xef, + /*64d0:*/ 0xd7, 0x0e, 0x74, 0x93, 0x66, 0xae, 0xa7, 0x10, 0x42, 0x10, 0xf6, 0x77, 0x5e, 0x16, 0xe7, 0x4c, + /*64e0:*/ 0x41, 0x51, 0xc8, 0x80, 0x6c, 0xaf, 0xb9, 0xb6, 0x91, 0x17, 0xb3, 0xba, 0x00, 0x07, 0xe4, 0xd1, + /*64f0:*/ 0x89, 0x05, 0x31, 0xc9, 0x6c, 0x5a, 0x8f, 0x4c, 0xd2, 0x03, 0xe7, 0x79, 0x65, 0xfb, 0x6a, 0x60, + /*6500:*/ 0x6c, 0x1d, 0x88, 0x94, 0xf3, 0xc0, 0x15, 0xd0, 0xc3, 0xad, 0x93, 0x81, 0xee, 0x3e, 0x48, 0x9b, + /*6510:*/ 0xa7, 0xe8, 0x9b, 0x26, 0x55, 0x97, 0xcd, 0x15, 0xc1, 0xf0, 0x97, 0xb0, 0x47, 0x42, 0xba, 0xea, + /*6520:*/ 0x04, 0x2e, 0x31, 0xf8, 0xb3, 0xf5, 0xcb, 0xa4, 0xec, 0xf5, 0x59, 0xe4, 0x8f, 0x03, 0x69, 0x85, + /*6530:*/ 0x94, 0x55, 0x00, 0xeb, 0xa5, 0x15, 0xca, 0xe2, 0xac, 0xc7, 0xfb, 0x79, 0x23, 0xbc, 0x60, 0x2b, + /*6540:*/ 0x87, 0xcc, 0x55, 0xc5, 0xe8, 0x79, 0xd0, 0x1e, 0x4b, 0xde, 0xf6, 0xf0, 0x26, 0x87, 0x88, 0x29, + /*6550:*/ 0xf4, 0x78, 0x77, 0x42, 0xaf, 0x38, 0x53, 0xc4, 0x91, 0x7b, 0xf0, 0x2d, 0x12, 0x2d, 0xa3, 0x15, + /*6560:*/ 0xaf, 0x2d, 0x0d, 0xd1, 0xc5, 0x07, 0x55, 0x03, 0x8c, 0x1a, 0x51, 0x5d, 0x1c, 0xcb, 0xd2, 0xd5, + /*6570:*/ 0x6a, 0x9b, 0x6e, 0x48, 0x35, 0x7d, 0xd0, 0xc0, 0x45, 0x8f, 0x14, 0xca, 0x74, 0x9f, 0x84, 0xf8, + /*6580:*/ 0xd3, 0xd3, 0xe6, 0x14, 0x66, 0xc6, 0x8c, 0xde, 0x3b, 0x54, 0x33, 0x69, 0x20, 0x23, 0x60, 0x3d, + /*6590:*/ 0xc4, 0xd5, 0x7c, 0xc6, 0xa9, 0xd9, 0xf0, 0xbd, 0x4b, 0xbd, 0x0d, 0x5c, 0xea, 0x74, 0x0a, 0x6a, + /*65a0:*/ 0x17, 0x0d, 0x71, 0xfd, 0x9b, 0xa9, 0x0a, 0x1c, 0x80, 0xf6, 0x2a, 0xd9, 0xf7, 0x2f, 0x1b, 0x41, + /*65b0:*/ 0x06, 0x09, 0x10, 0x95, 0xfc, 0xbd, 0xe4, 0x81, 0x54, 0x47, 0x0e, 0xfd, 0xca, 0xe5, 0x6f, 0x49, + /*65c0:*/ 0x39, 0xe7, 0xb4, 0xea, 0x75, 0x3c, 0x02, 0x76, 0xb5, 0xa8, 0x0e, 0x4b, 0x81, 0x2d, 0xbc, 0x9d, + /*65d0:*/ 0xc9, 0x88, 0xea, 0x8f, 0xde, 0x8d, 0xdb, 0x69, 0x91, 0x6b, 0x30, 0xbf, 0xdb, 0x43, 0x57, 0xa3, + /*65e0:*/ 0xd2, 0xde, 0x8b, 0x8e, 0xaa, 0xc0, 0x46, 0xb5, 0x09, 0x61, 0xfd, 0x92, 0x11, 0x78, 0x73, 0xed, + /*65f0:*/ 0x89, 0xa3, 0xf9, 0x33, 0xd8, 0x5f, 0xbe, 0x1c, 0x82, 0x6c, 0xd1, 0xd0, 0x58, 0xb5, 0x72, 0x43, + /*6600:*/ 0x37, 0xd6, 0xca, 0x98, 0x30, 0x9c, 0x29, 0xae, 0x11, 0x14, 0x73, 0x17, 0x6d, 0x10, 0xea, 0xa6, + /*6610:*/ 0x2d, 0xf3, 0x1b, 0xe4, 0xd2, 0xba, 0x01, 0x52, 0x4b, 0xe9, 0x54, 0xb5, 0x3f, 0x9c, 0xb4, 0x9e, + /*6620:*/ 0xac, 0xe0, 0x93, 0x6d, 0xdc, 0x1d, 0xfa, 0xf7, 0x04, 0x8f, 0x4a, 0x7e, 0x97, 0xf3, 0x01, 0x38, + /*6630:*/ 0x2f, 0xa2, 0x3d, 0xcf, 0xd1, 0x4c, 0x6c, 0x57, 0xb5, 0x8e, 0xb3, 0x59, 0xdd, 0x84, 0x8c, 0x1a, + /*6640:*/ 0xaa, 0xc4, 0x9a, 0x6d, 0x7d, 0xd2, 0xf3, 0x5f, 0x60, 0x2d, 0xd3, 0xc3, 0xdb, 0x3c, 0xef, 0xea, + /*6650:*/ 0x0c, 0x99, 0x3a, 0xd0, 0xb5, 0xbb, 0xda, 0xcc, 0x35, 0xce, 0x81, 0xc1, 0x15, 0x61, 0x2d, 0x7c, + /*6660:*/ 0x20, 0xb1, 0x2a, 0x4c, 0x19, 0x79, 0xff, 0xe7, 0xfd, 0xa2, 0x7c, 0xd4, 0x81, 0xef, 0xd6, 0xc7, + /*6670:*/ 0x89, 0xfd, 0x67, 0x8f, 0xa0, 0x64, 0xb9, 0x84, 0x68, 0x87, 0xa2, 0x7d, 0x21, 0xa9, 0xd4, 0x28, + /*6680:*/ 0x89, 0x0d, 0x62, 0x08, 0x25, 0xb6, 0x41, 0x9f, 0x0c, 0x3b, 0xdf, 0x0d, 0x86, 0x9c, 0xbd, 0x16, + /*6690:*/ 0x6f, 0x03, 0x1b, 0xd8, 0x1c, 0x00, 0x91, 0x14, 0xc1, 0x3a, 0x45, 0x96, 0xa4, 0x4c, 0xa3, 0x27, + /*66a0:*/ 0x31, 0x4d, 0xf7, 0x8b, 0x69, 0xdc, 0xab, 0x4e, 0x91, 0xb7, 0x68, 0x46, 0x52, 0x04, 0xb4, 0xf0, + /*66b0:*/ 0xa3, 0x7d, 0xf2, 0xa3, 0x14, 0xb4, 0x12, 0xda, 0xa1, 0xb4, 0xa9, 0x6b, 0x22, 0x49, 0x0c, 0xaa, + /*66c0:*/ 0x1a, 0x95, 0x57, 0x4c, 0x6c, 0x0b, 0x72, 0x36, 0xf9, 0x02, 0x41, 0x17, 0xc9, 0x70, 0x7e, 0x10, + /*66d0:*/ 0xce, 0x4c, 0xd2, 0xa0, 0x46, 0xac, 0x64, 0x5a, 0x53, 0x12, 0x5a, 0xd1, 0x4b, 0x5c, 0x87, 0xa0, + /*66e0:*/ 0xb6, 0xc9, 0xf5, 0x6e, 0xa2, 0xbb, 0x3b, 0x6c, 0x55, 0x67, 0x73, 0xe2, 0x01, 0x5d, 0xac, 0x26, + /*66f0:*/ 0xad, 0x79, 0xc4, 0x56, 0x2c, 0x33, 0x66, 0x7b, 0xb9, 0xdf, 0x4f, 0x9e, 0xe5, 0x13, 0xb8, 0xf0, + /*6700:*/ 0x70, 0x53, 0x59, 0xa0, 0xc2, 0x74, 0xc5, 0xeb, 0x76, 0x4e, 0x1c, 0x0d, 0xfe, 0x98, 0x05, 0x57, + /*6710:*/ 0xd5, 0xbe, 0x81, 0xb2, 0x67, 0x0a, 0xcc, 0xde, 0xc1, 0x4e, 0x07, 0x80, 0x34, 0xee, 0x20, 0x93, + /*6720:*/ 0xbd, 0xc1, 0xd6, 0x72, 0x47, 0x17, 0xe0, 0x27, 0x90, 0xca, 0x97, 0x0e, 0x0f, 0x6c, 0xcc, 0xe2, + /*6730:*/ 0x97, 0x47, 0x49, 0x0c, 0x73, 0xaf, 0x47, 0x8d, 0x8a, 0x2a, 0x6e, 0xfb, 0x79, 0x81, 0xe2, 0xc8, + /*6740:*/ 0x97, 0x9f, 0x7e, 0x9b, 0xf4, 0x9a, 0x8f, 0x10, 0x75, 0x23, 0x4a, 0xb9, 0xbd, 0x0d, 0x25, 0xa1, + /*6750:*/ 0x50, 0xdf, 0x40, 0x23, 0xbf, 0x1c, 0x83, 0xcd, 0x4c, 0xb7, 0xa3, 0x51, 0x7f, 0xca, 0x44, 0x23, + /*6760:*/ 0xbe, 0xd8, 0x74, 0x8a, 0x4c, 0xb3, 0x72, 0x93, 0xaa, 0x9a, 0x32, 0x11, 0xc1, 0x4b, 0x9b, 0x96, + /*6770:*/ 0x88, 0x61, 0xc7, 0x22, 0xa3, 0x6c, 0x28, 0xf1, 0x17, 0xa5, 0x02, 0x5e, 0x6d, 0x71, 0x44, 0xe7, + /*6780:*/ 0xa6, 0x63, 0x9e, 0xee, 0xc6, 0xef, 0xc0, 0x18, 0xf8, 0xea, 0xf8, 0x78, 0x73, 0x8f, 0xae, 0xed, + /*6790:*/ 0xb3, 0x5b, 0x80, 0x12, 0x5b, 0x47, 0x48, 0x54, 0x3a, 0xf3, 0xaf, 0x37, 0x14, 0xc3, 0x8c, 0x09, + /*67a0:*/ 0x1e, 0x11, 0xb5, 0xc2, 0x82, 0xef, 0x31, 0x36, 0xe6, 0x73, 0xbe, 0xea, 0x98, 0x4f, 0x14, 0x17, + /*67b0:*/ 0x1d, 0xbb, 0x89, 0xba, 0x95, 0xf6, 0x79, 0xa9, 0x71, 0xc0, 0x47, 0xf1, 0x86, 0x18, 0x7c, 0x74, + /*67c0:*/ 0x18, 0x27, 0xb7, 0x28, 0x27, 0xf6, 0x2a, 0x4a, 0xcc, 0x8e, 0x7a, 0x0f, 0x90, 0x65, 0x9a, 0xc0, + /*67d0:*/ 0xd1, 0xba, 0xf3, 0xd8, 0x49, 0x6a, 0x88, 0x68, 0x41, 0xaa, 0xb9, 0x28, 0xfe, 0x4f, 0xe4, 0x3e, + /*67e0:*/ 0x1b, 0xc8, 0xa2, 0x0f, 0x38, 0x8d, 0x7b, 0x63, 0xee, 0x46, 0xbd, 0xa2, 0x75, 0xb3, 0x27, 0x35, + /*67f0:*/ 0x72, 0xa7, 0xd4, 0xdd, 0xea, 0xdb, 0xb6, 0x1a, 0x65, 0x39, 0xce, 0xc3, 0x83, 0x65, 0x2d, 0x83, + /*6800:*/ 0xb0, 0xf1, 0xd9, 0xa1, 0xb0, 0x48, 0x0f, 0x55, 0x48, 0x3b, 0x78, 0x98, 0xc9, 0x3a, 0x93, 0xbc, + /*6810:*/ 0xdb, 0x43, 0x32, 0x27, 0xf6, 0xba, 0xb7, 0xb7, 0x99, 0x11, 0x04, 0xa9, 0x4f, 0x8f, 0x89, 0x30, + /*6820:*/ 0x19, 0xad, 0x0d, 0x30, 0xfd, 0x02, 0xfa, 0x87, 0x73, 0xc1, 0x18, 0x07, 0x51, 0x54, 0x1b, 0xdf, + /*6830:*/ 0xae, 0xfd, 0x6f, 0x62, 0x23, 0x0b, 0x7b, 0xfb, 0x8a, 0xf8, 0x2b, 0xcc, 0x69, 0x0e, 0x56, 0x6d, + /*6840:*/ 0x35, 0x9d, 0xbd, 0x71, 0x51, 0xa7, 0xd9, 0xeb, 0x34, 0x9a, 0x95, 0x9d, 0x52, 0x71, 0x3e, 0x04, + /*6850:*/ 0x9f, 0x20, 0xfb, 0xf8, 0x6a, 0xf7, 0x7d, 0x3e, 0x1f, 0xeb, 0x71, 0xe4, 0xf1, 0xbf, 0xb8, 0xb9, + /*6860:*/ 0x62, 0x70, 0x84, 0x87, 0xdc, 0x9e, 0xaf, 0x21, 0xd7, 0xa3, 0x58, 0x03, 0x90, 0x9e, 0xcb, 0x9f, + /*6870:*/ 0x5d, 0x48, 0xfb, 0xb7, 0xa6, 0x0e, 0x94, 0xb2, 0xaa, 0x4a, 0xb5, 0x7e, 0xfc, 0x6b, 0xd1, 0x59, + /*6880:*/ 0x80, 0xec, 0xb0, 0x91, 0x68, 0x62, 0xd1, 0x93, 0x25, 0x70, 0xf7, 0x47, 0x31, 0x69, 0xc9, 0x05, + /*6890:*/ 0x31, 0x5b, 0x97, 0x48, 0x28, 0xee, 0xb0, 0x77, 0xac, 0x56, 0xde, 0xb0, 0x5f, 0x14, 0x19, 0x58, + /*68a0:*/ 0x1f, 0xd1, 0x31, 0xf6, 0x02, 0xcb, 0x81, 0x6a, 0xac, 0x57, 0x62, 0xea, 0xb9, 0xf0, 0x8f, 0xfd, + /*68b0:*/ 0x78, 0xbf, 0xbc, 0x3b, 0xf2, 0x41, 0x2c, 0xff, 0x6e, 0x83, 0x5d, 0xde, 0x22, 0x7b, 0x48, 0x65, + /*68c0:*/ 0xac, 0x72, 0xce, 0x12, 0xcf, 0x0c, 0x27, 0x9b, 0xd5, 0x8d, 0xf3, 0x32, 0x1a, 0x4f, 0x67, 0xa6, + /*68d0:*/ 0xeb, 0x6a, 0x4c, 0xc8, 0x81, 0x35, 0xd0, 0x22, 0x75, 0xc9, 0xd1, 0x29, 0x8e, 0x42, 0x73, 0x99, + /*68e0:*/ 0xdd, 0x50, 0x7e, 0x3c, 0xcb, 0x5f, 0xca, 0xbf, 0x8d, 0x66, 0x13, 0x0e, 0x19, 0x01, 0x58, 0x2d, + /*68f0:*/ 0x16, 0x91, 0xb4, 0x40, 0xba, 0xed, 0x9a, 0x02, 0x04, 0xa3, 0x82, 0x14, 0x9d, 0x8b, 0xcc, 0xd5, + /*6900:*/ 0xf5, 0x6f, 0x78, 0x60, 0xe5, 0x8b, 0x06, 0xc7, 0xf0, 0xb0, 0x5d, 0xd7, 0x2e, 0x0f, 0xa0, 0x6b, + /*6910:*/ 0x39, 0xcd, 0xb4, 0x2a, 0x2d, 0x81, 0x97, 0xa1, 0xab, 0x07, 0x8c, 0x7e, 0xbc, 0x68, 0x13, 0x38, + /*6920:*/ 0x85, 0x0a, 0x88, 0x17, 0xf3, 0xba, 0xbf, 0x58, 0x9c, 0xbe, 0x43, 0x3d, 0x36, 0xc3, 0x92, 0x8c, + /*6930:*/ 0x31, 0x90, 0xe3, 0x05, 0x3f, 0x6a, 0x25, 0x6e, 0x65, 0xd7, 0x62, 0x60, 0x6e, 0x79, 0x02, 0x62, + /*6940:*/ 0xec, 0xd5, 0x9b, 0x99, 0xe4, 0x30, 0xd8, 0xf1, 0x99, 0x45, 0x9d, 0xfb, 0x62, 0x5a, 0x3f, 0x3e, + /*6950:*/ 0x2d, 0x75, 0x94, 0x5c, 0x04, 0x31, 0xc0, 0x56, 0xeb, 0x37, 0x29, 0x60, 0x3c, 0x29, 0x63, 0x54, + /*6960:*/ 0x24, 0x1f, 0x34, 0xd3, 0x81, 0x5c, 0x2b, 0x07, 0x78, 0x6a, 0xab, 0x85, 0x02, 0x50, 0xd3, 0x0f, + /*6970:*/ 0x0f, 0x94, 0x3b, 0x33, 0x9a, 0xcc, 0x99, 0xad, 0xcc, 0xfc, 0xa3, 0xdf, 0xc9, 0xe7, 0x90, 0xb7, + /*6980:*/ 0xc1, 0x76, 0xb5, 0x01, 0x66, 0xa1, 0x33, 0x38, 0x26, 0xa6, 0xbb, 0xff, 0xaf, 0x10, 0x27, 0x0a, + /*6990:*/ 0x96, 0x6b, 0x1d, 0x74, 0xb1, 0x7d, 0xa9, 0x17, 0x5c, 0x4f, 0x2d, 0x2e, 0x69, 0xaa, 0xb6, 0x4f, + /*69a0:*/ 0x95, 0xa7, 0x90, 0xcd, 0x1b, 0x60, 0xb0, 0x68, 0x93, 0x91, 0xba, 0x34, 0xa8, 0x2d, 0xe4, 0xfe, + /*69b0:*/ 0xa0, 0x8b, 0x9e, 0x82, 0x77, 0x7a, 0xe3, 0x32, 0xc1, 0x8c, 0x50, 0xdf, 0x49, 0x5f, 0x57, 0xd4, + /*69c0:*/ 0x55, 0xe4, 0x25, 0xf0, 0x07, 0x91, 0xaa, 0x77, 0x9b, 0xf9, 0x99, 0xfb, 0x98, 0xd0, 0x01, 0xf8, + /*69d0:*/ 0x6b, 0x14, 0xd3, 0xc1, 0x2d, 0xcb, 0x3e, 0xb7, 0xd5, 0xe8, 0x61, 0x20, 0xbd, 0xa5, 0xe3, 0xe0, + /*69e0:*/ 0x11, 0x6e, 0x3b, 0xe5, 0x6e, 0xe0, 0xdc, 0x2f, 0x4c, 0x8b, 0x14, 0xa7, 0x08, 0x93, 0xcd, 0xf3, + /*69f0:*/ 0x5c, 0x8e, 0x30, 0xab, 0x09, 0x36, 0x70, 0xe9, 0x0c, 0x09, 0x93, 0x45, 0xad, 0x2a, 0x6c, 0xdf, + /*6a00:*/ 0x30, 0xe9, 0x50, 0xae, 0x8b, 0x94, 0x5f, 0x20, 0x52, 0xf1, 0x91, 0x22, 0x07, 0xb6, 0x3a, 0x14, + /*6a10:*/ 0xa1, 0x33, 0x78, 0x80, 0xa6, 0x49, 0x08, 0xbf, 0xfc, 0xc2, 0x4c, 0x49, 0xee, 0x93, 0x33, 0x77, + /*6a20:*/ 0xfd, 0x7d, 0xb6, 0x3d, 0x23, 0x8f, 0x5a, 0x90, 0xa0, 0xe0, 0x3c, 0xc9, 0x93, 0x97, 0x00, 0x16, + /*6a30:*/ 0xc2, 0xeb, 0x9b, 0xfa, 0x24, 0x04, 0xc7, 0x9e, 0x46, 0xbf, 0x14, 0xa7, 0x97, 0x03, 0x5d, 0x25, + /*6a40:*/ 0x08, 0xb2, 0xf4, 0xa0, 0x1e, 0xe5, 0x47, 0x36, 0x64, 0x7e, 0xab, 0x5d, 0xa8, 0x04, 0x18, 0x84, + /*6a50:*/ 0x8e, 0x3d, 0x96, 0xa8, 0xc9, 0xfb, 0xe0, 0x1f, 0x8d, 0xa8, 0x77, 0x73, 0xe5, 0x6c, 0xcf, 0xbf, + /*6a60:*/ 0x65, 0x9c, 0x73, 0x73, 0xed, 0x36, 0x18, 0xbd, 0xcb, 0xd0, 0xb2, 0x87, 0xea, 0x0a, 0x18, 0xf5, + /*6a70:*/ 0x7c, 0x0f, 0xf7, 0x6b, 0x35, 0x4f, 0xd9, 0x07, 0x8a, 0xa1, 0xa4, 0x21, 0x40, 0x81, 0x75, 0xff, + /*6a80:*/ 0x73, 0xeb, 0xcb, 0xda, 0x30, 0x09, 0xd5, 0x2a, 0x30, 0x5c, 0xd7, 0x86, 0x72, 0xe5, 0xc9, 0x31, + /*6a90:*/ 0xca, 0x91, 0xc9, 0x90, 0x48, 0xae, 0x14, 0x59, 0xc3, 0x7e, 0x82, 0xb6, 0x9d, 0x56, 0x10, 0x59, + /*6aa0:*/ 0xd7, 0x14, 0xbb, 0x47, 0x61, 0xd8, 0x53, 0x2b, 0x56, 0x62, 0xf2, 0x8f, 0x84, 0x58, 0x1b, 0xfb, + /*6ab0:*/ 0x95, 0x8d, 0x29, 0x78, 0xf5, 0x35, 0xeb, 0xe0, 0xe1, 0x1e, 0x9b, 0x66, 0x5f, 0xbd, 0xf9, 0x8f, + /*6ac0:*/ 0x3d, 0x12, 0x95, 0xb2, 0xbb, 0x75, 0x84, 0x36, 0x51, 0x33, 0xfa, 0x5a, 0x32, 0x16, 0x93, 0x12, + /*6ad0:*/ 0x12, 0x31, 0xb5, 0x48, 0x14, 0xb4, 0xdc, 0xcb, 0xb3, 0x38, 0xa7, 0x0b, 0x60, 0x56, 0xfa, 0x73, + /*6ae0:*/ 0x28, 0x5d, 0xcf, 0x1b, 0x56, 0x4d, 0x6f, 0xea, 0xea, 0xbd, 0xfc, 0xe6, 0x3c, 0x5c, 0x41, 0x8a, + /*6af0:*/ 0x3f, 0x6c, 0xfc, 0x7d, 0x8b, 0x66, 0x4d, 0x51, 0x8d, 0x71, 0x0e, 0xbf, 0xdd, 0xa1, 0x1e, 0x92, + /*6b00:*/ 0x7c, 0x4e, 0xd4, 0x6e, 0x0c, 0xaa, 0x50, 0x96, 0xce, 0x90, 0x55, 0xcb, 0x86, 0x24, 0xf2, 0x33, + /*6b10:*/ 0xab, 0x9b, 0xc6, 0x60, 0x0d, 0x7f, 0x5b, 0x94, 0x16, 0xd3, 0x55, 0xb7, 0xb4, 0x9e, 0xfe, 0xf0, + /*6b20:*/ 0xdc, 0xae, 0x2c, 0xc5, 0x24, 0x0f, 0x7e, 0x99, 0xe4, 0x77, 0x0e, 0x96, 0x90, 0xe8, 0x39, 0xac, + /*6b30:*/ 0x8a, 0x53, 0xfb, 0xe8, 0x75, 0x24, 0x69, 0x6f, 0xb2, 0x11, 0x2a, 0x45, 0x2d, 0x2f, 0x87, 0xac, + /*6b40:*/ 0xfa, 0xea, 0xd5, 0x70, 0x98, 0x39, 0xdb, 0x81, 0xcd, 0x56, 0xdd, 0x4f, 0xdf, 0x78, 0xe1, 0x2c, + /*6b50:*/ 0xab, 0x35, 0x54, 0x37, 0x11, 0xf7, 0x23, 0x31, 0xda, 0xb1, 0xd8, 0x76, 0x2e, 0x86, 0xaa, 0xc7, + /*6b60:*/ 0x8e, 0x73, 0x6a, 0xba, 0x2a, 0x98, 0xd3, 0x6b, 0x8a, 0x1f, 0x1d, 0xd3, 0xe9, 0x04, 0x3f, 0xf0, + /*6b70:*/ 0xdb, 0xb8, 0x06, 0xd9, 0xae, 0x7e, 0xcb, 0xbf, 0x3d, 0x85, 0xa6, 0x10, 0x30, 0xbc, 0x04, 0x96, + /*6b80:*/ 0x2a, 0xc8, 0x89, 0xa9, 0xa6, 0x14, 0xdc, 0x75, 0x4d, 0x5a, 0xe5, 0x4a, 0x89, 0x49, 0x58, 0x1a, + /*6b90:*/ 0x4a, 0x07, 0x55, 0x28, 0xd8, 0x5a, 0x12, 0xa0, 0x97, 0x0e, 0xcb, 0x3b, 0x70, 0xb1, 0xa9, 0xaf, + /*6ba0:*/ 0x3a, 0xd3, 0x5b, 0xbb, 0x07, 0x4a, 0x3e, 0x04, 0xa7, 0x2f, 0x1e, 0xb7, 0xa3, 0x80, 0xa5, 0x5d, + /*6bb0:*/ 0x52, 0x1c, 0x45, 0xd4, 0x11, 0xdf, 0x1a, 0xc0, 0x8d, 0xf6, 0xe4, 0x87, 0x07, 0xa3, 0xb3, 0xa1, + /*6bc0:*/ 0xe0, 0x5d, 0x68, 0x0a, 0x2f, 0x94, 0xc3, 0xab, 0x98, 0x76, 0x5e, 0x71, 0xf3, 0x75, 0xb2, 0xcd, + /*6bd0:*/ 0x38, 0x38, 0x8e, 0xa3, 0x10, 0xb8, 0xc3, 0x83, 0x71, 0xde, 0x20, 0xa2, 0x62, 0xa9, 0x5f, 0x28, + /*6be0:*/ 0xbb, 0xfd, 0x14, 0x11, 0x6c, 0x9f, 0x90, 0x0e, 0x47, 0x0d, 0xf0, 0x28, 0x52, 0x55, 0x1c, 0x5e, + /*6bf0:*/ 0xf2, 0x8d, 0x70, 0x81, 0x73, 0x6b, 0x7a, 0x7d, 0x21, 0x3e, 0x8e, 0x4c, 0x80, 0x38, 0x8e, 0x4c, + /*6c00:*/ 0x7e, 0x29, 0x99, 0x07, 0x05, 0x25, 0x81, 0x66, 0x64, 0x34, 0x95, 0x45, 0x8c, 0xf3, 0x00, 0x81, + /*6c10:*/ 0x81, 0xb8, 0x91, 0xb4, 0xfc, 0x83, 0xc4, 0xac, 0x60, 0xfd, 0x01, 0x04, 0x7a, 0xff, 0x87, 0x04, + /*6c20:*/ 0x79, 0x40, 0xc0, 0x93, 0x72, 0x66, 0x32, 0xc6, 0xc1, 0x42, 0xe5, 0x5e, 0x74, 0xd5, 0x3b, 0xb8, + /*6c30:*/ 0xde, 0xca, 0xbd, 0x17, 0xc0, 0x5f, 0x93, 0xe5, 0xdc, 0xe7, 0xdb, 0xf8, 0x53, 0x70, 0x01, 0x4d, + /*6c40:*/ 0x7a, 0x78, 0x1f, 0xc9, 0xa8, 0x96, 0xbb, 0xde, 0x29, 0xf8, 0x0b, 0x32, 0xd2, 0x9b, 0x00, 0x33, + /*6c50:*/ 0x96, 0xa5, 0xd6, 0x7f, 0x88, 0x78, 0x3d, 0x03, 0x39, 0x8b, 0x82, 0x48, 0x88, 0xd6, 0x2d, 0x3d, + /*6c60:*/ 0xc5, 0x13, 0xee, 0x2b, 0x61, 0x54, 0xf2, 0x10, 0xec, 0xd2, 0x8d, 0x4a, 0xc4, 0xbe, 0xef, 0x36, + /*6c70:*/ 0x39, 0x4f, 0xdc, 0x63, 0xb7, 0x0c, 0x40, 0x38, 0x47, 0x85, 0x40, 0xc7, 0x8b, 0xfa, 0x1f, 0x69, + /*6c80:*/ 0x9f, 0xd9, 0xf7, 0x4f, 0x68, 0x7f, 0x34, 0x23, 0xfc, 0x95, 0xee, 0xb2, 0x1c, 0x18, 0xda, 0x2a, + /*6c90:*/ 0x2b, 0x78, 0x53, 0x53, 0xa4, 0x32, 0x01, 0x83, 0xf6, 0x3e, 0xf5, 0x40, 0xb2, 0xae, 0x0f, 0x1f, + /*6ca0:*/ 0xf7, 0x1f, 0x7f, 0x69, 0x4e, 0x44, 0x54, 0x24, 0x2d, 0x82, 0x32, 0xd3, 0x71, 0x8f, 0xf4, 0x68, + /*6cb0:*/ 0x79, 0xc0, 0xdc, 0x98, 0xa6, 0xfb, 0x9b, 0xde, 0xa5, 0xb3, 0xea, 0xbd, 0x02, 0x64, 0xcc, 0xd9, + /*6cc0:*/ 0xa2, 0x25, 0x1c, 0x42, 0x15, 0xa8, 0xf0, 0xe5, 0x43, 0x94, 0x39, 0xaf, 0x10, 0xc3, 0x20, 0xa9, + /*6cd0:*/ 0x49, 0x2d, 0x12, 0x9f, 0x8e, 0xe5, 0x10, 0x5f, 0x67, 0xb4, 0x55, 0x7a, 0x58, 0x7c, 0xfd, 0xf0, + /*6ce0:*/ 0x13, 0x8a, 0xfe, 0xff, 0x5e, 0xfc, 0xc1, 0x93, 0x57, 0xa8, 0x7f, 0xe0, 0x5e, 0xad, 0x63, 0xa8, + /*6cf0:*/ 0x38, 0x0c, 0xa3, 0xfa, 0xb3, 0xab, 0x67, 0x4a, 0x09, 0xb8, 0xe5, 0xb2, 0xbd, 0x52, 0xa6, 0xb2, + /*6d00:*/ 0x9f, 0x07, 0xe7, 0xce, 0x31, 0xe3, 0x14, 0x82, 0x99, 0xca, 0xad, 0x55, 0x9b, 0xb6, 0x9e, 0x2f, + /*6d10:*/ 0xa4, 0x4f, 0xc7, 0xaa, 0x84, 0xfb, 0x22, 0x0a, 0x45, 0x7d, 0xab, 0x24, 0xd5, 0xe3, 0xd2, 0xb1, + /*6d20:*/ 0x12, 0xc7, 0xda, 0x73, 0xe8, 0xd4, 0x43, 0x56, 0xaa, 0x9d, 0xc9, 0x0a, 0x9a, 0x19, 0x12, 0x08, + /*6d30:*/ 0x89, 0x6f, 0x37, 0x59, 0xfe, 0x67, 0x0f, 0x3c, 0x7b, 0xae, 0x30, 0xa7, 0x1b, 0x6e, 0x8d, 0xb9, + /*6d40:*/ 0xd1, 0x6f, 0x94, 0x03, 0x95, 0x22, 0x90, 0xdd, 0x2a, 0xb2, 0xc2, 0x7a, 0x12, 0xe6, 0xad, 0x41, + /*6d50:*/ 0xe6, 0xeb, 0x85, 0x8e, 0x98, 0xc0, 0xe1, 0xeb, 0x87, 0xaa, 0xf0, 0xd4, 0xde, 0x5e, 0x32, 0xdb, + /*6d60:*/ 0x73, 0xca, 0xc8, 0x5f, 0x87, 0xca, 0x00, 0x3b, 0xfe, 0x3d, 0x0f, 0x90, 0x75, 0xe1, 0x8b, 0xf6, + /*6d70:*/ 0x73, 0x46, 0x86, 0x87, 0x98, 0xbf, 0x7d, 0x6d, 0x21, 0xec, 0xa3, 0x8c, 0x5a, 0x53, 0x48, 0x06, + /*6d80:*/ 0x56, 0x9a, 0x3d, 0x2b, 0x0a, 0xd7, 0x85, 0x14, 0x0f, 0x12, 0x19, 0x91, 0xcb, 0xb1, 0x9e, 0x6d, + /*6d90:*/ 0x9c, 0x27, 0xb2, 0x4e, 0x36, 0xeb, 0xa6, 0x25, 0x22, 0x4a, 0x15, 0x21, 0xd6, 0x23, 0xcf, 0xf1, + /*6da0:*/ 0xdf, 0xba, 0x0a, 0xb0, 0x6b, 0xd9, 0xd1, 0x43, 0xfd, 0x0a, 0xa8, 0xf3, 0xf0, 0x34, 0x78, 0x41, + /*6db0:*/ 0x7e, 0x70, 0xf4, 0x40, 0xbf, 0x82, 0x37, 0x79, 0xef, 0xe5, 0x80, 0x48, 0x1f, 0x91, 0x47, 0xd6, + /*6dc0:*/ 0x7e, 0x41, 0x92, 0x1e, 0x59, 0x28, 0x05, 0xcc, 0xa6, 0xd2, 0xb8, 0xe0, 0x2c, 0xc0, 0x23, 0x58, + /*6dd0:*/ 0x50, 0x3a, 0x96, 0x83, 0xd5, 0xa8, 0xa1, 0x82, 0x88, 0x43, 0xab, 0x0b, 0x88, 0xbe, 0xb7, 0x2d, + /*6de0:*/ 0x6f, 0x19, 0x74, 0x41, 0x6f, 0xb9, 0xd4, 0xea, 0x25, 0xe1, 0xc5, 0x62, 0x87, 0xb6, 0x0c, 0x2a, + /*6df0:*/ 0x5b, 0x9b, 0xa4, 0xa2, 0xcf, 0x9c, 0xb7, 0x60, 0x3a, 0x99, 0x1a, 0x37, 0xf9, 0xf9, 0xce, 0x49, + /*6e00:*/ 0x64, 0x2f, 0x3a, 0xc2, 0x35, 0x1b, 0x48, 0x99, 0x64, 0xdb, 0x26, 0xb4, 0x96, 0x74, 0x48, 0x2a, + /*6e10:*/ 0x98, 0x39, 0x51, 0x6b, 0x95, 0xb8, 0xaa, 0x47, 0xaf, 0xba, 0xc9, 0x75, 0x3a, 0x83, 0xf4, 0x6b, + /*6e20:*/ 0xc2, 0xe2, 0x9d, 0x35, 0x04, 0x4a, 0x7c, 0x2c, 0xa4, 0xac, 0xaf, 0xd4, 0xb6, 0x9c, 0x8c, 0xb1, + /*6e30:*/ 0xf7, 0xff, 0xca, 0xab, 0xda, 0x74, 0x70, 0xaf, 0xfc, 0x79, 0x64, 0x0f, 0x24, 0xb6, 0xab, 0x66, + /*6e40:*/ 0x0c, 0x31, 0x15, 0xaa, 0x1e, 0xa8, 0x52, 0xc2, 0x19, 0x93, 0x8c, 0x46, 0xbb, 0x66, 0x66, 0xa0, + /*6e50:*/ 0xfb, 0xc8, 0x1d, 0x39, 0x89, 0xed, 0xcc, 0x6c, 0x16, 0x88, 0x4d, 0xc4, 0x28, 0x98, 0x1b, 0x6d, + /*6e60:*/ 0xa4, 0x42, 0x67, 0x00, 0x06, 0xf8, 0xd5, 0x2b, 0xc2, 0xe3, 0xc7, 0xa7, 0x19, 0x32, 0xcf, 0x79, + /*6e70:*/ 0xce, 0x4b, 0x5f, 0x7f, 0xfe, 0xd6, 0xb1, 0xc8, 0xec, 0xe6, 0x96, 0x8b, 0x6a, 0xf6, 0xa4, 0x2b, + /*6e80:*/ 0xa7, 0x8f, 0xd8, 0xb1, 0x1f, 0xc5, 0xce, 0x24, 0xfe, 0xd0, 0xd7, 0xd7, 0xd9, 0xfb, 0x8e, 0x19, + /*6e90:*/ 0xfd, 0x6f, 0x54, 0x3a, 0x73, 0xbe, 0x0a, 0x5c, 0xd0, 0x1e, 0xf2, 0x85, 0x7c, 0x1e, 0x18, 0xc9, + /*6ea0:*/ 0x4f, 0x86, 0x9b, 0x71, 0x1f, 0x0a, 0x75, 0xc4, 0x5d, 0x68, 0xac, 0x1a, 0xef, 0xce, 0xdf, 0xb0, + /*6eb0:*/ 0x23, 0x4b, 0x79, 0xa1, 0x64, 0x86, 0x07, 0xa2, 0x91, 0x0d, 0x00, 0x36, 0xf1, 0xbe, 0xe7, 0x4a, + /*6ec0:*/ 0x03, 0x13, 0xf2, 0xc0, 0x40, 0x8a, 0x82, 0x49, 0xa8, 0x80, 0x9c, 0xda, 0x0c, 0xe8, 0xf9, 0xb3, + /*6ed0:*/ 0x5c, 0xbb, 0x5c, 0x2b, 0x8b, 0xf7, 0xdd, 0x8f, 0x7a, 0x7a, 0xac, 0x29, 0x65, 0x36, 0xb5, 0xc9, + /*6ee0:*/ 0xac, 0x60, 0x77, 0x12, 0xe3, 0x2e, 0xbf, 0x7c, 0xdd, 0x3a, 0x99, 0xe9, 0x79, 0xed, 0x36, 0x85, + /*6ef0:*/ 0x0b, 0xc5, 0xe7, 0x0d, 0xdb, 0x4d, 0x5e, 0x8c, 0x3a, 0xb5, 0xc2, 0x09, 0x52, 0xf9, 0xf8, 0x90, + /*6f00:*/ 0xbd, 0x35, 0x94, 0x27, 0x21, 0xe1, 0xbf, 0xa7, 0xb6, 0x1d, 0x31, 0x23, 0x55, 0x5c, 0xec, 0x78, + /*6f10:*/ 0xe6, 0x86, 0xd0, 0x3a, 0x32, 0x14, 0x2a, 0x20, 0x20, 0x59, 0x78, 0x24, 0xab, 0x27, 0xb5, 0xa0, + /*6f20:*/ 0x13, 0xfc, 0xf5, 0x5b, 0x1e, 0xad, 0x3a, 0x36, 0x40, 0x18, 0x4a, 0x73, 0x5b, 0xdd, 0x8d, 0xb2, + /*6f30:*/ 0xc3, 0xb9, 0xe4, 0x15, 0xf0, 0xd6, 0xf6, 0xf3, 0x5c, 0x26, 0x00, 0x22, 0xde, 0x9a, 0xa4, 0xe1, + /*6f40:*/ 0x36, 0xa6, 0xd9, 0xe7, 0xc9, 0x9e, 0xd7, 0xb2, 0x64, 0xfb, 0x24, 0xe9, 0xb0, 0xba, 0xa1, 0xa6, + /*6f50:*/ 0xc5, 0xc6, 0x7f, 0xbe, 0x22, 0x28, 0x02, 0x62, 0xb5, 0xf4, 0x38, 0xaa, 0x2d, 0x85, 0x45, 0xac, + /*6f60:*/ 0xe8, 0xcc, 0xfc, 0x2f, 0x75, 0xec, 0x09, 0xd2, 0xf5, 0x63, 0x64, 0xd0, 0x1a, 0xec, 0xfc, 0xfb, + /*6f70:*/ 0x59, 0xea, 0x70, 0x42, 0x09, 0xae, 0xe9, 0xd0, 0x4f, 0xbb, 0x34, 0xa8, 0x9e, 0x76, 0x2b, 0x13, + /*6f80:*/ 0x00, 0xe0, 0xde, 0x26, 0x12, 0x49, 0x6c, 0x1c, 0x52, 0xc1, 0x8d, 0xb9, 0x47, 0xaa, 0xff, 0xb3, + /*6f90:*/ 0x06, 0x54, 0x5e, 0x5f, 0x77, 0x82, 0x93, 0x8f, 0xd0, 0x62, 0xd6, 0xde, 0xd2, 0x00, 0xb2, 0xc2, + /*6fa0:*/ 0x7e, 0x08, 0x34, 0x9b, 0xc5, 0x2e, 0x6d, 0x3d, 0xbf, 0x06, 0xc8, 0xce, 0x3c, 0x96, 0x9b, 0x9c, + /*6fb0:*/ 0xe5, 0x94, 0x0c, 0x56, 0x4e, 0x54, 0xcf, 0xee, 0xff, 0xb3, 0x61, 0x66, 0xf3, 0x4a, 0xe0, 0x6b, + /*6fc0:*/ 0x20, 0xda, 0xe3, 0x5f, 0x04, 0xf7, 0xef, 0xc6, 0x27, 0x85, 0xb0, 0xf8, 0xf0, 0xf5, 0x37, 0x50, + /*6fd0:*/ 0x34, 0x5d, 0xde, 0x5e, 0x20, 0x57, 0x95, 0xe4, 0x30, 0x0d, 0xa9, 0xe8, 0x05, 0xb8, 0x5e, 0xbe, + /*6fe0:*/ 0x2d, 0x74, 0x7b, 0x4b, 0xff, 0x5a, 0x88, 0x31, 0xe5, 0x11, 0xe3, 0x90, 0xef, 0xb3, 0xd1, 0x28, + /*6ff0:*/ 0x92, 0x24, 0x4d, 0x93, 0xd3, 0x9c, 0xbf, 0xfc, 0x9d, 0x1f, 0x80, 0x4c, 0xdb, 0xbc, 0x82, 0x3f, + /*7000:*/ 0x0d, 0xc9, 0xa6, 0xf5, 0x90, 0x95, 0x0c, 0x18, 0x9b, 0x5a, 0x08, 0xe4, 0x6d, 0xed, 0x36, 0x63, + /*7010:*/ 0x78, 0x36, 0x56, 0xfc, 0x40, 0xa9, 0xbb, 0x23, 0xbe, 0x39, 0x16, 0xae, 0xe9, 0x3d, 0x2c, 0xc8, + /*7020:*/ 0x3f, 0x70, 0xfc, 0x9d, 0x6d, 0x3b, 0xc8, 0x75, 0xb5, 0x62, 0x8a, 0x80, 0xea, 0x90, 0x25, 0x1b, + /*7030:*/ 0xc2, 0x6c, 0x24, 0xc8, 0xab, 0x99, 0x6e, 0x32, 0x59, 0x3e, 0x03, 0xd1, 0xab, 0x20, 0xab, 0x64, + /*7040:*/ 0x55, 0xf5, 0x98, 0x31, 0x92, 0xc5, 0xcd, 0x26, 0x97, 0xe0, 0x80, 0xc5, 0xfe, 0x65, 0xd4, 0x21, + /*7050:*/ 0x45, 0x9e, 0xee, 0xad, 0x59, 0xd5, 0x32, 0x61, 0x62, 0x6b, 0x86, 0x53, 0xeb, 0xed, 0x36, 0x4c, + /*7060:*/ 0x59, 0x1e, 0x0f, 0xc7, 0xcf, 0xf4, 0x9b, 0x8c, 0x43, 0x08, 0x2f, 0x9a, 0x5e, 0x2c, 0x1f, 0xdb, + /*7070:*/ 0x5e, 0xd7, 0x0b, 0xe8, 0x4e, 0xe5, 0x76, 0x67, 0x18, 0xdc, 0xd9, 0x6e, 0x64, 0xf4, 0x8f, 0x98, + /*7080:*/ 0x47, 0x2f, 0x8d, 0x85, 0xbe, 0x9c, 0xd7, 0xaf, 0x2e, 0x56, 0x82, 0x9d, 0x71, 0x91, 0xbd, 0x7d, + /*7090:*/ 0xdd, 0x40, 0x85, 0xd9, 0x40, 0x7b, 0x2d, 0x51, 0xd6, 0xf4, 0xc9, 0x49, 0x1d, 0x5f, 0x1a, 0x23, + /*70a0:*/ 0xdc, 0xa7, 0x67, 0x16, 0xe4, 0xde, 0x7b, 0xd9, 0xf0, 0xd6, 0x0d, 0x0f, 0x20, 0x06, 0x22, 0x70, + /*70b0:*/ 0xcb, 0x63, 0x94, 0xab, 0xdb, 0xc8, 0x3c, 0xa6, 0x20, 0x70, 0xf4, 0xf4, 0x01, 0xac, 0x8e, 0xc7, + /*70c0:*/ 0x5a, 0x3c, 0x38, 0x5f, 0x39, 0x06, 0x47, 0x35, 0x5c, 0x98, 0xbf, 0x9c, 0x59, 0xd0, 0x8d, 0x2f, + /*70d0:*/ 0x73, 0x13, 0x06, 0x14, 0x5c, 0x10, 0xc6, 0x17, 0x87, 0xc6, 0x4d, 0x1e, 0x54, 0x67, 0x94, 0x2c, + /*70e0:*/ 0xf2, 0xfc, 0x9f, 0x8a, 0x55, 0x8e, 0xd4, 0x16, 0x76, 0xe2, 0x4f, 0x94, 0x29, 0xc9, 0x27, 0xd4, + /*70f0:*/ 0x84, 0xd1, 0xc3, 0x33, 0xc7, 0xf3, 0x5c, 0x82, 0x11, 0x95, 0x4f, 0xfb, 0x7b, 0xa1, 0x4d, 0xb4, + /*7100:*/ 0x8c, 0x83, 0xec, 0xb6, 0xb2, 0x27, 0xaf, 0xeb, 0x31, 0x07, 0x52, 0x40, 0xd0, 0xc4, 0x75, 0x78, + /*7110:*/ 0xf5, 0xcf, 0x28, 0xce, 0x4d, 0xcb, 0x72, 0x87, 0x97, 0x48, 0x7c, 0xc2, 0x76, 0xc7, 0x43, 0x36, + /*7120:*/ 0xa5, 0x95, 0x0f, 0x90, 0x8b, 0x0a, 0x90, 0xf0, 0xb3, 0x37, 0x59, 0x9d, 0x0a, 0xde, 0x1a, 0x3a, + /*7130:*/ 0x6e, 0xcd, 0xff, 0x66, 0x15, 0xef, 0xcc, 0x5b, 0x83, 0x84, 0x76, 0x9d, 0x07, 0xb3, 0xe4, 0x1c, + /*7140:*/ 0x36, 0xb3, 0x99, 0xf6, 0x62, 0x6c, 0x96, 0x5d, 0x56, 0xa7, 0xd7, 0xf2, 0xe2, 0x39, 0x9e, 0x63, + /*7150:*/ 0x54, 0x2b, 0x45, 0xc4, 0x4e, 0x55, 0x92, 0x80, 0xd7, 0x24, 0x4d, 0x05, 0x3a, 0x86, 0x34, 0x17, + /*7160:*/ 0xb1, 0x09, 0xb4, 0xaf, 0x34, 0x35, 0x69, 0x4f, 0x74, 0x1e, 0x9e, 0x8f, 0x9f, 0x7d, 0x89, 0x7d, + /*7170:*/ 0x7e, 0x5a, 0x0a, 0x38, 0xe1, 0x53, 0x73, 0x9a, 0x80, 0xdc, 0xea, 0x3f, 0x79, 0xf0, 0xd8, 0x48, + /*7180:*/ 0x7f, 0xf7, 0xc8, 0x73, 0x20, 0x3f, 0xbe, 0x71, 0xec, 0xc5, 0x8a, 0x65, 0x17, 0x16, 0xd0, 0xf4, + /*7190:*/ 0x7f, 0x21, 0x33, 0x94, 0xe1, 0xa5, 0x93, 0x32, 0x02, 0x0f, 0x3b, 0x74, 0x97, 0x88, 0x59, 0xcb, + /*71a0:*/ 0x12, 0xc5, 0x80, 0xd8, 0x7a, 0xe5, 0x89, 0x0c, 0x09, 0x62, 0x2b, 0x58, 0x9b, 0xef, 0xb5, 0x21, + /*71b0:*/ 0xed, 0xb2, 0x70, 0x45, 0x9e, 0x17, 0x87, 0x3b, 0x1b, 0xef, 0xb1, 0xee, 0xea, 0x0f, 0x6f, 0x70, + /*71c0:*/ 0x7d, 0x4d, 0xf9, 0x40, 0x11, 0x81, 0x97, 0xe7, 0x08, 0x94, 0x64, 0xd3, 0xe1, 0xbe, 0x76, 0xec, + /*71d0:*/ 0x95, 0x29, 0x5a, 0x83, 0xb3, 0x75, 0xd7, 0x10, 0xb1, 0x55, 0x7f, 0xc5, 0xd2, 0x57, 0xe3, 0xf8, + /*71e0:*/ 0xf0, 0x78, 0xef, 0xd9, 0x9a, 0xa5, 0xa8, 0xf6, 0x3d, 0xc8, 0xf2, 0xce, 0x58, 0xf0, 0x4b, 0x5a, + /*71f0:*/ 0xf3, 0xb7, 0xb3, 0xc8, 0x94, 0xe8, 0x1f, 0xef, 0x4b, 0x1d, 0x03, 0x0b, 0xc2, 0x51, 0xbf, 0x48, + /*7200:*/ 0xa7, 0xcf, 0xbe, 0x93, 0x5d, 0x93, 0x21, 0xfc, 0x33, 0x45, 0x6d, 0x79, 0xee, 0xb1, 0x8a, 0x60, + /*7210:*/ 0x70, 0xce, 0x7c, 0xbc, 0x58, 0x0b, 0x34, 0xb3, 0x8c, 0xd6, 0x8f, 0x94, 0x50, 0xbf, 0x0b, 0x50, + /*7220:*/ 0xc4, 0xf9, 0x9a, 0xd7, 0x95, 0x1e, 0xb0, 0x53, 0xe8, 0xd8, 0x14, 0x9e, 0x13, 0x5b, 0x9c, 0x9f, + /*7230:*/ 0xb4, 0xf5, 0x0d, 0x65, 0xfa, 0xe2, 0xaf, 0x04, 0x94, 0xda, 0x9f, 0x8e, 0x31, 0x0e, 0x66, 0xb6, + /*7240:*/ 0x45, 0x8b, 0xa5, 0xb5, 0xbc, 0x10, 0x30, 0xcf, 0xf7, 0x77, 0x79, 0x87, 0xd4, 0xe4, 0x32, 0xe3, + /*7250:*/ 0xce, 0x97, 0x4d, 0x63, 0xe8, 0xe5, 0x06, 0xf1, 0x3b, 0x30, 0x29, 0x35, 0xab, 0xe4, 0x46, 0x68, + /*7260:*/ 0x77, 0x94, 0xf7, 0x0d, 0x82, 0xf7, 0x61, 0xcb, 0x84, 0x2f, 0x2f, 0xfe, 0x5d, 0xe1, 0x25, 0x93, + /*7270:*/ 0xe2, 0xb3, 0xd2, 0x35, 0xf0, 0x3d, 0x43, 0x20, 0x1d, 0x4e, 0x9f, 0x35, 0x8c, 0x44, 0x95, 0xc5, + /*7280:*/ 0x71, 0x12, 0xd2, 0xc7, 0x8b, 0xf1, 0x30, 0x4a, 0x49, 0x51, 0xe4, 0xe9, 0x03, 0x9b, 0x14, 0x51, + /*7290:*/ 0x90, 0xbd, 0xbb, 0x9c, 0x21, 0xb8, 0xe0, 0x51, 0xe3, 0xca, 0xf4, 0xb4, 0x10, 0xd5, 0xa4, 0x8d, + /*72a0:*/ 0x9d, 0x3f, 0x28, 0x73, 0x7e, 0x5b, 0x6c, 0xe7, 0xca, 0x57, 0x66, 0x8d, 0x5b, 0x34, 0xe9, 0xaa, + /*72b0:*/ 0xb4, 0x2f, 0x56, 0x49, 0x1e, 0xa9, 0x14, 0xed, 0x2b, 0xee, 0x43, 0xa1, 0x3e, 0x10, 0xa4, 0xed, + /*72c0:*/ 0x1a, 0x13, 0xad, 0x78, 0x7a, 0xf2, 0x6e, 0xad, 0xca, 0x30, 0x2a, 0xa1, 0xd8, 0xf8, 0xe1, 0xd1, + /*72d0:*/ 0x91, 0x68, 0x5f, 0x6e, 0xd9, 0x06, 0x91, 0xd2, 0x8b, 0x2a, 0x9e, 0x29, 0x8c, 0xca, 0x5f, 0x46, + /*72e0:*/ 0x77, 0x6c, 0x19, 0xdc, 0x92, 0xf9, 0x8f, 0xc9, 0x68, 0x21, 0xe7, 0x6b, 0x89, 0xf5, 0x83, 0xa8, + /*72f0:*/ 0x6b, 0x9d, 0xe0, 0x1d, 0x77, 0x20, 0x16, 0x66, 0xe6, 0x53, 0xda, 0x32, 0x02, 0x39, 0x09, 0xcf, + /*7300:*/ 0xed, 0x34, 0xec, 0x87, 0xf7, 0xc0, 0x8d, 0xc7, 0xfc, 0x05, 0x7f, 0xc0, 0x6c, 0x78, 0x7c, 0xd9, + /*7310:*/ 0xa3, 0x30, 0xe3, 0xa2, 0x14, 0x0f, 0x42, 0xd6, 0x16, 0x62, 0xcb, 0xb6, 0x4a, 0xf4, 0xab, 0xee, + /*7320:*/ 0x29, 0x7e, 0xf3, 0xc1, 0x8e, 0xb9, 0xdd, 0x61, 0x44, 0x82, 0x2f, 0x1f, 0xc0, 0x28, 0x36, 0xb8, + /*7330:*/ 0x2c, 0xec, 0x2a, 0x4c, 0xe7, 0x50, 0x37, 0x9b, 0x6f, 0xb3, 0xb3, 0xc2, 0x1b, 0xf4, 0x91, 0x88, + /*7340:*/ 0x46, 0xb8, 0x2a, 0xbe, 0xc9, 0x56, 0x4e, 0x74, 0x16, 0xd7, 0x1f, 0x49, 0x3b, 0x50, 0xf2, 0x60, + /*7350:*/ 0xbe, 0x0f, 0x3d, 0x79, 0x4b, 0xae, 0x5d, 0xe5, 0x8b, 0xea, 0xd9, 0xe6, 0xca, 0x84, 0x85, 0x93, + /*7360:*/ 0x84, 0x98, 0x10, 0x0b, 0xa6, 0xfb, 0xb2, 0xa5, 0x3c, 0xc2, 0x79, 0x75, 0x56, 0x69, 0x26, 0x55, + /*7370:*/ 0x61, 0x6e, 0xf3, 0x3d, 0xb3, 0xfa, 0xdc, 0xd1, 0xe4, 0x57, 0x8f, 0x8f, 0x04, 0x61, 0xec, 0x42, + /*7380:*/ 0x6b, 0xe2, 0x89, 0xe2, 0x22, 0xc4, 0xde, 0x2e, 0xae, 0x0f, 0x78, 0x73, 0x0a, 0x7f, 0x33, 0x4a, + /*7390:*/ 0x26, 0x13, 0x11, 0x73, 0x32, 0x7f, 0x30, 0x28, 0x02, 0x40, 0x19, 0xfc, 0xaf, 0xf0, 0x12, 0x0c, + /*73a0:*/ 0x64, 0xcd, 0x83, 0x47, 0x66, 0x7e, 0xa5, 0x45, 0x0c, 0x91, 0xd4, 0x13, 0x45, 0x83, 0xd2, 0xbe, + /*73b0:*/ 0x1e, 0x7b, 0x00, 0x43, 0xd8, 0x12, 0x6c, 0xfe, 0xc4, 0x15, 0x34, 0x6e, 0x17, 0xb0, 0x18, 0x72, + /*73c0:*/ 0xc1, 0x08, 0x8d, 0x8c, 0x25, 0x24, 0x1a, 0xce, 0x06, 0xdb, 0x34, 0x8d, 0xec, 0xcb, 0x95, 0xf0, + /*73d0:*/ 0x09, 0x72, 0xa5, 0x5a, 0x22, 0x99, 0x0a, 0x93, 0x88, 0xea, 0x6e, 0x50, 0x80, 0x35, 0x0a, 0x12, + /*73e0:*/ 0x3f, 0x88, 0x4e, 0xe9, 0x64, 0x70, 0xc9, 0xea, 0x5a, 0xe1, 0x43, 0xe7, 0xb3, 0xd0, 0x32, 0x16, + /*73f0:*/ 0x58, 0xbf, 0x4b, 0xa0, 0x40, 0x26, 0xad, 0x4f, 0x83, 0xbe, 0x44, 0xbd, 0x29, 0xb2, 0x11, 0xd7, + /*7400:*/ 0x7a, 0x23, 0xe5, 0xc5, 0xda, 0xfc, 0xa6, 0xf8, 0xa1, 0x26, 0x99, 0xb3, 0xbb, 0x3d, 0xe6, 0x37, + /*7410:*/ 0x24, 0x36, 0x89, 0xa3, 0x67, 0x9b, 0x16, 0x46, 0xdf, 0x9c, 0x09, 0x07, 0x00, 0xf7, 0x14, 0xac, + /*7420:*/ 0x6c, 0x88, 0x2f, 0xfe, 0x3a, 0x88, 0xf2, 0xbf, 0x88, 0x87, 0x4e, 0xe5, 0x1a, 0xad, 0x70, 0x79, + /*7430:*/ 0x85, 0x2c, 0xa4, 0x2c, 0xf7, 0x8c, 0x2c, 0x9c, 0x16, 0x07, 0x3b, 0x64, 0x62, 0x94, 0x6b, 0xca, + /*7440:*/ 0x30, 0x6f, 0xe6, 0x86, 0x71, 0x82, 0x32, 0xd5, 0x22, 0xb7, 0x69, 0x44, 0x82, 0xab, 0xaa, 0xe1, + /*7450:*/ 0x5e, 0xf3, 0xd6, 0xb3, 0xf9, 0xe0, 0x1a, 0xfa, 0xf5, 0x54, 0x11, 0x7d, 0xf7, 0x38, 0xdb, 0x31, + /*7460:*/ 0x38, 0xfb, 0xf4, 0x3b, 0x47, 0x90, 0x1c, 0x57, 0xbf, 0x66, 0x4e, 0x68, 0xd9, 0x67, 0x03, 0x5a, + /*7470:*/ 0xa8, 0xd9, 0xe9, 0x91, 0xee, 0x66, 0x9c, 0x5f, 0xeb, 0x18, 0x12, 0xaf, 0x90, 0xf7, 0x58, 0x13, + /*7480:*/ 0x41, 0x5e, 0xa9, 0x66, 0xd7, 0x8a, 0xe7, 0x0c, 0xe9, 0x47, 0xa8, 0x96, 0x25, 0x7c, 0x5c, 0x38, + /*7490:*/ 0x46, 0xbc, 0x5a, 0x3d, 0x7f, 0xed, 0x9e, 0xc2, 0xc0, 0xde, 0x93, 0xcb, 0xfc, 0x19, 0x47, 0x5c, + /*74a0:*/ 0x5a, 0xca, 0x38, 0xd1, 0x88, 0xac, 0x7f, 0xf9, 0xad, 0x6f, 0x90, 0x62, 0x80, 0x6a, 0xac, 0x5e, + /*74b0:*/ 0x5c, 0x58, 0xfd, 0xa2, 0x62, 0xf8, 0x05, 0xbb, 0x5d, 0x63, 0x32, 0x74, 0x74, 0xc9, 0x1e, 0x28, + /*74c0:*/ 0xb6, 0x0e, 0x16, 0xa7, 0x4e, 0xc1, 0x51, 0x8e, 0x0d, 0xad, 0x1c, 0x8d, 0x3e, 0x86, 0x2b, 0x99, + /*74d0:*/ 0x77, 0x7c, 0x97, 0x70, 0xe9, 0xdf, 0x15, 0x83, 0xa9, 0x9c, 0x92, 0x7a, 0xf5, 0x54, 0x98, 0x7b, + /*74e0:*/ 0x33, 0xdf, 0xfb, 0xac, 0xde, 0xe8, 0x89, 0xda, 0x49, 0x77, 0x99, 0x22, 0xac, 0x52, 0x21, 0xf6, + /*74f0:*/ 0x7c, 0xf5, 0xa1, 0x67, 0x21, 0xc1, 0x7f, 0x65, 0x96, 0xcb, 0x84, 0x67, 0x1e, 0x87, 0x0f, 0x19, + /*7500:*/ 0x92, 0x53, 0x19, 0xce, 0x4f, 0xc5, 0x26, 0xef, 0x5b, 0xe6, 0xee, 0x9e, 0xe0, 0x4e, 0x26, 0xbc, + /*7510:*/ 0xa7, 0xe7, 0x06, 0x2d, 0x20, 0xd6, 0x5b, 0xe9, 0x57, 0x05, 0x50, 0xc1, 0x53, 0x3d, 0x0c, 0x29, + /*7520:*/ 0xc3, 0xb3, 0xd1, 0xe4, 0x20, 0x0f, 0xe1, 0xad, 0x1d, 0x0d, 0xe8, 0xd9, 0x8f, 0x32, 0xf8, 0x85, + /*7530:*/ 0xf4, 0xac, 0x21, 0x01, 0x5a, 0x64, 0xc8, 0x8c, 0x40, 0x2f, 0xf8, 0x52, 0xc8, 0x4d, 0x41, 0x2e, + /*7540:*/ 0x6d, 0x97, 0x57, 0x37, 0xca, 0xef, 0xba, 0x0a, 0xb2, 0x15, 0x38, 0x4c, 0xa1, 0xe1, 0x94, 0x1e, + /*7550:*/ 0xc2, 0x8e, 0x58, 0xe4, 0x8b, 0x6d, 0x52, 0x1d, 0x15, 0x7b, 0x10, 0x4b, 0x50, 0x32, 0x7b, 0xff, + /*7560:*/ 0x7b, 0xd4, 0xd9, 0xc6, 0x26, 0x21, 0x76, 0xf7, 0x4f, 0x9d, 0x35, 0x56, 0x50, 0x5a, 0x0b, 0x94, + /*7570:*/ 0x8d, 0x60, 0x84, 0x4d, 0xb2, 0xb3, 0x75, 0x9d, 0x34, 0xf6, 0x8f, 0x2d, 0xc9, 0x48, 0xd9, 0x16, + /*7580:*/ 0x20, 0xb4, 0xfa, 0xd4, 0x03, 0x1c, 0x0b, 0x6f, 0x56, 0x4a, 0x7b, 0x5b, 0x00, 0x4d, 0x09, 0x98, + /*7590:*/ 0x73, 0xd2, 0x14, 0xe7, 0xef, 0xc6, 0xba, 0x03, 0xab, 0xf9, 0xc4, 0x49, 0xa1, 0xc2, 0x56, 0xa5, + /*75a0:*/ 0x6b, 0xbc, 0x91, 0x76, 0x80, 0xc8, 0x85, 0x39, 0xd1, 0x05, 0x81, 0x7a, 0x78, 0x91, 0x7c, 0x4e, + /*75b0:*/ 0x15, 0x5a, 0x67, 0x76, 0x08, 0xa5, 0x76, 0xf1, 0x6f, 0xc4, 0x6d, 0x36, 0x40, 0xc1, 0x0a, 0x2b, + /*75c0:*/ 0xa3, 0x03, 0x6a, 0xf3, 0x20, 0xcc, 0x39, 0x24, 0x15, 0x21, 0x0d, 0xff, 0x0d, 0x75, 0x38, 0x93, + /*75d0:*/ 0x5a, 0x5b, 0xb0, 0x95, 0x27, 0x16, 0x4a, 0xd2, 0xf2, 0x44, 0x76, 0x1d, 0x01, 0xef, 0xf2, 0x9e, + /*75e0:*/ 0x92, 0xad, 0xe9, 0x00, 0x96, 0x51, 0x59, 0x9e, 0x03, 0xf8, 0xc4, 0xe8, 0xbb, 0xec, 0xa8, 0xce, + /*75f0:*/ 0x38, 0xb2, 0xc6, 0x7d, 0x8f, 0x08, 0xc8, 0xb1, 0x94, 0x41, 0xa8, 0xa0, 0x33, 0xcd, 0x6e, 0x85, + /*7600:*/ 0x56, 0x54, 0xf8, 0x93, 0xec, 0x92, 0x43, 0xee, 0xed, 0xac, 0xa6, 0x1a, 0xa6, 0xcd, 0x2a, 0xe5, + /*7610:*/ 0x78, 0xf5, 0x2e, 0x44, 0xaf, 0x5b, 0x21, 0x55, 0x12, 0x75, 0xf3, 0xb6, 0x09, 0x9c, 0x1a, 0x79, + /*7620:*/ 0xc3, 0xf4, 0x5c, 0x5f, 0xb9, 0xb9, 0xf1, 0x0b, 0x90, 0xf1, 0xc9, 0x81, 0x2c, 0x1f, 0xea, 0x57, + /*7630:*/ 0xfb, 0xce, 0x80, 0x90, 0xbc, 0x2b, 0x6b, 0x19, 0xaa, 0x6e, 0xef, 0xc3, 0xff, 0x04, 0x5a, 0x46, + /*7640:*/ 0x1a, 0x31, 0x58, 0x59, 0x90, 0x51, 0x5b, 0x6e, 0x8d, 0x0e, 0x03, 0xd9, 0x1f, 0x97, 0xdd, 0xdf, + /*7650:*/ 0x8c, 0xc7, 0xf7, 0x9c, 0x35, 0xfb, 0x11, 0xb1, 0x46, 0x93, 0x50, 0x93, 0xa4, 0xab, 0x2a, 0x9c, + /*7660:*/ 0xc9, 0x05, 0x67, 0x82, 0x4c, 0xa9, 0x5f, 0x12, 0xf0, 0xb4, 0x09, 0xe5, 0x95, 0x16, 0xa4, 0xd2, + /*7670:*/ 0x49, 0x01, 0x37, 0xb8, 0x69, 0xdf, 0x89, 0xbc, 0xe5, 0x9a, 0x0c, 0x6a, 0xfd, 0xae, 0xd9, 0xa0, + /*7680:*/ 0x3c, 0xeb, 0xb6, 0x4c, 0xe9, 0xcb, 0xc2, 0x88, 0xc6, 0x67, 0x8e, 0xa7, 0x69, 0xf5, 0xfc, 0xb6, + /*7690:*/ 0xb7, 0x26, 0xf1, 0x13, 0x9f, 0x30, 0xd2, 0x0f, 0xb0, 0x45, 0x39, 0x32, 0xc7, 0x37, 0xb2, 0xc4, + /*76a0:*/ 0x0c, 0xbd, 0x8b, 0xff, 0x2f, 0x79, 0x0c, 0x2a, 0xbe, 0x7b, 0xf5, 0x8e, 0x23, 0xb9, 0x83, 0xe2, + /*76b0:*/ 0xbe, 0x90, 0xcd, 0xa3, 0x81, 0x81, 0x64, 0x24, 0xf4, 0x09, 0x27, 0x58, 0xf5, 0x9e, 0x96, 0x1a, + /*76c0:*/ 0xd6, 0x75, 0x92, 0x63, 0x18, 0xd8, 0xe6, 0x5e, 0x83, 0x9e, 0x1a, 0xaf, 0xcf, 0x68, 0x72, 0xdc, + /*76d0:*/ 0xc3, 0x7b, 0xcb, 0x32, 0x28, 0x84, 0xfd, 0x6c, 0x39, 0x1d, 0xc9, 0x9c, 0x17, 0x2d, 0x28, 0x75, + /*76e0:*/ 0xba, 0xa4, 0x00, 0xea, 0xe6, 0x04, 0x1e, 0x70, 0x27, 0x67, 0xff, 0x5b, 0xdd, 0xd1, 0x8f, 0xfc, + /*76f0:*/ 0x71, 0x27, 0xd1, 0x53, 0xf3, 0xc6, 0xb3, 0x52, 0x47, 0x43, 0x6a, 0x01, 0x07, 0xf6, 0x0a, 0x21, + /*7700:*/ 0x2a, 0xda, 0x4e, 0x03, 0x41, 0x2f, 0xee, 0x85, 0xae, 0x7f, 0x3b, 0xe6, 0x38, 0xf7, 0x97, 0xde, + /*7710:*/ 0xf5, 0x67, 0x10, 0x52, 0xd5, 0x20, 0x73, 0x1b, 0xd9, 0x6b, 0x5c, 0x9a, 0x00, 0x90, 0xbc, 0xd3, + /*7720:*/ 0x9c, 0x8d, 0x26, 0x87, 0x97, 0x94, 0x8f, 0x6f, 0x05, 0x64, 0x8d, 0x7b, 0x6f, 0x51, 0xf1, 0xf1, + /*7730:*/ 0x43, 0xd2, 0xa3, 0x5e, 0xd5, 0x93, 0x4a, 0xe1, 0x83, 0x84, 0x7c, 0xde, 0xcf, 0x65, 0x1f, 0x6a, + /*7740:*/ 0x45, 0xba, 0x07, 0xa6, 0x8e, 0xe4, 0x01, 0x4d, 0x22, 0xdf, 0x00, 0x22, 0x39, 0x75, 0x3e, 0x0d, + /*7750:*/ 0x8d, 0x3c, 0x68, 0x5b, 0x7c, 0x81, 0xd1, 0xc6, 0x79, 0x2b, 0x54, 0xb7, 0xc1, 0x86, 0x2e, 0x03, + /*7760:*/ 0x44, 0xa6, 0xc0, 0xe0, 0x17, 0x59, 0x3a, 0xed, 0x0b, 0x6b, 0x0c, 0x08, 0x0a, 0xce, 0x9a, 0x31, + /*7770:*/ 0xa5, 0x94, 0x3c, 0x96, 0x29, 0x8f, 0xc7, 0xb0, 0xa3, 0x54, 0x91, 0x0d, 0xd5, 0x5e, 0xb3, 0x73, + /*7780:*/ 0x1a, 0xf6, 0x69, 0xb4, 0xb0, 0x16, 0xc1, 0x28, 0xdc, 0xbd, 0x4e, 0x2f, 0x89, 0x9d, 0xd2, 0xfe, + /*7790:*/ 0x4f, 0xb9, 0x7b, 0x81, 0xcb, 0xf3, 0x67, 0x99, 0x85, 0x44, 0x62, 0xb0, 0x77, 0xd8, 0x3b, 0x2b, + /*77a0:*/ 0xda, 0x8d, 0xcd, 0xa2, 0xf5, 0x00, 0x35, 0x98, 0xc2, 0xb0, 0x1f, 0x8d, 0x24, 0xac, 0x42, 0x1b, + /*77b0:*/ 0x8b, 0xe7, 0xc0, 0x66, 0xa8, 0x91, 0xf0, 0x68, 0x0b, 0x21, 0xe2, 0x0d, 0x71, 0x7f, 0x10, 0x7f, + /*77c0:*/ 0x54, 0x0d, 0x77, 0x01, 0x21, 0x48, 0xde, 0x35, 0x7d, 0x3d, 0x7d, 0xde, 0xc1, 0x3a, 0x18, 0x27, + /*77d0:*/ 0x63, 0xb2, 0x81, 0x34, 0x6f, 0x6f, 0x61, 0x8f, 0xd4, 0xcb, 0x95, 0x14, 0x13, 0xc5, 0x62, 0xf2, + /*77e0:*/ 0x53, 0xed, 0xad, 0x38, 0x92, 0x7d, 0xd5, 0x1b, 0x10, 0x45, 0x42, 0x78, 0xd1, 0x85, 0x2c, 0x42, + /*77f0:*/ 0xcb, 0x72, 0x74, 0x0b, 0x8a, 0x08, 0x39, 0x7b, 0x7b, 0xdb, 0x97, 0x69, 0xcc, 0x22, 0xc7, 0x6e, + /*7800:*/ 0x13, 0x5a, 0x2b, 0x90, 0x4b, 0xd7, 0xb3, 0x54, 0x7b, 0x64, 0xf4, 0x4e, 0x3e, 0xd2, 0xd1, 0xf0, + /*7810:*/ 0xbb, 0xa5, 0xab, 0xd4, 0xd7, 0x5d, 0xb4, 0x4b, 0x43, 0x8b, 0xe4, 0x0b, 0x27, 0xcb, 0x4c, 0xf9, + /*7820:*/ 0xe8, 0x9c, 0x24, 0x68, 0x42, 0x57, 0x9f, 0xa6, 0xc9, 0xc7, 0x53, 0xfc, 0x94, 0x1b, 0x18, 0x97, + /*7830:*/ 0xd5, 0xeb, 0x24, 0xbc, 0xb9, 0xaa, 0xc8, 0xe0, 0x01, 0x30, 0xc5, 0x01, 0x49, 0xc3, 0x61, 0x8a, + /*7840:*/ 0x47, 0x7a, 0x8d, 0x5b, 0x74, 0x0d, 0x48, 0xbf, 0x0c, 0xb3, 0xec, 0xe9, 0xe0, 0x1f, 0x6c, 0x36, + /*7850:*/ 0x67, 0xb7, 0xa1, 0xec, 0x9d, 0x51, 0x00, 0x4e, 0x2f, 0x58, 0xae, 0x7f, 0x61, 0x2e, 0x79, 0x24, + /*7860:*/ 0x50, 0x38, 0xe2, 0x3e, 0xc4, 0x00, 0xbb, 0xf2, 0x25, 0x5b, 0xa8, 0xf6, 0x75, 0x58, 0x30, 0xd9, + /*7870:*/ 0x63, 0x46, 0x4a, 0x62, 0xfc, 0x47, 0x83, 0xb5, 0xb7, 0xb0, 0x21, 0xf1, 0xfb, 0xaa, 0x6b, 0x17, + /*7880:*/ 0xb9, 0xa9, 0xea, 0xd0, 0x98, 0xfc, 0xd5, 0x76, 0x4f, 0x7f, 0x04, 0x69, 0x70, 0x49, 0xcc, 0x34, + /*7890:*/ 0x1f, 0x88, 0x0f, 0x63, 0x29, 0x47, 0x15, 0x56, 0x30, 0xfc, 0x99, 0xa9, 0xb9, 0x1a, 0x42, 0xe3, + /*78a0:*/ 0x0f, 0x28, 0x7a, 0xed, 0xca, 0xad, 0x55, 0x0f, 0xd7, 0xca, 0x5a, 0xae, 0x61, 0x4b, 0x24, 0xd2, + /*78b0:*/ 0x77, 0x68, 0xcc, 0xd2, 0x4f, 0x97, 0xc2, 0xeb, 0x79, 0x5c, 0x0a, 0xfe, 0x90, 0x5a, 0x31, 0xcb, + /*78c0:*/ 0x26, 0xa4, 0x73, 0x1e, 0xea, 0x43, 0xd4, 0x64, 0x6e, 0x0c, 0x07, 0x9d, 0xea, 0x6c, 0x91, 0x3c, + /*78d0:*/ 0x86, 0x72, 0xa6, 0xf2, 0xcd, 0x87, 0xc8, 0xbb, 0xfd, 0xef, 0x05, 0xa1, 0xf7, 0xff, 0x5f, 0x08, + /*78e0:*/ 0xc3, 0xc6, 0x55, 0x92, 0xb6, 0xf3, 0x3a, 0x87, 0x2b, 0x40, 0x3e, 0xe0, 0x37, 0x1f, 0xe2, 0xd4, + /*78f0:*/ 0x1e, 0x67, 0xc3, 0x87, 0xb6, 0x93, 0x76, 0x99, 0x22, 0x79, 0xfd, 0x1d, 0xbc, 0xf8, 0x2c, 0x54, + /*7900:*/ 0x10, 0x03, 0x2f, 0x36, 0xdb, 0x8c, 0x63, 0xba, 0x91, 0xbc, 0xca, 0xe1, 0xd7, 0xc7, 0x8e, 0x32, + /*7910:*/ 0x02, 0xb1, 0x77, 0x4d, 0x1d, 0x70, 0x2b, 0x3a, 0x84, 0xea, 0x1f, 0x78, 0xcc, 0xe8, 0x85, 0x30, + /*7920:*/ 0xbc, 0xe5, 0xb6, 0x15, 0x31, 0x4f, 0x61, 0xb2, 0x18, 0x5e, 0x36, 0xad, 0x70, 0x75, 0xd8, 0xe4, + /*7930:*/ 0x65, 0xdf, 0xac, 0xa1, 0xcc, 0x51, 0x1a, 0x0e, 0x8d, 0x45, 0xc4, 0x46, 0x73, 0x69, 0x2c, 0xc9, + /*7940:*/ 0xb3, 0x96, 0x4e, 0x58, 0x5d, 0x57, 0x68, 0x4e, 0x60, 0x48, 0x16, 0x74, 0x5e, 0xc3, 0xd8, 0x61, + /*7950:*/ 0x22, 0x30, 0x3b, 0x63, 0x96, 0x02, 0x35, 0x2a, 0x15, 0x21, 0x62, 0x92, 0x66, 0x7b, 0xfa, 0x90, + /*7960:*/ 0xfd, 0x63, 0x3c, 0xa7, 0x5a, 0x72, 0xd4, 0x95, 0x63, 0xb8, 0x57, 0x2e, 0x3a, 0x71, 0xa7, 0xd4, + /*7970:*/ 0xff, 0xf9, 0x02, 0xd4, 0xc1, 0xfe, 0xeb, 0x3e, 0x8c, 0xbf, 0xab, 0x16, 0x42, 0x2c, 0x0c, 0x57, + /*7980:*/ 0x12, 0xf0, 0x5a, 0x64, 0xf5, 0x09, 0x1c, 0x46, 0x7c, 0xfb, 0xe0, 0x68, 0x94, 0x97, 0x2c, 0x70, + /*7990:*/ 0x57, 0x13, 0xed, 0xec, 0xdc, 0xd8, 0xab, 0xba, 0x8e, 0x49, 0x87, 0x7c, 0x03, 0x6a, 0x5e, 0xf5, + /*79a0:*/ 0xca, 0x09, 0x96, 0x2c, 0x4b, 0xfb, 0x55, 0xb6, 0x1a, 0x04, 0xf0, 0xb0, 0xbc, 0x71, 0x4f, 0x68, + /*79b0:*/ 0x7c, 0xd4, 0x04, 0xd8, 0x16, 0x6d, 0xae, 0xa9, 0x62, 0xa7, 0xc0, 0xdd, 0x6c, 0xf5, 0x6a, 0x81, + /*79c0:*/ 0x56, 0xb9, 0x09, 0xed, 0x6a, 0xe1, 0x86, 0x44, 0xf7, 0x94, 0xbf, 0xda, 0xcc, 0xf6, 0x9c, 0x7a, + /*79d0:*/ 0xe8, 0x11, 0x1f, 0xdc, 0x7d, 0x22, 0xf2, 0xf1, 0xd2, 0x29, 0x28, 0x02, 0x90, 0x08, 0xb3, 0xdc, + /*79e0:*/ 0x13, 0xe5, 0x57, 0x6b, 0xd1, 0xd5, 0x4c, 0xc6, 0xed, 0xf2, 0x7f, 0x45, 0x38, 0x74, 0xd2, 0xe5, + /*79f0:*/ 0xb3, 0x38, 0x15, 0xc8, 0x55, 0xbe, 0x3c, 0x3d, 0x4e, 0x0c, 0xdd, 0x52, 0x4f, 0xea, 0x31, 0x26, + /*7a00:*/ 0x66, 0x93, 0x37, 0x93, 0x2b, 0x0e, 0x3b, 0x36, 0xd7, 0xd5, 0xc4, 0x9b, 0x3d, 0x0a, 0x25, 0x34, + /*7a10:*/ 0xcd, 0x7f, 0xea, 0x96, 0x9c, 0x34, 0x8f, 0xb8, 0x4a, 0x22, 0x4d, 0x64, 0x33, 0xc8, 0x79, 0x2d, + /*7a20:*/ 0xed, 0xe0, 0x63, 0x19, 0xac, 0xed, 0xf4, 0x95, 0x9e, 0x82, 0x87, 0x6d, 0xdd, 0x13, 0x7f, 0x00, + /*7a30:*/ 0xfe, 0x0a, 0xf8, 0x23, 0x1c, 0x6f, 0x53, 0xa4, 0xcd, 0x64, 0xe2, 0xae, 0xb8, 0x27, 0xff, 0x9f, + /*7a40:*/ 0xe9, 0x1e, 0xd7, 0x3e, 0x62, 0xc2, 0x3b, 0xfb, 0x2c, 0x93, 0x06, 0xcf, 0x21, 0xdb, 0x65, 0x8c, + /*7a50:*/ 0xc5, 0xe0, 0xfa, 0x99, 0x71, 0xf6, 0x55, 0x17, 0x64, 0xc9, 0xd6, 0x79, 0x0f, 0x0d, 0x4b, 0xdc, + /*7a60:*/ 0xcf, 0x24, 0x5d, 0x52, 0xed, 0x41, 0xe8, 0x06, 0x31, 0x87, 0x76, 0xdc, 0x4f, 0x79, 0x8e, 0x10, + /*7a70:*/ 0xa5, 0x5c, 0x37, 0x8c, 0xd4, 0xf7, 0x72, 0x77, 0xd9, 0x69, 0x24, 0x54, 0xdc, 0xf6, 0x35, 0x97, + /*7a80:*/ 0x0d, 0xe4, 0x14, 0xdd, 0xc7, 0x1c, 0x75, 0x5f, 0x2c, 0x33, 0xbe, 0xaa, 0x62, 0xbc, 0x53, 0x04, + /*7a90:*/ 0x18, 0xe0, 0x56, 0x8b, 0xdb, 0xcd, 0xcf, 0x98, 0xb5, 0x1b, 0xb4, 0xa9, 0x84, 0xb3, 0x89, 0xcf, + /*7aa0:*/ 0x5c, 0x57, 0x2d, 0x3d, 0xea, 0x89, 0xd7, 0x14, 0x1e, 0x3b, 0x1e, 0xfb, 0x2e, 0xf6, 0xa7, 0x62, + /*7ab0:*/ 0xd5, 0x21, 0x6f, 0xd2, 0x73, 0xd8, 0x3e, 0xde, 0x1a, 0x65, 0x9f, 0xd0, 0xeb, 0x90, 0x0b, 0x9d, + /*7ac0:*/ 0x21, 0xe5, 0x62, 0x5f, 0x31, 0x8c, 0x8e, 0x55, 0x8b, 0x85, 0x38, 0xa3, 0x16, 0xe8, 0x85, 0x48, + /*7ad0:*/ 0xce, 0xc9, 0xf3, 0x6e, 0x1c, 0x36, 0xd4, 0x38, 0x44, 0x92, 0x9b, 0xf0, 0xc4, 0x6a, 0x44, 0x13, + /*7ae0:*/ 0xfa, 0xde, 0x91, 0x4e, 0x04, 0xeb, 0x70, 0x2d, 0xb4, 0x5f, 0xc5, 0xe0, 0x49, 0x1c, 0x42, 0x4c, + /*7af0:*/ 0xca, 0xa2, 0x70, 0xc3, 0x5f, 0x38, 0x9c, 0x3b, 0xed, 0x96, 0xdf, 0x8d, 0x7f, 0x8c, 0xf9, 0x29, + /*7b00:*/ 0xe6, 0x5d, 0x4e, 0x0e, 0x9d, 0x47, 0x12, 0x37, 0x0c, 0x59, 0xf7, 0x01, 0xa9, 0xab, 0x4a, 0x08, + /*7b10:*/ 0x31, 0x9e, 0x5d, 0x7a, 0xbb, 0xe3, 0x69, 0x03, 0x53, 0xaf, 0xca, 0x96, 0x2e, 0x98, 0x12, 0xfd, + /*7b20:*/ 0x30, 0xab, 0xed, 0x90, 0xa2, 0x08, 0xd5, 0x2d, 0xcc, 0xda, 0xc3, 0x1b, 0xf9, 0x4c, 0x83, 0x71, + /*7b30:*/ 0xb0, 0x40, 0xc9, 0xe6, 0x1f, 0x03, 0x38, 0xc7, 0x6a, 0x85, 0xe1, 0xae, 0x1f, 0xca, 0x12, 0xe4, + /*7b40:*/ 0x6e, 0x9c, 0x1d, 0x6f, 0x6d, 0xa8, 0x2b, 0x9b, 0x46, 0x47, 0x8c, 0xba, 0x32, 0x3d, 0x98, 0x5d, + /*7b50:*/ 0x1e, 0xea, 0x08, 0xa6, 0x6d, 0xd8, 0x8a, 0x1c, 0x1c, 0xeb, 0x61, 0x0d, 0xc2, 0x9a, 0x3f, 0x79, + /*7b60:*/ 0xf4, 0x73, 0x8f, 0x30, 0xb7, 0x73, 0x06, 0x0c, 0xfc, 0x74, 0xf9, 0x60, 0x05, 0x46, 0xe9, 0x10, + /*7b70:*/ 0x1f, 0x8d, 0x01, 0x46, 0xd7, 0xc3, 0x72, 0x19, 0x7f, 0x45, 0x09, 0xe7, 0xe2, 0x9f, 0x7e, 0x57, + /*7b80:*/ 0x65, 0x0a, 0x4b, 0x02, 0x51, 0x20, 0xda, 0x6d, 0x09, 0xbf, 0x10, 0x02, 0xbc, 0xb9, 0x57, 0x5a, + /*7b90:*/ 0x4d, 0x49, 0x51, 0x9d, 0xb5, 0x1d, 0xb1, 0xf0, 0x1d, 0x31, 0xe1, 0xac, 0x27, 0x28, 0x6f, 0xc2, + /*7ba0:*/ 0x2f, 0xd2, 0x2e, 0xb6, 0xe8, 0xa9, 0xaa, 0xfd, 0x48, 0x61, 0x1a, 0xcc, 0x06, 0x33, 0x43, 0x42, + /*7bb0:*/ 0x5b, 0x37, 0x63, 0x31, 0xbc, 0x08, 0x0b, 0xea, 0x64, 0x64, 0xbf, 0x64, 0x48, 0xd6, 0x67, 0x02, + /*7bc0:*/ 0xda, 0xb3, 0xd4, 0x7b, 0xac, 0x59, 0x47, 0xde, 0x5a, 0x69, 0xac, 0xf4, 0xbc, 0x92, 0x5f, 0x23, + /*7bd0:*/ 0x0c, 0xd8, 0x07, 0x48, 0xd4, 0x7a, 0x7e, 0x5b, 0x09, 0xff, 0xc6, 0xc8, 0x6d, 0x64, 0xcb, 0x36, + /*7be0:*/ 0x0f, 0x71, 0xe9, 0x8a, 0xa2, 0xbe, 0xee, 0xaa, 0x21, 0xf5, 0xfe, 0xe6, 0xdc, 0x05, 0x19, 0x26, + /*7bf0:*/ 0x58, 0x85, 0x09, 0x62, 0x18, 0x96, 0x37, 0x0d, 0xde, 0xf5, 0xbf, 0xe6, 0x96, 0x15, 0xea, 0x51, + /*7c00:*/ 0x88, 0x63, 0x2e, 0x1d, 0x08, 0xad, 0xa2, 0x48, 0x0b, 0x93, 0x89, 0xb0, 0xfc, 0x89, 0xa7, 0x64, + /*7c10:*/ 0x85, 0x42, 0x55, 0x64, 0x67, 0x76, 0xb9, 0x88, 0x94, 0xa0, 0x4a, 0x6a, 0xf2, 0x5e, 0x02, 0xa8, + /*7c20:*/ 0x06, 0xd1, 0x43, 0x8b, 0xfa, 0xe7, 0x99, 0x3b, 0xdc, 0x61, 0xbe, 0x3e, 0x9a, 0xd7, 0xea, 0x8f, + /*7c30:*/ 0x67, 0xd4, 0xdd, 0x46, 0x5a, 0x87, 0xed, 0x92, 0x25, 0xe7, 0x0e, 0x27, 0x08, 0x49, 0xfc, 0x5c, + /*7c40:*/ 0x22, 0x35, 0xa8, 0x2f, 0xcd, 0x9a, 0xa2, 0x2a, 0x54, 0xf5, 0xdb, 0x0e, 0x2c, 0x77, 0xf6, 0x5d, + /*7c50:*/ 0xa3, 0x1f, 0xf5, 0xa3, 0x9a, 0xa7, 0x74, 0xce, 0x58, 0xb0, 0xbd, 0x88, 0x8e, 0x4f, 0x97, 0xff, + /*7c60:*/ 0x78, 0x0c, 0x9c, 0x7d, 0x5c, 0x65, 0x6c, 0x24, 0x7c, 0xe3, 0x7f, 0xee, 0x2f, 0x50, 0xf3, 0x1f, + /*7c70:*/ 0x7d, 0x6b, 0xd4, 0xc3, 0xe3, 0x3a, 0x88, 0x81, 0x8d, 0x61, 0x7f, 0xdc, 0xa9, 0x4b, 0xac, 0x0e, + /*7c80:*/ 0x76, 0x1e, 0x4e, 0xd8, 0xf7, 0x5b, 0x2c, 0x03, 0x37, 0xa6, 0x93, 0x78, 0xb0, 0xad, 0x96, 0xff, + /*7c90:*/ 0xf1, 0xaf, 0x9a, 0x1c, 0xa4, 0x9d, 0x04, 0x5a, 0xbd, 0x85, 0x1b, 0xd9, 0xad, 0x92, 0x1a, 0x28, + /*7ca0:*/ 0xe7, 0x7e, 0x08, 0x25, 0x67, 0xb8, 0x0c, 0x83, 0x2f, 0x3d, 0x92, 0xd7, 0xfe, 0xcf, 0x18, 0xee, + /*7cb0:*/ 0xd8, 0xd3, 0x2d, 0xec, 0x6f, 0x56, 0x3c, 0x6a, 0x69, 0x4b, 0x31, 0x8b, 0x7e, 0x9d, 0x18, 0x26, + /*7cc0:*/ 0xdc, 0xdd, 0x89, 0xc2, 0x1d, 0x32, 0x49, 0x27, 0xf7, 0x78, 0x46, 0x8e, 0xbf, 0x47, 0x37, 0x9d, + /*7cd0:*/ 0x45, 0xad, 0x46, 0x63, 0x9e, 0x70, 0xd7, 0xd9, 0xdd, 0x0f, 0x2f, 0xe1, 0x11, 0xe9, 0x93, 0xa2, + /*7ce0:*/ 0x99, 0x6e, 0xc4, 0x98, 0x6a, 0xf3, 0x31, 0x33, 0xe9, 0x54, 0x84, 0x6e, 0xc7, 0xe5, 0x7b, 0x79, + /*7cf0:*/ 0x4f, 0x06, 0x69, 0x36, 0x64, 0x23, 0x7e, 0xc5, 0xdc, 0x95, 0x1c, 0x34, 0x86, 0x93, 0x9e, 0xa9, + /*7d00:*/ 0x5f, 0xab, 0x6c, 0xff, 0xee, 0x8e, 0x80, 0x0b, 0x66, 0x76, 0xc0, 0x12, 0x75, 0x6d, 0x96, 0xb1, + /*7d10:*/ 0xaf, 0xb2, 0xe9, 0x96, 0x34, 0xcc, 0x99, 0x89, 0x59, 0xbc, 0xe0, 0xd5, 0xde, 0x1e, 0x7b, 0x3b, + /*7d20:*/ 0x88, 0xd3, 0xe4, 0x27, 0x06, 0x93, 0x4c, 0xf4, 0x8b, 0xdb, 0xef, 0xd3, 0x23, 0x85, 0x30, 0x37, + /*7d30:*/ 0x47, 0x54, 0x7e, 0x7d, 0xe7, 0x21, 0xeb, 0xc5, 0x55, 0x93, 0x1f, 0xd4, 0xf1, 0x8c, 0x7d, 0xd4, + /*7d40:*/ 0x3b, 0xfe, 0x83, 0x4a, 0xc8, 0x9a, 0xd4, 0x2a, 0x69, 0x52, 0x73, 0x81, 0x77, 0x8f, 0x7c, 0x98, + /*7d50:*/ 0xa0, 0x01, 0x7e, 0x7e, 0x34, 0x91, 0xb1, 0xea, 0x5b, 0x05, 0xa4, 0x0d, 0x41, 0x8c, 0x38, 0x0c, + /*7d60:*/ 0xfe, 0x32, 0x81, 0xee, 0x1a, 0x54, 0xcf, 0x01, 0x8e, 0xb3, 0x6e, 0xa0, 0x41, 0xa1, 0xa5, 0xa3, + /*7d70:*/ 0xc0, 0x18, 0x5e, 0x06, 0x32, 0x04, 0x85, 0x72, 0x60, 0x07, 0xb5, 0x30, 0xce, 0xfc, 0x21, 0xb4, + /*7d80:*/ 0xaa, 0xaa, 0xd9, 0xaf, 0xb1, 0x7e, 0xbd, 0x03, 0x32, 0x56, 0x55, 0x5c, 0xdb, 0xe3, 0x05, 0x06, + /*7d90:*/ 0x6b, 0x39, 0x67, 0x81, 0xcd, 0xd0, 0xc8, 0x5d, 0xb8, 0xae, 0xb6, 0x13, 0x3b, 0x6e, 0x4c, 0x4b, + /*7da0:*/ 0x8f, 0x12, 0x5f, 0x21, 0x61, 0x6c, 0xfc, 0x3f, 0x96, 0x1b, 0x82, 0x57, 0xf9, 0xbe, 0x5a, 0x91, + /*7db0:*/ 0x19, 0xac, 0xdd, 0x54, 0x2a, 0xd6, 0x8b, 0xa6, 0x0b, 0xb8, 0x7e, 0xeb, 0xaa, 0x86, 0x3a, 0x44, + /*7dc0:*/ 0x96, 0x7a, 0xec, 0x6a, 0x3e, 0xa0, 0x94, 0x3e, 0xb3, 0xe0, 0xc1, 0xf9, 0xd4, 0xff, 0xa4, 0x10, + /*7dd0:*/ 0x79, 0x8e, 0x83, 0x65, 0x2e, 0xd9, 0x90, 0xec, 0x00, 0xca, 0x2a, 0x86, 0xb8, 0x85, 0xf1, 0xa1, + /*7de0:*/ 0xdc, 0xfe, 0x54, 0x11, 0x67, 0xcf, 0x6d, 0x42, 0x6c, 0x2d, 0xf7, 0x8e, 0x9c, 0x5e, 0x0f, 0x62, + /*7df0:*/ 0x49, 0xf8, 0xb2, 0x4c, 0xc8, 0x7a, 0x47, 0x40, 0x59, 0xba, 0xa3, 0x8b, 0xad, 0x61, 0x8e, 0xd6, + /*7e00:*/ 0xbf, 0xd1, 0xf4, 0x3e, 0xb9, 0x80, 0x47, 0xd5, 0x94, 0xa9, 0xb9, 0xc1, 0x4d, 0xf4, 0x35, 0xa6, + /*7e10:*/ 0xa4, 0x13, 0x90, 0xcb, 0x7f, 0x9d, 0x08, 0xb7, 0x5a, 0x5e, 0x1f, 0x5a, 0x5c, 0x19, 0xc2, 0xce, + /*7e20:*/ 0xa2, 0xe4, 0xc1, 0x2c, 0xdb, 0xb9, 0x84, 0xb4, 0x7a, 0xa4, 0x0c, 0xaf, 0xf0, 0xdc, 0x7e, 0xe4, + /*7e30:*/ 0x27, 0x94, 0x69, 0x07, 0x6d, 0xc2, 0xaa, 0xc4, 0x95, 0x80, 0xb5, 0x94, 0xf8, 0x57, 0x0e, 0x97, + /*7e40:*/ 0x4d, 0x9a, 0x3e, 0x5c, 0x63, 0x44, 0x1b, 0x61, 0x22, 0xd8, 0x47, 0x4c, 0x35, 0x39, 0xa0, 0xfd, + /*7e50:*/ 0x52, 0x3c, 0x3f, 0x2f, 0x2d, 0x15, 0x19, 0x7b, 0xd9, 0x17, 0xa7, 0x90, 0x0f, 0xbe, 0x21, 0xf6, + /*7e60:*/ 0x7b, 0x58, 0x8f, 0x48, 0x77, 0x0e, 0xac, 0x66, 0xa3, 0x2f, 0x80, 0xee, 0xe6, 0x23, 0x72, 0x03, + /*7e70:*/ 0x8e, 0x56, 0x54, 0x13, 0x1e, 0x06, 0xbc, 0x5d, 0xdf, 0x78, 0xf5, 0x1f, 0x1e, 0x2f, 0xd6, 0x68, + /*7e80:*/ 0x50, 0x1d, 0xaf, 0x61, 0x5d, 0x4b, 0x38, 0x31, 0x2c, 0xef, 0x54, 0x3c, 0x5f, 0xfc, 0xb5, 0x5e, + /*7e90:*/ 0xd9, 0x96, 0x08, 0x31, 0x25, 0x20, 0x42, 0xfb, 0x19, 0xba, 0xc8, 0xf2, 0x0f, 0xe3, 0xfd, 0x5b, + /*7ea0:*/ 0xae, 0x65, 0xba, 0x26, 0xfa, 0x7a, 0xfd, 0x79, 0xfd, 0xda, 0x2b, 0xab, 0xb2, 0x0b, 0x40, 0x55, + /*7eb0:*/ 0x87, 0x81, 0x6d, 0xc1, 0x02, 0xa4, 0xbc, 0x94, 0x89, 0x81, 0x42, 0xe7, 0x40, 0xf0, 0xd0, 0xfe, + /*7ec0:*/ 0x54, 0x56, 0xf8, 0xfa, 0x0c, 0x53, 0xce, 0xac, 0x04, 0xe3, 0xfb, 0xc6, 0x2f, 0x87, 0x6b, 0xde, + /*7ed0:*/ 0x74, 0x0f, 0x7a, 0x5b, 0xb8, 0xf2, 0x0a, 0x66, 0xf0, 0xb2, 0x1e, 0xd8, 0x2f, 0x37, 0xe0, 0xc1, + /*7ee0:*/ 0x45, 0x62, 0x6b, 0x0b, 0xab, 0xe8, 0x1f, 0x31, 0x7a, 0x28, 0xca, 0x54, 0x6f, 0x36, 0x10, 0xd6, + /*7ef0:*/ 0x43, 0xc1, 0xe1, 0x0a, 0x2e, 0xb6, 0xce, 0xaf, 0x45, 0xdc, 0x18, 0x9e, 0xcf, 0x5a, 0xdd, 0xea, + /*7f00:*/ 0x2e, 0xd7, 0xe5, 0x55, 0x49, 0x3e, 0x08, 0x15, 0xf7, 0xe3, 0xf7, 0x78, 0x8e, 0x41, 0xd1, 0xf8, + /*7f10:*/ 0xf4, 0x7a, 0x59, 0x93, 0xc8, 0xdf, 0xdb, 0xe1, 0x88, 0x66, 0x21, 0x84, 0xb7, 0x4d, 0xd6, 0x4a, + /*7f20:*/ 0x61, 0x2c, 0x5b, 0x8b, 0xf4, 0xc3, 0x64, 0xcc, 0x73, 0x69, 0xca, 0x0b, 0x55, 0x38, 0xbd, 0x2a, + /*7f30:*/ 0x6d, 0x1f, 0xad, 0xe4, 0xfe, 0x3a, 0xbf, 0x4a, 0xff, 0x18, 0x5f, 0x9c, 0x5d, 0xa7, 0x2f, 0xbc, + /*7f40:*/ 0x71, 0x8a, 0xe0, 0x82, 0x4a, 0xd8, 0x92, 0xdb, 0xb6, 0x80, 0x29, 0xa4, 0xed, 0x65, 0x3f, 0x72, + /*7f50:*/ 0xc4, 0xbc, 0x05, 0x4f, 0x3a, 0x97, 0x5d, 0x3c, 0x24, 0x50, 0xa4, 0x5b, 0x4e, 0x75, 0xab, 0x20, + /*7f60:*/ 0x96, 0x42, 0xa3, 0x5b, 0x36, 0x74, 0x79, 0xb0, 0xd2, 0xce, 0x49, 0x23, 0xa2, 0x22, 0xd7, 0x21, + /*7f70:*/ 0x66, 0xbe, 0xc4, 0xa9, 0x0c, 0x9d, 0xb3, 0xfc, 0x18, 0x81, 0x48, 0x7e, 0x1b, 0xfa, 0xdf, 0xb8, + /*7f80:*/ 0xba, 0xae, 0x15, 0x16, 0xdf, 0xee, 0x6c, 0x53, 0xf9, 0x6a, 0x80, 0xbb, 0xe0, 0x5e, 0x98, 0x2d, + /*7f90:*/ 0x18, 0xf1, 0x45, 0x99, 0x2d, 0xb8, 0xc6, 0xff, 0x74, 0xf4, 0xaa, 0x0b, 0x94, 0x42, 0x09, 0xb8, + /*7fa0:*/ 0x26, 0x5f, 0x7c, 0x15, 0x17, 0xe0, 0x90, 0x04, 0x96, 0x1e, 0x8d, 0xa9, 0xc3, 0x59, 0xcb, 0x5a, + /*7fb0:*/ 0xc2, 0x22, 0x78, 0x9c, 0xbe, 0xb1, 0xc8, 0x5b, 0x84, 0xda, 0x24, 0x3f, 0x3b, 0xc9, 0x9b, 0x7a, + /*7fc0:*/ 0xbb, 0xfd, 0xe7, 0x4b, 0x23, 0x43, 0xd1, 0x04, 0x98, 0x14, 0x5e, 0x23, 0xdb, 0xb9, 0x18, 0x3c, + /*7fd0:*/ 0x4f, 0xdb, 0xe1, 0x14, 0x1e, 0x30, 0x19, 0xd6, 0xb6, 0x70, 0xd4, 0xe1, 0xe1, 0x40, 0xad, 0xff, + /*7fe0:*/ 0xe9, 0xcc, 0xd5, 0xfa, 0xc1, 0x2b, 0x66, 0x07, 0xde, 0x05, 0x6d, 0xe7, 0x97, 0x75, 0xb9, 0x3f, + /*7ff0:*/ 0x5f, 0xd2, 0xdf, 0xd2, 0xd1, 0x27, 0xfe, 0x29, 0xb7, 0xc5, 0xfa, 0x41, 0xfd, 0x39, 0x39, 0x45, + /*8000:*/ 0xc6, 0x96, 0xa2, 0xd5, 0x25, 0xab, 0x00, 0xe4, 0x4c, 0xc8, 0x48, 0xe5, 0x89, 0xa5, 0x0b, 0x13, + /*8010:*/ 0x82, 0xb5, 0x53, 0xd6, 0x4c, 0x47, 0x7d, 0x28, 0x39, 0xe5, 0xad, 0x94, 0xc4, 0x6d, 0x21, 0x1e, + /*8020:*/ 0xb0, 0x73, 0xd9, 0xcc, 0xa6, 0x2f, 0x0b, 0xf0, 0x9c, 0xd7, 0x5c, 0x5f, 0x99, 0xf6, 0x09, 0x6e, + /*8030:*/ 0x64, 0xb1, 0xce, 0xcc, 0xee, 0x55, 0xd9, 0xeb, 0x51, 0x5f, 0x03, 0x03, 0x6f, 0xc2, 0xea, 0x70, + /*8040:*/ 0xc3, 0x4c, 0xd1, 0x9e, 0x26, 0x06, 0x0f, 0x80, 0x2d, 0xf0, 0x43, 0x75, 0x09, 0x8c, 0x52, 0x6a, + /*8050:*/ 0xbb, 0x76, 0xda, 0x09, 0x2f, 0x00, 0x45, 0xad, 0x9a, 0x24, 0x12, 0x4c, 0x29, 0x58, 0x67, 0x4f, + /*8060:*/ 0xd8, 0xdd, 0xe9, 0x62, 0xd4, 0x95, 0x0d, 0x83, 0x62, 0xfe, 0x66, 0xad, 0x12, 0x06, 0xe1, 0x16, + /*8070:*/ 0xb8, 0x89, 0xb4, 0x9f, 0xa6, 0xb6, 0x4f, 0xa7, 0xfe, 0x72, 0xd5, 0xbc, 0x7c, 0x84, 0x62, 0xe2, + /*8080:*/ 0xb1, 0xfb, 0x0c, 0x54, 0xed, 0x69, 0x96, 0x68, 0x5c, 0x1b, 0xcf, 0xa3, 0x56, 0xdd, 0x0b, 0x78, + /*8090:*/ 0x9c, 0x5d, 0x7d, 0x9d, 0x05, 0x79, 0x72, 0xb9, 0xa9, 0x6e, 0xd1, 0xfb, 0x0c, 0x28, 0x2b, 0xa9, + /*80a0:*/ 0xf4, 0xb3, 0x41, 0xb1, 0x12, 0xe0, 0xe3, 0xf4, 0xf0, 0x6c, 0x86, 0x50, 0xf0, 0xaf, 0x23, 0x87, + /*80b0:*/ 0x67, 0x91, 0xe2, 0x07, 0x6c, 0x77, 0x16, 0xf9, 0x5f, 0x83, 0x8a, 0x46, 0xb6, 0xe3, 0x02, 0x59, + /*80c0:*/ 0x77, 0xaf, 0x3e, 0x98, 0x33, 0x3f, 0xb6, 0xf4, 0x02, 0x23, 0x50, 0xd8, 0x4b, 0xc9, 0x4e, 0xd9, + /*80d0:*/ 0x00, 0xe9, 0x68, 0x13, 0x44, 0xed, 0x2c, 0x4d, 0xd7, 0x60, 0xb4, 0x69, 0xc6, 0xd4, 0xe7, 0xc6, + /*80e0:*/ 0x57, 0xe4, 0xb0, 0x5d, 0x74, 0x51, 0xb5, 0x09, 0x54, 0x11, 0x58, 0x1b, 0xab, 0xf6, 0x54, 0xfb, + /*80f0:*/ 0xe4, 0xaa, 0x99, 0xb0, 0xc2, 0xa8, 0xc3, 0x2d, 0x52, 0x95, 0x39, 0x51, 0x4b, 0x18, 0x83, 0xe6, + /*8100:*/ 0xfc, 0x55, 0xd5, 0x0a, 0xae, 0x93, 0x70, 0x97, 0x60, 0x65, 0x63, 0x61, 0x72, 0x65, 0x9a, 0xe8, + /*8110:*/ 0x13, 0x86, 0x99, 0x14, 0x75, 0xca, 0xe2, 0x9b, 0x40, 0xaf, 0x63, 0x49, 0x50, 0xfc, 0x1d, 0x9b, + /*8120:*/ 0x2a, 0x26, 0xee, 0xbc, 0x88, 0x78, 0x1d, 0xd8, 0xd6, 0x51, 0x8b, 0x8f, 0x45, 0xf9, 0xe0, 0x4b, + /*8130:*/ 0x70, 0xb4, 0x6b, 0x84, 0x42, 0xe5, 0x7b, 0x26, 0xf0, 0xb4, 0xff, 0x15, 0x70, 0x23, 0xc7, 0xd6, + /*8140:*/ 0xd7, 0xa0, 0x22, 0x84, 0x8f, 0x3d, 0xd6, 0x25, 0x26, 0x22, 0x3e, 0xcf, 0x81, 0x67, 0x1e, 0xdc, + /*8150:*/ 0x23, 0xc7, 0x2a, 0xe7, 0x2e, 0x68, 0x65, 0x06, 0x2f, 0xe0, 0x57, 0xe0, 0x89, 0x27, 0x5f, 0xc6, + /*8160:*/ 0x81, 0x85, 0x04, 0xb0, 0xa3, 0xc9, 0xde, 0xe3, 0x4f, 0x68, 0x4d, 0xc7, 0xa2, 0xc9, 0xc2, 0x6c, + /*8170:*/ 0x42, 0x37, 0x7d, 0x94, 0xe4, 0x61, 0x26, 0x39, 0x26, 0xc7, 0x30, 0xd9, 0xfc, 0x5a, 0x82, 0x44, + /*8180:*/ 0xee, 0x2c, 0x82, 0x2f, 0xa3, 0x66, 0xfc, 0x7a, 0x6b, 0xde, 0x3a, 0xf8, 0xad, 0xc4, 0xcc, 0xdf, + /*8190:*/ 0x4f, 0x38, 0xf0, 0x1e, 0xd8, 0x0d, 0x7d, 0x98, 0x6b, 0x74, 0xa5, 0xd7, 0x10, 0xce, 0xa0, 0x53, + /*81a0:*/ 0x72, 0x51, 0xf1, 0x5a, 0xa0, 0x01, 0x2c, 0x33, 0xe5, 0xfe, 0x25, 0xeb, 0x6c, 0xe3, 0x79, 0x02, + /*81b0:*/ 0x87, 0x5a, 0x56, 0xe9, 0xb6, 0xd0, 0xd1, 0x41, 0xe4, 0x2f, 0x53, 0xed, 0xbd, 0x22, 0x14, 0xe0, + /*81c0:*/ 0x2d, 0x48, 0x8c, 0xb9, 0x67, 0xd8, 0x7b, 0x27, 0x58, 0x7a, 0x7c, 0xc8, 0xd6, 0x48, 0xec, 0xd9, + /*81d0:*/ 0xba, 0xcf, 0xd1, 0xc4, 0xbd, 0x7f, 0x38, 0xb7, 0xdf, 0x4a, 0xff, 0x99, 0xd8, 0xf4, 0xaa, 0xbf, + /*81e0:*/ 0x68, 0x9a, 0xcb, 0x63, 0xcd, 0x01, 0x05, 0x53, 0xfd, 0xae, 0xcd, 0xd7, 0xfe, 0xa7, 0x79, 0x42, + /*81f0:*/ 0x85, 0x63, 0x40, 0x44, 0x65, 0x1b, 0x83, 0x70, 0x16, 0x1f, 0xc0, 0xf1, 0xb2, 0x49, 0x0f, 0x99, + /*8200:*/ 0x40, 0xbe, 0x21, 0xfa, 0x8e, 0x85, 0xb7, 0x9d, 0xee, 0x28, 0xbc, 0xac, 0x2b, 0x85, 0x3b, 0xdf, + /*8210:*/ 0x4a, 0x72, 0x81, 0x6d, 0x0e, 0x75, 0x58, 0x34, 0x41, 0x5b, 0xa3, 0x0f, 0x00, 0x1b, 0x28, 0xcf, + /*8220:*/ 0xa7, 0x57, 0x4e, 0x78, 0x41, 0x7c, 0xf9, 0x4e, 0x44, 0xcb, 0x6f, 0x4b, 0x88, 0x84, 0x73, 0x4f, + /*8230:*/ 0xfa, 0x4a, 0xc4, 0xa9, 0xad, 0xd7, 0xeb, 0x1d, 0x52, 0xe4, 0xd7, 0xa3, 0xdc, 0x37, 0xae, 0x23, + /*8240:*/ 0xe3, 0xa6, 0x91, 0x02, 0x75, 0xf0, 0x16, 0xbb, 0x24, 0x09, 0x15, 0xa3, 0x79, 0xe2, 0xd9, 0x66, + /*8250:*/ 0x25, 0x27, 0xe8, 0x5e, 0x72, 0x7d, 0xc6, 0x38, 0xac, 0xfb, 0x62, 0x3b, 0x7d, 0x23, 0xe6, 0xbf, + /*8260:*/ 0x94, 0x12, 0x15, 0xcb, 0xd7, 0x73, 0xd7, 0xc9, 0x02, 0xff, 0xa5, 0xae, 0x15, 0x45, 0xc7, 0xfd, + /*8270:*/ 0x82, 0x77, 0x54, 0xd3, 0xc0, 0xcb, 0xc6, 0x1c, 0x8d, 0x58, 0x51, 0xd2, 0x82, 0x66, 0x03, 0x84, + /*8280:*/ 0x5a, 0x16, 0xad, 0x90, 0x0b, 0x29, 0x98, 0x6c, 0xa1, 0x53, 0xc3, 0x8e, 0x9e, 0x30, 0x61, 0x6f, + /*8290:*/ 0xc0, 0xc1, 0x8e, 0x61, 0x67, 0x82, 0x32, 0xb8, 0xa7, 0x4c, 0xa6, 0x78, 0x28, 0x72, 0xed, 0xc9, + /*82a0:*/ 0x17, 0x6d, 0xf4, 0xe1, 0x83, 0x9c, 0xa3, 0xc8, 0x57, 0x47, 0xf6, 0x0f, 0xa5, 0x43, 0x36, 0x78, + /*82b0:*/ 0x53, 0xd2, 0xf7, 0x75, 0xc2, 0x93, 0xb5, 0x4b, 0x5a, 0xbf, 0xa0, 0xfe, 0x09, 0xb3, 0xa4, 0x69, + /*82c0:*/ 0x3e, 0xee, 0x5e, 0xb1, 0xe6, 0x2b, 0xca, 0x21, 0x62, 0xed, 0xf5, 0x3a, 0xa6, 0x3c, 0x41, 0x44, + /*82d0:*/ 0x75, 0x03, 0xc8, 0x1e, 0x7f, 0x82, 0x5c, 0x9f, 0x77, 0x72, 0x73, 0xcf, 0xf4, 0x9e, 0x20, 0x63, + /*82e0:*/ 0x60, 0xe1, 0x4b, 0x42, 0xb4, 0xa1, 0xdf, 0xda, 0xdc, 0x2e, 0xda, 0x4f, 0xba, 0xf2, 0x2a, 0x44, + /*82f0:*/ 0x7a, 0x82, 0x40, 0xb9, 0x5d, 0xa2, 0x61, 0x1e, 0xea, 0xff, 0x9a, 0xd7, 0x85, 0x8b, 0x2a, 0x88, + /*8300:*/ 0x6a, 0xbc, 0xdb, 0x16, 0x1b, 0x43, 0x02, 0xbd, 0x36, 0xa1, 0x9e, 0x86, 0x45, 0x15, 0x4b, 0x07, + /*8310:*/ 0x05, 0xe0, 0x64, 0x85, 0xda, 0xc3, 0x61, 0xdd, 0xc6, 0xf7, 0xf1, 0x6b, 0xe0, 0xf0, 0x0b, 0xcd, + /*8320:*/ 0x6d, 0x6e, 0x33, 0x05, 0xdf, 0x4e, 0x18, 0x79, 0xfc, 0x85, 0x30, 0xf1, 0x04, 0xa8, 0x7a, 0x9a, + /*8330:*/ 0xbe, 0x72, 0x8f, 0x92, 0x30, 0xd8, 0x04, 0x19, 0xbc, 0x26, 0xc5, 0xe6, 0x71, 0xd3, 0x4d, 0xfc, + /*8340:*/ 0xe8, 0x44, 0xca, 0x60, 0xb6, 0x0a, 0x2f, 0x8a, 0x36, 0x83, 0x54, 0x6f, 0x68, 0xcd, 0xa6, 0x60, + /*8350:*/ 0x64, 0xdc, 0xcd, 0xde, 0xeb, 0x92, 0x47, 0x61, 0xce, 0xc7, 0xa9, 0x99, 0xd9, 0xad, 0x4e, 0x4d, + /*8360:*/ 0x11, 0xb5, 0x10, 0x46, 0x31, 0x91, 0x66, 0x42, 0xad, 0xe1, 0xb9, 0x79, 0x93, 0x62, 0xde, 0x40, + /*8370:*/ 0xd5, 0x1b, 0x74, 0x70, 0x73, 0xb1, 0xa7, 0xa3, 0x85, 0xcd, 0x55, 0x62, 0x8b, 0x2c, 0xf9, 0xcf, + /*8380:*/ 0xa5, 0x7f, 0x02, 0x3f, 0x58, 0x04, 0x7c, 0x02, 0x6f, 0x4d, 0xd4, 0x67, 0x95, 0x94, 0xf5, 0x42, + /*8390:*/ 0x57, 0xf9, 0xa1, 0x65, 0xc6, 0x2e, 0xb6, 0x7d, 0x1b, 0x93, 0x5b, 0xa3, 0x2d, 0x32, 0x77, 0x6b, + /*83a0:*/ 0xb0, 0xcd, 0xd6, 0x9b, 0xd6, 0x11, 0x7b, 0x5b, 0xc5, 0x10, 0x86, 0xc9, 0x74, 0x35, 0xfa, 0x67, + /*83b0:*/ 0xbc, 0xea, 0x5d, 0x46, 0x5c, 0xf6, 0x4f, 0xb7, 0x86, 0x58, 0xda, 0x5c, 0x38, 0xf5, 0x68, 0xb8, + /*83c0:*/ 0xcf, 0xbb, 0x7e, 0x76, 0x0d, 0xdd, 0x1b, 0x28, 0xcd, 0x4f, 0xb3, 0x99, 0x8c, 0x11, 0xef, 0x6e, + /*83d0:*/ 0x1b, 0xf0, 0x81, 0xb4, 0x6b, 0xb9, 0x34, 0xa4, 0x93, 0x5d, 0xf1, 0xca, 0xef, 0x45, 0x60, 0xc2, + /*83e0:*/ 0x35, 0xdf, 0x01, 0xcf, 0x2b, 0x3a, 0xb6, 0x1f, 0xd1, 0x8d, 0x3d, 0xe7, 0x12, 0x60, 0xed, 0xc4, + /*83f0:*/ 0x0b, 0x36, 0x84, 0xe3, 0x6b, 0x75, 0x09, 0x2a, 0x95, 0xad, 0xa5, 0x37, 0x4f, 0x75, 0xc5, 0x13, + /*8400:*/ 0x61, 0x74, 0x17, 0x83, 0x86, 0x94, 0x94, 0xfe, 0x0e, 0x7d, 0xc1, 0x54, 0x6b, 0x13, 0x3b, 0xd9, + /*8410:*/ 0x7c, 0xf7, 0x90, 0x56, 0x7d, 0x30, 0x42, 0xd0, 0x82, 0x42, 0xc3, 0x3a, 0x52, 0xdf, 0x70, 0x24, + /*8420:*/ 0xb3, 0xcb, 0x25, 0x15, 0x2d, 0x4e, 0xa9, 0xd4, 0x56, 0x33, 0xb9, 0x79, 0xca, 0xbd, 0xcc, 0x56, + /*8430:*/ 0x9f, 0x13, 0xc0, 0x44, 0xe4, 0x71, 0xdf, 0x2d, 0xf2, 0x55, 0x49, 0xae, 0x0f, 0x10, 0x4d, 0x03, + /*8440:*/ 0x08, 0x59, 0x6d, 0xf9, 0xb1, 0xd8, 0x14, 0x88, 0xdd, 0x0e, 0x0f, 0xa9, 0xbc, 0x5d, 0x74, 0xff, + /*8450:*/ 0x9b, 0xf8, 0x8c, 0xbb, 0xdf, 0xb4, 0x60, 0x64, 0x2f, 0x7b, 0x5e, 0x83, 0x52, 0xf5, 0x7a, 0xf7, + /*8460:*/ 0x33, 0x50, 0x08, 0x07, 0xb0, 0x2e, 0x7e, 0x88, 0xa8, 0x4b, 0xd2, 0xe5, 0xbc, 0x9c, 0xf2, 0x1b, + /*8470:*/ 0x64, 0xe9, 0x1c, 0x65, 0xb4, 0xec, 0x97, 0x0d, 0xd3, 0xa0, 0x8e, 0x02, 0xe9, 0x2b, 0xb1, 0x05, + /*8480:*/ 0x74, 0xe9, 0x8c, 0x18, 0x27, 0xcd, 0x6c, 0x59, 0x5d, 0xfd, 0xf3, 0x56, 0x5e, 0x56, 0xd7, 0xf0, + /*8490:*/ 0xa4, 0x0a, 0xc0, 0x16, 0x81, 0x07, 0x41, 0xc7, 0xf0, 0xe1, 0x08, 0x1a, 0xf8, 0xa8, 0x0f, 0xa7, + /*84a0:*/ 0x23, 0x95, 0xaa, 0x49, 0x3c, 0x5e, 0xb2, 0x7f, 0x69, 0xf3, 0x3d, 0xdd, 0xb4, 0x56, 0x96, 0xdb, + /*84b0:*/ 0xea, 0xf2, 0x34, 0xa8, 0xd0, 0xb7, 0x72, 0x98, 0x47, 0x15, 0x93, 0xf6, 0x57, 0x9c, 0xb1, 0x26, + /*84c0:*/ 0xf1, 0x00, 0xdf, 0xe8, 0xfb, 0x81, 0x15, 0x0f, 0x8d, 0x33, 0x9e, 0x79, 0x0e, 0x41, 0xf4, 0x16, + /*84d0:*/ 0x31, 0xdd, 0xfd, 0xec, 0x7d, 0x4b, 0x7e, 0x3b, 0xd7, 0x71, 0xf1, 0x1c, 0xb2, 0x53, 0x2b, 0x6f, + /*84e0:*/ 0xc5, 0x58, 0xf1, 0x50, 0xfe, 0xc3, 0x29, 0x82, 0xd2, 0xf4, 0x7c, 0xd7, 0x42, 0x8a, 0x7a, 0x83, + /*84f0:*/ 0x79, 0x42, 0x62, 0xde, 0x92, 0x64, 0x58, 0x6e, 0x9b, 0x24, 0x8d, 0x16, 0xb8, 0xf9, 0x83, 0xf9, + /*8500:*/ 0x8a, 0x35, 0x67, 0xf7, 0x07, 0xd5, 0x43, 0xd0, 0xc6, 0x71, 0x35, 0xfb, 0xb5, 0x9f, 0x0d, 0x84, + /*8510:*/ 0x9e, 0xa9, 0x69, 0x3b, 0x4e, 0x3c, 0xa3, 0x72, 0xd7, 0x48, 0xaf, 0xae, 0xba, 0xae, 0x4a, 0xf7, + /*8520:*/ 0x06, 0xce, 0xf6, 0xc8, 0x41, 0x0a, 0x7e, 0xfb, 0x76, 0xc6, 0xb0, 0xcc, 0xa9, 0xd9, 0xd3, 0xb6, + /*8530:*/ 0xfe, 0xc5, 0x62, 0x99, 0x28, 0x03, 0xdb, 0xa8, 0x10, 0xe9, 0xd2, 0x3b, 0x1b, 0xe2, 0xf5, 0x1b, + /*8540:*/ 0x81, 0xea, 0xfd, 0xd2, 0x9f, 0x34, 0xc8, 0xca, 0x58, 0x6d, 0x74, 0xbf, 0x2b, 0x53, 0x17, 0xf2, + /*8550:*/ 0x64, 0x15, 0xc0, 0x31, 0x77, 0x7a, 0x00, 0xcd, 0x28, 0x72, 0x56, 0x82, 0x81, 0xb8, 0xd8, 0x56, + /*8560:*/ 0x0f, 0xe1, 0xa3, 0xc2, 0xf8, 0x78, 0x01, 0x9f, 0x76, 0xd8, 0x77, 0xf6, 0x06, 0x78, 0x4c, 0xf4, + /*8570:*/ 0xf8, 0xab, 0x09, 0x9f, 0x81, 0x7c, 0xdf, 0x6c, 0x79, 0x0f, 0xb8, 0xed, 0xec, 0x92, 0x68, 0xb1, + /*8580:*/ 0x0d, 0xed, 0x5c, 0x62, 0xe1, 0x94, 0x91, 0xfd, 0x39, 0xbe, 0x65, 0x59, 0x45, 0xfb, 0x59, 0xe1, + /*8590:*/ 0xbd, 0xad, 0xbc, 0x41, 0xa0, 0x94, 0x49, 0xec, 0x29, 0x06, 0xe9, 0xd8, 0x64, 0x04, 0xe1, 0x70, + /*85a0:*/ 0x31, 0xb9, 0xe4, 0xdf, 0x23, 0xf9, 0x7d, 0x0f, 0x5d, 0x9a, 0xa6, 0x67, 0x4c, 0xde, 0xdd, 0xb6, + /*85b0:*/ 0xb2, 0xc5, 0x33, 0x87, 0xee, 0xb8, 0x36, 0xaa, 0x32, 0xdb, 0xc4, 0x90, 0x9b, 0xe0, 0xc2, 0x6c, + /*85c0:*/ 0xcd, 0xae, 0xff, 0x7e, 0x9a, 0x35, 0xa7, 0x4e, 0x48, 0xe2, 0x62, 0x1b, 0x0e, 0x7d, 0x9b, 0x44, + /*85d0:*/ 0x43, 0xbd, 0x55, 0x82, 0x88, 0x1a, 0x9c, 0x83, 0xfc, 0x1e, 0x3d, 0x8b, 0x6b, 0x29, 0x23, 0xf8, + /*85e0:*/ 0x1e, 0xba, 0xb4, 0x5b, 0xc5, 0x80, 0x12, 0x70, 0x48, 0x9b, 0x41, 0xfb, 0xe6, 0xc8, 0xf3, 0x19, + /*85f0:*/ 0x15, 0x7b, 0xc0, 0x8d, 0xb0, 0x49, 0x67, 0xcc, 0xf4, 0xe0, 0x12, 0x41, 0xf9, 0xfb, 0xd4, 0x1a, + /*8600:*/ 0xe8, 0x72, 0x1b, 0xfc, 0x02, 0xbe, 0x6d, 0x34, 0x96, 0xaf, 0xba, 0x96, 0x44, 0x7d, 0xce, 0x3f, + /*8610:*/ 0x0e, 0x58, 0x7b, 0xb1, 0x0d, 0xb7, 0x00, 0x43, 0x6d, 0x81, 0xaa, 0xa6, 0xe4, 0x5c, 0xf1, 0xa4, + /*8620:*/ 0x1f, 0xe4, 0xa8, 0x30, 0x2b, 0x0c, 0xbf, 0xdd, 0x69, 0xfa, 0xe7, 0xf7, 0x44, 0xff, 0x50, 0x2b, + /*8630:*/ 0x39, 0x73, 0xbd, 0x03, 0x22, 0x84, 0xef, 0x14, 0x08, 0x74, 0xa8, 0x85, 0x05, 0x64, 0xd4, 0xc7, + /*8640:*/ 0x30, 0xa4, 0x84, 0x2e, 0xbd, 0x8d, 0x0c, 0xee, 0xfc, 0x11, 0x0f, 0x0c, 0x3f, 0xb1, 0x48, 0x6e, + /*8650:*/ 0xb6, 0x09, 0x01, 0xc8, 0x54, 0x6a, 0xe7, 0x1b, 0x46, 0x90, 0x5b, 0x79, 0x64, 0x08, 0xa8, 0xda, + /*8660:*/ 0xb0, 0x7e, 0x1f, 0xc3, 0x8c, 0xee, 0x9e, 0x9f, 0x8b, 0x9b, 0xc2, 0x80, 0x2f, 0x4f, 0x0d, 0x3a, + /*8670:*/ 0x97, 0x3b, 0xcd, 0xfa, 0xde, 0xa0, 0xaf, 0x6d, 0x1e, 0xd2, 0x47, 0x31, 0xe0, 0xf3, 0xcf, 0x15, + /*8680:*/ 0x12, 0xae, 0x45, 0xbb, 0x28, 0x04, 0x5e, 0xf6, 0x2e, 0xab, 0xa5, 0x8f, 0xea, 0xd0, 0xa4, 0xbf, + /*8690:*/ 0xbe, 0xa7, 0x77, 0x5d, 0x7b, 0xab, 0x48, 0x5f, 0x1a, 0xe4, 0xc6, 0xb3, 0x62, 0x70, 0xdf, 0x82, + /*86a0:*/ 0x24, 0x59, 0xd6, 0x88, 0x5c, 0x36, 0xd6, 0x0c, 0xbe, 0xbc, 0xbd, 0xc6, 0x1a, 0xcb, 0x93, 0xfa, + /*86b0:*/ 0xff, 0x16, 0x26, 0xea, 0xd2, 0xd3, 0x41, 0x5a, 0x49, 0x00, 0x99, 0x12, 0x48, 0xbe, 0xa8, 0xc7, + /*86c0:*/ 0xe3, 0x5d, 0x3b, 0xb1, 0x40, 0x35, 0xee, 0xfe, 0xc3, 0x78, 0x2b, 0xfe, 0x10, 0x20, 0xc9, 0x96, + /*86d0:*/ 0x28, 0xc2, 0xb2, 0x17, 0x03, 0x69, 0x85, 0x74, 0xf5, 0xac, 0x28, 0x02, 0xd0, 0x97, 0x74, 0xf2, + /*86e0:*/ 0x22, 0x12, 0x80, 0xf1, 0x1b, 0xd8, 0x49, 0x1d, 0x70, 0x79, 0x56, 0x7a, 0xbb, 0x2e, 0x5b, 0x35, + /*86f0:*/ 0x17, 0x34, 0x9b, 0xef, 0xf8, 0x58, 0x8d, 0x4b, 0xf3, 0x9a, 0x7a, 0xb3, 0xf7, 0x8c, 0x08, 0x4c, + /*8700:*/ 0x1f, 0xe4, 0x47, 0x30, 0xa2, 0x16, 0x9e, 0xe3, 0x5f, 0xb6, 0x57, 0xb3, 0x93, 0x8f, 0xd0, 0x5e, + /*8710:*/ 0x3b, 0x8d, 0x64, 0x70, 0x7c, 0xbc, 0x6e, 0xc0, 0x12, 0x4b, 0x1e, 0xcd, 0x0b, 0x58, 0x5c, 0xed, + /*8720:*/ 0x19, 0x2f, 0x72, 0x39, 0xaf, 0x03, 0xaf, 0x8f, 0xe0, 0xc1, 0x3f, 0xcc, 0x8a, 0x9a, 0x95, 0x12, + /*8730:*/ 0x7c, 0x88, 0x38, 0x7d, 0x82, 0xdb, 0xbe, 0x58, 0xbb, 0xa8, 0x9b, 0x05, 0x5f, 0x81, 0xe4, 0xaa, + /*8740:*/ 0x58, 0x81, 0xdc, 0x5f, 0x8a, 0x7c, 0xc0, 0xbc, 0x57, 0xa8, 0x48, 0xa4, 0x7e, 0xd5, 0x6d, 0xc4, + /*8750:*/ 0x04, 0x62, 0xbd, 0x28, 0x0e, 0x5c, 0x97, 0x3b, 0xf2, 0x6f, 0xee, 0xe9, 0x0d, 0x5a, 0x9c, 0x79, + /*8760:*/ 0x17, 0xfe, 0xac, 0x66, 0xb0, 0xa6, 0x6e, 0x11, 0x9b, 0xbe, 0x0b, 0xb4, 0x32, 0x67, 0x47, 0x14, + /*8770:*/ 0x70, 0xd6, 0x1c, 0x8c, 0x8f, 0x95, 0x96, 0xa8, 0x46, 0x10, 0x82, 0x49, 0xb7, 0x69, 0xb7, 0x40, + /*8780:*/ 0x83, 0xad, 0xfa, 0x1f, 0x89, 0x05, 0x8a, 0x16, 0x58, 0xee, 0x9c, 0xfd, 0x9f, 0x0c, 0xc6, 0xca, + /*8790:*/ 0xaf, 0x47, 0x5a, 0x00, 0xcd, 0xd6, 0x83, 0x8d, 0x04, 0xf6, 0x18, 0xc7, 0xf3, 0xd2, 0x4c, 0x7c, + /*87a0:*/ 0xdf, 0xc8, 0x61, 0xa9, 0x82, 0x96, 0xf3, 0x18, 0x77, 0xe2, 0x0a, 0x2c, 0x77, 0x67, 0x3c, 0x65, + /*87b0:*/ 0xd4, 0x56, 0xb0, 0xa6, 0x57, 0x0e, 0x74, 0xc9, 0xb5, 0x5e, 0xde, 0xe3, 0x09, 0x69, 0x53, 0x77, + /*87c0:*/ 0xdf, 0xd6, 0x20, 0xba, 0x19, 0xd6, 0x16, 0xbd, 0x4c, 0x95, 0x94, 0x00, 0x4a, 0xf8, 0x72, 0x83, + /*87d0:*/ 0x4c, 0xf2, 0x96, 0xa7, 0x1e, 0xf9, 0x62, 0x98, 0x64, 0x1a, 0xa5, 0x40, 0xb1, 0xbe, 0xd5, 0xb6, + /*87e0:*/ 0x53, 0x5f, 0xb9, 0xce, 0xa3, 0xcf, 0x03, 0x46, 0x94, 0x85, 0xd8, 0xc4, 0x86, 0x23, 0x85, 0x08, + /*87f0:*/ 0x1a, 0x13, 0xa2, 0x41, 0xf6, 0x9d, 0x52, 0xc6, 0xb2, 0x67, 0xe3, 0x30, 0x23, 0xcb, 0x3a, 0x4b, + /*8800:*/ 0x41, 0x57, 0x5f, 0xd2, 0x75, 0x8b, 0x5f, 0x44, 0x39, 0x40, 0x34, 0x25, 0xf1, 0xda, 0x0a, 0xb0, + /*8810:*/ 0xf0, 0xac, 0x15, 0x8d, 0xee, 0x68, 0x5c, 0x39, 0xbf, 0x48, 0x9a, 0x82, 0xfd, 0x81, 0x45, 0x7e, + /*8820:*/ 0xce, 0x81, 0xe6, 0x97, 0x3d, 0xf4, 0x21, 0x8c, 0x9b, 0x36, 0xe6, 0xd0, 0xbf, 0xcc, 0xf2, 0x33, + /*8830:*/ 0x4e, 0x98, 0x70, 0x3f, 0x08, 0x52, 0x9f, 0xd4, 0x48, 0xf3, 0x0a, 0xd8, 0x51, 0xfb, 0x39, 0x9b, + /*8840:*/ 0x8a, 0xf1, 0x32, 0x55, 0xf0, 0x59, 0x68, 0x17, 0xc8, 0x35, 0xe3, 0x38, 0x8c, 0x40, 0xd4, 0xf7, + /*8850:*/ 0xd3, 0xe7, 0x20, 0x07, 0x84, 0xf8, 0xc0, 0x9a, 0x2c, 0x56, 0x6d, 0xaa, 0xae, 0xca, 0x16, 0x82, + /*8860:*/ 0x9a, 0xd1, 0x72, 0x2e, 0xd4, 0x12, 0xda, 0x65, 0xe6, 0x78, 0x01, 0x79, 0x16, 0xa2, 0x05, 0x45, + /*8870:*/ 0x0b, 0xbc, 0x65, 0xd4, 0xf5, 0x19, 0x9d, 0x1f, 0xa4, 0x49, 0x02, 0xe3, 0x0f, 0x1a, 0x82, 0x49, + /*8880:*/ 0x2c, 0xd2, 0x22, 0xdf, 0x97, 0x7d, 0xe6, 0xaf, 0x14, 0x03, 0xdf, 0x69, 0xe6, 0xf3, 0x07, 0x50, + /*8890:*/ 0x48, 0xe5, 0x42, 0xfe, 0xe3, 0x59, 0x91, 0x6d, 0xbc, 0xf6, 0xd1, 0xf0, 0x2a, 0xbd, 0x0a, 0x4d, + /*88a0:*/ 0x4f, 0x51, 0x6e, 0x0f, 0x76, 0xef, 0xa8, 0xb5, 0xa7, 0x8b, 0x49, 0xf3, 0xd5, 0x8e, 0xf4, 0x41, + /*88b0:*/ 0xf9, 0x57, 0x26, 0x2f, 0xcf, 0xa8, 0xd7, 0x76, 0x36, 0xd1, 0xf1, 0xb9, 0x26, 0x79, 0x92, 0xaf, + /*88c0:*/ 0xcc, 0xf6, 0xe9, 0xab, 0xf2, 0x96, 0xec, 0x5e, 0xbb, 0xcc, 0xf0, 0x89, 0x39, 0xc1, 0x83, 0x8f, + /*88d0:*/ 0xf5, 0x07, 0xb6, 0x17, 0x61, 0x17, 0x1c, 0xcd, 0xb6, 0x3b, 0xcc, 0x68, 0x8d, 0x52, 0x96, 0x18, + /*88e0:*/ 0xbf, 0x18, 0x00, 0xcf, 0xf5, 0x9c, 0x81, 0x20, 0xb0, 0xed, 0x63, 0xef, 0x1e, 0xa2, 0xac, 0x84, + /*88f0:*/ 0x19, 0xd8, 0x9a, 0x28, 0x68, 0x27, 0xb1, 0x99, 0x54, 0x4b, 0xe4, 0x0b, 0xcc, 0x55, 0x9e, 0x49, + /*8900:*/ 0xdb, 0xbc, 0x4d, 0x85, 0x1d, 0x83, 0x83, 0x46, 0x64, 0x27, 0xe1, 0x6d, 0x25, 0x24, 0x72, 0xfe, + /*8910:*/ 0xfb, 0x37, 0x67, 0x48, 0xf0, 0x7f, 0x7a, 0xbc, 0x9c, 0x9b, 0xa6, 0xe0, 0x55, 0xa4, 0x98, 0x3b, + /*8920:*/ 0x8e, 0xbe, 0x5b, 0x92, 0x29, 0x5e, 0xcd, 0x46, 0xcd, 0x83, 0x43, 0xfb, 0x8a, 0xaf, 0x68, 0x89, + /*8930:*/ 0xc6, 0x68, 0x32, 0x83, 0x7c, 0x33, 0x6e, 0xf9, 0x8f, 0x53, 0x40, 0xda, 0x2c, 0x6f, 0xcc, 0x7a, + /*8940:*/ 0xd7, 0x90, 0xd7, 0xc0, 0x29, 0x9d, 0xb7, 0x08, 0xe0, 0xa4, 0x41, 0x25, 0x7e, 0x39, 0x04, 0xf3, + /*8950:*/ 0x02, 0xb8, 0x4e, 0x3e, 0xee, 0x80, 0x07, 0x20, 0xdc, 0x49, 0x16, 0x9e, 0xab, 0xb0, 0x81, 0xd3, + /*8960:*/ 0x33, 0x00, 0xfe, 0xf6, 0x85, 0xcd, 0xf8, 0xe6, 0x79, 0x87, 0x1a, 0x5b, 0x1e, 0x11, 0x1b, 0xca, + /*8970:*/ 0x89, 0x35, 0xa5, 0x3a, 0x98, 0x0f, 0x4d, 0x20, 0x25, 0xe4, 0xbf, 0x48, 0x6d, 0x2c, 0x03, 0x97, + /*8980:*/ 0xff, 0xbb, 0x85, 0x3b, 0x1f, 0x17, 0x4f, 0xd6, 0xf4, 0xd4, 0xb8, 0x80, 0x49, 0x1a, 0x52, 0x26, + /*8990:*/ 0xbd, 0x81, 0x41, 0xe8, 0xc3, 0x63, 0x67, 0xf3, 0xe5, 0xeb, 0x57, 0xbe, 0x28, 0x83, 0xef, 0x3f, + /*89a0:*/ 0xcc, 0xff, 0x4f, 0xed, 0x19, 0xce, 0xe9, 0xe5, 0x0d, 0x1e, 0x0c, 0xd3, 0x8d, 0xed, 0xa3, 0x47, + /*89b0:*/ 0xb7, 0x1d, 0x63, 0x61, 0xc7, 0xfe, 0x36, 0xfa, 0x05, 0x30, 0xd9, 0x36, 0x04, 0xb8, 0x05, 0x1b, + /*89c0:*/ 0x89, 0xf3, 0xc0, 0x81, 0x07, 0xd5, 0xdf, 0x7f, 0x17, 0x5c, 0xaf, 0x75, 0x35, 0xeb, 0x2b, 0xac, + /*89d0:*/ 0x48, 0xd6, 0x07, 0xe7, 0x72, 0x3e, 0xa6, 0x30, 0x75, 0x77, 0x03, 0x74, 0x31, 0xe5, 0x8b, 0x10, + /*89e0:*/ 0xd0, 0x2a, 0x3c, 0xc7, 0x7d, 0xd4, 0x4e, 0xa5, 0xc9, 0xc7, 0xd1, 0xb8, 0xdb, 0x9d, 0x34, 0xbb, + /*89f0:*/ 0xce, 0x26, 0x16, 0x60, 0x38, 0x95, 0x28, 0x78, 0x60, 0xcb, 0x3f, 0xbd, 0xaa, 0x93, 0xed, 0xb3, + /*8a00:*/ 0x0d, 0xd0, 0x8c, 0xf4, 0x69, 0x24, 0x35, 0x84, 0x60, 0x2b, 0x48, 0x5b, 0x9a, 0x7e, 0xb8, 0xe1, + /*8a10:*/ 0xec, 0x6a, 0x17, 0x17, 0xb9, 0xdc, 0x5d, 0xa9, 0xf2, 0x95, 0x7f, 0xf5, 0xe7, 0x6c, 0x79, 0x93, + /*8a20:*/ 0xab, 0xb2, 0x52, 0x1a, 0x39, 0x5b, 0x3e, 0x49, 0x18, 0x19, 0x3c, 0xe7, 0x7e, 0xf4, 0x95, 0x96, + /*8a30:*/ 0x79, 0x30, 0xc0, 0x3f, 0x7a, 0xde, 0x28, 0xd9, 0x95, 0xe3, 0x69, 0x5b, 0xa5, 0x10, 0xb3, 0xe6, + /*8a40:*/ 0x1c, 0x01, 0xcc, 0xd4, 0xf2, 0x58, 0x76, 0x52, 0x9b, 0x1e, 0xa1, 0x90, 0xb0, 0xa4, 0x8e, 0x3e, + /*8a50:*/ 0x9f, 0x46, 0x9e, 0xa8, 0x75, 0x15, 0xe7, 0xfb, 0xf8, 0x5b, 0xb4, 0x55, 0x92, 0x12, 0x1b, 0x07, + /*8a60:*/ 0xb0, 0xe9, 0x0e, 0xf7, 0xf6, 0x1c, 0x7b, 0x31, 0x35, 0x2c, 0x3f, 0x12, 0x08, 0x1f, 0xe5, 0xf7, + /*8a70:*/ 0x7c, 0x9a, 0x32, 0xa2, 0xa5, 0x5c, 0x49, 0x54, 0x52, 0x0d, 0xca, 0xeb, 0x2c, 0x5e, 0x0d, 0xf2, + /*8a80:*/ 0x54, 0x10, 0x6b, 0x8f, 0x81, 0x1d, 0x56, 0x6e, 0x62, 0x7b, 0xfa, 0xe5, 0x65, 0x85, 0x71, 0xde, + /*8a90:*/ 0x53, 0x5e, 0x8a, 0x39, 0xed, 0x01, 0x3d, 0xe0, 0x37, 0x22, 0x1d, 0xd5, 0x6d, 0x94, 0xee, 0x8b, + /*8aa0:*/ 0x26, 0x8b, 0xe4, 0xf9, 0x2e, 0x14, 0xe8, 0x33, 0x59, 0xd1, 0x91, 0x32, 0x4a, 0x57, 0x4b, 0x8a, + /*8ab0:*/ 0x81, 0xbc, 0x57, 0x87, 0xe4, 0xa2, 0x73, 0x27, 0xd5, 0x25, 0x7b, 0x25, 0x09, 0x58, 0x29, 0xd5, + /*8ac0:*/ 0xb2, 0x7a, 0x3b, 0x59, 0x00, 0xf3, 0xba, 0x38, 0x72, 0xa2, 0xd3, 0x0e, 0x92, 0x0f, 0xbd, 0x9d, + /*8ad0:*/ 0x08, 0xbb, 0xe1, 0xdd, 0x55, 0x7c, 0xd7, 0xaa, 0xf6, 0x23, 0x2f, 0x21, 0xba, 0x7a, 0x4c, 0xe6, + /*8ae0:*/ 0xf6, 0x21, 0x8a, 0x3f, 0x28, 0xfa, 0x5d, 0x78, 0x4a, 0xba, 0x36, 0x1f, 0xdc, 0xeb, 0xa4, 0x25, + /*8af0:*/ 0x4a, 0x5c, 0x19, 0xab, 0xaf, 0x78, 0x25, 0x85, 0x5d, 0x2c, 0x56, 0x91, 0xb2, 0xc2, 0x4c, 0xd1, + /*8b00:*/ 0x12, 0x1b, 0x0f, 0xcf, 0x71, 0x79, 0x3f, 0x39, 0xd4, 0x0c, 0x02, 0xef, 0x4c, 0x77, 0x61, 0xb2, + /*8b10:*/ 0x3e, 0x7e, 0x2e, 0x89, 0x23, 0x88, 0x61, 0xd2, 0xb7, 0x7b, 0xe0, 0xfa, 0x91, 0xa6, 0x7b, 0x20, + /*8b20:*/ 0x26, 0x37, 0xbd, 0xd0, 0xaa, 0x0c, 0x6b, 0x9a, 0x12, 0x3a, 0xf6, 0xff, 0x39, 0x7f, 0x41, 0xee, + /*8b30:*/ 0x8b, 0xd3, 0xc6, 0x0e, 0x0e, 0xc1, 0x73, 0x60, 0x7e, 0xd0, 0x65, 0x4b, 0x47, 0x16, 0x17, 0xcd, + /*8b40:*/ 0x6d, 0x4d, 0x6e, 0x24, 0xdd, 0x1f, 0x24, 0x4c, 0x2a, 0xb1, 0x09, 0xf7, 0x77, 0xb6, 0x18, 0xe2, + /*8b50:*/ 0xa6, 0xd7, 0x2f, 0x41, 0xf8, 0x87, 0xb2, 0x89, 0x86, 0x60, 0xdc, 0x55, 0x0f, 0xbe, 0x68, 0xa9, + /*8b60:*/ 0x3c, 0x3e, 0xc1, 0xd9, 0x2b, 0x92, 0x1e, 0xb1, 0xe9, 0x97, 0xfc, 0xc8, 0xe9, 0x0a, 0xdc, 0xa6, + /*8b70:*/ 0x43, 0xe8, 0xc1, 0xeb, 0x02, 0x54, 0x9f, 0x94, 0xaa, 0xf2, 0xef, 0x72, 0xa3, 0x5b, 0x96, 0xfe, + /*8b80:*/ 0x33, 0xc5, 0x04, 0x0f, 0x37, 0x1c, 0x77, 0x5d, 0x53, 0x7c, 0xa3, 0x42, 0x0c, 0x40, 0x4a, 0x50, + /*8b90:*/ 0xc6, 0x44, 0x1e, 0xdd, 0x1c, 0x27, 0x87, 0x8f, 0x79, 0x8f, 0x2b, 0x7e, 0x2c, 0x2c, 0x08, 0xaf, + /*8ba0:*/ 0xc6, 0xcb, 0x68, 0xbe, 0xc7, 0x41, 0x9e, 0x01, 0xf5, 0x51, 0x04, 0xa2, 0x52, 0xb0, 0x58, 0xa6, + /*8bb0:*/ 0xc3, 0xd9, 0xf8, 0xe5, 0xe5, 0x60, 0x5a, 0x42, 0x1c, 0x92, 0x71, 0x27, 0x2b, 0x1b, 0x7b, 0xad, + /*8bc0:*/ 0x32, 0x24, 0x3e, 0x75, 0xa2, 0x64, 0xaa, 0x8e, 0xe1, 0x96, 0x6e, 0x80, 0xf7, 0x6f, 0xdb, 0xce, + /*8bd0:*/ 0xa8, 0xd5, 0x4a, 0x8b, 0xd4, 0x29, 0x10, 0x03, 0x17, 0x38, 0x5f, 0xdc, 0xca, 0xd7, 0xeb, 0xac, + /*8be0:*/ 0x45, 0x3d, 0xb8, 0x1b, 0x20, 0xae, 0x91, 0x6b, 0x63, 0xc7, 0xe4, 0x69, 0x94, 0xb9, 0x41, 0xe8, + /*8bf0:*/ 0xdc, 0x67, 0xb8, 0x0a, 0xfa, 0x72, 0x4e, 0x23, 0x12, 0xd9, 0xb1, 0x13, 0xf7, 0x53, 0xf6, 0x2b, + /*8c00:*/ 0x89, 0x06, 0x80, 0x67, 0x02, 0xc5, 0x4b, 0xbd, 0xaf, 0x60, 0x73, 0x90, 0x00, 0xd3, 0xfc, 0x9e, + /*8c10:*/ 0x59, 0x76, 0xaf, 0x70, 0x44, 0xd9, 0xae, 0x1a, 0x6b, 0xa7, 0x56, 0xad, 0x1b, 0xc2, 0xe6, 0xd5, + /*8c20:*/ 0xbc, 0x6f, 0x4a, 0xd9, 0x59, 0x11, 0xc1, 0xc5, 0xaf, 0x36, 0x26, 0x93, 0xd6, 0x20, 0x72, 0x61, + /*8c30:*/ 0x8e, 0xb6, 0x84, 0xab, 0x54, 0xcb, 0x7c, 0xf6, 0x84, 0x3b, 0x09, 0x3a, 0x46, 0x2f, 0xc6, 0x95, + /*8c40:*/ 0x07, 0x5f, 0xda, 0xf6, 0x8b, 0x30, 0x6d, 0xd9, 0xbb, 0x6f, 0x13, 0xea, 0x81, 0xa3, 0xd5, 0x72, + /*8c50:*/ 0x46, 0x43, 0x53, 0xe5, 0xbd, 0x02, 0x9c, 0x1d, 0x29, 0x94, 0x97, 0x01, 0xce, 0x6a, 0x76, 0x7b, + /*8c60:*/ 0xc3, 0xa5, 0x2f, 0xcf, 0xe4, 0x81, 0x32, 0xb5, 0x9f, 0xa1, 0x98, 0xea, 0xab, 0xe9, 0x6c, 0x8a, + /*8c70:*/ 0x37, 0x4e, 0x9e, 0x10, 0x1b, 0x87, 0xbd, 0x06, 0x77, 0xd5, 0x79, 0x79, 0xe3, 0x6d, 0x4e, 0x96, + /*8c80:*/ 0x51, 0x56, 0xd6, 0x18, 0x93, 0xe8, 0x69, 0xb4, 0x50, 0xf6, 0x61, 0xfc, 0x67, 0xdf, 0x82, 0xd4, + /*8c90:*/ 0x99, 0x06, 0x16, 0x97, 0x95, 0xd6, 0x43, 0xd6, 0x31, 0x4f, 0xb7, 0xeb, 0x2f, 0x3a, 0x3b, 0x1a, + /*8ca0:*/ 0xd9, 0xe2, 0xa1, 0xca, 0xbb, 0x76, 0x48, 0xe3, 0x47, 0xcc, 0xbe, 0x67, 0x24, 0xa2, 0xd0, 0x9a, + /*8cb0:*/ 0x7c, 0x30, 0x4f, 0x1b, 0x85, 0x08, 0xc9, 0xec, 0x98, 0x65, 0xb0, 0x93, 0x10, 0x1c, 0xca, 0x83, + /*8cc0:*/ 0x2d, 0x00, 0x68, 0x96, 0x39, 0x3f, 0x3f, 0x7c, 0x42, 0x6b, 0x6f, 0x41, 0x3f, 0xf3, 0x29, 0x66, + /*8cd0:*/ 0x98, 0xfb, 0x14, 0x3c, 0x8b, 0xd9, 0x5f, 0xdd, 0xe7, 0x8d, 0xbd, 0x40, 0x5a, 0x12, 0x41, 0x0c, + /*8ce0:*/ 0xd8, 0x02, 0x89, 0xc1, 0x65, 0x1b, 0xb2, 0x79, 0x6b, 0x98, 0x50, 0xff, 0xc8, 0xf0, 0x67, 0x66, + /*8cf0:*/ 0x51, 0xb8, 0x05, 0xc9, 0x1a, 0xcc, 0x7e, 0x28, 0x22, 0xc7, 0x11, 0xf6, 0xfc, 0x71, 0xeb, 0x97, + /*8d00:*/ 0x4b, 0x51, 0x53, 0x25, 0x88, 0xc9, 0x5e, 0x11, 0x84, 0x79, 0x4e, 0xf2, 0x02, 0x2f, 0xa6, 0x7e, + /*8d10:*/ 0x82, 0x65, 0x34, 0xfa, 0xd6, 0x33, 0xfe, 0xaa, 0x95, 0xe5, 0xb3, 0xd1, 0x5e, 0xf6, 0xdf, 0x96, + /*8d20:*/ 0x20, 0x29, 0xd6, 0xd4, 0xc1, 0x5c, 0x53, 0x2b, 0x4c, 0x32, 0xf4, 0xae, 0xfc, 0x69, 0x53, 0xfc, + /*8d30:*/ 0x2a, 0x7e, 0x83, 0xfb, 0x8f, 0x35, 0xe2, 0xd9, 0x5c, 0x12, 0x22, 0x5c, 0xc0, 0x75, 0x8a, 0x23, + /*8d40:*/ 0x8d, 0x63, 0xc8, 0xa9, 0x69, 0x40, 0x9c, 0x29, 0x22, 0xe9, 0x6a, 0x2b, 0x0c, 0xb7, 0xc8, 0x79, + /*8d50:*/ 0xb6, 0xcd, 0xaf, 0xac, 0x91, 0x96, 0x78, 0xb6, 0x29, 0x0b, 0xbd, 0x76, 0xd5, 0x2e, 0xcc, 0x39, + /*8d60:*/ 0x3b, 0xcc, 0xb1, 0xff, 0x91, 0xb9, 0xab, 0xcb, 0x34, 0xfb, 0xcf, 0xaf, 0xe3, 0xde, 0xb2, 0x37, + /*8d70:*/ 0xb5, 0x79, 0x47, 0xb3, 0xac, 0x9b, 0x20, 0xc4, 0xda, 0x7d, 0x6f, 0x49, 0x6f, 0x8b, 0xe3, 0x4b, + /*8d80:*/ 0x31, 0x23, 0x28, 0x63, 0x08, 0x59, 0x23, 0xf1, 0xa5, 0xea, 0x64, 0x08, 0x88, 0x34, 0xf3, 0x39, + /*8d90:*/ 0x62, 0xe8, 0x7a, 0x18, 0xed, 0x25, 0xa4, 0x68, 0x3d, 0xa6, 0x64, 0x0d, 0xdc, 0x99, 0x05, 0xc9, + /*8da0:*/ 0xb0, 0x9e, 0xc3, 0xe3, 0xa2, 0x9e, 0xc7, 0x92, 0x7a, 0xe1, 0xdd, 0x0e, 0x9d, 0x71, 0x6c, 0xf5, + /*8db0:*/ 0x73, 0xa5, 0xf9, 0xdf, 0x94, 0x49, 0xa3, 0x23, 0x73, 0xe0, 0x51, 0x6d, 0x0f, 0x9e, 0x1a, 0x87, + /*8dc0:*/ 0x3a, 0xef, 0xa4, 0x63, 0x13, 0x79, 0x7a, 0x2d, 0x0f, 0x7c, 0x88, 0x8b, 0xb1, 0x65, 0xbf, 0x0a, + /*8dd0:*/ 0xb5, 0x21, 0xc4, 0x7c, 0x65, 0xe3, 0x52, 0x1d, 0xa2, 0xf6, 0x1d, 0x93, 0x84, 0x86, 0x7a, 0xe8, + /*8de0:*/ 0x5f, 0x72, 0x4b, 0x85, 0x48, 0x8f, 0x23, 0x93, 0x7f, 0xdd, 0xef, 0x17, 0x46, 0x5d, 0xbe, 0xc0, + /*8df0:*/ 0x67, 0xbd, 0xe4, 0xd7, 0xc9, 0xca, 0x2e, 0xc6, 0x8b, 0xc3, 0x82, 0x28, 0x0f, 0xa6, 0x22, 0x9c, + /*8e00:*/ 0xaf, 0x0c, 0xa2, 0x5f, 0xe6, 0x91, 0x72, 0x6b, 0x43, 0x44, 0xd5, 0x8c, 0xd5, 0x55, 0xc2, 0x6a, + /*8e10:*/ 0x95, 0xe0, 0x42, 0x22, 0x41, 0xe7, 0xd5, 0x2a, 0xfa, 0xf7, 0xaa, 0x74, 0x29, 0x4f, 0x87, 0x2c, + /*8e20:*/ 0x38, 0x6a, 0x4a, 0x07, 0x38, 0xfd, 0x8c, 0xe2, 0x8d, 0xd8, 0x2b, 0x2e, 0xe7, 0x2b, 0xbc, 0x02, + /*8e30:*/ 0x22, 0xa1, 0x26, 0xce, 0x57, 0xab, 0x9b, 0x20, 0x02, 0x43, 0xaf, 0xb5, 0x73, 0x95, 0xc1, 0x5a, + /*8e40:*/ 0xe2, 0xe3, 0x7f, 0x60, 0x04, 0xab, 0xa3, 0x21, 0xf8, 0x18, 0xdb, 0x6b, 0x01, 0xdf, 0x6a, 0xac, + /*8e50:*/ 0xdb, 0x37, 0xa4, 0xdd, 0x4b, 0x0e, 0xfa, 0x39, 0xed, 0x64, 0xfb, 0xfc, 0x98, 0xe7, 0x71, 0x02, + /*8e60:*/ 0xdd, 0xbb, 0xa5, 0x62, 0x7e, 0x18, 0x16, 0xe1, 0x6e, 0xbd, 0x1d, 0xb3, 0xc5, 0x11, 0xd2, 0xdb, + /*8e70:*/ 0x20, 0x1f, 0x3a, 0x84, 0xda, 0x08, 0x7d, 0x58, 0x50, 0xc3, 0x3c, 0x5c, 0x7c, 0xc9, 0xb8, 0x78, + /*8e80:*/ 0x03, 0x57, 0x93, 0x71, 0x71, 0x28, 0xaf, 0x84, 0xd6, 0x89, 0xa2, 0xd4, 0x01, 0xcb, 0x26, 0x1b, + /*8e90:*/ 0x0a, 0x35, 0x38, 0xf8, 0x77, 0xb1, 0x09, 0x03, 0xb7, 0x1a, 0x0d, 0xb2, 0x82, 0x90, 0x22, 0x05, + /*8ea0:*/ 0x19, 0x63, 0x66, 0x58, 0x4a, 0xf9, 0x2f, 0x2f, 0xe2, 0xbb, 0x2b, 0x31, 0xca, 0xdc, 0x96, 0x47, + /*8eb0:*/ 0x88, 0x7d, 0x62, 0x75, 0xe6, 0x96, 0xf3, 0xa2, 0x1e, 0x62, 0x59, 0xff, 0x24, 0xbe, 0x2f, 0x8f, + /*8ec0:*/ 0xdf, 0xd5, 0x72, 0xfc, 0x0f, 0xc8, 0x10, 0x48, 0xa2, 0x90, 0xe0, 0x1a, 0xa2, 0x0c, 0x80, 0x80, + /*8ed0:*/ 0xda, 0xb8, 0x2f, 0x8c, 0xc4, 0x07, 0x49, 0x7a, 0x29, 0xf5, 0xbb, 0x02, 0x49, 0xc0, 0xa5, 0x5c, + /*8ee0:*/ 0x54, 0x6f, 0x05, 0xb6, 0x48, 0x1c, 0x41, 0xc9, 0xa2, 0x19, 0xab, 0xc4, 0x39, 0x6d, 0xf7, 0x7b, + /*8ef0:*/ 0x22, 0xc0, 0xbd, 0xbf, 0xd7, 0x88, 0x46, 0xe4, 0x18, 0x42, 0x06, 0xea, 0x45, 0xcb, 0x6a, 0xe1, + /*8f00:*/ 0x23, 0xe6, 0x93, 0x32, 0x7a, 0x56, 0x90, 0x80, 0xa9, 0xb1, 0xe3, 0x47, 0x6f, 0x71, 0x17, 0xb2, + /*8f10:*/ 0x6f, 0x5b, 0x23, 0x7a, 0x22, 0xea, 0xeb, 0xd1, 0x52, 0xed, 0x41, 0x71, 0xf5, 0x16, 0x98, 0x3a, + /*8f20:*/ 0x57, 0x79, 0x86, 0x99, 0xbf, 0xbe, 0xd2, 0x6b, 0x9d, 0x2a, 0x14, 0x61, 0x03, 0x5e, 0x4b, 0x5f, + /*8f30:*/ 0x02, 0x59, 0x22, 0x37, 0x13, 0x79, 0x7d, 0x47, 0xca, 0xc4, 0xe9, 0xa9, 0x0f, 0x33, 0x89, 0x72, + /*8f40:*/ 0x86, 0x3a, 0x79, 0x68, 0x17, 0x63, 0x6a, 0x0d, 0x50, 0x59, 0xd3, 0xb8, 0x3f, 0x32, 0x84, 0x6a, + /*8f50:*/ 0x7c, 0x11, 0x65, 0xb1, 0x34, 0xb6, 0x6a, 0x9f, 0x59, 0x28, 0xdd, 0xe8, 0xef, 0x10, 0x2a, 0x65, + /*8f60:*/ 0xde, 0x73, 0x8e, 0x15, 0x64, 0xcf, 0x99, 0xa9, 0x01, 0xdb, 0x79, 0x12, 0x99, 0x9b, 0x66, 0x0c, + /*8f70:*/ 0x5b, 0x2f, 0x31, 0xd4, 0xdd, 0x74, 0x8b, 0x64, 0x3e, 0x7e, 0xee, 0x85, 0xac, 0xcb, 0x94, 0x8a, + /*8f80:*/ 0xfb, 0xc8, 0x87, 0xce, 0xeb, 0x18, 0x23, 0xd4, 0x13, 0x4c, 0x22, 0xeb, 0x2d, 0x71, 0x7e, 0xd6, + /*8f90:*/ 0x4f, 0x06, 0x85, 0xf2, 0xf7, 0x4d, 0x39, 0xc3, 0x11, 0x33, 0x2a, 0x9e, 0xf8, 0x3c, 0xde, 0xef, + /*8fa0:*/ 0x06, 0xbe, 0xcd, 0x77, 0x21, 0xeb, 0xb0, 0xd6, 0xcf, 0x41, 0xd2, 0xd9, 0xb5, 0x8c, 0xa9, 0x51, + /*8fb0:*/ 0xae, 0x17, 0xe0, 0xb0, 0x60, 0x3f, 0x62, 0x82, 0x71, 0x28, 0x7e, 0xb9, 0x6d, 0x17, 0x26, 0xde, + /*8fc0:*/ 0xb0, 0x98, 0xeb, 0x35, 0x28, 0xb9, 0x1e, 0xd5, 0x82, 0xf7, 0xaf, 0xa2, 0x3b, 0xb7, 0xbe, 0xfd, + /*8fd0:*/ 0x4d, 0x68, 0x6a, 0x20, 0x61, 0x50, 0x47, 0xb2, 0x4a, 0x42, 0x7a, 0xfa, 0x29, 0xcc, 0x9e, 0x2f, + /*8fe0:*/ 0xd9, 0x50, 0x5b, 0xac, 0x1d, 0x02, 0x90, 0xd9, 0xe5, 0xe8, 0x51, 0x12, 0xe8, 0x3b, 0xb9, 0x06, + /*8ff0:*/ 0x93, 0xb5, 0x3c, 0xa3, 0xdf, 0x96, 0xd1, 0x07, 0xb5, 0xf7, 0x6d, 0xcd, 0x6e, 0x2c, 0xd3, 0x89, + /*9000:*/ 0xcd, 0x97, 0xfb, 0x6a, 0x85, 0xcf, 0x10, 0x46, 0xdc, 0xc6, 0xde, 0x2d, 0x28, 0x1a, 0xe7, 0x1a, + /*9010:*/ 0x6a, 0x19, 0x84, 0x67, 0x2d, 0x47, 0xb2, 0x05, 0xca, 0xe2, 0x74, 0xf6, 0xbc, 0x62, 0x15, 0x74, + /*9020:*/ 0x19, 0x15, 0x04, 0x73, 0xd1, 0x52, 0xe6, 0x57, 0xbf, 0x05, 0x0b, 0xe4, 0x38, 0x0c, 0x7c, 0x7b, + /*9030:*/ 0x87, 0x7c, 0xa0, 0xd3, 0x14, 0x94, 0xcc, 0x4d, 0x73, 0x12, 0xac, 0x5e, 0x7d, 0x74, 0xb3, 0x43, + /*9040:*/ 0xe1, 0x88, 0xca, 0x1d, 0x3d, 0x1c, 0xa1, 0x11, 0x83, 0xea, 0xf0, 0x72, 0x29, 0xda, 0xbe, 0xd3, + /*9050:*/ 0x98, 0xd2, 0xd8, 0xd6, 0x71, 0x9c, 0x7b, 0x44, 0xb8, 0x3c, 0xf6, 0x04, 0xc5, 0x32, 0xb8, 0x4e, + /*9060:*/ 0xb9, 0xcd, 0x59, 0x36, 0xe8, 0xd1, 0x63, 0x70, 0xd6, 0x5d, 0x0d, 0x49, 0xc8, 0x0e, 0xb6, 0x28, + /*9070:*/ 0x68, 0x67, 0xe8, 0x0c, 0x8c, 0x2f, 0x74, 0xfd, 0x56, 0x1d, 0x65, 0xaf, 0x33, 0xba, 0xf4, 0xe0, + /*9080:*/ 0x8c, 0xff, 0x5e, 0x96, 0x4c, 0xa9, 0x25, 0xde, 0x03, 0x8d, 0x38, 0xc6, 0xba, 0x40, 0xf8, 0xdf, + /*9090:*/ 0x93, 0xb4, 0x50, 0x58, 0x42, 0x73, 0x91, 0xad, 0xb4, 0x6f, 0x25, 0x0b, 0x7f, 0x5a, 0xd0, 0x69, + /*90a0:*/ 0x0e, 0x44, 0xbc, 0x27, 0xcc, 0x14, 0x07, 0xeb, 0x11, 0x20, 0x05, 0x3b, 0xf0, 0x73, 0x51, 0xc2, + /*90b0:*/ 0x3e, 0xbb, 0x85, 0xc9, 0xd7, 0xea, 0xd0, 0x0e, 0x25, 0xa1, 0x41, 0xe1, 0x70, 0xbd, 0xae, 0x81, + /*90c0:*/ 0xcc, 0x2b, 0x19, 0x39, 0x3b, 0xb3, 0x65, 0x2b, 0xd7, 0x9d, 0x94, 0xb3, 0xe1, 0xe7, 0xa5, 0xde, + /*90d0:*/ 0xd5, 0xe8, 0xb7, 0xc3, 0x4d, 0xbb, 0x32, 0x71, 0xa3, 0xfc, 0xb0, 0x6c, 0x8e, 0x20, 0xe7, 0xeb, + /*90e0:*/ 0x88, 0xc8, 0xa4, 0x76, 0xe8, 0xd5, 0xb1, 0x24, 0xbb, 0xa4, 0x35, 0xc8, 0x74, 0xb5, 0x3b, 0xba, + /*90f0:*/ 0x08, 0xbc, 0xbd, 0xcd, 0xe6, 0x0e, 0x71, 0x32, 0x0e, 0x88, 0x52, 0xfa, 0x45, 0xe7, 0x02, 0x3b, + /*9100:*/ 0x11, 0x5d, 0x8c, 0x07, 0x14, 0xc1, 0x68, 0x05, 0xc2, 0x4f, 0x03, 0x1c, 0x17, 0xa6, 0x38, 0xa1, + /*9110:*/ 0x9d, 0x07, 0xb0, 0xb3, 0x00, 0xab, 0x98, 0x89, 0x79, 0xd3, 0x8b, 0xb2, 0x93, 0x6b, 0x30, 0xf4, + /*9120:*/ 0x0c, 0xbd, 0xe3, 0x79, 0x3d, 0x1e, 0x3a, 0x75, 0xf8, 0x67, 0x3f, 0xd9, 0x20, 0x07, 0x22, 0xe6, + /*9130:*/ 0xc1, 0x4f, 0x85, 0x56, 0x68, 0xaa, 0xd1, 0x70, 0xd9, 0x3c, 0x24, 0xee, 0xdf, 0xcc, 0x1c, 0xda, + /*9140:*/ 0x76, 0xf5, 0x18, 0xd1, 0x53, 0x43, 0x3c, 0x1a, 0x51, 0xa4, 0x34, 0xce, 0xde, 0x4d, 0xfb, 0xee, + /*9150:*/ 0x8e, 0xca, 0xb7, 0x36, 0xae, 0x68, 0xcc, 0x22, 0x8b, 0xec, 0x66, 0xba, 0xcd, 0x93, 0x41, 0x75, + /*9160:*/ 0xc5, 0xba, 0x92, 0x23, 0xde, 0x1b, 0xc4, 0xc8, 0x75, 0xcb, 0xcc, 0x14, 0x2b, 0x99, 0x06, 0x43, + /*9170:*/ 0xd1, 0x9d, 0xae, 0xd5, 0x54, 0xda, 0x5f, 0x6f, 0x9c, 0x96, 0x52, 0x1c, 0xca, 0xf6, 0xab, 0x58, + /*9180:*/ 0xe4, 0xbd, 0x83, 0x35, 0xc6, 0x32, 0xae, 0xd7, 0x54, 0x59, 0x53, 0xb3, 0x33, 0xe6, 0xd9, 0x7c, + /*9190:*/ 0x72, 0xb5, 0xcb, 0x02, 0x92, 0xd8, 0xf2, 0x68, 0xd1, 0xdb, 0x93, 0xd8, 0x2e, 0xc9, 0xda, 0x87, + /*91a0:*/ 0x50, 0xf2, 0x6c, 0xf9, 0x58, 0x2e, 0x6a, 0x6a, 0xfc, 0x08, 0x56, 0x9c, 0x6e, 0xe1, 0xdf, 0xe2, + /*91b0:*/ 0x90, 0x38, 0xbe, 0xb9, 0xbc, 0x2e, 0xb9, 0x2c, 0xcc, 0xd9, 0x0d, 0x25, 0xe2, 0x37, 0xf4, 0x28, + /*91c0:*/ 0xe1, 0xc1, 0xf2, 0xc9, 0x68, 0xd3, 0xff, 0xa3, 0xf0, 0x28, 0x67, 0x48, 0xfb, 0x91, 0xfe, 0x46, + /*91d0:*/ 0xc4, 0xbf, 0x60, 0xe7, 0x97, 0x37, 0x3f, 0xd2, 0x7e, 0xdf, 0x3d, 0x27, 0x6d, 0x3e, 0x69, 0xa5, + /*91e0:*/ 0x7f, 0x2f, 0x57, 0xeb, 0x82, 0x7e, 0x94, 0x85, 0x69, 0xb2, 0x9d, 0xa6, 0x66, 0x16, 0xa7, 0xc2, + /*91f0:*/ 0x87, 0xe8, 0x72, 0x7c, 0x99, 0xd4, 0xb1, 0x43, 0xa8, 0x06, 0x32, 0x32, 0x1e, 0xb2, 0x6e, 0x2f, + /*9200:*/ 0xd0, 0xca, 0xe7, 0x10, 0xd5, 0xc2, 0xe5, 0x6b, 0x91, 0xac, 0xb4, 0x79, 0x6f, 0x23, 0xcc, 0xfc, + /*9210:*/ 0x09, 0xe4, 0x62, 0x5e, 0xb6, 0x58, 0xd1, 0x53, 0xd4, 0x10, 0x0b, 0x01, 0xf5, 0x26, 0x5f, 0x5a, + /*9220:*/ 0xcf, 0xf6, 0x44, 0x93, 0xad, 0xed, 0x64, 0xd2, 0xfd, 0x2c, 0x6a, 0xfe, 0x3c, 0x37, 0x44, 0xf0, + /*9230:*/ 0x0d, 0x21, 0xd3, 0x7b, 0x8d, 0x8a, 0xfe, 0x0c, 0xf9, 0x5a, 0x0a, 0x86, 0xed, 0xfb, 0x5b, 0x6b, + /*9240:*/ 0xbe, 0x39, 0xb9, 0x85, 0xf8, 0x76, 0xde, 0x5f, 0xd8, 0x6e, 0x95, 0xb6, 0xd5, 0x4b, 0x40, 0x32, + /*9250:*/ 0x4a, 0xf1, 0x1c, 0xa8, 0x48, 0xe2, 0xf3, 0x10, 0xa6, 0x51, 0xee, 0x2a, 0xbb, 0x65, 0xaa, 0xe6, + /*9260:*/ 0x4b, 0x9c, 0x5f, 0x30, 0xcc, 0xbe, 0xae, 0xe3, 0x0f, 0xbe, 0x34, 0x44, 0xf5, 0x3c, 0xb2, 0x6d, + /*9270:*/ 0xd5, 0x2f, 0x3b, 0x59, 0xc8, 0x7f, 0x48, 0xfa, 0x53, 0x6f, 0x85, 0x7b, 0xaa, 0x6d, 0xf5, 0x2c, + /*9280:*/ 0x0f, 0x23, 0x8a, 0x25, 0xee, 0x4f, 0x08, 0x00, 0xc9, 0x1d, 0x53, 0xdb, 0xad, 0x37, 0x35, 0x41, + /*9290:*/ 0x6c, 0x9f, 0xe2, 0x79, 0x6a, 0x21, 0x04, 0x05, 0xe6, 0x6f, 0x74, 0x9e, 0x9a, 0x1c, 0x33, 0xd6, + /*92a0:*/ 0x44, 0x5c, 0x09, 0x40, 0xcb, 0x0e, 0xe4, 0x27, 0xa3, 0xf8, 0xf7, 0xd4, 0xed, 0x09, 0x33, 0x71, + /*92b0:*/ 0x5d, 0x5c, 0x95, 0x25, 0x67, 0x0a, 0x5c, 0x2e, 0xb6, 0xe7, 0xb0, 0x10, 0x9c, 0x19, 0xb4, 0x39, + /*92c0:*/ 0x99, 0x11, 0xbd, 0x82, 0x87, 0x28, 0x6d, 0x75, 0x9d, 0x4e, 0x66, 0xbb, 0x1f, 0x01, 0x6b, 0x33, + /*92d0:*/ 0xf5, 0x01, 0x20, 0x9f, 0x69, 0x09, 0x99, 0x29, 0xda, 0x12, 0x5a, 0xa5, 0x47, 0xe2, 0x4d, 0x3c, + /*92e0:*/ 0x39, 0x54, 0x5e, 0x69, 0xa4, 0x54, 0x14, 0x1f, 0x3f, 0x75, 0xfc, 0x25, 0xa3, 0x3d, 0xc1, 0x65, + /*92f0:*/ 0xc6, 0xd0, 0xdb, 0x44, 0xbe, 0xe9, 0x6d, 0x3d, 0x00, 0x81, 0x3b, 0xed, 0xb5, 0xfd, 0xa6, 0x19, + /*9300:*/ 0x63, 0xa2, 0xf0, 0xd8, 0x86, 0xeb, 0x86, 0x20, 0xe2, 0xaa, 0x98, 0xf9, 0x21, 0x51, 0x40, 0x63, + /*9310:*/ 0x84, 0x80, 0x6d, 0x18, 0x84, 0x3c, 0x91, 0x6a, 0x93, 0x85, 0x25, 0x5b, 0x5a, 0x12, 0x61, 0xf3, + /*9320:*/ 0x20, 0x02, 0x6e, 0x52, 0x08, 0xcf, 0x9a, 0xda, 0xd0, 0xbc, 0xd5, 0x70, 0xca, 0x73, 0x28, 0xcb, + /*9330:*/ 0x6c, 0x97, 0xc1, 0xb0, 0x0e, 0xb7, 0xa2, 0xd7, 0xb8, 0xb2, 0xe3, 0x98, 0xf7, 0x9e, 0x60, 0xc6, + /*9340:*/ 0x54, 0x2d, 0x04, 0x98, 0x6f, 0x29, 0xbe, 0xdc, 0x67, 0xad, 0xfd, 0x2d, 0xf5, 0x0e, 0x11, 0xfb, + /*9350:*/ 0x00, 0xac, 0xef, 0x9d, 0x6c, 0x12, 0x26, 0xf4, 0xf0, 0xaf, 0x05, 0xe4, 0xbf, 0x07, 0x50, 0x17, + /*9360:*/ 0x9e, 0xf9, 0xfe, 0x37, 0x35, 0xa2, 0xb5, 0xff, 0x98, 0xd7, 0x05, 0xa2, 0xb2, 0xa7, 0x5c, 0x2a, + /*9370:*/ 0x3f, 0x67, 0x01, 0x06, 0xa9, 0x3e, 0xdc, 0x76, 0x97, 0xfb, 0x36, 0x72, 0x30, 0xb7, 0xe4, 0x30, + /*9380:*/ 0x51, 0xe3, 0xe7, 0xeb, 0xcc, 0xd3, 0x3d, 0x6f, 0x9e, 0x7e, 0x00, 0xc6, 0x7c, 0x14, 0xb0, 0xae, + /*9390:*/ 0x79, 0x1c, 0x0b, 0x55, 0xcc, 0x61, 0xaf, 0xfc, 0x96, 0xcf, 0xcc, 0xe1, 0x99, 0x4b, 0x85, 0xe7, + /*93a0:*/ 0xa8, 0x9b, 0x40, 0xa9, 0xf8, 0xe8, 0x68, 0xe7, 0x9d, 0xde, 0xf4, 0xdc, 0x93, 0x57, 0x0a, 0x54, + /*93b0:*/ 0x5e, 0x4a, 0x1c, 0xd7, 0x2f, 0xc4, 0x5d, 0x37, 0x98, 0xbc, 0x63, 0xf6, 0x5c, 0x9a, 0xc0, 0xf4, + /*93c0:*/ 0x5e, 0x07, 0xc5, 0xab, 0xe5, 0x51, 0xf1, 0xe9, 0x8d, 0xcd, 0x48, 0x54, 0xce, 0x87, 0x69, 0x51, + /*93d0:*/ 0x10, 0xb9, 0xe6, 0x47, 0x8c, 0x2f, 0x2f, 0xe1, 0x9b, 0xcd, 0x05, 0x55, 0x9c, 0xa7, 0x0f, 0x18, + /*93e0:*/ 0x76, 0xee, 0xc3, 0x7e, 0xfa, 0x69, 0xa3, 0x7f, 0xc2, 0xa9, 0xff, 0xaa, 0x7a, 0x2d, 0x13, 0xd1, + /*93f0:*/ 0xde, 0x8b, 0x1c, 0xd8, 0xe6, 0x6f, 0x12, 0xfc, 0x4c, 0xec, 0x79, 0x02, 0x17, 0x6f, 0xc3, 0xd1, + /*9400:*/ 0xb5, 0x6e, 0xff, 0x06, 0xf1, 0x06, 0xd6, 0xbe, 0xbf, 0x02, 0x04, 0x72, 0x48, 0xed, 0x80, 0x58, + /*9410:*/ 0xf0, 0x5f, 0x31, 0xcf, 0x4d, 0xec, 0xe0, 0x1b, 0x6d, 0x33, 0x69, 0xfd, 0x2f, 0x62, 0xb8, 0x93, + /*9420:*/ 0xac, 0x31, 0x56, 0x8e, 0x61, 0xde, 0x88, 0xea, 0x3f, 0xc4, 0x6b, 0xff, 0xcc, 0x6f, 0x10, 0x26, + /*9430:*/ 0x85, 0x04, 0x98, 0xe4, 0x3a, 0xda, 0x18, 0xa2, 0x99, 0x59, 0x73, 0x58, 0x91, 0x7c, 0x22, 0x7e, + /*9440:*/ 0x16, 0xd4, 0xd3, 0x20, 0x4c, 0x82, 0x21, 0x81, 0x43, 0x83, 0x36, 0x73, 0x04, 0x0e, 0x07, 0x79, + /*9450:*/ 0x81, 0xd7, 0x8e, 0x44, 0x50, 0x9f, 0x33, 0x68, 0x0c, 0x67, 0x18, 0xd3, 0xba, 0xbe, 0xc9, 0xb7, + /*9460:*/ 0xed, 0x8f, 0xb0, 0xdc, 0xc6, 0xab, 0x17, 0x84, 0xa0, 0x79, 0x78, 0xf9, 0x87, 0x8a, 0x21, 0xdf, + /*9470:*/ 0xe7, 0x4d, 0xfa, 0x3b, 0xd8, 0xf4, 0x00, 0x85, 0x00, 0x0d, 0x8e, 0x68, 0x7a, 0x5a, 0x1a, 0x6a, + /*9480:*/ 0x3a, 0x6d, 0x36, 0x12, 0xf4, 0xd4, 0x09, 0xf9, 0xc5, 0x50, 0x1c, 0xe6, 0xe0, 0x58, 0x25, 0xfa, + /*9490:*/ 0xbc, 0xea, 0xfe, 0x6e, 0x1f, 0x1a, 0x16, 0x8f, 0x2f, 0x0f, 0xb2, 0xf3, 0x85, 0xe0, 0x11, 0x9e, + /*94a0:*/ 0x90, 0xf1, 0xab, 0x01, 0xea, 0x9e, 0x03, 0xbe, 0xaa, 0x73, 0x8c, 0x96, 0xf2, 0x1c, 0x74, 0x46, + /*94b0:*/ 0xdd, 0x4c, 0xff, 0x63, 0x18, 0x4b, 0xee, 0x7d, 0xed, 0xff, 0x16, 0xc8, 0x8d, 0xac, 0x0e, 0xe1, + /*94c0:*/ 0x3b, 0x21, 0x1a, 0x5b, 0x69, 0x16, 0xb9, 0xb7, 0xbd, 0x97, 0x02, 0xb6, 0x29, 0xba, 0xd7, 0x0c, + /*94d0:*/ 0xb0, 0x33, 0xba, 0x5a, 0x0d, 0xd2, 0xe6, 0x32, 0x70, 0xd9, 0x71, 0xa3, 0x59, 0xce, 0xe0, 0xac, + /*94e0:*/ 0x9f, 0x3d, 0xd3, 0xba, 0x2e, 0x3d, 0x70, 0x1c, 0x19, 0x9e, 0xa5, 0x34, 0xef, 0xf7, 0x93, 0xcd, + /*94f0:*/ 0x6f, 0xd1, 0xfd, 0x72, 0x76, 0x3a, 0x33, 0x5c, 0x54, 0xd9, 0x85, 0xbf, 0x72, 0xfd, 0x13, 0xf0, + /*9500:*/ 0x5d, 0x37, 0x35, 0x42, 0x1c, 0xd2, 0x41, 0x66, 0x1d, 0xcb, 0xf9, 0x76, 0xd9, 0x26, 0x3b, 0xb7, + /*9510:*/ 0xe7, 0xf6, 0x32, 0xa9, 0x26, 0xba, 0x25, 0x9c, 0x35, 0xa5, 0x80, 0x11, 0x3d, 0x0d, 0x43, 0x80, + /*9520:*/ 0xd1, 0x90, 0xba, 0xe1, 0xc8, 0x1c, 0xe4, 0x83, 0x08, 0xaa, 0xaf, 0x66, 0x8e, 0x33, 0x9a, 0x4a, + /*9530:*/ 0xdd, 0x79, 0xf6, 0xa7, 0xfa, 0x15, 0x59, 0x61, 0xf6, 0x35, 0xd8, 0x0b, 0xe4, 0x86, 0xbb, 0x74, + /*9540:*/ 0xfa, 0x6b, 0xa5, 0x4e, 0xf8, 0x41, 0xa7, 0xb4, 0x37, 0x82, 0x8e, 0x5b, 0x1c, 0x71, 0xe2, 0xe1, + /*9550:*/ 0x57, 0xa8, 0xa1, 0xc3, 0x18, 0x6f, 0xcb, 0x31, 0x2e, 0x28, 0x9d, 0x09, 0x33, 0x67, 0x9b, 0xaf, + /*9560:*/ 0x6f, 0x07, 0x18, 0x49, 0xd1, 0x78, 0x5d, 0x87, 0xdf, 0xb7, 0x62, 0x14, 0x00, 0x7e, 0xc7, 0xe8, + /*9570:*/ 0x7f, 0xbc, 0x6a, 0xd4, 0x4c, 0x91, 0xc6, 0xde, 0xd3, 0x89, 0xc8, 0xbf, 0x90, 0xda, 0x84, 0x0f, + /*9580:*/ 0x56, 0xdd, 0x95, 0xae, 0x92, 0x78, 0xf3, 0x93, 0xf0, 0x6c, 0x9e, 0xab, 0xf5, 0xb7, 0xb5, 0x99, + /*9590:*/ 0xf6, 0xb3, 0x94, 0x57, 0xd1, 0x96, 0x91, 0x60, 0x31, 0x0d, 0xa9, 0xf4, 0x67, 0x62, 0xa4, 0xd5, + /*95a0:*/ 0xf1, 0x5e, 0x15, 0xd8, 0xba, 0x27, 0x4c, 0x2d, 0x1f, 0x92, 0x0e, 0x8a, 0x51, 0x74, 0xdd, 0x8f, + /*95b0:*/ 0x27, 0x89, 0x9b, 0xba, 0x1b, 0x1a, 0x01, 0x1e, 0x9a, 0xb5, 0x77, 0x72, 0x8e, 0xde, 0x73, 0xbb, + /*95c0:*/ 0xe9, 0x6a, 0xa1, 0xeb, 0xa2, 0xab, 0x70, 0x7a, 0x34, 0x34, 0x4f, 0x86, 0x2f, 0x26, 0x4f, 0x39, + /*95d0:*/ 0xab, 0x57, 0x4f, 0x76, 0xed, 0xf8, 0x30, 0xc0, 0x21, 0xb5, 0x17, 0x03, 0x8e, 0xf1, 0x4c, 0xe2, + /*95e0:*/ 0x50, 0x6e, 0xf8, 0x95, 0xee, 0x19, 0xc9, 0xf0, 0x7c, 0x06, 0x9e, 0x3d, 0x69, 0xdf, 0x90, 0x03, + /*95f0:*/ 0xae, 0xfb, 0xc4, 0x34, 0x9e, 0x0a, 0x7d, 0x2e, 0x4d, 0xc5, 0x97, 0x18, 0x01, 0xb7, 0xfb, 0xd7, + /*9600:*/ 0x89, 0x81, 0xd8, 0xd7, 0x2c, 0x12, 0x29, 0xd4, 0x3f, 0xa7, 0xcc, 0x67, 0x9a, 0xed, 0x17, 0xb9, + /*9610:*/ 0xd8, 0x74, 0x27, 0x54, 0xa0, 0x11, 0x44, 0xe0, 0x64, 0xfe, 0xa2, 0x57, 0xf5, 0x63, 0x55, 0xdd, + /*9620:*/ 0x7b, 0x45, 0xea, 0xc2, 0x19, 0xad, 0x3d, 0x68, 0xb7, 0x94, 0x89, 0xa6, 0x6e, 0x28, 0xd2, 0xbc, + /*9630:*/ 0x09, 0xe4, 0x75, 0x37, 0xd4, 0x26, 0x4e, 0xf1, 0x6c, 0x8b, 0x5d, 0x16, 0x12, 0xfc, 0x10, 0xff, + /*9640:*/ 0x12, 0x33, 0xdb, 0xd9, 0x7b, 0x22, 0x55, 0x7b, 0xe7, 0xc4, 0x9c, 0xd7, 0x50, 0x87, 0xc5, 0xde, + /*9650:*/ 0x8d, 0xe0, 0x74, 0xc7, 0x03, 0x9f, 0x64, 0x7f, 0xf4, 0xfd, 0xbd, 0xed, 0x0c, 0x14, 0x8c, 0x2a, + /*9660:*/ 0xf9, 0x2e, 0x06, 0x6e, 0xb7, 0x2a, 0x3e, 0x61, 0x02, 0xce, 0x84, 0xd4, 0xb6, 0x02, 0xee, 0x47, + /*9670:*/ 0x13, 0x01, 0x8c, 0x78, 0x6d, 0x2b, 0xea, 0xa2, 0x74, 0x3f, 0x87, 0x2d, 0x42, 0xa1, 0x7a, 0x63, + /*9680:*/ 0x25, 0x81, 0x88, 0x65, 0x0a, 0x42, 0x52, 0xa1, 0x8f, 0xba, 0xf5, 0x32, 0x27, 0xdd, 0x87, 0x68, + /*9690:*/ 0x95, 0x0e, 0x6e, 0xb3, 0x04, 0xbb, 0x40, 0x5e, 0x65, 0x0e, 0x51, 0x4c, 0x2a, 0x9c, 0x5a, 0x2e, + /*96a0:*/ 0xc9, 0xed, 0xc0, 0xe1, 0xb5, 0x7e, 0x69, 0xcf, 0x4e, 0x16, 0xe3, 0x11, 0x8e, 0xef, 0xb9, 0x44, + /*96b0:*/ 0x6b, 0x79, 0x1a, 0xf2, 0x7a, 0x58, 0xe7, 0xd3, 0xbb, 0x95, 0x9e, 0x9a, 0x63, 0xa2, 0x3c, 0x8c, + /*96c0:*/ 0xd3, 0x4f, 0x7e, 0x08, 0xd5, 0x48, 0x8f, 0x6f, 0x6d, 0x14, 0x44, 0x9d, 0x82, 0x1e, 0x27, 0x1c, + /*96d0:*/ 0xb7, 0x0d, 0xb5, 0xc8, 0x4a, 0x9e, 0x1d, 0x45, 0x6c, 0x69, 0x8d, 0x8b, 0x46, 0x21, 0x36, 0x51, + /*96e0:*/ 0xb8, 0x41, 0x18, 0x2f, 0x3c, 0x1f, 0xe1, 0xeb, 0x34, 0xc3, 0x09, 0xb5, 0xe8, 0xd7, 0x78, 0x60, + /*96f0:*/ 0xd5, 0x6f, 0xe4, 0xb1, 0x01, 0x3e, 0xac, 0xbf, 0xaa, 0xfd, 0x1a, 0x33, 0x75, 0xc7, 0x11, 0x66, + /*9700:*/ 0xed, 0x08, 0x5e, 0xbc, 0xa4, 0xc2, 0x12, 0x3e, 0x9f, 0xac, 0xc4, 0xee, 0xfe, 0xb2, 0xdb, 0x0f, + /*9710:*/ 0x0d, 0x6a, 0x03, 0x63, 0xe8, 0x9a, 0xfe, 0xde, 0xe1, 0x30, 0xba, 0x98, 0x1d, 0x33, 0x5c, 0x94, + /*9720:*/ 0x07, 0x88, 0x25, 0x84, 0xbe, 0x9c, 0x01, 0x21, 0xc3, 0x27, 0x98, 0xdb, 0x69, 0xb4, 0xec, 0x17, + /*9730:*/ 0x21, 0x15, 0x40, 0xbc, 0x54, 0xb3, 0xda, 0x62, 0x73, 0x09, 0x64, 0x6a, 0x41, 0x23, 0x8d, 0x47, + /*9740:*/ 0x19, 0xf7, 0x30, 0xe7, 0xb4, 0x2c, 0x60, 0xcb, 0x8c, 0xf3, 0xc4, 0xd8, 0xc5, 0x38, 0xba, 0xf7, + /*9750:*/ 0xf7, 0xe8, 0x1a, 0x07, 0x9c, 0xde, 0x82, 0x1c, 0x0f, 0xf9, 0x38, 0x4f, 0x32, 0xc0, 0x6c, 0x3d, + /*9760:*/ 0x4d, 0x90, 0x04, 0x0a, 0xe6, 0x34, 0xa9, 0x1d, 0xf6, 0x00, 0x97, 0xd8, 0x07, 0x8b, 0xfa, 0x3d, + /*9770:*/ 0x65, 0x0f, 0x31, 0x24, 0xd9, 0xf9, 0xdb, 0xc4, 0xbd, 0x6d, 0x14, 0xc5, 0x97, 0xdf, 0x6d, 0x22, + /*9780:*/ 0x82, 0x7b, 0x9d, 0x2e, 0x40, 0x53, 0x71, 0x0c, 0xde, 0x63, 0xe3, 0xf0, 0x50, 0xb9, 0x00, 0x99, + /*9790:*/ 0x76, 0x75, 0x3c, 0x90, 0x2d, 0x17, 0xb9, 0xed, 0x04, 0xcf, 0x14, 0x78, 0x8b, 0xe2, 0xcc, 0x7f, + /*97a0:*/ 0xa9, 0x49, 0xb0, 0x5d, 0x04, 0x64, 0xe4, 0x72, 0x55, 0x39, 0x1a, 0x9e, 0x88, 0xd4, 0x23, 0x9c, + /*97b0:*/ 0x04, 0xbf, 0xe0, 0x9b, 0xdf, 0xeb, 0x68, 0x6c, 0xc7, 0x04, 0xef, 0x6c, 0xb7, 0x6f, 0xd6, 0xff, + /*97c0:*/ 0xfe, 0x63, 0xeb, 0x9c, 0xc9, 0x7b, 0xfe, 0x30, 0x15, 0xce, 0x6c, 0xd2, 0x6f, 0xcc, 0x64, 0x5c, + /*97d0:*/ 0x76, 0x65, 0x45, 0xa6, 0x17, 0x85, 0x6c, 0xc5, 0x27, 0x2f, 0xd7, 0x16, 0x9e, 0xb7, 0x56, 0xb2, + /*97e0:*/ 0xb0, 0x72, 0x83, 0x5e, 0xde, 0xba, 0x80, 0xf1, 0x06, 0xe3, 0xaf, 0xcb, 0xad, 0xd8, 0x6b, 0xdd, + /*97f0:*/ 0x4a, 0xa9, 0xb6, 0x19, 0x48, 0x10, 0x50, 0xb7, 0xeb, 0x0a, 0x85, 0xa8, 0x9e, 0xbd, 0x10, 0x63, + /*9800:*/ 0x6c, 0x14, 0x33, 0x0a, 0x90, 0x63, 0x1f, 0xda, 0x0b, 0x1d, 0x19, 0xee, 0xf6, 0x20, 0xc5, 0x0c, + /*9810:*/ 0x79, 0x2d, 0x38, 0xbb, 0xdc, 0x38, 0x86, 0x4e, 0xce, 0x64, 0x1e, 0xfb, 0xfd, 0xbf, 0x8e, 0xa6, + /*9820:*/ 0x16, 0xec, 0xd9, 0x7b, 0x69, 0xb9, 0xc3, 0x96, 0x4a, 0x86, 0x43, 0x02, 0xf6, 0x74, 0xb5, 0x5f, + /*9830:*/ 0xb8, 0x39, 0xb1, 0x83, 0x40, 0x45, 0x72, 0xd8, 0xe9, 0x64, 0x81, 0x6a, 0xeb, 0x19, 0xbb, 0x42, + /*9840:*/ 0x61, 0xba, 0x45, 0x42, 0x47, 0x81, 0xe9, 0x19, 0x34, 0xdd, 0x80, 0x3e, 0xb9, 0x2c, 0x00, 0xad, + /*9850:*/ 0x0e, 0x3c, 0x71, 0x0b, 0xea, 0x1f, 0xf8, 0xa5, 0x38, 0x68, 0x66, 0x01, 0xa0, 0x70, 0xf4, 0x41, + /*9860:*/ 0x96, 0xa7, 0xb1, 0xae, 0x3c, 0xd9, 0xfd, 0x10, 0xb8, 0x4a, 0x70, 0x7b, 0x94, 0x00, 0xe8, 0xb6, + /*9870:*/ 0xa5, 0x24, 0xac, 0xa3, 0x5a, 0xd8, 0x6f, 0xa5, 0x48, 0x26, 0xd8, 0x7b, 0x4c, 0x5c, 0x30, 0x8b, + /*9880:*/ 0x6b, 0x55, 0x8a, 0x7b, 0x1b, 0xc8, 0xce, 0x9b, 0x7a, 0xc1, 0x36, 0xe7, 0x9a, 0x58, 0xe8, 0xc7, + /*9890:*/ 0x14, 0x8b, 0x01, 0x5f, 0x13, 0x04, 0x4c, 0x10, 0x43, 0x44, 0x33, 0x44, 0xe2, 0x60, 0xb6, 0x47, + /*98a0:*/ 0xca, 0x0a, 0x2e, 0x90, 0xa7, 0x49, 0xfc, 0x06, 0x3d, 0xf2, 0x4f, 0xd2, 0x69, 0x69, 0x6c, 0x0b, + /*98b0:*/ 0xe4, 0x37, 0x2a, 0x60, 0x8a, 0x8c, 0x0f, 0x33, 0xa9, 0xb1, 0xb3, 0xc8, 0xe6, 0x82, 0xa8, 0xaf, + /*98c0:*/ 0x56, 0x17, 0xc7, 0x77, 0xf6, 0xc9, 0xb2, 0x27, 0x79, 0x7e, 0xec, 0x3c, 0xba, 0xc4, 0x3b, 0x0f, + /*98d0:*/ 0x4f, 0xf4, 0x22, 0x13, 0x4c, 0x20, 0xda, 0xfb, 0xaf, 0x56, 0xae, 0x51, 0x27, 0x54, 0x15, 0x80, + /*98e0:*/ 0x85, 0x94, 0xb7, 0x97, 0x82, 0x8b, 0xef, 0xcf, 0x4a, 0xbf, 0xb8, 0x18, 0x2c, 0x37, 0x59, 0x8d, + /*98f0:*/ 0x32, 0xed, 0x94, 0x78, 0x56, 0x01, 0x05, 0xc0, 0xfe, 0x6f, 0x8c, 0x60, 0x7e, 0x77, 0xee, 0xc0, + /*9900:*/ 0xa8, 0x3f, 0x8d, 0xb9, 0x7d, 0x19, 0x8e, 0x95, 0xf8, 0xbe, 0xc5, 0xe8, 0x57, 0xbd, 0x3c, 0xfc, + /*9910:*/ 0x9b, 0xfd, 0x72, 0x44, 0xf4, 0x42, 0x2d, 0xcb, 0x8c, 0x81, 0x8c, 0x3b, 0x0c, 0xfe, 0x05, 0x42, + /*9920:*/ 0x55, 0xeb, 0xb9, 0x30, 0x27, 0xc5, 0x4c, 0x1b, 0x79, 0xd5, 0x9e, 0x2e, 0x50, 0x25, 0x08, 0x62, + /*9930:*/ 0xcc, 0x75, 0x72, 0x33, 0x26, 0xc3, 0xcd, 0x86, 0xb0, 0xe4, 0xee, 0xea, 0xd6, 0x2d, 0x57, 0xd3, + /*9940:*/ 0x80, 0x9c, 0xef, 0x9d, 0x78, 0x6d, 0x96, 0x28, 0xac, 0xed, 0x27, 0xea, 0x62, 0xbd, 0x8d, 0x9e, + /*9950:*/ 0x20, 0x2b, 0xc4, 0xe4, 0x3d, 0x61, 0x68, 0xff, 0x5c, 0x5d, 0x47, 0x44, 0x40, 0x4c, 0x9a, 0x47, + /*9960:*/ 0xa0, 0x24, 0x16, 0x1e, 0x88, 0xd5, 0x86, 0x29, 0x96, 0x0c, 0x4f, 0x13, 0x1f, 0x2c, 0x03, 0x98, + /*9970:*/ 0x56, 0xd9, 0x46, 0xe5, 0x18, 0x83, 0xed, 0x85, 0xd9, 0x8a, 0x8a, 0x88, 0xe6, 0x19, 0xf2, 0x7b, + /*9980:*/ 0xe4, 0x68, 0x3d, 0xfc, 0xbd, 0x71, 0x27, 0x22, 0xf4, 0x60, 0x51, 0x30, 0x52, 0x99, 0x43, 0x88, + /*9990:*/ 0x42, 0xa4, 0xe8, 0x16, 0xf2, 0x17, 0x3a, 0xd7, 0x2b, 0x85, 0x49, 0x53, 0x50, 0x14, 0x51, 0xd3, + /*99a0:*/ 0x4c, 0x85, 0xcc, 0x80, 0x1e, 0x49, 0x18, 0xb8, 0x3c, 0x3e, 0x1c, 0xbe, 0x56, 0x07, 0xf7, 0xc7, + /*99b0:*/ 0x9f, 0xda, 0xce, 0x00, 0x93, 0xe6, 0xa1, 0xda, 0xf1, 0x45, 0x7b, 0x3f, 0x26, 0x9c, 0xb6, 0xe8, + /*99c0:*/ 0xfb, 0xce, 0x3b, 0x85, 0x64, 0xf5, 0x85, 0x9c, 0x34, 0x4f, 0x89, 0x44, 0x52, 0x69, 0x99, 0xc9, + /*99d0:*/ 0x5d, 0x87, 0x52, 0x2c, 0xd3, 0x3a, 0x6e, 0x5c, 0x02, 0x41, 0x5c, 0x03, 0xa8, 0xfb, 0xcd, 0x82, + /*99e0:*/ 0xe6, 0xd7, 0xe2, 0x90, 0x06, 0x9e, 0x4f, 0xbc, 0x53, 0x79, 0x24, 0xd9, 0x20, 0xb6, 0x5f, 0xa6, + /*99f0:*/ 0x0d, 0x88, 0x85, 0xbe, 0x19, 0xe4, 0x1f, 0x95, 0xf8, 0x94, 0x6e, 0x01, 0x9d, 0xc0, 0xef, 0x18, + /*9a00:*/ 0xaf, 0xda, 0xac, 0x64, 0x8c, 0x7a, 0x84, 0x6d, 0x45, 0xa4, 0x34, 0x66, 0x9b, 0x81, 0xab, 0x69, + /*9a10:*/ 0x19, 0x49, 0x6c, 0xa8, 0xc6, 0x8b, 0x3b, 0xbd, 0xff, 0x27, 0x23, 0x48, 0xa6, 0x6b, 0xa9, 0x30, + /*9a20:*/ 0xf0, 0xbb, 0xe4, 0x08, 0x3d, 0x52, 0x21, 0x70, 0xbc, 0x42, 0x45, 0x92, 0xf7, 0x0c, 0x83, 0x33, + /*9a30:*/ 0x9f, 0x38, 0x28, 0x1b, 0xb3, 0xf2, 0xc4, 0x38, 0x24, 0x03, 0xfd, 0xa9, 0x18, 0x60, 0x54, 0xcc, + /*9a40:*/ 0xc1, 0xb0, 0x78, 0x8e, 0x99, 0x64, 0x9c, 0xeb, 0x02, 0xbc, 0x63, 0x7b, 0xd6, 0x03, 0x6d, 0xcb, + /*9a50:*/ 0x1f, 0x6f, 0x34, 0x59, 0xe6, 0x7e, 0xb0, 0x10, 0xbb, 0x5d, 0xe6, 0xfa, 0x66, 0xbe, 0x14, 0x10, + /*9a60:*/ 0xca, 0xd1, 0x3f, 0x99, 0x4c, 0x04, 0xfb, 0x56, 0x64, 0xec, 0x2e, 0x07, 0x61, 0x05, 0x9c, 0x8c, + /*9a70:*/ 0x1a, 0xc4, 0x34, 0x1d, 0xbf, 0x33, 0x69, 0x38, 0x9f, 0xa4, 0x9e, 0xbd, 0xc6, 0x4d, 0x49, 0xe4, + /*9a80:*/ 0xf3, 0xc5, 0x38, 0xb4, 0xb7, 0xa3, 0x0a, 0x49, 0x67, 0x9e, 0x79, 0xf0, 0xa7, 0x4c, 0x91, 0xf7, + /*9a90:*/ 0x42, 0x88, 0xc1, 0x4f, 0x01, 0xa0, 0x43, 0x6e, 0x39, 0xbd, 0x96, 0x07, 0x3e, 0xab, 0x70, 0x56, + /*9aa0:*/ 0x54, 0xe1, 0xc9, 0xa2, 0x9a, 0x98, 0xb9, 0xd6, 0x3c, 0x17, 0xa9, 0xbe, 0xc5, 0xe2, 0x36, 0x18, + /*9ab0:*/ 0xf4, 0x15, 0x9d, 0x0b, 0xa2, 0x66, 0x87, 0x79, 0x45, 0x6d, 0x24, 0x09, 0xa0, 0xcd, 0x87, 0xdc, + /*9ac0:*/ 0x3d, 0x69, 0x16, 0x6b, 0xef, 0xf4, 0x3b, 0x04, 0x34, 0x84, 0xf1, 0x19, 0x8c, 0x73, 0x90, 0xf0, + /*9ad0:*/ 0xde, 0xfb, 0xcf, 0x48, 0x44, 0x41, 0xf9, 0x81, 0xb3, 0xa7, 0x0a, 0xc2, 0xd4, 0x8c, 0x84, 0x9a, + /*9ae0:*/ 0x6a, 0x1c, 0x34, 0x63, 0x96, 0x0a, 0xe0, 0xc6, 0x10, 0x88, 0x8f, 0x8e, 0xac, 0x96, 0xee, 0xc0, + /*9af0:*/ 0x86, 0x16, 0x61, 0x8f, 0x35, 0xec, 0x47, 0x4e, 0x75, 0x17, 0x49, 0x0e, 0x3f, 0x34, 0x68, 0x7e, + /*9b00:*/ 0xae, 0x61, 0x0e, 0x7e, 0xd2, 0x81, 0x53, 0xd1, 0x53, 0x7a, 0x20, 0x7a, 0x40, 0x7a, 0x2e, 0xbc, + /*9b10:*/ 0x43, 0x3a, 0x66, 0x39, 0x0f, 0xc1, 0x85, 0xc0, 0x71, 0xe0, 0x15, 0x28, 0x47, 0xb5, 0xd1, 0x99, + /*9b20:*/ 0x6e, 0xd3, 0x48, 0xe0, 0x41, 0xa7, 0xf3, 0x27, 0x8f, 0xda, 0x55, 0x5f, 0x89, 0x0f, 0x9b, 0x91, + /*9b30:*/ 0xe9, 0x1f, 0x9b, 0x5e, 0x32, 0x53, 0x3e, 0x8c, 0x65, 0xd5, 0x92, 0x0b, 0x8c, 0x5f, 0x73, 0xcc, + /*9b40:*/ 0x0d, 0xc5, 0xa7, 0x1c, 0x80, 0x85, 0xca, 0xbc, 0x00, 0xf6, 0x73, 0x07, 0x9b, 0xb4, 0x93, 0x48, + /*9b50:*/ 0x22, 0xe3, 0xf9, 0x63, 0x9d, 0xe5, 0x82, 0x17, 0x3e, 0x65, 0x2b, 0x4f, 0x68, 0xc3, 0xc3, 0x6d, + /*9b60:*/ 0x8d, 0x9a, 0x5e, 0x47, 0xe6, 0x1f, 0x99, 0x94, 0xab, 0xd6, 0xc2, 0xeb, 0x05, 0x70, 0x23, 0x7a, + /*9b70:*/ 0x6b, 0xbd, 0xc0, 0x1d, 0xe2, 0x22, 0xa9, 0xb5, 0x56, 0xcb, 0x93, 0x2c, 0x88, 0xed, 0xd9, 0xbf, + /*9b80:*/ 0x14, 0x44, 0xb3, 0x99, 0xe2, 0x58, 0x2d, 0x78, 0x53, 0xc3, 0xbf, 0x94, 0xd0, 0x57, 0x95, 0xec, + /*9b90:*/ 0x25, 0xe2, 0x51, 0xb4, 0x6f, 0x2d, 0xf9, 0xb4, 0x15, 0x32, 0xa4, 0x20, 0xf8, 0x7e, 0x47, 0x65, + /*9ba0:*/ 0xc8, 0xb2, 0x95, 0xad, 0x41, 0xd5, 0x91, 0xbb, 0xd7, 0x66, 0x2c, 0x96, 0x7d, 0x78, 0x85, 0x3c, + /*9bb0:*/ 0x72, 0x21, 0x9d, 0xe4, 0x4a, 0x4a, 0x4f, 0x29, 0x76, 0x24, 0x82, 0x83, 0xb8, 0x19, 0x1b, 0x5a, + /*9bc0:*/ 0x1f, 0x13, 0x76, 0xc2, 0xe3, 0x69, 0x75, 0xea, 0x4a, 0xb0, 0xbd, 0x34, 0x87, 0x0c, 0xe3, 0xda, + /*9bd0:*/ 0x14, 0xce, 0x42, 0x65, 0x42, 0xed, 0x9a, 0x7f, 0x69, 0x83, 0x55, 0xa4, 0xbf, 0xd5, 0x91, 0xa9, + /*9be0:*/ 0x00, 0x57, 0xa1, 0x24, 0x8d, 0xd8, 0x01, 0xf7, 0x5a, 0x76, 0xf8, 0x15, 0x14, 0x80, 0xd0, 0x8e, + /*9bf0:*/ 0x26, 0xbb, 0x5c, 0x5b, 0x6b, 0x62, 0x5c, 0xa4, 0x75, 0xe2, 0x01, 0xd1, 0x46, 0x9b, 0x7f, 0x7f, + /*9c00:*/ 0x16, 0xd1, 0xa0, 0xfa, 0x4f, 0x8e, 0x3d, 0xe4, 0xe0, 0xab, 0xc4, 0x25, 0x7f, 0x3a, 0x1b, 0x17, + /*9c10:*/ 0x3a, 0x99, 0xff, 0xa6, 0x54, 0xce, 0x8d, 0x7c, 0xa6, 0x4a, 0xce, 0x6f, 0x98, 0xe3, 0x1d, 0x84, + /*9c20:*/ 0x8b, 0x74, 0xf7, 0x01, 0x99, 0x05, 0x21, 0xce, 0x4d, 0x0f, 0x4c, 0x91, 0x40, 0x24, 0xf4, 0x78, + /*9c30:*/ 0xec, 0x90, 0xc9, 0xca, 0xc2, 0x63, 0x97, 0x84, 0x56, 0x21, 0x88, 0x57, 0xc2, 0xc0, 0x9d, 0xbd, + /*9c40:*/ 0x78, 0xc8, 0x69, 0x9a, 0x00, 0xd0, 0xaa, 0x65, 0x9a, 0x74, 0x06, 0xf1, 0x66, 0x15, 0xcc, 0xf2, + /*9c50:*/ 0x2a, 0x6a, 0xc1, 0xf3, 0x02, 0x6e, 0x08, 0xc4, 0xea, 0x54, 0x55, 0x05, 0x86, 0xeb, 0x19, 0x4a, + /*9c60:*/ 0xa3, 0xee, 0xa7, 0x1a, 0x3c, 0x93, 0x34, 0x07, 0x91, 0x72, 0x36, 0xbd, 0xb7, 0x54, 0xc5, 0x05, + /*9c70:*/ 0xdb, 0xe3, 0xe6, 0x5d, 0x48, 0x58, 0x16, 0x23, 0xed, 0x21, 0x9e, 0xe6, 0xed, 0xb4, 0x8f, 0x75, + /*9c80:*/ 0x8d, 0x5b, 0x9a, 0x16, 0x65, 0x9e, 0x5f, 0xb9, 0xff, 0xc9, 0xcd, 0xd0, 0xa8, 0xd3, 0x36, 0x3e, + /*9c90:*/ 0x36, 0x67, 0x30, 0xf5, 0xd8, 0xbe, 0x1c, 0xe3, 0x30, 0x9e, 0x0c, 0x1b, 0x06, 0x6d, 0x34, 0x07, + /*9ca0:*/ 0x73, 0x56, 0x08, 0xff, 0xaa, 0x12, 0x5b, 0x46, 0x54, 0x57, 0xb5, 0x3d, 0x56, 0x95, 0x09, 0x9f, + /*9cb0:*/ 0x40, 0x99, 0x96, 0x83, 0x58, 0xbb, 0xcc, 0x88, 0x1a, 0x62, 0xbd, 0xb7, 0xaa, 0x27, 0x9a, 0xf7, + /*9cc0:*/ 0xd1, 0x23, 0x3c, 0xa7, 0x5f, 0x82, 0x20, 0x91, 0x0c, 0xa5, 0x4c, 0xda, 0x74, 0xf8, 0x0e, 0x59, + /*9cd0:*/ 0x68, 0x13, 0xd6, 0x07, 0xe2, 0x4e, 0x57, 0x5c, 0xd3, 0xb5, 0xb9, 0x11, 0xaa, 0x45, 0x74, 0xf2, + /*9ce0:*/ 0xf4, 0x37, 0x37, 0xff, 0x45, 0x6c, 0x51, 0x1d, 0xfe, 0xf0, 0x12, 0x40, 0x57, 0x6f, 0x41, 0x93, + /*9cf0:*/ 0xb0, 0x7c, 0xd3, 0x5d, 0xe4, 0x10, 0x0c, 0xe2, 0xfa, 0x90, 0xa9, 0x68, 0xf9, 0x41, 0xd4, 0x71, + /*9d00:*/ 0x2e, 0x46, 0xfb, 0x78, 0xca, 0xa6, 0x44, 0xec, 0xbf, 0xfb, 0x33, 0xea, 0xcd, 0x46, 0x64, 0xf0, + /*9d10:*/ 0x1e, 0x5a, 0x3a, 0x3a, 0xbe, 0x7f, 0x83, 0x94, 0xb2, 0x11, 0xb1, 0x32, 0x14, 0x05, 0xc0, 0xa0, + /*9d20:*/ 0x87, 0x7f, 0xb7, 0xf2, 0xe9, 0x08, 0xcb, 0x1f, 0x5d, 0x87, 0x30, 0xec, 0x05, 0xcf, 0xaa, 0x01, + /*9d30:*/ 0x2f, 0x23, 0x0d, 0x81, 0xde, 0x30, 0x8e, 0x03, 0x0e, 0x44, 0x6e, 0x62, 0xb9, 0x6e, 0x7c, 0x0e, + /*9d40:*/ 0x0a, 0x00, 0x63, 0xea, 0xb9, 0xbd, 0x9b, 0x8e, 0x1a, 0x3c, 0xb4, 0xff, 0xae, 0xd4, 0x15, 0x18, + /*9d50:*/ 0xe6, 0x0f, 0xfe, 0x28, 0x6e, 0xdc, 0x76, 0x2a, 0xf5, 0xd4, 0x14, 0xd8, 0x8c, 0x76, 0x35, 0xa8, + /*9d60:*/ 0x85, 0x38, 0x55, 0xfe, 0xc3, 0x83, 0xd5, 0xaa, 0x58, 0x92, 0xb8, 0x82, 0x45, 0x9c, 0xe5, 0x92, + /*9d70:*/ 0xd4, 0x11, 0xc9, 0xf9, 0xab, 0x5b, 0x9c, 0x77, 0xb3, 0xbe, 0x3f, 0x65, 0x89, 0xbd, 0x1d, 0xdf, + /*9d80:*/ 0x89, 0x64, 0xe3, 0x0b, 0xf4, 0xc8, 0xf2, 0xe1, 0x23, 0xbf, 0x13, 0x81, 0x33, 0x92, 0x94, 0x75, + /*9d90:*/ 0x1b, 0xd1, 0xfc, 0x34, 0xee, 0x54, 0xdc, 0x3c, 0x40, 0xf4, 0x5d, 0xdd, 0x64, 0xd5, 0xb0, 0xdf, + /*9da0:*/ 0x6a, 0xb6, 0x3b, 0x92, 0x71, 0x06, 0x33, 0xf7, 0xba, 0x9b, 0x4a, 0x79, 0x91, 0x31, 0x17, 0x86, + /*9db0:*/ 0x35, 0x37, 0x8f, 0x62, 0x57, 0x43, 0xe7, 0x72, 0x32, 0x56, 0x91, 0x41, 0xd5, 0xc9, 0x27, 0x54, + /*9dc0:*/ 0x7e, 0x61, 0x7b, 0x36, 0x15, 0x2d, 0xbd, 0x4d, 0x9f, 0x51, 0xfd, 0x85, 0x8d, 0x00, 0x91, 0xe3, + /*9dd0:*/ 0x64, 0xb1, 0x8b, 0x51, 0xbe, 0x0e, 0x5d, 0xdb, 0x41, 0x79, 0xec, 0x11, 0x95, 0xa7, 0xfa, 0x4b, + /*9de0:*/ 0xd3, 0x55, 0x98, 0xb2, 0xd2, 0x51, 0xfe, 0x51, 0x35, 0x9c, 0x22, 0x3e, 0x25, 0x91, 0x42, 0xc3, + /*9df0:*/ 0xb0, 0x75, 0x05, 0xeb, 0xf2, 0xcb, 0x7d, 0xaa, 0xb6, 0x4b, 0x82, 0x12, 0xc2, 0x88, 0xf9, 0x78, + /*9e00:*/ 0xf6, 0x01, 0x30, 0x50, 0x38, 0x6a, 0xcb, 0xb1, 0xf1, 0x27, 0xcb, 0xf7, 0xd3, 0xe1, 0x43, 0xf3, + /*9e10:*/ 0x9e, 0x8c, 0x92, 0xab, 0xcd, 0xa7, 0x03, 0xc3, 0xd0, 0x9c, 0x91, 0x8b, 0x2d, 0xde, 0xbc, 0x50, + /*9e20:*/ 0x63, 0x95, 0x4b, 0x7e, 0xda, 0xf4, 0x72, 0xe3, 0xcc, 0x2c, 0x35, 0x5d, 0x2c, 0xd0, 0x4b, 0x54, + /*9e30:*/ 0xaf, 0xf4, 0x42, 0x0e, 0xd4, 0x8a, 0x66, 0x56, 0x83, 0xd9, 0x5e, 0x1d, 0x81, 0xd3, 0xce, 0xad, + /*9e40:*/ 0x61, 0xca, 0x20, 0xe6, 0xc3, 0x17, 0xef, 0x4b, 0xbe, 0xf0, 0xbc, 0xda, 0xb3, 0x79, 0xb5, 0xcb, + /*9e50:*/ 0x38, 0x67, 0x2a, 0x17, 0x4f, 0xda, 0xfc, 0x1a, 0x87, 0x8d, 0xc3, 0x73, 0x87, 0x65, 0xf6, 0x03, + /*9e60:*/ 0xc9, 0xf0, 0xab, 0x2c, 0x6f, 0xae, 0x90, 0x15, 0x10, 0xf1, 0x8d, 0x90, 0x05, 0x1a, 0x27, 0x72, + /*9e70:*/ 0x2d, 0x2d, 0xfb, 0x1b, 0xec, 0x9a, 0x90, 0x21, 0x08, 0xb6, 0x58, 0x57, 0xb3, 0x3d, 0xb1, 0x29, + /*9e80:*/ 0x00, 0x62, 0x95, 0x68, 0x6b, 0x5b, 0xfb, 0x98, 0x6e, 0xbb, 0x9c, 0x53, 0x03, 0xd3, 0xda, 0x91, + /*9e90:*/ 0xac, 0xec, 0x1c, 0x4e, 0x56, 0xbb, 0x50, 0xe3, 0x23, 0xc0, 0x01, 0x63, 0x45, 0x01, 0xff, 0x30, + /*9ea0:*/ 0x6e, 0x6f, 0xe9, 0x60, 0xed, 0xab, 0x89, 0x5c, 0xcf, 0x0a, 0x89, 0x13, 0x39, 0x2a, 0xa6, 0x93, + /*9eb0:*/ 0x18, 0xc8, 0x26, 0xd3, 0x23, 0x8c, 0x22, 0xa4, 0x3c, 0xde, 0xe7, 0x7d, 0x9c, 0x5c, 0x35, 0x4c, + /*9ec0:*/ 0xb1, 0x6e, 0xfc, 0x19, 0xaa, 0x5a, 0x17, 0xad, 0x22, 0x75, 0x3e, 0x83, 0xa7, 0x7e, 0x72, 0xe0, + /*9ed0:*/ 0xaa, 0x75, 0x37, 0x2a, 0xd0, 0xd3, 0x8f, 0xbf, 0x20, 0x0b, 0x3e, 0xff, 0xea, 0x0b, 0x3c, 0x20, + /*9ee0:*/ 0x33, 0x6b, 0x28, 0xc8, 0x67, 0x85, 0x97, 0x61, 0x5f, 0x48, 0xaf, 0x38, 0x38, 0x07, 0x41, 0x6a, + /*9ef0:*/ 0x5e, 0x5a, 0x39, 0x4e, 0x45, 0xc6, 0xb5, 0x8f, 0xea, 0x78, 0x47, 0x51, 0x83, 0xb2, 0x98, 0xd1, + /*9f00:*/ 0x43, 0x0f, 0xc4, 0xaf, 0xad, 0xf4, 0x95, 0xe5, 0xc8, 0x6f, 0x48, 0x50, 0x83, 0x7c, 0xd4, 0xb9, + /*9f10:*/ 0x13, 0x7b, 0x60, 0x41, 0xf9, 0x2f, 0xe0, 0x31, 0x5f, 0x3f, 0x20, 0xce, 0x6f, 0xcd, 0x94, 0x0a, + /*9f20:*/ 0xd5, 0x0b, 0x01, 0x09, 0x5f, 0x1d, 0x43, 0x0a, 0x35, 0x05, 0x6b, 0xe6, 0x0a, 0x48, 0xb1, 0xa7, + /*9f30:*/ 0xe5, 0x03, 0x7f, 0x6b, 0xfe, 0xcc, 0xdf, 0x88, 0xbc, 0xde, 0x8f, 0x1f, 0xad, 0x77, 0xb0, 0xe9, + /*9f40:*/ 0x53, 0x1f, 0xad, 0xb0, 0x81, 0x9f, 0xa6, 0x9f, 0x7e, 0x36, 0x8e, 0xed, 0xba, 0xa9, 0x07, 0x78, + /*9f50:*/ 0x2f, 0xea, 0xdb, 0x66, 0x63, 0x32, 0x47, 0xbf, 0x38, 0xfe, 0x6b, 0xa8, 0x29, 0x27, 0x0a, 0x41, + /*9f60:*/ 0x0b, 0x84, 0x11, 0xcf, 0x5c, 0x57, 0x0f, 0x2a, 0xbc, 0x6f, 0xc8, 0xa8, 0x55, 0x19, 0xd8, 0xd0, + /*9f70:*/ 0x7c, 0xec, 0x19, 0x72, 0x50, 0xfa, 0x86, 0xf8, 0xa9, 0x1e, 0xb7, 0xa3, 0x96, 0xe2, 0x58, 0x17, + /*9f80:*/ 0x1c, 0xc9, 0x95, 0x38, 0x9e, 0x94, 0x9e, 0x16, 0xe1, 0x69, 0xe7, 0xea, 0xf2, 0x49, 0x5f, 0x9a, + /*9f90:*/ 0x64, 0x42, 0x5e, 0x7b, 0xb5, 0x4b, 0x5c, 0x29, 0x23, 0x84, 0xaf, 0xa3, 0x41, 0x54, 0xd2, 0x9e, + /*9fa0:*/ 0x25, 0x1d, 0x19, 0x1a, 0x86, 0x1d, 0xa5, 0xb4, 0xc6, 0x8f, 0x81, 0x1f, 0x06, 0xed, 0xb8, 0xee, + /*9fb0:*/ 0x1b, 0xf0, 0xb6, 0x78, 0xd1, 0x00, 0x85, 0x81, 0xff, 0xde, 0xdb, 0xc1, 0x6c, 0xb9, 0xdc, 0xb3, + /*9fc0:*/ 0x45, 0x16, 0x5f, 0xaf, 0x54, 0x17, 0xef, 0x0b, 0x98, 0x33, 0x29, 0xb5, 0x4a, 0xfb, 0x3d, 0x19, + /*9fd0:*/ 0x0d, 0x74, 0x8b, 0xee, 0x20, 0x94, 0x80, 0x59, 0xac, 0x93, 0xba, 0x50, 0x8a, 0x7b, 0xff, 0xd1, + /*9fe0:*/ 0xad, 0x7e, 0x91, 0x79, 0xcb, 0xb1, 0x64, 0x58, 0x55, 0x2a, 0xf8, 0xc4, 0xcd, 0x9b, 0xdc, 0x4c, + /*9ff0:*/ 0x17, 0x61, 0x19, 0x99, 0x54, 0x30, 0x20, 0x6b, 0xe9, 0xc8, 0xad, 0x1f, 0xcf, 0x61, 0x18, 0x5f, + /*a000:*/ 0x1d, 0x2d, 0xb1, 0xb6, 0xbf, 0xd9, 0xee, 0x38, 0x22, 0xd1, 0xd4, 0xad, 0xe7, 0xe4, 0xb3, 0xcd, + /*a010:*/ 0x65, 0x9c, 0x45, 0xcf, 0x2b, 0xe0, 0xde, 0x2c, 0x3a, 0x53, 0x1f, 0x98, 0x10, 0xf5, 0x15, 0xd8, + /*a020:*/ 0x53, 0xa4, 0x3c, 0x46, 0x00, 0x53, 0xab, 0x9b, 0x4f, 0x92, 0xb8, 0x70, 0x84, 0x24, 0xa7, 0xaf, + /*a030:*/ 0xe3, 0x0a, 0x5f, 0x89, 0x10, 0xa1, 0x72, 0x3d, 0x68, 0x14, 0x1d, 0xb9, 0x16, 0x4e, 0x6c, 0x19, + /*a040:*/ 0x43, 0x95, 0x83, 0xb8, 0x18, 0x61, 0x4d, 0x20, 0x6d, 0xb9, 0x97, 0x6b, 0x44, 0xe4, 0x9b, 0x2c, + /*a050:*/ 0xb5, 0x5a, 0xdd, 0xd5, 0xd1, 0x6a, 0xdf, 0x19, 0xf7, 0xb0, 0x5a, 0x09, 0xc1, 0x55, 0x3e, 0x88, + /*a060:*/ 0xbe, 0xa5, 0x49, 0x20, 0x95, 0x7f, 0xcb, 0x97, 0x5b, 0x51, 0x4d, 0xb0, 0x77, 0x89, 0xab, 0x4d, + /*a070:*/ 0xfc, 0x88, 0x20, 0x25, 0x68, 0x38, 0x6a, 0xb9, 0x5d, 0x0b, 0x9a, 0xe6, 0x96, 0xeb, 0x64, 0x66, + /*a080:*/ 0x1f, 0x7b, 0xb0, 0x2f, 0x35, 0xb6, 0x45, 0x25, 0x46, 0x09, 0x70, 0x98, 0xf8, 0xdc, 0x47, 0x14, + /*a090:*/ 0x7d, 0x61, 0xfa, 0x6e, 0x4e, 0x7c, 0x4f, 0x42, 0xe3, 0xaa, 0x1a, 0xf7, 0x44, 0xa8, 0x4a, 0x85, + /*a0a0:*/ 0xa5, 0xcc, 0x07, 0x7c, 0x2a, 0x23, 0xab, 0x1d, 0xf7, 0xa0, 0xd5, 0xd9, 0x9b, 0xfc, 0xf9, 0x9b, + /*a0b0:*/ 0xec, 0x93, 0xd4, 0x03, 0x86, 0x1d, 0x0b, 0x02, 0x82, 0xde, 0x06, 0xb3, 0xd1, 0x58, 0x03, 0xf1, + /*a0c0:*/ 0xbd, 0x8f, 0xf8, 0xc9, 0x39, 0x9d, 0xce, 0x16, 0x54, 0xb0, 0x42, 0x8b, 0xac, 0x08, 0x5c, 0xfb, + /*a0d0:*/ 0x0c, 0xcb, 0x79, 0xfc, 0x65, 0xe0, 0xe6, 0x54, 0xcd, 0x39, 0x6d, 0x3d, 0x67, 0x69, 0xf4, 0xb6, + /*a0e0:*/ 0x0d, 0x51, 0xb2, 0x3b, 0xc0, 0x61, 0x97, 0xde, 0xbd, 0x7f, 0x0a, 0xe0, 0xb0, 0xd7, 0x46, 0x21, + /*a0f0:*/ 0xb4, 0xa5, 0x9b, 0x96, 0x3c, 0xf5, 0x75, 0x39, 0x44, 0xb9, 0x06, 0xf2, 0xf7, 0x51, 0xc8, 0xfa, + /*a100:*/ 0x6f, 0x1c, 0x06, 0x3c, 0x90, 0xf0, 0xf6, 0x67, 0x17, 0xe8, 0xb2, 0x0c, 0x75, 0x40, 0x92, 0x4d, + /*a110:*/ 0x41, 0x08, 0x39, 0xf9, 0x71, 0xb8, 0xe5, 0xbf, 0x8f, 0xad, 0x90, 0x84, 0x29, 0x48, 0x8e, 0x75, + /*a120:*/ 0x4f, 0xb3, 0xf3, 0xe3, 0xc3, 0xf5, 0x3d, 0xe6, 0x95, 0xfb, 0x14, 0x5b, 0x89, 0xe4, 0xd8, 0xf3, + /*a130:*/ 0x16, 0x26, 0x76, 0xf5, 0x76, 0x43, 0x1f, 0xe3, 0x0b, 0xe4, 0xb7, 0x5a, 0x1a, 0x2c, 0x71, 0xb0, + /*a140:*/ 0xd4, 0xd0, 0x09, 0x8c, 0x64, 0x70, 0x57, 0x98, 0xe6, 0xa6, 0x10, 0x6f, 0xde, 0xe1, 0xa5, 0x45, + /*a150:*/ 0x9e, 0x41, 0x35, 0x3f, 0x78, 0x8e, 0xf1, 0x3c, 0x30, 0x32, 0xe2, 0xe1, 0xa6, 0xd8, 0x58, 0xc0, + /*a160:*/ 0xa4, 0x69, 0x1a, 0x5a, 0xb2, 0x56, 0x7f, 0x33, 0x3f, 0x10, 0x77, 0x92, 0xa7, 0xc0, 0xb2, 0xc0, + /*a170:*/ 0xf8, 0x27, 0xa5, 0xcd, 0xfa, 0x27, 0x9f, 0xe3, 0x28, 0x59, 0x54, 0xb3, 0x43, 0xf8, 0xd7, 0x20, + /*a180:*/ 0x25, 0xee, 0x34, 0x3d, 0x66, 0xa1, 0x48, 0x83, 0x61, 0x03, 0x29, 0xcb, 0xbb, 0x72, 0x56, 0x1d, + /*a190:*/ 0x66, 0xfc, 0xcf, 0x6e, 0x28, 0x22, 0xed, 0x3a, 0x2f, 0xdb, 0x4a, 0x0b, 0xa6, 0xbe, 0xb2, 0xe4, + /*a1a0:*/ 0x26, 0x40, 0x82, 0xd0, 0xab, 0xfa, 0x95, 0x03, 0x4d, 0xdb, 0x5b, 0x97, 0x65, 0x36, 0x4a, 0x5e, + /*a1b0:*/ 0xd9, 0x63, 0xc8, 0x9c, 0xbe, 0x70, 0x76, 0xee, 0xa0, 0xcf, 0x34, 0xad, 0xcd, 0xa1, 0x81, 0x19, + /*a1c0:*/ 0x71, 0x49, 0xb7, 0xc9, 0x47, 0xec, 0x92, 0x32, 0xc8, 0xf0, 0xe0, 0x30, 0xee, 0x9a, 0xbb, 0x11, + /*a1d0:*/ 0x8e, 0xe4, 0xa8, 0xdb, 0x1f, 0x29, 0xf5, 0xcf, 0x16, 0x82, 0x7b, 0xcf, 0x10, 0x48, 0xaa, 0x55, + /*a1e0:*/ 0x75, 0x9e, 0x8b, 0xc1, 0x34, 0xd2, 0x91, 0xd1, 0x56, 0x51, 0xee, 0xcb, 0xc5, 0x8b, 0xeb, 0x30, + /*a1f0:*/ 0xa9, 0x0c, 0xcd, 0x05, 0x7c, 0xd0, 0x64, 0x8b, 0x66, 0xba, 0x59, 0xd2, 0x0d, 0x87, 0x8f, 0xf6, + /*a200:*/ 0x67, 0x8b, 0x85, 0x44, 0x7f, 0xd9, 0x02, 0xfd, 0x75, 0x0b, 0x11, 0x45, 0xa5, 0x1d, 0x2a, 0x37, + /*a210:*/ 0xd8, 0xe7, 0xde, 0x33, 0xcf, 0xdb, 0xdb, 0x31, 0xe4, 0xf5, 0x41, 0xae, 0x33, 0x6e, 0x0e, 0x02, + /*a220:*/ 0x02, 0x38, 0xd7, 0x67, 0xb5, 0x24, 0xe9, 0x31, 0x91, 0x0f, 0x5f, 0x24, 0xd3, 0x2f, 0x41, 0xe7, + /*a230:*/ 0x8a, 0xb0, 0x5c, 0x88, 0x32, 0x4e, 0xff, 0xf1, 0xa4, 0xaf, 0xa8, 0x6b, 0x04, 0x5d, 0x0e, 0xb2, + /*a240:*/ 0xd8, 0x69, 0x74, 0x5b, 0xbc, 0x91, 0xf3, 0x59, 0x98, 0xf5, 0x13, 0xdd, 0x10, 0x45, 0x02, 0x6d, + /*a250:*/ 0xcb, 0x3e, 0x01, 0x31, 0xa0, 0x29, 0x07, 0x67, 0x3b, 0x04, 0x4a, 0xc3, 0x9c, 0x9e, 0x90, 0xa0, + /*a260:*/ 0x1d, 0xc1, 0x6a, 0x9e, 0xef, 0xd5, 0xf2, 0x1f, 0x91, 0xd0, 0xe7, 0xe2, 0x76, 0x83, 0xaa, 0x85, + /*a270:*/ 0xd6, 0x29, 0x8a, 0x74, 0x09, 0x94, 0xed, 0x4e, 0x2b, 0xd9, 0x6a, 0x55, 0x70, 0x3d, 0x16, 0x57, + /*a280:*/ 0xd4, 0x9e, 0x31, 0x66, 0x8b, 0xf4, 0x6a, 0x70, 0xce, 0xe5, 0x33, 0xc0, 0xb4, 0xcf, 0x41, 0xf7, + /*a290:*/ 0xb2, 0xbf, 0x95, 0xa1, 0xe3, 0x8b, 0x2e, 0x46, 0x1f, 0x44, 0xe5, 0xd0, 0x5e, 0x99, 0x4a, 0xb6, + /*a2a0:*/ 0x65, 0x90, 0x74, 0x2a, 0x8e, 0xbc, 0x1f, 0x17, 0x6a, 0x01, 0x05, 0xb7, 0xb5, 0xd2, 0xab, 0xf6, + /*a2b0:*/ 0xe6, 0x90, 0x5a, 0x07, 0xa1, 0x7c, 0x68, 0x9d, 0x7a, 0x88, 0x1c, 0x10, 0xa4, 0xe3, 0x7b, 0xbb, + /*a2c0:*/ 0xf4, 0xb0, 0x1f, 0x59, 0x96, 0x31, 0xea, 0xc5, 0xf2, 0x7e, 0x1e, 0x31, 0xa2, 0x94, 0x84, 0x3a, + /*a2d0:*/ 0xbd, 0x08, 0x8a, 0x3a, 0xa5, 0x6d, 0x0e, 0x45, 0x63, 0xd8, 0xe5, 0xf4, 0x53, 0xd5, 0x04, 0x64, + /*a2e0:*/ 0x43, 0x14, 0xed, 0x45, 0x96, 0x31, 0xdd, 0x73, 0xf8, 0xe5, 0x1f, 0x4f, 0xd7, 0x41, 0x9e, 0xed, + /*a2f0:*/ 0x87, 0xb0, 0x20, 0x8a, 0x51, 0xcf, 0x9e, 0x42, 0xe4, 0xb8, 0xce, 0x61, 0xbe, 0x3f, 0x03, 0xf6, + /*a300:*/ 0xdd, 0x55, 0x57, 0x17, 0x89, 0xe3, 0x11, 0x2f, 0x75, 0x54, 0x8f, 0xcc, 0x69, 0xc8, 0xd9, 0xd0, + /*a310:*/ 0x17, 0xfc, 0x6a, 0x4f, 0x11, 0x08, 0xc5, 0x67, 0xd4, 0xdd, 0x6e, 0x9c, 0xae, 0x18, 0x05, 0x50, + /*a320:*/ 0xd9, 0xb0, 0x75, 0x8c, 0x4a, 0x0a, 0xb9, 0x37, 0x91, 0x38, 0xab, 0x5e, 0xbc, 0xe0, 0x15, 0x07, + /*a330:*/ 0x10, 0xdd, 0x4c, 0xb2, 0xc7, 0x62, 0x57, 0x51, 0x72, 0xe9, 0x23, 0x50, 0x47, 0xf9, 0xc2, 0x31, + /*a340:*/ 0x40, 0x47, 0xfd, 0xe3, 0xf6, 0x45, 0xc4, 0xd8, 0x3b, 0x42, 0x47, 0xed, 0xd6, 0x36, 0x0a, 0x66, + /*a350:*/ 0x96, 0x1d, 0x3a, 0x27, 0x59, 0xa3, 0x51, 0xa6, 0xc0, 0x6c, 0xdb, 0x43, 0x0f, 0x86, 0xcb, 0xe6, + /*a360:*/ 0x01, 0x2d, 0x42, 0xcd, 0xa7, 0x63, 0x27, 0x0e, 0xd0, 0xdb, 0xa9, 0x39, 0xbe, 0x43, 0x78, 0x16, + /*a370:*/ 0x54, 0xcc, 0xff, 0x0d, 0x4c, 0x44, 0x22, 0x9e, 0xbf, 0x33, 0xbb, 0xb6, 0xd5, 0x9b, 0xe1, 0x80, + /*a380:*/ 0x26, 0x54, 0x76, 0xe7, 0xcb, 0x8b, 0x36, 0x9c, 0x85, 0xb7, 0xee, 0x62, 0x26, 0xa0, 0xd9, 0x99, + /*a390:*/ 0x1d, 0x8e, 0xfc, 0x66, 0xb8, 0x80, 0x64, 0x74, 0xc7, 0x5a, 0x51, 0x4e, 0x27, 0xac, 0x53, 0xb5, + /*a3a0:*/ 0x94, 0xf8, 0xab, 0xd9, 0xf9, 0x7b, 0xdd, 0xda, 0xac, 0xd6, 0xf8, 0x81, 0x8b, 0x1e, 0xd2, 0x11, + /*a3b0:*/ 0xc3, 0x2a, 0xc2, 0x32, 0xb5, 0x96, 0x11, 0xae, 0xa5, 0x44, 0xe8, 0xe3, 0x37, 0x2e, 0xe5, 0x46, + /*a3c0:*/ 0x89, 0xc1, 0x4a, 0x18, 0xdd, 0x0d, 0x08, 0x7c, 0x54, 0x4e, 0xe6, 0x48, 0x76, 0x74, 0x19, 0x7e, + /*a3d0:*/ 0x40, 0xf4, 0xf4, 0xe6, 0x04, 0x1c, 0xe2, 0x19, 0x2a, 0x87, 0x1d, 0x07, 0x3b, 0xf9, 0xf5, 0x72, + /*a3e0:*/ 0x67, 0xc5, 0xd5, 0x53, 0x5d, 0xa2, 0x6f, 0x87, 0x38, 0xe6, 0x3d, 0x7c, 0xf5, 0xcd, 0x02, 0xfc, + /*a3f0:*/ 0xf2, 0x74, 0x27, 0x62, 0x62, 0x71, 0x45, 0xaa, 0x1f, 0xbd, 0x49, 0x8c, 0xa3, 0xb8, 0xf7, 0x14, + /*a400:*/ 0xac, 0x49, 0xeb, 0xb3, 0x8f, 0x5f, 0x12, 0x46, 0x07, 0x28, 0x32, 0x4a, 0x50, 0x0e, 0x98, 0xb3, + /*a410:*/ 0x8f, 0x63, 0x38, 0x45, 0x76, 0xf1, 0xcf, 0x04, 0x86, 0x16, 0x2f, 0x10, 0xbd, 0xa0, 0xb1, 0xd1, + /*a420:*/ 0xe4, 0x32, 0x09, 0xa3, 0x0c, 0x4c, 0xf3, 0xb0, 0x3b, 0x7d, 0xa8, 0x9b, 0xf7, 0x6c, 0x11, 0xce, + /*a430:*/ 0xe4, 0x19, 0x8c, 0xbb, 0x27, 0x12, 0x73, 0x9f, 0xe9, 0x46, 0x4a, 0x82, 0xf9, 0x26, 0x30, 0x4e, + /*a440:*/ 0xef, 0x11, 0x55, 0x98, 0x2c, 0xa4, 0xf4, 0xa9, 0x42, 0x56, 0x67, 0x36, 0xbf, 0x8c, 0xe4, 0x8c, + /*a450:*/ 0xf8, 0x47, 0x8f, 0x73, 0x3a, 0x0c, 0xdd, 0xe6, 0x49, 0x29, 0x12, 0xf4, 0xc2, 0x7d, 0x72, 0x0f, + /*a460:*/ 0xa5, 0x5b, 0xb9, 0x19, 0xfe, 0x24, 0x65, 0xfd, 0x5a, 0xe6, 0x3f, 0xb0, 0x2c, 0x78, 0xec, 0x3f, + /*a470:*/ 0x1f, 0xc2, 0xa8, 0xd0, 0xdf, 0x1b, 0xa1, 0x9b, 0x47, 0x0b, 0x16, 0xb2, 0x1d, 0x75, 0xba, 0x23, + /*a480:*/ 0x20, 0x5a, 0x88, 0xca, 0x99, 0x54, 0x00, 0x8e, 0xd4, 0x9e, 0x31, 0x71, 0xdf, 0xb8, 0xf9, 0x23, + /*a490:*/ 0xc7, 0x88, 0x2a, 0x40, 0xc5, 0x5f, 0x17, 0x07, 0xe5, 0xab, 0x70, 0xff, 0xac, 0x79, 0xe8, 0x51, + /*a4a0:*/ 0x9c, 0x9f, 0x06, 0x43, 0x31, 0x7a, 0x0f, 0xa1, 0x12, 0x5a, 0x50, 0x86, 0x7a, 0x0f, 0xf9, 0xf2, + /*a4b0:*/ 0x13, 0x7d, 0x11, 0x72, 0x56, 0xa5, 0x54, 0x52, 0xb4, 0xcf, 0xb0, 0xdb, 0xce, 0xe1, 0x02, 0x8e, + /*a4c0:*/ 0xeb, 0xf8, 0xc6, 0xdd, 0xcf, 0x7f, 0x48, 0xa6, 0x18, 0xc1, 0x8e, 0xeb, 0xf7, 0xf0, 0x59, 0x2e, + /*a4d0:*/ 0xb5, 0xb0, 0x29, 0x7c, 0x46, 0x88, 0xfb, 0xf8, 0x5e, 0xb8, 0xd1, 0x96, 0x23, 0x8e, 0xaf, 0x06, + /*a4e0:*/ 0x44, 0x1b, 0xe0, 0xac, 0xf9, 0x5c, 0xa0, 0x2a, 0x05, 0xfc, 0x8f, 0x74, 0x4d, 0x42, 0x4c, 0xca, + /*a4f0:*/ 0xe8, 0x98, 0x96, 0x8c, 0x9b, 0x59, 0x92, 0xb1, 0x9a, 0x19, 0xed, 0x41, 0xc7, 0xe7, 0x61, 0x9b, + /*a500:*/ 0x30, 0x3c, 0x5b, 0x45, 0xcf, 0x90, 0xfb, 0xf4, 0x9f, 0xce, 0xc3, 0x83, 0x82, 0x70, 0xc2, 0xfd, + /*a510:*/ 0xb6, 0xcd, 0x94, 0x6a, 0x15, 0xa5, 0x30, 0x39, 0xa3, 0xbb, 0x0a, 0x70, 0x18, 0x69, 0x93, 0x7b, + /*a520:*/ 0x21, 0x1f, 0x7f, 0x71, 0x61, 0xb7, 0xa3, 0x21, 0xb1, 0xba, 0x65, 0x1d, 0x84, 0x39, 0xc7, 0x4e, + /*a530:*/ 0x21, 0x2f, 0xfe, 0x8a, 0x0f, 0xdf, 0x81, 0xbb, 0xb2, 0x72, 0x71, 0x25, 0xfa, 0xc2, 0xc5, 0xff, + /*a540:*/ 0x99, 0x6d, 0x1f, 0xa3, 0xfc, 0xf3, 0xec, 0x32, 0x92, 0xd3, 0x28, 0xf2, 0xc6, 0x26, 0x1f, 0xa0, + /*a550:*/ 0xe6, 0xdf, 0xc5, 0xb2, 0x6b, 0x17, 0x69, 0x64, 0xe1, 0xda, 0x68, 0x38, 0x14, 0xf5, 0x2e, 0xf5, + /*a560:*/ 0xaf, 0x57, 0x74, 0x44, 0xe1, 0x28, 0x6e, 0x2e, 0x28, 0x7f, 0x99, 0x1c, 0x23, 0x26, 0x96, 0x38, + /*a570:*/ 0xcb, 0x70, 0x62, 0x53, 0x1b, 0x70, 0xb3, 0x1b, 0xbb, 0x9a, 0x9e, 0x31, 0xfd, 0x6f, 0x74, 0x84, + /*a580:*/ 0x5c, 0xd5, 0xf7, 0x10, 0xf7, 0x76, 0xd4, 0x22, 0xe6, 0x5e, 0x4b, 0xad, 0x41, 0xe6, 0x23, 0xe5, + /*a590:*/ 0x36, 0xf1, 0x2b, 0x57, 0x87, 0x97, 0x60, 0x46, 0x9d, 0xea, 0x18, 0x25, 0xcf, 0x33, 0x4f, 0x68, + /*a5a0:*/ 0x4d, 0x9f, 0x61, 0x59, 0x09, 0xf4, 0x45, 0xa3, 0x03, 0x76, 0x68, 0x24, 0x18, 0x36, 0xbe, 0xb7, + /*a5b0:*/ 0x78, 0xf7, 0xdc, 0x21, 0xce, 0x36, 0x28, 0xd2, 0x79, 0xb9, 0xda, 0xf3, 0x7f, 0xc0, 0x74, 0x55, + /*a5c0:*/ 0x00, 0x38, 0x57, 0x73, 0x9b, 0x1e, 0x80, 0x84, 0x55, 0xfc, 0x35, 0x1c, 0xbd, 0x8c, 0x27, 0xf0, + /*a5d0:*/ 0x6d, 0xef, 0x8a, 0x6a, 0x3a, 0x76, 0x77, 0xd1, 0xf3, 0xf7, 0xbc, 0xdd, 0x97, 0x0b, 0x68, 0xcc, + /*a5e0:*/ 0x2b, 0xdc, 0x1f, 0xde, 0x52, 0x66, 0x67, 0x7d, 0x72, 0x4c, 0x2c, 0xa8, 0xf1, 0x8d, 0x6d, 0xa3, + /*a5f0:*/ 0x4c, 0x33, 0xcf, 0xa9, 0x25, 0x6b, 0x6e, 0xe0, 0x48, 0x81, 0x51, 0x85, 0xf4, 0x33, 0xda, 0x32, + /*a600:*/ 0x7b, 0xdd, 0xa8, 0x0e, 0x94, 0x08, 0xc2, 0x16, 0xd0, 0xdd, 0x93, 0x22, 0xdc, 0x90, 0x04, 0xc9, + /*a610:*/ 0xee, 0x2a, 0xcd, 0x58, 0xac, 0xf7, 0x9a, 0xe2, 0xd9, 0x0a, 0x7b, 0x18, 0x9f, 0x85, 0xfc, 0x8e, + /*a620:*/ 0xb6, 0x5c, 0x05, 0x46, 0x94, 0x55, 0xd5, 0x28, 0x84, 0x0a, 0xb1, 0x35, 0x8d, 0x38, 0x34, 0xd5, + /*a630:*/ 0xd6, 0x2b, 0x66, 0xd6, 0xc1, 0x19, 0x5d, 0x99, 0x2f, 0xbe, 0x7f, 0xd9, 0x53, 0xa5, 0x6f, 0xa0, + /*a640:*/ 0x18, 0xb5, 0x77, 0x12, 0x56, 0xdd, 0x64, 0x4c, 0x84, 0x43, 0xa6, 0x05, 0x29, 0xf2, 0x70, 0x88, + /*a650:*/ 0x64, 0x1e, 0x28, 0x35, 0x31, 0x2d, 0x9a, 0xa0, 0x1e, 0x05, 0x53, 0xa2, 0xf1, 0xa9, 0xa8, 0xae, + /*a660:*/ 0x6d, 0x93, 0x13, 0x2d, 0xeb, 0x94, 0xe9, 0x7f, 0x9e, 0x05, 0x52, 0x18, 0xa0, 0xaa, 0x4d, 0x25, + /*a670:*/ 0xf2, 0x1c, 0xa6, 0xf4, 0x38, 0x14, 0x36, 0xb6, 0x0c, 0x5f, 0xb3, 0x26, 0x1f, 0x35, 0x3d, 0x6d, + /*a680:*/ 0xa2, 0xa1, 0x06, 0x41, 0x44, 0xf2, 0xc2, 0xee, 0x8a, 0xf0, 0x5b, 0x4c, 0x15, 0xa2, 0x1d, 0xd1, + /*a690:*/ 0xd3, 0x44, 0x89, 0x49, 0x92, 0xe3, 0x1c, 0x15, 0x69, 0x43, 0xab, 0x10, 0xce, 0x16, 0xcf, 0x82, + /*a6a0:*/ 0x5b, 0x81, 0x1b, 0x86, 0x8b, 0x71, 0x79, 0x47, 0x49, 0x87, 0x8f, 0x73, 0x7a, 0xc2, 0xda, 0xb6, + /*a6b0:*/ 0x68, 0x45, 0x4d, 0x41, 0xbc, 0xec, 0x5c, 0x4a, 0xb1, 0x8b, 0x2d, 0xc2, 0x1f, 0x62, 0xd8, 0x8c, + /*a6c0:*/ 0x9e, 0x0d, 0x00, 0x5b, 0x20, 0x23, 0x39, 0xfe, 0x8c, 0x1c, 0x1d, 0xf6, 0xb8, 0x86, 0xb4, 0x2b, + /*a6d0:*/ 0xe2, 0xe9, 0x79, 0xc4, 0x30, 0xcf, 0xd8, 0xc4, 0x9d, 0xcf, 0x9d, 0xb2, 0xd3, 0x50, 0x2b, 0xdc, + /*a6e0:*/ 0xae, 0xfb, 0x67, 0x50, 0x73, 0x86, 0x0c, 0x01, 0x31, 0x8e, 0xb0, 0x98, 0x96, 0xe9, 0x3c, 0x58, + /*a6f0:*/ 0x08, 0x68, 0x0a, 0x63, 0xd2, 0xdf, 0xc7, 0x2e, 0xd5, 0xed, 0x14, 0xeb, 0x61, 0x56, 0x63, 0xa1, + /*a700:*/ 0xc1, 0xa9, 0x26, 0x25, 0xe8, 0x6c, 0xea, 0xa0, 0x5a, 0x8e, 0xaf, 0x5d, 0xca, 0x06, 0xa4, 0x64, + /*a710:*/ 0xad, 0xf8, 0xbd, 0x90, 0xbb, 0xbf, 0xb7, 0xb6, 0x25, 0x5d, 0x09, 0x39, 0x82, 0x01, 0x7d, 0xfb, + /*a720:*/ 0x31, 0x3c, 0x82, 0x2b, 0x40, 0x63, 0x01, 0x80, 0x4e, 0x7c, 0xe8, 0x6c, 0x9b, 0xef, 0x12, 0x2c, + /*a730:*/ 0x8d, 0x63, 0xff, 0xf5, 0xad, 0x77, 0x59, 0x39, 0x20, 0x99, 0x85, 0x51, 0xe7, 0x75, 0x07, 0xac, + /*a740:*/ 0xe8, 0x30, 0xa4, 0xc9, 0xbf, 0x9f, 0xa4, 0x1f, 0x11, 0x98, 0x01, 0x9b, 0xfb, 0x96, 0x7d, 0xa3, + /*a750:*/ 0xaf, 0x73, 0x15, 0x7b, 0xce, 0x7a, 0xce, 0x2c, 0x00, 0xa1, 0x0f, 0x3c, 0x49, 0x6c, 0x62, 0x4c, + /*a760:*/ 0x7c, 0xec, 0xbb, 0x44, 0xb5, 0xed, 0x16, 0x9d, 0x57, 0x2b, 0x76, 0x56, 0x57, 0x54, 0x8d, 0xd7, + /*a770:*/ 0xa1, 0x6c, 0xd8, 0x0f, 0xb5, 0x13, 0xe0, 0x56, 0xb6, 0xea, 0xaf, 0x60, 0x13, 0xd1, 0xf8, 0xbc, + /*a780:*/ 0x58, 0xa8, 0x52, 0x5e, 0x42, 0x1b, 0x70, 0x7d, 0x63, 0x7d, 0x8b, 0x69, 0x82, 0xc3, 0xab, 0x38, + /*a790:*/ 0x64, 0x82, 0xef, 0x3f, 0xa9, 0xd9, 0x51, 0x5c, 0x4b, 0x88, 0x35, 0x17, 0xc4, 0xd2, 0x2d, 0xa5, + /*a7a0:*/ 0x46, 0xb0, 0x11, 0xcf, 0x6d, 0x94, 0xa3, 0x93, 0x93, 0xb7, 0xa7, 0xf8, 0x09, 0x39, 0x03, 0x1c, + /*a7b0:*/ 0x15, 0xba, 0x34, 0x3e, 0xe0, 0x08, 0xda, 0x0a, 0x93, 0xa2, 0x35, 0x23, 0x9b, 0xa0, 0x49, 0x7e, + /*a7c0:*/ 0x58, 0xe4, 0x6d, 0xef, 0x21, 0xbd, 0xfb, 0x15, 0xe5, 0xb2, 0x26, 0xb9, 0xd9, 0xab, 0xef, 0x0e, + /*a7d0:*/ 0x12, 0xfc, 0x24, 0xd6, 0x5c, 0xfd, 0x0e, 0xf2, 0x00, 0x12, 0x0f, 0x22, 0x0c, 0x53, 0x54, 0xdd, + /*a7e0:*/ 0xe6, 0x04, 0x61, 0xcb, 0xf5, 0x4b, 0xd0, 0x91, 0x24, 0x7e, 0x91, 0x95, 0x07, 0x41, 0x4c, 0x32, + /*a7f0:*/ 0x64, 0x44, 0x4e, 0xdc, 0x0b, 0xf4, 0x8a, 0xb5, 0x75, 0xc8, 0x73, 0xee, 0xc3, 0x7d, 0xb0, 0xbf, + /*a800:*/ 0x63, 0x7d, 0x69, 0x96, 0x58, 0x9c, 0x10, 0xed, 0xe6, 0x5a, 0x55, 0xf7, 0x20, 0xda, 0xbd, 0x1b, + /*a810:*/ 0xba, 0x0a, 0xab, 0x36, 0x1f, 0xe3, 0xe0, 0x3c, 0x20, 0xae, 0x90, 0x60, 0xcd, 0xe0, 0x29, 0xe7, + /*a820:*/ 0x41, 0x27, 0x68, 0x1c, 0xf3, 0xcc, 0xb7, 0x79, 0xfb, 0x06, 0x48, 0x89, 0x61, 0xb2, 0x02, 0xb2, + /*a830:*/ 0xcf, 0x61, 0xe9, 0x77, 0x9f, 0x8d, 0x7e, 0x19, 0x2b, 0xd0, 0x2d, 0xf9, 0x61, 0x29, 0xc9, 0x46, + /*a840:*/ 0x84, 0xd1, 0x54, 0x4d, 0x83, 0xb0, 0x8c, 0x33, 0x4f, 0xa5, 0xeb, 0x98, 0xa0, 0x41, 0x5b, 0xa0, + /*a850:*/ 0x04, 0x09, 0x37, 0xc2, 0xa7, 0x5f, 0xdf, 0x63, 0xa8, 0x82, 0x78, 0xf9, 0xea, 0xfc, 0xde, 0xa5, + /*a860:*/ 0x5c, 0xe4, 0xd9, 0x80, 0x54, 0x78, 0x34, 0x77, 0x59, 0x2b, 0xbb, 0x38, 0x6e, 0xdd, 0x57, 0x9e, + /*a870:*/ 0xd7, 0xe3, 0x9c, 0x67, 0x2e, 0xc1, 0xa1, 0x9d, 0xf2, 0xa1, 0xb8, 0x99, 0xc0, 0x89, 0x83, 0x2c, + /*a880:*/ 0x03, 0xfc, 0xc0, 0x03, 0x77, 0x06, 0xc9, 0xbe, 0x8a, 0xe6, 0xaa, 0x42, 0x95, 0x43, 0x57, 0x30, + /*a890:*/ 0xdf, 0xc0, 0x71, 0x9b, 0x42, 0x39, 0x67, 0x35, 0xc1, 0xa8, 0xb0, 0x16, 0xe3, 0xc3, 0xa8, 0x20, + /*a8a0:*/ 0xd6, 0x11, 0xed, 0x12, 0x42, 0x62, 0x2e, 0x2b, 0x17, 0x43, 0x3a, 0x27, 0x0d, 0x83, 0xd6, 0x87, + /*a8b0:*/ 0x70, 0x0e, 0x84, 0x01, 0xfd, 0xa1, 0xd9, 0x2b, 0x5c, 0xdb, 0xf9, 0xbe, 0x27, 0xd3, 0x05, 0x7a, + /*a8c0:*/ 0x89, 0x77, 0x23, 0x7a, 0x0c, 0x4c, 0x3f, 0xb3, 0xbc, 0xc1, 0x80, 0xde, 0x88, 0x68, 0x6c, 0xbe, + /*a8d0:*/ 0x6b, 0xa0, 0xf4, 0xfe, 0x9d, 0xde, 0xa4, 0x8d, 0xc8, 0xfe, 0x8f, 0x0d, 0xf8, 0xfb, 0xe3, 0x33, + /*a8e0:*/ 0xd9, 0x9f, 0x38, 0x44, 0xf0, 0x1e, 0x13, 0x87, 0x4a, 0x35, 0x79, 0xbd, 0x56, 0x77, 0x4d, 0x2e, + /*a8f0:*/ 0xed, 0x44, 0x05, 0x70, 0xcb, 0xee, 0x56, 0xb8, 0x40, 0xc4, 0x29, 0x1a, 0xaf, 0x14, 0xd3, 0xd3, + /*a900:*/ 0x18, 0x34, 0x77, 0x79, 0x7c, 0x69, 0x36, 0xbc, 0x18, 0xea, 0xc8, 0x5e, 0xdf, 0x17, 0xfe, 0xf0, + /*a910:*/ 0x22, 0xd7, 0x5c, 0xa7, 0x24, 0xd8, 0xe9, 0x85, 0x2f, 0x08, 0xef, 0x68, 0x9a, 0xe9, 0x81, 0x80, + /*a920:*/ 0xe2, 0xb2, 0x5d, 0x11, 0x30, 0xf0, 0xa9, 0xab, 0x6b, 0xee, 0x2c, 0x62, 0x0a, 0xde, 0xec, 0x4e, + /*a930:*/ 0xd0, 0x25, 0xbb, 0xd5, 0xc5, 0x2d, 0xa8, 0xea, 0x1e, 0x7b, 0xfc, 0x84, 0x4b, 0x38, 0xb8, 0x90, + /*a940:*/ 0x8d, 0x4b, 0x3d, 0x7c, 0xa6, 0x8d, 0x1a, 0x73, 0x0f, 0x72, 0xb9, 0x2a, 0xc2, 0x31, 0x3c, 0xa5, + /*a950:*/ 0x18, 0xfe, 0x02, 0xb6, 0x2f, 0xfa, 0x3c, 0x23, 0x99, 0x73, 0x93, 0xcf, 0x14, 0x06, 0xb8, 0x76, + /*a960:*/ 0xf5, 0x66, 0xb2, 0xb8, 0x04, 0xd0, 0x10, 0x13, 0x38, 0x41, 0x17, 0x59, 0x20, 0x63, 0x09, 0xee, + /*a970:*/ 0x1b, 0xae, 0xc0, 0xea, 0xf3, 0xbf, 0xca, 0x9f, 0x25, 0x94, 0x0c, 0x96, 0x3f, 0x2d, 0x99, 0xc3, + /*a980:*/ 0x42, 0xe4, 0xe0, 0x92, 0x9c, 0x13, 0x0d, 0xb6, 0x87, 0xd6, 0x42, 0xbd, 0x35, 0xb2, 0x72, 0x57, + /*a990:*/ 0xb4, 0x52, 0x16, 0xa3, 0x86, 0x82, 0x21, 0x67, 0x5f, 0xff, 0x3d, 0x58, 0xcd, 0xb1, 0x9e, 0xbd, + /*a9a0:*/ 0x15, 0x87, 0x1e, 0x2f, 0x8d, 0x98, 0xcf, 0x4b, 0x93, 0x7b, 0x3f, 0xdd, 0x7c, 0x2b, 0xc5, 0x57, + /*a9b0:*/ 0x9b, 0x98, 0xfb, 0xc7, 0x53, 0xc3, 0x1f, 0xae, 0x9d, 0xd6, 0xed, 0xc8, 0xd0, 0xb6, 0x34, 0x21, + /*a9c0:*/ 0x94, 0xf3, 0x95, 0xfb, 0xf0, 0x80, 0x24, 0x98, 0x0f, 0xd1, 0xd3, 0xe0, 0xfd, 0xc5, 0xcd, 0xa6, + /*a9d0:*/ 0xda, 0xfb, 0x58, 0xb0, 0x1b, 0x9a, 0x24, 0x59, 0xaf, 0x55, 0xa6, 0x82, 0xab, 0x21, 0x40, 0x4a, + /*a9e0:*/ 0xaa, 0x4e, 0xcd, 0x23, 0x7d, 0x2b, 0xa3, 0x01, 0x18, 0x63, 0xfd, 0x2f, 0x12, 0xd3, 0x2b, 0x25, + /*a9f0:*/ 0xbd, 0xb0, 0x10, 0x59, 0x7c, 0x85, 0x5d, 0xdb, 0x28, 0x34, 0xd1, 0x1d, 0x9d, 0x50, 0x78, 0xef, + /*aa00:*/ 0x84, 0x97, 0x1a, 0x49, 0x1a, 0x8b, 0xd3, 0x88, 0xbe, 0x67, 0xac, 0x4a, 0x1f, 0x1b, 0x15, 0x21, + /*aa10:*/ 0x61, 0x85, 0xf3, 0x74, 0x48, 0x20, 0xe1, 0x55, 0x16, 0x2a, 0xf3, 0xdd, 0x5c, 0x9e, 0xc9, 0x13, + /*aa20:*/ 0x55, 0x70, 0xf7, 0xc1, 0x07, 0xcb, 0xa2, 0xa5, 0x7d, 0x7d, 0xcb, 0xbb, 0x56, 0x07, 0x7a, 0x5a, + /*aa30:*/ 0xa4, 0xf7, 0x1b, 0x28, 0x0a, 0x89, 0xef, 0x5a, 0x28, 0x01, 0xe0, 0xbb, 0x67, 0x9d, 0xab, 0x2f, + /*aa40:*/ 0xb8, 0x71, 0x48, 0x6c, 0x6e, 0x98, 0xc5, 0x7d, 0x81, 0xcd, 0xba, 0xc2, 0x70, 0x63, 0x9e, 0x87, + /*aa50:*/ 0x14, 0x54, 0xbb, 0xbb, 0xd6, 0x7b, 0xb1, 0xaa, 0xae, 0x22, 0xba, 0x87, 0x80, 0x59, 0x6f, 0x23, + /*aa60:*/ 0x06, 0x5c, 0x6c, 0x1d, 0x34, 0x70, 0xce, 0xfd, 0x37, 0x73, 0xff, 0x85, 0x92, 0xae, 0x13, 0xb7, + /*aa70:*/ 0x67, 0x5d, 0x32, 0xff, 0x39, 0x8e, 0x52, 0xaa, 0x3c, 0x99, 0xa7, 0xe9, 0x27, 0x4e, 0xbb, 0x58, + /*aa80:*/ 0x78, 0xa2, 0x85, 0x36, 0xad, 0xa5, 0xbe, 0xa9, 0x78, 0xc4, 0xae, 0x78, 0xef, 0xea, 0x18, 0x24, + /*aa90:*/ 0x50, 0x4a, 0x56, 0x85, 0x6c, 0xdc, 0x69, 0x14, 0xe2, 0xe0, 0xb3, 0x8d, 0x2e, 0xdf, 0x62, 0x47, + /*aaa0:*/ 0xcf, 0xf2, 0xee, 0xe2, 0x0b, 0xab, 0x08, 0xf0, 0x89, 0x29, 0x91, 0x12, 0xfc, 0x9f, 0x4c, 0xb9, + /*aab0:*/ 0x0c, 0x92, 0xd3, 0x0d, 0x41, 0x72, 0xce, 0x67, 0xbf, 0x72, 0x4a, 0xd5, 0x10, 0x3b, 0x7b, 0xa0, + /*aac0:*/ 0x6e, 0xf4, 0x51, 0x63, 0x47, 0x74, 0xd9, 0x5e, 0x0b, 0xb3, 0x3e, 0x56, 0xb9, 0x90, 0x30, 0xd8, + /*aad0:*/ 0xa6, 0x54, 0xf3, 0x87, 0x87, 0xf2, 0xca, 0xa8, 0x81, 0x72, 0xea, 0x07, 0x34, 0x2f, 0xb2, 0x11, + /*aae0:*/ 0x23, 0x49, 0xf5, 0x9d, 0x6c, 0x52, 0xd6, 0x41, 0x71, 0xe4, 0x2c, 0xc1, 0x4c, 0x30, 0x9e, 0xf3, + /*aaf0:*/ 0xb2, 0x21, 0x21, 0x3e, 0x1f, 0x12, 0x7b, 0x6b, 0xd1, 0xc7, 0xe8, 0xd0, 0x74, 0x1c, 0xf2, 0x46, + /*ab00:*/ 0xcc, 0x12, 0x89, 0x97, 0x9e, 0x92, 0x7f, 0x89, 0xdb, 0x82, 0x1c, 0xd4, 0xe8, 0xcd, 0x36, 0x76, + /*ab10:*/ 0x6c, 0x09, 0xe3, 0x15, 0x2e, 0x6a, 0xbf, 0x46, 0x28, 0x95, 0x2f, 0x01, 0x92, 0x00, 0x68, 0x6e, + /*ab20:*/ 0x5d, 0xbf, 0x3d, 0xc1, 0x29, 0xbf, 0x09, 0x4a, 0x08, 0x74, 0x79, 0x48, 0xb4, 0x5e, 0x5f, 0x52, + /*ab30:*/ 0x55, 0x0c, 0x41, 0x69, 0x3d, 0x48, 0xf6, 0xf0, 0x9b, 0x63, 0x1f, 0xaa, 0x6e, 0xfd, 0x7f, 0x0f, + /*ab40:*/ 0x83, 0x29, 0x68, 0xd7, 0xb5, 0xa6, 0x12, 0x05, 0x8f, 0x43, 0x07, 0xbc, 0x25, 0xd2, 0xec, 0xb3, + /*ab50:*/ 0xab, 0xc9, 0xf3, 0x1f, 0xbb, 0xc2, 0xe3, 0x78, 0x4e, 0xb6, 0x35, 0xfb, 0x94, 0xde, 0xf0, 0xd9, + /*ab60:*/ 0xe6, 0xec, 0xf8, 0xae, 0xf8, 0x46, 0x1a, 0x83, 0xd3, 0xdb, 0xfe, 0xbc, 0x80, 0x65, 0x4d, 0xc7, + /*ab70:*/ 0x83, 0x75, 0xb2, 0xdd, 0x77, 0xc3, 0x46, 0xd4, 0x32, 0xa4, 0x54, 0xef, 0x9b, 0xa3, 0x76, 0xb7, + /*ab80:*/ 0x9e, 0x60, 0x14, 0x6d, 0xd7, 0xb1, 0x47, 0x82, 0xef, 0x2c, 0xcf, 0x88, 0x17, 0x5c, 0xa1, 0xe6, + /*ab90:*/ 0x60, 0x22, 0xdb, 0x85, 0x18, 0x11, 0x08, 0xd0, 0x59, 0xc6, 0xe9, 0x19, 0x55, 0x3c, 0x81, 0xf4, + /*aba0:*/ 0x6d, 0xec, 0x1b, 0x88, 0xd6, 0xb6, 0x7a, 0x62, 0x5d, 0x7a, 0xc4, 0xf1, 0xf0, 0xa0, 0x09, 0x1a, + /*abb0:*/ 0xbc, 0xdf, 0x3c, 0xb0, 0x4f, 0x2b, 0xe1, 0x2e, 0x44, 0x3d, 0x9d, 0x0a, 0xb1, 0x1d, 0x66, 0x62, + /*abc0:*/ 0xbe, 0xbf, 0xe2, 0x2b, 0x66, 0xae, 0xa1, 0x35, 0x04, 0x63, 0x77, 0x97, 0xc9, 0x0b, 0xab, 0xeb, + /*abd0:*/ 0xf0, 0x61, 0xf2, 0x1f, 0xdb, 0x60, 0x51, 0x6f, 0xda, 0xd6, 0x19, 0xdf, 0x5b, 0xad, 0x6e, 0x02, + /*abe0:*/ 0x9c, 0xc8, 0xce, 0x0c, 0xa7, 0xcb, 0x93, 0x3d, 0x3c, 0xff, 0x9e, 0x88, 0xfa, 0xf9, 0x9c, 0x73, + /*abf0:*/ 0x9f, 0x3e, 0xbb, 0xa9, 0x40, 0x2c, 0x88, 0x4f, 0x19, 0x59, 0x1a, 0x42, 0x13, 0xca, 0x47, 0xb8, + /*ac00:*/ 0x46, 0x77, 0x49, 0xa0, 0xb7, 0xec, 0x73, 0x72, 0xb1, 0x9b, 0x61, 0x07, 0x8a, 0x61, 0x08, 0x1a, + /*ac10:*/ 0x4a, 0x59, 0x63, 0x60, 0x2a, 0x0f, 0x5a, 0xdf, 0x3c, 0x23, 0x83, 0x47, 0x32, 0x37, 0xde, 0x8a, + /*ac20:*/ 0x30, 0x10, 0x24, 0x3f, 0x31, 0x93, 0xcb, 0xca, 0xfa, 0x5c, 0xf0, 0xf9, 0x28, 0x50, 0x40, 0x2a, + /*ac30:*/ 0x62, 0xfd, 0x0b, 0x22, 0x52, 0x0b, 0xa4, 0x4d, 0xc4, 0xbc, 0x88, 0x32, 0x0f, 0x85, 0xab, 0xc9, + /*ac40:*/ 0x5c, 0x55, 0xc5, 0x63, 0xbb, 0x2f, 0xfb, 0x41, 0xf6, 0x52, 0xd7, 0x67, 0x35, 0x96, 0x0e, 0xf6, + /*ac50:*/ 0x46, 0x10, 0xaa, 0x92, 0x0a, 0xdf, 0xdf, 0xcb, 0x9b, 0xa7, 0xaa, 0x71, 0xe1, 0xd8, 0xfe, 0x03, + /*ac60:*/ 0xef, 0x25, 0x22, 0x72, 0x86, 0x42, 0x72, 0x00, 0xfc, 0xd2, 0x13, 0xbe, 0x03, 0x1c, 0x4c, 0x4d, + /*ac70:*/ 0x48, 0xb3, 0xaf, 0x7b, 0xb4, 0xa0, 0xe7, 0x0f, 0xc0, 0x40, 0x2b, 0x99, 0xfe, 0x6a, 0x8d, 0x82, + /*ac80:*/ 0x72, 0xef, 0x2b, 0x76, 0xdf, 0x82, 0x74, 0xd2, 0x17, 0xd0, 0xbc, 0xcf, 0x54, 0xb3, 0x6f, 0x34, + /*ac90:*/ 0xd7, 0x86, 0x90, 0x63, 0x1f, 0xdc, 0x54, 0xa6, 0xa7, 0x77, 0x4d, 0x84, 0x0d, 0x5a, 0x02, 0xc1, + /*aca0:*/ 0x3c, 0xd2, 0xc0, 0xc6, 0x1d, 0xa5, 0x60, 0x9b, 0x22, 0x08, 0x44, 0x01, 0xb8, 0x1a, 0xe4, 0x59, + /*acb0:*/ 0x63, 0x2b, 0x48, 0xed, 0xf1, 0x1f, 0x86, 0x18, 0x9c, 0x27, 0xe3, 0x11, 0xb8, 0x03, 0x1a, 0x28, + /*acc0:*/ 0xbb, 0x16, 0x90, 0x80, 0x8e, 0xc9, 0xd7, 0x57, 0x33, 0x82, 0x06, 0x44, 0x2b, 0x3f, 0xee, 0xbc, + /*acd0:*/ 0x4a, 0x19, 0x73, 0x96, 0x09, 0xb9, 0x26, 0x08, 0x57, 0xe9, 0x66, 0x86, 0x33, 0xfe, 0xf0, 0xad, + /*ace0:*/ 0xeb, 0x5f, 0x46, 0xd3, 0x8c, 0x6e, 0xa9, 0xeb, 0x0f, 0x58, 0x27, 0x1d, 0x37, 0x42, 0xd9, 0xbb, + /*acf0:*/ 0x65, 0x6d, 0xf0, 0x75, 0x89, 0xfb, 0x5e, 0x4d, 0xd7, 0x6d, 0x09, 0xb4, 0x42, 0x7e, 0x7c, 0x94, + /*ad00:*/ 0xa5, 0x34, 0x36, 0x13, 0x88, 0x1a, 0x12, 0x2b, 0x02, 0xd4, 0x38, 0x00, 0x25, 0xc4, 0x95, 0xe6, + /*ad10:*/ 0x3c, 0x9b, 0xbe, 0x55, 0x5d, 0x58, 0x6c, 0xef, 0x36, 0xbf, 0xeb, 0x90, 0x74, 0x93, 0x14, 0x07, + /*ad20:*/ 0xad, 0xfa, 0x42, 0x13, 0x7b, 0x13, 0x17, 0x1a, 0x9b, 0x0f, 0x36, 0xee, 0x61, 0x76, 0xe2, 0x85, + /*ad30:*/ 0x99, 0x42, 0x29, 0x50, 0x20, 0x7e, 0x3f, 0x09, 0xaf, 0x3a, 0xe5, 0x3f, 0x53, 0xf6, 0x76, 0x79, + /*ad40:*/ 0xfb, 0x8c, 0x73, 0xc9, 0x83, 0xf6, 0x1c, 0x21, 0xec, 0x05, 0x07, 0x10, 0xbc, 0x16, 0x8e, 0x65, + /*ad50:*/ 0x7f, 0xfe, 0x4a, 0x3e, 0xbe, 0xf7, 0x74, 0x47, 0x51, 0x89, 0x5f, 0xad, 0xc1, 0x9e, 0xa1, 0x6a, + /*ad60:*/ 0x69, 0x33, 0x5c, 0x10, 0x48, 0x10, 0xbb, 0x49, 0x98, 0x63, 0x04, 0xe4, 0x19, 0xfa, 0x45, 0x93, + /*ad70:*/ 0x09, 0x0d, 0xda, 0x37, 0x2e, 0xff, 0x4f, 0xaf, 0xdc, 0x3d, 0x71, 0x3e, 0x0c, 0x97, 0x3b, 0x8f, + /*ad80:*/ 0x80, 0xfc, 0x34, 0x24, 0x4e, 0x37, 0xaa, 0x11, 0xd0, 0x4a, 0x57, 0x9b, 0xa6, 0x6c, 0x4d, 0xc1, + /*ad90:*/ 0x65, 0x07, 0x6d, 0x1c, 0x9e, 0x06, 0xd9, 0xe3, 0x1a, 0x3f, 0xe0, 0xf1, 0x36, 0x9e, 0x74, 0x65, + /*ada0:*/ 0x5c, 0x75, 0xd2, 0xf5, 0xd9, 0xbc, 0x3c, 0x4f, 0x24, 0x4e, 0x04, 0x62, 0x04, 0x97, 0x3e, 0x6e, + /*adb0:*/ 0xc4, 0x01, 0x4c, 0x88, 0xfb, 0xb0, 0xdf, 0x7d, 0x45, 0xcd, 0xa0, 0xca, 0x91, 0x96, 0x11, 0x6e, + /*adc0:*/ 0x56, 0x5d, 0xe5, 0xd1, 0xf3, 0x2c, 0x4a, 0xf6, 0x07, 0xb3, 0x6d, 0xb6, 0x6b, 0x98, 0x7b, 0x9b, + /*add0:*/ 0x80, 0x7a, 0x02, 0x83, 0xc7, 0xef, 0x0e, 0x00, 0x81, 0xfc, 0x95, 0x64, 0xe4, 0xc0, 0xb3, 0xc1, + /*ade0:*/ 0x2f, 0xfe, 0x4a, 0x97, 0xa1, 0x1c, 0x68, 0xde, 0xee, 0xc6, 0xcc, 0x23, 0x33, 0x5c, 0x2b, 0xcd, + /*adf0:*/ 0xa1, 0x4b, 0xff, 0x97, 0x08, 0x01, 0x51, 0x5a, 0xc1, 0x69, 0x6a, 0xbc, 0xac, 0x3f, 0xc4, 0xf3, + /*ae00:*/ 0x5d, 0x75, 0x53, 0x23, 0x8d, 0xb5, 0x43, 0x8d, 0x2f, 0x41, 0x05, 0xd2, 0x7f, 0x88, 0xdd, 0x9e, + /*ae10:*/ 0xb8, 0x5b, 0x13, 0x34, 0x1a, 0x74, 0x5c, 0x6e, 0x81, 0xd3, 0x65, 0x6e, 0x02, 0xcf, 0xf1, 0xf2, + /*ae20:*/ 0xf2, 0x87, 0xca, 0xab, 0x11, 0x6e, 0xea, 0xf6, 0xa4, 0xa8, 0x82, 0xa8, 0x00, 0xbd, 0xc7, 0x80, + /*ae30:*/ 0x4f, 0xeb, 0x73, 0xbc, 0x9f, 0xbb, 0xc4, 0x17, 0x58, 0x68, 0x1f, 0x36, 0xfb, 0x3c, 0xda, 0xf4, + /*ae40:*/ 0xf4, 0xea, 0x6a, 0xce, 0x79, 0xe9, 0xb1, 0x83, 0x6d, 0x27, 0x22, 0xdc, 0x01, 0xf8, 0xec, 0x58, + /*ae50:*/ 0x6b, 0x58, 0x03, 0x24, 0x50, 0xeb, 0xed, 0xa9, 0x1c, 0x01, 0x1a, 0x7c, 0x50, 0xe3, 0x5e, 0x78, + /*ae60:*/ 0x90, 0xe8, 0x50, 0xfd, 0xe8, 0x34, 0xfc, 0x7c, 0x3e, 0x7b, 0x61, 0xd5, 0x93, 0x65, 0x47, 0xed, + /*ae70:*/ 0xfe, 0x63, 0xc1, 0xd1, 0x31, 0x86, 0x78, 0xa1, 0x68, 0xee, 0xfa, 0x4f, 0x5c, 0xf2, 0x45, 0x90, + /*ae80:*/ 0x7c, 0xb9, 0x6d, 0x98, 0x89, 0x3f, 0x3e, 0xc8, 0x0d, 0x02, 0xa2, 0x2e, 0xfd, 0x96, 0x3e, 0x16, + /*ae90:*/ 0xd6, 0xc8, 0x46, 0x89, 0xf5, 0x82, 0x71, 0xe7, 0x93, 0xcb, 0x57, 0x14, 0xce, 0xef, 0x51, 0x53, + /*aea0:*/ 0xaa, 0x3d, 0xe7, 0xdc, 0xbf, 0x14, 0xc1, 0x14, 0xdc, 0x24, 0xd1, 0xc9, 0x61, 0xb3, 0x0a, 0x9d, + /*aeb0:*/ 0xca, 0xcb, 0x00, 0x49, 0xc0, 0x9a, 0xbe, 0x59, 0x10, 0x9a, 0x0a, 0x75, 0x0a, 0x7a, 0x2d, 0xe2, + /*aec0:*/ 0x87, 0xe5, 0xb1, 0x32, 0x55, 0x8d, 0xd2, 0x3a, 0x0b, 0x3b, 0xd9, 0x16, 0xb1, 0x78, 0xa8, 0x83, + /*aed0:*/ 0x13, 0x30, 0x2f, 0xf8, 0xa0, 0x91, 0x55, 0xc5, 0x0b, 0x5e, 0x4a, 0x90, 0x1c, 0x10, 0x7c, 0x5a, + /*aee0:*/ 0x8e, 0x4b, 0x4b, 0xea, 0x12, 0xe2, 0x51, 0xfa, 0xc4, 0x5a, 0x52, 0x33, 0xff, 0xf9, 0x18, 0xc1, + /*aef0:*/ 0x5b, 0xa1, 0x29, 0xeb, 0x3f, 0xab, 0xf8, 0x1c, 0xa2, 0x7e, 0x97, 0xfd, 0x59, 0x04, 0x1a, 0x0c, + /*af00:*/ 0x60, 0x5e, 0x3d, 0x23, 0x5e, 0x0b, 0x8e, 0x2b, 0xf5, 0x57, 0xe7, 0x06, 0x71, 0x11, 0x68, 0xb6, + /*af10:*/ 0x5a, 0xc4, 0x49, 0xfa, 0x24, 0x17, 0xe7, 0xf7, 0xd2, 0xca, 0xc8, 0xbf, 0x5c, 0x5a, 0x98, 0xe5, + /*af20:*/ 0xb8, 0x72, 0x85, 0xb0, 0x8c, 0x4c, 0x49, 0xbc, 0x5f, 0xd5, 0xb3, 0x36, 0xa0, 0xc9, 0x59, 0xbc, + /*af30:*/ 0xc8, 0x5e, 0x00, 0xa4, 0x09, 0x95, 0x48, 0x31, 0x96, 0x76, 0x80, 0xee, 0x49, 0x9a, 0xac, 0xe4, + /*af40:*/ 0xbe, 0x94, 0xa5, 0xc6, 0x6c, 0xd0, 0xce, 0xcf, 0xa8, 0xdf, 0x61, 0xbb, 0xe5, 0x7a, 0x59, 0xe3, + /*af50:*/ 0x7d, 0xad, 0x3b, 0xa9, 0xcc, 0x26, 0xe7, 0x4e, 0x29, 0x5b, 0xed, 0x59, 0x43, 0x70, 0xdd, 0xb6, + /*af60:*/ 0xbf, 0x6c, 0xa6, 0x12, 0x87, 0xd0, 0xa2, 0x33, 0xf2, 0x9a, 0x8a, 0x39, 0xca, 0x63, 0x1e, 0x6a, + /*af70:*/ 0xf4, 0xf7, 0x4a, 0x97, 0xc6, 0x62, 0x85, 0xb1, 0x98, 0xf4, 0xbd, 0x2d, 0x2c, 0xf7, 0xe8, 0x47, + /*af80:*/ 0x73, 0x61, 0xda, 0x0b, 0xca, 0xc7, 0xa8, 0x37, 0x72, 0xdd, 0x08, 0xed, 0xfe, 0xb2, 0xc2, 0xa7, + /*af90:*/ 0x1f, 0x30, 0xce, 0x3a, 0x2e, 0xd8, 0x73, 0x77, 0xbf, 0xe1, 0x53, 0xab, 0xcf, 0xbf, 0x1d, 0xa2, + /*afa0:*/ 0x7b, 0xe6, 0x93, 0xa8, 0x0b, 0x1d, 0x7b, 0xdb, 0xaa, 0x83, 0x91, 0x76, 0x0b, 0xda, 0x09, 0x17, + /*afb0:*/ 0xe6, 0x8a, 0x25, 0x89, 0x1e, 0x9e, 0xe3, 0xec, 0xed, 0x9e, 0xfd, 0x5e, 0xb1, 0x47, 0x78, 0xd9, + /*afc0:*/ 0x1e, 0x2a, 0xfe, 0x92, 0x9b, 0x73, 0x70, 0x16, 0x2d, 0xdf, 0x76, 0x18, 0x35, 0x84, 0x40, 0xed, + /*afd0:*/ 0x42, 0xb5, 0xa6, 0x89, 0x52, 0x75, 0xf0, 0xbb, 0x20, 0xea, 0xea, 0xec, 0xa2, 0x40, 0xc8, 0x32, + /*afe0:*/ 0x82, 0xfb, 0x84, 0x0b, 0x99, 0x22, 0x39, 0x22, 0x0a, 0xde, 0x4f, 0x92, 0x96, 0xd1, 0xa5, 0xf1, + /*aff0:*/ 0x6b, 0xf4, 0x01, 0x04, 0x3d, 0x65, 0x70, 0x82, 0xe2, 0x2e, 0x76, 0xfc, 0x25, 0x81, 0x24, 0x59, + /*b000:*/ 0x7c, 0x77, 0x24, 0xab, 0x00, 0x06, 0x74, 0x9e, 0xa7, 0x6c, 0xaa, 0x04, 0x30, 0xed, 0x9d, 0xb3, + /*b010:*/ 0x56, 0xfc, 0x85, 0x8d, 0xa2, 0x90, 0xc3, 0xcd, 0x08, 0xd2, 0x71, 0xd7, 0xf2, 0x2e, 0x28, 0xfb, + /*b020:*/ 0x13, 0x28, 0xfc, 0x43, 0x40, 0x56, 0x80, 0xc4, 0x56, 0xd1, 0x39, 0x96, 0x1f, 0xdc, 0xa8, 0x70, + /*b030:*/ 0x32, 0x84, 0x40, 0xa1, 0x98, 0xb6, 0x1e, 0x7f, 0xbc, 0x05, 0xb8, 0x2c, 0x95, 0x26, 0xfd, 0x41, + /*b040:*/ 0x20, 0xbb, 0x88, 0x9f, 0x26, 0xf6, 0x4e, 0x99, 0x0e, 0x9c, 0xd9, 0xac, 0xc9, 0xcf, 0x71, 0x31, + /*b050:*/ 0xab, 0x6e, 0x05, 0xfd, 0x20, 0x69, 0x50, 0x93, 0x54, 0xe5, 0xc4, 0x0b, 0xc6, 0xa4, 0xd4, 0x00, + /*b060:*/ 0xcb, 0x58, 0x27, 0x33, 0x07, 0x01, 0xd6, 0xce, 0x25, 0xdf, 0xf9, 0x36, 0x54, 0x94, 0xf1, 0x40, + /*b070:*/ 0x61, 0x69, 0x12, 0x79, 0x5c, 0xb0, 0xf1, 0xba, 0xd2, 0x01, 0x9a, 0xd7, 0x96, 0xbe, 0x34, 0x95, + /*b080:*/ 0x06, 0xe7, 0x05, 0xc3, 0x13, 0x58, 0x4e, 0x85, 0xb6, 0xdb, 0x72, 0xba, 0x5e, 0x15, 0xc9, 0x0a, + /*b090:*/ 0x62, 0x60, 0x53, 0x3f, 0xad, 0x29, 0x3f, 0xe3, 0xe1, 0xbb, 0x23, 0xcc, 0x13, 0xb9, 0xbd, 0x85, + /*b0a0:*/ 0x5d, 0x84, 0x0b, 0x5f, 0x7c, 0x4d, 0x2e, 0x64, 0x41, 0x06, 0x39, 0x71, 0x2b, 0x30, 0x14, 0x59, + /*b0b0:*/ 0xfe, 0x18, 0x80, 0x37, 0x17, 0x9e, 0x40, 0xa8, 0x55, 0xf2, 0xf6, 0xcc, 0x4c, 0xad, 0x10, 0x88, + /*b0c0:*/ 0x70, 0x6d, 0xcc, 0x69, 0xc9, 0xfd, 0x11, 0xa3, 0xba, 0xd0, 0x6a, 0xe0, 0x65, 0xd1, 0xb8, 0x38, + /*b0d0:*/ 0x55, 0xec, 0x1a, 0x81, 0xd0, 0x51, 0x33, 0x31, 0x3b, 0x5a, 0xc9, 0x26, 0xc6, 0xf2, 0x78, 0x2d, + /*b0e0:*/ 0x8e, 0x4e, 0x22, 0x8b, 0x0d, 0x74, 0x4d, 0x36, 0x18, 0x45, 0xdc, 0x41, 0x44, 0x35, 0x6a, 0x3b, + /*b0f0:*/ 0x66, 0x2c, 0xd4, 0x61, 0x92, 0xb8, 0x48, 0xab, 0xa2, 0xb6, 0x09, 0x7f, 0xa7, 0x91, 0xe9, 0x97, + /*b100:*/ 0x53, 0x59, 0x03, 0x08, 0x00, 0x3f, 0x03, 0x1e, 0x05, 0x0e, 0x88, 0x00, 0x01, 0x01, 0xff, 0x0a, + /*b110:*/ 0x1f, 0x03, 0xff, 0x04, 0x1e, 0x06, 0x2d, 0x5c, 0x0f, 0x8d, 0x03, 0x01, 0x34, 0xfe, 0x33, 0xff, + /*b120:*/ 0x78, 0x43, 0xfd, 0x43, 0x50, 0xc3, 0x38, 0xc7, 0x00, 0x18, 0x20, 0x20, 0x20, 0x20, 0x14, 0x02, + /*b130:*/ 0x0c, 0x32, 0xe3, 0xbc, 0x00, 0x00, 0x05, 0x28, 0x0a, 0x2d, 0x00, 0x28, 0x0a, 0x32, 0x00, 0xc4, + /*b140:*/ 0x09, 0x3c, 0x00, 0xf0, 0x0a, 0x50, 0x00, 0x1e, 0x1e, 0x8c, 0x00, 0x96, 0x00, 0x14, 0x0a, 0x04, + /*b150:*/ 0x29, 0x1a, 0x64, 0x07, 0x66, 0x64, 0xc0, 0x20, 0x02, 0xaf, 0x00, 0x03, 0x0e, 0x1f, 0x08, 0x2a, + /*b160:*/ 0x00, 0x20, 0x04, 0x1b, 0x00, 0x80, 0x14, 0xc0, 0xc8, 0xc8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0x38, + /*b170:*/ 0x37, 0x35, 0x34, 0x32, 0x31, 0x2f, 0x2d, 0x01, 0x04, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x13, 0x00, + /*b180:*/ 0x00, 0x00, 0x40, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x20, 0x20, 0x20, 0x20, + /*b190:*/ 0x20, 0x20, 0x20, 0x10, 0x5a, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d, 0x39, 0x00, 0x0a, 0x00, 0x10, + /*b1a0:*/ 0x27, 0x66, 0x12, 0xd4, 0x10, 0xff, 0x1a, 0x00, 0x28, 0x28, 0x1c, 0x26, 0x66, 0x66, 0x66, 0x66, + /*b1b0:*/ 0x66, 0x66, 0x66, 0xff, 0xc8, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, + /*b1c0:*/ 0x04, 0x20, 0x40, 0x03, 0x00, 0x1f, 0x00, 0x1d, 0x2d, 0x1d, 0x2b, 0x1d, 0x28, 0x1d, 0x2c, 0x1d, + /*b1d0:*/ 0x20, 0xdc, 0x73, 0xfe, 0x73, 0xe5, 0xcd, 0x0d, 0x04, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + /*b1e0:*/ 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + /*b1f0:*/ 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + /*b200:*/ 0x27, 0x29, 0x2a, 0x2d, 0x2b, 0x28, 0x2c, 0x20, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x14, + /*b210:*/ 0x12, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, + /*b220:*/ 0x01, 0x00, 0x1d, 0x66, 0x66, 0x6d, 0x6d, 0x73, 0x73, 0x7a, 0x7a, 0x80, 0x80, 0x86, 0x86, 0x8d, + /*b230:*/ 0x8d, 0x93, 0x93, 0x9a, 0x9a, 0xa0, 0xa0, 0xa6, 0xa6, 0xad, 0xad, 0xb3, 0xb3, 0x80, 0x80, 0x80, + /*b240:*/ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /*b250:*/ 0x80, 0x0a, 0x1c, 0x2b, 0x1e, 0x0a, 0x80, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b260:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b270:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b280:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b290:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x48, 0xb2, + /*b300:*/ 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b310:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b320:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b330:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b340:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b350:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b360:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b370:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b380:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b390:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b400:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b410:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b420:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b430:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b440:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + /*b450:*/ 0x3f, 0x03, 0x1e, 0x05, 0x0e, 0x08, 0x00, 0x19, 0x19, 0x00, 0x10, 0xe2, 0x04, 0xb6, 0x08, 0x1e, + /*b460:*/ 0x05, 0x28, 0xf5, 0x28, 0x1e, 0x05, 0x01, 0x30, 0x00, 0x30, 0x00, 0x00, 0x50, 0x00, 0x50, 0xf0, + /*b470:*/ 0xd2, 0xf0, 0xd2, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x04, 0xc0, 0x32, 0x70, 0x00, 0x00, + /*b480:*/ 0x00, 0x80, 0x04, 0x2e, 0x1b, 0x64, 0x07, 0x00, 0x00, 0x56, 0x35, 0x05, 0x10, 0x00, 0x00, 0x0b, + /*b490:*/ 0x20, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x37, 0x33, + /*b4a0:*/ 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x03, 0x0f, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf0, + /*b4b0:*/ 0x15, 0x1b, 0x2e, 0x49, 0x40, 0xff, 0x0b, 0x20, 0x0c, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + /*b4c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b4d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x88, 0x55, + /*b4e0:*/ 0x15, 0x21, 0x11, 0x92, 0x87, 0x4f, 0x13, 0x01, 0x01, 0x89, 0x00, 0x4b, 0x00, 0x01, 0x34, 0x00, + /*b4f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b500:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b510:*/ 0x00, 0x02, 0x5e, 0x01, 0x03, 0x0e, 0x1f, 0x00, 0xde, 0x01, 0x19, 0x04, 0x1b, 0x00, 0x10, 0x0a, + /*b520:*/ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b530:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x05, 0x00, 0x00, + /*b540:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, + /*b550:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x28, 0x00, 0x77, 0x18, 0x80, 0x18, 0x80, 0x1a, + /*b560:*/ 0x01, 0x19, 0x3f, 0x4d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x10, 0x0a, 0x00, 0x00, + /*b570:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x04, 0x40, 0x40, 0x03, 0x00, 0x2e, 0x1b, + /*b580:*/ 0x44, 0x00, 0x19, 0x01, 0x00, 0xbe, 0x00, 0xde, 0x3f, 0xd0, 0x80, 0x08, 0x03, 0x00, 0x00, 0x00, + /*b590:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7d, 0x10, 0x00, 0x01, 0x54, 0x00, + /*b5f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b600:*/ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x51, 0x51, + /*b610:*/ 0x51, 0x51, 0x51, 0xcd, 0x0d, 0x04, 0x00, 0x00, 0x1c, 0x80, 0x00, 0x04, 0xff, 0x2e, 0x1b, 0x05, + /*b620:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b630:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b640:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b650:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b660:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b670:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b680:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b690:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6e0:*/ 0x00, 0x00, 0x00, 0x1d, 0x1a, 0x16, 0x00, 0x01, 0x55, 0x1b, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x00, + /*b6f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b700:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b710:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b720:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x32, 0x00, 0x1e, 0x04, 0x80, 0xc0, 0x04, + /*b730:*/ 0x28, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b740:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b750:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b760:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b770:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b780:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b790:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x28, 0x00, 0x00, 0x51, 0x00, + /*b7f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b800:*/ 0xff}; +#endif + +const char *rmi_config_ver = "N51XX_SY_1216"; + +const u8 rmi_fw[] = { + /*0000:*/ 0x02, 0x62, 0x3e, 0x94, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + /*0010:*/ 0x53, 0x37, 0x33, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0020:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0030:*/ 0x44, 0x53, 0x34, 0x20, 0x52, 0x33, 0x2e, 0x35, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0040:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0050:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0060:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0070:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0080:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0090:*/ 0x49, 0x32, 0x43, 0x00, 0x04, 0x00, 0xff, 0x00, 0x0c, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + /*00a0:*/ 0x49, 0x32, 0x43, 0x00, 0x04, 0x00, 0xff, 0x00, 0x0c, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + /*00b0:*/ 0x09, 0xd9, 0x94, 0xe6, 0x23, 0xe3, 0x8d, 0xce, 0x50, 0x96, 0xc3, 0x4b, 0x8f, 0x1a, 0x4f, 0x6d, + /*00c0:*/ 0x57, 0x05, 0x48, 0x7c, 0xd7, 0x03, 0xb0, 0x50, 0xe0, 0x77, 0x3c, 0x8b, 0x79, 0xf6, 0x71, 0x75, + /*00d0:*/ 0xca, 0xec, 0xb0, 0x31, 0x53, 0xaa, 0x37, 0xe9, 0x19, 0x47, 0x46, 0x84, 0xba, 0x28, 0x18, 0xe9, + /*00e0:*/ 0x51, 0x89, 0xe7, 0xce, 0x3e, 0x64, 0x26, 0xa6, 0x25, 0x31, 0xc5, 0x0d, 0x9a, 0xa9, 0x93, 0xfa, + /*00f0:*/ 0x8a, 0x67, 0xd2, 0x1b, 0x4b, 0x66, 0x4d, 0x12, 0xa8, 0x62, 0x72, 0xf6, 0xed, 0xb7, 0x09, 0x4e, + /*0100:*/ 0xce, 0xd6, 0xc5, 0x28, 0x69, 0xd2, 0xa9, 0x7d, 0x39, 0xf4, 0xe4, 0x78, 0x56, 0xd2, 0x53, 0x4e, + /*0110:*/ 0x35, 0x9f, 0xa7, 0xc9, 0x55, 0x7b, 0xec, 0xb3, 0xd2, 0xb0, 0x47, 0x38, 0x01, 0x7e, 0xf6, 0x5d, + /*0120:*/ 0xa3, 0xef, 0xc0, 0x55, 0xf3, 0xca, 0x62, 0x4f, 0xc8, 0x13, 0xbd, 0x20, 0xe6, 0x3a, 0xac, 0xcd, + /*0130:*/ 0x2b, 0x4b, 0x2c, 0x18, 0x21, 0x16, 0xf3, 0xb6, 0xaa, 0x41, 0xe2, 0x66, 0xfc, 0x6f, 0x1f, 0xce, + /*0140:*/ 0x14, 0xd1, 0x9c, 0x00, 0x78, 0x74, 0x94, 0xa6, 0xd2, 0x4e, 0xff, 0x63, 0x8f, 0x42, 0xcb, 0x54, + /*0150:*/ 0xcc, 0x1b, 0x3f, 0x78, 0xf2, 0xf6, 0x8a, 0xbe, 0x7f, 0x80, 0x69, 0x1a, 0x1a, 0xff, 0xc2, 0x2a, + /*0160:*/ 0x12, 0x01, 0xc8, 0x11, 0xe3, 0xe2, 0x83, 0xc2, 0x71, 0x24, 0x74, 0x0e, 0x6b, 0xd3, 0x26, 0xb3, + /*0170:*/ 0xda, 0xdc, 0xfd, 0x86, 0xe6, 0xdc, 0xb0, 0x14, 0xc0, 0x87, 0x68, 0x6d, 0x15, 0x39, 0x99, 0x81, + /*0180:*/ 0xf4, 0x8f, 0xfa, 0x4b, 0x47, 0x53, 0x99, 0x05, 0xe8, 0x9f, 0xd7, 0x8c, 0x0a, 0xdd, 0x12, 0x95, + /*0190:*/ 0xc6, 0xd0, 0xe3, 0xf9, 0x2c, 0xb0, 0xee, 0x4f, 0x50, 0x51, 0x9e, 0x2c, 0x7f, 0x07, 0xd7, 0xd7, + /*01a0:*/ 0xa6, 0xfc, 0x58, 0x56, 0x65, 0x04, 0x49, 0x73, 0x05, 0x3e, 0xd2, 0xe9, 0x37, 0xb8, 0xd7, 0xbc, + /*01b0:*/ 0x79, 0x5f, 0x8c, 0xc7, 0x28, 0xe6, 0x39, 0xef, 0x29, 0x7f, 0x26, 0x52, 0xd8, 0xda, 0x99, 0x4c, + /*01c0:*/ 0x6b, 0x6e, 0x7a, 0xd3, 0x9e, 0x75, 0xca, 0x55, 0xb2, 0x29, 0x88, 0xb8, 0x0b, 0x1d, 0x1c, 0x81, + /*01d0:*/ 0x98, 0x15, 0xf7, 0x59, 0x1d, 0x73, 0xc3, 0x8d, 0x42, 0x5e, 0xce, 0x78, 0x9b, 0x36, 0x49, 0xbe, + /*01e0:*/ 0xad, 0xc9, 0x81, 0xa4, 0x7e, 0x4c, 0xcb, 0x35, 0x52, 0x17, 0xd7, 0x73, 0x29, 0x4e, 0x81, 0xdf, + /*01f0:*/ 0x66, 0x04, 0x1d, 0x49, 0x3f, 0xa0, 0xf2, 0x2f, 0x42, 0xd0, 0xf4, 0xe9, 0x49, 0xae, 0x52, 0xf7, + /*0200:*/ 0xce, 0x67, 0x45, 0x5c, 0x59, 0x91, 0xb0, 0x83, 0xc0, 0x2e, 0xf4, 0x77, 0xcb, 0x65, 0xb5, 0xd3, + /*0210:*/ 0x18, 0x15, 0x9e, 0x05, 0x30, 0x8f, 0xb7, 0xb8, 0x40, 0x1f, 0x71, 0xb1, 0x0f, 0x81, 0x03, 0x89, + /*0220:*/ 0xb7, 0x6d, 0xef, 0x46, 0x6e, 0x45, 0x46, 0xc5, 0xd3, 0x94, 0x92, 0x41, 0xca, 0xc5, 0x32, 0xac, + /*0230:*/ 0x34, 0x10, 0x2b, 0x1a, 0x4f, 0xec, 0x94, 0xcf, 0x91, 0xd9, 0x80, 0xf1, 0x60, 0x9d, 0xe7, 0x63, + /*0240:*/ 0x51, 0xa7, 0xec, 0xe6, 0x1d, 0xf8, 0x38, 0xc7, 0xec, 0xe7, 0x69, 0x08, 0x02, 0x7b, 0x09, 0x89, + /*0250:*/ 0x84, 0x9a, 0xbd, 0x1f, 0x04, 0x9f, 0xf3, 0x20, 0xc8, 0x23, 0x4c, 0xd7, 0x0a, 0x64, 0x47, 0x43, + /*0260:*/ 0xb6, 0xc8, 0xad, 0xb7, 0xd5, 0xa4, 0xb0, 0xea, 0x57, 0x8d, 0xe9, 0x4e, 0x18, 0x81, 0x08, 0x26, + /*0270:*/ 0x68, 0x66, 0xe6, 0x0b, 0xb2, 0x5d, 0xf5, 0xc3, 0xc1, 0xc1, 0x25, 0x84, 0xdd, 0x00, 0x34, 0x10, + /*0280:*/ 0x94, 0xb6, 0xaf, 0x9f, 0x6a, 0xd5, 0x34, 0x1e, 0x9a, 0x42, 0xd0, 0xa7, 0xc9, 0xd7, 0x3f, 0xc3, + /*0290:*/ 0x43, 0xf2, 0x80, 0x94, 0x2e, 0xb9, 0xdb, 0x60, 0x76, 0xc5, 0xf5, 0x6f, 0xe8, 0x83, 0x96, 0x1b, + /*02a0:*/ 0xe4, 0xdc, 0x2e, 0x2b, 0xb5, 0x80, 0x99, 0x1c, 0x26, 0xda, 0x52, 0x46, 0x1f, 0x54, 0x1c, 0x0e, + /*02b0:*/ 0xee, 0x3a, 0xd2, 0x3f, 0x8f, 0x98, 0x5b, 0xf3, 0x5b, 0xa2, 0x33, 0x03, 0xef, 0x98, 0x35, 0xed, + /*02c0:*/ 0x73, 0xd5, 0xe3, 0x66, 0xca, 0xd7, 0x62, 0x65, 0x93, 0xe2, 0x4d, 0x2c, 0x3c, 0xa9, 0x47, 0xfa, + /*02d0:*/ 0x3d, 0x52, 0x65, 0x92, 0xc1, 0x57, 0xf4, 0x92, 0xff, 0x86, 0x14, 0x22, 0xb1, 0x5b, 0x72, 0xc3, + /*02e0:*/ 0x17, 0x47, 0xb6, 0x8d, 0xb4, 0x55, 0xf9, 0xf9, 0x89, 0xf2, 0xfa, 0xc5, 0xc9, 0xc7, 0xe0, 0xd6, + /*02f0:*/ 0x2c, 0xba, 0x56, 0xc1, 0xc6, 0x0f, 0x69, 0x51, 0x0e, 0x7c, 0x1e, 0x6a, 0x5d, 0x2f, 0x2d, 0x26, + /*0300:*/ 0xaf, 0xa0, 0x68, 0x71, 0x08, 0xf3, 0x10, 0xea, 0xb1, 0xc8, 0x48, 0x14, 0x73, 0xcb, 0x9c, 0x33, + /*0310:*/ 0x9d, 0x4d, 0x2b, 0x1d, 0x18, 0xc2, 0x61, 0xbe, 0xde, 0x02, 0x96, 0x68, 0xf0, 0xaa, 0x9c, 0xb8, + /*0320:*/ 0x2a, 0x94, 0xf2, 0xc1, 0xc3, 0xdb, 0xf9, 0x6e, 0x5b, 0x6e, 0xb5, 0xb4, 0xa3, 0x0e, 0xb6, 0xb9, + /*0330:*/ 0x95, 0x0e, 0x18, 0x69, 0x40, 0x4c, 0xcb, 0xf7, 0xf3, 0xd6, 0x53, 0x16, 0xc1, 0xcf, 0xc0, 0x34, + /*0340:*/ 0xcb, 0xe9, 0x2b, 0x3f, 0xdd, 0xe0, 0xa4, 0x4e, 0x97, 0x41, 0x72, 0x15, 0xfc, 0x7a, 0x40, 0x84, + /*0350:*/ 0x96, 0xeb, 0x45, 0x16, 0x96, 0xcb, 0x72, 0x8d, 0xb6, 0xca, 0x00, 0x58, 0x56, 0x88, 0x47, 0x39, + /*0360:*/ 0x90, 0x34, 0x76, 0x5c, 0x46, 0x70, 0x96, 0x89, 0xd0, 0x34, 0x60, 0xbd, 0x7d, 0x0e, 0xdb, 0xa6, + /*0370:*/ 0x0f, 0x17, 0x49, 0x67, 0x27, 0x87, 0x06, 0xae, 0x69, 0x19, 0x89, 0xcd, 0xb2, 0x68, 0xa1, 0x1b, + /*0380:*/ 0x52, 0xb4, 0x1d, 0xfa, 0xc4, 0x5b, 0xf1, 0xe8, 0x1f, 0xef, 0xa7, 0x5e, 0x87, 0x18, 0x0d, 0xdb, + /*0390:*/ 0xdf, 0xc9, 0xf3, 0x03, 0x3c, 0xfd, 0x9f, 0x0b, 0xa0, 0x17, 0x2b, 0x4b, 0xad, 0x14, 0x66, 0xb5, + /*03a0:*/ 0x31, 0x7b, 0x5f, 0xc7, 0x03, 0xa7, 0x83, 0x9c, 0xab, 0x7b, 0x58, 0x1b, 0x39, 0xb8, 0xc4, 0x44, + /*03b0:*/ 0xdd, 0xa1, 0xf8, 0xe8, 0x9e, 0x51, 0x92, 0xb1, 0xd5, 0xfa, 0x8e, 0x53, 0x7a, 0x51, 0xd9, 0x1b, + /*03c0:*/ 0xa2, 0x4a, 0x7f, 0xc6, 0xf7, 0x58, 0x64, 0xe3, 0x8d, 0x35, 0xbf, 0xb0, 0xd6, 0x11, 0x88, 0x05, + /*03d0:*/ 0x17, 0x26, 0x53, 0x5a, 0x02, 0x3d, 0xe1, 0x35, 0x2a, 0x81, 0xd3, 0xac, 0xfd, 0xb6, 0xdc, 0xf0, + /*03e0:*/ 0x35, 0x02, 0x6f, 0x72, 0xcd, 0x53, 0xf3, 0xbf, 0x18, 0x3e, 0x4f, 0x64, 0xee, 0x02, 0xfc, 0xdd, + /*03f0:*/ 0x78, 0xb8, 0x46, 0x06, 0x46, 0x0a, 0x13, 0xa0, 0x07, 0xc2, 0x42, 0x2a, 0xd2, 0xb3, 0x5d, 0x74, + /*0400:*/ 0x8b, 0x1d, 0x47, 0x64, 0x9b, 0x78, 0x86, 0x62, 0x89, 0x5f, 0xdd, 0x65, 0x16, 0x89, 0x46, 0x73, + /*0410:*/ 0xe0, 0x54, 0x1d, 0xf1, 0xc2, 0x20, 0x12, 0x49, 0x6e, 0x45, 0xf1, 0xce, 0x25, 0x3e, 0xb5, 0x1b, + /*0420:*/ 0x09, 0xd6, 0xc7, 0xb4, 0xe7, 0x79, 0xfb, 0x48, 0x3e, 0x7a, 0x86, 0xa5, 0xc1, 0xca, 0x99, 0xb9, + /*0430:*/ 0xeb, 0xe1, 0x06, 0x4b, 0xe5, 0xf0, 0xa2, 0xf0, 0xd9, 0xff, 0x6b, 0x76, 0x9f, 0x86, 0x6e, 0x6f, + /*0440:*/ 0xe6, 0x7a, 0xe8, 0x74, 0x77, 0x25, 0xc1, 0x86, 0x2a, 0xc7, 0x1e, 0xe4, 0xb5, 0x88, 0x3a, 0xd7, + /*0450:*/ 0x43, 0x1e, 0xc9, 0x66, 0xa9, 0x0b, 0x7a, 0x9b, 0x8f, 0x9f, 0xb5, 0x9a, 0x89, 0x5f, 0x2f, 0xa7, + /*0460:*/ 0xe1, 0x1d, 0x19, 0x20, 0x6f, 0x17, 0x71, 0xd1, 0x33, 0x63, 0xdf, 0xed, 0x82, 0x08, 0x28, 0xab, + /*0470:*/ 0x3c, 0xb5, 0x73, 0x84, 0x3f, 0x78, 0x19, 0x26, 0x5b, 0x6d, 0x08, 0x8f, 0xde, 0x61, 0x87, 0x24, + /*0480:*/ 0x60, 0xd9, 0x85, 0xa9, 0x88, 0x5b, 0xcf, 0x56, 0xd6, 0x23, 0x88, 0xfc, 0xf3, 0x2c, 0xae, 0x7c, + /*0490:*/ 0x31, 0x33, 0xee, 0xc6, 0xf0, 0xff, 0xae, 0x56, 0x90, 0xba, 0x15, 0xbe, 0xfb, 0x18, 0xae, 0x8b, + /*04a0:*/ 0xe9, 0x34, 0x9d, 0xbb, 0xbe, 0xf6, 0xea, 0x90, 0x87, 0xf3, 0x55, 0xd5, 0xca, 0x3e, 0xc3, 0x04, + /*04b0:*/ 0x17, 0xab, 0x3c, 0x9e, 0x2a, 0x11, 0x07, 0x24, 0xbe, 0x3c, 0x4a, 0x2a, 0x11, 0xe1, 0x48, 0x52, + /*04c0:*/ 0x93, 0x5f, 0xee, 0x8f, 0x57, 0x3e, 0x06, 0x53, 0xc5, 0xc7, 0x16, 0x60, 0x01, 0x83, 0xc1, 0xb5, + /*04d0:*/ 0x9b, 0xf5, 0xaf, 0x0e, 0xe3, 0x03, 0x80, 0xb0, 0x42, 0x71, 0xf1, 0x14, 0xa0, 0x21, 0x3e, 0xd8, + /*04e0:*/ 0xb9, 0x15, 0x8c, 0x8a, 0xdc, 0x48, 0x51, 0xdc, 0xe4, 0x9c, 0x2e, 0x5f, 0x41, 0x55, 0x4f, 0x10, + /*04f0:*/ 0x4d, 0x5a, 0x4c, 0x32, 0xfa, 0x6e, 0x54, 0x63, 0x57, 0x43, 0x19, 0x0f, 0x97, 0x18, 0x4e, 0xa9, + /*0500:*/ 0xde, 0x48, 0x20, 0x1f, 0xc5, 0x24, 0x15, 0xe0, 0x56, 0x58, 0x99, 0x2d, 0xf8, 0xb2, 0x3d, 0xc9, + /*0510:*/ 0x39, 0xe0, 0xfb, 0xf0, 0x3c, 0x67, 0xc1, 0x98, 0x5f, 0x13, 0x52, 0x10, 0x0e, 0xe2, 0x64, 0xfc, + /*0520:*/ 0x22, 0x38, 0x9a, 0x59, 0x78, 0x7f, 0x0d, 0x8c, 0xc3, 0xb6, 0x3a, 0x76, 0x1b, 0x91, 0x66, 0xaa, + /*0530:*/ 0x02, 0x90, 0x41, 0xfb, 0x50, 0x6f, 0xb9, 0xba, 0x6b, 0x6a, 0xc8, 0x2f, 0xdb, 0x06, 0x9f, 0x1c, + /*0540:*/ 0xc2, 0xec, 0x4e, 0xa2, 0x9a, 0xbf, 0x24, 0xb6, 0x56, 0x7e, 0x0e, 0xd8, 0x6a, 0x83, 0x7f, 0x35, + /*0550:*/ 0xfc, 0xe8, 0xf4, 0xc6, 0x49, 0x4d, 0xeb, 0xa3, 0x99, 0xb7, 0x07, 0xff, 0x25, 0x4a, 0x72, 0xd9, + /*0560:*/ 0xe7, 0xce, 0x3d, 0x37, 0x9b, 0x77, 0x4a, 0x06, 0x1b, 0x41, 0xc9, 0xae, 0x2e, 0x51, 0x41, 0x94, + /*0570:*/ 0x14, 0x08, 0xc4, 0x74, 0x7c, 0xa2, 0xfe, 0xa1, 0x4e, 0x6b, 0x31, 0x0e, 0xb2, 0x41, 0xd1, 0x44, + /*0580:*/ 0xde, 0xc6, 0x53, 0xd3, 0x14, 0xec, 0x71, 0x19, 0x91, 0x3d, 0x5b, 0xb0, 0xd0, 0x89, 0x5d, 0xa0, + /*0590:*/ 0x0c, 0x16, 0xb7, 0x5c, 0x6c, 0xbb, 0x17, 0xb3, 0xd0, 0xea, 0x14, 0x4c, 0x80, 0xa3, 0xb3, 0xe4, + /*05a0:*/ 0x4e, 0xdf, 0x8d, 0x11, 0xc1, 0x4a, 0x2b, 0x72, 0x4a, 0x9f, 0x09, 0x8d, 0x2d, 0x74, 0x3d, 0x62, + /*05b0:*/ 0x0e, 0x9c, 0xa0, 0x2b, 0x9f, 0xc1, 0x7e, 0xeb, 0x6f, 0x55, 0x8e, 0x4f, 0xe1, 0x74, 0xb4, 0x53, + /*05c0:*/ 0x0f, 0x32, 0xf4, 0x99, 0xec, 0x0e, 0xc4, 0x38, 0x27, 0xd2, 0xd0, 0x6f, 0x6e, 0x34, 0xba, 0x1b, + /*05d0:*/ 0x60, 0xbd, 0xcb, 0x06, 0xfe, 0x2e, 0xd1, 0x81, 0x56, 0x9d, 0xcf, 0x68, 0x3e, 0xa5, 0xa0, 0x1a, + /*05e0:*/ 0x7e, 0x52, 0x0f, 0xad, 0x55, 0x6f, 0x00, 0xc6, 0xd4, 0x24, 0x74, 0x75, 0x2e, 0x5b, 0x61, 0xd6, + /*05f0:*/ 0x1d, 0xf9, 0xab, 0xdf, 0x58, 0xfb, 0xac, 0x07, 0x57, 0x22, 0x3d, 0xdd, 0x11, 0xe5, 0xa2, 0x2d, + /*0600:*/ 0xeb, 0x99, 0x3c, 0xb3, 0x65, 0x08, 0x79, 0xe7, 0x82, 0x65, 0x8f, 0x6e, 0x43, 0xa8, 0xa0, 0x51, + /*0610:*/ 0xde, 0xd1, 0xf4, 0xb4, 0x38, 0xa7, 0xb8, 0x68, 0x92, 0xb9, 0x99, 0x2d, 0x9f, 0x2b, 0x0c, 0xe7, + /*0620:*/ 0x31, 0xcd, 0x05, 0xcb, 0x97, 0xb8, 0xf1, 0xf2, 0xfc, 0x2b, 0xb0, 0x17, 0xcd, 0x7b, 0x62, 0x6a, + /*0630:*/ 0x0d, 0x30, 0xaa, 0x14, 0xd6, 0xd2, 0xd7, 0x66, 0xc0, 0x1f, 0x57, 0xe9, 0xd8, 0xe5, 0x4d, 0xe3, + /*0640:*/ 0x23, 0xaf, 0xa2, 0xbb, 0x01, 0xda, 0xcd, 0x3e, 0xf8, 0x4a, 0x6d, 0x11, 0xe5, 0x8f, 0x5f, 0x8e, + /*0650:*/ 0x08, 0x30, 0x98, 0x6a, 0xad, 0x73, 0x4e, 0xcf, 0xd6, 0xc8, 0x51, 0x73, 0xf4, 0x3e, 0xd5, 0x8e, + /*0660:*/ 0x7c, 0x26, 0x9c, 0xcc, 0xe8, 0xf4, 0xfb, 0x69, 0x43, 0xac, 0x08, 0x60, 0xae, 0x90, 0xb6, 0x84, + /*0670:*/ 0x40, 0xc8, 0x73, 0xbb, 0xfc, 0xff, 0xf3, 0x16, 0xaf, 0x21, 0xd2, 0x4f, 0x29, 0x8e, 0xb3, 0x69, + /*0680:*/ 0xe6, 0xfe, 0x47, 0x85, 0xdd, 0x0b, 0x4d, 0x12, 0x8b, 0x1b, 0x55, 0xdf, 0x65, 0xb5, 0x4a, 0xdd, + /*0690:*/ 0x4d, 0x67, 0x68, 0xf2, 0x38, 0xd5, 0x73, 0x00, 0xbe, 0x37, 0x2f, 0xab, 0xda, 0x25, 0x6d, 0x26, + /*06a0:*/ 0x62, 0x47, 0xa9, 0x73, 0x6b, 0x87, 0x26, 0x66, 0xb6, 0x4f, 0xee, 0x15, 0x7f, 0x3e, 0xc1, 0xe4, + /*06b0:*/ 0xa9, 0x13, 0xd3, 0x56, 0xb7, 0x1c, 0x81, 0x21, 0x2a, 0xa6, 0x1c, 0x3f, 0x58, 0xe2, 0xd9, 0x38, + /*06c0:*/ 0xc2, 0x0d, 0x49, 0x3e, 0x8c, 0xdf, 0x6b, 0x56, 0x76, 0xc4, 0xe6, 0x9d, 0x4f, 0x5b, 0x77, 0x0f, + /*06d0:*/ 0x18, 0x38, 0xeb, 0x07, 0xc1, 0x00, 0x0c, 0xfa, 0x8e, 0x60, 0x6b, 0xde, 0xcc, 0xf5, 0xd1, 0x2a, + /*06e0:*/ 0x0d, 0x0f, 0x01, 0x93, 0xf9, 0x12, 0x55, 0x3f, 0x51, 0x4e, 0x84, 0xcd, 0x89, 0x3e, 0xf8, 0xee, + /*06f0:*/ 0xca, 0x1c, 0x5c, 0xa8, 0x9c, 0x3d, 0x5d, 0xad, 0x12, 0x1a, 0xf5, 0x28, 0xb3, 0x57, 0xb7, 0xb7, + /*0700:*/ 0x64, 0x74, 0xcb, 0x92, 0x4a, 0xdf, 0x9b, 0xb2, 0xfa, 0x08, 0xa1, 0xcc, 0xde, 0x6d, 0x0b, 0x9e, + /*0710:*/ 0x4e, 0x6d, 0xde, 0xfc, 0x69, 0xe2, 0xaa, 0x4e, 0x49, 0x10, 0xd9, 0xec, 0x58, 0x7c, 0x1e, 0x84, + /*0720:*/ 0x8d, 0x50, 0x6c, 0x90, 0x5f, 0x76, 0x67, 0x77, 0x66, 0x95, 0x54, 0xec, 0xda, 0xc6, 0xd4, 0x44, + /*0730:*/ 0x0a, 0xe5, 0xbe, 0x52, 0x08, 0xdf, 0x44, 0x62, 0x77, 0x38, 0x15, 0x73, 0xa2, 0xcc, 0xa3, 0x06, + /*0740:*/ 0xd0, 0xb2, 0x7b, 0xe2, 0xdd, 0x55, 0xd2, 0xa3, 0x65, 0x51, 0x8f, 0x39, 0x0c, 0x3e, 0x19, 0xf6, + /*0750:*/ 0x52, 0xa6, 0x4c, 0xf0, 0xb1, 0x2c, 0xe2, 0x71, 0x89, 0x40, 0x92, 0x7b, 0x11, 0xa0, 0x76, 0xfa, + /*0760:*/ 0x07, 0x23, 0x2d, 0x8e, 0xb1, 0xbc, 0x5e, 0x04, 0xdb, 0xba, 0xa0, 0x2e, 0xc0, 0xc5, 0xac, 0x03, + /*0770:*/ 0x65, 0xbe, 0x68, 0x95, 0xbe, 0x0d, 0x6e, 0xe4, 0x3e, 0xbe, 0x88, 0x47, 0x2f, 0xb8, 0xd9, 0xf6, + /*0780:*/ 0x59, 0x2b, 0xe0, 0x27, 0xc6, 0xbc, 0xf4, 0x0d, 0x01, 0x46, 0x7a, 0x70, 0xfe, 0x0c, 0xcc, 0x30, + /*0790:*/ 0x97, 0xa7, 0x19, 0x00, 0x5a, 0x5b, 0x3a, 0xfa, 0xc8, 0x07, 0x33, 0xa3, 0x31, 0x3f, 0x0c, 0xe1, + /*07a0:*/ 0x81, 0xa7, 0xef, 0x18, 0x7f, 0x78, 0x9d, 0x3f, 0x79, 0xe2, 0x59, 0x02, 0x55, 0xe0, 0xae, 0x2b, + /*07b0:*/ 0xaf, 0xdf, 0x2d, 0x7b, 0x3d, 0xd8, 0x1a, 0x28, 0xfb, 0xcd, 0x01, 0x12, 0xb8, 0xbf, 0x13, 0x45, + /*07c0:*/ 0xfd, 0x46, 0xb3, 0x8d, 0x46, 0x74, 0x76, 0xfd, 0x35, 0x7c, 0xe4, 0x6e, 0xe9, 0xc5, 0x42, 0x60, + /*07d0:*/ 0x0d, 0xfd, 0x2e, 0xf1, 0xcb, 0x30, 0xb1, 0x4e, 0x23, 0xf0, 0x68, 0x99, 0x95, 0xba, 0x8d, 0x5f, + /*07e0:*/ 0x08, 0xf7, 0x43, 0xed, 0xa1, 0x12, 0x1b, 0x54, 0x27, 0x78, 0x31, 0x19, 0xf7, 0xbb, 0x5d, 0xdd, + /*07f0:*/ 0x89, 0x97, 0x69, 0x27, 0x86, 0x00, 0x6a, 0x3b, 0xc5, 0xef, 0x13, 0xa0, 0x70, 0x91, 0x5c, 0xfa, + /*0800:*/ 0x05, 0xc6, 0xfa, 0x45, 0x1a, 0xbd, 0x58, 0x86, 0xfd, 0x0d, 0x51, 0x5d, 0xc6, 0x21, 0x55, 0x15, + /*0810:*/ 0x18, 0x11, 0x42, 0x81, 0xde, 0xbb, 0x44, 0x37, 0xaf, 0x59, 0xa5, 0x6d, 0x2a, 0xf8, 0x97, 0xc3, + /*0820:*/ 0x47, 0x5a, 0x09, 0x01, 0xfd, 0x6c, 0xcb, 0x59, 0xfd, 0x48, 0x36, 0xaf, 0x7a, 0x13, 0x62, 0xa3, + /*0830:*/ 0xc0, 0xa9, 0xe5, 0xa6, 0xbc, 0xf5, 0xd6, 0xa0, 0xa4, 0x52, 0xa4, 0xb8, 0x6f, 0x9d, 0x05, 0x30, + /*0840:*/ 0x71, 0x59, 0x44, 0xac, 0xa1, 0x81, 0x1d, 0xc3, 0xc7, 0xe6, 0xee, 0xde, 0xed, 0xd5, 0xf5, 0x67, + /*0850:*/ 0x11, 0x04, 0xc2, 0x33, 0xe2, 0x9c, 0x26, 0xb5, 0x05, 0x80, 0xa4, 0x51, 0xca, 0xd7, 0xc6, 0xda, + /*0860:*/ 0x08, 0xe6, 0xa1, 0xc5, 0xc2, 0x25, 0xc1, 0xa7, 0x5c, 0x84, 0x67, 0xbf, 0x4b, 0x69, 0xf3, 0xc3, + /*0870:*/ 0x4c, 0xfe, 0xc5, 0xa3, 0xdb, 0x05, 0xe4, 0x17, 0x94, 0x0c, 0x05, 0xf2, 0x73, 0x9b, 0xf0, 0xe5, + /*0880:*/ 0x6b, 0x4e, 0x44, 0xcc, 0x4c, 0xcd, 0x40, 0x4d, 0x18, 0x2f, 0xe0, 0xa8, 0x8c, 0xb8, 0x6d, 0x02, + /*0890:*/ 0xc8, 0x13, 0x1f, 0x46, 0x2c, 0x42, 0x63, 0x9c, 0xb3, 0xb8, 0xc3, 0x60, 0xb8, 0xfe, 0x84, 0x5c, + /*08a0:*/ 0xa0, 0x6d, 0xba, 0x03, 0xf7, 0x98, 0xfd, 0x44, 0xaa, 0xcf, 0x24, 0x5b, 0x51, 0x77, 0x57, 0x63, + /*08b0:*/ 0x3f, 0x19, 0x7a, 0x7f, 0x56, 0x35, 0x2a, 0x32, 0xd8, 0x2c, 0x3a, 0x2a, 0x32, 0xf7, 0x5a, 0xd6, + /*08c0:*/ 0x1a, 0xb7, 0x81, 0xb1, 0xd1, 0x4f, 0xb2, 0xa6, 0xea, 0xde, 0x1d, 0x9b, 0x12, 0x31, 0x3f, 0x9d, + /*08d0:*/ 0xd6, 0x68, 0x60, 0x0d, 0x12, 0x57, 0xa9, 0x0e, 0xab, 0x0a, 0xe2, 0x46, 0xf8, 0x22, 0x06, 0x3f, + /*08e0:*/ 0xa5, 0x21, 0xa1, 0xea, 0xe6, 0xd1, 0x74, 0x03, 0x14, 0xad, 0x4e, 0x60, 0x8a, 0xe1, 0x59, 0x07, + /*08f0:*/ 0x45, 0x73, 0x5c, 0x13, 0x98, 0xf1, 0x18, 0x5f, 0x26, 0xdb, 0x2c, 0xa2, 0x43, 0xe6, 0x9a, 0xf9, + /*0900:*/ 0x90, 0x16, 0xaf, 0x08, 0x7e, 0xa3, 0xba, 0x46, 0x95, 0xce, 0x18, 0x2e, 0x32, 0x73, 0x63, 0x0a, + /*0910:*/ 0xe4, 0xfb, 0x81, 0x51, 0x0f, 0x81, 0x8a, 0x6e, 0x79, 0xd3, 0x53, 0x5c, 0x95, 0x2d, 0xc3, 0x86, + /*0920:*/ 0x62, 0xd8, 0xd5, 0x64, 0xe3, 0xda, 0xb0, 0xa6, 0x3d, 0x12, 0xb4, 0xfc, 0x26, 0x84, 0x8c, 0xcf, + /*0930:*/ 0x08, 0x84, 0xab, 0xe2, 0x0e, 0x18, 0xf5, 0x6a, 0x7b, 0xcc, 0xd5, 0x27, 0x9d, 0x2b, 0x66, 0x6e, + /*0940:*/ 0x9e, 0xfe, 0x7d, 0x30, 0x2d, 0x77, 0x33, 0x0e, 0xc4, 0x74, 0xc2, 0x12, 0x10, 0x5c, 0xf4, 0xb5, + /*0950:*/ 0xe7, 0xbb, 0x96, 0xd8, 0xc6, 0x07, 0x22, 0x31, 0xd6, 0x7a, 0xd6, 0xa6, 0x86, 0xa7, 0x53, 0x31, + /*0960:*/ 0xff, 0x41, 0x87, 0xad, 0xda, 0x77, 0xe7, 0xaf, 0x36, 0xc9, 0xda, 0x41, 0x2e, 0x9d, 0xd0, 0x08, + /*0970:*/ 0x02, 0x81, 0xc1, 0x88, 0xac, 0xb4, 0x40, 0xb8, 0x4f, 0x8b, 0xb4, 0xc7, 0x7e, 0x65, 0x58, 0x68, + /*0980:*/ 0x04, 0x17, 0x69, 0xbd, 0xb5, 0xf2, 0x66, 0xf3, 0xab, 0x7b, 0x2c, 0xba, 0x63, 0x47, 0x9d, 0x17, + /*0990:*/ 0xce, 0x6d, 0x77, 0xf6, 0x25, 0x14, 0x58, 0x1c, 0xa6, 0xbc, 0xd1, 0xa6, 0x74, 0xed, 0x49, 0x55, + /*09a0:*/ 0x6d, 0x46, 0xfe, 0xdd, 0xea, 0x7b, 0x50, 0xf9, 0xb2, 0x5b, 0xa5, 0x2e, 0x7b, 0x90, 0x24, 0x51, + /*09b0:*/ 0xda, 0x35, 0x01, 0x31, 0x15, 0x15, 0xba, 0x83, 0x9b, 0x82, 0x1a, 0xe0, 0x20, 0x2a, 0xb1, 0xd7, + /*09c0:*/ 0x1b, 0x46, 0xb8, 0xea, 0xc2, 0xb8, 0x2d, 0x44, 0xe0, 0x0d, 0xd6, 0x3c, 0x9e, 0xe2, 0xcf, 0x44, + /*09d0:*/ 0x1d, 0x24, 0x58, 0xb0, 0x68, 0x0a, 0xfe, 0x05, 0x36, 0x8a, 0x96, 0x91, 0x40, 0xfa, 0x12, 0xb8, + /*09e0:*/ 0xd0, 0xf1, 0x6b, 0xd4, 0x76, 0x4e, 0x62, 0x7d, 0xf6, 0x8e, 0xe8, 0x77, 0x48, 0x02, 0xef, 0x6f, + /*09f0:*/ 0xac, 0xc6, 0xd9, 0x21, 0x96, 0x91, 0xcd, 0xf1, 0xa6, 0xe1, 0xd5, 0xd0, 0x6d, 0x62, 0x95, 0xbf, + /*0a00:*/ 0xf6, 0x91, 0x7b, 0xf0, 0xd6, 0x63, 0x6d, 0x5c, 0xd3, 0x9d, 0x8f, 0xe7, 0x3e, 0x2a, 0x82, 0xc6, + /*0a10:*/ 0x38, 0x24, 0xb0, 0x2c, 0x7d, 0x8f, 0x00, 0x26, 0xbd, 0x4c, 0xf0, 0x45, 0xc6, 0x16, 0xdd, 0x82, + /*0a20:*/ 0xa3, 0x8b, 0x32, 0xe4, 0xd8, 0xa8, 0x71, 0xca, 0x1d, 0x02, 0x4f, 0x58, 0x50, 0xd4, 0x8d, 0x21, + /*0a30:*/ 0x3a, 0x68, 0x49, 0x34, 0xac, 0x55, 0xbb, 0xc4, 0x3d, 0x9e, 0x2a, 0x90, 0x6d, 0x4b, 0x15, 0x6b, + /*0a40:*/ 0xe6, 0xe2, 0x04, 0x78, 0xe6, 0x8f, 0xd4, 0xf7, 0xce, 0x64, 0x95, 0xfb, 0xc7, 0x77, 0x6e, 0x4f, + /*0a50:*/ 0xea, 0x44, 0x2f, 0x34, 0x67, 0xbc, 0xef, 0xba, 0xe5, 0x02, 0xa0, 0x87, 0x26, 0x4f, 0x40, 0x95, + /*0a60:*/ 0x9d, 0x63, 0xcb, 0xc2, 0xdd, 0xf2, 0x31, 0x4f, 0x28, 0xee, 0x12, 0x8a, 0x5e, 0x05, 0xad, 0xd6, + /*0a70:*/ 0x55, 0x16, 0xfc, 0x3f, 0x5d, 0x35, 0x57, 0xdc, 0xef, 0x33, 0x98, 0x31, 0xb7, 0xc1, 0xe4, 0x05, + /*0a80:*/ 0x28, 0x17, 0xf0, 0x0c, 0x0e, 0x92, 0xf4, 0xa7, 0x02, 0x57, 0xb3, 0x9f, 0xcb, 0xd4, 0x83, 0x41, + /*0a90:*/ 0x50, 0xbe, 0xba, 0xe4, 0x3a, 0xdc, 0xe4, 0xc5, 0xab, 0x5b, 0xa5, 0x47, 0x81, 0xc3, 0x8b, 0x34, + /*0aa0:*/ 0x2b, 0xe7, 0x52, 0x4a, 0x0d, 0x78, 0x57, 0x1c, 0xa6, 0x50, 0x6c, 0xe0, 0x19, 0xc0, 0x12, 0xa1, + /*0ab0:*/ 0x0c, 0x54, 0x53, 0x89, 0xff, 0xbd, 0xd1, 0x2c, 0xb3, 0x59, 0xd9, 0x43, 0xc2, 0xd5, 0x92, 0xab, + /*0ac0:*/ 0xe6, 0xc9, 0xfa, 0x39, 0xec, 0x29, 0xfd, 0x17, 0xf4, 0x87, 0x3b, 0x1f, 0x16, 0x22, 0x5d, 0x1b, + /*0ad0:*/ 0x49, 0x95, 0x59, 0xe5, 0xa6, 0x7f, 0xb0, 0x25, 0x38, 0x34, 0x2d, 0x10, 0x62, 0x20, 0x3c, 0x55, + /*0ae0:*/ 0x8a, 0x5e, 0x1d, 0x31, 0x45, 0x23, 0xa9, 0x62, 0x2b, 0x35, 0x3f, 0x60, 0xe3, 0xb7, 0xf0, 0x85, + /*0af0:*/ 0xcc, 0x0b, 0xba, 0xa9, 0x1b, 0xde, 0x36, 0x65, 0x11, 0x9e, 0x69, 0x01, 0xfd, 0x3b, 0xb0, 0xa9, + /*0b00:*/ 0x99, 0x37, 0x01, 0xcf, 0x08, 0x35, 0x1b, 0x15, 0x36, 0x55, 0x40, 0x29, 0xc0, 0x67, 0x3d, 0x2e, + /*0b10:*/ 0xd3, 0xe1, 0x27, 0x5b, 0x43, 0x0d, 0xec, 0xa8, 0x1c, 0x2f, 0x75, 0x73, 0xc9, 0x91, 0x4c, 0x1b, + /*0b20:*/ 0xe0, 0x75, 0xe2, 0xcb, 0xcc, 0x15, 0x58, 0x84, 0x32, 0x88, 0xec, 0x1d, 0x68, 0x89, 0xed, 0xc5, + /*0b30:*/ 0xb5, 0xcf, 0x7c, 0xa8, 0xe4, 0x14, 0x8f, 0x76, 0x7f, 0xc3, 0xd0, 0xde, 0xd8, 0x59, 0xb1, 0x1d, + /*0b40:*/ 0xc8, 0x72, 0x68, 0x7c, 0x2a, 0x6a, 0xc2, 0x45, 0xf2, 0xbb, 0xe6, 0x48, 0x30, 0x0f, 0x37, 0xa1, + /*0b50:*/ 0x71, 0x5e, 0x98, 0xa3, 0x7d, 0x53, 0x9c, 0x21, 0xdd, 0xf6, 0x75, 0x90, 0xcd, 0xd8, 0x09, 0x9b, + /*0b60:*/ 0x0f, 0x36, 0xda, 0x1c, 0xf9, 0x18, 0xa3, 0xc2, 0x2b, 0xf0, 0xec, 0x0f, 0xff, 0x04, 0xf6, 0xfc, + /*0b70:*/ 0x39, 0x93, 0x96, 0x93, 0x5d, 0xac, 0x8a, 0x08, 0xc3, 0x10, 0xe0, 0xfc, 0xf9, 0x28, 0x97, 0x0d, + /*0b80:*/ 0x69, 0xa2, 0x55, 0x7c, 0x39, 0x66, 0xb5, 0xaf, 0x88, 0x7b, 0x56, 0x1e, 0x5b, 0xbf, 0x51, 0xf5, + /*0b90:*/ 0x75, 0x71, 0x8d, 0x2c, 0xf1, 0x6e, 0x23, 0x93, 0xbc, 0x4d, 0x0b, 0x82, 0x73, 0x57, 0x14, 0x62, + /*0ba0:*/ 0x53, 0x75, 0xd5, 0x75, 0xed, 0x96, 0x4e, 0x62, 0xf4, 0x26, 0x85, 0x33, 0x6d, 0x3f, 0xf8, 0x8b, + /*0bb0:*/ 0xcd, 0x71, 0x27, 0x83, 0xd5, 0x55, 0x2c, 0x3a, 0x2f, 0xa6, 0x52, 0xc4, 0xf5, 0xfa, 0x21, 0xc1, + /*0bc0:*/ 0xbe, 0xbe, 0x02, 0x7f, 0xc2, 0xf6, 0x8c, 0xf5, 0xa7, 0x4f, 0x7d, 0xaa, 0x0d, 0xd1, 0x50, 0x15, + /*0bd0:*/ 0xda, 0x9e, 0x94, 0x99, 0x40, 0xb2, 0x40, 0xf3, 0xc7, 0x0f, 0x3f, 0x65, 0x32, 0xd6, 0x87, 0xdc, + /*0be0:*/ 0x54, 0x27, 0xac, 0xd9, 0x5b, 0xa1, 0x8d, 0x7f, 0x7e, 0x6f, 0x71, 0xa0, 0xee, 0x56, 0x2d, 0x58, + /*0bf0:*/ 0x85, 0x1f, 0x59, 0xf0, 0x52, 0xf3, 0x76, 0x46, 0xe0, 0xd6, 0x71, 0xf7, 0xb2, 0x4f, 0xc2, 0xa6, + /*0c00:*/ 0xe6, 0x15, 0xa0, 0x5a, 0x9c, 0x13, 0xbd, 0x46, 0x44, 0xa8, 0xd2, 0x44, 0xf8, 0xec, 0xe4, 0xd1, + /*0c10:*/ 0xa2, 0x9f, 0x5b, 0xda, 0x80, 0x80, 0x37, 0x1e, 0x99, 0xbe, 0xf7, 0x3a, 0xf1, 0xa8, 0x3d, 0x16, + /*0c20:*/ 0x90, 0x5f, 0xb0, 0xa7, 0x04, 0x8d, 0x21, 0xc5, 0xa3, 0x75, 0xaf, 0x7f, 0x54, 0xe5, 0x91, 0xaf, + /*0c30:*/ 0x05, 0xf1, 0xc3, 0xf7, 0x9e, 0xf5, 0x22, 0x31, 0xc9, 0xa9, 0x23, 0x60, 0x18, 0x3f, 0xc2, 0x55, + /*0c40:*/ 0x69, 0xbe, 0x13, 0xc3, 0x22, 0x9c, 0xb7, 0x26, 0x79, 0x06, 0xdf, 0x6e, 0x37, 0x79, 0xd9, 0x88, + /*0c50:*/ 0xdf, 0xb3, 0x21, 0xc0, 0xff, 0x78, 0xdf, 0x0f, 0x58, 0x59, 0x09, 0xc5, 0x48, 0x6a, 0xc4, 0x67, + /*0c60:*/ 0x89, 0x88, 0x8e, 0x22, 0x9a, 0x0e, 0xb2, 0x82, 0x29, 0xb0, 0x2e, 0xd4, 0xaa, 0x7e, 0x82, 0xfa, + /*0c70:*/ 0x58, 0x3e, 0x63, 0x5c, 0x53, 0x6d, 0xbf, 0xbd, 0xe0, 0x68, 0x0a, 0xca, 0x6e, 0x4c, 0xc8, 0x62, + /*0c80:*/ 0xe5, 0x45, 0xa3, 0x1f, 0xf1, 0xe1, 0x0d, 0xee, 0xd2, 0xff, 0xbb, 0x18, 0x80, 0x2e, 0xc0, 0xba, + /*0c90:*/ 0x59, 0xe7, 0x51, 0x1c, 0xf0, 0x26, 0x04, 0x43, 0x7b, 0xc5, 0xec, 0x74, 0x89, 0x27, 0x7c, 0xcf, + /*0ca0:*/ 0x99, 0xbe, 0xe7, 0x7d, 0x5b, 0x2f, 0x4b, 0xa8, 0xae, 0xb9, 0xe9, 0x04, 0xa3, 0x28, 0x9b, 0x60, + /*0cb0:*/ 0x6e, 0x3b, 0x4b, 0x1e, 0x14, 0x02, 0x6b, 0x90, 0x5f, 0x54, 0xa5, 0x8e, 0x29, 0x7f, 0xcc, 0xa2, + /*0cc0:*/ 0x43, 0xd6, 0x19, 0xfc, 0xef, 0x65, 0x3f, 0xff, 0x85, 0xb8, 0xcd, 0x50, 0x17, 0x33, 0x00, 0xce, + /*0cd0:*/ 0x8c, 0xd9, 0xe1, 0x7f, 0x2d, 0x53, 0x2b, 0xe7, 0x6b, 0xe3, 0x38, 0x39, 0xbd, 0x96, 0xe6, 0x1a, + /*0ce0:*/ 0x9b, 0x9a, 0x75, 0xdc, 0x59, 0xd4, 0x7c, 0x90, 0xbd, 0x20, 0x72, 0xa2, 0x6b, 0x34, 0x86, 0x98, + /*0cf0:*/ 0x91, 0xa4, 0xf8, 0xa8, 0xaf, 0x54, 0x8a, 0x0f, 0x0a, 0xcc, 0x3d, 0x9a, 0x26, 0xbe, 0x1d, 0x3f, + /*0d00:*/ 0x8b, 0x32, 0x78, 0x47, 0x2b, 0xb3, 0x12, 0x5f, 0xf2, 0xb8, 0x63, 0x2a, 0xd3, 0x4e, 0xc1, 0xbb, + /*0d10:*/ 0x24, 0x9a, 0xac, 0x8c, 0x34, 0xe3, 0x03, 0x81, 0xbd, 0xdf, 0x5f, 0xae, 0xa4, 0x29, 0x9a, 0x17, + /*0d20:*/ 0x11, 0x31, 0xc7, 0xba, 0xcf, 0xed, 0x48, 0x68, 0x7f, 0x85, 0xfe, 0xdb, 0xfe, 0x50, 0x86, 0xe6, + /*0d30:*/ 0xbb, 0x68, 0x44, 0xa6, 0xb6, 0x5b, 0xe3, 0xf4, 0x84, 0x32, 0x3d, 0x7c, 0x4c, 0xd8, 0xf3, 0xe5, + /*0d40:*/ 0xa0, 0x3b, 0x18, 0x91, 0x7a, 0xe7, 0x56, 0x5f, 0xa1, 0xd6, 0xf0, 0xbf, 0x23, 0xf0, 0x89, 0x26, + /*0d50:*/ 0x03, 0xf8, 0x5e, 0xc6, 0x55, 0xb4, 0x78, 0x25, 0xb1, 0x4b, 0x32, 0x1b, 0xf7, 0x67, 0x37, 0xae, + /*0d60:*/ 0xc6, 0x23, 0x0e, 0x85, 0x90, 0x15, 0x3e, 0x38, 0xb4, 0x42, 0xc0, 0x77, 0xe6, 0x52, 0xa1, 0xc8, + /*0d70:*/ 0x64, 0x96, 0x63, 0x20, 0x14, 0x9c, 0xe8, 0xc8, 0x88, 0x24, 0xa3, 0x40, 0xd1, 0xb2, 0x7f, 0xed, + /*0d80:*/ 0x4a, 0xb8, 0x8e, 0x71, 0x73, 0x58, 0x7d, 0x51, 0x7e, 0xde, 0x58, 0x64, 0x6f, 0xa9, 0x19, 0xa1, + /*0d90:*/ 0x0e, 0x7f, 0x20, 0x6e, 0xfa, 0xfb, 0x9f, 0xc6, 0xd3, 0xc5, 0x4d, 0xd2, 0x1b, 0x5e, 0x8a, 0x14, + /*0da0:*/ 0xb9, 0x6a, 0xcf, 0xf6, 0x2c, 0xa0, 0x85, 0xdd, 0xa4, 0xa1, 0x0d, 0x75, 0xd0, 0x75, 0xa1, 0x07, + /*0db0:*/ 0xf4, 0x45, 0x09, 0x7a, 0xbd, 0x00, 0x03, 0xbd, 0x4c, 0x42, 0x49, 0xb2, 0x3c, 0x09, 0xd8, 0x87, + /*0dc0:*/ 0xfb, 0xa1, 0xc2, 0x1a, 0xd7, 0x16, 0xae, 0x3a, 0x0b, 0x61, 0x4b, 0x34, 0x98, 0x32, 0x77, 0x23, + /*0dd0:*/ 0xc8, 0x0b, 0x8b, 0x81, 0xed, 0xc1, 0x56, 0x8a, 0xcc, 0x79, 0x03, 0x58, 0x01, 0x57, 0xc1, 0x94, + /*0de0:*/ 0x60, 0x2c, 0x0a, 0x56, 0x12, 0xf1, 0xd8, 0xb8, 0xaa, 0x4e, 0xb5, 0x7b, 0xb5, 0xe6, 0x35, 0x1c, + /*0df0:*/ 0x20, 0x87, 0x40, 0x52, 0xd0, 0xe1, 0xf8, 0x59, 0xb3, 0xaf, 0x45, 0x0b, 0xce, 0xb0, 0xf7, 0x48, + /*0e00:*/ 0x3d, 0x60, 0x16, 0xbb, 0x1c, 0x3d, 0xf8, 0x10, 0xba, 0xfa, 0x86, 0x47, 0xb8, 0x9f, 0x89, 0x43, + /*0e10:*/ 0xc9, 0x3f, 0xa7, 0x5f, 0x3b, 0xa6, 0x30, 0x60, 0xce, 0x7a, 0x29, 0x87, 0xf1, 0x38, 0xde, 0x17, + /*0e20:*/ 0x70, 0xc5, 0x10, 0xb9, 0xa4, 0x0e, 0x13, 0x8b, 0xa9, 0x5c, 0x8a, 0xe8, 0x11, 0xfe, 0xf0, 0x0e, + /*0e30:*/ 0x63, 0x22, 0xc5, 0xeb, 0x16, 0x7a, 0x8e, 0xbc, 0x90, 0x54, 0x6e, 0x54, 0x8f, 0x41, 0xb8, 0x13, + /*0e40:*/ 0xe8, 0x2e, 0x7a, 0xaf, 0xf6, 0xcf, 0x11, 0xf8, 0xd8, 0xdf, 0x06, 0x00, 0x76, 0xa3, 0x05, 0x0a, + /*0e50:*/ 0x92, 0x37, 0xb9, 0x87, 0x84, 0x53, 0xfe, 0x6f, 0x27, 0xdc, 0xa0, 0x75, 0xd8, 0x83, 0xa7, 0xa2, + /*0e60:*/ 0x65, 0xa9, 0x45, 0x3f, 0xfe, 0xf2, 0xef, 0x4e, 0xc0, 0xc9, 0x9f, 0x58, 0xa6, 0xfd, 0x62, 0xc8, + /*0e70:*/ 0x69, 0x36, 0xd5, 0xad, 0x64, 0xc1, 0xdb, 0x55, 0x29, 0xe4, 0x37, 0xe8, 0xde, 0x1e, 0x1c, 0x80, + /*0e80:*/ 0x58, 0xb3, 0x31, 0x7a, 0x14, 0xbd, 0xde, 0x3c, 0xf9, 0x64, 0xbb, 0xb4, 0x2d, 0x4e, 0x78, 0x52, + /*0e90:*/ 0xe6, 0xba, 0x90, 0xf7, 0x36, 0xc3, 0x56, 0xaf, 0xf4, 0x06, 0xe3, 0xee, 0x12, 0x3e, 0x35, 0x41, + /*0ea0:*/ 0xcd, 0xe7, 0x3d, 0xec, 0x02, 0x8f, 0x88, 0x23, 0x7e, 0x84, 0x81, 0x24, 0x49, 0x46, 0xe9, 0x4c, + /*0eb0:*/ 0xaf, 0x7c, 0x81, 0x34, 0x63, 0xcd, 0xe0, 0x55, 0xa1, 0xdb, 0x2e, 0x8a, 0xb7, 0x08, 0x89, 0x22, + /*0ec0:*/ 0x01, 0xeb, 0xa8, 0x20, 0x90, 0xc5, 0x43, 0x51, 0xd1, 0x49, 0xa7, 0x80, 0xd8, 0xb3, 0xda, 0xcb, + /*0ed0:*/ 0x06, 0x68, 0x27, 0x0f, 0x8b, 0xc5, 0x85, 0x19, 0x8b, 0x72, 0x7f, 0x9c, 0x01, 0x9e, 0x9c, 0x89, + /*0ee0:*/ 0xb2, 0x95, 0xe0, 0xcb, 0x15, 0xd8, 0xc7, 0x60, 0x48, 0x93, 0x24, 0x18, 0x78, 0xc0, 0x8b, 0x40, + /*0ef0:*/ 0x5a, 0x2f, 0xe9, 0xc9, 0xc4, 0xec, 0xb3, 0x26, 0xb5, 0xdf, 0x88, 0x1b, 0xf3, 0x4f, 0x0e, 0xe4, + /*0f00:*/ 0xc0, 0x7c, 0x07, 0xf1, 0xcd, 0xa6, 0xb2, 0x8e, 0x53, 0x74, 0x42, 0x89, 0xb5, 0x8c, 0xa7, 0xcc, + /*0f10:*/ 0x22, 0x2a, 0x15, 0x6c, 0xc8, 0x45, 0xdf, 0x88, 0xbc, 0xec, 0x64, 0xea, 0x73, 0x22, 0xde, 0xe4, + /*0f20:*/ 0xb1, 0x55, 0x66, 0x37, 0xbc, 0x8d, 0x67, 0x60, 0x13, 0xcb, 0xc2, 0x3e, 0xe1, 0x5f, 0x9c, 0x90, + /*0f30:*/ 0xc8, 0xa5, 0x8e, 0x70, 0x48, 0xf3, 0xcd, 0xcf, 0x3b, 0x73, 0xfc, 0x98, 0x0f, 0xa0, 0x2e, 0x6e, + /*0f40:*/ 0x53, 0xfc, 0xcb, 0xd9, 0x2e, 0x7e, 0x9e, 0x2f, 0x66, 0x23, 0xd4, 0xe3, 0xb5, 0xda, 0xb0, 0xef, + /*0f50:*/ 0x7c, 0x28, 0xc4, 0xe3, 0x6b, 0xeb, 0x28, 0x06, 0x83, 0xcd, 0x58, 0xd1, 0xa4, 0x08, 0x73, 0x36, + /*0f60:*/ 0x7d, 0x87, 0xdf, 0x67, 0x72, 0x23, 0x8a, 0x8d, 0xce, 0x4d, 0xcd, 0x95, 0x7e, 0xec, 0x8e, 0x9e, + /*0f70:*/ 0x0c, 0x21, 0x09, 0x89, 0x4b, 0x2e, 0x86, 0xd7, 0x1b, 0x7e, 0xbc, 0x67, 0x17, 0x4d, 0x18, 0xa7, + /*0f80:*/ 0xba, 0xca, 0x25, 0x30, 0x2d, 0x72, 0xb1, 0xfe, 0x49, 0xd9, 0xdc, 0x54, 0x8e, 0x81, 0x47, 0x50, + /*0f90:*/ 0x03, 0x95, 0xb4, 0xb6, 0x37, 0x36, 0xeb, 0xc4, 0xc3, 0x9d, 0x90, 0xaf, 0x24, 0x03, 0x6d, 0x78, + /*0fa0:*/ 0x35, 0x12, 0x17, 0x64, 0xb3, 0xb5, 0x20, 0xf5, 0xc6, 0xc1, 0xd2, 0xdd, 0xa8, 0x5f, 0xdb, 0xc8, + /*0fb0:*/ 0xc2, 0xa9, 0xbd, 0x38, 0x9a, 0xc2, 0x75, 0x29, 0xca, 0xb2, 0x5f, 0x02, 0x9d, 0x02, 0x25, 0x12, + /*0fc0:*/ 0x2a, 0x90, 0x56, 0x93, 0x1b, 0xcd, 0x5c, 0x75, 0x73, 0xdc, 0xeb, 0x03, 0x62, 0x52, 0x02, 0x6d, + /*0fd0:*/ 0x14, 0x20, 0xeb, 0x16, 0x2a, 0x08, 0x1c, 0x0f, 0xbb, 0x36, 0x0a, 0x0a, 0x9f, 0x44, 0x1c, 0xb5, + /*0fe0:*/ 0xb7, 0x60, 0x82, 0xcc, 0x33, 0xa0, 0x53, 0xb3, 0xb7, 0xe5, 0xc5, 0x9a, 0xb7, 0xa3, 0xf2, 0x2e, + /*0ff0:*/ 0x85, 0x8b, 0xc9, 0x5c, 0xe9, 0x22, 0x82, 0xb1, 0x23, 0x7f, 0x39, 0xf6, 0xd8, 0x6e, 0x1a, 0xb4, + /*1000:*/ 0xb8, 0xe2, 0x6f, 0x88, 0xe1, 0x34, 0x48, 0x15, 0xb1, 0x37, 0x42, 0x64, 0xe1, 0xb6, 0xc6, 0x7a, + /*1010:*/ 0x21, 0x55, 0x20, 0x11, 0x29, 0x1b, 0xc3, 0x81, 0x1e, 0x43, 0x28, 0xb0, 0x2c, 0x0c, 0x71, 0x04, + /*1020:*/ 0x24, 0xde, 0xbb, 0x81, 0xac, 0xb7, 0xb5, 0xda, 0xf9, 0x85, 0x78, 0x2c, 0xdb, 0xfb, 0x1f, 0xed, + /*1030:*/ 0x95, 0xd6, 0x67, 0x04, 0xa7, 0xde, 0xc4, 0x00, 0x6a, 0xf4, 0x97, 0xe6, 0xa5, 0x46, 0x9f, 0x42, + /*1040:*/ 0x68, 0x79, 0xea, 0xcd, 0xfa, 0xb1, 0xb0, 0x97, 0xfc, 0x78, 0xc3, 0xa8, 0xcc, 0xdd, 0x09, 0x9b, + /*1050:*/ 0x93, 0x5b, 0x0a, 0xd2, 0xe4, 0x42, 0x98, 0x61, 0xbe, 0xa2, 0xbe, 0x8f, 0xf4, 0x1f, 0x1a, 0xeb, + /*1060:*/ 0xda, 0x59, 0x1e, 0xe5, 0x8e, 0x41, 0x3c, 0x96, 0x14, 0xb9, 0xb0, 0x16, 0x07, 0x38, 0xa4, 0xc9, + /*1070:*/ 0xb3, 0xff, 0xb4, 0xf1, 0xed, 0xe7, 0xe5, 0x4e, 0x21, 0x90, 0x5f, 0x35, 0x6e, 0x9f, 0xfb, 0xd3, + /*1080:*/ 0x57, 0x86, 0x12, 0xe1, 0xde, 0x74, 0x33, 0xe5, 0xf3, 0x29, 0x3f, 0xe6, 0x49, 0x30, 0xae, 0xaa, + /*1090:*/ 0x62, 0xaf, 0xd5, 0x1f, 0xc8, 0xca, 0x4f, 0xea, 0x00, 0xda, 0x4e, 0xba, 0x21, 0x5f, 0xeb, 0x85, + /*10a0:*/ 0xa9, 0x77, 0xce, 0x2e, 0x98, 0xa5, 0xa0, 0x22, 0x12, 0x9f, 0x15, 0xaa, 0x25, 0xd9, 0x65, 0x03, + /*10b0:*/ 0x7b, 0xda, 0x3e, 0x29, 0xb1, 0x94, 0x5f, 0x9b, 0x7d, 0x0e, 0xf0, 0xe3, 0x29, 0x95, 0xef, 0xc5, + /*10c0:*/ 0x0b, 0x97, 0x61, 0x8b, 0xa2, 0x03, 0xe1, 0x33, 0x76, 0x0c, 0xb7, 0xe6, 0xaa, 0x4d, 0x66, 0xc1, + /*10d0:*/ 0x5c, 0x9c, 0xa9, 0x36, 0xef, 0xda, 0xe4, 0xad, 0xed, 0xbf, 0x93, 0x9a, 0xdd, 0xa4, 0x52, 0xcb, + /*10e0:*/ 0x5f, 0xdb, 0x61, 0x82, 0xfe, 0x77, 0x86, 0x28, 0x33, 0x3d, 0x90, 0xbb, 0x86, 0x6a, 0xb3, 0x15, + /*10f0:*/ 0x2f, 0x91, 0xfe, 0x99, 0x18, 0xb9, 0xe9, 0x47, 0x27, 0xfe, 0x78, 0x07, 0x33, 0xa0, 0x96, 0xb8, + /*1100:*/ 0x06, 0x09, 0x74, 0xad, 0x1a, 0x75, 0x49, 0xbe, 0x35, 0xe9, 0x18, 0x1a, 0x79, 0x31, 0x9f, 0xf2, + /*1110:*/ 0x35, 0x4f, 0xa9, 0xf4, 0xfa, 0x64, 0x20, 0xbb, 0x0d, 0x65, 0x1f, 0x80, 0x5b, 0x8d, 0x83, 0xca, + /*1120:*/ 0x2a, 0x42, 0xea, 0x84, 0x15, 0x6e, 0xd3, 0xbb, 0x51, 0xe5, 0x65, 0x95, 0x44, 0x09, 0x56, 0x50, + /*1130:*/ 0x53, 0x8f, 0xbb, 0xd9, 0xf7, 0x5d, 0xc9, 0xdf, 0x16, 0x95, 0xa6, 0x8a, 0x22, 0x29, 0xd9, 0x00, + /*1140:*/ 0xcf, 0x55, 0xab, 0xc8, 0x90, 0x96, 0x8f, 0x07, 0xdd, 0x0b, 0x40, 0xb6, 0xde, 0xd3, 0x1d, 0x96, + /*1150:*/ 0x58, 0xff, 0x89, 0x25, 0xfb, 0x2d, 0x0c, 0xcc, 0x05, 0xb4, 0xe9, 0x47, 0x60, 0xeb, 0xb4, 0xe2, + /*1160:*/ 0x24, 0x99, 0xb9, 0xf1, 0x88, 0xba, 0x1e, 0xd3, 0x16, 0xa7, 0x6e, 0x44, 0x48, 0x57, 0x90, 0x04, + /*1170:*/ 0x37, 0x94, 0xd3, 0x42, 0x1c, 0xbd, 0x51, 0x2c, 0x0d, 0x4f, 0x71, 0xf8, 0x98, 0x71, 0x16, 0x48, + /*1180:*/ 0x53, 0x2b, 0x62, 0x90, 0x21, 0xc3, 0xbf, 0xf4, 0x83, 0x11, 0xb5, 0xd4, 0xc7, 0xe4, 0x73, 0x65, + /*1190:*/ 0xed, 0x01, 0x49, 0xf2, 0xb1, 0x1b, 0xb8, 0x6c, 0xce, 0x55, 0xe1, 0xa7, 0x58, 0xf0, 0x2f, 0x24, + /*11a0:*/ 0xf5, 0xc1, 0x26, 0x02, 0x78, 0x66, 0x48, 0x7d, 0x2f, 0xb9, 0x81, 0x4b, 0xac, 0x73, 0x6d, 0x0d, + /*11b0:*/ 0xfd, 0xe6, 0x27, 0xa8, 0x3a, 0xcd, 0x35, 0x4d, 0xa4, 0xc8, 0xf7, 0xb5, 0x2c, 0xa0, 0xa6, 0x4a, + /*11c0:*/ 0x57, 0xb8, 0x62, 0xb3, 0xd7, 0xd4, 0x2a, 0xa9, 0xa5, 0x93, 0x5b, 0x23, 0x0f, 0x88, 0xb3, 0x69, + /*11d0:*/ 0xd2, 0x89, 0x21, 0x66, 0x9c, 0x4a, 0x40, 0xce, 0x22, 0x0d, 0xcf, 0xff, 0x1b, 0x60, 0xae, 0xff, + /*11e0:*/ 0x10, 0xb0, 0xfb, 0x5c, 0x02, 0x26, 0x72, 0x3d, 0xb1, 0x9b, 0x7e, 0xab, 0x18, 0xba, 0x0a, 0x49, + /*11f0:*/ 0xf0, 0x1f, 0xfd, 0x53, 0xa7, 0x96, 0xe8, 0xf7, 0xde, 0xab, 0xf0, 0x72, 0xce, 0x21, 0xb9, 0xb9, + /*1200:*/ 0x8f, 0x14, 0xb5, 0x13, 0x37, 0x61, 0x72, 0x73, 0xa3, 0xca, 0x5c, 0x63, 0x60, 0xe4, 0x99, 0xd5, + /*1210:*/ 0x6f, 0x38, 0x72, 0x7e, 0xa4, 0xf6, 0xc9, 0xb7, 0xc4, 0x66, 0xd9, 0xdd, 0x50, 0x2c, 0x56, 0x21, + /*1220:*/ 0x66, 0x3f, 0x3b, 0xc4, 0x28, 0x50, 0x87, 0x9b, 0x2f, 0xec, 0x71, 0xd8, 0x3a, 0x1b, 0x71, 0x97, + /*1230:*/ 0x2d, 0xf3, 0x59, 0xdf, 0x3d, 0xc6, 0x22, 0x44, 0xa2, 0xf0, 0x8f, 0xed, 0x6a, 0x11, 0x03, 0x49, + /*1240:*/ 0x8f, 0x86, 0x98, 0xc7, 0x34, 0xc6, 0x20, 0x1f, 0x96, 0x39, 0x2e, 0x6e, 0xa3, 0x5f, 0x26, 0x17, + /*1250:*/ 0xaf, 0x24, 0x7a, 0x70, 0x3d, 0x23, 0x30, 0x97, 0x4d, 0xf5, 0x9c, 0x9c, 0xfe, 0x64, 0x15, 0x99, + /*1260:*/ 0xee, 0x9e, 0xb1, 0x85, 0x28, 0xe8, 0xcd, 0xc8, 0x3a, 0x5e, 0x8f, 0x0c, 0x20, 0x48, 0x56, 0x62, + /*1270:*/ 0x88, 0xf8, 0x70, 0x0c, 0xee, 0x60, 0x12, 0xbf, 0xee, 0xa8, 0x94, 0xe6, 0x03, 0x10, 0x1f, 0x6e, + /*1280:*/ 0x5c, 0x60, 0x27, 0x5e, 0x64, 0xa3, 0x65, 0x88, 0xe6, 0x65, 0x53, 0xc3, 0xe8, 0x9c, 0xd5, 0xc6, + /*1290:*/ 0xe5, 0x55, 0x19, 0xdc, 0xc6, 0x9f, 0x80, 0x65, 0x35, 0x32, 0xea, 0xd1, 0xb4, 0x4f, 0xf8, 0x0b, + /*12a0:*/ 0xc5, 0x53, 0x74, 0x61, 0x01, 0xb6, 0x0b, 0x60, 0x46, 0x54, 0xd7, 0x21, 0x7e, 0x90, 0xc5, 0x7e, + /*12b0:*/ 0x38, 0xd6, 0x5c, 0x70, 0x02, 0x44, 0x35, 0xc9, 0x83, 0xb6, 0x7b, 0x47, 0xb6, 0xb8, 0x22, 0x39, + /*12c0:*/ 0x87, 0x10, 0xe0, 0x72, 0xec, 0x04, 0x86, 0x62, 0xfe, 0xb8, 0xf3, 0x2d, 0x63, 0x39, 0xd0, 0x6f, + /*12d0:*/ 0x23, 0x80, 0xc1, 0x51, 0xd5, 0xeb, 0x4a, 0x8d, 0x03, 0xce, 0xb9, 0xf1, 0x59, 0x13, 0x6f, 0xc8, + /*12e0:*/ 0x03, 0x64, 0x6e, 0x1b, 0x8b, 0x24, 0xe0, 0x91, 0x0b, 0xbb, 0x9d, 0x34, 0x13, 0x42, 0xf6, 0xd4, + /*12f0:*/ 0x0c, 0xe9, 0xb9, 0x4c, 0x5b, 0xb5, 0xd0, 0x18, 0x11, 0x80, 0x78, 0x1c, 0xfc, 0x89, 0xe8, 0xb2, + /*1300:*/ 0xde, 0xf7, 0x01, 0x2a, 0x07, 0x39, 0x8f, 0x4e, 0x34, 0xce, 0xf8, 0xd1, 0x86, 0x44, 0x02, 0xc4, + /*1310:*/ 0x3e, 0xd7, 0x8e, 0x49, 0x2e, 0x84, 0x86, 0x6d, 0x4f, 0x67, 0xbf, 0x80, 0x2d, 0xe2, 0x5a, 0x1b, + /*1320:*/ 0xed, 0xbe, 0xd2, 0x41, 0x25, 0x78, 0x53, 0x1c, 0x04, 0xa8, 0x2f, 0x9c, 0x4e, 0xaf, 0x8c, 0x97, + /*1330:*/ 0x38, 0xac, 0x56, 0xd9, 0x81, 0x08, 0x91, 0x0c, 0xf0, 0x20, 0xdb, 0x0a, 0x68, 0x87, 0x3f, 0x44, + /*1340:*/ 0xd5, 0xee, 0xb1, 0x04, 0x09, 0x42, 0x86, 0xd2, 0x5c, 0xd9, 0xa9, 0x6d, 0x52, 0x68, 0xd9, 0x29, + /*1350:*/ 0x82, 0x42, 0xbb, 0x2a, 0xc9, 0x7e, 0x9b, 0x8f, 0x57, 0xcf, 0x90, 0xf0, 0x7e, 0xd6, 0x42, 0xef, + /*1360:*/ 0xd2, 0xf4, 0xbe, 0xae, 0x6e, 0xdb, 0x71, 0xe5, 0xb8, 0xe0, 0x11, 0x20, 0x8b, 0xfd, 0x96, 0x59, + /*1370:*/ 0x48, 0x94, 0x49, 0xf0, 0x3d, 0x37, 0xa7, 0xa4, 0x7d, 0x5e, 0x93, 0x0b, 0x55, 0x92, 0x7a, 0x69, + /*1380:*/ 0xdc, 0x9f, 0xb5, 0x0e, 0xe7, 0x4a, 0x60, 0x3f, 0x44, 0x6a, 0x93, 0x52, 0x6a, 0x6f, 0x18, 0xf9, + /*1390:*/ 0xda, 0x98, 0x94, 0x38, 0xb7, 0x45, 0x4a, 0xcf, 0xb1, 0xc5, 0xf7, 0x03, 0x39, 0x8a, 0x21, 0x07, + /*13a0:*/ 0xb1, 0x3f, 0x53, 0x5a, 0xde, 0xde, 0xee, 0xf5, 0xbd, 0x1d, 0xb3, 0xea, 0xa2, 0x0e, 0x0c, 0xe4, + /*13b0:*/ 0xd2, 0x25, 0x45, 0xc5, 0x29, 0xfa, 0x9e, 0x3a, 0x75, 0x8a, 0x75, 0x3e, 0x3b, 0x8e, 0x82, 0xea, + /*13c0:*/ 0xef, 0x7e, 0x1e, 0x4c, 0xb4, 0x26, 0x15, 0x19, 0x82, 0x40, 0x12, 0xe1, 0x04, 0x4c, 0x48, 0x24, + /*13d0:*/ 0xad, 0xed, 0x4b, 0xe8, 0xc5, 0x0c, 0x15, 0x91, 0x22, 0x7f, 0xb5, 0xd0, 0x9e, 0x73, 0x6e, 0x59, + /*13e0:*/ 0xd0, 0xfb, 0x26, 0xb2, 0x2a, 0x60, 0xdb, 0x1c, 0xd0, 0x86, 0xd6, 0x7d, 0xdd, 0xfe, 0x64, 0x1c, + /*13f0:*/ 0xd2, 0xb1, 0x9e, 0x73, 0xeb, 0x5b, 0x99, 0x4b, 0x13, 0x14, 0xc2, 0xf3, 0x20, 0xdf, 0x55, 0xc1, + /*1400:*/ 0x57, 0xf2, 0x13, 0x0f, 0xc9, 0x8f, 0xa1, 0x7e, 0x94, 0x1f, 0xff, 0xf6, 0x78, 0x8c, 0x46, 0xf9, + /*1410:*/ 0xd1, 0x99, 0xa3, 0xe9, 0xe8, 0x0e, 0x97, 0x00, 0xde, 0x34, 0xd9, 0x14, 0xd7, 0x1e, 0xa4, 0x83, + /*1420:*/ 0x39, 0xa9, 0xda, 0x7c, 0x47, 0x54, 0x40, 0x45, 0x13, 0x49, 0x55, 0x7d, 0x00, 0x79, 0xb0, 0x00, + /*1430:*/ 0x32, 0x1b, 0x3b, 0x53, 0xc9, 0x96, 0x1c, 0xb4, 0xb3, 0xac, 0xaa, 0x67, 0xbb, 0x42, 0xaa, 0xcf, + /*1440:*/ 0x81, 0x08, 0x5a, 0x56, 0x3e, 0x0e, 0x41, 0x18, 0xdb, 0xe7, 0x99, 0xd0, 0x0e, 0xe9, 0x40, 0x1b, + /*1450:*/ 0xc7, 0x6a, 0x57, 0x12, 0x89, 0x64, 0xb6, 0x1d, 0xd1, 0xd6, 0x04, 0xa5, 0xa1, 0xb0, 0xe9, 0x46, + /*1460:*/ 0x32, 0x88, 0x9b, 0x39, 0x06, 0xab, 0x4f, 0xef, 0xef, 0x49, 0xfb, 0x42, 0x58, 0x01, 0xcc, 0x29, + /*1470:*/ 0x53, 0x06, 0xc7, 0xb2, 0x09, 0x63, 0xff, 0xd3, 0x7d, 0xb3, 0xbb, 0x54, 0xd3, 0x2c, 0x7e, 0x4b, + /*1480:*/ 0xf8, 0x05, 0x7e, 0xb3, 0x55, 0x38, 0xc9, 0x92, 0x15, 0x12, 0xd4, 0xde, 0x38, 0x29, 0x8d, 0xcf, + /*1490:*/ 0xaa, 0xc4, 0x88, 0x61, 0x36, 0x34, 0x95, 0x3c, 0x48, 0xfb, 0xec, 0x5e, 0xdf, 0x72, 0x83, 0xff, + /*14a0:*/ 0xe7, 0x8f, 0x72, 0x1a, 0xaf, 0xa8, 0xef, 0xbf, 0xbe, 0xb7, 0x57, 0xa8, 0xa4, 0xe0, 0x80, 0x2a, + /*14b0:*/ 0x45, 0x3a, 0xf0, 0x80, 0x5d, 0xd5, 0x3a, 0x3c, 0x03, 0x77, 0x66, 0xd1, 0x46, 0xb0, 0x92, 0x2e, + /*14c0:*/ 0x54, 0xce, 0xe5, 0x08, 0x00, 0xfd, 0x84, 0xf0, 0x0d, 0x2f, 0xd9, 0x9b, 0x73, 0x31, 0x40, 0x53, + /*14d0:*/ 0x66, 0x2d, 0xd1, 0x84, 0xc8, 0xfe, 0x1a, 0xdf, 0xd4, 0x4a, 0x80, 0x30, 0x56, 0xc3, 0x26, 0x3b, + /*14e0:*/ 0x61, 0xde, 0x37, 0x34, 0x08, 0xbd, 0x40, 0xd8, 0x5e, 0xdf, 0x45, 0xf4, 0xe4, 0x2b, 0xf7, 0x4b, + /*14f0:*/ 0x8f, 0xf5, 0xa7, 0x70, 0x50, 0x25, 0x48, 0x18, 0xfd, 0x1a, 0xb5, 0xfd, 0xf2, 0x6a, 0xb4, 0x1b, + /*1500:*/ 0x44, 0xd5, 0x3f, 0x59, 0x23, 0x4b, 0x96, 0x7e, 0x72, 0x3a, 0xf1, 0x6e, 0x13, 0x40, 0x7b, 0x17, + /*1510:*/ 0x20, 0x09, 0xf2, 0x09, 0xb7, 0x77, 0xd3, 0x4e, 0x21, 0xbf, 0xac, 0x16, 0x2c, 0x9c, 0x95, 0x17, + /*1520:*/ 0xd1, 0x4b, 0x55, 0x00, 0x8a, 0xff, 0x4e, 0x25, 0x59, 0xba, 0xad, 0x4c, 0xf9, 0x17, 0xce, 0xec, + /*1530:*/ 0x1e, 0xdd, 0xfb, 0xb0, 0x4f, 0x5d, 0xca, 0xe8, 0x29, 0xb1, 0xba, 0x5e, 0x77, 0x2c, 0xf2, 0xa3, + /*1540:*/ 0x26, 0x86, 0x39, 0x86, 0x9d, 0xa4, 0xd5, 0x0a, 0x94, 0xea, 0xbf, 0x39, 0xc4, 0x21, 0x4c, 0xd7, + /*1550:*/ 0x5f, 0xdb, 0xdd, 0x10, 0x14, 0x81, 0x45, 0x36, 0xe4, 0xe5, 0xcc, 0x84, 0x8f, 0x8c, 0xa3, 0xee, + /*1560:*/ 0x23, 0x0e, 0x1c, 0xf9, 0x23, 0xa7, 0x48, 0xac, 0x69, 0xfc, 0x09, 0x30, 0xf6, 0x2c, 0x44, 0x04, + /*1570:*/ 0xe7, 0x3f, 0xc1, 0xeb, 0xb7, 0x28, 0x1b, 0x1f, 0xe0, 0x47, 0x54, 0x41, 0xf8, 0x4f, 0x6c, 0xb4, + /*1580:*/ 0xb3, 0x23, 0x1f, 0x7c, 0xb2, 0xfc, 0x96, 0x1a, 0xf1, 0x37, 0x28, 0x66, 0xf8, 0xa8, 0x6b, 0xe1, + /*1590:*/ 0x4b, 0xb5, 0x61, 0xf2, 0xd2, 0xa7, 0x8c, 0xfc, 0x24, 0x3e, 0x4e, 0xc7, 0x00, 0xd4, 0x20, 0x06, + /*15a0:*/ 0x1f, 0xe3, 0x48, 0xe5, 0x95, 0x2c, 0xa7, 0x10, 0x55, 0x5f, 0xe2, 0x51, 0x8d, 0x80, 0x7c, 0x2d, + /*15b0:*/ 0x86, 0x05, 0x1e, 0x95, 0xd1, 0x19, 0xe1, 0xe9, 0x1f, 0x94, 0x26, 0x82, 0x57, 0x8b, 0x63, 0xd2, + /*15c0:*/ 0xa7, 0xff, 0xb1, 0x5a, 0x82, 0x87, 0xd2, 0xc6, 0x1a, 0x01, 0xa2, 0xa6, 0xe9, 0xc1, 0x09, 0xb7, + /*15d0:*/ 0xc1, 0x00, 0x92, 0xdf, 0x2a, 0xee, 0xb7, 0xb0, 0x89, 0xf5, 0x23, 0x24, 0xac, 0xf3, 0xc9, 0xfc, + /*15e0:*/ 0xd2, 0x26, 0xdc, 0x0b, 0xf4, 0x00, 0xbb, 0x39, 0x74, 0xe8, 0x31, 0xa2, 0xbb, 0x5b, 0x79, 0xcd, + /*15f0:*/ 0x09, 0x89, 0x45, 0x29, 0xba, 0xee, 0x42, 0x5c, 0x38, 0xa1, 0xd2, 0x94, 0xaa, 0x26, 0x31, 0x6d, + /*1600:*/ 0x74, 0xec, 0xb0, 0xdb, 0xfc, 0x70, 0x70, 0xf3, 0x3e, 0xa2, 0x5f, 0xef, 0xab, 0xbc, 0x2c, 0xc2, + /*1610:*/ 0x17, 0xc9, 0x3b, 0xd0, 0xba, 0xf9, 0x4a, 0x54, 0x43, 0x8e, 0xc7, 0x96, 0x1c, 0x66, 0x0e, 0x25, + /*1620:*/ 0xb6, 0x62, 0x08, 0x51, 0x57, 0x1f, 0x5d, 0xfa, 0x16, 0x8b, 0x14, 0x06, 0x20, 0x01, 0x79, 0xda, + /*1630:*/ 0xc9, 0x41, 0x59, 0x33, 0x38, 0xb6, 0x92, 0xe9, 0xea, 0x6d, 0x03, 0x75, 0x86, 0xa1, 0x6f, 0xb7, + /*1640:*/ 0x15, 0xe2, 0xa4, 0x48, 0x7d, 0xa3, 0x89, 0x72, 0x38, 0xfc, 0xab, 0x06, 0xac, 0x9e, 0xc7, 0xa0, + /*1650:*/ 0x94, 0x51, 0x5c, 0x7a, 0xea, 0x80, 0xc8, 0x7d, 0xf6, 0x7d, 0xbf, 0x42, 0xdb, 0x04, 0x62, 0x9e, + /*1660:*/ 0xba, 0x05, 0x1f, 0xaa, 0x94, 0x62, 0xfc, 0x83, 0xa2, 0x96, 0x71, 0xe5, 0x89, 0x70, 0xc1, 0x17, + /*1670:*/ 0x25, 0xd3, 0x40, 0x0d, 0x25, 0x25, 0x19, 0xb8, 0x13, 0xba, 0x50, 0x30, 0xab, 0x97, 0x0d, 0x3c, + /*1680:*/ 0x73, 0xa5, 0x86, 0xa7, 0x37, 0x99, 0xa8, 0xff, 0x37, 0xeb, 0x1a, 0xca, 0x80, 0xe9, 0xda, 0xb6, + /*1690:*/ 0x1c, 0xbc, 0x29, 0x6f, 0x96, 0x50, 0x28, 0xd1, 0x63, 0x17, 0x1b, 0xb4, 0xfa, 0x3c, 0x9b, 0x30, + /*16a0:*/ 0xa2, 0xe2, 0x76, 0x5d, 0x6e, 0x07, 0xef, 0xb2, 0x20, 0x83, 0x26, 0x13, 0x1d, 0xd0, 0x35, 0x17, + /*16b0:*/ 0x49, 0xf8, 0x38, 0x88, 0xeb, 0x18, 0xd1, 0x8f, 0x54, 0x96, 0x70, 0x42, 0x4c, 0x7c, 0x42, 0x21, + /*16c0:*/ 0xba, 0x4a, 0xb5, 0xc0, 0x07, 0xee, 0x00, 0xe4, 0x0f, 0x9c, 0xe5, 0x57, 0xaf, 0x18, 0x38, 0x0c, + /*16d0:*/ 0x0e, 0x08, 0x61, 0x76, 0xb8, 0xf4, 0x91, 0x73, 0xa3, 0xab, 0x54, 0x8c, 0x84, 0x4e, 0xff, 0xee, + /*16e0:*/ 0x36, 0x1c, 0x95, 0x31, 0x29, 0x6b, 0x52, 0xeb, 0x77, 0x78, 0xed, 0x17, 0x00, 0xbf, 0x71, 0x4a, + /*16f0:*/ 0x44, 0x5f, 0xfe, 0xb1, 0x14, 0xe5, 0xf2, 0xa5, 0x25, 0x4d, 0x90, 0x61, 0x97, 0x83, 0x27, 0xff, + /*1700:*/ 0xa9, 0x04, 0xd2, 0xcc, 0xfe, 0xae, 0xf0, 0x31, 0x90, 0x2d, 0xcb, 0xea, 0x8e, 0xd9, 0xbf, 0x66, + /*1710:*/ 0x32, 0xbb, 0x23, 0xf5, 0x97, 0xf7, 0xf4, 0x00, 0xd9, 0x18, 0xf7, 0x49, 0xc8, 0x6c, 0xb7, 0xa7, + /*1720:*/ 0xb4, 0x94, 0x25, 0x8d, 0xe6, 0xfc, 0x04, 0x70, 0x52, 0x8a, 0x3c, 0x73, 0x83, 0x54, 0xd6, 0x80, + /*1730:*/ 0x78, 0x17, 0xb8, 0xe8, 0xf1, 0x81, 0x5c, 0xc9, 0x02, 0x81, 0xe2, 0x79, 0x28, 0xa1, 0x2a, 0x1a, + /*1740:*/ 0x88, 0xa5, 0xcf, 0x00, 0x69, 0xeb, 0xff, 0x47, 0x24, 0x37, 0x3c, 0x61, 0x9e, 0x8a, 0xa9, 0x5e, + /*1750:*/ 0xc7, 0xe6, 0xe3, 0x39, 0x39, 0x5e, 0x24, 0x8e, 0x47, 0x2d, 0x86, 0x37, 0x3c, 0xfd, 0x4b, 0xf2, + /*1760:*/ 0xfd, 0x16, 0xa7, 0x3f, 0x0c, 0x90, 0x99, 0x81, 0x91, 0x98, 0x76, 0x8e, 0xd9, 0xc4, 0x87, 0x9c, + /*1770:*/ 0x5e, 0xaa, 0x8f, 0xa1, 0x12, 0xc8, 0x7a, 0x55, 0x63, 0x43, 0x80, 0x38, 0xa5, 0x92, 0x51, 0x20, + /*1780:*/ 0x74, 0x98, 0xb3, 0x05, 0xc8, 0xf1, 0xae, 0xe1, 0xf8, 0x7c, 0x73, 0x63, 0xe7, 0x6c, 0x70, 0x43, + /*1790:*/ 0x1a, 0xed, 0x1c, 0xd5, 0x44, 0x7f, 0x89, 0x4f, 0x92, 0x38, 0x02, 0x05, 0x8d, 0x1e, 0x71, 0x44, + /*17a0:*/ 0x31, 0x10, 0xc9, 0xae, 0xb0, 0x6e, 0x62, 0xd3, 0xd6, 0x00, 0x99, 0xa7, 0x1b, 0x81, 0xc2, 0x4f, + /*17b0:*/ 0x81, 0x5c, 0xf3, 0x30, 0xe6, 0x80, 0xc2, 0xa7, 0x1c, 0x42, 0xbb, 0x61, 0xd9, 0xd2, 0x0d, 0xe2, + /*17c0:*/ 0xc3, 0xd1, 0x9c, 0x28, 0xda, 0xb4, 0x62, 0x8b, 0x48, 0x56, 0x97, 0x08, 0x23, 0x94, 0x96, 0xa3, + /*17d0:*/ 0x98, 0x66, 0x39, 0x36, 0xd3, 0xb5, 0x67, 0x0c, 0x01, 0x3c, 0x12, 0xda, 0xc9, 0x42, 0x25, 0x47, + /*17e0:*/ 0xeb, 0x29, 0xe5, 0x53, 0xc8, 0x12, 0x98, 0x44, 0x6f, 0x73, 0x4f, 0x7c, 0x5f, 0xcd, 0x69, 0x02, + /*17f0:*/ 0x5b, 0x3c, 0xad, 0xc9, 0xcb, 0xd4, 0xe5, 0x8d, 0x5c, 0x73, 0xa0, 0x9d, 0x51, 0xf4, 0x99, 0x19, + /*1800:*/ 0xe1, 0xe0, 0x22, 0xcf, 0x00, 0xbd, 0x63, 0xab, 0xd7, 0x9b, 0xb6, 0x2a, 0xdd, 0xa1, 0x1e, 0x3d, + /*1810:*/ 0x19, 0xe0, 0x63, 0x6f, 0x3f, 0xf6, 0x4a, 0x70, 0xd8, 0x6d, 0x73, 0xa7, 0x88, 0xbc, 0xcd, 0x7d, + /*1820:*/ 0xae, 0xe2, 0xe4, 0x2b, 0x63, 0x44, 0x29, 0x83, 0xfc, 0x3b, 0x69, 0x9f, 0x11, 0x8e, 0xee, 0xf5, + /*1830:*/ 0xb0, 0x38, 0xd2, 0x71, 0xe3, 0x90, 0xde, 0x04, 0x81, 0x29, 0xbf, 0xc7, 0x4d, 0xb9, 0xf2, 0x29, + /*1840:*/ 0x57, 0xc3, 0xa5, 0x41, 0x3f, 0x1b, 0x70, 0xec, 0x48, 0x97, 0xee, 0xb9, 0xce, 0xfd, 0xbb, 0x74, + /*1850:*/ 0x12, 0xf4, 0x57, 0x4b, 0x44, 0xcd, 0x6c, 0xdd, 0xd6, 0xd5, 0x0f, 0xa0, 0xc9, 0x40, 0x52, 0x8f, + /*1860:*/ 0x8c, 0x22, 0x4e, 0xb2, 0x3c, 0x12, 0x5a, 0x13, 0x1f, 0x24, 0xcc, 0xb8, 0xd2, 0xa6, 0xb4, 0xe1, + /*1870:*/ 0x22, 0x71, 0x96, 0x48, 0xf3, 0x08, 0xd5, 0x55, 0x20, 0x71, 0x1e, 0x9b, 0x51, 0x56, 0xf3, 0x81, + /*1880:*/ 0x3f, 0x3b, 0x4c, 0xe7, 0x67, 0xa4, 0x24, 0x1c, 0x84, 0x4d, 0x57, 0xd7, 0x33, 0x2d, 0xb2, 0x3e, + /*1890:*/ 0xff, 0xe4, 0x42, 0xbb, 0x37, 0x4b, 0x5c, 0x71, 0xf0, 0xd8, 0x5a, 0xc8, 0xcb, 0xbc, 0x46, 0x60, + /*18a0:*/ 0x4e, 0x33, 0x9e, 0x9b, 0x02, 0x83, 0xf7, 0x65, 0x61, 0x14, 0x69, 0xd5, 0x9d, 0x78, 0xef, 0x44, + /*18b0:*/ 0x79, 0xf3, 0x5c, 0xf9, 0xab, 0x9b, 0x6b, 0x93, 0x12, 0x7a, 0x2d, 0x1d, 0xab, 0xff, 0xf8, 0x1d, + /*18c0:*/ 0xcb, 0x2e, 0x2d, 0xa8, 0x24, 0xcd, 0x74, 0x7e, 0xc1, 0xb7, 0xf1, 0x7f, 0x5a, 0xa7, 0x4f, 0xd5, + /*18d0:*/ 0xe1, 0x7c, 0xbe, 0x5c, 0xcc, 0x8d, 0xb0, 0xe8, 0x05, 0x0c, 0xc6, 0x53, 0x79, 0xa3, 0xe6, 0xda, + /*18e0:*/ 0xa6, 0x23, 0x6c, 0x9d, 0x1b, 0x98, 0xa9, 0x78, 0xe2, 0x20, 0xd6, 0xcf, 0xb1, 0x12, 0x4c, 0xec, + /*18f0:*/ 0xb7, 0xb3, 0x04, 0x1d, 0xe3, 0xf0, 0xc2, 0xa6, 0x97, 0x29, 0xef, 0x43, 0x55, 0xef, 0xff, 0x71, + /*1900:*/ 0xb1, 0x1f, 0x4e, 0x0f, 0x08, 0x05, 0x91, 0x19, 0xd0, 0x73, 0x6b, 0x36, 0x7d, 0x1d, 0xae, 0xc6, + /*1910:*/ 0xbf, 0xdb, 0x03, 0x3f, 0xc7, 0x06, 0xf3, 0xed, 0x15, 0xa3, 0xda, 0x03, 0xbd, 0x57, 0x6f, 0x86, + /*1920:*/ 0x30, 0x77, 0x7b, 0x2c, 0xd9, 0xa9, 0x77, 0x8f, 0xf0, 0xe3, 0x78, 0x75, 0x88, 0x13, 0x3b, 0x1a, + /*1930:*/ 0xa8, 0xdf, 0x4a, 0x09, 0xb0, 0x52, 0x55, 0x79, 0xba, 0x0a, 0xf3, 0x36, 0x9a, 0x0c, 0xd5, 0x93, + /*1940:*/ 0xed, 0x15, 0x47, 0x80, 0xb8, 0x0d, 0xb7, 0xd7, 0x6d, 0x51, 0xd0, 0x1c, 0xc5, 0x2c, 0x8d, 0x31, + /*1950:*/ 0xb7, 0x35, 0x62, 0xf9, 0xa3, 0xd2, 0xfa, 0x26, 0xe7, 0x61, 0x3f, 0x85, 0xae, 0x96, 0x85, 0xf9, + /*1960:*/ 0xb3, 0x4a, 0x1b, 0x0e, 0x30, 0x2a, 0xc2, 0x10, 0xe8, 0xfb, 0x16, 0xc0, 0x74, 0x29, 0x2a, 0x16, + /*1970:*/ 0x39, 0xd9, 0xd8, 0xaf, 0x45, 0x92, 0x5e, 0xdf, 0xa4, 0x2f, 0xae, 0x42, 0xc2, 0xf5, 0x7b, 0xa1, + /*1980:*/ 0x33, 0x26, 0xa1, 0x06, 0x7f, 0x57, 0x4e, 0x1e, 0x5d, 0xaa, 0x5c, 0xa1, 0x52, 0xdb, 0xb3, 0xba, + /*1990:*/ 0x8f, 0x4e, 0x6f, 0x00, 0xc2, 0x95, 0x12, 0x0c, 0xe7, 0xf0, 0xad, 0xb8, 0x33, 0xc0, 0xfc, 0x3b, + /*19a0:*/ 0x9f, 0x06, 0x4d, 0x4c, 0x45, 0x5c, 0xea, 0x12, 0x92, 0xff, 0x3e, 0xa7, 0xc6, 0x4b, 0x15, 0xb0, + /*19b0:*/ 0x51, 0x59, 0x5d, 0x40, 0xb1, 0xff, 0xae, 0xfb, 0x9a, 0x66, 0xc0, 0x1c, 0x38, 0x7b, 0x6f, 0xa7, + /*19c0:*/ 0xc6, 0x81, 0xbe, 0x91, 0xb1, 0xb0, 0xce, 0x2b, 0x7c, 0x04, 0x69, 0xdd, 0x67, 0xd1, 0x9e, 0x9e, + /*19d0:*/ 0x41, 0x3c, 0x90, 0x04, 0x17, 0x5c, 0x73, 0x51, 0xfd, 0x49, 0x7e, 0x2d, 0x0a, 0xd3, 0x77, 0x1d, + /*19e0:*/ 0xbc, 0x8e, 0x2e, 0xf6, 0x44, 0x20, 0x8a, 0x3f, 0x44, 0xa2, 0xd6, 0x8c, 0x40, 0xac, 0x6c, 0x91, + /*19f0:*/ 0xa4, 0x34, 0xe6, 0xbe, 0x3b, 0x55, 0xde, 0x9b, 0x3b, 0x97, 0xba, 0xbc, 0x43, 0x79, 0xe5, 0xba, + /*1a00:*/ 0xc5, 0x34, 0x87, 0xb9, 0x68, 0xef, 0x83, 0x9c, 0x90, 0x55, 0x27, 0xcb, 0xc2, 0x57, 0xad, 0x27, + /*1a10:*/ 0xe8, 0xe4, 0xe0, 0xa6, 0x03, 0x27, 0x9f, 0x41, 0x38, 0xb4, 0x1e, 0x7b, 0xa4, 0xe2, 0xab, 0x27, + /*1a20:*/ 0x7b, 0x81, 0xfa, 0x9a, 0x7b, 0xc0, 0xb6, 0xd4, 0xe4, 0x0f, 0xf2, 0x2c, 0x25, 0x73, 0xef, 0x3f, + /*1a30:*/ 0xae, 0xb2, 0x84, 0xd9, 0x6d, 0xc2, 0x41, 0x34, 0xc1, 0x00, 0x69, 0xc7, 0x68, 0xda, 0xca, 0xbb, + /*1a40:*/ 0x82, 0x97, 0x93, 0xb8, 0x21, 0xe4, 0xee, 0xd9, 0x65, 0xcc, 0xa9, 0x89, 0x70, 0x3d, 0x87, 0x8a, + /*1a50:*/ 0x98, 0xaf, 0x73, 0xdd, 0x9e, 0x41, 0x9b, 0xad, 0xbb, 0xb8, 0xfb, 0x3e, 0xdd, 0x57, 0xd0, 0x66, + /*1a60:*/ 0xc8, 0x11, 0x42, 0xd8, 0x84, 0x5e, 0x20, 0x4c, 0xe9, 0xaa, 0xad, 0x08, 0x8f, 0x9d, 0x9e, 0xf9, + /*1a70:*/ 0x47, 0xfb, 0x46, 0x89, 0xaa, 0xec, 0x21, 0x32, 0x56, 0x49, 0x47, 0xc3, 0x0d, 0x26, 0x06, 0xe8, + /*1a80:*/ 0xfe, 0x50, 0xbb, 0xf1, 0x13, 0xec, 0x78, 0x02, 0xcb, 0xe2, 0x5d, 0x4c, 0xe5, 0x17, 0x50, 0x9a, + /*1a90:*/ 0x29, 0x24, 0x06, 0xd2, 0x27, 0xf1, 0xcc, 0x31, 0x44, 0xc5, 0xeb, 0xda, 0xbf, 0x7f, 0xe0, 0xa8, + /*1aa0:*/ 0x27, 0xad, 0xc9, 0xf1, 0x22, 0xce, 0x52, 0x1f, 0x66, 0xac, 0x29, 0xc3, 0x6b, 0xea, 0x7e, 0xdc, + /*1ab0:*/ 0x57, 0xc1, 0xee, 0xf2, 0xa3, 0x9d, 0xc2, 0xdb, 0x47, 0xa3, 0xd1, 0x40, 0xda, 0xa8, 0x4f, 0x51, + /*1ac0:*/ 0x31, 0x7a, 0x58, 0xf4, 0x76, 0xef, 0xe4, 0xeb, 0x47, 0xd8, 0x33, 0x1e, 0x33, 0x1d, 0xca, 0xd8, + /*1ad0:*/ 0xce, 0x20, 0x21, 0x6d, 0xd4, 0xa4, 0x0d, 0x9b, 0x41, 0x8e, 0xcb, 0x00, 0xb3, 0x3c, 0x7f, 0x2a, + /*1ae0:*/ 0xe1, 0x4f, 0x43, 0x10, 0xde, 0x96, 0x71, 0xd1, 0x23, 0x21, 0x2b, 0x4a, 0xab, 0x4d, 0x88, 0xbb, + /*1af0:*/ 0x4e, 0x7d, 0x51, 0x42, 0x86, 0xd0, 0x45, 0x8a, 0x12, 0x01, 0xec, 0x87, 0xc3, 0xa4, 0xfc, 0x9e, + /*1b00:*/ 0x38, 0x47, 0xd6, 0xdb, 0xbb, 0x9f, 0x76, 0xa7, 0x7a, 0x20, 0x6c, 0x1f, 0x2b, 0x85, 0xbf, 0xf0, + /*1b10:*/ 0x2b, 0x17, 0x29, 0xd3, 0xc1, 0x21, 0x76, 0x33, 0x54, 0xc7, 0x00, 0x8b, 0x42, 0xf7, 0x4b, 0x1f, + /*1b20:*/ 0x90, 0x95, 0xe3, 0x00, 0x06, 0x7c, 0x16, 0x8e, 0x55, 0x75, 0x25, 0x72, 0xcf, 0x6c, 0xaf, 0x03, + /*1b30:*/ 0x60, 0xde, 0xe0, 0x4f, 0xb5, 0x46, 0x98, 0xb9, 0xbf, 0x42, 0x6d, 0x50, 0xcf, 0xe2, 0x7c, 0xe7, + /*1b40:*/ 0x69, 0xa1, 0x38, 0x08, 0xbb, 0x4d, 0x28, 0xf0, 0x1a, 0x09, 0x2b, 0x15, 0xa9, 0x90, 0x50, 0x09, + /*1b50:*/ 0x9a, 0xd0, 0x06, 0x1d, 0xe6, 0x25, 0xb9, 0x11, 0xbd, 0x10, 0xc1, 0x8d, 0x99, 0xba, 0x51, 0xca, + /*1b60:*/ 0xc1, 0x6b, 0x26, 0xac, 0x6a, 0x81, 0xd7, 0xbd, 0x84, 0xc8, 0x6d, 0xb1, 0x22, 0x73, 0x99, 0x7c, + /*1b70:*/ 0x7d, 0xdc, 0xcc, 0xa8, 0x36, 0xcf, 0xf7, 0x85, 0xb2, 0x2f, 0x3a, 0xfa, 0x31, 0x21, 0x5b, 0x86, + /*1b80:*/ 0xf3, 0xae, 0x82, 0xc3, 0x69, 0x08, 0xf4, 0xa4, 0xfc, 0x70, 0x9f, 0xf3, 0x64, 0xdb, 0x90, 0xa8, + /*1b90:*/ 0x2c, 0x81, 0xe2, 0x2b, 0x59, 0x5b, 0x8d, 0xed, 0x08, 0x37, 0x88, 0xd0, 0xca, 0xf2, 0xaf, 0x6e, + /*1ba0:*/ 0x46, 0x00, 0x60, 0x6f, 0xbf, 0x7b, 0xf4, 0x69, 0xa1, 0x92, 0x4e, 0x30, 0x2c, 0x0f, 0xa1, 0xcb, + /*1bb0:*/ 0xbf, 0x8e, 0xe9, 0x1b, 0xe5, 0x90, 0x6c, 0x90, 0x5a, 0x5e, 0x92, 0xdf, 0x4f, 0xc6, 0x9c, 0x07, + /*1bc0:*/ 0xaf, 0xdd, 0x6b, 0x7c, 0x28, 0x8b, 0x01, 0x42, 0x1a, 0x7f, 0x43, 0xca, 0xbf, 0x9f, 0xf4, 0x56, + /*1bd0:*/ 0x88, 0xc2, 0x6e, 0xb4, 0x2d, 0xec, 0x75, 0x55, 0x88, 0x89, 0xec, 0x34, 0xd1, 0x4e, 0x7f, 0x58, + /*1be0:*/ 0x2d, 0xaf, 0x4b, 0x74, 0x9e, 0x1f, 0x40, 0x17, 0xcd, 0xa5, 0x03, 0x63, 0x2a, 0x52, 0xb5, 0x85, + /*1bf0:*/ 0x37, 0xac, 0xf9, 0x35, 0xe7, 0x04, 0x4f, 0x6f, 0x9b, 0xe4, 0x21, 0xd7, 0xc1, 0x37, 0x03, 0x6a, + /*1c00:*/ 0xc5, 0x2e, 0xf2, 0xa7, 0xfa, 0x3f, 0x41, 0x08, 0xf2, 0xf1, 0x9b, 0x3b, 0xef, 0xf8, 0x39, 0x16, + /*1c10:*/ 0xf9, 0xe9, 0xe7, 0x7c, 0xb9, 0x7c, 0xde, 0x7b, 0xd8, 0x32, 0xdf, 0x67, 0xff, 0x6f, 0x47, 0x8f, + /*1c20:*/ 0x4f, 0x90, 0x80, 0x6a, 0xf6, 0x3f, 0xef, 0x14, 0xd5, 0x9c, 0x78, 0x65, 0x95, 0xb3, 0x16, 0x7e, + /*1c30:*/ 0x22, 0xc1, 0x12, 0xb6, 0x7e, 0x8a, 0xa8, 0x2e, 0x06, 0x29, 0x41, 0xe7, 0x19, 0xf3, 0x60, 0xc1, + /*1c40:*/ 0xe7, 0xad, 0x7b, 0xd6, 0xf4, 0xa3, 0x9a, 0x60, 0x33, 0xfc, 0x00, 0x37, 0xe3, 0xe8, 0xba, 0xa7, + /*1c50:*/ 0xbe, 0x25, 0x09, 0x0b, 0x6b, 0x10, 0x9e, 0x5a, 0x8b, 0xfb, 0x16, 0x34, 0xae, 0x70, 0x16, 0x62, + /*1c60:*/ 0x08, 0x44, 0x83, 0x13, 0xa2, 0xb4, 0x5f, 0xe6, 0x4e, 0x97, 0xf0, 0x38, 0x32, 0xf0, 0xeb, 0x15, + /*1c70:*/ 0x3f, 0x22, 0xa5, 0x2d, 0xda, 0x5e, 0x8a, 0xc7, 0x1a, 0x67, 0xbc, 0x27, 0xb6, 0xe2, 0x33, 0xe0, + /*1c80:*/ 0x7e, 0xe1, 0x48, 0xcf, 0xbb, 0x98, 0xd5, 0xf4, 0x46, 0x9f, 0xc0, 0xa8, 0x9b, 0x5d, 0xcd, 0x51, + /*1c90:*/ 0xae, 0xab, 0xf8, 0xf1, 0x3a, 0x61, 0xb7, 0x40, 0x68, 0x8f, 0xb9, 0x65, 0xfe, 0x7f, 0xcf, 0x9d, + /*1ca0:*/ 0xc3, 0xf8, 0x9c, 0x02, 0x69, 0xa4, 0x46, 0xfd, 0x90, 0x94, 0xb4, 0x17, 0x48, 0x24, 0xd7, 0x9b, + /*1cb0:*/ 0x9e, 0xad, 0xe4, 0x0c, 0x7b, 0x8e, 0xf5, 0xcc, 0xf6, 0x6d, 0x8b, 0x25, 0x27, 0xd0, 0x12, 0x25, + /*1cc0:*/ 0x4e, 0x26, 0xca, 0x25, 0x3e, 0x0f, 0x85, 0x07, 0x03, 0xad, 0xb5, 0xed, 0xb5, 0xd3, 0x42, 0xbc, + /*1cd0:*/ 0xaa, 0xa5, 0xd1, 0xbb, 0xa9, 0xd7, 0x2f, 0x8e, 0x1a, 0x05, 0x00, 0xf1, 0xcd, 0x8b, 0x30, 0x11, + /*1ce0:*/ 0xa9, 0x3c, 0x7d, 0x08, 0x86, 0xf0, 0xc0, 0x5e, 0x89, 0x2a, 0xdc, 0xf7, 0xaa, 0xfa, 0x69, 0xf4, + /*1cf0:*/ 0xed, 0x1f, 0x73, 0x5f, 0x12, 0x9f, 0x7d, 0x6d, 0x56, 0x38, 0x39, 0x52, 0xfb, 0xa1, 0x59, 0xc5, + /*1d00:*/ 0x33, 0x4b, 0x60, 0x65, 0x0a, 0xee, 0x64, 0xbc, 0xd1, 0x08, 0x07, 0x65, 0xa7, 0x25, 0x08, 0xd5, + /*1d10:*/ 0xc5, 0x66, 0x36, 0x26, 0x2b, 0x08, 0xb2, 0x9a, 0x94, 0x84, 0x3e, 0xb3, 0x1e, 0xff, 0xeb, 0x0b, + /*1d20:*/ 0x17, 0xa2, 0xc2, 0x3b, 0x2d, 0x87, 0xdf, 0xcc, 0x2d, 0x33, 0x90, 0xd1, 0xb8, 0x13, 0x52, 0xf9, + /*1d30:*/ 0xf6, 0xde, 0xba, 0x43, 0x17, 0x57, 0x4b, 0x25, 0xe7, 0xd6, 0x6f, 0x92, 0xed, 0x9a, 0xf6, 0x33, + /*1d40:*/ 0x79, 0x3b, 0xfb, 0x4f, 0x06, 0xff, 0x16, 0x17, 0xba, 0xdd, 0x76, 0x85, 0x31, 0xaa, 0x6a, 0x02, + /*1d50:*/ 0x8a, 0xd0, 0x4e, 0xcd, 0xd1, 0x16, 0xa0, 0x81, 0xff, 0x68, 0x17, 0x89, 0xdc, 0x66, 0x1a, 0x01, + /*1d60:*/ 0xf5, 0x61, 0xe6, 0xb7, 0x9c, 0xc8, 0x4a, 0x0c, 0x8c, 0xbc, 0x4e, 0x8f, 0x1e, 0x8f, 0x44, 0x1b, + /*1d70:*/ 0x31, 0x53, 0x99, 0xa3, 0x4b, 0x59, 0xfe, 0xc1, 0x51, 0x98, 0x5a, 0x4f, 0x27, 0x56, 0x37, 0xe5, + /*1d80:*/ 0x90, 0x48, 0x02, 0x07, 0xaf, 0xf7, 0xbd, 0xe1, 0xcb, 0xe0, 0x08, 0x4f, 0x75, 0x68, 0x38, 0xdc, + /*1d90:*/ 0xb0, 0xad, 0x92, 0xc0, 0xf9, 0xc8, 0x84, 0x25, 0x4f, 0xac, 0x0e, 0x89, 0x41, 0x26, 0x0e, 0xb8, + /*1da0:*/ 0xa0, 0x73, 0x56, 0x16, 0xd9, 0x70, 0xdf, 0xde, 0xd8, 0x9b, 0x84, 0x8b, 0x2c, 0xe2, 0x2e, 0x80, + /*1db0:*/ 0x39, 0x33, 0x20, 0x18, 0x29, 0x72, 0x69, 0x2d, 0x61, 0x44, 0x67, 0xc5, 0x56, 0x04, 0x7d, 0xe5, + /*1dc0:*/ 0xc8, 0xdb, 0xb1, 0x6d, 0x5d, 0x2b, 0x34, 0x4e, 0xdd, 0x14, 0xff, 0x4b, 0x5a, 0xae, 0xa6, 0xee, + /*1dd0:*/ 0x5c, 0x81, 0xee, 0x61, 0x5d, 0x9f, 0x0d, 0x24, 0x21, 0x05, 0x48, 0x58, 0xe9, 0x12, 0x3a, 0x17, + /*1de0:*/ 0x73, 0x77, 0xb6, 0x54, 0x63, 0xd0, 0xe6, 0x7c, 0x87, 0x6b, 0xdf, 0xdd, 0x24, 0xd9, 0xd5, 0xc0, + /*1df0:*/ 0x4f, 0xed, 0xb6, 0x18, 0x72, 0x46, 0x98, 0x51, 0x78, 0x63, 0xe3, 0xf7, 0x55, 0xbe, 0x2b, 0x1a, + /*1e00:*/ 0x92, 0xb1, 0x7e, 0x7f, 0x37, 0xb0, 0xf8, 0x3c, 0x54, 0xc3, 0xf2, 0x8c, 0xa3, 0x57, 0x57, 0xd0, + /*1e10:*/ 0x7f, 0x72, 0x59, 0xda, 0xfe, 0xe2, 0x11, 0x84, 0x35, 0x69, 0xcc, 0x58, 0x19, 0x02, 0x17, 0x7a, + /*1e20:*/ 0xf1, 0xfc, 0x3a, 0x5f, 0x44, 0x2c, 0x8d, 0x61, 0xf5, 0x6f, 0x47, 0xd4, 0xc7, 0xe7, 0xb4, 0xe4, + /*1e30:*/ 0x39, 0xe6, 0xde, 0xf3, 0xa7, 0x40, 0x30, 0xf4, 0x47, 0x58, 0xd6, 0x9e, 0x2b, 0x26, 0x67, 0x59, + /*1e40:*/ 0xb6, 0xf1, 0x28, 0x8a, 0x23, 0xad, 0x08, 0xd0, 0x84, 0xf3, 0xd8, 0xfa, 0xfb, 0x72, 0x0a, 0x94, + /*1e50:*/ 0x89, 0xca, 0x41, 0x88, 0x2f, 0x33, 0xa1, 0x42, 0xbb, 0xe2, 0x30, 0x90, 0xb1, 0xa4, 0xbb, 0x28, + /*1e60:*/ 0x2b, 0xc5, 0x6f, 0xb2, 0x36, 0xd7, 0x35, 0xc5, 0x57, 0xb5, 0x94, 0x77, 0x63, 0x0c, 0x9a, 0x72, + /*1e70:*/ 0xf8, 0x93, 0xcf, 0x24, 0x28, 0xb6, 0x62, 0x95, 0x8d, 0xf4, 0x5e, 0xb8, 0x71, 0x49, 0x74, 0x97, + /*1e80:*/ 0xeb, 0xd0, 0x51, 0x58, 0x14, 0xe1, 0xc9, 0x70, 0xf1, 0x49, 0x26, 0x46, 0x1e, 0x3f, 0x36, 0x81, + /*1e90:*/ 0xb6, 0xc8, 0x1c, 0x9c, 0x5d, 0x67, 0x35, 0x25, 0xc1, 0x9b, 0x76, 0x3a, 0x95, 0x52, 0xb2, 0xe1, + /*1ea0:*/ 0xb2, 0x8a, 0x56, 0x1b, 0x82, 0x67, 0xfe, 0x48, 0x08, 0x3e, 0x5f, 0xc6, 0xf8, 0xe9, 0xb8, 0xe0, + /*1eb0:*/ 0x7e, 0x93, 0x99, 0xed, 0x22, 0x58, 0x6e, 0x5a, 0x8d, 0x9a, 0x51, 0xf1, 0x74, 0x6e, 0x92, 0x91, + /*1ec0:*/ 0xd6, 0x76, 0x19, 0xd2, 0xaf, 0xee, 0xaa, 0x0d, 0x91, 0x36, 0xae, 0xa6, 0xc6, 0xea, 0x8e, 0xe2, + /*1ed0:*/ 0x43, 0x34, 0x45, 0x6e, 0x11, 0x49, 0x32, 0x8d, 0x8d, 0x08, 0xfd, 0xc5, 0xf5, 0xb8, 0xf7, 0x49, + /*1ee0:*/ 0x66, 0x00, 0x6b, 0x50, 0x61, 0x3e, 0x24, 0xa3, 0x67, 0x0c, 0x9f, 0x3b, 0x4d, 0x69, 0x0d, 0xe5, + /*1ef0:*/ 0x66, 0x67, 0xf2, 0xcd, 0x79, 0x88, 0x36, 0xff, 0x21, 0x3b, 0x41, 0xcb, 0x88, 0x67, 0xdb, 0xa7, + /*1f00:*/ 0xc8, 0x3d, 0x16, 0xda, 0x7e, 0x58, 0x76, 0xdc, 0x0c, 0xd7, 0x96, 0x23, 0x59, 0x6f, 0xe2, 0xda, + /*1f10:*/ 0x62, 0xf7, 0x9f, 0x11, 0xee, 0x3f, 0x84, 0xeb, 0xbb, 0xeb, 0x62, 0x79, 0xa9, 0x6c, 0x93, 0x82, + /*1f20:*/ 0x07, 0x8f, 0x98, 0xcc, 0x27, 0x16, 0xf1, 0x65, 0x40, 0x20, 0x40, 0x00, 0x31, 0x16, 0xdb, 0x9c, + /*1f30:*/ 0x3a, 0x03, 0xc1, 0x73, 0x5f, 0x0e, 0x5a, 0xc1, 0x19, 0x5a, 0xcb, 0x72, 0x73, 0x62, 0x3c, 0x83, + /*1f40:*/ 0x8c, 0x05, 0x39, 0x8c, 0x10, 0x81, 0x06, 0xb9, 0x9a, 0x37, 0xed, 0x5a, 0xb0, 0x92, 0x75, 0x51, + /*1f50:*/ 0x20, 0x62, 0xc6, 0xca, 0xf7, 0x0d, 0xd0, 0x7a, 0x98, 0x41, 0x43, 0x5b, 0x08, 0x08, 0xb2, 0x04, + /*1f60:*/ 0x7f, 0x86, 0x84, 0x39, 0xe3, 0x7e, 0x5f, 0x9b, 0xff, 0x8a, 0x49, 0x78, 0x40, 0x99, 0x71, 0x77, + /*1f70:*/ 0xbd, 0xb3, 0x01, 0xfa, 0x4f, 0x57, 0x9c, 0xe4, 0x92, 0x00, 0xef, 0xcd, 0x60, 0x4a, 0xb8, 0x73, + /*1f80:*/ 0xb6, 0xd0, 0x51, 0x62, 0x34, 0x27, 0xb0, 0x40, 0xd9, 0x25, 0x8c, 0x7b, 0x47, 0x7f, 0x33, 0xdd, + /*1f90:*/ 0x64, 0x9d, 0x1b, 0xfb, 0xe8, 0x4f, 0x85, 0x95, 0x62, 0xb7, 0x87, 0x43, 0x47, 0x28, 0xec, 0xda, + /*1fa0:*/ 0x08, 0x52, 0x16, 0xca, 0x11, 0xf7, 0x35, 0x5c, 0x6d, 0xbd, 0xa6, 0x3d, 0xe3, 0x45, 0x78, 0xe7, + /*1fb0:*/ 0xb9, 0x08, 0xc3, 0xca, 0x97, 0x8e, 0x88, 0x6e, 0xb2, 0x00, 0x15, 0x9c, 0x44, 0x6f, 0x98, 0x80, + /*1fc0:*/ 0xe6, 0x24, 0x0e, 0xf9, 0xaa, 0xf6, 0x22, 0x54, 0xd5, 0xde, 0x97, 0x93, 0x77, 0x25, 0x79, 0xbf, + /*1fd0:*/ 0x93, 0xb1, 0x26, 0xbd, 0x8e, 0x6f, 0x71, 0xeb, 0xeb, 0x26, 0xb9, 0xca, 0x21, 0x53, 0x21, 0x73, + /*1fe0:*/ 0x1b, 0x09, 0x60, 0x03, 0xe3, 0x28, 0x7c, 0x8e, 0x55, 0x59, 0x99, 0x6a, 0xb8, 0xdc, 0x15, 0xf3, + /*1ff0:*/ 0xcf, 0x96, 0x61, 0x26, 0x2b, 0x2b, 0x32, 0xaa, 0xa0, 0x37, 0x1f, 0x3c, 0x22, 0x9e, 0xc2, 0x14, + /*2000:*/ 0x43, 0x79, 0x50, 0x7b, 0xf7, 0x72, 0xc8, 0xc4, 0xb5, 0x9e, 0x04, 0xe7, 0x7b, 0xd5, 0x01, 0xd0, + /*2010:*/ 0xd9, 0xf2, 0x57, 0x76, 0x6a, 0x11, 0xd4, 0xe5, 0x0f, 0xcd, 0xd8, 0xd1, 0x5c, 0xf1, 0x9d, 0x7e, + /*2020:*/ 0x31, 0x43, 0xdf, 0x82, 0x81, 0x30, 0xe1, 0xf9, 0x85, 0x9d, 0xbf, 0xe8, 0x6d, 0xb9, 0xa0, 0x40, + /*2030:*/ 0x4e, 0x7f, 0x88, 0x3f, 0xb4, 0x78, 0xb8, 0x5a, 0x30, 0x39, 0xf1, 0xb5, 0x3e, 0x13, 0x91, 0x63, + /*2040:*/ 0x88, 0xce, 0xc3, 0x29, 0xde, 0x4c, 0x40, 0x0d, 0x1f, 0x98, 0x36, 0x78, 0x0b, 0x6a, 0x0e, 0x3a, + /*2050:*/ 0x4c, 0x24, 0xe5, 0x5c, 0x48, 0x9f, 0x4c, 0xa7, 0xc7, 0x2d, 0x57, 0x7a, 0x2a, 0xa1, 0x5e, 0x47, + /*2060:*/ 0xbc, 0x29, 0x31, 0xb5, 0x51, 0xe6, 0x01, 0x22, 0x61, 0xcb, 0xed, 0x8f, 0xb9, 0xc7, 0x47, 0xf3, + /*2070:*/ 0x74, 0x32, 0xc3, 0x83, 0xf8, 0x29, 0x61, 0x07, 0x5d, 0xc1, 0xe4, 0x45, 0x53, 0xcd, 0x3d, 0x7a, + /*2080:*/ 0xfd, 0x65, 0xce, 0x29, 0xdc, 0x73, 0x22, 0xa8, 0x99, 0xfb, 0xcb, 0xee, 0xc7, 0xb4, 0x96, 0x7f, + /*2090:*/ 0x5a, 0xb9, 0xd6, 0xa0, 0xd1, 0xcc, 0x6f, 0x87, 0x6e, 0x82, 0x66, 0xa3, 0x81, 0xb2, 0xee, 0x2e, + /*20a0:*/ 0x32, 0x32, 0xd8, 0xf3, 0x3e, 0xfc, 0x43, 0xc1, 0x3c, 0x2c, 0xa4, 0x43, 0x3b, 0x10, 0x5b, 0x2b, + /*20b0:*/ 0xf0, 0x6a, 0xce, 0xee, 0x77, 0xb2, 0xb8, 0xac, 0x87, 0xdb, 0x6c, 0x85, 0xc5, 0x61, 0x45, 0x47, + /*20c0:*/ 0xb1, 0xb8, 0x95, 0x39, 0x7f, 0xdc, 0x3c, 0xfb, 0xf3, 0x1a, 0x0d, 0xbf, 0xd8, 0x43, 0xcb, 0x7b, + /*20d0:*/ 0xfa, 0xf0, 0xa5, 0x56, 0xca, 0x40, 0xe1, 0x54, 0xe9, 0x8a, 0x33, 0xee, 0x00, 0xdd, 0xcf, 0xb6, + /*20e0:*/ 0x95, 0x67, 0x91, 0x36, 0xac, 0x3b, 0xa3, 0x72, 0xf6, 0x24, 0x5c, 0xed, 0x39, 0x53, 0xc0, 0xfd, + /*20f0:*/ 0x25, 0x61, 0x7b, 0x4d, 0x67, 0xff, 0x5b, 0x6d, 0xce, 0x5b, 0x85, 0x9b, 0x20, 0xc5, 0x8a, 0x62, + /*2100:*/ 0x70, 0x14, 0x6a, 0x7e, 0x78, 0x54, 0x4b, 0x77, 0x2b, 0xb9, 0x42, 0x12, 0xca, 0xb5, 0xad, 0x37, + /*2110:*/ 0x6d, 0x2f, 0x3e, 0x2e, 0x32, 0x0c, 0xba, 0x17, 0x1e, 0x4b, 0xd0, 0x0f, 0x29, 0xf9, 0x45, 0xa0, + /*2120:*/ 0xa4, 0x7b, 0xb9, 0xce, 0x7f, 0x3a, 0xd5, 0xaf, 0x1c, 0xeb, 0x49, 0xb9, 0xb6, 0x5d, 0x61, 0x1f, + /*2130:*/ 0x7a, 0x36, 0xab, 0x92, 0x9e, 0xb9, 0xfb, 0x54, 0xcf, 0xf1, 0xd4, 0x1f, 0xdd, 0x48, 0xc4, 0xd1, + /*2140:*/ 0x6a, 0x73, 0x9d, 0x07, 0xce, 0x87, 0x9f, 0x53, 0x82, 0x28, 0x43, 0x27, 0x53, 0x85, 0x19, 0x5d, + /*2150:*/ 0xd6, 0x88, 0x3e, 0xe1, 0x77, 0x4a, 0x1f, 0x73, 0x4d, 0x82, 0x42, 0x87, 0x49, 0x5b, 0x1f, 0x49, + /*2160:*/ 0x1c, 0x46, 0xaf, 0x7f, 0xbc, 0xa4, 0xdf, 0x0b, 0xa5, 0x8f, 0xdf, 0x0a, 0x33, 0x13, 0xc4, 0x33, + /*2170:*/ 0xa9, 0x7c, 0x05, 0x76, 0x83, 0xbd, 0x2a, 0xa2, 0x48, 0xfa, 0xf9, 0x0a, 0xfb, 0x17, 0xa8, 0x46, + /*2180:*/ 0x10, 0x9b, 0x16, 0x17, 0x45, 0xa1, 0x0b, 0xf9, 0x63, 0x5f, 0x5a, 0xb7, 0x86, 0x84, 0xc8, 0x3f, + /*2190:*/ 0x1d, 0x8a, 0xf1, 0xba, 0x57, 0x00, 0xd9, 0x7e, 0x52, 0xf0, 0x2d, 0x05, 0x26, 0x72, 0x97, 0xb4, + /*21a0:*/ 0x8d, 0x92, 0x37, 0xf8, 0x02, 0x9e, 0x6a, 0x41, 0x68, 0x37, 0x76, 0xb0, 0xeb, 0xca, 0xbc, 0xd3, + /*21b0:*/ 0x7a, 0xdf, 0xa9, 0x2c, 0x30, 0x36, 0x1c, 0x1d, 0x0e, 0x19, 0x2b, 0xc0, 0x7a, 0x59, 0x29, 0x82, + /*21c0:*/ 0x36, 0x5e, 0x76, 0x8e, 0x50, 0x27, 0xc4, 0x6c, 0xfb, 0xf0, 0x19, 0x9d, 0x40, 0x0c, 0x21, 0x95, + /*21d0:*/ 0x2d, 0xdc, 0xaf, 0x0d, 0x23, 0xde, 0xa2, 0x6a, 0xf3, 0x7a, 0x30, 0x3e, 0x2b, 0x07, 0xd4, 0x3d, + /*21e0:*/ 0xaa, 0x45, 0xec, 0x32, 0x87, 0x23, 0xb2, 0xb9, 0x77, 0xca, 0x6e, 0xfb, 0x68, 0xfc, 0x22, 0x0c, + /*21f0:*/ 0x5a, 0xff, 0x25, 0xfa, 0x62, 0x40, 0xe7, 0xb9, 0x3f, 0x84, 0x17, 0x35, 0x2a, 0x72, 0xff, 0x42, + /*2200:*/ 0xab, 0x0e, 0xbe, 0xe6, 0x46, 0x28, 0xb7, 0xb3, 0x9d, 0x84, 0x7e, 0x5f, 0x02, 0xd7, 0xe9, 0xa2, + /*2210:*/ 0x68, 0xb1, 0x27, 0xc6, 0x89, 0xda, 0xc3, 0x37, 0x3b, 0x6c, 0x1a, 0x70, 0x08, 0xaa, 0x84, 0x7c, + /*2220:*/ 0xc9, 0x7e, 0x69, 0x4c, 0x5c, 0x8c, 0x98, 0x82, 0xc8, 0xe0, 0x58, 0x17, 0xeb, 0x8a, 0xda, 0x2a, + /*2230:*/ 0xe3, 0x68, 0x5a, 0x65, 0xef, 0x23, 0xd4, 0x46, 0x02, 0x8e, 0x68, 0xb5, 0x19, 0x25, 0x31, 0x69, + /*2240:*/ 0xd2, 0xc6, 0xe0, 0x84, 0x8e, 0x0a, 0xc4, 0x72, 0x9a, 0x4a, 0x1d, 0x56, 0x06, 0x4a, 0x9f, 0xaa, + /*2250:*/ 0x7a, 0xbe, 0x37, 0x5a, 0x38, 0xd0, 0x7b, 0xaa, 0x11, 0x40, 0x6a, 0xdb, 0xea, 0x6b, 0xa5, 0x7a, + /*2260:*/ 0xa3, 0x8e, 0xa1, 0x8e, 0x93, 0x9c, 0x38, 0x09, 0x27, 0x9d, 0xf2, 0x07, 0xfb, 0xf0, 0xba, 0x4d, + /*2270:*/ 0x9d, 0xaa, 0xa6, 0xd3, 0x32, 0x86, 0x3f, 0xd1, 0x6b, 0xcf, 0x86, 0x61, 0xdc, 0x28, 0xf0, 0x6a, + /*2280:*/ 0x11, 0x1f, 0x6d, 0x2e, 0xaf, 0x98, 0x59, 0x5b, 0x97, 0x2a, 0xd5, 0x5f, 0xf1, 0xca, 0x9d, 0xb6, + /*2290:*/ 0x48, 0x87, 0x21, 0x85, 0xfa, 0xb5, 0x80, 0x01, 0x85, 0x9e, 0xc3, 0x57, 0x20, 0xb9, 0x86, 0xea, + /*22a0:*/ 0x27, 0x8e, 0x29, 0xa7, 0xca, 0x5c, 0x89, 0x50, 0xc6, 0xa2, 0x6b, 0xdb, 0x0b, 0x0c, 0xc4, 0x1f, + /*22b0:*/ 0x57, 0x20, 0xbe, 0xfe, 0xcf, 0xca, 0x4b, 0x81, 0xb9, 0x6e, 0x82, 0x4f, 0x5d, 0xa9, 0xf5, 0x2e, + /*22c0:*/ 0x32, 0x07, 0x8d, 0x67, 0x65, 0x00, 0xe6, 0x92, 0x82, 0x68, 0x79, 0x54, 0x45, 0x89, 0x3e, 0xd0, + /*22d0:*/ 0x0d, 0x5c, 0x42, 0x11, 0xe6, 0xdd, 0xf5, 0xd0, 0x59, 0x1e, 0xd5, 0xb7, 0x0b, 0xd5, 0x80, 0xb7, + /*22e0:*/ 0xa9, 0x02, 0x96, 0xea, 0x77, 0x7d, 0x63, 0x72, 0x6c, 0x16, 0xb2, 0xfb, 0xf8, 0x28, 0xe5, 0xb1, + /*22f0:*/ 0x7a, 0x1c, 0xb0, 0xbd, 0xcd, 0xe0, 0x7f, 0xe8, 0xca, 0x36, 0xa9, 0x84, 0x87, 0x8e, 0x43, 0x42, + /*2300:*/ 0xe5, 0x06, 0xea, 0x4d, 0xef, 0xa5, 0x70, 0x40, 0xe1, 0xc1, 0x25, 0xec, 0x3d, 0x25, 0x14, 0xb1, + /*2310:*/ 0x90, 0x01, 0x67, 0x4e, 0xea, 0x7c, 0xf7, 0x8b, 0xca, 0x8d, 0x17, 0xc6, 0xa2, 0x73, 0x28, 0x09, + /*2320:*/ 0x8a, 0x9a, 0x02, 0x1d, 0x55, 0x86, 0xdd, 0x2f, 0x02, 0x9c, 0x3b, 0x8e, 0x2c, 0x54, 0x14, 0x62, + /*2330:*/ 0x5a, 0x5a, 0x96, 0x97, 0x40, 0x55, 0xd2, 0x8f, 0xb9, 0x79, 0x4e, 0x9a, 0xe0, 0xb3, 0xb8, 0xa9, + /*2340:*/ 0xfe, 0xbb, 0xc5, 0xca, 0x9a, 0x07, 0x9d, 0x20, 0x89, 0x9b, 0xb0, 0x2d, 0x57, 0xc9, 0x74, 0xbe, + /*2350:*/ 0x21, 0xc8, 0xd9, 0x6d, 0x3a, 0x12, 0xcd, 0xa8, 0xb4, 0xa4, 0x44, 0x2c, 0xca, 0xff, 0x5c, 0xd0, + /*2360:*/ 0xa0, 0x0a, 0x1f, 0xe4, 0x1b, 0x68, 0xbe, 0xe6, 0x27, 0xa6, 0x41, 0x58, 0xf9, 0x45, 0x5d, 0xd5, + /*2370:*/ 0xb0, 0x5e, 0x03, 0x29, 0xa0, 0xa7, 0x38, 0xfd, 0x80, 0x30, 0xa8, 0x59, 0x15, 0xc5, 0x9a, 0x73, + /*2380:*/ 0xb1, 0x37, 0xe9, 0x1f, 0xfe, 0x24, 0x29, 0x25, 0xdb, 0x02, 0xd4, 0x31, 0xbc, 0xff, 0x51, 0xc0, + /*2390:*/ 0x6a, 0xee, 0x2c, 0xc5, 0xe7, 0x99, 0xa2, 0x3f, 0xeb, 0xbe, 0x12, 0x89, 0xfd, 0xd7, 0x81, 0xe3, + /*23a0:*/ 0x2b, 0xc2, 0x17, 0x83, 0x4d, 0x0e, 0x38, 0x3d, 0x5a, 0xae, 0xf3, 0xdf, 0xd1, 0xcb, 0x1b, 0xca, + /*23b0:*/ 0x6f, 0xfc, 0xe9, 0xd4, 0x22, 0x6a, 0x1d, 0x22, 0xe2, 0xef, 0x2e, 0xde, 0xcd, 0x24, 0x93, 0xf1, + /*23c0:*/ 0x8f, 0xff, 0x43, 0x31, 0x63, 0x6b, 0xc9, 0xfc, 0x87, 0x77, 0xbe, 0x5b, 0x1c, 0x65, 0xad, 0x90, + /*23d0:*/ 0xd0, 0x5a, 0x63, 0x00, 0x3c, 0x41, 0x68, 0x2b, 0x1d, 0xdf, 0x4b, 0x72, 0x8c, 0xdd, 0x0a, 0x9b, + /*23e0:*/ 0xe6, 0xab, 0x61, 0x2f, 0xe8, 0xaa, 0x1a, 0x0f, 0x3a, 0x9b, 0x1a, 0x46, 0x6a, 0xf2, 0xaa, 0x2c, + /*23f0:*/ 0xa9, 0x20, 0xab, 0xf0, 0xb3, 0x6a, 0xd9, 0x8a, 0x8e, 0x28, 0x40, 0xb6, 0xd4, 0x47, 0x86, 0x0f, + /*2400:*/ 0x86, 0x10, 0x9c, 0xbc, 0xad, 0x68, 0x19, 0x3c, 0x4d, 0xed, 0x32, 0xa7, 0xfd, 0x26, 0xa1, 0x69, + /*2410:*/ 0x15, 0xf4, 0xe1, 0x59, 0x48, 0x9d, 0xab, 0x05, 0x46, 0x54, 0x3a, 0xcc, 0x77, 0x91, 0xfd, 0x48, + /*2420:*/ 0x21, 0x49, 0x98, 0x26, 0x9a, 0x08, 0xe9, 0x63, 0x3b, 0x43, 0x0b, 0x00, 0xa4, 0x51, 0xf3, 0xcb, + /*2430:*/ 0x95, 0xba, 0x03, 0x48, 0xd7, 0x6e, 0x43, 0xdc, 0x6a, 0xfa, 0x35, 0x83, 0x19, 0xd9, 0xc0, 0x90, + /*2440:*/ 0x3d, 0x8b, 0x22, 0x63, 0xaf, 0xb5, 0x00, 0x5d, 0x65, 0x2c, 0x5f, 0xbc, 0xad, 0x40, 0x94, 0x55, + /*2450:*/ 0x23, 0x0e, 0x1d, 0x14, 0x51, 0x01, 0x64, 0x28, 0x94, 0x39, 0xbc, 0x50, 0x9c, 0x76, 0xbf, 0x6c, + /*2460:*/ 0xd2, 0xc3, 0xd9, 0xd6, 0x8f, 0x20, 0x46, 0xe4, 0xe0, 0x6e, 0x2a, 0x36, 0x48, 0x03, 0x2c, 0x1b, + /*2470:*/ 0xc1, 0xdb, 0x9d, 0x91, 0x30, 0xfc, 0xf7, 0x8f, 0x05, 0x73, 0xac, 0xcc, 0x7d, 0xc6, 0x2a, 0x0f, + /*2480:*/ 0xc6, 0xce, 0xd6, 0x6c, 0xc9, 0x2a, 0x9f, 0x80, 0x58, 0xd0, 0x84, 0x16, 0xd6, 0xe2, 0xe8, 0x75, + /*2490:*/ 0x0e, 0x93, 0x96, 0x1b, 0xb3, 0xa3, 0x60, 0x24, 0x30, 0x9d, 0x67, 0xaf, 0xc3, 0x16, 0xe0, 0x36, + /*24a0:*/ 0xdc, 0x6e, 0x59, 0xf6, 0x81, 0xfb, 0x6c, 0x5e, 0x96, 0x5c, 0xd3, 0xac, 0xa3, 0x29, 0xdf, 0x02, + /*24b0:*/ 0xf3, 0x3c, 0x47, 0x1f, 0x94, 0x26, 0x9f, 0x18, 0x80, 0xc1, 0x28, 0xeb, 0x23, 0xd5, 0x7d, 0x2a, + /*24c0:*/ 0x73, 0x7d, 0x44, 0x40, 0x48, 0x33, 0x64, 0x4f, 0x9c, 0x69, 0x12, 0xe6, 0xa8, 0x58, 0xa6, 0x10, + /*24d0:*/ 0x50, 0x64, 0xb1, 0x3c, 0x6c, 0x07, 0x7e, 0xf5, 0x2d, 0x87, 0x3a, 0x67, 0xa7, 0x72, 0xad, 0xaa, + /*24e0:*/ 0xe8, 0x07, 0x51, 0xf0, 0xbf, 0x5d, 0x91, 0xc5, 0x3d, 0xba, 0x82, 0xe6, 0xd6, 0xf3, 0x06, 0x42, + /*24f0:*/ 0x38, 0x12, 0x84, 0xc1, 0x4c, 0x16, 0xc4, 0xbf, 0xca, 0xcc, 0x88, 0xcf, 0x6d, 0xb3, 0x64, 0xb7, + /*2500:*/ 0x83, 0x3d, 0xb3, 0xc4, 0xeb, 0x8a, 0xb4, 0x51, 0xe2, 0xd2, 0xa7, 0x7d, 0x7a, 0x42, 0x06, 0x76, + /*2510:*/ 0x12, 0xd2, 0xd6, 0x93, 0x59, 0xa4, 0xd9, 0x03, 0xf1, 0x86, 0x9b, 0xb3, 0xb7, 0x95, 0xcc, 0xe6, + /*2520:*/ 0x9f, 0x58, 0x50, 0x65, 0xfc, 0xbd, 0x56, 0xd3, 0x0c, 0x62, 0xc7, 0x26, 0x18, 0x37, 0x9f, 0x1f, + /*2530:*/ 0x59, 0x2e, 0x19, 0x85, 0x53, 0x2f, 0x89, 0x34, 0x6d, 0xcd, 0x55, 0x5b, 0x43, 0xe9, 0x04, 0x58, + /*2540:*/ 0x3d, 0x5d, 0x35, 0x8e, 0x87, 0xcc, 0x0b, 0x86, 0x3f, 0x6f, 0xdc, 0x2e, 0xb2, 0xf6, 0x9a, 0x34, + /*2550:*/ 0x32, 0xef, 0x53, 0x27, 0xbd, 0x7f, 0x46, 0xce, 0xf5, 0x12, 0x45, 0x61, 0x30, 0x05, 0x75, 0xa7, + /*2560:*/ 0x15, 0x6a, 0xb2, 0xe5, 0x64, 0xde, 0x84, 0x1b, 0xef, 0x1d, 0xeb, 0x9d, 0xc8, 0x40, 0x59, 0xf7, + /*2570:*/ 0xd7, 0x8d, 0xb1, 0x43, 0x4d, 0xbf, 0xb8, 0x6f, 0x5f, 0x1e, 0xd8, 0x78, 0xb0, 0x76, 0x6c, 0x98, + /*2580:*/ 0xb3, 0xc5, 0xe6, 0x42, 0xe6, 0x75, 0xfd, 0xeb, 0x5b, 0xc4, 0xea, 0xa8, 0xc3, 0x09, 0x0c, 0x14, + /*2590:*/ 0x10, 0xd3, 0x07, 0x51, 0x18, 0xb7, 0x92, 0x96, 0x9c, 0x89, 0x69, 0xa6, 0xba, 0xe4, 0xed, 0x46, + /*25a0:*/ 0xdd, 0x8a, 0x2b, 0x72, 0x79, 0xe5, 0x99, 0xb6, 0x9e, 0x9a, 0x6e, 0x43, 0x6f, 0xd8, 0xbb, 0x1f, + /*25b0:*/ 0xea, 0x95, 0xe4, 0x91, 0xfd, 0x22, 0x9a, 0xa3, 0x70, 0x17, 0x4e, 0x20, 0xc9, 0x58, 0x8b, 0x68, + /*25c0:*/ 0xac, 0xcb, 0x5a, 0xc6, 0xdb, 0xe4, 0x3d, 0xb6, 0x38, 0x64, 0x9a, 0x92, 0xe2, 0x7d, 0xf0, 0x4d, + /*25d0:*/ 0x7f, 0x7d, 0x32, 0x2c, 0xf1, 0xc5, 0x5f, 0xf6, 0x69, 0x87, 0xa9, 0x5d, 0x28, 0x5b, 0x4c, 0x47, + /*25e0:*/ 0xd9, 0x6a, 0x2f, 0x30, 0xdc, 0x94, 0x08, 0xe7, 0x19, 0x85, 0x82, 0x8d, 0xf7, 0xce, 0x71, 0x5e, + /*25f0:*/ 0x14, 0x5a, 0x69, 0x2a, 0xb1, 0x43, 0x4c, 0xc4, 0xd1, 0xbf, 0xcb, 0x22, 0x57, 0xa4, 0x17, 0x48, + /*2600:*/ 0x41, 0x40, 0x19, 0xb6, 0xed, 0x43, 0xf6, 0xba, 0xec, 0x75, 0x34, 0xd7, 0x1b, 0xf8, 0x24, 0x75, + /*2610:*/ 0xb2, 0xd3, 0x5c, 0xf3, 0xa1, 0x09, 0xea, 0xa7, 0xd8, 0x51, 0x83, 0xc4, 0xe1, 0x19, 0x4a, 0x6f, + /*2620:*/ 0x18, 0x23, 0xba, 0x6d, 0xea, 0x68, 0xf2, 0x9f, 0x94, 0xbd, 0x7a, 0xdc, 0xb8, 0xbf, 0x31, 0x1a, + /*2630:*/ 0x9e, 0xfa, 0xa2, 0xcd, 0xd2, 0x06, 0xc5, 0xd4, 0x40, 0xeb, 0x36, 0xca, 0x5a, 0xd6, 0xc6, 0x1e, + /*2640:*/ 0x4d, 0xdf, 0xcd, 0x9d, 0x0e, 0x03, 0x8a, 0x17, 0x0e, 0x14, 0x71, 0xf4, 0xf8, 0x7b, 0x0b, 0x3e, + /*2650:*/ 0x75, 0xf2, 0xed, 0x86, 0xe7, 0x80, 0xa8, 0xdc, 0x49, 0x2f, 0xe7, 0xc8, 0x4c, 0xa4, 0x41, 0x31, + /*2660:*/ 0xe5, 0xa4, 0x18, 0x26, 0x92, 0xd9, 0x8d, 0xb6, 0x7d, 0x8e, 0xaa, 0xff, 0x36, 0xdd, 0x05, 0x6e, + /*2670:*/ 0x90, 0x3f, 0x4c, 0xf8, 0x9d, 0xbc, 0xba, 0x80, 0x23, 0xa8, 0x0e, 0xff, 0x30, 0x3a, 0x72, 0x35, + /*2680:*/ 0xa2, 0x0d, 0x5d, 0xcc, 0xcf, 0xef, 0xc1, 0x85, 0x50, 0xdd, 0x44, 0x1e, 0x2b, 0x27, 0x1d, 0x24, + /*2690:*/ 0x69, 0x3c, 0xc6, 0x1d, 0xdc, 0xd7, 0x36, 0xbb, 0xc4, 0xd9, 0x6e, 0xb2, 0x47, 0x1a, 0x10, 0x31, + /*26a0:*/ 0xe8, 0x0d, 0xcd, 0x1a, 0x6e, 0x5f, 0xf4, 0xeb, 0xb9, 0xa2, 0xa9, 0xaa, 0x2e, 0x24, 0x63, 0xf2, + /*26b0:*/ 0x06, 0x8d, 0xa2, 0x9e, 0x43, 0x67, 0x5f, 0x54, 0x46, 0xa4, 0x9a, 0x21, 0xab, 0x3a, 0x94, 0xb9, + /*26c0:*/ 0x31, 0x26, 0x2b, 0x00, 0xd9, 0xc8, 0x8a, 0xd9, 0x21, 0x57, 0x1d, 0xad, 0x5b, 0xe7, 0x16, 0x97, + /*26d0:*/ 0x7b, 0xaf, 0xdc, 0x29, 0x0e, 0x65, 0xbb, 0xa6, 0x37, 0x60, 0xd3, 0x3a, 0x16, 0x54, 0xad, 0xc2, + /*26e0:*/ 0x24, 0x16, 0x37, 0x50, 0x70, 0xa4, 0xbf, 0x2f, 0x2e, 0xbb, 0x70, 0x7f, 0x8c, 0x02, 0x79, 0xd4, + /*26f0:*/ 0xd8, 0xcd, 0x30, 0x86, 0x41, 0xb2, 0x04, 0xee, 0x02, 0x48, 0xc4, 0xe3, 0x0f, 0x07, 0x16, 0x33, + /*2700:*/ 0x84, 0xb9, 0xe3, 0xcb, 0x93, 0x08, 0x0a, 0xb9, 0x43, 0xa3, 0xde, 0x93, 0x3c, 0x28, 0x87, 0xc6, + /*2710:*/ 0x86, 0xcd, 0x2c, 0x76, 0xf1, 0xcf, 0x6b, 0x9d, 0x5f, 0xe5, 0x4a, 0x2d, 0xf6, 0xa5, 0xaf, 0x07, + /*2720:*/ 0x86, 0xa1, 0x47, 0xa7, 0x2a, 0xb3, 0xa7, 0xa7, 0x58, 0xe4, 0x0f, 0x8c, 0x01, 0xe3, 0x1d, 0x9a, + /*2730:*/ 0xc5, 0xe6, 0xac, 0x1b, 0x54, 0xf0, 0x67, 0x9b, 0x41, 0xdd, 0x28, 0x6a, 0xed, 0xf0, 0x09, 0x3a, + /*2740:*/ 0xd1, 0x73, 0x7a, 0x22, 0x4f, 0x1e, 0x51, 0xa4, 0xdf, 0x72, 0xf7, 0xef, 0xb9, 0xbb, 0x3b, 0x4d, + /*2750:*/ 0x12, 0x3b, 0xd3, 0xcb, 0x3d, 0xe2, 0xe4, 0x2b, 0x11, 0x9b, 0x3a, 0xa1, 0x53, 0xaa, 0xeb, 0xc4, + /*2760:*/ 0xc9, 0xbc, 0x1c, 0x58, 0xd1, 0x52, 0x8f, 0x32, 0xac, 0xee, 0x91, 0xe6, 0x2f, 0x24, 0x92, 0x33, + /*2770:*/ 0xdd, 0xe5, 0xab, 0x20, 0x8c, 0x5f, 0x2a, 0x17, 0x93, 0x25, 0x9e, 0xb7, 0x93, 0x60, 0x6e, 0xde, + /*2780:*/ 0x42, 0x5e, 0x76, 0x54, 0xe9, 0x33, 0xf2, 0xd0, 0x8a, 0x15, 0xec, 0x0b, 0xff, 0x40, 0xf2, 0xe7, + /*2790:*/ 0x2e, 0x17, 0xeb, 0x36, 0x13, 0x9d, 0xe3, 0xd2, 0xa4, 0x14, 0x27, 0xbe, 0x8f, 0x3a, 0x80, 0xa7, + /*27a0:*/ 0x5d, 0xb8, 0xa7, 0xf6, 0x6a, 0x7f, 0x39, 0xdb, 0xa6, 0x39, 0x14, 0xfa, 0x57, 0xa7, 0x77, 0xbf, + /*27b0:*/ 0xe3, 0xe4, 0xf0, 0x8f, 0x13, 0x85, 0xd4, 0x21, 0xfb, 0x5c, 0x0d, 0xb8, 0xea, 0x0a, 0xb5, 0xb4, + /*27c0:*/ 0x92, 0x9f, 0x2b, 0x48, 0x47, 0x14, 0x26, 0x04, 0x4c, 0xe9, 0x66, 0x11, 0x55, 0x09, 0x09, 0x81, + /*27d0:*/ 0x80, 0x04, 0x2c, 0x3d, 0x2e, 0x53, 0x28, 0x5e, 0x75, 0x34, 0xc5, 0x26, 0x03, 0xfe, 0x1a, 0xe5, + /*27e0:*/ 0x69, 0xea, 0xec, 0x65, 0x5f, 0xaa, 0x8f, 0x51, 0xfe, 0x66, 0xd2, 0x7c, 0x14, 0x95, 0xfc, 0xaf, + /*27f0:*/ 0x93, 0x95, 0xe9, 0x2a, 0x21, 0x73, 0x19, 0x03, 0xc0, 0x22, 0xb8, 0xcb, 0xfa, 0x70, 0xde, 0xb1, + /*2800:*/ 0x22, 0xa5, 0xc1, 0xf5, 0x7c, 0xb1, 0xe4, 0x27, 0xbc, 0xd5, 0xcf, 0x5f, 0x8d, 0x0c, 0xb1, 0x32, + /*2810:*/ 0x32, 0x42, 0xa0, 0x9a, 0x4e, 0xbf, 0x49, 0x8f, 0xb1, 0xd9, 0x54, 0xe9, 0x43, 0x87, 0x62, 0xb2, + /*2820:*/ 0xe5, 0xc8, 0xda, 0xbb, 0x94, 0x2c, 0x70, 0x98, 0x53, 0x34, 0xaa, 0x5e, 0x6e, 0x83, 0x62, 0x33, + /*2830:*/ 0x82, 0xeb, 0x3f, 0xa2, 0x3b, 0x47, 0xfa, 0x8a, 0x53, 0x9f, 0xc4, 0xff, 0x5f, 0x42, 0x54, 0xea, + /*2840:*/ 0x39, 0xf6, 0xc5, 0x6f, 0x25, 0xcb, 0x8e, 0xc2, 0x6a, 0xa2, 0x89, 0xed, 0x4d, 0xee, 0x3b, 0xe9, + /*2850:*/ 0xba, 0x33, 0x84, 0x55, 0xc3, 0x3e, 0xae, 0xba, 0xd4, 0x1a, 0x15, 0x76, 0xe8, 0x86, 0x6c, 0xf2, + /*2860:*/ 0x71, 0x9e, 0xa9, 0x53, 0x47, 0xbc, 0x84, 0x0a, 0xdf, 0x7e, 0x76, 0x58, 0xdd, 0x29, 0x11, 0x33, + /*2870:*/ 0xa8, 0xf4, 0x83, 0xe9, 0xad, 0x0f, 0x49, 0x14, 0x5d, 0xd2, 0x1d, 0xa7, 0x9a, 0xa7, 0x99, 0xdb, + /*2880:*/ 0xff, 0x6c, 0x7d, 0x15, 0x8d, 0x8a, 0x57, 0x2e, 0x20, 0x0a, 0xcb, 0x45, 0x76, 0x0b, 0x7b, 0xf0, + /*2890:*/ 0x7f, 0xb7, 0x76, 0x74, 0x25, 0xec, 0x3c, 0x57, 0xd7, 0x59, 0xb0, 0x8e, 0xef, 0xb3, 0x69, 0xa6, + /*28a0:*/ 0x56, 0x78, 0x16, 0x52, 0x5a, 0xa1, 0x1a, 0xf1, 0x71, 0xe6, 0xfb, 0x0e, 0xcc, 0xde, 0xa7, 0xf5, + /*28b0:*/ 0x13, 0x3f, 0xe4, 0x6a, 0x8f, 0x59, 0xb1, 0x99, 0x3b, 0x87, 0x51, 0xee, 0x93, 0x50, 0xd6, 0xac, + /*28c0:*/ 0x70, 0xc6, 0xd8, 0x62, 0xad, 0x35, 0xc0, 0xb4, 0xd4, 0x2b, 0xba, 0x47, 0x5c, 0x7d, 0xc9, 0xb5, + /*28d0:*/ 0x77, 0x88, 0xf2, 0x89, 0x2e, 0x0e, 0x32, 0x9d, 0x7f, 0xc5, 0x23, 0x59, 0xc7, 0x9c, 0x2e, 0xa4, + /*28e0:*/ 0x55, 0x9f, 0xd1, 0xbd, 0xaf, 0x79, 0x22, 0xb3, 0xdc, 0xb6, 0xb0, 0xc4, 0xa6, 0x94, 0x0b, 0x75, + /*28f0:*/ 0x84, 0x73, 0xb4, 0x9e, 0xed, 0xd5, 0x7b, 0x4d, 0x2c, 0x99, 0x38, 0x40, 0xd1, 0xec, 0x86, 0x20, + /*2900:*/ 0x98, 0xe4, 0x4b, 0xad, 0xa4, 0x1f, 0x52, 0xb1, 0x1e, 0xc1, 0x6a, 0x36, 0xe1, 0x81, 0x01, 0xf8, + /*2910:*/ 0xea, 0xbf, 0xaf, 0x50, 0xcb, 0x26, 0x91, 0xc0, 0xaf, 0x58, 0x83, 0x18, 0x35, 0x9f, 0x5d, 0x81, + /*2920:*/ 0x2d, 0xb6, 0x57, 0x44, 0xce, 0x5f, 0x90, 0x0d, 0x80, 0x6c, 0xd3, 0xc7, 0x54, 0x09, 0x17, 0xde, + /*2930:*/ 0xe7, 0x6c, 0xef, 0x31, 0xa5, 0x19, 0xc3, 0xfd, 0x8e, 0x66, 0xd5, 0x6c, 0x12, 0x3c, 0x42, 0xc6, + /*2940:*/ 0x35, 0xc8, 0x76, 0x06, 0x1e, 0xc0, 0xfc, 0xe7, 0xc0, 0x0c, 0x0c, 0x79, 0xec, 0x36, 0x82, 0xf2, + /*2950:*/ 0xcc, 0x60, 0x97, 0x2e, 0xf7, 0x81, 0x35, 0xa0, 0x47, 0x1b, 0xbc, 0xfe, 0x2e, 0x0f, 0xdc, 0xfc, + /*2960:*/ 0xa6, 0xc2, 0xe5, 0x86, 0x4f, 0x26, 0x8d, 0x45, 0x1f, 0x41, 0xdf, 0x94, 0x0c, 0x7e, 0x56, 0x3f, + /*2970:*/ 0x1c, 0x8a, 0xfd, 0x31, 0x83, 0xf8, 0x14, 0x25, 0xf0, 0x01, 0x42, 0x26, 0xe3, 0xf8, 0x9a, 0x17, + /*2980:*/ 0xa8, 0x9b, 0x88, 0x39, 0x52, 0x1e, 0x4b, 0x8b, 0x06, 0x67, 0x75, 0x7d, 0xa1, 0x11, 0x4a, 0x98, + /*2990:*/ 0x2c, 0x84, 0x91, 0x87, 0xdc, 0x4a, 0xf7, 0x8d, 0x81, 0x60, 0x85, 0xb9, 0xd8, 0x70, 0x55, 0xa6, + /*29a0:*/ 0xae, 0x44, 0xbd, 0x27, 0x2a, 0x4e, 0x36, 0xcc, 0x02, 0x8e, 0x21, 0x4b, 0xbf, 0xdc, 0x86, 0xa8, + /*29b0:*/ 0xb8, 0x61, 0xad, 0x98, 0x96, 0xd5, 0x02, 0xc5, 0x1f, 0xe2, 0x6b, 0xf3, 0x4c, 0x54, 0xc0, 0x4f, + /*29c0:*/ 0xfb, 0x39, 0x1a, 0xf7, 0x2e, 0x56, 0xc8, 0x95, 0x7e, 0x1f, 0xeb, 0xa9, 0x1e, 0xec, 0xe7, 0x48, + /*29d0:*/ 0x2c, 0x03, 0x11, 0xde, 0xec, 0x97, 0x23, 0x2e, 0x16, 0x42, 0x4c, 0xdd, 0x4b, 0x18, 0x32, 0x6e, + /*29e0:*/ 0x6e, 0x0e, 0x1f, 0xf9, 0x69, 0xbd, 0xde, 0xf9, 0x37, 0xb8, 0xf8, 0x98, 0xf8, 0x5c, 0x88, 0xaa, + /*29f0:*/ 0x61, 0xb3, 0xe7, 0x79, 0x92, 0x68, 0xef, 0x86, 0x04, 0xba, 0x18, 0x5e, 0xa6, 0x03, 0x68, 0x4b, + /*2a00:*/ 0x26, 0xe5, 0x5f, 0x0f, 0xf6, 0xb2, 0xae, 0x02, 0x40, 0xbe, 0xa7, 0x1a, 0xec, 0x22, 0x5e, 0xe6, + /*2a10:*/ 0x21, 0x42, 0xd9, 0xb0, 0xd2, 0xe4, 0x89, 0xf5, 0xd0, 0x2d, 0xd6, 0x23, 0x39, 0xc9, 0xdb, 0xeb, + /*2a20:*/ 0x53, 0x55, 0xbf, 0x01, 0x36, 0x17, 0xf9, 0x05, 0x20, 0x80, 0x13, 0x38, 0x32, 0x2d, 0x09, 0x98, + /*2a30:*/ 0x04, 0x6a, 0x90, 0x6c, 0x18, 0x52, 0x41, 0x82, 0xc7, 0x0c, 0xe9, 0xae, 0x12, 0x35, 0xc9, 0xaf, + /*2a40:*/ 0x43, 0x52, 0x68, 0x19, 0x2f, 0xff, 0x75, 0xf7, 0xab, 0x9d, 0x58, 0x13, 0x0f, 0xa4, 0x17, 0x3f, + /*2a50:*/ 0x9f, 0x29, 0x37, 0xb9, 0x28, 0x00, 0x19, 0x06, 0xb9, 0xe9, 0x54, 0x6d, 0xa7, 0x21, 0x58, 0xf9, + /*2a60:*/ 0xa5, 0xf2, 0xc5, 0x10, 0x50, 0x0d, 0x50, 0x0d, 0xb4, 0xe5, 0xb8, 0x27, 0xa3, 0xe7, 0xab, 0x25, + /*2a70:*/ 0x8d, 0x8c, 0x09, 0x28, 0xd8, 0x8c, 0x69, 0x34, 0xd2, 0x8e, 0xa1, 0xf7, 0x49, 0x35, 0xa0, 0x2f, + /*2a80:*/ 0x06, 0x38, 0x57, 0xfe, 0x6f, 0xdc, 0x68, 0xcd, 0xfc, 0x71, 0xf1, 0x9e, 0xb9, 0x1e, 0x75, 0xff, + /*2a90:*/ 0x90, 0x36, 0xbc, 0x7a, 0x86, 0x65, 0xd3, 0xeb, 0x71, 0xa1, 0x62, 0x05, 0x33, 0xa5, 0x3c, 0xe5, + /*2aa0:*/ 0x2b, 0xfd, 0x7b, 0x4c, 0x25, 0x6f, 0x7b, 0xba, 0xdf, 0x90, 0x9e, 0xed, 0x8c, 0x1a, 0x7b, 0xac, + /*2ab0:*/ 0x08, 0xa7, 0x7d, 0xf4, 0xf4, 0xa2, 0x60, 0x48, 0xd5, 0x53, 0x39, 0xb4, 0xd9, 0x59, 0x8c, 0xcc, + /*2ac0:*/ 0x20, 0xb7, 0x16, 0x97, 0x7e, 0xd9, 0x6f, 0x2b, 0x57, 0xd9, 0xb5, 0xfa, 0x67, 0x3f, 0xc6, 0x45, + /*2ad0:*/ 0x50, 0x16, 0x24, 0x46, 0x4f, 0x5c, 0xfe, 0x43, 0xc7, 0x7d, 0x35, 0xec, 0x69, 0x41, 0xf6, 0x8f, + /*2ae0:*/ 0xaf, 0x55, 0x53, 0x43, 0xc7, 0x08, 0x1c, 0x15, 0x0e, 0x77, 0xea, 0x2d, 0x80, 0x05, 0xf6, 0x5e, + /*2af0:*/ 0x66, 0x93, 0x9b, 0x2b, 0xd8, 0xc3, 0xc1, 0xf4, 0x3a, 0x6e, 0x1a, 0x81, 0x7e, 0xba, 0x14, 0xe2, + /*2b00:*/ 0x62, 0x13, 0xb4, 0x2b, 0x64, 0x83, 0x75, 0x8d, 0x7c, 0xce, 0x9d, 0xbd, 0x65, 0xd5, 0x4b, 0x28, + /*2b10:*/ 0x37, 0xb3, 0xc2, 0x7c, 0xcd, 0xbd, 0x68, 0x52, 0xa9, 0x23, 0x3e, 0xdf, 0xb6, 0xec, 0x34, 0x06, + /*2b20:*/ 0x36, 0xd7, 0x41, 0x1e, 0xff, 0x03, 0xa3, 0x53, 0x76, 0x06, 0x05, 0x1f, 0xe0, 0x56, 0xc7, 0xb5, + /*2b30:*/ 0x13, 0xc1, 0x82, 0x6c, 0x72, 0x9f, 0x9f, 0xa5, 0x33, 0x68, 0x2f, 0x54, 0x75, 0x02, 0xd6, 0xfa, + /*2b40:*/ 0x02, 0x9d, 0xe2, 0xde, 0xaf, 0x77, 0xb6, 0x5d, 0xc7, 0xa6, 0xff, 0xaf, 0x91, 0x07, 0x63, 0xd5, + /*2b50:*/ 0x75, 0xf4, 0xa6, 0xf6, 0x66, 0xe2, 0x8c, 0xb0, 0xf5, 0x40, 0xd8, 0xc3, 0xfd, 0x7c, 0xb7, 0xe4, + /*2b60:*/ 0x6f, 0xd1, 0xfa, 0xe5, 0x86, 0xba, 0x04, 0xb4, 0x65, 0xba, 0x92, 0x80, 0xa0, 0x40, 0x2c, 0xe1, + /*2b70:*/ 0x5f, 0xdb, 0xc3, 0x62, 0x73, 0xf7, 0xa9, 0x9d, 0xbf, 0x17, 0x13, 0x6d, 0xc9, 0x4a, 0x8a, 0x51, + /*2b80:*/ 0x72, 0x8f, 0xad, 0x35, 0x5a, 0xac, 0x43, 0x70, 0xd2, 0xc2, 0x64, 0xaf, 0x33, 0x76, 0xe5, 0xda, + /*2b90:*/ 0x59, 0xb2, 0xdf, 0x54, 0x61, 0x9f, 0x9a, 0xa3, 0x57, 0x74, 0xf1, 0x22, 0xcc, 0x4d, 0x87, 0x68, + /*2ba0:*/ 0x4f, 0x77, 0xcb, 0xc1, 0x7c, 0xb5, 0xaf, 0x6f, 0xe0, 0x79, 0xbd, 0xa6, 0x2b, 0xf1, 0xb3, 0x4c, + /*2bb0:*/ 0xcf, 0x7e, 0xa4, 0x41, 0x32, 0x49, 0x72, 0x8b, 0x3c, 0xaf, 0xe4, 0xf4, 0x38, 0x30, 0x95, 0xb7, + /*2bc0:*/ 0x16, 0x80, 0x59, 0x18, 0x3d, 0x24, 0x91, 0xa5, 0x13, 0x4e, 0x8e, 0xe3, 0xe0, 0x55, 0x86, 0x3c, + /*2bd0:*/ 0xe9, 0x28, 0xae, 0x85, 0x2a, 0x08, 0xa0, 0xa5, 0x99, 0xdd, 0x66, 0xfd, 0x55, 0x4f, 0x71, 0x73, + /*2be0:*/ 0x05, 0xd6, 0x82, 0xbf, 0x7f, 0x4c, 0x3f, 0x20, 0xaf, 0x7d, 0x15, 0x71, 0x5a, 0x1a, 0x11, 0xaf, + /*2bf0:*/ 0xcc, 0xc8, 0x3f, 0x3a, 0x20, 0x0e, 0x87, 0x31, 0xdb, 0x6a, 0xe7, 0x41, 0x26, 0x72, 0xce, 0xe0, + /*2c00:*/ 0xd7, 0x69, 0x04, 0x34, 0x58, 0x82, 0xac, 0x25, 0x70, 0x0f, 0x2a, 0x71, 0x4b, 0x03, 0x39, 0x74, + /*2c10:*/ 0x74, 0x7a, 0x42, 0xde, 0x91, 0xaa, 0xdf, 0xf3, 0x9c, 0x7f, 0x72, 0x54, 0x40, 0x31, 0x01, 0xfd, + /*2c20:*/ 0x71, 0xc5, 0x2d, 0x5e, 0xfa, 0xb9, 0xab, 0x2c, 0x86, 0x63, 0x6e, 0xa7, 0xde, 0x01, 0xe8, 0x0f, + /*2c30:*/ 0x97, 0x72, 0xa2, 0x18, 0x4b, 0xd8, 0xb1, 0x04, 0xd7, 0x66, 0x2b, 0xad, 0x5b, 0xe5, 0x2c, 0x68, + /*2c40:*/ 0x78, 0xb4, 0xb5, 0x28, 0xc3, 0x8b, 0x05, 0x01, 0xf3, 0xcc, 0xf0, 0x21, 0x30, 0x1b, 0xd4, 0xab, + /*2c50:*/ 0x0a, 0x97, 0x8e, 0x46, 0xcf, 0x9a, 0xc7, 0x40, 0xe2, 0xd0, 0x8f, 0x00, 0xd7, 0x02, 0x7e, 0xab, + /*2c60:*/ 0xd3, 0xd4, 0xf4, 0x8d, 0x1f, 0x3e, 0x29, 0x26, 0x17, 0xf6, 0x06, 0xfa, 0x41, 0x45, 0x53, 0xa6, + /*2c70:*/ 0x9d, 0x50, 0xdc, 0xf8, 0x19, 0x76, 0x83, 0xc7, 0x9c, 0xe3, 0x24, 0x24, 0xd3, 0x3a, 0x14, 0x61, + /*2c80:*/ 0xb5, 0x6b, 0x08, 0x21, 0x08, 0xb1, 0xe5, 0x64, 0x8f, 0x5c, 0x2f, 0x17, 0x47, 0xef, 0x89, 0x72, + /*2c90:*/ 0x9d, 0x9e, 0x24, 0x36, 0xe9, 0x38, 0x11, 0xf2, 0x1c, 0xaf, 0x15, 0xe3, 0xac, 0x90, 0x93, 0x91, + /*2ca0:*/ 0x22, 0x30, 0x7f, 0x4d, 0x13, 0x3f, 0x64, 0x5e, 0x60, 0xc0, 0xf3, 0x47, 0xad, 0xdb, 0x94, 0xc4, + /*2cb0:*/ 0x10, 0x2e, 0xdd, 0x45, 0x21, 0xc7, 0xca, 0x0d, 0xd2, 0x3e, 0xb8, 0x28, 0xa3, 0x6c, 0x75, 0xfd, + /*2cc0:*/ 0xbc, 0xf7, 0x05, 0x70, 0x00, 0xf6, 0xda, 0xc4, 0xd0, 0x6d, 0xa7, 0x67, 0x3a, 0xa2, 0x1e, 0x4f, + /*2cd0:*/ 0xdc, 0xf8, 0x5c, 0xde, 0xb8, 0x63, 0xe6, 0xcd, 0xcd, 0x9f, 0x63, 0x54, 0x34, 0xd4, 0xa7, 0xd2, + /*2ce0:*/ 0xcf, 0xef, 0x89, 0x81, 0x83, 0x93, 0xf1, 0xda, 0xee, 0x97, 0x5a, 0x97, 0x89, 0x62, 0x03, 0xc6, + /*2cf0:*/ 0x64, 0x9d, 0x1f, 0xbb, 0x4e, 0x11, 0xf8, 0x7f, 0x6e, 0x3a, 0xd9, 0x97, 0x0d, 0xb6, 0xf1, 0x8c, + /*2d00:*/ 0xfd, 0x2d, 0x21, 0x3a, 0x20, 0xee, 0x22, 0x0a, 0xca, 0x9a, 0x46, 0x95, 0x99, 0x70, 0x84, 0x62, + /*2d10:*/ 0x65, 0x4c, 0x56, 0x13, 0x9f, 0xc4, 0xf3, 0xb1, 0x3a, 0x05, 0xe9, 0x14, 0xec, 0xb4, 0x63, 0x17, + /*2d20:*/ 0x08, 0x63, 0xc5, 0x3c, 0x0f, 0xf2, 0x26, 0xea, 0x2e, 0xc1, 0x0d, 0xc8, 0xe8, 0x02, 0x36, 0xbb, + /*2d30:*/ 0x62, 0x69, 0x99, 0x0e, 0xfc, 0xa9, 0x84, 0x1a, 0xfa, 0x38, 0xb3, 0xac, 0x7f, 0x74, 0x9e, 0x7f, + /*2d40:*/ 0xad, 0xeb, 0x76, 0xab, 0x09, 0xba, 0x81, 0x4e, 0x2a, 0x68, 0x00, 0xce, 0x1f, 0xc2, 0xc2, 0x25, + /*2d50:*/ 0x86, 0x77, 0x70, 0x27, 0x23, 0xe7, 0xf2, 0x71, 0x50, 0xc2, 0x0b, 0x30, 0x98, 0xbc, 0x0d, 0xb3, + /*2d60:*/ 0x41, 0xa7, 0x30, 0xc4, 0x32, 0x96, 0x5d, 0xa8, 0x57, 0xa4, 0x89, 0x16, 0xd3, 0x4f, 0x4b, 0x6c, + /*2d70:*/ 0xb3, 0xea, 0xc3, 0x8f, 0xc1, 0x4b, 0x19, 0xc8, 0x3d, 0xea, 0xe3, 0xf2, 0x57, 0x94, 0x4f, 0x27, + /*2d80:*/ 0x87, 0x19, 0x07, 0x46, 0xfb, 0x3e, 0x52, 0x5c, 0xdc, 0x5b, 0xb4, 0xd5, 0xee, 0x16, 0x39, 0x70, + /*2d90:*/ 0x2c, 0x0c, 0xf2, 0xe5, 0x78, 0xef, 0x10, 0xe9, 0x0f, 0xbd, 0x30, 0xdb, 0x42, 0xb9, 0xb5, 0x04, + /*2da0:*/ 0x0f, 0xa6, 0x43, 0x7b, 0x93, 0x3b, 0xb5, 0xf3, 0xb0, 0x1c, 0x52, 0x5e, 0x68, 0xb4, 0xda, 0xba, + /*2db0:*/ 0x3b, 0x66, 0x50, 0x97, 0xcd, 0x26, 0xf0, 0x3c, 0x76, 0xa3, 0xad, 0xe1, 0x42, 0x00, 0xde, 0x59, + /*2dc0:*/ 0x90, 0x70, 0xf5, 0x2f, 0x71, 0xd5, 0x82, 0x83, 0xfb, 0x74, 0xd2, 0x46, 0xbc, 0xad, 0x40, 0xf3, + /*2dd0:*/ 0x37, 0x9e, 0x6e, 0xa6, 0xa7, 0x1a, 0x3e, 0xbb, 0x5b, 0xd3, 0x09, 0x04, 0x68, 0xcf, 0xdb, 0xdd, + /*2de0:*/ 0x9e, 0x31, 0x4d, 0xf9, 0x41, 0x8d, 0xf2, 0xfc, 0x8b, 0xc6, 0x84, 0xf0, 0x77, 0xd6, 0xf0, 0x33, + /*2df0:*/ 0x5f, 0x8c, 0x26, 0x23, 0x96, 0x7a, 0x28, 0x6c, 0xfd, 0x39, 0xab, 0xa8, 0x95, 0xd2, 0xa6, 0x93, + /*2e00:*/ 0xe0, 0x0e, 0xe5, 0x2d, 0x92, 0xa4, 0xee, 0xfe, 0x4e, 0x7e, 0x7e, 0xe3, 0xae, 0x1d, 0x85, 0xfb, + /*2e10:*/ 0xb7, 0xc3, 0x7c, 0x16, 0x83, 0x98, 0x62, 0x48, 0xfe, 0x97, 0xae, 0xc7, 0x43, 0x00, 0xc4, 0xe7, + /*2e20:*/ 0x62, 0xc1, 0xcf, 0xfe, 0x7d, 0xce, 0xbe, 0xdc, 0xfa, 0x73, 0xde, 0xc5, 0x04, 0x22, 0x56, 0x18, + /*2e30:*/ 0x9c, 0xf9, 0xea, 0xab, 0x3a, 0x82, 0xb6, 0xab, 0xc7, 0x55, 0xe1, 0xe7, 0x4e, 0x88, 0xc9, 0xf5, + /*2e40:*/ 0x48, 0x1a, 0x92, 0xd0, 0x2e, 0x2a, 0x00, 0xbe, 0x2f, 0x10, 0x74, 0x8e, 0xde, 0x04, 0x01, 0x82, + /*2e50:*/ 0xe3, 0x21, 0xc2, 0x63, 0xab, 0x2b, 0x68, 0x6a, 0x2b, 0xfb, 0xd8, 0xca, 0xb9, 0x8b, 0x75, 0xe3, + /*2e60:*/ 0xd5, 0xe3, 0xcf, 0x0d, 0xde, 0x70, 0x39, 0x88, 0x85, 0xa5, 0x52, 0x96, 0x6c, 0x95, 0x44, 0x8b, + /*2e70:*/ 0x5e, 0x31, 0x57, 0xb3, 0xe8, 0xef, 0x7a, 0x1e, 0xfa, 0x56, 0x4a, 0xe9, 0x5a, 0xb2, 0xba, 0x24, + /*2e80:*/ 0x01, 0x19, 0x1c, 0x4e, 0xa9, 0xd3, 0xdf, 0xcb, 0xe0, 0x48, 0xb1, 0xd6, 0x30, 0xca, 0xa8, 0x5c, + /*2e90:*/ 0x91, 0x2f, 0x37, 0x8b, 0x9a, 0x06, 0x2a, 0x4d, 0x30, 0x32, 0x13, 0x4b, 0x4b, 0x67, 0x61, 0xbc, + /*2ea0:*/ 0xc3, 0x74, 0xae, 0xeb, 0xcb, 0x45, 0xd6, 0xaa, 0xf7, 0x60, 0xb6, 0x4b, 0xf5, 0x83, 0xe8, 0x7f, + /*2eb0:*/ 0x3a, 0x91, 0xdd, 0x92, 0xfa, 0xe7, 0x49, 0x8c, 0x20, 0x60, 0x74, 0x68, 0xe5, 0x24, 0xce, 0xc1, + /*2ec0:*/ 0x83, 0xa7, 0x43, 0xb3, 0x8d, 0x3f, 0xd6, 0x23, 0x2b, 0x1c, 0xc5, 0x7d, 0xdc, 0x00, 0xea, 0x3f, + /*2ed0:*/ 0x78, 0xc8, 0x72, 0x9a, 0x59, 0x37, 0x86, 0xfb, 0x33, 0x35, 0x8f, 0x9f, 0x7d, 0x67, 0xe9, 0x6e, + /*2ee0:*/ 0x11, 0xd5, 0x0e, 0x95, 0x3d, 0xcc, 0xb7, 0x1d, 0x06, 0xf5, 0x72, 0x48, 0xdc, 0x8f, 0xbe, 0xbf, + /*2ef0:*/ 0xd2, 0x37, 0x03, 0xa9, 0x2f, 0xa6, 0x7e, 0x73, 0xd7, 0xbe, 0xd2, 0xd2, 0x21, 0xbf, 0x1d, 0xf4, + /*2f00:*/ 0x61, 0xd1, 0x58, 0x0e, 0x83, 0xcd, 0xdb, 0x2a, 0x94, 0x5c, 0xe7, 0x38, 0x34, 0x68, 0x3a, 0x12, + /*2f10:*/ 0x80, 0xa7, 0x2b, 0x5a, 0xc6, 0x49, 0x20, 0x8f, 0x45, 0x5d, 0x04, 0xcf, 0xc6, 0xc8, 0xa3, 0x24, + /*2f20:*/ 0xc7, 0x33, 0xb3, 0x6c, 0x63, 0x78, 0x8f, 0xcf, 0xe3, 0x61, 0xf5, 0xe3, 0x0a, 0x43, 0xfd, 0x89, + /*2f30:*/ 0x62, 0x82, 0xe0, 0x91, 0x66, 0xf4, 0x04, 0x60, 0xe2, 0x15, 0x1a, 0x81, 0xe2, 0x1e, 0x6f, 0xc6, + /*2f40:*/ 0xcc, 0x87, 0xe4, 0xb5, 0xf2, 0xe5, 0xcf, 0x22, 0x11, 0xfe, 0x03, 0x3a, 0xc3, 0x0f, 0x0c, 0xe7, + /*2f50:*/ 0xb7, 0x87, 0xf9, 0x45, 0x5a, 0x78, 0x18, 0xba, 0x73, 0x63, 0x4d, 0x89, 0x00, 0xeb, 0x35, 0xa6, + /*2f60:*/ 0xee, 0x71, 0xa1, 0xb1, 0x17, 0xc6, 0x83, 0x69, 0xab, 0x7a, 0x18, 0xed, 0xaa, 0x1c, 0x56, 0x88, + /*2f70:*/ 0x89, 0x3e, 0x3a, 0x54, 0x18, 0x7d, 0x3e, 0x72, 0x86, 0x0f, 0xa4, 0xfb, 0x96, 0x14, 0x12, 0x7b, + /*2f80:*/ 0x94, 0x3c, 0x6a, 0xbc, 0x8b, 0x2d, 0x81, 0x36, 0x24, 0x12, 0xfc, 0x73, 0x78, 0xcd, 0xe4, 0x7a, + /*2f90:*/ 0xfb, 0xd2, 0x48, 0xfa, 0x59, 0x8b, 0xf0, 0x2a, 0xe8, 0xae, 0xf5, 0x88, 0x31, 0xdf, 0xbe, 0x89, + /*2fa0:*/ 0x6b, 0x6e, 0xa1, 0x8f, 0x57, 0x94, 0x92, 0x0c, 0x0c, 0x23, 0x81, 0x6b, 0x48, 0x9b, 0xe7, 0x96, + /*2fb0:*/ 0xd3, 0xe3, 0x3b, 0x4a, 0xff, 0xe4, 0x7a, 0x79, 0xa2, 0x25, 0xf0, 0x08, 0x04, 0x59, 0x91, 0xe3, + /*2fc0:*/ 0x44, 0xa4, 0xf1, 0xe6, 0x56, 0x34, 0xc0, 0x94, 0x75, 0x51, 0x7c, 0x78, 0x71, 0xdd, 0xb9, 0x36, + /*2fd0:*/ 0xb8, 0xf5, 0xc3, 0xf4, 0xb6, 0x87, 0x72, 0xcb, 0x99, 0x79, 0x24, 0x12, 0xc8, 0x3e, 0xf6, 0xcd, + /*2fe0:*/ 0x00, 0x6f, 0x4e, 0x47, 0xac, 0x90, 0x08, 0x69, 0x26, 0xd2, 0x5e, 0x84, 0x71, 0x5f, 0xb2, 0x1e, + /*2ff0:*/ 0x7f, 0x3c, 0x9d, 0x9d, 0x11, 0x37, 0xa6, 0x2d, 0x12, 0x0c, 0xb3, 0x43, 0x2b, 0xe0, 0x03, 0x40, + /*3000:*/ 0x04, 0x7b, 0xc5, 0x3a, 0x76, 0xf1, 0xa0, 0xf6, 0x40, 0x30, 0x60, 0xf7, 0xe4, 0x08, 0x0f, 0x0e, + /*3010:*/ 0x3a, 0x7d, 0x2c, 0xac, 0xe1, 0x11, 0xfc, 0x01, 0xef, 0x9c, 0x5b, 0x94, 0xda, 0x52, 0x80, 0xe4, + /*3020:*/ 0x98, 0x17, 0x01, 0xc2, 0x95, 0xa2, 0xce, 0x8b, 0x61, 0xb2, 0x96, 0x70, 0xdc, 0xfc, 0x33, 0x63, + /*3030:*/ 0x25, 0xa2, 0x7a, 0x70, 0xe3, 0xb5, 0x65, 0x98, 0xe2, 0x99, 0x46, 0x54, 0x0d, 0x36, 0xff, 0xfd, + /*3040:*/ 0x36, 0x4d, 0x26, 0x4c, 0x1d, 0x67, 0xea, 0xd8, 0x2b, 0x0d, 0xd4, 0x9f, 0xab, 0x77, 0xde, 0x9d, + /*3050:*/ 0x0d, 0xa1, 0x12, 0x41, 0xa6, 0xc5, 0x37, 0x6d, 0x76, 0xdb, 0xdb, 0xa2, 0x90, 0xa3, 0xbf, 0x96, + /*3060:*/ 0xb7, 0xef, 0x0b, 0xd0, 0xf0, 0xda, 0x1e, 0x91, 0xcf, 0x4e, 0xd8, 0x18, 0x0e, 0x80, 0x0a, 0x4b, + /*3070:*/ 0x51, 0xf0, 0x05, 0xb0, 0x18, 0xc2, 0x95, 0xb7, 0xa6, 0x83, 0x66, 0x92, 0x99, 0x06, 0x0e, 0x93, + /*3080:*/ 0xff, 0x18, 0x70, 0x1c, 0x4f, 0xec, 0x72, 0x13, 0x38, 0xcb, 0x6d, 0xe7, 0x81, 0x7a, 0xb4, 0x90, + /*3090:*/ 0x16, 0xc2, 0xac, 0xaa, 0x09, 0xdc, 0x5b, 0xe2, 0x6a, 0xf3, 0xfe, 0xc6, 0x63, 0x17, 0x33, 0x72, + /*30a0:*/ 0xbd, 0xee, 0x7c, 0xb4, 0x1c, 0x54, 0x18, 0xff, 0x10, 0x87, 0xe1, 0x26, 0xe5, 0xa6, 0x1a, 0xba, + /*30b0:*/ 0xd3, 0x96, 0x31, 0xf1, 0x95, 0x71, 0xbf, 0xe2, 0x6e, 0x37, 0xaa, 0x89, 0x64, 0x94, 0xdf, 0x77, + /*30c0:*/ 0xc3, 0x26, 0x42, 0xe2, 0xc2, 0xa5, 0x62, 0xea, 0x02, 0x58, 0xa6, 0x55, 0x71, 0xe5, 0xf5, 0x5b, + /*30d0:*/ 0x3c, 0xea, 0x7f, 0x64, 0xac, 0xc0, 0xc4, 0x86, 0xc0, 0xa9, 0xeb, 0xcb, 0x17, 0x13, 0xff, 0x9e, + /*30e0:*/ 0xe0, 0xbb, 0xd0, 0x78, 0xfb, 0xfb, 0x5e, 0xe8, 0xb9, 0xbc, 0x71, 0x91, 0x67, 0x17, 0x18, 0x57, + /*30f0:*/ 0x66, 0x96, 0x10, 0x74, 0xca, 0xb9, 0x26, 0x7b, 0x4d, 0x70, 0xf0, 0xa7, 0x17, 0x45, 0xe8, 0x9a, + /*3100:*/ 0xe6, 0x8a, 0x20, 0xca, 0x70, 0x36, 0x05, 0x97, 0x9b, 0x72, 0x5b, 0xf4, 0x8d, 0x53, 0x53, 0xbb, + /*3110:*/ 0x7f, 0xdd, 0x50, 0xb7, 0x15, 0xec, 0xd2, 0x2f, 0x4b, 0xa6, 0xdc, 0x3d, 0x35, 0xf4, 0xa0, 0x33, + /*3120:*/ 0xaa, 0x3a, 0xff, 0x10, 0x6f, 0x90, 0x12, 0x28, 0x2b, 0x63, 0x07, 0xa6, 0x9d, 0xd9, 0xa7, 0x9a, + /*3130:*/ 0x3c, 0x70, 0xbd, 0x00, 0x8f, 0x32, 0x13, 0x70, 0xff, 0xd0, 0x19, 0x50, 0xcb, 0x96, 0x3f, 0xfe, + /*3140:*/ 0x11, 0x89, 0x27, 0xfb, 0xbf, 0x3d, 0x0d, 0x76, 0x99, 0x06, 0xc3, 0x75, 0xd4, 0xa4, 0x3c, 0xbe, + /*3150:*/ 0xdb, 0x7c, 0x0c, 0xf1, 0xb7, 0xf4, 0x56, 0xdd, 0x90, 0x54, 0xbd, 0x3e, 0x69, 0x15, 0xda, 0x17, + /*3160:*/ 0xf7, 0xb8, 0x06, 0xf5, 0xab, 0x2d, 0x69, 0xb2, 0xaf, 0xa9, 0x01, 0xa0, 0xc4, 0x61, 0x79, 0x63, + /*3170:*/ 0xb9, 0x9c, 0x06, 0x21, 0x1d, 0x8c, 0xd3, 0x31, 0x65, 0x12, 0x4e, 0xb0, 0xcb, 0x2a, 0x36, 0x06, + /*3180:*/ 0x28, 0xff, 0x9d, 0x97, 0xd0, 0x75, 0xbc, 0x69, 0xec, 0x90, 0xb3, 0xf9, 0x4a, 0x94, 0xf0, 0xd6, + /*3190:*/ 0xd0, 0xd5, 0xd2, 0xb3, 0xd9, 0x58, 0x02, 0x75, 0x60, 0xf0, 0x49, 0x45, 0xe5, 0xa8, 0x41, 0x77, + /*31a0:*/ 0xb7, 0xd4, 0x8d, 0x93, 0x05, 0xb8, 0x56, 0xb9, 0xe8, 0x79, 0x9e, 0x83, 0xc4, 0x45, 0xe5, 0x20, + /*31b0:*/ 0xa9, 0x7d, 0x7a, 0xf7, 0x20, 0x23, 0x6c, 0xf4, 0x57, 0xc2, 0xba, 0x79, 0xa8, 0x8c, 0x01, 0x9e, + /*31c0:*/ 0x66, 0x6a, 0xae, 0x76, 0x49, 0x27, 0x74, 0xe7, 0x17, 0x84, 0xaa, 0x49, 0xb5, 0x16, 0x37, 0xea, + /*31d0:*/ 0x6c, 0x01, 0x90, 0x79, 0x21, 0xe2, 0x0d, 0x77, 0xca, 0x7a, 0xf8, 0xff, 0x41, 0x21, 0xf5, 0x1c, + /*31e0:*/ 0xf7, 0x9f, 0x8b, 0xa3, 0x5c, 0xc1, 0x5b, 0xce, 0xbb, 0x12, 0x22, 0xf8, 0xd0, 0x36, 0x67, 0x23, + /*31f0:*/ 0xa1, 0x1d, 0xf7, 0x60, 0x33, 0xa3, 0x85, 0xcd, 0x0f, 0xeb, 0x39, 0xa7, 0xda, 0xd5, 0xcd, 0x8c, + /*3200:*/ 0xaf, 0x12, 0x06, 0xe8, 0x4c, 0x44, 0x1d, 0x93, 0xfc, 0x89, 0x93, 0x00, 0x64, 0xa3, 0xcc, 0x00, + /*3210:*/ 0x00, 0x09, 0x9a, 0x19, 0x9e, 0xbc, 0x82, 0x1c, 0x22, 0x1a, 0x65, 0x08, 0x99, 0xe8, 0x42, 0x68, + /*3220:*/ 0x98, 0x1d, 0x63, 0x25, 0x00, 0xda, 0xa5, 0xce, 0xf2, 0x6b, 0x6c, 0x12, 0x3b, 0xda, 0xde, 0xa2, + /*3230:*/ 0xaa, 0xd3, 0x5e, 0x3d, 0x32, 0x84, 0x53, 0x53, 0x7f, 0x44, 0x68, 0xbd, 0x1e, 0xea, 0xd6, 0x38, + /*3240:*/ 0xba, 0x80, 0xf5, 0x2d, 0x29, 0x10, 0x53, 0x4f, 0xc7, 0x72, 0xc6, 0xab, 0xfd, 0xe5, 0x6b, 0x74, + /*3250:*/ 0x30, 0xe7, 0x86, 0x5c, 0x39, 0x6e, 0x9d, 0xf2, 0x06, 0xa6, 0xc1, 0x2d, 0x62, 0x5e, 0x6b, 0x08, + /*3260:*/ 0xf8, 0x05, 0xb8, 0xa0, 0xc3, 0x36, 0x92, 0x13, 0xcd, 0x55, 0x51, 0xca, 0x1c, 0xcf, 0xb4, 0x70, + /*3270:*/ 0x6d, 0xa4, 0x5d, 0x8c, 0xa4, 0x56, 0xe9, 0xd2, 0x79, 0xe1, 0xe4, 0xfa, 0x68, 0x91, 0xb9, 0x45, + /*3280:*/ 0x28, 0x3c, 0xf2, 0x2e, 0x40, 0xda, 0x1b, 0xc4, 0x0e, 0x22, 0x17, 0x7c, 0xd4, 0xc6, 0x74, 0xc9, + /*3290:*/ 0x13, 0x9c, 0xa5, 0x12, 0xa8, 0x7d, 0xa4, 0x68, 0xff, 0x17, 0xb0, 0xdd, 0xae, 0xcb, 0xb3, 0x95, + /*32a0:*/ 0x15, 0xec, 0x61, 0x2a, 0x40, 0x92, 0x0f, 0x44, 0xfb, 0x62, 0xd5, 0xf7, 0x75, 0x69, 0x0d, 0xa8, + /*32b0:*/ 0xb6, 0x99, 0x85, 0xac, 0x63, 0x9d, 0x7c, 0x50, 0xa5, 0xed, 0x27, 0x3d, 0xd8, 0x6e, 0x54, 0xb5, + /*32c0:*/ 0x43, 0x27, 0xab, 0x2d, 0x29, 0x4d, 0x2e, 0x10, 0xc9, 0xa4, 0x25, 0xa4, 0x5b, 0x43, 0xb0, 0x1a, + /*32d0:*/ 0x5c, 0xfd, 0x36, 0xc9, 0xfb, 0x04, 0x02, 0x9e, 0x13, 0x2b, 0xc8, 0xfa, 0xfa, 0x4d, 0x06, 0x1d, + /*32e0:*/ 0xdd, 0xb4, 0x02, 0x35, 0xac, 0x92, 0xb3, 0x9d, 0xd4, 0xb0, 0xea, 0xeb, 0x0b, 0xce, 0xbe, 0x02, + /*32f0:*/ 0xc1, 0x58, 0xc9, 0x3c, 0x04, 0x67, 0x48, 0x60, 0x5c, 0xe3, 0x0d, 0x86, 0xfc, 0x94, 0x1f, 0x87, + /*3300:*/ 0x20, 0xff, 0x0c, 0x15, 0x4f, 0x26, 0xc7, 0x71, 0xfd, 0x97, 0xff, 0xe9, 0xce, 0x84, 0x20, 0xcb, + /*3310:*/ 0xcf, 0x8f, 0x03, 0x17, 0x34, 0x50, 0xe5, 0xca, 0x30, 0xd2, 0x0c, 0x05, 0x2b, 0x61, 0x80, 0x9a, + /*3320:*/ 0x85, 0xa2, 0x3a, 0xa9, 0xfe, 0xf0, 0xda, 0xc4, 0xeb, 0xc7, 0x77, 0xc0, 0x03, 0x48, 0xaf, 0x40, + /*3330:*/ 0xab, 0xc0, 0xf6, 0xc6, 0xb7, 0x49, 0x02, 0x39, 0x6a, 0xfb, 0x17, 0x5e, 0x06, 0x3a, 0xad, 0x30, + /*3340:*/ 0x25, 0x7d, 0xbf, 0x48, 0xa9, 0x79, 0x0e, 0x7e, 0x2d, 0x2e, 0xa2, 0xa9, 0x66, 0xda, 0x55, 0x37, + /*3350:*/ 0x0e, 0x04, 0x76, 0x06, 0x84, 0x40, 0x10, 0x22, 0x23, 0xbf, 0xe7, 0xef, 0xd4, 0xc8, 0x95, 0x30, + /*3360:*/ 0x88, 0x4a, 0xbf, 0x09, 0x69, 0x9a, 0x05, 0xe6, 0xd1, 0x48, 0xea, 0x7b, 0x31, 0x4e, 0x47, 0x73, + /*3370:*/ 0x8d, 0xe4, 0x0a, 0x12, 0x7b, 0xb8, 0xfb, 0x48, 0x80, 0x5c, 0x1c, 0x35, 0xcc, 0x68, 0x93, 0x65, + /*3380:*/ 0x60, 0x3b, 0x3a, 0x6e, 0x3c, 0x99, 0x51, 0xbf, 0x27, 0x1f, 0x24, 0x5e, 0x40, 0xc2, 0xf0, 0x48, + /*3390:*/ 0x60, 0x3d, 0x5c, 0xc3, 0x4d, 0xb7, 0xdf, 0x10, 0x54, 0x62, 0x5e, 0x6e, 0xb9, 0xd2, 0x5a, 0x95, + /*33a0:*/ 0xfc, 0x10, 0xa8, 0xc2, 0xfc, 0x77, 0x3a, 0xea, 0x99, 0x12, 0x7c, 0xa6, 0xd7, 0x2b, 0xba, 0xd0, + /*33b0:*/ 0xa1, 0x31, 0x6d, 0xc2, 0x26, 0x7c, 0xc4, 0x03, 0x32, 0x27, 0x48, 0x6a, 0x80, 0x02, 0xa8, 0x58, + /*33c0:*/ 0x23, 0xba, 0xb1, 0x8c, 0x8e, 0x66, 0x83, 0x54, 0x6c, 0x96, 0xad, 0xfa, 0xe6, 0xaa, 0x98, 0x6a, + /*33d0:*/ 0xd9, 0x7e, 0x03, 0xf9, 0xe2, 0x54, 0xf1, 0x0a, 0x41, 0x19, 0x33, 0x7a, 0x13, 0x85, 0xfa, 0xd8, + /*33e0:*/ 0xa5, 0xbc, 0x55, 0x2e, 0xc2, 0x39, 0x7d, 0xbf, 0x82, 0xd4, 0x3d, 0x43, 0x6f, 0xf0, 0xc0, 0x8c, + /*33f0:*/ 0x30, 0xdc, 0x25, 0x0b, 0x20, 0x09, 0x13, 0x0e, 0x64, 0x62, 0x7e, 0xd5, 0xdd, 0xc3, 0x87, 0x95, + /*3400:*/ 0xe0, 0xae, 0x49, 0xf1, 0x8a, 0xb1, 0x89, 0x76, 0x94, 0x0e, 0xd3, 0x14, 0x8d, 0xfa, 0xb3, 0xf1, + /*3410:*/ 0x3f, 0x3a, 0xa9, 0x07, 0xf8, 0x6a, 0x81, 0x60, 0x73, 0x3b, 0x81, 0xd8, 0xbc, 0xf2, 0xf1, 0x62, + /*3420:*/ 0xcb, 0xa3, 0x60, 0xb5, 0x27, 0x06, 0x57, 0x91, 0x5b, 0xd3, 0xab, 0x95, 0xe9, 0x42, 0xce, 0x1a, + /*3430:*/ 0x80, 0xd8, 0x54, 0x8b, 0x12, 0x5e, 0x75, 0x31, 0xc6, 0x74, 0xe7, 0xfb, 0xe7, 0xa4, 0xf8, 0xbc, + /*3440:*/ 0xff, 0x8d, 0x3c, 0x9b, 0xcf, 0x3e, 0xc7, 0x3a, 0xd9, 0x8f, 0x85, 0xc9, 0x17, 0xe6, 0x43, 0x04, + /*3450:*/ 0xa2, 0xa6, 0xba, 0x06, 0x6f, 0xa1, 0x0a, 0x1a, 0x61, 0xc3, 0x4c, 0x2c, 0x9d, 0x0f, 0xcc, 0xf6, + /*3460:*/ 0x74, 0x2e, 0x12, 0xc7, 0xa4, 0x79, 0x27, 0xd8, 0x75, 0x92, 0xab, 0x1e, 0x18, 0xd5, 0xb5, 0xc8, + /*3470:*/ 0xa7, 0x57, 0x58, 0x40, 0xcd, 0x3e, 0xb4, 0x1e, 0x99, 0xde, 0x5f, 0x97, 0x76, 0x83, 0xac, 0x61, + /*3480:*/ 0x41, 0xbd, 0xb6, 0x05, 0xf7, 0xec, 0x2a, 0x50, 0xb3, 0x03, 0xca, 0x2d, 0x0f, 0xf1, 0x2a, 0xc7, + /*3490:*/ 0x87, 0x41, 0xcd, 0xfc, 0x19, 0x0a, 0x7e, 0xf6, 0x14, 0x06, 0xfd, 0x03, 0x6e, 0xdf, 0xcf, 0x12, + /*34a0:*/ 0x9a, 0xa9, 0xe6, 0xe7, 0xb8, 0x30, 0x5a, 0xfb, 0xe7, 0xe4, 0xe0, 0x66, 0x26, 0x8a, 0x32, 0x68, + /*34b0:*/ 0x59, 0x2b, 0xca, 0x10, 0x59, 0x71, 0x23, 0x07, 0xb6, 0xb6, 0xc4, 0x55, 0xdb, 0xd7, 0xe9, 0xc1, + /*34c0:*/ 0x6d, 0x21, 0xf3, 0x12, 0x68, 0x7d, 0x4d, 0x58, 0x15, 0xd4, 0xc0, 0x03, 0x89, 0x62, 0x33, 0x4a, + /*34d0:*/ 0x34, 0x9e, 0xc3, 0x93, 0xda, 0xd8, 0xe8, 0x42, 0x4e, 0x8a, 0x2a, 0xc3, 0x4c, 0x5e, 0xd1, 0x84, + /*34e0:*/ 0x7e, 0xfb, 0x57, 0x11, 0x8a, 0xda, 0xdf, 0x37, 0x67, 0xdd, 0xbc, 0x67, 0x67, 0x23, 0xaf, 0xe6, + /*34f0:*/ 0x1c, 0xaf, 0x65, 0xf6, 0x9f, 0x93, 0x64, 0x5c, 0x97, 0xe2, 0x23, 0xbb, 0xcf, 0xb7, 0x37, 0x6c, + /*3500:*/ 0xfa, 0xc6, 0x26, 0xb6, 0x00, 0xc0, 0xf1, 0x3a, 0x99, 0x2a, 0x2b, 0x75, 0xb9, 0x59, 0xf8, 0xaa, + /*3510:*/ 0x9a, 0x93, 0x1a, 0x91, 0x49, 0x58, 0x1f, 0x4a, 0xf2, 0xe2, 0x17, 0x6d, 0xd7, 0x8a, 0xba, 0xa8, + /*3520:*/ 0x74, 0xe5, 0xa9, 0x95, 0xb8, 0xc9, 0x5e, 0x04, 0x2c, 0x23, 0x04, 0xa2, 0x43, 0x1b, 0x78, 0x8f, + /*3530:*/ 0x8d, 0x82, 0xd7, 0x3f, 0x5a, 0x2b, 0x8c, 0x8e, 0xd9, 0x59, 0x54, 0xf1, 0x02, 0x6d, 0x5e, 0x74, + /*3540:*/ 0xf7, 0xf5, 0xb2, 0x08, 0xce, 0x35, 0x71, 0x96, 0x83, 0xc9, 0x1f, 0xb3, 0x47, 0xdf, 0x5a, 0x10, + /*3550:*/ 0x95, 0x2b, 0x1f, 0xf4, 0x6b, 0x96, 0xc0, 0x72, 0x16, 0x8a, 0x98, 0xf1, 0x4a, 0x75, 0x6c, 0x7e, + /*3560:*/ 0xff, 0x07, 0xe3, 0x60, 0xa1, 0xcc, 0xe2, 0xd0, 0xbc, 0xe2, 0x61, 0xa9, 0x14, 0x9c, 0xea, 0xa9, + /*3570:*/ 0x8d, 0x0f, 0xe4, 0x3e, 0x2d, 0xee, 0x77, 0x13, 0x89, 0xa7, 0x5f, 0x6c, 0x3b, 0x2b, 0xc3, 0xeb, + /*3580:*/ 0x6c, 0x89, 0xd9, 0x55, 0xbc, 0xe8, 0xe6, 0x1a, 0xf9, 0xcf, 0xa8, 0x7a, 0x59, 0xd4, 0x5c, 0x3b, + /*3590:*/ 0x03, 0x34, 0x17, 0xe3, 0xaf, 0x69, 0x16, 0x75, 0xb1, 0x03, 0x6f, 0x40, 0xb2, 0xf5, 0x88, 0x36, + /*35a0:*/ 0x3e, 0x1e, 0x0e, 0x75, 0xfd, 0x8c, 0x40, 0x5d, 0x07, 0x7f, 0xc0, 0x63, 0x45, 0xa2, 0x86, 0x52, + /*35b0:*/ 0xbb, 0x20, 0xab, 0x78, 0xb2, 0x73, 0x44, 0xfd, 0xac, 0xca, 0xa7, 0x93, 0x46, 0x44, 0xc0, 0x20, + /*35c0:*/ 0x44, 0x8c, 0xc4, 0xb5, 0x15, 0xed, 0x52, 0xf1, 0x67, 0x35, 0x35, 0xb0, 0x4d, 0xd5, 0x4c, 0xb0, + /*35d0:*/ 0x31, 0x6f, 0xfe, 0x67, 0x38, 0x17, 0x97, 0xab, 0xce, 0x8f, 0xb0, 0xc1, 0x9d, 0x84, 0x1d, 0xef, + /*35e0:*/ 0x19, 0x4b, 0x4f, 0x09, 0xf9, 0x5d, 0xea, 0x98, 0xf6, 0xcf, 0xf3, 0x76, 0x41, 0x94, 0x32, 0xa6, + /*35f0:*/ 0x9f, 0xb4, 0x20, 0xed, 0xda, 0xdb, 0x9e, 0x89, 0xa3, 0xaf, 0x62, 0x0a, 0x76, 0xae, 0x78, 0x84, + /*3600:*/ 0xa3, 0xda, 0x48, 0xaa, 0x16, 0xd5, 0x50, 0x27, 0xcb, 0x8d, 0xd0, 0x7e, 0x3b, 0x4e, 0x7f, 0x92, + /*3610:*/ 0x68, 0x58, 0xc0, 0xec, 0x95, 0xc0, 0x37, 0x17, 0x38, 0x09, 0xfa, 0xd8, 0x87, 0xf0, 0xd7, 0xe9, + /*3620:*/ 0xcf, 0x2d, 0x74, 0x29, 0xb8, 0x07, 0x8b, 0xb5, 0x09, 0xc6, 0x4f, 0xe7, 0x65, 0xe9, 0xc5, 0x8a, + /*3630:*/ 0xc1, 0xee, 0xa8, 0xbf, 0xa4, 0x3f, 0x25, 0x47, 0xee, 0x18, 0xca, 0x7d, 0x8f, 0xc8, 0xfa, 0xf9, + /*3640:*/ 0xb8, 0xab, 0x00, 0xa1, 0x72, 0xc3, 0x16, 0x35, 0x50, 0x2c, 0x8f, 0x1a, 0x63, 0xc6, 0x7f, 0x20, + /*3650:*/ 0x9b, 0x1a, 0xc1, 0xb5, 0xbd, 0xfb, 0xb5, 0x42, 0x95, 0xdf, 0x1c, 0xa5, 0x62, 0x89, 0x78, 0x2f, + /*3660:*/ 0xb3, 0xa6, 0x57, 0x0a, 0x1a, 0x67, 0xf9, 0xdc, 0x21, 0x27, 0xee, 0xe2, 0x7b, 0x00, 0xd6, 0x26, + /*3670:*/ 0x2b, 0x12, 0xce, 0x69, 0x8d, 0x57, 0x26, 0x14, 0x21, 0x24, 0x71, 0x1a, 0x67, 0x3e, 0x8a, 0xa1, + /*3680:*/ 0xa2, 0xb1, 0x3a, 0x08, 0xaa, 0xcf, 0x32, 0xfc, 0xc7, 0x95, 0x42, 0xdb, 0x72, 0x26, 0x34, 0xe2, + /*3690:*/ 0x8d, 0x44, 0x5e, 0x02, 0xd3, 0x89, 0x08, 0x9c, 0x61, 0x54, 0xeb, 0x2b, 0x4e, 0xa6, 0x5d, 0x3e, + /*36a0:*/ 0x69, 0x0b, 0xd2, 0xfb, 0x00, 0xdd, 0xa7, 0x24, 0x44, 0x89, 0x68, 0x14, 0xcb, 0x2c, 0xbb, 0xf7, + /*36b0:*/ 0x8b, 0xef, 0xe9, 0x24, 0xb6, 0x60, 0x3b, 0x9d, 0xdf, 0xfb, 0x0c, 0x6f, 0xb1, 0xf1, 0x09, 0x7c, + /*36c0:*/ 0xa2, 0x53, 0xfc, 0x44, 0x89, 0x43, 0x93, 0x0f, 0xe3, 0x34, 0x39, 0xaa, 0x70, 0x6f, 0x28, 0x5a, + /*36d0:*/ 0x1c, 0x58, 0x68, 0xb3, 0xe2, 0xee, 0xf6, 0xb8, 0x43, 0x54, 0xb8, 0xdf, 0x9a, 0xed, 0x38, 0xf0, + /*36e0:*/ 0xd5, 0xfe, 0x11, 0xc5, 0x46, 0x98, 0x99, 0x25, 0x29, 0xa6, 0xbb, 0x03, 0x5e, 0x5f, 0x7b, 0xfe, + /*36f0:*/ 0xce, 0x22, 0x24, 0xb3, 0x6f, 0x77, 0xab, 0x90, 0x02, 0xe4, 0x0c, 0x5c, 0x6e, 0x6e, 0x86, 0x3a, + /*3700:*/ 0x0e, 0xbf, 0x93, 0x9a, 0x78, 0xba, 0xa3, 0x55, 0xfd, 0xbc, 0x0e, 0xde, 0x99, 0xc3, 0x6b, 0x6d, + /*3710:*/ 0x87, 0x90, 0x93, 0x10, 0xb4, 0x7e, 0xce, 0x84, 0x98, 0xed, 0x01, 0x7e, 0x8d, 0x8c, 0x48, 0x06, + /*3720:*/ 0xbb, 0x58, 0xce, 0xd3, 0x6d, 0x41, 0x3b, 0x41, 0x13, 0x84, 0x68, 0x33, 0xf2, 0xb3, 0xba, 0x05, + /*3730:*/ 0x41, 0x55, 0xdf, 0x13, 0x1a, 0xb8, 0x86, 0x20, 0x5a, 0xbb, 0x7a, 0x36, 0x3b, 0x77, 0x1a, 0xe8, + /*3740:*/ 0x46, 0x31, 0x27, 0x0d, 0xb8, 0x7a, 0x19, 0x2c, 0x4d, 0xd1, 0xfb, 0xc3, 0xda, 0x2b, 0x0d, 0x97, + /*3750:*/ 0x04, 0xef, 0xf7, 0x54, 0xf3, 0xc4, 0xa6, 0x32, 0xb9, 0xce, 0xca, 0xd8, 0x88, 0x63, 0x0c, 0x5c, + /*3760:*/ 0xa7, 0xe6, 0xe1, 0xa7, 0xc4, 0xdc, 0xb1, 0x6e, 0xb7, 0xd3, 0x82, 0x69, 0xca, 0xa0, 0x57, 0x5d, + /*3770:*/ 0xfd, 0x41, 0x58, 0x8d, 0xe0, 0x8c, 0x51, 0x81, 0xc4, 0xa1, 0x52, 0xa9, 0x6d, 0x86, 0x06, 0x43, + /*3780:*/ 0x07, 0x07, 0xcb, 0xb8, 0xd7, 0xdb, 0x65, 0xb3, 0xc9, 0xe8, 0x43, 0x0f, 0xe2, 0x3d, 0xde, 0x30, + /*3790:*/ 0x66, 0xca, 0x30, 0x25, 0xba, 0x71, 0x9e, 0x12, 0x73, 0x40, 0xf2, 0xd6, 0xff, 0xa7, 0x51, 0x72, + /*37a0:*/ 0x44, 0x7e, 0xd5, 0xba, 0xa8, 0x89, 0x4a, 0xf8, 0x30, 0x1e, 0xe9, 0x3c, 0xab, 0x16, 0xc9, 0x51, + /*37b0:*/ 0x3c, 0xef, 0xfe, 0x6f, 0x8f, 0x04, 0x47, 0xbc, 0xce, 0x7d, 0x27, 0x61, 0x28, 0xd8, 0x47, 0x9f, + /*37c0:*/ 0x1c, 0x89, 0x6c, 0x25, 0xc9, 0x61, 0x8d, 0x47, 0x63, 0xb3, 0x6f, 0xbc, 0xb9, 0x44, 0x8e, 0x50, + /*37d0:*/ 0x60, 0x5a, 0xa3, 0x26, 0x5d, 0xb8, 0x3c, 0xf9, 0xef, 0x8f, 0xfc, 0xdb, 0xd6, 0x62, 0x87, 0xd2, + /*37e0:*/ 0xfd, 0x95, 0xbd, 0x61, 0x2b, 0xcc, 0xef, 0xf7, 0x74, 0x96, 0x30, 0x10, 0x48, 0x0f, 0x84, 0xaf, + /*37f0:*/ 0x0c, 0x5d, 0x8f, 0xb8, 0x4e, 0x08, 0x60, 0xf5, 0x84, 0x1b, 0xa7, 0x02, 0x58, 0xc4, 0x1c, 0x6e, + /*3800:*/ 0xd2, 0x6d, 0xe1, 0x70, 0x4f, 0x57, 0x67, 0xfe, 0xbb, 0x59, 0x03, 0xac, 0x98, 0xa6, 0x88, 0xc4, + /*3810:*/ 0x93, 0x4c, 0x53, 0x55, 0xbe, 0xc0, 0x97, 0x09, 0x61, 0x05, 0x11, 0x9e, 0x43, 0x9b, 0x03, 0x56, + /*3820:*/ 0x77, 0x89, 0xcb, 0x32, 0x15, 0xe9, 0x0b, 0xa8, 0xe7, 0x00, 0x66, 0xbf, 0xf9, 0xbf, 0x9f, 0x77, + /*3830:*/ 0xde, 0xf2, 0x50, 0x0d, 0x88, 0xb8, 0x4d, 0x16, 0x42, 0x0b, 0xaf, 0xda, 0xe2, 0x9c, 0x29, 0xf8, + /*3840:*/ 0xc5, 0x2b, 0xf6, 0xfc, 0x89, 0xf0, 0x0c, 0x2e, 0xf7, 0xb8, 0xb9, 0x60, 0x31, 0x5d, 0x7a, 0x8a, + /*3850:*/ 0x7f, 0xdf, 0xf2, 0xa6, 0xd6, 0x39, 0x4f, 0x20, 0xaf, 0x07, 0xc9, 0x9c, 0xd0, 0x8f, 0x21, 0x2c, + /*3860:*/ 0xae, 0x78, 0x1a, 0x00, 0xad, 0x52, 0x07, 0x2c, 0xbd, 0x99, 0x8e, 0x43, 0x68, 0xa0, 0x47, 0xf6, + /*3870:*/ 0xf9, 0xb7, 0xe1, 0x42, 0x53, 0x37, 0x8c, 0x5d, 0xcc, 0x5e, 0x7c, 0x70, 0x89, 0x0c, 0xeb, 0x66, + /*3880:*/ 0x5c, 0x5f, 0x96, 0xf1, 0x29, 0xa9, 0x49, 0x68, 0xb2, 0x9f, 0x5c, 0x49, 0x85, 0xb9, 0x47, 0x4c, + /*3890:*/ 0xb9, 0x40, 0x42, 0x29, 0x98, 0x2e, 0xbc, 0xd1, 0xde, 0xd1, 0xe4, 0x67, 0x66, 0x98, 0x7c, 0x6a, + /*38a0:*/ 0x60, 0x00, 0xd2, 0xd0, 0x3f, 0xcb, 0xc0, 0xde, 0x18, 0x95, 0xb9, 0xd7, 0xbc, 0x2c, 0x39, 0xc7, + /*38b0:*/ 0x90, 0x59, 0x88, 0xa9, 0x17, 0xcd, 0x81, 0x28, 0x09, 0x97, 0xe0, 0x34, 0x7a, 0x6a, 0xcb, 0x0c, + /*38c0:*/ 0x8a, 0x9c, 0xf2, 0x9d, 0xa6, 0xce, 0xdd, 0x09, 0x13, 0x4e, 0x0f, 0x51, 0xfc, 0xa0, 0x11, 0xf5, + /*38d0:*/ 0x74, 0xd2, 0x3e, 0xcb, 0x93, 0xca, 0x60, 0x48, 0x00, 0xb6, 0xd9, 0xa6, 0x7b, 0x14, 0x26, 0x8f, + /*38e0:*/ 0x75, 0x77, 0x74, 0x55, 0xd6, 0x29, 0x6f, 0x6f, 0x4d, 0xac, 0x4c, 0x7b, 0xba, 0x9c, 0xb5, 0x88, + /*38f0:*/ 0x0f, 0x7c, 0x45, 0x74, 0x26, 0xe2, 0x2e, 0xd4, 0x45, 0x79, 0x29, 0x07, 0xd6, 0x58, 0x7d, 0x8c, + /*3900:*/ 0x93, 0x61, 0x8d, 0x96, 0xef, 0xc2, 0xc5, 0xa5, 0xf6, 0xab, 0xa1, 0x20, 0x44, 0x61, 0xd7, 0x60, + /*3910:*/ 0x62, 0x79, 0xa7, 0x7a, 0xeb, 0x8f, 0xd9, 0x96, 0xce, 0xf9, 0xb1, 0xb0, 0xe7, 0xfe, 0xe0, 0x69, + /*3920:*/ 0x2b, 0xbd, 0xfd, 0xb2, 0x25, 0x6b, 0x8b, 0x11, 0x8b, 0x59, 0x92, 0xfa, 0xcd, 0x6c, 0xd0, 0x90, + /*3930:*/ 0xb4, 0xde, 0x70, 0x32, 0xa9, 0x4d, 0x08, 0x92, 0x47, 0x0c, 0x7a, 0xb6, 0x00, 0xe2, 0x1c, 0x71, + /*3940:*/ 0xa0, 0x39, 0x1c, 0xcb, 0x96, 0xc2, 0xda, 0x70, 0x50, 0x29, 0x35, 0x3e, 0x28, 0xf6, 0x86, 0xbb, + /*3950:*/ 0xb2, 0x8a, 0xba, 0x93, 0xf9, 0x42, 0xf4, 0xc9, 0xa8, 0x54, 0x03, 0xd3, 0xb4, 0xc4, 0x40, 0xbf, + /*3960:*/ 0x72, 0x1f, 0x86, 0xfe, 0x32, 0xc3, 0x44, 0x80, 0x9c, 0x77, 0x7b, 0x30, 0xb2, 0xeb, 0x44, 0x2c, + /*3970:*/ 0xee, 0x15, 0x00, 0x16, 0x1b, 0x57, 0xfe, 0x22, 0x9f, 0x4a, 0x7e, 0x40, 0xe8, 0xd3, 0xb1, 0x12, + /*3980:*/ 0xe2, 0x78, 0x36, 0x94, 0x61, 0x9e, 0x46, 0x37, 0x5b, 0x17, 0x0a, 0x58, 0xd5, 0x40, 0x25, 0x52, + /*3990:*/ 0x08, 0xc6, 0x42, 0x50, 0xb7, 0x4d, 0x76, 0xe4, 0x05, 0xb7, 0x3f, 0x83, 0x0b, 0xab, 0x32, 0x1a, + /*39a0:*/ 0x66, 0xcc, 0x14, 0xc5, 0x98, 0xb6, 0x37, 0x7d, 0x44, 0xbd, 0xb0, 0x38, 0x29, 0x17, 0xe0, 0xa7, + /*39b0:*/ 0x27, 0x2f, 0x66, 0x88, 0x8a, 0x45, 0x53, 0xda, 0x57, 0x9d, 0xcc, 0xca, 0x25, 0x83, 0xe8, 0x18, + /*39c0:*/ 0x6e, 0x8a, 0x22, 0x0a, 0x35, 0x49, 0x78, 0x85, 0x05, 0xe1, 0xec, 0x02, 0x62, 0x3e, 0xad, 0x6b, + /*39d0:*/ 0x71, 0x95, 0xf7, 0xd7, 0x29, 0xea, 0x21, 0xc4, 0x63, 0x5f, 0x68, 0x9f, 0x10, 0x9d, 0x31, 0x39, + /*39e0:*/ 0x92, 0xc9, 0x79, 0x66, 0x9b, 0xb4, 0xe0, 0x53, 0xb4, 0x2b, 0xd8, 0xe8, 0xea, 0x4f, 0x47, 0x88, + /*39f0:*/ 0xaa, 0xb1, 0x7f, 0x5d, 0xd0, 0x16, 0x80, 0xa9, 0x24, 0xd5, 0x51, 0x68, 0x58, 0xff, 0x5b, 0x35, + /*3a00:*/ 0x11, 0x32, 0x0d, 0x3d, 0xb9, 0xa5, 0x3b, 0xb8, 0x5c, 0x19, 0xc1, 0xe7, 0x04, 0xcb, 0x7c, 0xc2, + /*3a10:*/ 0x01, 0x87, 0xea, 0xf3, 0x5a, 0x55, 0xb9, 0x31, 0x27, 0x95, 0xae, 0x6e, 0x68, 0x1a, 0x64, 0xda, + /*3a20:*/ 0x78, 0x65, 0x56, 0x67, 0x61, 0x03, 0xb9, 0xfb, 0x99, 0x0c, 0xa9, 0xa6, 0x72, 0x88, 0x89, 0x3f, + /*3a30:*/ 0xd1, 0x3e, 0xe3, 0xb1, 0x93, 0x09, 0xce, 0x0e, 0x0b, 0x7c, 0x08, 0xa5, 0x82, 0x4e, 0x2a, 0x52, + /*3a40:*/ 0x99, 0x0d, 0xee, 0x35, 0x28, 0xff, 0xe2, 0x17, 0x65, 0xfb, 0xb4, 0x59, 0x05, 0x86, 0xf2, 0x0a, + /*3a50:*/ 0xff, 0xb4, 0x4c, 0xe0, 0x0e, 0x9b, 0xd6, 0x86, 0xb3, 0xb3, 0x6f, 0x22, 0x35, 0x0c, 0x77, 0x3a, + /*3a60:*/ 0xd5, 0x42, 0x5b, 0x1a, 0xc6, 0x45, 0xb4, 0x16, 0x4e, 0x7b, 0x22, 0xbb, 0xb3, 0xe2, 0x18, 0x8f, + /*3a70:*/ 0xf0, 0x13, 0xc4, 0xaf, 0x03, 0x7f, 0xbe, 0x0f, 0x43, 0x5f, 0x83, 0xd3, 0x57, 0xbf, 0xc0, 0x6b, + /*3a80:*/ 0xb3, 0xea, 0x7f, 0x39, 0xa1, 0xf6, 0xb2, 0x67, 0xeb, 0xa0, 0x6a, 0x1f, 0xc8, 0x0b, 0x33, 0x06, + /*3a90:*/ 0x5b, 0x69, 0x67, 0x82, 0x39, 0x27, 0x38, 0xa5, 0x14, 0xa2, 0x68, 0xbc, 0xe8, 0x52, 0xf7, 0xcb, + /*3aa0:*/ 0x4c, 0xfd, 0xa3, 0x9a, 0x23, 0x9c, 0xa1, 0xd7, 0x3e, 0x1d, 0x3b, 0x6b, 0x6e, 0x1e, 0xbc, 0x8b, + /*3ab0:*/ 0xff, 0xc1, 0xa5, 0x3e, 0xa9, 0x5b, 0x7f, 0x86, 0xa6, 0x95, 0xf0, 0xcc, 0x3b, 0xeb, 0x76, 0x77, + /*3ac0:*/ 0x51, 0x51, 0x3e, 0xe6, 0x97, 0x38, 0x1e, 0xd1, 0x34, 0x20, 0xb2, 0xeb, 0x8a, 0x35, 0xc1, 0x5f, + /*3ad0:*/ 0x5e, 0xd9, 0x97, 0xab, 0x30, 0x95, 0xae, 0x5e, 0xb0, 0x62, 0xa3, 0x4c, 0x12, 0xf6, 0x0c, 0xd7, + /*3ae0:*/ 0x16, 0x92, 0x97, 0x27, 0xcb, 0xe7, 0x1e, 0xf1, 0x87, 0xc4, 0xd1, 0x09, 0xb9, 0xe6, 0xff, 0xb6, + /*3af0:*/ 0xab, 0xc7, 0x9c, 0x42, 0x55, 0xab, 0x1f, 0x6a, 0x85, 0x80, 0x6f, 0xc4, 0x3c, 0x16, 0x9b, 0x89, + /*3b00:*/ 0x9c, 0x42, 0xed, 0xd9, 0x97, 0xdc, 0x4f, 0xe2, 0x69, 0xdd, 0xab, 0xe7, 0x2c, 0x9a, 0xda, 0x91, + /*3b10:*/ 0x7c, 0x71, 0x63, 0x41, 0x48, 0xc0, 0x6f, 0x24, 0xd6, 0xaf, 0x6b, 0x30, 0xce, 0xc0, 0x86, 0xff, + /*3b20:*/ 0xa9, 0x26, 0x91, 0xd7, 0x42, 0xa0, 0x00, 0x4e, 0x39, 0xb0, 0x6c, 0xfc, 0xad, 0xd4, 0x22, 0xd0, + /*3b30:*/ 0x6d, 0xb6, 0xf1, 0xeb, 0xbd, 0x28, 0x72, 0x87, 0x15, 0xb5, 0x17, 0x76, 0x0a, 0x31, 0xc2, 0x2b, + /*3b40:*/ 0xc0, 0x5f, 0x4a, 0x52, 0xa0, 0xed, 0x9e, 0xe0, 0x7d, 0x7e, 0x6e, 0x0c, 0x12, 0x03, 0x27, 0x58, + /*3b50:*/ 0x28, 0x68, 0xb0, 0x6e, 0x19, 0xfb, 0xec, 0x50, 0x0e, 0xc8, 0xf9, 0x0b, 0xfb, 0xfd, 0xf4, 0x17, + /*3b60:*/ 0x79, 0xec, 0xaf, 0x1b, 0x79, 0x15, 0x23, 0x9a, 0x06, 0xcd, 0x60, 0xbc, 0x95, 0x5d, 0x8a, 0x76, + /*3b70:*/ 0x49, 0x3e, 0xa9, 0xd3, 0xcb, 0xed, 0x2f, 0x5f, 0xe0, 0xa7, 0xb8, 0xc7, 0x01, 0x60, 0x78, 0x0d, + /*3b80:*/ 0x33, 0x8b, 0xda, 0xb8, 0x04, 0x15, 0x00, 0x6a, 0xe6, 0x4e, 0x43, 0xb6, 0xd2, 0x0d, 0x81, 0x60, + /*3b90:*/ 0x74, 0x6c, 0x09, 0xdb, 0x05, 0xc3, 0xb4, 0xc3, 0x8f, 0xae, 0x23, 0xeb, 0xe0, 0x32, 0x73, 0x24, + /*3ba0:*/ 0xa9, 0xfa, 0xee, 0xc0, 0xfe, 0x44, 0x14, 0x41, 0xce, 0xe9, 0x31, 0x8a, 0x24, 0x8d, 0xd3, 0xa9, + /*3bb0:*/ 0x49, 0x0c, 0xe0, 0x6b, 0xb6, 0xd5, 0xf8, 0x5d, 0xe2, 0x5b, 0xac, 0xc8, 0x31, 0x5b, 0xb3, 0x25, + /*3bc0:*/ 0xe2, 0x3f, 0x51, 0x22, 0x38, 0x6c, 0x72, 0x68, 0xdd, 0xe9, 0x80, 0xb4, 0x39, 0xa3, 0xe0, 0xc1, + /*3bd0:*/ 0x3b, 0x02, 0x7d, 0x63, 0xbe, 0xb0, 0xb2, 0x80, 0x87, 0x6e, 0x55, 0x32, 0x4e, 0x12, 0x92, 0xee, + /*3be0:*/ 0xf0, 0xe1, 0x45, 0xf5, 0x1b, 0x1b, 0xa4, 0x56, 0xa6, 0x11, 0x92, 0xa1, 0x15, 0x56, 0x25, 0xb7, + /*3bf0:*/ 0x94, 0x8e, 0x04, 0x12, 0x1c, 0x4b, 0x9a, 0x87, 0x84, 0x70, 0x1e, 0xdb, 0x49, 0xeb, 0xd5, 0xfa, + /*3c00:*/ 0xa2, 0xb1, 0x11, 0xd2, 0x8c, 0x4f, 0x88, 0xed, 0xf9, 0x69, 0x08, 0x53, 0xff, 0x82, 0x79, 0x18, + /*3c10:*/ 0x2b, 0xf8, 0xa6, 0x87, 0xdd, 0x13, 0xa0, 0x7b, 0xfc, 0x51, 0x7d, 0xde, 0xac, 0xfc, 0x8b, 0xd4, + /*3c20:*/ 0x0e, 0xf5, 0x61, 0x7e, 0x0f, 0xa9, 0x96, 0xd2, 0xcf, 0x85, 0x2c, 0x4d, 0x9b, 0x12, 0xbe, 0xf9, + /*3c30:*/ 0x7c, 0x4f, 0x75, 0x68, 0x4d, 0x34, 0x98, 0xf8, 0x5f, 0xc4, 0xcf, 0x29, 0x87, 0x26, 0xec, 0x09, + /*3c40:*/ 0x64, 0xd0, 0x6e, 0x92, 0x13, 0xc4, 0x49, 0xc1, 0xb3, 0xe2, 0x2a, 0x70, 0x03, 0x28, 0x83, 0xde, + /*3c50:*/ 0x28, 0x33, 0x6a, 0x48, 0x9e, 0xf2, 0x8b, 0x9b, 0x52, 0xc3, 0xc3, 0x20, 0x8b, 0xc3, 0xdb, 0x74, + /*3c60:*/ 0x56, 0xb6, 0x7a, 0x2b, 0xe8, 0x7d, 0x2d, 0x54, 0x27, 0x8b, 0xa8, 0xa3, 0x52, 0x99, 0xcb, 0x9a, + /*3c70:*/ 0xbf, 0x32, 0xa7, 0xb4, 0x82, 0x51, 0x05, 0xad, 0xc2, 0x81, 0x7f, 0xaa, 0xfe, 0x87, 0x1e, 0xb4, + /*3c80:*/ 0x57, 0xb7, 0x63, 0x6a, 0x7d, 0x5d, 0x0f, 0x8c, 0x77, 0x16, 0x1f, 0x49, 0xa4, 0xba, 0x0f, 0x56, + /*3c90:*/ 0x1c, 0x73, 0x95, 0x42, 0x1e, 0x56, 0xc6, 0x11, 0x5a, 0x0d, 0x3d, 0x88, 0x23, 0xc8, 0xaa, 0x5d, + /*3ca0:*/ 0x60, 0x87, 0xce, 0xd0, 0xd0, 0xea, 0x43, 0xd4, 0x31, 0xbb, 0xb3, 0xd9, 0xbb, 0x5e, 0x56, 0x79, + /*3cb0:*/ 0x4e, 0x6c, 0x4a, 0x54, 0x1a, 0x96, 0x81, 0xe2, 0xdb, 0x47, 0xc4, 0x6d, 0xb3, 0xfa, 0xc0, 0x0e, + /*3cc0:*/ 0xdd, 0x3d, 0x12, 0xe3, 0x51, 0x66, 0x05, 0xe1, 0xe1, 0x8e, 0x3d, 0x0a, 0x7d, 0xb2, 0xe5, 0x7d, + /*3cd0:*/ 0x78, 0x10, 0xb9, 0x95, 0xf1, 0xdc, 0xa7, 0xcd, 0x3a, 0xcf, 0xf3, 0xe0, 0x11, 0x10, 0x6b, 0xc2, + /*3ce0:*/ 0xc0, 0x9b, 0x7e, 0xc1, 0x40, 0x7e, 0x57, 0xfa, 0xe8, 0x95, 0x42, 0x52, 0x32, 0xe2, 0x3f, 0xf0, + /*3cf0:*/ 0x74, 0x94, 0xd7, 0x2f, 0x47, 0xdc, 0xe0, 0x98, 0x09, 0xf1, 0x51, 0xca, 0x0f, 0x03, 0xfc, 0xf6, + /*3d00:*/ 0x89, 0xef, 0xa6, 0x49, 0x1b, 0x05, 0x1b, 0x3e, 0xbc, 0x3d, 0xde, 0x32, 0x4e, 0xff, 0xcb, 0x44, + /*3d10:*/ 0x86, 0xbf, 0xeb, 0x1f, 0xeb, 0x15, 0x37, 0xb9, 0xde, 0x68, 0xd0, 0x91, 0x37, 0xff, 0x9b, 0xf9, + /*3d20:*/ 0xcd, 0x62, 0xf8, 0x1a, 0xfb, 0x80, 0x60, 0x15, 0x76, 0x62, 0x01, 0x8c, 0x9e, 0xda, 0x93, 0xd9, + /*3d30:*/ 0x51, 0x5a, 0x87, 0xd4, 0xe0, 0x24, 0x67, 0xac, 0xa7, 0x72, 0x33, 0x54, 0xc0, 0x94, 0x15, 0x23, + /*3d40:*/ 0x10, 0xa3, 0x18, 0xde, 0x0d, 0x0f, 0xd9, 0xc1, 0x52, 0xad, 0x37, 0xd2, 0x6d, 0xf0, 0x57, 0x20, + /*3d50:*/ 0xe6, 0xaf, 0x21, 0xe5, 0xa5, 0x32, 0xd5, 0xfe, 0xca, 0x57, 0x50, 0x75, 0xd7, 0xb7, 0x20, 0xa2, + /*3d60:*/ 0x3c, 0xf0, 0xa2, 0xca, 0xce, 0x43, 0xe5, 0xe0, 0xaa, 0xb2, 0xf3, 0x5d, 0x12, 0x15, 0x46, 0x72, + /*3d70:*/ 0xfe, 0x99, 0x21, 0x2a, 0x43, 0x6f, 0x9f, 0x70, 0x42, 0x9d, 0xe9, 0xf7, 0x8e, 0xc7, 0x4a, 0xd9, + /*3d80:*/ 0x05, 0x09, 0xc6, 0xb5, 0x9f, 0x4b, 0x6f, 0xb9, 0x53, 0x4b, 0x4e, 0x3f, 0x01, 0x7b, 0x3e, 0x7c, + /*3d90:*/ 0x75, 0x61, 0x32, 0x46, 0xb9, 0x3d, 0xc6, 0xdf, 0x75, 0x05, 0x6a, 0xe5, 0x7e, 0xbf, 0x44, 0xdd, + /*3da0:*/ 0xc5, 0xca, 0xa8, 0x9a, 0x9b, 0x71, 0xf7, 0x98, 0xa3, 0xec, 0xee, 0x1c, 0xc9, 0x8d, 0x10, 0x11, + /*3db0:*/ 0xd6, 0x3b, 0xda, 0x3c, 0x35, 0x89, 0x3d, 0x8d, 0x9a, 0xcc, 0x43, 0x17, 0x1e, 0x32, 0x05, 0x23, + /*3dc0:*/ 0x70, 0xa4, 0x26, 0x69, 0xc1, 0x8a, 0x83, 0x7a, 0xdf, 0x9d, 0x1a, 0x3b, 0xcc, 0x22, 0x52, 0x76, + /*3dd0:*/ 0xe5, 0x7e, 0xc3, 0x63, 0xf8, 0xd1, 0xc1, 0x3a, 0x8e, 0x88, 0x64, 0x80, 0x50, 0x5f, 0xa0, 0x8d, + /*3de0:*/ 0x16, 0x89, 0x88, 0x57, 0x21, 0x38, 0xc1, 0x76, 0x19, 0xc5, 0x5b, 0x90, 0x92, 0xd3, 0x45, 0xf5, + /*3df0:*/ 0xf4, 0x79, 0x35, 0xf5, 0x1a, 0x2d, 0x53, 0xe1, 0x7c, 0x23, 0x3a, 0x52, 0x6f, 0x4c, 0x44, 0x87, + /*3e00:*/ 0x99, 0x71, 0xf7, 0x13, 0x5b, 0x4f, 0x50, 0x15, 0x06, 0x10, 0x32, 0xc4, 0xb7, 0x81, 0xd7, 0x73, + /*3e10:*/ 0xeb, 0x20, 0x8b, 0x92, 0x62, 0xd1, 0x37, 0xe7, 0x6b, 0xe8, 0x8c, 0x5b, 0xe3, 0x27, 0x13, 0x07, + /*3e20:*/ 0x39, 0xdc, 0x1b, 0xa7, 0x67, 0x40, 0x8b, 0x44, 0x83, 0xff, 0x47, 0x1a, 0xfa, 0x0d, 0x27, 0x98, + /*3e30:*/ 0x4c, 0xc9, 0xe4, 0x76, 0x9f, 0x4f, 0xc3, 0xf7, 0x3a, 0x51, 0x54, 0x84, 0x75, 0x21, 0x6b, 0xb8, + /*3e40:*/ 0x3f, 0x01, 0x54, 0x46, 0x7f, 0x0d, 0x0d, 0x26, 0x4a, 0x6a, 0x92, 0xe1, 0x8a, 0x3a, 0x22, 0x9f, + /*3e50:*/ 0x01, 0x00, 0x55, 0x3a, 0x16, 0x2a, 0xc5, 0xad, 0x3a, 0xb1, 0x76, 0xd5, 0x13, 0xf2, 0x6a, 0xd4, + /*3e60:*/ 0x7f, 0x50, 0xca, 0x75, 0x20, 0x77, 0xd0, 0xbf, 0x34, 0x7e, 0x22, 0xd7, 0x9a, 0xaf, 0xcb, 0x0b, + /*3e70:*/ 0x07, 0x67, 0x77, 0xb9, 0xa5, 0xaf, 0x86, 0x42, 0x3f, 0xc1, 0x4b, 0x17, 0xc1, 0x0c, 0xe7, 0x4e, + /*3e80:*/ 0xab, 0x11, 0xe3, 0xbd, 0x21, 0x30, 0xe3, 0x58, 0x0f, 0xbe, 0xeb, 0xaa, 0xe0, 0x0c, 0x25, 0xfd, + /*3e90:*/ 0x8f, 0xc2, 0x67, 0x5b, 0xbf, 0x62, 0xe8, 0x5b, 0x0a, 0x08, 0xd5, 0xee, 0xf4, 0x0a, 0x90, 0x58, + /*3ea0:*/ 0xf6, 0x6d, 0x0e, 0x17, 0x3f, 0x7b, 0x63, 0x52, 0x9b, 0x1e, 0xd5, 0x57, 0x44, 0xc9, 0x2f, 0x36, + /*3eb0:*/ 0xd0, 0x82, 0x95, 0x9a, 0xf8, 0xe7, 0x52, 0x3b, 0xda, 0x91, 0xf1, 0xd4, 0x33, 0xb6, 0xca, 0x5b, + /*3ec0:*/ 0xf5, 0x86, 0x72, 0x9f, 0x5a, 0x75, 0xaf, 0xde, 0xcc, 0xc2, 0x86, 0x7f, 0x36, 0xcc, 0x0f, 0x90, + /*3ed0:*/ 0x69, 0x7b, 0x7b, 0xa4, 0xdf, 0xf3, 0x65, 0x6d, 0xb2, 0xd5, 0xd0, 0x47, 0x27, 0x80, 0x03, 0x86, + /*3ee0:*/ 0x0c, 0x5a, 0x6b, 0x53, 0x62, 0x54, 0x87, 0xe3, 0xd7, 0x19, 0xdb, 0x6d, 0xb8, 0x4f, 0x7c, 0x32, + /*3ef0:*/ 0xd1, 0xd6, 0xe1, 0x1e, 0xa0, 0x02, 0x28, 0xed, 0x7e, 0xe0, 0x11, 0x8c, 0x94, 0x64, 0xa8, 0xee, + /*3f00:*/ 0x25, 0x81, 0x1d, 0x38, 0xa7, 0x2d, 0x65, 0xdc, 0x64, 0x2e, 0x61, 0xb5, 0x1e, 0xc7, 0x50, 0x20, + /*3f10:*/ 0x2a, 0x20, 0x28, 0x65, 0xba, 0x5a, 0xb3, 0x31, 0x10, 0x07, 0x4f, 0xb0, 0x74, 0x53, 0xd2, 0xb3, + /*3f20:*/ 0xf3, 0xbe, 0x5a, 0x5c, 0x0b, 0xcc, 0x31, 0x8e, 0xfe, 0x0f, 0xd2, 0x27, 0x1f, 0x4e, 0x76, 0xd0, + /*3f30:*/ 0x6a, 0xf6, 0x23, 0x19, 0x2e, 0xc7, 0x79, 0xcf, 0x27, 0xe6, 0xb9, 0x64, 0xa0, 0x46, 0x30, 0xf9, + /*3f40:*/ 0x7a, 0x7e, 0x42, 0x98, 0x68, 0x20, 0x56, 0x59, 0xe5, 0xf2, 0x32, 0x9e, 0x24, 0xf3, 0x39, 0xcb, + /*3f50:*/ 0x8d, 0x1c, 0x40, 0xc8, 0x56, 0x5d, 0x61, 0x03, 0xbc, 0x9f, 0x9b, 0x1c, 0xe6, 0x6d, 0xa2, 0xee, + /*3f60:*/ 0xf1, 0x33, 0x5a, 0xe7, 0x7e, 0xf7, 0x9c, 0xd4, 0x9c, 0xd9, 0x20, 0xce, 0x9f, 0x80, 0x18, 0x8a, + /*3f70:*/ 0xaa, 0xe7, 0x44, 0x87, 0xd7, 0x23, 0xc6, 0x9c, 0x9c, 0x5d, 0x0c, 0xc0, 0xc9, 0x6f, 0x7b, 0x3d, + /*3f80:*/ 0x49, 0xa7, 0x2d, 0x88, 0x0b, 0xf3, 0x23, 0xec, 0x42, 0xfd, 0xc7, 0x61, 0x0d, 0xa2, 0xed, 0xac, + /*3f90:*/ 0x13, 0x07, 0xe5, 0xd6, 0x77, 0x55, 0x48, 0xa1, 0x34, 0xbb, 0xe2, 0x77, 0x30, 0xc0, 0x15, 0x19, + /*3fa0:*/ 0xfd, 0xdf, 0xd2, 0x39, 0x60, 0xc6, 0x98, 0x0e, 0x82, 0xfd, 0xe1, 0xef, 0x34, 0xf0, 0x83, 0x8c, + /*3fb0:*/ 0x9e, 0x2b, 0x1b, 0xdf, 0xf5, 0xfc, 0x42, 0x78, 0x43, 0xa1, 0x6d, 0xa4, 0x0a, 0x65, 0xae, 0xfe, + /*3fc0:*/ 0xf6, 0xdb, 0xfb, 0x02, 0x9d, 0x53, 0x15, 0xcf, 0x9d, 0x65, 0x1b, 0x9e, 0xfb, 0x20, 0x50, 0xe4, + /*3fd0:*/ 0xe3, 0xf0, 0x5d, 0xc8, 0x68, 0xb8, 0xd8, 0xa3, 0xe3, 0xff, 0xc5, 0xc1, 0x8c, 0xab, 0xcc, 0x8d, + /*3fe0:*/ 0xa1, 0x7a, 0x17, 0xe5, 0xdc, 0xb1, 0xf1, 0xea, 0x0c, 0x47, 0x0e, 0x22, 0xe2, 0x2e, 0x45, 0x3a, + /*3ff0:*/ 0x36, 0x66, 0xbb, 0x39, 0x38, 0xbd, 0x44, 0x1a, 0x53, 0xce, 0xd9, 0x41, 0x2c, 0x01, 0x2b, 0x49, + /*4000:*/ 0x81, 0x18, 0x05, 0x96, 0x4d, 0xd8, 0xd2, 0x38, 0xab, 0xef, 0xf9, 0x44, 0xc0, 0x12, 0xfe, 0xa3, + /*4010:*/ 0x16, 0xdf, 0x1f, 0xe8, 0xcd, 0x87, 0xb2, 0x00, 0x76, 0xcb, 0xa3, 0x14, 0xfa, 0x4c, 0x3b, 0x22, + /*4020:*/ 0xd8, 0x5b, 0x2e, 0xe3, 0x06, 0xee, 0x77, 0xd1, 0x3f, 0xbb, 0x22, 0x9a, 0xd5, 0x10, 0x09, 0xc0, + /*4030:*/ 0x91, 0xd7, 0x81, 0x8d, 0x95, 0x6c, 0x57, 0x72, 0xf3, 0x67, 0xa6, 0xc8, 0x29, 0xc5, 0xd1, 0x85, + /*4040:*/ 0xac, 0x37, 0x1e, 0x5b, 0x7b, 0x5f, 0x69, 0x35, 0x39, 0xce, 0x5d, 0xea, 0x6a, 0x3b, 0x4c, 0xa7, + /*4050:*/ 0x12, 0x3a, 0x68, 0xa8, 0xc9, 0x72, 0xc3, 0x1b, 0x98, 0xdb, 0x61, 0xd4, 0xc4, 0xf9, 0x8f, 0x8b, + /*4060:*/ 0xd9, 0x29, 0xf4, 0x89, 0xcb, 0x3b, 0x28, 0x62, 0x0a, 0x9c, 0x2d, 0x9e, 0xc1, 0xab, 0xe6, 0xb5, + /*4070:*/ 0x7e, 0x66, 0x51, 0xc7, 0x9c, 0x6f, 0xa8, 0xd4, 0x5d, 0xa5, 0x22, 0xed, 0x30, 0x26, 0xb6, 0x2b, + /*4080:*/ 0x85, 0x6d, 0x76, 0xc6, 0x86, 0x0e, 0xef, 0xe2, 0x1e, 0x9a, 0xaa, 0xf9, 0xae, 0xed, 0x02, 0x26, + /*4090:*/ 0x68, 0x0b, 0x15, 0xf9, 0x45, 0xf8, 0xb7, 0xcb, 0xfc, 0xff, 0xf2, 0x3e, 0xc9, 0x5a, 0x35, 0x14, + /*40a0:*/ 0x6b, 0x67, 0x69, 0xe9, 0x03, 0x12, 0xf4, 0xfb, 0x46, 0xa7, 0x9c, 0xc8, 0x43, 0x03, 0x08, 0xea, + /*40b0:*/ 0xf8, 0x5b, 0xdb, 0x29, 0xad, 0x73, 0x8c, 0x19, 0x18, 0x70, 0x47, 0xd7, 0x40, 0x66, 0x50, 0xfe, + /*40c0:*/ 0xf2, 0x00, 0xc4, 0xeb, 0x20, 0x8f, 0x20, 0xf1, 0x9d, 0xea, 0x23, 0x37, 0x8f, 0x22, 0x5d, 0xff, + /*40d0:*/ 0x8c, 0x17, 0xaa, 0x6a, 0x3a, 0xad, 0x9a, 0x79, 0x74, 0xe9, 0xdc, 0xc2, 0x97, 0x96, 0xb0, 0xf8, + /*40e0:*/ 0x86, 0x38, 0x13, 0x41, 0xfa, 0x08, 0xd9, 0x2a, 0x18, 0xbc, 0x4a, 0xb6, 0x2a, 0x7e, 0x8f, 0x0d, + /*40f0:*/ 0xeb, 0x09, 0x6c, 0xec, 0x39, 0xdc, 0x2e, 0x4c, 0xcd, 0x58, 0x0f, 0xaf, 0x7e, 0x0f, 0x04, 0x71, + /*4100:*/ 0x8f, 0xa4, 0x08, 0xe6, 0x2b, 0xda, 0xde, 0x42, 0x48, 0xb4, 0xa3, 0x4c, 0x1c, 0x70, 0x4d, 0x5c, + /*4110:*/ 0x5c, 0x5b, 0xca, 0x00, 0xa4, 0x2c, 0x9c, 0x39, 0x23, 0xcc, 0xf8, 0xbb, 0xa2, 0x5a, 0xe9, 0x33, + /*4120:*/ 0xe0, 0xa5, 0xb6, 0xcc, 0x86, 0x70, 0x8c, 0xd9, 0x22, 0x34, 0xf2, 0x44, 0xd0, 0xcb, 0x23, 0xbe, + /*4130:*/ 0xee, 0xa1, 0xeb, 0xbf, 0x17, 0xb5, 0x95, 0x5d, 0xc2, 0x35, 0xd2, 0x7e, 0xbb, 0xc4, 0xd7, 0xb3, + /*4140:*/ 0x43, 0x9e, 0x03, 0x5b, 0xc8, 0x54, 0xd8, 0x78, 0x8d, 0x6d, 0x3f, 0x51, 0x40, 0x0a, 0x9d, 0x44, + /*4150:*/ 0xcf, 0xc5, 0x9d, 0xe8, 0x44, 0x9b, 0xb7, 0x65, 0xd5, 0x42, 0x6f, 0xb5, 0x1f, 0x1a, 0x52, 0x36, + /*4160:*/ 0x73, 0x30, 0x29, 0xb4, 0x4c, 0x31, 0xa4, 0xff, 0xc8, 0x54, 0xb2, 0xde, 0xa7, 0x10, 0xa9, 0xb4, + /*4170:*/ 0x3b, 0xfd, 0x20, 0xdf, 0xc6, 0xcc, 0xfa, 0x32, 0xea, 0xf3, 0x60, 0x08, 0x4a, 0x29, 0x16, 0x72, + /*4180:*/ 0xb3, 0x4c, 0x7a, 0xe5, 0xc1, 0x88, 0x29, 0x23, 0x10, 0x02, 0x14, 0xad, 0x24, 0x64, 0xe3, 0x9e, + /*4190:*/ 0xfc, 0xd3, 0x5b, 0x43, 0xee, 0x1a, 0x4b, 0x1e, 0x49, 0xf2, 0x53, 0x37, 0xae, 0x21, 0xe9, 0x4b, + /*41a0:*/ 0x61, 0x89, 0xd0, 0x70, 0x94, 0x20, 0x17, 0x75, 0x59, 0x01, 0x0a, 0xb4, 0x98, 0xb2, 0x98, 0x0b, + /*41b0:*/ 0x17, 0x99, 0xc3, 0xfe, 0x63, 0x51, 0x97, 0xb2, 0x3b, 0x71, 0x54, 0x63, 0x70, 0x12, 0x3f, 0x26, + /*41c0:*/ 0xbe, 0x0e, 0x39, 0x26, 0xf6, 0xe4, 0xda, 0x87, 0xb2, 0x45, 0x03, 0x71, 0xce, 0xe6, 0xc1, 0xd1, + /*41d0:*/ 0x05, 0xfc, 0x46, 0x37, 0x27, 0x92, 0xb2, 0xa2, 0xfd, 0xa7, 0x9f, 0xa3, 0xdd, 0x94, 0x38, 0x83, + /*41e0:*/ 0x3e, 0x7b, 0xa2, 0x1d, 0xc2, 0x32, 0x36, 0xbf, 0x35, 0x2d, 0xa6, 0x1d, 0xf0, 0x94, 0x01, 0x78, + /*41f0:*/ 0xd3, 0x80, 0x66, 0x5f, 0xc8, 0xa5, 0x12, 0x99, 0x35, 0xb7, 0x96, 0x7b, 0x18, 0x41, 0x85, 0x9a, + /*4200:*/ 0x4b, 0x56, 0xd4, 0xf4, 0x3e, 0xe3, 0x17, 0xb8, 0x46, 0x55, 0xe8, 0x54, 0xbc, 0x1f, 0x43, 0x18, + /*4210:*/ 0xf4, 0xb7, 0x51, 0x7c, 0xd2, 0xa6, 0x3d, 0x75, 0xb6, 0x1d, 0x29, 0xad, 0x5b, 0xb7, 0xb0, 0x4c, + /*4220:*/ 0xc9, 0x51, 0xc0, 0x09, 0x25, 0x40, 0x90, 0xd7, 0x7c, 0x43, 0xfb, 0xa2, 0x86, 0x69, 0x0e, 0x3e, + /*4230:*/ 0x2b, 0x3e, 0xe9, 0x13, 0xef, 0x95, 0x70, 0x17, 0x57, 0x02, 0x0b, 0x50, 0x9d, 0x94, 0x1b, 0xb6, + /*4240:*/ 0x1e, 0x6b, 0x5e, 0x5f, 0xa1, 0x78, 0xc3, 0xfd, 0x5c, 0x2d, 0x66, 0x3e, 0xbe, 0x44, 0x03, 0x4e, + /*4250:*/ 0x95, 0x44, 0x28, 0xba, 0x09, 0xdc, 0x2d, 0x25, 0x68, 0xac, 0x17, 0x90, 0x5f, 0x2a, 0x8e, 0x74, + /*4260:*/ 0x88, 0x30, 0x7d, 0x60, 0x5b, 0xfd, 0x21, 0x3c, 0x72, 0x0c, 0x48, 0x90, 0x14, 0x8d, 0xc7, 0x8b, + /*4270:*/ 0xa9, 0x92, 0x66, 0xaa, 0xe4, 0x2d, 0x1b, 0x6f, 0xaf, 0x40, 0xd1, 0x63, 0x78, 0x7c, 0x19, 0x0a, + /*4280:*/ 0x30, 0x75, 0x7c, 0xb5, 0xaf, 0x64, 0xb7, 0x37, 0x60, 0x11, 0x7c, 0xc0, 0x1f, 0xa1, 0xeb, 0xf8, + /*4290:*/ 0x2b, 0x9b, 0x95, 0x31, 0x9f, 0x51, 0x8e, 0x5b, 0x88, 0xaa, 0x13, 0x54, 0xa8, 0xba, 0x21, 0xfe, + /*42a0:*/ 0x3c, 0xc3, 0x28, 0x7f, 0xc6, 0x03, 0xbc, 0x53, 0xde, 0xcd, 0x3c, 0x88, 0xd9, 0xa6, 0x3b, 0xe8, + /*42b0:*/ 0x47, 0x97, 0xca, 0xe9, 0x30, 0x9d, 0xb2, 0x3e, 0x61, 0x87, 0xc2, 0x65, 0x1a, 0x3d, 0x43, 0x8c, + /*42c0:*/ 0x0d, 0x46, 0x44, 0x20, 0xfb, 0x36, 0xd1, 0x1b, 0x67, 0x63, 0x5a, 0x75, 0xdc, 0x14, 0x26, 0xb3, + /*42d0:*/ 0xca, 0x3a, 0xab, 0x17, 0x2e, 0xaf, 0xe1, 0xec, 0x76, 0xc5, 0xc2, 0xef, 0xba, 0xfa, 0xb7, 0xa9, + /*42e0:*/ 0x52, 0xb9, 0x3e, 0xe5, 0x74, 0x21, 0xc3, 0x6b, 0x24, 0x43, 0xcb, 0x82, 0x73, 0x5d, 0x49, 0x59, + /*42f0:*/ 0xa1, 0xf8, 0x5c, 0x95, 0xea, 0x94, 0x93, 0x5b, 0x01, 0xda, 0xd9, 0x19, 0x50, 0x8d, 0x40, 0xa5, + /*4300:*/ 0x83, 0x34, 0x52, 0x7e, 0x41, 0x3f, 0x81, 0x87, 0xc5, 0x5a, 0x70, 0xc9, 0x04, 0x07, 0xe9, 0x68, + /*4310:*/ 0x8e, 0x56, 0x93, 0x6f, 0x2b, 0x2a, 0x7a, 0x16, 0xdb, 0x4e, 0x7b, 0x2b, 0xcd, 0xe0, 0x24, 0x9a, + /*4320:*/ 0xc1, 0xbd, 0x2e, 0x4b, 0x36, 0xba, 0x49, 0x97, 0xbf, 0x97, 0x51, 0x2a, 0xfd, 0xe5, 0xf9, 0x71, + /*4330:*/ 0xf2, 0xf0, 0x2a, 0xe1, 0x33, 0x99, 0x49, 0xf6, 0x7f, 0xea, 0x07, 0x1d, 0x55, 0x88, 0x2b, 0x24, + /*4340:*/ 0xed, 0x3b, 0x9f, 0xd4, 0xaf, 0x50, 0x6b, 0xfe, 0xdf, 0xe2, 0x66, 0x0d, 0xdc, 0x13, 0x5e, 0xf9, + /*4350:*/ 0x66, 0xb8, 0x61, 0x52, 0x93, 0x14, 0x12, 0x8e, 0x36, 0x21, 0xe2, 0x34, 0xa0, 0xd6, 0xde, 0x0e, + /*4360:*/ 0x8d, 0x35, 0x01, 0xfb, 0xe7, 0xe7, 0x60, 0x41, 0xe8, 0xab, 0xf5, 0x4c, 0x82, 0x60, 0x69, 0xbe, + /*4370:*/ 0x3e, 0x9e, 0x9f, 0x65, 0xa3, 0x0a, 0x6e, 0xba, 0x86, 0xff, 0x45, 0x20, 0x8a, 0x3d, 0xf9, 0xfa, + /*4380:*/ 0xe8, 0x01, 0xf4, 0x42, 0x21, 0x5d, 0xa5, 0x3b, 0xff, 0x80, 0xd1, 0xbf, 0xe0, 0x9d, 0x99, 0xf1, + /*4390:*/ 0xe0, 0x97, 0x14, 0xd9, 0xc7, 0x1a, 0x3b, 0xf2, 0x21, 0x76, 0x56, 0x75, 0xf6, 0x8b, 0x75, 0x95, + /*43a0:*/ 0x5d, 0x0d, 0x2e, 0x59, 0xcb, 0xf2, 0x0e, 0xde, 0x42, 0xb8, 0xdd, 0x86, 0x2a, 0xcc, 0xb3, 0x97, + /*43b0:*/ 0x7d, 0x5f, 0x81, 0xb7, 0xf5, 0x88, 0x54, 0xea, 0xdb, 0x0a, 0x97, 0x08, 0x08, 0x55, 0x97, 0x51, + /*43c0:*/ 0x1d, 0x8d, 0xae, 0xf4, 0x5a, 0xc5, 0x84, 0xef, 0x07, 0xb0, 0xb3, 0x4d, 0x3b, 0xfb, 0xe8, 0x33, + /*43d0:*/ 0x24, 0xed, 0x5a, 0xb3, 0xa4, 0xe6, 0x0c, 0x14, 0xb3, 0xd2, 0x39, 0x8f, 0x1e, 0x39, 0xe0, 0x00, + /*43e0:*/ 0xfc, 0x4e, 0x0a, 0x0e, 0x76, 0x8c, 0xef, 0x21, 0xec, 0x95, 0xf8, 0x18, 0xa6, 0x66, 0xce, 0xec, + /*43f0:*/ 0x62, 0x22, 0xf5, 0xfe, 0xc8, 0x6c, 0x6e, 0x3e, 0x42, 0x35, 0xde, 0xce, 0xa9, 0x73, 0x8c, 0xc9, + /*4400:*/ 0xe2, 0xaa, 0xe8, 0xfa, 0xab, 0x13, 0xcb, 0x06, 0xf7, 0xee, 0x99, 0xfd, 0x2d, 0x0b, 0x92, 0xe2, + /*4410:*/ 0x79, 0x96, 0x6b, 0xf3, 0x73, 0x01, 0x26, 0x48, 0x32, 0xcd, 0x19, 0x2a, 0x12, 0x84, 0xa0, 0xca, + /*4420:*/ 0x5f, 0xc0, 0xe8, 0x86, 0x40, 0x8c, 0xa3, 0xd5, 0x2e, 0x14, 0x5d, 0x58, 0xad, 0x2b, 0xcf, 0xf7, + /*4430:*/ 0xeb, 0x8c, 0xba, 0x59, 0x18, 0x13, 0x62, 0x14, 0xe6, 0x01, 0x89, 0xeb, 0xae, 0x22, 0xf6, 0x66, + /*4440:*/ 0xd5, 0x9a, 0x07, 0x76, 0x87, 0xf8, 0xb9, 0x1b, 0xa5, 0x4f, 0xa2, 0xfd, 0x84, 0xcd, 0x1d, 0x81, + /*4450:*/ 0x1b, 0xda, 0xd6, 0x14, 0x60, 0xfa, 0x17, 0x14, 0x59, 0x18, 0x06, 0x70, 0x06, 0x61, 0x03, 0x80, + /*4460:*/ 0x44, 0x8f, 0x5e, 0xb8, 0xb8, 0xc5, 0x80, 0x43, 0xb5, 0x35, 0x97, 0xbe, 0x4c, 0x25, 0x38, 0xfd, + /*4470:*/ 0x2b, 0xa6, 0xbc, 0xcc, 0x37, 0x34, 0x23, 0x44, 0x32, 0x85, 0xf1, 0x7d, 0xea, 0xc5, 0xb2, 0x3d, + /*4480:*/ 0xed, 0x58, 0xe3, 0x07, 0xed, 0xb4, 0x52, 0x84, 0xf4, 0xcf, 0xa4, 0xe9, 0x4b, 0xe4, 0x35, 0xb5, + /*4490:*/ 0x4b, 0x3d, 0xb1, 0x2f, 0x6f, 0xcc, 0x9f, 0xc5, 0xf1, 0x6e, 0x74, 0xe4, 0x07, 0x1e, 0xef, 0x0e, + /*44a0:*/ 0xf0, 0x32, 0x3f, 0x91, 0x7d, 0x44, 0x0c, 0xe6, 0xb9, 0x3a, 0xdd, 0x8b, 0x0b, 0x34, 0x7b, 0x28, + /*44b0:*/ 0x10, 0xe5, 0xc9, 0x95, 0x34, 0x18, 0xa7, 0xd2, 0x6f, 0x67, 0x8b, 0x3d, 0xa3, 0x49, 0x16, 0xb8, + /*44c0:*/ 0x9e, 0x1b, 0x64, 0x2d, 0xbe, 0xf9, 0x81, 0x16, 0xcb, 0xd5, 0x2f, 0x67, 0x1d, 0x54, 0x64, 0xb8, + /*44d0:*/ 0xee, 0x98, 0x75, 0x12, 0xa1, 0x62, 0xb9, 0xa6, 0x4b, 0xc7, 0x8f, 0x85, 0x77, 0xd2, 0xf4, 0x8f, + /*44e0:*/ 0x36, 0xbe, 0xa3, 0xe7, 0x6c, 0xf9, 0xb1, 0x88, 0xf8, 0xf0, 0xac, 0x74, 0x32, 0xa5, 0x47, 0x69, + /*44f0:*/ 0x6d, 0xb6, 0x11, 0xc7, 0x47, 0x0d, 0xdf, 0x35, 0xf3, 0x59, 0x66, 0x2b, 0x47, 0xd7, 0x21, 0x46, + /*4500:*/ 0x57, 0x53, 0x83, 0x33, 0x66, 0x00, 0x78, 0x82, 0x93, 0x7c, 0xb8, 0x46, 0x3b, 0xe6, 0xd5, 0xe9, + /*4510:*/ 0xee, 0xac, 0x1a, 0x7f, 0x88, 0xb3, 0xc1, 0x06, 0xd1, 0x97, 0x9f, 0xa6, 0x03, 0xea, 0x7a, 0x41, + /*4520:*/ 0xfd, 0xae, 0xc6, 0x75, 0x11, 0x77, 0x35, 0x1b, 0x7b, 0x79, 0x6b, 0xb0, 0x0d, 0xd8, 0x7c, 0xd2, + /*4530:*/ 0x7a, 0x50, 0x58, 0x38, 0x94, 0x8e, 0x19, 0x4d, 0x97, 0x45, 0x53, 0xf9, 0x99, 0xa2, 0x8c, 0xaf, + /*4540:*/ 0xf9, 0x87, 0x11, 0x5a, 0xd3, 0x09, 0xcb, 0x63, 0x93, 0x0e, 0xd1, 0xbf, 0x27, 0x88, 0x3d, 0xb6, + /*4550:*/ 0x17, 0x96, 0x20, 0x9a, 0x27, 0x49, 0xd9, 0x45, 0x05, 0x34, 0x70, 0xa6, 0x4e, 0xab, 0x6b, 0xa2, + /*4560:*/ 0x3c, 0xa6, 0x2e, 0xf2, 0x29, 0xfe, 0x7a, 0xc9, 0x06, 0x7d, 0xa1, 0xb6, 0x8b, 0xf2, 0xbf, 0xe7, + /*4570:*/ 0xd0, 0x02, 0x39, 0x04, 0x19, 0x22, 0xf0, 0x18, 0x6e, 0x7f, 0x00, 0x4b, 0x8a, 0x42, 0xa7, 0xe3, + /*4580:*/ 0x8f, 0x46, 0x0a, 0x92, 0x12, 0x7a, 0xe5, 0xf9, 0x4a, 0x4f, 0x28, 0xb2, 0x57, 0x1c, 0x8a, 0xb2, + /*4590:*/ 0x6d, 0xce, 0x6e, 0x42, 0xd6, 0x68, 0xba, 0x60, 0xb2, 0x2a, 0x82, 0x12, 0x80, 0x8c, 0x61, 0xc9, + /*45a0:*/ 0xdb, 0xdf, 0x9f, 0x0a, 0x18, 0x8b, 0x7c, 0xf4, 0x25, 0xba, 0x7f, 0x7e, 0x0d, 0x7e, 0x17, 0xc8, + /*45b0:*/ 0x05, 0x39, 0x13, 0x55, 0x55, 0x0d, 0x0f, 0x21, 0x5d, 0xf8, 0x6a, 0x83, 0x2a, 0xe4, 0x25, 0xa9, + /*45c0:*/ 0x27, 0x6b, 0x3b, 0xa5, 0xff, 0x66, 0xfc, 0x83, 0xcf, 0x73, 0xef, 0xfc, 0x72, 0x51, 0x58, 0x97, + /*45d0:*/ 0x52, 0x1f, 0x57, 0x54, 0xa5, 0xe6, 0x14, 0xe5, 0xfe, 0xb2, 0x3e, 0xb7, 0x52, 0x13, 0x62, 0x8c, + /*45e0:*/ 0x39, 0xfe, 0x67, 0x45, 0xc4, 0xf3, 0x16, 0xd7, 0xa1, 0x0e, 0x16, 0xe1, 0xb2, 0xb9, 0xba, 0xe7, + /*45f0:*/ 0xe1, 0x5c, 0x44, 0x6c, 0xaf, 0xae, 0xea, 0xdf, 0x16, 0x7a, 0xd1, 0xcd, 0xe6, 0x77, 0xf8, 0x0c, + /*4600:*/ 0x99, 0xc9, 0x07, 0xa4, 0x3a, 0xa9, 0x7a, 0x79, 0xe1, 0x00, 0x76, 0xbf, 0x8c, 0x54, 0xf9, 0x13, + /*4610:*/ 0xf3, 0x2d, 0xe5, 0xc1, 0xcc, 0x39, 0x18, 0xbb, 0x68, 0x44, 0x14, 0xdb, 0x52, 0x3f, 0x9d, 0x5e, + /*4620:*/ 0x70, 0x80, 0xd1, 0x12, 0x69, 0xe8, 0xe5, 0x05, 0x9b, 0x3f, 0x34, 0x24, 0xf6, 0xb9, 0x14, 0xaf, + /*4630:*/ 0x62, 0x38, 0x5b, 0x41, 0xa7, 0x2a, 0x4f, 0x75, 0xb1, 0x4a, 0x5c, 0xef, 0x78, 0x21, 0x9c, 0x78, + /*4640:*/ 0xd7, 0xf8, 0x4e, 0xe6, 0x9c, 0x2e, 0xde, 0xe5, 0x65, 0x3d, 0xfe, 0x7b, 0xd2, 0xea, 0x2f, 0x15, + /*4650:*/ 0x35, 0x6e, 0xc7, 0xfe, 0xcc, 0xe6, 0x3d, 0x40, 0xb6, 0x4a, 0xb8, 0x0e, 0x78, 0x26, 0xba, 0xa0, + /*4660:*/ 0xf5, 0xdd, 0xfd, 0x89, 0x5a, 0xb8, 0x3d, 0x92, 0x62, 0x32, 0xe8, 0xc5, 0xc8, 0x69, 0x93, 0xb0, + /*4670:*/ 0xd2, 0xaa, 0xe2, 0xda, 0x9c, 0xe4, 0xd7, 0x41, 0x5e, 0xdc, 0x74, 0xab, 0x36, 0x1b, 0xaf, 0x71, + /*4680:*/ 0xdd, 0xd2, 0x67, 0x25, 0x38, 0x10, 0xd3, 0xc6, 0x00, 0x8e, 0xe6, 0xba, 0xea, 0x91, 0x81, 0x45, + /*4690:*/ 0x2e, 0xad, 0x9b, 0x38, 0xe8, 0x77, 0x1d, 0x11, 0x81, 0xd4, 0x90, 0x1a, 0xac, 0xb5, 0x66, 0xdf, + /*46a0:*/ 0x5e, 0x4c, 0xc1, 0x1e, 0x82, 0x7a, 0xb1, 0x89, 0xbe, 0xb1, 0xe1, 0xad, 0x4d, 0xd4, 0xce, 0xa3, + /*46b0:*/ 0x76, 0x0f, 0x2a, 0xe7, 0x5b, 0x4a, 0x75, 0x0d, 0xbb, 0xd9, 0xf8, 0xe0, 0x8c, 0xd3, 0x0f, 0x3d, + /*46c0:*/ 0xbe, 0x17, 0x58, 0x15, 0x5a, 0x83, 0x2e, 0x81, 0xae, 0xa5, 0x69, 0xe2, 0x71, 0xf4, 0x24, 0xd7, + /*46d0:*/ 0xd2, 0x18, 0x5c, 0x74, 0x2c, 0x2e, 0xe7, 0xae, 0x6e, 0xe9, 0x18, 0x64, 0x83, 0x24, 0xb4, 0x5b, + /*46e0:*/ 0x6e, 0xe3, 0xb3, 0xae, 0x38, 0xe0, 0xb4, 0xba, 0xfe, 0xf7, 0x82, 0xed, 0xa3, 0x88, 0xad, 0xa9, + /*46f0:*/ 0xa6, 0x37, 0xf2, 0xc5, 0x83, 0xf8, 0x24, 0xc9, 0x56, 0x8e, 0x94, 0xa3, 0x7d, 0xa7, 0x2b, 0x83, + /*4700:*/ 0xc2, 0xe9, 0x87, 0xa0, 0x85, 0x05, 0x4d, 0x35, 0x1e, 0xe0, 0x9e, 0x06, 0xbf, 0x81, 0x26, 0xde, + /*4710:*/ 0x6d, 0x55, 0x5f, 0x93, 0xad, 0x80, 0x1e, 0xa5, 0x5c, 0x9d, 0xa6, 0xac, 0x19, 0xa1, 0xf7, 0xb4, + /*4720:*/ 0x65, 0x4a, 0xfd, 0xe1, 0xeb, 0x3d, 0xb9, 0x44, 0x53, 0x8f, 0xd0, 0xbe, 0x7d, 0xcf, 0xd5, 0x6c, + /*4730:*/ 0xf8, 0x32, 0xde, 0x8f, 0x50, 0x63, 0xa7, 0x4d, 0xe5, 0x0a, 0x5b, 0x2a, 0x2c, 0xd1, 0xcd, 0x32, + /*4740:*/ 0x96, 0xd1, 0x4e, 0x21, 0x08, 0xa7, 0x4a, 0xbd, 0x96, 0x51, 0xa3, 0x18, 0x7a, 0xb2, 0xba, 0x41, + /*4750:*/ 0xb6, 0x99, 0x70, 0xc8, 0xc1, 0x7b, 0xb8, 0x84, 0xa2, 0x20, 0x8a, 0x1e, 0x1b, 0x9b, 0x56, 0xd4, + /*4760:*/ 0xc6, 0xdd, 0x00, 0xfe, 0xa6, 0xb1, 0xb6, 0x8b, 0x02, 0x5b, 0xcd, 0xdf, 0xb5, 0x72, 0xe4, 0xd0, + /*4770:*/ 0x9d, 0x95, 0x1d, 0x44, 0xf2, 0x73, 0x7f, 0x18, 0x5b, 0xc5, 0xc3, 0xc4, 0xdd, 0xc6, 0x13, 0x58, + /*4780:*/ 0x71, 0x44, 0xec, 0x5b, 0xf6, 0x43, 0x89, 0x21, 0xd8, 0x91, 0x64, 0xb6, 0x69, 0x89, 0x91, 0x4f, + /*4790:*/ 0x78, 0x3d, 0xfb, 0xa1, 0x73, 0x96, 0x5f, 0xbf, 0xc0, 0x19, 0x82, 0x0f, 0xb5, 0x2b, 0x3f, 0x1d, + /*47a0:*/ 0xba, 0x9a, 0xe8, 0x2e, 0xe5, 0xb9, 0xb9, 0xe7, 0x4c, 0x27, 0x00, 0xca, 0x79, 0xac, 0x5a, 0xfd, + /*47b0:*/ 0x13, 0xcb, 0x53, 0x35, 0x65, 0xfa, 0x4d, 0xed, 0xe7, 0x98, 0xe4, 0x00, 0xa0, 0x0f, 0x9d, 0xfc, + /*47c0:*/ 0x54, 0x71, 0x69, 0x14, 0x0b, 0xd4, 0x46, 0x62, 0xa9, 0xa5, 0x72, 0x75, 0x5d, 0x22, 0x7b, 0x82, + /*47d0:*/ 0x3d, 0xf2, 0x2b, 0xd8, 0x8e, 0x77, 0xc8, 0xf8, 0x97, 0xc3, 0xce, 0x00, 0xdf, 0xa8, 0x00, 0x8a, + /*47e0:*/ 0x2a, 0x12, 0x75, 0x10, 0xa8, 0x21, 0x82, 0x86, 0xbd, 0xa8, 0xa1, 0x75, 0xc1, 0x9a, 0x00, 0x71, + /*47f0:*/ 0x27, 0x73, 0x00, 0xb8, 0x2a, 0x04, 0x21, 0xb8, 0xc4, 0x56, 0xa0, 0xef, 0xd2, 0x90, 0xc7, 0x23, + /*4800:*/ 0x4e, 0x51, 0x7e, 0xcb, 0x9b, 0x5e, 0x4c, 0xae, 0xb0, 0x62, 0xbe, 0x39, 0x3d, 0x19, 0x39, 0x5f, + /*4810:*/ 0x32, 0x13, 0x86, 0x6a, 0x5a, 0xad, 0x11, 0x6c, 0x74, 0xf9, 0x5e, 0x78, 0x5e, 0x6e, 0x04, 0xcf, + /*4820:*/ 0xeb, 0x2d, 0xe1, 0x7c, 0x5a, 0xfa, 0x7d, 0x26, 0xdc, 0x68, 0x43, 0x09, 0x55, 0x1c, 0x32, 0xcf, + /*4830:*/ 0xd8, 0x6d, 0x89, 0xa1, 0xab, 0xb3, 0x17, 0x94, 0x18, 0x25, 0x86, 0x76, 0xc2, 0x05, 0xf4, 0x11, + /*4840:*/ 0x06, 0x39, 0x9b, 0x1b, 0x89, 0xab, 0x3d, 0x33, 0x77, 0x09, 0xf1, 0x16, 0x7d, 0x44, 0x2e, 0x05, + /*4850:*/ 0xe4, 0x38, 0xc6, 0xc6, 0x4e, 0xdb, 0xe1, 0x2f, 0x98, 0xae, 0x45, 0xf5, 0xf5, 0x34, 0x50, 0x05, + /*4860:*/ 0xf0, 0x32, 0x1f, 0x7a, 0x7c, 0xf5, 0x71, 0xa5, 0x08, 0xbb, 0x61, 0x58, 0x3b, 0x4d, 0x48, 0xf8, + /*4870:*/ 0x9b, 0x76, 0x32, 0x34, 0x1b, 0x3d, 0x13, 0x1e, 0xf8, 0xed, 0x51, 0x6b, 0x24, 0xa5, 0xe9, 0x96, + /*4880:*/ 0x34, 0x98, 0x68, 0xfb, 0xa9, 0x4d, 0x12, 0xa1, 0xa1, 0x0d, 0x6e, 0x32, 0x82, 0xb4, 0xd3, 0xb1, + /*4890:*/ 0xb5, 0x20, 0x42, 0xa0, 0xe2, 0x3f, 0x8e, 0xac, 0xe9, 0x37, 0xc5, 0x14, 0x91, 0x5d, 0xd4, 0xd3, + /*48a0:*/ 0xed, 0x11, 0x04, 0x27, 0x90, 0xe1, 0x6d, 0xe4, 0xef, 0xd3, 0x41, 0xe3, 0xdc, 0xd3, 0xfc, 0x4c, + /*48b0:*/ 0x22, 0x59, 0xc2, 0x33, 0x3c, 0x08, 0xbb, 0x80, 0x32, 0x44, 0xf9, 0x50, 0x11, 0x26, 0x12, 0xd8, + /*48c0:*/ 0x68, 0x6c, 0x3b, 0x7f, 0x54, 0x94, 0x03, 0x59, 0x00, 0xea, 0x1d, 0x9d, 0xbb, 0x22, 0xe2, 0xbd, + /*48d0:*/ 0xd6, 0x00, 0xe9, 0xcf, 0x9f, 0x86, 0x05, 0x2f, 0x48, 0x2b, 0x79, 0x86, 0x0f, 0x4c, 0xc9, 0xb2, + /*48e0:*/ 0x2d, 0xbb, 0xde, 0x59, 0x01, 0x47, 0x98, 0x6b, 0x0d, 0xb2, 0xeb, 0x84, 0x66, 0x1a, 0xd4, 0xa3, + /*48f0:*/ 0x0f, 0xb9, 0xb7, 0xd9, 0xa5, 0x0b, 0x23, 0xa8, 0x49, 0xc9, 0x47, 0xd3, 0xff, 0x94, 0xcd, 0x5e, + /*4900:*/ 0x78, 0x6a, 0x58, 0x7b, 0x41, 0x12, 0x8d, 0x50, 0x3e, 0xa4, 0x50, 0x53, 0x1d, 0x84, 0xda, 0x58, + /*4910:*/ 0x6f, 0x7f, 0x90, 0x58, 0xaf, 0xfa, 0x25, 0xd0, 0x02, 0xd8, 0xea, 0xc9, 0x35, 0x88, 0xd9, 0xf3, + /*4920:*/ 0x02, 0xa8, 0xf0, 0xbc, 0x8b, 0x46, 0x42, 0xc5, 0x36, 0xf6, 0xcf, 0x15, 0x5c, 0x74, 0x98, 0x2d, + /*4930:*/ 0x29, 0x7f, 0x80, 0xe5, 0xae, 0xb7, 0xb6, 0xf3, 0x11, 0xcc, 0x54, 0x1f, 0xb4, 0x93, 0x34, 0xbe, + /*4940:*/ 0x85, 0x7f, 0x4e, 0x3d, 0x1e, 0xe9, 0x63, 0x9c, 0x17, 0x10, 0x28, 0xfb, 0x5a, 0xbc, 0xcb, 0x71, + /*4950:*/ 0xb5, 0x64, 0x09, 0x84, 0x9c, 0x6b, 0x8c, 0x54, 0x35, 0xc7, 0x75, 0xc2, 0x6c, 0x3a, 0xee, 0xc2, + /*4960:*/ 0xcb, 0xb6, 0x57, 0xad, 0x23, 0xea, 0x18, 0x65, 0x6f, 0xd8, 0xbe, 0x2d, 0x5f, 0x05, 0x18, 0x0e, + /*4970:*/ 0x1d, 0xe6, 0xce, 0xaa, 0xd7, 0xf3, 0x36, 0xed, 0xc9, 0x8c, 0xaf, 0x33, 0x80, 0xe0, 0xf2, 0x80, + /*4980:*/ 0x78, 0x4d, 0xa9, 0x69, 0xa7, 0x1c, 0xd6, 0x13, 0x0f, 0xdd, 0xd6, 0x58, 0x05, 0xc8, 0xad, 0x98, + /*4990:*/ 0x2e, 0x6f, 0xcd, 0x38, 0x75, 0x85, 0x99, 0xd2, 0xc3, 0x3f, 0x8b, 0xcb, 0x8b, 0xf0, 0xcf, 0x87, + /*49a0:*/ 0x84, 0xd5, 0xf7, 0xb9, 0xca, 0x85, 0x3e, 0x5d, 0x0a, 0xbd, 0xd8, 0x4b, 0xfb, 0x5a, 0xdc, 0x84, + /*49b0:*/ 0x3e, 0x0f, 0x0e, 0x16, 0x6b, 0x0a, 0x17, 0xac, 0xc6, 0x91, 0x65, 0xd0, 0x7b, 0xaf, 0x41, 0xea, + /*49c0:*/ 0xaf, 0xa9, 0x9e, 0x8f, 0xfb, 0x38, 0xee, 0xe9, 0xf8, 0xcd, 0x90, 0xf4, 0xc0, 0x9c, 0xb3, 0x2f, + /*49d0:*/ 0x0d, 0x52, 0xdc, 0x83, 0x06, 0xfd, 0xb0, 0xe8, 0x2e, 0x89, 0x1a, 0x1f, 0xb0, 0x86, 0x05, 0x2b, + /*49e0:*/ 0x00, 0xac, 0x0a, 0x8e, 0xf7, 0x3b, 0xb0, 0xa3, 0x94, 0x6e, 0x5b, 0xb9, 0x02, 0x34, 0xc5, 0xa1, + /*49f0:*/ 0x65, 0xce, 0x03, 0x23, 0x71, 0x3b, 0x96, 0x96, 0x20, 0x29, 0x13, 0x6a, 0x5d, 0x1d, 0xab, 0x44, + /*4a00:*/ 0xc2, 0xfc, 0xab, 0x74, 0xf9, 0x90, 0xeb, 0xf7, 0x4a, 0x08, 0x8e, 0x47, 0x9f, 0x16, 0xc0, 0x07, + /*4a10:*/ 0x97, 0x36, 0x59, 0x1b, 0xce, 0x87, 0xf4, 0xf9, 0x4c, 0x8b, 0xa9, 0xa0, 0x06, 0x25, 0x4e, 0x0f, + /*4a20:*/ 0xc3, 0xb9, 0x67, 0xe1, 0xb1, 0xfd, 0x4c, 0x5e, 0xad, 0x29, 0x28, 0xc5, 0x34, 0x00, 0x11, 0x23, + /*4a30:*/ 0xb9, 0x29, 0xb3, 0x5a, 0x5c, 0x31, 0x67, 0x23, 0x84, 0xa6, 0xd9, 0x26, 0x27, 0x11, 0x09, 0x21, + /*4a40:*/ 0x43, 0x0b, 0x8b, 0x97, 0xbc, 0x4d, 0x9b, 0x3b, 0x21, 0xf8, 0x8d, 0xa2, 0x1f, 0xbb, 0xca, 0xd7, + /*4a50:*/ 0x38, 0xcf, 0xb7, 0x20, 0x7c, 0x95, 0x0d, 0x42, 0xaf, 0xf4, 0x71, 0x6f, 0x3c, 0x47, 0xb1, 0x0d, + /*4a60:*/ 0x76, 0x26, 0x14, 0x70, 0xff, 0x2c, 0xd8, 0x06, 0xc0, 0xdd, 0x18, 0xa1, 0x18, 0x83, 0x26, 0x6e, + /*4a70:*/ 0x9a, 0x3b, 0x25, 0xf0, 0xfb, 0x7e, 0xab, 0xaf, 0x9a, 0x26, 0x90, 0xd1, 0xb2, 0x29, 0x94, 0x49, + /*4a80:*/ 0x45, 0x4b, 0x4b, 0x95, 0xf4, 0xd6, 0xc6, 0x30, 0xc5, 0xf7, 0x21, 0x1b, 0x48, 0x45, 0x50, 0x01, + /*4a90:*/ 0xb1, 0xb8, 0x83, 0xe4, 0xfb, 0xbb, 0x5a, 0xc6, 0x63, 0xe2, 0x5e, 0x85, 0x98, 0x3e, 0xdf, 0x67, + /*4aa0:*/ 0x75, 0xbd, 0xb6, 0x59, 0x67, 0x47, 0x01, 0xea, 0xe3, 0x2d, 0xcc, 0xde, 0xf8, 0x58, 0x37, 0x99, + /*4ab0:*/ 0xb6, 0xbd, 0xec, 0xd5, 0x51, 0x9c, 0x22, 0x4e, 0x96, 0x52, 0x2a, 0x2a, 0x2e, 0x3b, 0x82, 0x98, + /*4ac0:*/ 0xd8, 0xae, 0x56, 0x6a, 0x20, 0x7c, 0x4d, 0x86, 0x46, 0x1c, 0x0c, 0x91, 0x4c, 0xe4, 0x23, 0xf2, + /*4ad0:*/ 0x0d, 0x06, 0x89, 0x72, 0xd3, 0xd7, 0x24, 0xd9, 0xb8, 0x4e, 0xb2, 0x6a, 0x72, 0x75, 0x74, 0x9a, + /*4ae0:*/ 0x94, 0x65, 0x97, 0xac, 0xdf, 0x1d, 0x5c, 0x48, 0x0e, 0xa7, 0x1a, 0x22, 0x69, 0x2e, 0xb3, 0x92, + /*4af0:*/ 0x6e, 0x69, 0xdc, 0x65, 0xd1, 0xf0, 0xfa, 0xf5, 0x41, 0x5c, 0x78, 0x54, 0x72, 0x1a, 0x8e, 0xe7, + /*4b00:*/ 0xc8, 0x7c, 0xd2, 0x43, 0x6b, 0x78, 0xe9, 0x22, 0xc3, 0x87, 0x28, 0x3c, 0x10, 0x8d, 0x86, 0x9f, + /*4b10:*/ 0x93, 0xdf, 0x0c, 0x5c, 0x55, 0x91, 0x4c, 0x7f, 0x3a, 0x80, 0x47, 0x5f, 0x73, 0xba, 0xa1, 0xbb, + /*4b20:*/ 0xe2, 0xb5, 0xba, 0xfc, 0x83, 0x0f, 0x70, 0xe5, 0xea, 0x7c, 0x9e, 0xe8, 0x8e, 0x3d, 0x3a, 0xde, + /*4b30:*/ 0x5c, 0x60, 0xc7, 0x99, 0x21, 0x3e, 0x2d, 0x35, 0x45, 0xee, 0x11, 0xe6, 0xdd, 0x3f, 0x21, 0xb4, + /*4b40:*/ 0xae, 0x9c, 0x69, 0x48, 0x86, 0xec, 0xac, 0x6c, 0x53, 0x98, 0xba, 0x8c, 0xcc, 0xf2, 0x10, 0x39, + /*4b50:*/ 0x7b, 0x83, 0x71, 0x8b, 0xda, 0x2f, 0xd3, 0xca, 0x64, 0xd8, 0x56, 0xdc, 0xc2, 0x34, 0x51, 0x64, + /*4b60:*/ 0x78, 0x90, 0x57, 0x1d, 0xa7, 0xae, 0x70, 0x77, 0x3d, 0x0d, 0xef, 0x4d, 0x58, 0xae, 0xe1, 0xe4, + /*4b70:*/ 0xe6, 0xee, 0xfd, 0x21, 0x12, 0xf7, 0x3b, 0x8d, 0x9f, 0xb2, 0x62, 0xe4, 0x97, 0x6b, 0x46, 0x69, + /*4b80:*/ 0xfa, 0x03, 0x9e, 0x30, 0x9b, 0x16, 0xad, 0xe5, 0xe6, 0x06, 0xf6, 0x8e, 0x87, 0x68, 0xa6, 0x48, + /*4b90:*/ 0x91, 0xa2, 0x77, 0x54, 0xc4, 0xd8, 0x52, 0x58, 0x59, 0x66, 0x19, 0xc9, 0x88, 0x4e, 0x4e, 0xd7, + /*4ba0:*/ 0xd3, 0x8a, 0x3f, 0x33, 0xa2, 0x55, 0xfe, 0x6a, 0x00, 0xc3, 0x40, 0xec, 0x36, 0x5f, 0x61, 0x0a, + /*4bb0:*/ 0xbe, 0x37, 0x62, 0x35, 0x75, 0x82, 0x73, 0x20, 0x52, 0x22, 0x01, 0x48, 0x6a, 0x64, 0x99, 0x81, + /*4bc0:*/ 0xa2, 0x86, 0xb6, 0x62, 0xe9, 0x23, 0x73, 0xdf, 0x4b, 0xc2, 0xf8, 0x08, 0x7d, 0xe6, 0x0f, 0x5d, + /*4bd0:*/ 0x98, 0xbd, 0xb7, 0x7e, 0x60, 0x8d, 0xfd, 0x30, 0x59, 0x38, 0xf8, 0xa2, 0xa3, 0x7e, 0x92, 0x4a, + /*4be0:*/ 0xe1, 0x46, 0x20, 0xab, 0xa8, 0x0f, 0x5f, 0x4e, 0x95, 0xa3, 0x23, 0x4b, 0x50, 0x92, 0x39, 0xb3, + /*4bf0:*/ 0x45, 0xa3, 0x67, 0xee, 0xbe, 0x0f, 0xea, 0x34, 0xd1, 0x2d, 0x0f, 0x78, 0x31, 0xfc, 0x4b, 0x32, + /*4c00:*/ 0xe6, 0x2b, 0x63, 0xab, 0xda, 0xf1, 0xbc, 0x55, 0xc2, 0xfe, 0x9e, 0xae, 0x07, 0x4f, 0x1e, 0x0c, + /*4c10:*/ 0x18, 0x78, 0xf5, 0x6a, 0x6c, 0xa4, 0x8b, 0xc3, 0xe3, 0xd1, 0x87, 0x04, 0x8d, 0x9a, 0xb7, 0x87, + /*4c20:*/ 0x68, 0x8b, 0x44, 0x6e, 0x2f, 0x0b, 0x07, 0x33, 0x43, 0x87, 0x0f, 0x86, 0x08, 0x7a, 0xd6, 0xb5, + /*4c30:*/ 0x3c, 0x5f, 0x81, 0x49, 0x10, 0xa4, 0x07, 0x09, 0xef, 0xc9, 0xb4, 0xbf, 0x95, 0x84, 0x0a, 0x5c, + /*4c40:*/ 0xfd, 0x44, 0xfe, 0x7f, 0xf4, 0x5a, 0xb0, 0xb4, 0xb1, 0x42, 0xe8, 0xbf, 0x82, 0xf7, 0xe9, 0x09, + /*4c50:*/ 0x97, 0x6c, 0xbf, 0x30, 0x2b, 0x83, 0xd1, 0x40, 0xe8, 0x2b, 0xb8, 0x10, 0x54, 0x12, 0xaa, 0x8f, + /*4c60:*/ 0x33, 0x76, 0x1a, 0xc9, 0x70, 0x6e, 0xaa, 0xa7, 0xe9, 0xcd, 0x16, 0x58, 0x2c, 0x18, 0xb0, 0x4f, + /*4c70:*/ 0x2c, 0x0c, 0x7d, 0xd2, 0xa4, 0x42, 0x3f, 0xbf, 0x50, 0x14, 0xa3, 0x8f, 0x10, 0x8a, 0xd6, 0xcc, + /*4c80:*/ 0x89, 0xf8, 0xdb, 0x77, 0x0f, 0x91, 0xf0, 0x9b, 0xbd, 0x1a, 0xfd, 0xc6, 0x2b, 0x58, 0x26, 0x92, + /*4c90:*/ 0x31, 0xf3, 0x6c, 0xdd, 0xd1, 0x39, 0x25, 0xc6, 0xff, 0x7d, 0x97, 0xae, 0x2d, 0xa7, 0x72, 0xa8, + /*4ca0:*/ 0x9b, 0x02, 0x3a, 0xad, 0x61, 0x73, 0x82, 0xf2, 0xbb, 0x18, 0x7e, 0xf4, 0x3c, 0x66, 0x8f, 0x6a, + /*4cb0:*/ 0xb9, 0xb0, 0xad, 0x7a, 0x25, 0x3a, 0xbe, 0x0c, 0x78, 0xc3, 0x3c, 0x53, 0xd7, 0x3d, 0xf8, 0xb5, + /*4cc0:*/ 0xab, 0xd9, 0xe2, 0x59, 0xaf, 0x37, 0x67, 0x31, 0xc2, 0x6d, 0x02, 0xf8, 0x0b, 0x96, 0xd0, 0x50, + /*4cd0:*/ 0x8a, 0x35, 0xdf, 0x92, 0x27, 0x44, 0x2c, 0x5d, 0x31, 0x84, 0x3d, 0x12, 0xe6, 0xe3, 0xd1, 0x01, + /*4ce0:*/ 0xe8, 0xd3, 0xbb, 0x68, 0x6c, 0x12, 0x74, 0x0a, 0x83, 0x53, 0x29, 0x88, 0xff, 0xec, 0xef, 0x2f, + /*4cf0:*/ 0xe2, 0xa8, 0x8e, 0xd0, 0x07, 0xb8, 0x6e, 0xae, 0x80, 0x9c, 0x34, 0x51, 0xcd, 0xdb, 0x59, 0x2c, + /*4d00:*/ 0x06, 0x7e, 0x72, 0x9c, 0xa7, 0x7f, 0xeb, 0x2d, 0x4e, 0x1e, 0xfe, 0xa6, 0x89, 0x93, 0x8a, 0x6d, + /*4d10:*/ 0x82, 0xec, 0x91, 0x75, 0x2b, 0x13, 0x72, 0x2d, 0x21, 0xa6, 0x3c, 0x99, 0x03, 0xc2, 0x39, 0x33, + /*4d20:*/ 0xb1, 0xd9, 0xae, 0x23, 0x04, 0x33, 0xd7, 0x03, 0x19, 0x83, 0x04, 0xdd, 0x1b, 0x7b, 0x19, 0xd0, + /*4d30:*/ 0xf7, 0x75, 0x2f, 0x8b, 0xda, 0x8d, 0xad, 0xae, 0xd3, 0x84, 0x0a, 0x14, 0xf7, 0xb6, 0x4a, 0x6f, + /*4d40:*/ 0xf6, 0x6c, 0x2b, 0x8c, 0x2a, 0x0d, 0x21, 0xc0, 0x16, 0x2f, 0x76, 0x75, 0xac, 0x58, 0xa4, 0x2d, + /*4d50:*/ 0xae, 0xa5, 0x0c, 0xe7, 0xc4, 0x16, 0xb2, 0xc3, 0xf0, 0x56, 0x39, 0xa2, 0xc9, 0xc4, 0x05, 0xd1, + /*4d60:*/ 0x6b, 0xe6, 0x25, 0xdb, 0x9b, 0x0f, 0x41, 0x9c, 0x59, 0xe5, 0x81, 0xca, 0x47, 0x78, 0x66, 0xae, + /*4d70:*/ 0xb7, 0x5d, 0x90, 0xa2, 0xcc, 0x8a, 0x66, 0x5c, 0x36, 0xd8, 0x22, 0x4d, 0x26, 0x4c, 0x66, 0x4a, + /*4d80:*/ 0x08, 0xce, 0x04, 0x8c, 0x3f, 0x02, 0xcc, 0x06, 0x36, 0x41, 0x0b, 0x27, 0x7a, 0x1c, 0x4d, 0x84, + /*4d90:*/ 0xbc, 0x32, 0x5e, 0x32, 0x2c, 0x35, 0x24, 0xaa, 0x29, 0x0d, 0xd1, 0xfc, 0x5b, 0x16, 0x5b, 0x63, + /*4da0:*/ 0x3b, 0x22, 0x15, 0x80, 0xe7, 0x2b, 0x25, 0x78, 0xc5, 0xae, 0x8a, 0x9f, 0xff, 0xc0, 0xbd, 0x49, + /*4db0:*/ 0x56, 0x77, 0x5b, 0xf0, 0xee, 0x4d, 0xc7, 0x60, 0x9d, 0x53, 0x60, 0xd7, 0xd9, 0xa9, 0x22, 0x9d, + /*4dc0:*/ 0xa9, 0x1f, 0x58, 0x0e, 0x55, 0x7e, 0xc1, 0x39, 0x38, 0x70, 0x7c, 0x7b, 0x9f, 0xc8, 0x74, 0x91, + /*4dd0:*/ 0xbf, 0x5c, 0xd9, 0xba, 0x67, 0x9f, 0xe7, 0xcb, 0xe6, 0xda, 0x6c, 0xb5, 0xe2, 0x15, 0x77, 0x35, + /*4de0:*/ 0x43, 0x09, 0x40, 0x0f, 0x2a, 0x2d, 0x58, 0x1a, 0xda, 0xd4, 0x42, 0x34, 0x02, 0x5e, 0x28, 0x5b, + /*4df0:*/ 0x93, 0x26, 0x9e, 0xfb, 0x2a, 0x3f, 0xb0, 0x48, 0xc6, 0x22, 0x75, 0x54, 0x72, 0xbc, 0x68, 0x2a, + /*4e00:*/ 0xb3, 0x90, 0xe6, 0xaf, 0x37, 0x08, 0x41, 0xad, 0xf9, 0x45, 0x97, 0x4a, 0x10, 0x07, 0x51, 0x3d, + /*4e10:*/ 0x19, 0xd9, 0x36, 0xa4, 0x4f, 0x42, 0x92, 0xd3, 0x2e, 0x7e, 0xe1, 0x30, 0xbe, 0x9f, 0x2f, 0x79, + /*4e20:*/ 0x34, 0xc8, 0x95, 0xee, 0x28, 0x5e, 0x01, 0x05, 0xc3, 0x00, 0xcb, 0x49, 0x38, 0xcf, 0x52, 0xa4, + /*4e30:*/ 0x2b, 0xb2, 0xcd, 0xb8, 0x7c, 0x74, 0xb6, 0xd5, 0x8a, 0xff, 0x61, 0x35, 0x19, 0x5f, 0xea, 0x54, + /*4e40:*/ 0x9f, 0xa9, 0xa0, 0x47, 0x2b, 0x98, 0x65, 0x1d, 0x13, 0xe2, 0x2d, 0x86, 0xa4, 0x96, 0xb6, 0x19, + /*4e50:*/ 0xc0, 0x72, 0xfd, 0x06, 0x92, 0x7f, 0x1d, 0x98, 0x47, 0x39, 0x66, 0xff, 0xea, 0x00, 0x80, 0x34, + /*4e60:*/ 0xd4, 0x73, 0x0e, 0xc5, 0x88, 0x1c, 0x66, 0xf7, 0x0c, 0xb4, 0x67, 0x75, 0xe5, 0x8b, 0x37, 0x03, + /*4e70:*/ 0x41, 0x96, 0x6d, 0x62, 0xda, 0xbb, 0x77, 0x2a, 0x93, 0x2b, 0xf6, 0xce, 0x8a, 0x89, 0x25, 0x0a, + /*4e80:*/ 0x97, 0x73, 0x99, 0x68, 0x2d, 0xbe, 0x96, 0x31, 0x16, 0xba, 0xfe, 0x05, 0x0e, 0x37, 0x58, 0x3f, + /*4e90:*/ 0x2d, 0xce, 0xd1, 0x8e, 0x9d, 0x0a, 0xac, 0x91, 0x06, 0xbd, 0x38, 0x8c, 0x43, 0x43, 0xf8, 0xbd, + /*4ea0:*/ 0x43, 0xb7, 0xfc, 0xf1, 0xe0, 0x53, 0x59, 0x67, 0xbb, 0x99, 0x22, 0xd7, 0xb5, 0x9d, 0xed, 0x85, + /*4eb0:*/ 0xae, 0xbc, 0xb3, 0xa4, 0x6a, 0xe2, 0x5b, 0x8d, 0x4e, 0x93, 0x31, 0x44, 0xeb, 0x5b, 0x78, 0x1f, + /*4ec0:*/ 0x1c, 0x20, 0x20, 0x1d, 0xb6, 0xd2, 0x51, 0x96, 0x0b, 0xcd, 0x09, 0x5c, 0x44, 0x20, 0x0d, 0xc5, + /*4ed0:*/ 0x7a, 0x54, 0x0c, 0xef, 0xb9, 0x2e, 0x34, 0x56, 0xa5, 0xbd, 0x06, 0x4f, 0x73, 0x1a, 0x4b, 0x97, + /*4ee0:*/ 0x43, 0xcd, 0xf6, 0xe1, 0x35, 0x29, 0x82, 0x0e, 0xcc, 0x62, 0x4f, 0xe9, 0x32, 0x40, 0x78, 0x33, + /*4ef0:*/ 0xa2, 0xcb, 0x4d, 0x6a, 0x7f, 0x04, 0x5b, 0x04, 0x45, 0xc4, 0xd2, 0xef, 0x6d, 0x51, 0xff, 0xe3, + /*4f00:*/ 0x28, 0xbb, 0x23, 0x1e, 0x21, 0x7f, 0x19, 0x61, 0x7c, 0xb6, 0x6f, 0x8f, 0x2a, 0x10, 0x2b, 0x3e, + /*4f10:*/ 0x77, 0x6a, 0x6d, 0xfa, 0x2a, 0x63, 0xa2, 0x09, 0xde, 0x84, 0x67, 0xd2, 0x1b, 0xf2, 0x06, 0x5e, + /*4f20:*/ 0xc4, 0x63, 0xce, 0xe0, 0x23, 0x85, 0xb3, 0x30, 0x22, 0x61, 0xd4, 0x99, 0x2b, 0x3a, 0xca, 0xf4, + /*4f30:*/ 0x80, 0xba, 0x0a, 0xee, 0xa3, 0x58, 0xfc, 0xcd, 0x3e, 0x66, 0x3e, 0xfe, 0xb5, 0xaa, 0xdf, 0x69, + /*4f40:*/ 0x62, 0x8e, 0x7e, 0xda, 0x44, 0x4d, 0xc6, 0x6a, 0x0b, 0x20, 0x52, 0xbb, 0xf3, 0xf3, 0x0c, 0x39, + /*4f50:*/ 0x4b, 0xf8, 0x6c, 0x94, 0xce, 0x1f, 0x11, 0x5f, 0x6f, 0xbd, 0x4b, 0xbc, 0xcc, 0x21, 0xf0, 0x0c, + /*4f60:*/ 0x8f, 0x64, 0x98, 0x82, 0x99, 0x47, 0xa1, 0x73, 0x46, 0x0d, 0x1b, 0xd4, 0x66, 0x16, 0xd2, 0xed, + /*4f70:*/ 0xaf, 0xcd, 0x35, 0x5c, 0x61, 0xe7, 0xdc, 0xd3, 0xac, 0x82, 0xa1, 0xea, 0x90, 0x33, 0x19, 0x8a, + /*4f80:*/ 0x68, 0x20, 0x1c, 0xfd, 0xae, 0xfc, 0x6f, 0x8a, 0x69, 0xcd, 0xcc, 0x8e, 0x22, 0x68, 0xef, 0x8a, + /*4f90:*/ 0xa9, 0x64, 0x86, 0xcc, 0x2f, 0x46, 0xc6, 0x8d, 0x81, 0x1f, 0x5a, 0xc9, 0x3d, 0xdc, 0x84, 0xf3, + /*4fa0:*/ 0x27, 0x81, 0x4d, 0x34, 0xc3, 0x66, 0x2b, 0xbb, 0x13, 0xa4, 0x7d, 0x02, 0x91, 0x43, 0x7d, 0x2c, + /*4fb0:*/ 0x5b, 0x7b, 0xd0, 0x82, 0x51, 0xa8, 0x1b, 0x9b, 0xbd, 0xa3, 0x95, 0x5b, 0xca, 0x21, 0x48, 0x34, + /*4fc0:*/ 0xaa, 0x00, 0x30, 0x3d, 0xa0, 0x6c, 0x5a, 0xa6, 0x16, 0xa6, 0x92, 0x6b, 0x25, 0xb6, 0x47, 0xbb, + /*4fd0:*/ 0xb0, 0x2b, 0xb7, 0x82, 0x1b, 0xa3, 0x4a, 0xc4, 0x72, 0xbe, 0xf7, 0xbf, 0xaf, 0xcf, 0xaf, 0x2b, + /*4fe0:*/ 0x0e, 0x9e, 0x88, 0x91, 0xe6, 0xcd, 0x2a, 0x50, 0x73, 0xd8, 0xf7, 0x6e, 0xf6, 0x7d, 0xb4, 0xc9, + /*4ff0:*/ 0xb6, 0xb8, 0x03, 0x90, 0xf8, 0xbe, 0x36, 0x95, 0x5c, 0x91, 0x54, 0x24, 0x6f, 0xfd, 0x6c, 0xa5, + /*5000:*/ 0x07, 0xfd, 0x75, 0x1e, 0x2e, 0xcb, 0x11, 0x08, 0x84, 0x18, 0xc6, 0xcb, 0xdd, 0x01, 0xf1, 0x5a, + /*5010:*/ 0x64, 0xf7, 0x8b, 0x64, 0xa4, 0x6f, 0xe8, 0xad, 0xc2, 0x27, 0x86, 0xeb, 0xca, 0xdd, 0xe1, 0x2e, + /*5020:*/ 0x10, 0x34, 0x9c, 0x03, 0x7e, 0x6b, 0x5a, 0x7f, 0x83, 0xe6, 0xd3, 0x60, 0xe7, 0x1e, 0xec, 0xd2, + /*5030:*/ 0x63, 0xe6, 0x60, 0xd2, 0xab, 0x12, 0x56, 0x65, 0x3d, 0xfe, 0x9c, 0x36, 0xab, 0x5a, 0x43, 0x57, + /*5040:*/ 0xf1, 0x12, 0x31, 0x7c, 0xa8, 0xf4, 0xbc, 0x48, 0x36, 0x0f, 0xa7, 0xc4, 0x47, 0x3c, 0x67, 0xc9, + /*5050:*/ 0xbd, 0xa3, 0x46, 0x86, 0x13, 0x0e, 0xc2, 0xdc, 0x43, 0xa3, 0xa6, 0x16, 0xfa, 0xa7, 0xeb, 0xae, + /*5060:*/ 0xbb, 0x6d, 0x07, 0x3d, 0xb5, 0x2c, 0xad, 0x2a, 0x7c, 0x78, 0xd1, 0x58, 0x31, 0x5a, 0x1e, 0x5c, + /*5070:*/ 0xf9, 0xbf, 0x89, 0xbf, 0x99, 0xc5, 0xd2, 0x6b, 0x0d, 0xf1, 0xbe, 0x27, 0xfc, 0x60, 0x70, 0xb5, + /*5080:*/ 0xbd, 0xd4, 0x59, 0x37, 0x9c, 0xd4, 0x94, 0xd9, 0x3e, 0x32, 0x8a, 0xe9, 0xe1, 0x26, 0x25, 0x81, + /*5090:*/ 0x47, 0x4a, 0x0e, 0xfc, 0xa0, 0xae, 0xa3, 0x94, 0x2e, 0x1f, 0x56, 0x83, 0xc4, 0xc8, 0x23, 0x99, + /*50a0:*/ 0xf1, 0x23, 0xdd, 0xb1, 0xa6, 0x6b, 0xa7, 0x37, 0x39, 0x54, 0xb4, 0xbc, 0x67, 0x65, 0x9d, 0x69, + /*50b0:*/ 0x23, 0x28, 0xf2, 0x69, 0xbf, 0xd4, 0xdf, 0x54, 0xd5, 0x05, 0x21, 0xbc, 0xe5, 0xb6, 0xe1, 0xd2, + /*50c0:*/ 0xae, 0x2c, 0x87, 0x03, 0x21, 0x77, 0xe0, 0x86, 0xe7, 0x1a, 0x55, 0x8c, 0x0d, 0x14, 0x78, 0xbb, + /*50d0:*/ 0xe1, 0xc8, 0xf1, 0xd3, 0xf7, 0x10, 0x58, 0x23, 0xf7, 0x39, 0x38, 0x05, 0xbe, 0x62, 0xb0, 0x14, + /*50e0:*/ 0xd1, 0x9f, 0xdd, 0xb9, 0xf8, 0x79, 0x37, 0x1f, 0x8b, 0xf9, 0x54, 0x71, 0xde, 0x08, 0xeb, 0x46, + /*50f0:*/ 0xbf, 0xa8, 0x74, 0xd5, 0xc6, 0x92, 0xb7, 0x18, 0xed, 0xae, 0xcd, 0x62, 0x29, 0xf7, 0xb9, 0x74, + /*5100:*/ 0x27, 0x91, 0x95, 0x3b, 0x34, 0x64, 0x17, 0xbf, 0x35, 0x52, 0xb0, 0x9e, 0x1a, 0x0e, 0x37, 0x48, + /*5110:*/ 0xaa, 0x47, 0x2b, 0xe5, 0xbb, 0x48, 0xc5, 0xe5, 0x58, 0x35, 0xd7, 0x3a, 0x1a, 0x55, 0xf8, 0x30, + /*5120:*/ 0xd4, 0xdd, 0x07, 0xd0, 0x31, 0x42, 0xce, 0x57, 0x2e, 0xdd, 0xea, 0x97, 0x7a, 0xbe, 0xa3, 0xc0, + /*5130:*/ 0x2a, 0xb2, 0xad, 0xf2, 0x13, 0x54, 0x09, 0x90, 0x0d, 0xe7, 0x58, 0xf2, 0x37, 0x51, 0xd8, 0x1d, + /*5140:*/ 0x2e, 0x72, 0x34, 0x51, 0xd6, 0x21, 0x41, 0x3c, 0x5e, 0xab, 0x16, 0xec, 0x1a, 0x23, 0xd4, 0xde, + /*5150:*/ 0x40, 0x3f, 0x5c, 0xce, 0xb0, 0x9f, 0x1a, 0x96, 0xf6, 0x78, 0x9d, 0xec, 0xef, 0x73, 0x63, 0x11, + /*5160:*/ 0x12, 0x57, 0x71, 0x01, 0x20, 0xa5, 0x63, 0xdc, 0x33, 0x18, 0x1a, 0x67, 0x1c, 0x6a, 0x82, 0xfe, + /*5170:*/ 0x41, 0xca, 0x6b, 0x17, 0x62, 0x75, 0xda, 0xff, 0xa0, 0x8e, 0xb3, 0x75, 0xab, 0x13, 0x81, 0x2d, + /*5180:*/ 0x4c, 0x35, 0x3a, 0x6b, 0xe2, 0x7d, 0x31, 0x8d, 0xc0, 0x7b, 0xb3, 0x6b, 0xd9, 0xea, 0xaf, 0x52, + /*5190:*/ 0x93, 0x35, 0x76, 0x9b, 0xc9, 0xc4, 0x85, 0x08, 0xf7, 0x6c, 0x79, 0xcf, 0x80, 0x8a, 0x03, 0xed, + /*51a0:*/ 0xe5, 0xac, 0x2a, 0x22, 0xdb, 0x37, 0x67, 0xa2, 0xcb, 0xa0, 0xd4, 0x34, 0x04, 0x40, 0xc4, 0x09, + /*51b0:*/ 0xae, 0xde, 0xea, 0xa4, 0xd0, 0x1f, 0x33, 0x3e, 0x00, 0xa0, 0x10, 0x68, 0x1e, 0xe9, 0x95, 0xa9, + /*51c0:*/ 0x91, 0x9d, 0xb1, 0x73, 0xc9, 0xa1, 0x89, 0xce, 0x72, 0x4a, 0x41, 0xc9, 0x35, 0x2c, 0x0f, 0x10, + /*51d0:*/ 0xb0, 0xab, 0xe1, 0x72, 0x48, 0x2f, 0x53, 0x3c, 0x3d, 0x6f, 0x9d, 0x09, 0x82, 0x88, 0x14, 0xee, + /*51e0:*/ 0x38, 0xa9, 0x72, 0x01, 0xfd, 0xd4, 0x24, 0xba, 0x14, 0xb9, 0x90, 0x4a, 0x0c, 0x9a, 0xe4, 0x47, + /*51f0:*/ 0x9f, 0x72, 0xe2, 0x3b, 0x9e, 0x0e, 0x72, 0x43, 0xf4, 0x74, 0xb6, 0x57, 0x53, 0x88, 0x33, 0xef, + /*5200:*/ 0xf5, 0x8a, 0xd1, 0x96, 0x0f, 0x47, 0xb3, 0x98, 0x8a, 0xd5, 0x49, 0x2d, 0x0f, 0xf6, 0x99, 0x53, + /*5210:*/ 0x68, 0xa9, 0x84, 0x38, 0xe6, 0x88, 0x94, 0x27, 0x7f, 0xfa, 0xd4, 0x13, 0x37, 0x2a, 0xe1, 0xfe, + /*5220:*/ 0x8f, 0xe4, 0x56, 0x1b, 0xce, 0xbf, 0x27, 0x8b, 0x62, 0xb3, 0xbb, 0xca, 0xa7, 0x81, 0x8a, 0xb4, + /*5230:*/ 0x4a, 0x73, 0xba, 0x09, 0xcf, 0xab, 0xa1, 0xfa, 0x7b, 0xc6, 0xdb, 0xd4, 0x12, 0x15, 0x89, 0x58, + /*5240:*/ 0xc0, 0xd1, 0xe5, 0x26, 0x3f, 0x99, 0xe0, 0xa6, 0x0f, 0xb6, 0x81, 0xbf, 0x72, 0x53, 0x3a, 0xda, + /*5250:*/ 0x2f, 0x8a, 0xa5, 0x93, 0x6a, 0xc5, 0x89, 0x0c, 0xc6, 0x44, 0xda, 0xed, 0x46, 0x76, 0x7e, 0x9a, + /*5260:*/ 0xd5, 0x96, 0x96, 0x7c, 0xa5, 0x90, 0x80, 0xb4, 0x71, 0x01, 0xdb, 0x08, 0xe6, 0x37, 0x2b, 0x5c, + /*5270:*/ 0x83, 0xca, 0x24, 0x1e, 0x9b, 0xd6, 0x71, 0xe6, 0xfc, 0xae, 0x0f, 0x24, 0xbc, 0x89, 0x13, 0x4f, + /*5280:*/ 0xbc, 0x43, 0x5c, 0x9c, 0x3f, 0x48, 0x94, 0xe0, 0x66, 0xf0, 0x4a, 0x76, 0xa0, 0x08, 0x9a, 0x10, + /*5290:*/ 0x09, 0x8b, 0xa6, 0x2c, 0xc5, 0x9d, 0xd6, 0xc5, 0x45, 0xd1, 0x63, 0x43, 0x44, 0x0f, 0xca, 0x5b, + /*52a0:*/ 0x66, 0x77, 0xa3, 0x44, 0x90, 0x2c, 0xe4, 0xab, 0x28, 0xcb, 0x06, 0xab, 0x98, 0x64, 0x2b, 0xfb, + /*52b0:*/ 0x4a, 0x7b, 0xb5, 0x9b, 0x12, 0xca, 0x30, 0xa7, 0x01, 0x5a, 0x99, 0x53, 0xde, 0x87, 0x24, 0x1a, + /*52c0:*/ 0xa6, 0xec, 0x13, 0xd1, 0x0c, 0xf0, 0x90, 0x41, 0x4c, 0x00, 0x91, 0x86, 0xbb, 0x1e, 0xf0, 0xed, + /*52d0:*/ 0x81, 0xeb, 0xa7, 0x39, 0x6e, 0xfd, 0x88, 0xf8, 0x31, 0x23, 0x73, 0x6c, 0xd0, 0x21, 0xf4, 0x16, + /*52e0:*/ 0xc3, 0x6f, 0xcc, 0xb0, 0x46, 0x78, 0x96, 0x2d, 0x5e, 0xeb, 0x10, 0x68, 0x7b, 0x1e, 0xaa, 0x21, + /*52f0:*/ 0x8e, 0x22, 0x75, 0xbf, 0xaf, 0xbc, 0x00, 0xa2, 0x45, 0x65, 0x5b, 0x6b, 0x32, 0x0e, 0xe7, 0x05, + /*5300:*/ 0xa2, 0xbc, 0xcc, 0x21, 0x5f, 0x32, 0x68, 0xad, 0x74, 0x7e, 0xdd, 0xe5, 0x80, 0x22, 0x0e, 0x30, + /*5310:*/ 0x18, 0xc7, 0x38, 0xd2, 0xec, 0x8d, 0x19, 0xf5, 0xb7, 0xe4, 0x15, 0x8f, 0x44, 0x40, 0x5a, 0xf0, + /*5320:*/ 0x03, 0x91, 0xc7, 0x4c, 0x21, 0xa2, 0xe7, 0xe0, 0x41, 0x22, 0x7c, 0xde, 0xb8, 0xf1, 0xe5, 0x8d, + /*5330:*/ 0x83, 0x56, 0xd5, 0x46, 0x68, 0x9a, 0x33, 0xb7, 0xba, 0xd2, 0x35, 0x62, 0x54, 0x4e, 0x4a, 0x73, + /*5340:*/ 0x3d, 0x52, 0x6d, 0x25, 0x2c, 0x04, 0x03, 0x05, 0x41, 0x01, 0x74, 0xfa, 0xe2, 0x49, 0x48, 0xdc, + /*5350:*/ 0xf7, 0x77, 0x03, 0x33, 0x85, 0xda, 0xa3, 0xb8, 0xef, 0xf8, 0x0d, 0x04, 0x55, 0x85, 0x21, 0xdf, + /*5360:*/ 0xe8, 0xc4, 0x2d, 0x14, 0xe2, 0xf2, 0x55, 0xc8, 0xbe, 0xf0, 0xfd, 0x1b, 0x4f, 0x7b, 0x2c, 0x40, + /*5370:*/ 0x0b, 0x9f, 0x79, 0x98, 0xfa, 0x2d, 0x3a, 0xc5, 0xa2, 0x94, 0xdb, 0xcc, 0x5c, 0x50, 0x0b, 0x24, + /*5380:*/ 0x12, 0x2e, 0xe8, 0x91, 0x87, 0xf5, 0x63, 0xcd, 0x08, 0x75, 0xa9, 0x47, 0x22, 0x81, 0xba, 0xa6, + /*5390:*/ 0xd2, 0x60, 0xc4, 0x39, 0x28, 0xf8, 0x8f, 0x03, 0xc0, 0x1a, 0xac, 0xb0, 0x98, 0xb9, 0x0e, 0x18, + /*53a0:*/ 0x2a, 0xa8, 0x7c, 0xb5, 0xbd, 0xb8, 0x43, 0x20, 0xe2, 0x7e, 0xe5, 0x30, 0x18, 0x76, 0xca, 0xe5, + /*53b0:*/ 0xe0, 0xd6, 0x57, 0xa8, 0x6a, 0xdf, 0x35, 0x4c, 0x35, 0xd4, 0xa2, 0x6b, 0x4a, 0x05, 0xf9, 0xa4, + /*53c0:*/ 0x9c, 0x35, 0x61, 0xff, 0x0b, 0x77, 0x41, 0x99, 0x65, 0xed, 0x56, 0xa4, 0x6e, 0xfb, 0xd6, 0x08, + /*53d0:*/ 0x9e, 0x54, 0x04, 0x1e, 0x02, 0x71, 0xab, 0x2b, 0xed, 0xeb, 0xc4, 0x26, 0x98, 0xfa, 0xc6, 0xd5, + /*53e0:*/ 0xc8, 0x19, 0xb3, 0xa0, 0xe7, 0xb9, 0x11, 0x5b, 0xf2, 0x9b, 0x5d, 0xd8, 0x7c, 0x14, 0x98, 0x07, + /*53f0:*/ 0x5f, 0xf0, 0xcc, 0xad, 0x8d, 0x70, 0x30, 0xb7, 0x87, 0xea, 0x60, 0x0e, 0xcf, 0x06, 0x3d, 0xa5, + /*5400:*/ 0x0d, 0xad, 0x7c, 0x35, 0xe8, 0xc8, 0x7d, 0x72, 0x33, 0xa5, 0x10, 0x14, 0x93, 0xca, 0x95, 0x54, + /*5410:*/ 0xda, 0xb7, 0x18, 0xc1, 0xae, 0xc5, 0x98, 0xc6, 0xe2, 0xc5, 0xd5, 0xac, 0x56, 0x55, 0xcc, 0xd1, + /*5420:*/ 0x04, 0xbe, 0x6c, 0xb8, 0xc9, 0xa7, 0xac, 0x52, 0x4b, 0x91, 0xf5, 0x0c, 0x77, 0xf8, 0x75, 0x79, + /*5430:*/ 0xe2, 0x56, 0xa3, 0xe8, 0xff, 0xf7, 0x22, 0x5a, 0x24, 0x4e, 0x6e, 0xf1, 0xc9, 0xcb, 0xd0, 0xd3, + /*5440:*/ 0xfc, 0x16, 0x82, 0xb5, 0x49, 0x47, 0xfe, 0x27, 0x8a, 0xd5, 0xa3, 0xc0, 0x5c, 0x90, 0xf1, 0xfb, + /*5450:*/ 0xb2, 0xec, 0x3d, 0xb6, 0x01, 0x6e, 0x14, 0x32, 0xc9, 0xcc, 0xfa, 0xfa, 0xc5, 0x17, 0xff, 0xb3, + /*5460:*/ 0x18, 0x6f, 0xd5, 0x04, 0x7a, 0xa7, 0xfc, 0xcf, 0x18, 0x25, 0xe3, 0x69, 0x86, 0x27, 0xeb, 0x16, + /*5470:*/ 0x93, 0xf6, 0x6e, 0x3b, 0xc7, 0x73, 0xf8, 0x83, 0xb7, 0xce, 0x82, 0x8d, 0x4a, 0x0a, 0xcb, 0xe3, + /*5480:*/ 0x07, 0x55, 0x79, 0x8c, 0x18, 0x39, 0x31, 0xdf, 0xca, 0xcb, 0xfd, 0x41, 0x1b, 0xfb, 0xb6, 0x35, + /*5490:*/ 0x09, 0x59, 0xca, 0x90, 0xad, 0x71, 0x46, 0xeb, 0xf6, 0x18, 0xb2, 0xb6, 0x3f, 0xa9, 0x08, 0x03, + /*54a0:*/ 0x57, 0x57, 0xf1, 0x0c, 0x73, 0x26, 0x20, 0x33, 0xef, 0x74, 0xa7, 0xe7, 0x6e, 0x25, 0x9a, 0x7e, + /*54b0:*/ 0x3a, 0x66, 0xf1, 0x97, 0x07, 0xcc, 0x89, 0xea, 0x4d, 0x3c, 0x92, 0x15, 0xd9, 0xe1, 0x99, 0x89, + /*54c0:*/ 0x2c, 0xd4, 0x5a, 0xf3, 0x51, 0x10, 0xa0, 0x54, 0x77, 0x7e, 0x1a, 0x07, 0x02, 0x87, 0x0e, 0xb8, + /*54d0:*/ 0x87, 0x11, 0xce, 0xd2, 0xd8, 0x84, 0x30, 0x2a, 0xe7, 0x08, 0x49, 0x8b, 0x7c, 0xcb, 0xaf, 0x43, + /*54e0:*/ 0x17, 0x15, 0x17, 0xa1, 0xa0, 0xa2, 0x74, 0x4c, 0xa9, 0xcc, 0xe0, 0x26, 0xd5, 0xc1, 0xc3, 0x4a, + /*54f0:*/ 0x69, 0x0c, 0x89, 0x52, 0xcd, 0xae, 0x47, 0xd7, 0x6e, 0x0c, 0xc5, 0x62, 0x6e, 0xaa, 0x0e, 0x08, + /*5500:*/ 0x40, 0x32, 0x21, 0x50, 0x6c, 0xd8, 0xb7, 0xd6, 0xc7, 0xd3, 0x3f, 0xae, 0x4f, 0x0d, 0xba, 0xaa, + /*5510:*/ 0x37, 0x17, 0xbd, 0x13, 0x0a, 0xcc, 0x12, 0x3d, 0x6b, 0xab, 0x12, 0xc9, 0xf4, 0xa6, 0xe9, 0x64, + /*5520:*/ 0x73, 0xa2, 0xd6, 0xe0, 0x1f, 0x8d, 0xd7, 0xab, 0x95, 0x4d, 0x8d, 0x25, 0xca, 0xe8, 0x9f, 0xca, + /*5530:*/ 0xf6, 0x54, 0x4a, 0xbf, 0x1d, 0xeb, 0xf6, 0x39, 0x20, 0xaa, 0x2c, 0xc9, 0x3c, 0xa7, 0x0c, 0x4b, + /*5540:*/ 0x85, 0x92, 0x23, 0x48, 0xed, 0x7c, 0x55, 0x0a, 0xbb, 0x4f, 0x65, 0xac, 0x6d, 0x23, 0x4c, 0x5e, + /*5550:*/ 0xf9, 0x9e, 0xa7, 0x76, 0x4d, 0xdd, 0xfb, 0x52, 0x68, 0x75, 0x1d, 0xab, 0xc9, 0x53, 0xa8, 0xfc, + /*5560:*/ 0x39, 0xcf, 0xea, 0x93, 0x90, 0x50, 0x95, 0x3e, 0x91, 0x4a, 0xac, 0xc7, 0x80, 0x02, 0x84, 0x1a, + /*5570:*/ 0x6a, 0xf3, 0x61, 0xad, 0xca, 0x78, 0x09, 0x67, 0x8a, 0x41, 0x79, 0xda, 0x5b, 0x8f, 0x79, 0xc2, + /*5580:*/ 0xf4, 0x73, 0x26, 0xb8, 0x8c, 0xf8, 0x64, 0x7f, 0xba, 0x25, 0xa7, 0x90, 0xf5, 0x49, 0xd6, 0x5f, + /*5590:*/ 0x4c, 0xf4, 0x18, 0x5d, 0xe0, 0x20, 0x61, 0xc5, 0x59, 0x69, 0x89, 0x48, 0x29, 0xbb, 0x98, 0xcd, + /*55a0:*/ 0x92, 0x42, 0x80, 0x91, 0xc4, 0x35, 0x24, 0x7d, 0x70, 0x35, 0x23, 0x90, 0xa4, 0x19, 0x2d, 0x8a, + /*55b0:*/ 0xf3, 0x7b, 0x89, 0x1b, 0xb9, 0xe2, 0x4e, 0x12, 0xa5, 0x41, 0x7e, 0x4e, 0x84, 0xb7, 0x0d, 0x6b, + /*55c0:*/ 0xf2, 0xb6, 0xb8, 0x29, 0x1a, 0x85, 0xa3, 0xc5, 0x00, 0x71, 0xf4, 0xad, 0x4c, 0x62, 0x75, 0xc5, + /*55d0:*/ 0xa8, 0xd1, 0xad, 0xcd, 0x4e, 0x62, 0xd5, 0x37, 0xf0, 0xaf, 0x4c, 0xdd, 0x31, 0x83, 0x92, 0x81, + /*55e0:*/ 0xb9, 0x11, 0x20, 0xcc, 0x4c, 0x4f, 0xff, 0x3e, 0x5b, 0x68, 0xb9, 0xbf, 0x3b, 0x1b, 0x8f, 0xdf, + /*55f0:*/ 0xd7, 0x13, 0x13, 0x49, 0x3f, 0x6e, 0x00, 0x87, 0xae, 0x8d, 0x9d, 0x00, 0x66, 0x29, 0x30, 0x6e, + /*5600:*/ 0x65, 0x28, 0x09, 0x87, 0xa4, 0xf7, 0xde, 0xf8, 0x04, 0xba, 0x20, 0x0c, 0xb0, 0x68, 0x13, 0xfb, + /*5610:*/ 0x73, 0x66, 0x82, 0x04, 0xea, 0xd6, 0x7b, 0x89, 0x43, 0x52, 0x08, 0x3a, 0x37, 0x17, 0x56, 0xa3, + /*5620:*/ 0x63, 0xbd, 0x01, 0x82, 0x9c, 0xeb, 0x44, 0x3c, 0x01, 0xf9, 0x77, 0x64, 0x0a, 0x18, 0xff, 0x50, + /*5630:*/ 0xe5, 0x15, 0x69, 0xa3, 0x2d, 0xcc, 0xb0, 0xba, 0xb1, 0xef, 0x78, 0x3c, 0x07, 0x19, 0xfd, 0x7a, + /*5640:*/ 0xd6, 0x91, 0x66, 0x35, 0xd1, 0xef, 0x8e, 0xc2, 0xf6, 0xb0, 0xfe, 0x5d, 0x2c, 0x7e, 0x28, 0x77, + /*5650:*/ 0x1d, 0xc6, 0x3e, 0x5f, 0x58, 0x11, 0x3f, 0x72, 0xf6, 0x1e, 0x59, 0x88, 0xcf, 0x16, 0x52, 0xc9, + /*5660:*/ 0x7f, 0x31, 0xce, 0x87, 0x22, 0x3b, 0x81, 0xab, 0x52, 0xb5, 0x22, 0x67, 0x56, 0xdf, 0xe8, 0xed, + /*5670:*/ 0x72, 0xe5, 0xff, 0xcf, 0xa7, 0xf1, 0xa3, 0xb7, 0x97, 0x8e, 0x9c, 0x56, 0x5b, 0x0c, 0x0c, 0x5a, + /*5680:*/ 0x2e, 0x08, 0xa1, 0xee, 0xcb, 0xd2, 0xc9, 0x26, 0xa8, 0x38, 0xd4, 0x94, 0x8e, 0x47, 0xb0, 0x69, + /*5690:*/ 0x0d, 0x5e, 0xbb, 0xc0, 0x53, 0x8a, 0xc8, 0x98, 0x7a, 0x9f, 0xa6, 0x5c, 0x8a, 0x6f, 0x87, 0xbf, + /*56a0:*/ 0xd2, 0xae, 0x7e, 0x57, 0xd5, 0xc5, 0xf3, 0x7b, 0xcb, 0x04, 0x27, 0xd3, 0x95, 0x43, 0x28, 0x8d, + /*56b0:*/ 0x6f, 0xe5, 0xa4, 0xaa, 0x88, 0x52, 0xea, 0x6a, 0xa7, 0xbf, 0x18, 0x15, 0xd5, 0x0d, 0x57, 0xf1, + /*56c0:*/ 0xe2, 0x8e, 0xfc, 0x86, 0x19, 0xf1, 0xce, 0xee, 0xab, 0x7e, 0x56, 0xfb, 0xac, 0xe8, 0x20, 0xfb, + /*56d0:*/ 0x77, 0x43, 0x09, 0xf5, 0xca, 0xf6, 0xd1, 0x80, 0x3d, 0xed, 0xd1, 0x8c, 0x67, 0xc1, 0x6d, 0x99, + /*56e0:*/ 0x76, 0xb3, 0xcd, 0xc0, 0x22, 0xd2, 0xe3, 0xff, 0xe6, 0x00, 0xff, 0xe2, 0x48, 0xdc, 0x73, 0xc5, + /*56f0:*/ 0x10, 0x1d, 0x32, 0x90, 0x42, 0xfd, 0xe5, 0x2c, 0x94, 0x1a, 0x9d, 0x7f, 0x11, 0x1e, 0x7a, 0xf6, + /*5700:*/ 0xba, 0x50, 0x22, 0x08, 0xc5, 0x38, 0xb8, 0x15, 0xb7, 0x80, 0x50, 0x45, 0x1d, 0xe8, 0x4d, 0x9f, + /*5710:*/ 0xd5, 0xbc, 0x45, 0xd6, 0x83, 0x3d, 0x59, 0xf3, 0x1e, 0x33, 0x60, 0x83, 0x91, 0xb8, 0x0e, 0xb9, + /*5720:*/ 0x16, 0x6c, 0x57, 0xaf, 0x4d, 0x91, 0x84, 0x0c, 0xe4, 0x0f, 0x25, 0xdc, 0xed, 0x09, 0x73, 0xc9, + /*5730:*/ 0xcf, 0x6f, 0x96, 0x37, 0x9f, 0xf0, 0xd8, 0xee, 0xbb, 0x55, 0x9d, 0xf1, 0xa8, 0xfd, 0xbd, 0x93, + /*5740:*/ 0xb6, 0xc5, 0x43, 0xf3, 0xa6, 0x0f, 0x9d, 0x33, 0x04, 0x6b, 0x3f, 0xd1, 0x73, 0xd4, 0xaf, 0xe4, + /*5750:*/ 0x23, 0xf8, 0xc5, 0xa1, 0xbb, 0x86, 0x42, 0x7e, 0x14, 0x15, 0x32, 0xe0, 0xe9, 0x9c, 0x8e, 0xa1, + /*5760:*/ 0x4c, 0xee, 0x6c, 0x0f, 0xb3, 0xd2, 0x1c, 0xc9, 0x52, 0x14, 0x06, 0x06, 0xb5, 0x38, 0x77, 0x5f, + /*5770:*/ 0x4e, 0xa0, 0x32, 0xe6, 0x4d, 0x51, 0x67, 0x44, 0x8f, 0xb2, 0x6e, 0x57, 0x63, 0xb1, 0x19, 0x20, + /*5780:*/ 0xd3, 0x04, 0x3c, 0xf3, 0x37, 0xc5, 0x86, 0x44, 0xec, 0xf0, 0x20, 0xe1, 0x52, 0xeb, 0xe7, 0xeb, + /*5790:*/ 0x17, 0x87, 0xa1, 0x6e, 0xa9, 0xe5, 0xae, 0x75, 0x3d, 0x3c, 0x44, 0x6d, 0x20, 0x76, 0xc5, 0x84, + /*57a0:*/ 0x7e, 0x45, 0xf4, 0x57, 0x85, 0x5c, 0x41, 0x4b, 0x45, 0xf5, 0x8f, 0x89, 0xab, 0x01, 0xce, 0x9a, + /*57b0:*/ 0xe2, 0x47, 0xcb, 0xe6, 0x14, 0x14, 0x0e, 0x23, 0xb8, 0xa1, 0x15, 0x4b, 0x67, 0xfe, 0xf5, 0x38, + /*57c0:*/ 0x48, 0x9b, 0x48, 0x3e, 0x60, 0xd2, 0x9e, 0x86, 0x60, 0xa1, 0xf1, 0x31, 0x8c, 0x95, 0x93, 0xfc, + /*57d0:*/ 0xd4, 0x26, 0xb9, 0xd5, 0x36, 0xac, 0x57, 0x03, 0x86, 0xac, 0xcb, 0xb7, 0x75, 0x66, 0xda, 0x48, + /*57e0:*/ 0x74, 0x17, 0x12, 0x22, 0xd1, 0xf0, 0x9f, 0xed, 0x50, 0xcf, 0xea, 0xc5, 0xce, 0x94, 0x68, 0x81, + /*57f0:*/ 0x2a, 0x0e, 0xf3, 0x48, 0xe3, 0x03, 0xf0, 0xe4, 0x4e, 0x95, 0xfa, 0xc0, 0xda, 0x35, 0x41, 0x23, + /*5800:*/ 0x0d, 0x8b, 0xcc, 0xff, 0x25, 0xe5, 0x18, 0x88, 0x25, 0x20, 0x0c, 0xa5, 0x32, 0xae, 0xfe, 0x89, + /*5810:*/ 0xaa, 0xc6, 0xa3, 0x47, 0x0e, 0xc8, 0x8a, 0x83, 0xd9, 0x2a, 0x97, 0x85, 0xbf, 0xe5, 0x9f, 0xe6, + /*5820:*/ 0x0e, 0x79, 0x21, 0x25, 0xc2, 0x99, 0x81, 0x28, 0x70, 0x32, 0x23, 0xa3, 0x4d, 0x8a, 0x2d, 0x97, + /*5830:*/ 0xbb, 0x7d, 0xa7, 0x9a, 0xee, 0xb6, 0xed, 0xda, 0x09, 0x5f, 0x9f, 0xfc, 0x1a, 0x27, 0xd0, 0x94, + /*5840:*/ 0xb7, 0x83, 0x29, 0x59, 0x46, 0x63, 0x01, 0xc9, 0x10, 0xbe, 0x37, 0xf8, 0xac, 0x4f, 0x84, 0x10, + /*5850:*/ 0x8a, 0x8e, 0x08, 0x99, 0x13, 0x29, 0x0e, 0x8b, 0xd3, 0xd4, 0x89, 0x8e, 0xd6, 0xe7, 0x1c, 0x47, + /*5860:*/ 0xbb, 0x24, 0x6f, 0x25, 0x74, 0x9c, 0x08, 0x85, 0x49, 0x5b, 0x15, 0x25, 0xc2, 0x09, 0xb4, 0x33, + /*5870:*/ 0xe3, 0xc3, 0xe9, 0xa9, 0xa2, 0xa4, 0x38, 0x7f, 0x81, 0xa1, 0x16, 0xcb, 0x28, 0x42, 0xf2, 0x9f, + /*5880:*/ 0x37, 0x48, 0x73, 0xa2, 0xcf, 0x40, 0x4b, 0xea, 0x8f, 0x86, 0xf0, 0x74, 0x54, 0xe9, 0xc8, 0xa2, + /*5890:*/ 0x62, 0x9a, 0x6b, 0x5a, 0x82, 0x02, 0xf3, 0x63, 0x67, 0xdd, 0xb7, 0x81, 0xe6, 0xa9, 0x98, 0x44, + /*58a0:*/ 0xb6, 0xb1, 0x63, 0xb7, 0x18, 0xb9, 0x54, 0x10, 0xac, 0x44, 0x97, 0x03, 0x92, 0x11, 0xfe, 0x84, + /*58b0:*/ 0xeb, 0x60, 0x6f, 0x15, 0xf5, 0x61, 0x87, 0x3e, 0x5b, 0x27, 0x87, 0x3b, 0xaf, 0x6b, 0xa9, 0x65, + /*58c0:*/ 0x42, 0x27, 0xe5, 0x0d, 0xba, 0x83, 0xe1, 0xf2, 0x7c, 0xda, 0x1b, 0x1e, 0x7b, 0x12, 0xc5, 0x36, + /*58d0:*/ 0x6a, 0x4b, 0x10, 0x65, 0xa3, 0xfd, 0xd6, 0xf9, 0x5b, 0xf7, 0xd6, 0x93, 0xa4, 0x01, 0x64, 0xf0, + /*58e0:*/ 0x10, 0x10, 0x9b, 0x94, 0xa7, 0x16, 0x1c, 0x34, 0xc0, 0x3d, 0x33, 0xba, 0x46, 0x41, 0x5e, 0x3c, + /*58f0:*/ 0xdf, 0xaf, 0xab, 0x39, 0x94, 0x36, 0xe0, 0x7c, 0x83, 0x80, 0x92, 0xa9, 0x3b, 0xb1, 0x4e, 0x1d, + /*5900:*/ 0xff, 0x97, 0x02, 0x0d, 0x7b, 0x57, 0x23, 0x1f, 0x85, 0x41, 0xc9, 0xdd, 0x83, 0x7b, 0x01, 0x97, + /*5910:*/ 0xe0, 0x28, 0x15, 0x91, 0x49, 0x5c, 0x7f, 0xaf, 0xf1, 0x40, 0xac, 0x45, 0xf7, 0xf3, 0x26, 0x37, + /*5920:*/ 0xc5, 0xd6, 0xa6, 0xc5, 0xe1, 0x70, 0xd1, 0xca, 0x0a, 0x33, 0x54, 0x33, 0xe6, 0x7f, 0xf2, 0xb0, + /*5930:*/ 0xd5, 0x09, 0xb8, 0xe0, 0x7f, 0x54, 0x81, 0x7f, 0xd3, 0x14, 0x1a, 0xbf, 0xeb, 0x1b, 0xd5, 0xa7, + /*5940:*/ 0x81, 0x5c, 0xa4, 0x0a, 0xc7, 0x05, 0x33, 0xce, 0x97, 0xf4, 0xd8, 0x74, 0xac, 0xe1, 0x90, 0x3f, + /*5950:*/ 0xc3, 0x8d, 0x5e, 0xe2, 0x43, 0xda, 0x55, 0xbe, 0x3b, 0x12, 0x9a, 0xfc, 0xb8, 0x7f, 0x9e, 0xd1, + /*5960:*/ 0x36, 0x6e, 0x2b, 0x89, 0xe3, 0x49, 0x9b, 0x5c, 0xa8, 0xe6, 0xc4, 0xb6, 0x9d, 0xea, 0xe4, 0x71, + /*5970:*/ 0x19, 0x15, 0x7e, 0x4a, 0x28, 0xa9, 0x11, 0x31, 0xc7, 0xb2, 0xf7, 0x16, 0x38, 0xb5, 0x99, 0x92, + /*5980:*/ 0xfe, 0x9a, 0xa1, 0x08, 0xfd, 0xbc, 0xea, 0x14, 0x43, 0xa8, 0xc3, 0xc7, 0xdb, 0xae, 0x7f, 0xc4, + /*5990:*/ 0x26, 0x1d, 0x75, 0x6b, 0xbd, 0x9e, 0x46, 0x07, 0x2c, 0x3c, 0x96, 0xef, 0x54, 0xfa, 0xb7, 0x64, + /*59a0:*/ 0x3a, 0x36, 0xf6, 0xcf, 0x0e, 0xe4, 0xd8, 0x45, 0x3a, 0x11, 0x68, 0x05, 0xed, 0xf0, 0xf7, 0xe8, + /*59b0:*/ 0x39, 0x57, 0xa8, 0x9c, 0x37, 0xc9, 0x04, 0x3d, 0xf8, 0x15, 0xf6, 0xcf, 0x8a, 0x11, 0x84, 0xcd, + /*59c0:*/ 0x5f, 0xe7, 0xb9, 0x23, 0xbb, 0xab, 0xe2, 0xc5, 0x82, 0xef, 0xd4, 0x08, 0x42, 0x15, 0xcd, 0x55, + /*59d0:*/ 0xfa, 0x6c, 0x50, 0x4e, 0x53, 0xfc, 0x47, 0x9d, 0x7d, 0xdc, 0x5b, 0xda, 0x05, 0x64, 0xfa, 0xcf, + /*59e0:*/ 0x41, 0x88, 0xd1, 0xbd, 0x3f, 0x15, 0xcd, 0xba, 0xb1, 0x67, 0xf6, 0x7a, 0x82, 0x76, 0x1a, 0x64, + /*59f0:*/ 0xf7, 0x75, 0xfa, 0x71, 0xdf, 0x9a, 0xf9, 0x05, 0xb2, 0x30, 0x5a, 0x74, 0x53, 0x3d, 0xd8, 0x97, + /*5a00:*/ 0x7c, 0xdf, 0xd8, 0xda, 0x91, 0xa2, 0x0f, 0xed, 0x0b, 0x08, 0x95, 0x4c, 0x90, 0x13, 0x24, 0xd3, + /*5a10:*/ 0xb0, 0x63, 0xae, 0x46, 0x86, 0x56, 0x4c, 0x1a, 0x36, 0x41, 0x34, 0x2f, 0x30, 0x9e, 0xf0, 0x91, + /*5a20:*/ 0x9b, 0x51, 0x02, 0x8a, 0x70, 0x71, 0xfd, 0xf8, 0x19, 0xc2, 0xb3, 0xaf, 0x5e, 0x65, 0xd2, 0xca, + /*5a30:*/ 0xcc, 0x80, 0x2f, 0xcc, 0xd4, 0xe9, 0xce, 0xa0, 0x6d, 0x38, 0x5e, 0x00, 0x02, 0x2d, 0xcc, 0x4e, + /*5a40:*/ 0x05, 0xe5, 0x4f, 0xeb, 0x7d, 0x94, 0x74, 0x6e, 0xaa, 0xa5, 0xc0, 0xce, 0xaa, 0xd6, 0xed, 0xcf, + /*5a50:*/ 0x84, 0xdd, 0x44, 0xa6, 0xc8, 0x01, 0x2f, 0x30, 0xd0, 0x1a, 0xa1, 0x14, 0x83, 0x82, 0xe2, 0x6a, + /*5a60:*/ 0x6e, 0x0a, 0x42, 0xf6, 0x14, 0xbc, 0xd8, 0xa4, 0x44, 0x67, 0x29, 0x92, 0xaf, 0x0b, 0x8b, 0x6a, + /*5a70:*/ 0xa5, 0x45, 0x7f, 0xd3, 0x46, 0xc9, 0xec, 0x29, 0xa9, 0x3d, 0xa3, 0xd2, 0x56, 0x5f, 0xd8, 0x37, + /*5a80:*/ 0x2d, 0xf0, 0x07, 0x91, 0xe2, 0xc9, 0x78, 0xbe, 0x4c, 0x00, 0x5a, 0xda, 0x89, 0xc7, 0x96, 0xd6, + /*5a90:*/ 0x67, 0x1a, 0x33, 0x98, 0x9c, 0x0a, 0x96, 0x82, 0x44, 0x07, 0x9d, 0x08, 0x39, 0x83, 0x5d, 0xae, + /*5aa0:*/ 0x03, 0xa7, 0x36, 0xc6, 0xb1, 0x15, 0xd2, 0x80, 0x97, 0xbb, 0x6e, 0x93, 0x22, 0x99, 0xc1, 0x12, + /*5ab0:*/ 0xd9, 0x63, 0xa4, 0xa6, 0xc0, 0x99, 0x53, 0xeb, 0x9b, 0x38, 0x72, 0xe0, 0x3f, 0x2d, 0xb3, 0xd1, + /*5ac0:*/ 0x15, 0xef, 0x6f, 0xfe, 0x36, 0x11, 0xfb, 0x7a, 0xa9, 0x53, 0x44, 0x76, 0xeb, 0xfa, 0x29, 0x75, + /*5ad0:*/ 0xc0, 0xd9, 0xbf, 0x98, 0x44, 0xcb, 0x57, 0x0f, 0xa6, 0x1e, 0xab, 0xff, 0xa2, 0x1d, 0x0c, 0x70, + /*5ae0:*/ 0x2c, 0x67, 0x03, 0x82, 0x3f, 0x0e, 0x3f, 0x0b, 0xad, 0xa4, 0x42, 0x72, 0xf7, 0xbf, 0x6d, 0x6e, + /*5af0:*/ 0xf5, 0x58, 0x82, 0xdd, 0xbd, 0xd2, 0xc8, 0x1a, 0xa0, 0xf9, 0xb7, 0x27, 0x14, 0x7b, 0xe2, 0x42, + /*5b00:*/ 0xa1, 0xe2, 0xcd, 0x52, 0x65, 0xee, 0x08, 0x02, 0x2c, 0x8f, 0x8d, 0x2f, 0x6c, 0x5f, 0xa2, 0x1c, + /*5b10:*/ 0xde, 0x77, 0xa7, 0xc7, 0x4d, 0xa3, 0x87, 0x92, 0x9c, 0xb1, 0xf3, 0xcc, 0x5a, 0x8e, 0x9a, 0x98, + /*5b20:*/ 0xb9, 0x7e, 0xee, 0x20, 0x57, 0x1a, 0x27, 0x80, 0xda, 0x66, 0x34, 0xb7, 0xa6, 0xea, 0x15, 0xcd, + /*5b30:*/ 0x8f, 0x47, 0x05, 0xb6, 0x86, 0xd7, 0xb9, 0x21, 0x27, 0x9c, 0x47, 0x0e, 0x4b, 0x80, 0x10, 0x8d, + /*5b40:*/ 0x06, 0x02, 0xe8, 0x42, 0x34, 0x08, 0x67, 0x1e, 0x77, 0xd4, 0xdc, 0x61, 0xd7, 0xe5, 0xad, 0xb9, + /*5b50:*/ 0x3d, 0xf9, 0x16, 0xdf, 0x5f, 0x12, 0xd9, 0x7d, 0xaa, 0xce, 0x5d, 0x5c, 0x4f, 0xe4, 0x5d, 0x28, + /*5b60:*/ 0xd0, 0x3f, 0xea, 0xb8, 0xcc, 0xc9, 0xbe, 0x07, 0xe3, 0x27, 0x97, 0x35, 0x70, 0xb3, 0xac, 0xd4, + /*5b70:*/ 0x7a, 0xc7, 0xff, 0xc4, 0x44, 0xf8, 0x36, 0xd7, 0xb8, 0x5c, 0x7b, 0xcc, 0xd5, 0xac, 0xef, 0x16, + /*5b80:*/ 0xd4, 0x3e, 0x1c, 0xf7, 0x47, 0xa1, 0xf9, 0xeb, 0xb4, 0xd2, 0x7d, 0x0a, 0x03, 0x61, 0xb4, 0xe4, + /*5b90:*/ 0x2c, 0x3c, 0x05, 0xe6, 0x87, 0xc2, 0x07, 0xd7, 0xce, 0xc9, 0xb6, 0x98, 0xa7, 0xc8, 0x18, 0x9f, + /*5ba0:*/ 0x12, 0x4b, 0x50, 0x52, 0xfc, 0xc7, 0xd1, 0x70, 0xff, 0x06, 0xe8, 0x5b, 0xbf, 0xce, 0xf4, 0xc1, + /*5bb0:*/ 0xa0, 0xbd, 0x97, 0x8d, 0x8c, 0x3a, 0xe3, 0xf6, 0x87, 0x3b, 0x37, 0xdd, 0xb0, 0x53, 0x08, 0x25, + /*5bc0:*/ 0xbb, 0x18, 0x46, 0xf5, 0x0b, 0x39, 0x3f, 0xe7, 0x62, 0x7e, 0x29, 0x87, 0x70, 0xca, 0xa8, 0x35, + /*5bd0:*/ 0xfc, 0x36, 0xbf, 0x69, 0x24, 0xe0, 0x11, 0x7e, 0x9c, 0x09, 0x97, 0xdb, 0x83, 0x22, 0x3a, 0xa5, + /*5be0:*/ 0x5e, 0x05, 0xe7, 0x31, 0xaa, 0x44, 0x4c, 0x9b, 0xd5, 0xcc, 0x7e, 0x78, 0x86, 0xa6, 0x4b, 0x59, + /*5bf0:*/ 0x12, 0xa4, 0x98, 0xab, 0x18, 0xf6, 0x34, 0x4d, 0xc8, 0xa5, 0xdc, 0xa1, 0x96, 0x30, 0x8c, 0xed, + /*5c00:*/ 0xe6, 0x68, 0x6f, 0x90, 0xa4, 0xd3, 0x25, 0x5a, 0x35, 0x89, 0x94, 0x66, 0x0e, 0x7c, 0x91, 0x84, + /*5c10:*/ 0x89, 0x3a, 0xb6, 0x7e, 0x34, 0x0f, 0x05, 0x6a, 0x82, 0x9a, 0xbc, 0x13, 0x01, 0xed, 0x43, 0xde, + /*5c20:*/ 0xdb, 0x16, 0xf3, 0x5b, 0xa9, 0xad, 0xca, 0x66, 0xb9, 0x73, 0x61, 0xd8, 0xb2, 0x9c, 0x61, 0xfe, + /*5c30:*/ 0xe7, 0x2f, 0xad, 0xec, 0x9d, 0x96, 0xe3, 0xd9, 0x35, 0xb2, 0xf9, 0x3a, 0xf8, 0xf7, 0x6f, 0x9d, + /*5c40:*/ 0x2a, 0xcf, 0x0e, 0x72, 0x15, 0x9d, 0xe2, 0x74, 0x35, 0x82, 0x26, 0x48, 0x68, 0x66, 0x2c, 0x33, + /*5c50:*/ 0x82, 0x46, 0x33, 0x66, 0xa3, 0xf3, 0xbb, 0x01, 0xfe, 0xf5, 0x1b, 0x49, 0xd2, 0xdf, 0x42, 0xb3, + /*5c60:*/ 0x59, 0x5b, 0x7f, 0xee, 0xbe, 0x16, 0xf0, 0x17, 0x50, 0xf8, 0xc0, 0xfb, 0x99, 0xd6, 0x7f, 0x9c, + /*5c70:*/ 0x6c, 0x92, 0x83, 0x53, 0x32, 0x0e, 0x87, 0x26, 0x32, 0xd7, 0x5e, 0x9b, 0x2c, 0x93, 0x01, 0xa4, + /*5c80:*/ 0x83, 0x2d, 0x78, 0x58, 0x8c, 0x34, 0x8a, 0xdd, 0x94, 0xec, 0xe3, 0x61, 0x05, 0x57, 0xaa, 0xcf, + /*5c90:*/ 0x63, 0x63, 0x98, 0x3e, 0xc3, 0x6c, 0xce, 0x7d, 0x40, 0xbe, 0x23, 0x07, 0x13, 0x61, 0x21, 0x96, + /*5ca0:*/ 0x0f, 0x78, 0x5d, 0x6e, 0x84, 0x24, 0x01, 0x16, 0x5b, 0x52, 0x41, 0x64, 0x35, 0xe6, 0xb5, 0x8f, + /*5cb0:*/ 0xeb, 0xfa, 0x3b, 0xc1, 0x04, 0xaf, 0x39, 0x21, 0x13, 0xc8, 0x63, 0x6b, 0xab, 0xb6, 0x42, 0x5f, + /*5cc0:*/ 0xb5, 0x54, 0x76, 0x62, 0x47, 0xed, 0x55, 0x62, 0x81, 0x3e, 0xea, 0xdb, 0xf3, 0xcd, 0x81, 0x6c, + /*5cd0:*/ 0xa5, 0x7b, 0xaf, 0x77, 0x22, 0xe8, 0x13, 0x66, 0xf2, 0x50, 0xc1, 0xc9, 0xb0, 0xae, 0x99, 0x08, + /*5ce0:*/ 0xea, 0x4c, 0x17, 0xbe, 0x80, 0xb4, 0x66, 0x41, 0x27, 0xdb, 0x7f, 0xc8, 0xe1, 0x79, 0xc7, 0x48, + /*5cf0:*/ 0xc9, 0xc4, 0x69, 0x8d, 0x5d, 0x50, 0x6e, 0x82, 0xdc, 0x96, 0xa2, 0x2b, 0x2d, 0xc0, 0xf7, 0x0b, + /*5d00:*/ 0x00, 0xe9, 0xab, 0x36, 0xe4, 0xe3, 0xb8, 0xd6, 0xa7, 0xe8, 0x8c, 0xe5, 0x84, 0x72, 0xa6, 0xfa, + /*5d10:*/ 0xf5, 0xbf, 0xd6, 0xec, 0xe9, 0x65, 0x6f, 0x7b, 0xcc, 0x6c, 0x43, 0x77, 0x04, 0x63, 0x84, 0x25, + /*5d20:*/ 0x27, 0xc7, 0x58, 0xe4, 0xa9, 0x34, 0x68, 0x57, 0xeb, 0xe4, 0x5f, 0x24, 0x5e, 0xeb, 0x9b, 0x3c, + /*5d30:*/ 0x69, 0x4b, 0xa1, 0xfc, 0x33, 0xbf, 0x4a, 0xd9, 0x24, 0x77, 0x2c, 0x07, 0xd5, 0x32, 0xe6, 0x31, + /*5d40:*/ 0xf3, 0xa8, 0xc9, 0x36, 0xf0, 0x9a, 0x89, 0xa7, 0xce, 0x85, 0x98, 0x08, 0x8a, 0x95, 0x20, 0x0d, + /*5d50:*/ 0x94, 0xf3, 0xb0, 0x1b, 0x15, 0x27, 0xde, 0xa9, 0xb1, 0xfc, 0x89, 0xdc, 0x61, 0x25, 0x8b, 0xd4, + /*5d60:*/ 0x6a, 0xff, 0x02, 0x30, 0xf8, 0xff, 0x60, 0x0b, 0x43, 0x2a, 0x46, 0x27, 0x2b, 0xad, 0x91, 0x93, + /*5d70:*/ 0x19, 0x7d, 0x56, 0x0b, 0x47, 0xd0, 0x52, 0xa1, 0x34, 0x6b, 0xbd, 0xb1, 0x3d, 0x66, 0x51, 0x25, + /*5d80:*/ 0x00, 0xf9, 0xa0, 0x3e, 0x7f, 0xd5, 0xc3, 0xb4, 0x32, 0x63, 0x30, 0x6b, 0x41, 0xe6, 0x53, 0x7c, + /*5d90:*/ 0x02, 0xd9, 0xa2, 0xa9, 0xb4, 0x97, 0xc2, 0x4c, 0x2f, 0x68, 0xd0, 0x8e, 0x72, 0x0f, 0xac, 0x57, + /*5da0:*/ 0x1d, 0xf2, 0x6f, 0xe6, 0x6f, 0x5b, 0x4a, 0x7e, 0xf6, 0x77, 0x77, 0x0a, 0xac, 0x58, 0x32, 0x39, + /*5db0:*/ 0x61, 0xef, 0x09, 0x44, 0x85, 0x3f, 0x25, 0x99, 0x86, 0x97, 0x0a, 0x20, 0x28, 0x1d, 0xb9, 0x82, + /*5dc0:*/ 0x2b, 0x99, 0x4a, 0x6e, 0x54, 0x3b, 0xe8, 0x12, 0xde, 0xfb, 0xc7, 0x97, 0xa5, 0x23, 0x79, 0xed, + /*5dd0:*/ 0x4d, 0x8f, 0xca, 0x7f, 0xb6, 0x25, 0x08, 0x97, 0x50, 0xda, 0x73, 0xe0, 0x8f, 0xa8, 0xc5, 0xce, + /*5de0:*/ 0xa2, 0xb8, 0x2f, 0x5f, 0x10, 0xce, 0xb0, 0xd6, 0x90, 0x2a, 0x84, 0x90, 0x9e, 0xaf, 0x7c, 0x5c, + /*5df0:*/ 0xfb, 0x69, 0xe9, 0x33, 0x50, 0x43, 0xf5, 0x37, 0x75, 0x82, 0x30, 0xd0, 0x83, 0x7f, 0x6b, 0xe5, + /*5e00:*/ 0x93, 0x03, 0xce, 0xca, 0x41, 0x5c, 0x91, 0x31, 0x15, 0x00, 0x5c, 0x88, 0xa4, 0xcd, 0xd1, 0xb1, + /*5e10:*/ 0x11, 0x12, 0x35, 0x1c, 0xbf, 0xb7, 0xf5, 0x76, 0xf6, 0x78, 0xe4, 0x31, 0x03, 0xce, 0xbe, 0x43, + /*5e20:*/ 0xae, 0xc0, 0x32, 0x28, 0xc1, 0xf1, 0x67, 0x2b, 0x00, 0x99, 0xc5, 0xb5, 0x54, 0xe2, 0x67, 0x3b, + /*5e30:*/ 0xf0, 0x2f, 0x7f, 0x71, 0xf1, 0x56, 0xe0, 0x2c, 0x4c, 0x38, 0x88, 0x12, 0x28, 0x1c, 0x4c, 0x98, + /*5e40:*/ 0xa6, 0xf7, 0x2e, 0xbc, 0x68, 0x16, 0xf4, 0x79, 0x65, 0x91, 0x6c, 0x5e, 0xe2, 0x3e, 0x10, 0x9e, + /*5e50:*/ 0x88, 0xab, 0xb3, 0x14, 0x0e, 0x25, 0x6e, 0xd3, 0x0c, 0x63, 0x1c, 0xa5, 0x18, 0xc5, 0x9c, 0x8b, + /*5e60:*/ 0x12, 0x9e, 0x2c, 0xbe, 0x37, 0x59, 0x2c, 0x4c, 0xfb, 0x2b, 0xec, 0x4a, 0x5b, 0x6b, 0x69, 0xf0, + /*5e70:*/ 0xcc, 0x22, 0x77, 0x5d, 0xa1, 0xe0, 0x25, 0x16, 0x11, 0x23, 0x76, 0x8d, 0xbb, 0x9d, 0xea, 0x19, + /*5e80:*/ 0x40, 0x73, 0x68, 0x9b, 0x72, 0x63, 0x0c, 0xe6, 0x87, 0x58, 0x8f, 0x6d, 0x5a, 0xd6, 0xf2, 0xbc, + /*5e90:*/ 0x82, 0x57, 0x50, 0x6e, 0x35, 0x92, 0x4a, 0x88, 0x5e, 0x26, 0x50, 0xe7, 0x93, 0x8e, 0x41, 0xe4, + /*5ea0:*/ 0xdd, 0xe7, 0xdf, 0x64, 0xfa, 0x3b, 0x94, 0xea, 0xae, 0xd4, 0x60, 0x64, 0x73, 0x43, 0x27, 0xe5, + /*5eb0:*/ 0xb7, 0x22, 0x2b, 0x79, 0x13, 0x24, 0xaf, 0x74, 0xf4, 0x97, 0x05, 0xde, 0x6f, 0xa8, 0xf9, 0x34, + /*5ec0:*/ 0xb5, 0xa6, 0x17, 0x06, 0x9b, 0x5c, 0xdf, 0xe7, 0x7b, 0x12, 0x48, 0xb2, 0x7b, 0x68, 0xe9, 0x5a, + /*5ed0:*/ 0xc4, 0x4a, 0xab, 0x49, 0xb5, 0xce, 0x69, 0xec, 0x77, 0x42, 0x61, 0x85, 0xf5, 0x5f, 0x05, 0x2a, + /*5ee0:*/ 0x17, 0x65, 0xef, 0x88, 0x5c, 0x23, 0x5f, 0xb3, 0xf1, 0x55, 0x49, 0x46, 0x51, 0xee, 0x22, 0x4e, + /*5ef0:*/ 0xb6, 0x43, 0x84, 0xfd, 0x99, 0xe3, 0x7b, 0x77, 0xfa, 0x63, 0x5b, 0x88, 0xd7, 0xa0, 0xc0, 0x49, + /*5f00:*/ 0x87, 0xac, 0x08, 0x20, 0x72, 0x84, 0xd9, 0x1a, 0xf7, 0x4d, 0xe9, 0x05, 0xbc, 0x19, 0xe8, 0x2b, + /*5f10:*/ 0x1b, 0x1d, 0xe6, 0x76, 0x7d, 0x1f, 0x19, 0x15, 0x8b, 0xcd, 0x78, 0x3f, 0x99, 0x6a, 0xcb, 0x65, + /*5f20:*/ 0xaf, 0x0b, 0x05, 0xcb, 0x64, 0x3d, 0x54, 0xb6, 0x79, 0xfd, 0x66, 0xdc, 0x7c, 0x30, 0x87, 0x57, + /*5f30:*/ 0x94, 0x16, 0xce, 0x4b, 0x6a, 0x94, 0x57, 0x87, 0xea, 0x8d, 0xdc, 0x6c, 0xb5, 0x89, 0xd7, 0x55, + /*5f40:*/ 0x3b, 0xb2, 0x6b, 0x44, 0x10, 0x43, 0x79, 0x0f, 0xc0, 0xa2, 0x42, 0x59, 0x80, 0x7a, 0xf7, 0x02, + /*5f50:*/ 0x2a, 0xa2, 0x9c, 0x0a, 0x73, 0xfc, 0xbb, 0xab, 0x2b, 0x9b, 0xb5, 0xb0, 0xcc, 0x2c, 0x9b, 0xf3, + /*5f60:*/ 0x3c, 0xbe, 0x64, 0xb8, 0x00, 0x12, 0x58, 0x99, 0x8d, 0x7c, 0x2d, 0xcd, 0xb7, 0x8e, 0xef, 0x55, + /*5f70:*/ 0x3e, 0x91, 0xa5, 0x4f, 0xf8, 0x47, 0x8d, 0x04, 0x2e, 0xd5, 0x71, 0x59, 0x07, 0x01, 0x49, 0x99, + /*5f80:*/ 0x05, 0x1f, 0x50, 0xf0, 0x5e, 0x2f, 0xd8, 0xb5, 0x34, 0x02, 0x0c, 0x55, 0x91, 0x36, 0x64, 0xd5, + /*5f90:*/ 0x29, 0x63, 0x58, 0x81, 0xae, 0x49, 0xe4, 0xa5, 0x34, 0x17, 0xa8, 0x98, 0x2a, 0x70, 0x1a, 0xd9, + /*5fa0:*/ 0x3b, 0xc2, 0x90, 0x3e, 0x1a, 0xf5, 0xa7, 0x7d, 0xa5, 0x12, 0x6d, 0xf8, 0x2a, 0x6a, 0x7a, 0x16, + /*5fb0:*/ 0x65, 0x4e, 0xc6, 0xc3, 0xd8, 0xea, 0xa9, 0x5f, 0xfc, 0x68, 0x21, 0x29, 0x35, 0x0a, 0xbf, 0xf0, + /*5fc0:*/ 0x54, 0x3e, 0x64, 0x4e, 0x67, 0x4d, 0xf7, 0x9d, 0xe5, 0x9f, 0x90, 0x70, 0x4a, 0xfa, 0xea, 0xc3, + /*5fd0:*/ 0xd7, 0x61, 0x53, 0xcc, 0x41, 0x99, 0xed, 0x44, 0x16, 0xc0, 0xe1, 0x15, 0x50, 0xaf, 0xa0, 0x2d, + /*5fe0:*/ 0x45, 0x02, 0xad, 0x0f, 0xcc, 0x6e, 0xa4, 0x45, 0x7b, 0x2e, 0x49, 0x84, 0x0f, 0x51, 0x05, 0xe7, + /*5ff0:*/ 0x64, 0x1c, 0xbc, 0xa5, 0x79, 0x51, 0xab, 0xc6, 0x5c, 0x6a, 0xe3, 0x66, 0x96, 0x75, 0x8c, 0x3f, + /*6000:*/ 0xca, 0xe6, 0x4d, 0xf5, 0x3f, 0x56, 0x05, 0x3c, 0xa9, 0xb8, 0x0d, 0xc1, 0xbc, 0xfe, 0x9a, 0x63, + /*6010:*/ 0x3c, 0x1f, 0x3f, 0xee, 0xd3, 0x53, 0x2d, 0xfb, 0xb6, 0x49, 0x04, 0x88, 0xaa, 0x2e, 0x67, 0x4b, + /*6020:*/ 0x04, 0x0e, 0x9d, 0xbd, 0xd0, 0x95, 0x3f, 0xb4, 0xef, 0x26, 0x78, 0xad, 0x04, 0x21, 0x60, 0x5b, + /*6030:*/ 0x08, 0xd4, 0x13, 0x85, 0xbe, 0x05, 0x8a, 0x36, 0xfc, 0xb9, 0x44, 0x3e, 0xb0, 0x01, 0xff, 0x0f, + /*6040:*/ 0x4d, 0x0f, 0x38, 0x57, 0xca, 0x00, 0xe7, 0x40, 0xf1, 0xb7, 0x95, 0xf6, 0xf7, 0x6d, 0x22, 0x4b, + /*6050:*/ 0x34, 0x14, 0xed, 0x01, 0xc2, 0x91, 0x5d, 0x68, 0xb5, 0xf7, 0x6a, 0xa1, 0x12, 0xd8, 0x84, 0x4f, + /*6060:*/ 0xf0, 0x99, 0x9a, 0x56, 0xd7, 0x2c, 0xd1, 0x38, 0xb5, 0x94, 0x81, 0xf2, 0x05, 0x8f, 0x5f, 0x1c, + /*6070:*/ 0xb2, 0xdb, 0x4c, 0x98, 0x7a, 0x62, 0x82, 0xe9, 0x02, 0x58, 0x98, 0xa3, 0x78, 0xf0, 0x67, 0x21, + /*6080:*/ 0x22, 0x4c, 0xa7, 0x73, 0x6f, 0xc1, 0x50, 0xd8, 0xde, 0x6d, 0x85, 0xfd, 0xa0, 0x84, 0x8f, 0xbc, + /*6090:*/ 0x04, 0x20, 0x88, 0x6f, 0x73, 0x74, 0x18, 0x7d, 0xa1, 0x23, 0xfd, 0xb4, 0x25, 0xc1, 0x1b, 0x4b, + /*60a0:*/ 0x93, 0x43, 0x8a, 0x3b, 0x89, 0x81, 0x11, 0x9f, 0xf7, 0x8e, 0x0c, 0xdc, 0xfe, 0x74, 0x9f, 0xaf, + /*60b0:*/ 0x83, 0xe4, 0xbb, 0x37, 0xaf, 0x4d, 0x5d, 0x68, 0xf4, 0xa0, 0x73, 0x24, 0x06, 0x55, 0xbe, 0xe7, + /*60c0:*/ 0xe9, 0xbb, 0xfa, 0x94, 0x28, 0x4b, 0xd6, 0xa5, 0x06, 0xa7, 0x9a, 0x30, 0xc4, 0x22, 0xec, 0xa7, + /*60d0:*/ 0x1b, 0xbc, 0x9d, 0xb9, 0x54, 0xe4, 0x8a, 0xc1, 0x79, 0xa4, 0x5f, 0xc3, 0xf3, 0xe6, 0xe6, 0x4b, + /*60e0:*/ 0x9f, 0x93, 0x77, 0x53, 0xed, 0x12, 0xbb, 0xc7, 0x7f, 0xc0, 0x8e, 0xbb, 0xcf, 0xd1, 0x2e, 0x8c, + /*60f0:*/ 0x17, 0x20, 0xc6, 0x03, 0xc9, 0x8e, 0x89, 0x33, 0x8f, 0x19, 0x83, 0x29, 0xd9, 0xb7, 0x8e, 0x58, + /*6100:*/ 0x7c, 0x3c, 0xf4, 0x9c, 0x63, 0x70, 0xbe, 0xba, 0x9a, 0x02, 0x5f, 0x44, 0x04, 0xcd, 0x24, 0xf3, + /*6110:*/ 0x1a, 0x8d, 0xaa, 0xff, 0x69, 0x71, 0x97, 0x98, 0x06, 0x4d, 0xcc, 0xd9, 0x76, 0x34, 0x6f, 0x91, + /*6120:*/ 0xff, 0xef, 0x1b, 0x65, 0x39, 0x6e, 0xb7, 0xb0, 0x5f, 0x9e, 0xfb, 0x42, 0x50, 0xc1, 0xf4, 0x79, + /*6130:*/ 0x9c, 0x56, 0xfa, 0xcc, 0x51, 0x54, 0xca, 0x53, 0x2d, 0xa4, 0x01, 0x00, 0xfd, 0x4e, 0x1d, 0x8b, + /*6140:*/ 0x54, 0x3d, 0xcc, 0x2c, 0xef, 0x12, 0x10, 0x55, 0xaf, 0x7c, 0xd1, 0xcc, 0xf2, 0x60, 0xc6, 0xcd, + /*6150:*/ 0xfa, 0x1d, 0x13, 0x93, 0xb7, 0x14, 0x0a, 0x6c, 0xe2, 0xf6, 0x21, 0x0a, 0x08, 0xa0, 0x48, 0xef, + /*6160:*/ 0x9d, 0xae, 0x72, 0x00, 0xd3, 0xef, 0xe7, 0x22, 0x1e, 0xd4, 0x98, 0x6c, 0xf3, 0x44, 0x81, 0xaf, + /*6170:*/ 0xe5, 0x57, 0x4b, 0xf9, 0xcb, 0x4c, 0x26, 0x0a, 0x73, 0xe4, 0x55, 0xc9, 0x43, 0x03, 0x29, 0xd9, + /*6180:*/ 0x79, 0xd1, 0x12, 0x5c, 0x06, 0x3c, 0xf1, 0x7d, 0x80, 0x26, 0x73, 0x20, 0x07, 0x99, 0xf4, 0xfa, + /*6190:*/ 0x34, 0x51, 0xb5, 0x59, 0x75, 0x72, 0xd7, 0x61, 0xf4, 0xd0, 0x44, 0x71, 0xc1, 0x13, 0xc7, 0xfd, + /*61a0:*/ 0x59, 0xc6, 0x49, 0x49, 0x70, 0xc4, 0x78, 0xf7, 0x3a, 0xe3, 0x5a, 0x8a, 0xf8, 0xc5, 0x52, 0xe0, + /*61b0:*/ 0xbd, 0x47, 0x38, 0x2a, 0x50, 0xb3, 0x80, 0x93, 0x60, 0x63, 0xfd, 0x01, 0xd6, 0x98, 0xb4, 0xea, + /*61c0:*/ 0x78, 0x13, 0x47, 0x50, 0xf5, 0xf9, 0x86, 0x6c, 0x95, 0x6d, 0x5a, 0xfa, 0x6f, 0x8f, 0x00, 0xed, + /*61d0:*/ 0x9a, 0xfa, 0xd4, 0x78, 0x2f, 0x3a, 0x62, 0x0e, 0x76, 0x15, 0x4b, 0xdf, 0x79, 0x1a, 0x6a, 0xcf, + /*61e0:*/ 0x75, 0x49, 0xfd, 0xf7, 0x63, 0x59, 0xd8, 0x46, 0xc2, 0xc1, 0x87, 0xbf, 0x6c, 0xfe, 0xcf, 0xe6, + /*61f0:*/ 0x10, 0x6f, 0x16, 0xa9, 0xfb, 0xae, 0x43, 0x1b, 0x04, 0xa1, 0x2d, 0xfa, 0x0b, 0x85, 0x31, 0x3d, + /*6200:*/ 0x45, 0x0f, 0xe4, 0xe6, 0xe8, 0xf0, 0x1c, 0x5e, 0x03, 0x4a, 0x25, 0x0a, 0xcf, 0xdd, 0x10, 0x17, + /*6210:*/ 0xef, 0xac, 0x90, 0xf4, 0x03, 0xc9, 0xec, 0x98, 0x78, 0x35, 0x8c, 0x96, 0x3b, 0x83, 0xd1, 0xed, + /*6220:*/ 0x53, 0x89, 0x9d, 0x9d, 0xab, 0xa9, 0x99, 0x8c, 0x0b, 0xd4, 0xcb, 0xf9, 0x5e, 0x02, 0x4c, 0x5c, + /*6230:*/ 0x11, 0xec, 0x45, 0x0e, 0xba, 0x35, 0x64, 0xa2, 0xa0, 0x20, 0x5f, 0xae, 0x7b, 0x28, 0x9d, 0x38, + /*6240:*/ 0x0c, 0x9a, 0x88, 0x75, 0x69, 0xc7, 0x2b, 0xdd, 0x06, 0xd6, 0xfb, 0xd0, 0x56, 0x29, 0x81, 0xb7, + /*6250:*/ 0xfe, 0x00, 0x0d, 0xc5, 0xf7, 0x79, 0x1f, 0xec, 0x75, 0x67, 0x1c, 0x04, 0xae, 0x39, 0x8b, 0x11, + /*6260:*/ 0xdd, 0xed, 0x83, 0x97, 0x59, 0x22, 0x02, 0x38, 0xe8, 0x04, 0x0f, 0x4f, 0xf5, 0xd1, 0x89, 0x0a, + /*6270:*/ 0xe4, 0x5a, 0x17, 0x3f, 0x66, 0x1b, 0x70, 0x5a, 0xfa, 0xea, 0xc7, 0x8f, 0x24, 0x42, 0xd5, 0x2d, + /*6280:*/ 0x47, 0x63, 0x19, 0xad, 0x95, 0x94, 0xac, 0x45, 0xbc, 0xb2, 0x15, 0xb6, 0xd3, 0x76, 0x78, 0xee, + /*6290:*/ 0x2f, 0xbc, 0x98, 0xfc, 0x0b, 0x71, 0x48, 0x21, 0x1b, 0xda, 0xc4, 0x76, 0x3f, 0x43, 0x12, 0x4a, + /*62a0:*/ 0x7b, 0x64, 0x24, 0x6b, 0xea, 0xbf, 0x9f, 0xdd, 0x47, 0x8a, 0x25, 0x2d, 0x8d, 0x3e, 0xe6, 0x1b, + /*62b0:*/ 0x7f, 0xea, 0xc8, 0xa7, 0xb1, 0x80, 0x30, 0xa7, 0x20, 0xc9, 0x6e, 0x8b, 0xee, 0xc8, 0x6a, 0x47, + /*62c0:*/ 0x20, 0xe7, 0x27, 0x25, 0x4b, 0x14, 0x3e, 0x98, 0xf3, 0x87, 0x95, 0x20, 0x59, 0xb8, 0x71, 0x44, + /*62d0:*/ 0x35, 0xf8, 0x72, 0xf8, 0x06, 0x94, 0xde, 0x42, 0xe5, 0x93, 0x57, 0x30, 0xd7, 0xc4, 0x36, 0x0a, + /*62e0:*/ 0x07, 0x53, 0xd8, 0x86, 0x17, 0x6b, 0xda, 0xf8, 0x35, 0x14, 0xa6, 0xd3, 0x35, 0xfd, 0xcd, 0xba, + /*62f0:*/ 0x43, 0x6c, 0x91, 0xb9, 0x77, 0x8a, 0xf1, 0x9a, 0x6d, 0x77, 0x47, 0x7b, 0x80, 0x3a, 0xb8, 0x39, + /*6300:*/ 0x34, 0x43, 0x31, 0x79, 0x25, 0x37, 0x01, 0x2b, 0xad, 0x07, 0xac, 0x67, 0xe2, 0xea, 0x2c, 0x29, + /*6310:*/ 0x5f, 0xfa, 0x6d, 0x73, 0x76, 0x58, 0x75, 0x0a, 0x40, 0x4d, 0xbf, 0x31, 0x0f, 0xa8, 0x4e, 0xf0, + /*6320:*/ 0x39, 0xba, 0xe2, 0x18, 0x91, 0x2d, 0xe5, 0xe4, 0xbf, 0x37, 0x86, 0x8d, 0xbe, 0x14, 0x93, 0x9f, + /*6330:*/ 0x0d, 0x95, 0x21, 0xc8, 0xae, 0x76, 0x90, 0x87, 0xad, 0xdb, 0x07, 0x11, 0x27, 0x24, 0xcb, 0xce, + /*6340:*/ 0x5d, 0x8f, 0x49, 0x84, 0xc2, 0x10, 0xe9, 0xd1, 0xa5, 0x0c, 0xea, 0xf0, 0x0d, 0x3f, 0x20, 0xf6, + /*6350:*/ 0x0e, 0x54, 0x7f, 0xca, 0x89, 0xf1, 0x10, 0x37, 0x06, 0xbe, 0x67, 0xdd, 0x9b, 0x1d, 0x6b, 0xd0, + /*6360:*/ 0x92, 0x5c, 0x78, 0xca, 0xbe, 0x5f, 0x4d, 0xc3, 0xc8, 0xfa, 0x48, 0x57, 0x7f, 0xda, 0x82, 0xb1, + /*6370:*/ 0x0d, 0xe2, 0xc3, 0x28, 0x76, 0x33, 0x0f, 0x6b, 0x0a, 0xc6, 0xbb, 0xdb, 0x1c, 0x94, 0x4f, 0x6a, + /*6380:*/ 0xe9, 0xff, 0x5c, 0xf9, 0x99, 0x45, 0x74, 0xda, 0xca, 0x3a, 0x2d, 0x1b, 0xf5, 0x98, 0xb0, 0xc8, + /*6390:*/ 0x4d, 0xa0, 0x8f, 0x78, 0xc5, 0xe8, 0xb8, 0xea, 0x63, 0x20, 0x34, 0x23, 0x67, 0xea, 0x30, 0xa7, + /*63a0:*/ 0x42, 0xf7, 0x2d, 0x0f, 0x35, 0xe3, 0xe0, 0x36, 0xad, 0x97, 0xe9, 0x02, 0x36, 0x02, 0x6d, 0x5f, + /*63b0:*/ 0x04, 0x5c, 0xcc, 0x65, 0x5a, 0x3b, 0x5a, 0x9f, 0xe3, 0x71, 0xb2, 0x9c, 0x49, 0xd6, 0x0a, 0x24, + /*63c0:*/ 0xfb, 0xd2, 0xb0, 0x7e, 0x72, 0x16, 0xe1, 0x7f, 0xb1, 0xbf, 0x04, 0x9f, 0xd2, 0xe5, 0x53, 0x98, + /*63d0:*/ 0xad, 0x68, 0x08, 0x9c, 0x4d, 0xa8, 0x5b, 0x22, 0xd9, 0xaf, 0x56, 0xb4, 0xad, 0x45, 0x9c, 0x07, + /*63e0:*/ 0x15, 0xc8, 0xc0, 0xec, 0x5f, 0x09, 0x02, 0x3b, 0xf9, 0xe3, 0xbc, 0x7d, 0x27, 0xe2, 0x2d, 0xde, + /*63f0:*/ 0xea, 0x7a, 0xdd, 0x90, 0x63, 0xed, 0x55, 0x10, 0xf4, 0x95, 0x73, 0x24, 0xd1, 0xcb, 0x1d, 0x3d, + /*6400:*/ 0xcf, 0x45, 0x53, 0x41, 0x47, 0x94, 0x85, 0xc0, 0x8b, 0x1f, 0xd1, 0x0d, 0x46, 0x13, 0x42, 0xef, + /*6410:*/ 0xe9, 0xc5, 0xc4, 0xa9, 0xa2, 0xf0, 0x87, 0x35, 0x34, 0x00, 0xbe, 0xc5, 0x5d, 0x40, 0x11, 0x75, + /*6420:*/ 0x8b, 0xec, 0x46, 0xd3, 0x1d, 0x54, 0xdc, 0xb3, 0x6c, 0x6e, 0x3b, 0x49, 0xa9, 0x80, 0xe8, 0x76, + /*6430:*/ 0x5d, 0xad, 0xce, 0x0e, 0x96, 0x24, 0xfd, 0x79, 0xb1, 0x58, 0x79, 0x98, 0x50, 0x29, 0x64, 0x8c, + /*6440:*/ 0x85, 0xd8, 0x16, 0x7b, 0xec, 0xa9, 0xb7, 0x53, 0x18, 0x55, 0x41, 0x44, 0x12, 0xf6, 0x52, 0x77, + /*6450:*/ 0x6c, 0x0f, 0xfe, 0x71, 0xf8, 0xf6, 0xf8, 0xb3, 0xb3, 0x47, 0xb6, 0xe5, 0x9e, 0x28, 0x4f, 0x87, + /*6460:*/ 0x92, 0xb0, 0x0c, 0x60, 0xbe, 0x7a, 0x91, 0xf3, 0x6e, 0x9a, 0xae, 0x2b, 0x37, 0x20, 0x8d, 0xf8, + /*6470:*/ 0x08, 0xdd, 0x65, 0xbe, 0xe5, 0x83, 0xeb, 0x6d, 0xf0, 0xe9, 0x07, 0x29, 0xb2, 0x3b, 0x10, 0x8a, + /*6480:*/ 0x95, 0xc7, 0x57, 0xdd, 0x21, 0x7b, 0xb0, 0x48, 0x91, 0x88, 0x68, 0x87, 0x93, 0x85, 0x82, 0x50, + /*6490:*/ 0xfa, 0x3d, 0xb9, 0x26, 0x86, 0xa2, 0x84, 0x47, 0x9d, 0x41, 0x91, 0xe5, 0x2e, 0xcb, 0xd1, 0x92, + /*64a0:*/ 0xcb, 0xb2, 0x20, 0x33, 0x05, 0x1e, 0xde, 0x16, 0x75, 0x5f, 0xc1, 0xd1, 0x84, 0x2c, 0x98, 0xb9, + /*64b0:*/ 0xf4, 0xba, 0x69, 0x13, 0x6f, 0x51, 0x55, 0x07, 0xcd, 0x4e, 0x10, 0x61, 0xd9, 0x67, 0x4b, 0x57, + /*64c0:*/ 0x8e, 0x3a, 0x88, 0x09, 0xdb, 0xfe, 0x71, 0x34, 0x5d, 0xd8, 0x7e, 0xb1, 0x10, 0xa8, 0x07, 0xf7, + /*64d0:*/ 0x05, 0x3c, 0x3c, 0x81, 0xb4, 0xd9, 0x13, 0x31, 0x9b, 0x9d, 0x97, 0xee, 0xeb, 0x07, 0xbb, 0x0a, + /*64e0:*/ 0xa9, 0x76, 0x8d, 0x3b, 0x49, 0x35, 0xeb, 0x31, 0x32, 0x99, 0x25, 0x3f, 0x44, 0xf5, 0x6c, 0x76, + /*64f0:*/ 0x08, 0x34, 0x96, 0xd8, 0xfa, 0x6f, 0xef, 0x23, 0xf1, 0x7d, 0x77, 0x07, 0x56, 0x46, 0x18, 0x2c, + /*6500:*/ 0x80, 0xa3, 0xbc, 0x4e, 0x35, 0xfc, 0x9a, 0x32, 0xc9, 0x64, 0x15, 0xd1, 0x2d, 0x47, 0xa1, 0xd7, + /*6510:*/ 0x87, 0xb3, 0xc3, 0x99, 0x64, 0xfe, 0xd1, 0x53, 0xce, 0x5c, 0x56, 0x54, 0x3e, 0x9c, 0xf7, 0xa3, + /*6520:*/ 0xb5, 0x81, 0xf3, 0x54, 0x35, 0xbc, 0x1c, 0x40, 0x52, 0xe4, 0xba, 0x08, 0x45, 0xf7, 0x6a, 0x85, + /*6530:*/ 0xc9, 0xe6, 0x0a, 0x2d, 0xe5, 0xf6, 0x86, 0x30, 0x61, 0x5f, 0xa8, 0x7a, 0xdb, 0x2c, 0x38, 0x78, + /*6540:*/ 0xff, 0x45, 0x9f, 0x7b, 0xcf, 0xf7, 0x66, 0x8d, 0x57, 0xfe, 0xcd, 0x0a, 0x3c, 0xbb, 0x4a, 0x45, + /*6550:*/ 0x82, 0x01, 0xd0, 0x30, 0x34, 0x22, 0xd9, 0x84, 0xb5, 0x19, 0x5e, 0xe2, 0xa9, 0x23, 0x3b, 0xfb, + /*6560:*/ 0xed, 0x42, 0xb2, 0x80, 0xdc, 0x8c, 0xae, 0x27, 0x6e, 0x54, 0xab, 0x9c, 0x87, 0x60, 0x18, 0xd6, + /*6570:*/ 0x57, 0x62, 0x6b, 0xb9, 0x87, 0xc4, 0x28, 0x52, 0x42, 0xc2, 0x0c, 0x83, 0xad, 0x1e, 0x79, 0xce, + /*6580:*/ 0x50, 0x49, 0x8b, 0xd4, 0xe7, 0x10, 0x1a, 0x32, 0x5a, 0x8f, 0x98, 0xd1, 0x20, 0x29, 0xc1, 0x35, + /*6590:*/ 0x02, 0x7f, 0xcf, 0x18, 0xac, 0x45, 0x24, 0x9f, 0xd3, 0x82, 0xe5, 0x95, 0xdc, 0x68, 0x2d, 0x1a, + /*65a0:*/ 0x8c, 0x6e, 0xa5, 0x79, 0x2b, 0xde, 0x17, 0x6c, 0x8b, 0x23, 0x06, 0x92, 0x01, 0x4e, 0x29, 0x3d, + /*65b0:*/ 0x5e, 0x8e, 0x45, 0x13, 0x85, 0x1c, 0x13, 0x61, 0xf4, 0xbb, 0x1b, 0x39, 0xcd, 0xd7, 0x3f, 0xde, + /*65c0:*/ 0xd3, 0xbe, 0x60, 0x41, 0xda, 0xe4, 0x95, 0xa6, 0xf8, 0x10, 0xe5, 0xe9, 0x34, 0x47, 0x49, 0x75, + /*65d0:*/ 0x7b, 0xa0, 0xbe, 0xa1, 0x4d, 0xce, 0xe3, 0xa5, 0xe7, 0xb3, 0x88, 0xf2, 0x06, 0x7c, 0xa5, 0x5f, + /*65e0:*/ 0xb7, 0x08, 0x1a, 0x19, 0x33, 0xc9, 0x66, 0x29, 0x77, 0xf6, 0x00, 0x48, 0x3c, 0x1b, 0xda, 0xa6, + /*65f0:*/ 0xb9, 0x31, 0xc3, 0xf6, 0x81, 0x32, 0x77, 0x69, 0x61, 0x7e, 0xc5, 0xe4, 0x90, 0xb1, 0xdd, 0x01, + /*6600:*/ 0xac, 0x89, 0xcf, 0x5b, 0x49, 0x10, 0xef, 0x23, 0x0d, 0x05, 0x87, 0x0f, 0xa2, 0x62, 0x24, 0x49, + /*6610:*/ 0x54, 0xa1, 0x9d, 0xc2, 0x4f, 0x4f, 0x06, 0x61, 0xa4, 0x24, 0x76, 0xd7, 0xcd, 0x59, 0x34, 0xb9, + /*6620:*/ 0xcc, 0x25, 0x41, 0x2e, 0xbd, 0x73, 0x3e, 0x07, 0xe7, 0xf0, 0x8f, 0xf3, 0xe0, 0x82, 0xf4, 0xc8, + /*6630:*/ 0x1f, 0x93, 0x0c, 0x79, 0xa3, 0x83, 0xba, 0xa1, 0x2e, 0x1b, 0x08, 0x0c, 0x26, 0x5e, 0x92, 0x75, + /*6640:*/ 0x2a, 0x8c, 0xcb, 0x4d, 0x1b, 0xd6, 0x95, 0x66, 0xf1, 0xa8, 0xea, 0x41, 0x49, 0x0c, 0x62, 0x7f, + /*6650:*/ 0x98, 0x9e, 0xd8, 0xf1, 0x2b, 0x26, 0x07, 0xe7, 0xa7, 0xb2, 0xc3, 0x95, 0xcb, 0x5f, 0xa7, 0x4f, + /*6660:*/ 0x5d, 0x45, 0x57, 0x00, 0xb1, 0x1d, 0xd5, 0x8b, 0x7a, 0x00, 0x78, 0xeb, 0x57, 0xad, 0xe4, 0x4b, + /*6670:*/ 0xa6, 0x47, 0xfe, 0x40, 0x19, 0x6b, 0x3f, 0xac, 0xba, 0xe8, 0xaf, 0x03, 0xe8, 0x8e, 0x1f, 0xb1, + /*6680:*/ 0x89, 0x26, 0x4b, 0x57, 0x2e, 0x74, 0xc0, 0xd8, 0x42, 0x2c, 0xb5, 0x0b, 0x95, 0xf0, 0x2f, 0x04, + /*6690:*/ 0x00, 0x44, 0x19, 0xdd, 0xff, 0x6f, 0xe4, 0x6e, 0x93, 0x33, 0x2e, 0xd1, 0x4a, 0xc5, 0x68, 0x5c, + /*66a0:*/ 0x9c, 0xea, 0x25, 0x9f, 0x78, 0xac, 0x08, 0xc1, 0x84, 0x8d, 0x08, 0x25, 0xb0, 0x79, 0x13, 0xbb, + /*66b0:*/ 0xf0, 0x5c, 0x2c, 0xa9, 0x22, 0x7c, 0xd4, 0xf9, 0xbe, 0xc4, 0x99, 0x8b, 0xba, 0xe0, 0x1b, 0x3a, + /*66c0:*/ 0xa2, 0xe8, 0xbf, 0x1a, 0xe2, 0x90, 0xd2, 0x0c, 0xfc, 0x7c, 0x96, 0x17, 0xd7, 0x25, 0x14, 0xa1, + /*66d0:*/ 0x67, 0xfe, 0xb2, 0x62, 0xca, 0x38, 0x0c, 0x6e, 0x6d, 0x6c, 0x65, 0x27, 0xb5, 0x53, 0x49, 0xc6, + /*66e0:*/ 0x62, 0x53, 0xc2, 0x14, 0x14, 0xf7, 0xec, 0xef, 0xfa, 0x9f, 0x81, 0x71, 0x80, 0xf7, 0x03, 0x9c, + /*66f0:*/ 0x69, 0x37, 0x38, 0xfc, 0xa6, 0x3b, 0x31, 0x81, 0x7e, 0x4c, 0x81, 0xf9, 0xd4, 0x17, 0xfe, 0x92, + /*6700:*/ 0x4d, 0x93, 0x1b, 0xbd, 0xcf, 0x5a, 0xfa, 0xfb, 0xaa, 0xcf, 0xf9, 0x10, 0xb2, 0x0f, 0xd7, 0x2f, + /*6710:*/ 0x71, 0x20, 0xd0, 0xda, 0x25, 0xd8, 0x6d, 0xe2, 0x81, 0x1d, 0x17, 0x55, 0x16, 0x1a, 0x66, 0xcc, + /*6720:*/ 0x21, 0x95, 0xf7, 0x3d, 0x96, 0xe1, 0x71, 0x59, 0x7c, 0x9c, 0xdd, 0xbe, 0xf8, 0xa5, 0x14, 0xe4, + /*6730:*/ 0x21, 0x31, 0x2c, 0xe2, 0x6e, 0x4a, 0x4e, 0x27, 0x29, 0x73, 0xf6, 0x9a, 0x8b, 0x04, 0xcd, 0x34, + /*6740:*/ 0xa4, 0x0f, 0x15, 0x57, 0x51, 0x42, 0x95, 0xf7, 0x54, 0x35, 0x0d, 0xd2, 0x5b, 0x9f, 0xd7, 0x51, + /*6750:*/ 0xff, 0x30, 0x1e, 0xa3, 0x14, 0x20, 0xa9, 0x46, 0xca, 0x87, 0x55, 0x83, 0x24, 0x2f, 0x97, 0x6f, + /*6760:*/ 0xc0, 0x03, 0xe3, 0x9a, 0x97, 0x92, 0x80, 0x95, 0x38, 0x69, 0x78, 0x2d, 0xed, 0xb0, 0x32, 0x85, + /*6770:*/ 0xfa, 0xb8, 0x78, 0x8c, 0xc2, 0x5d, 0x7b, 0xc9, 0x17, 0x6e, 0xca, 0x3b, 0xdd, 0x7d, 0xbc, 0xbe, + /*6780:*/ 0x80, 0xe0, 0xfb, 0x80, 0x5d, 0x33, 0xc1, 0xa3, 0x47, 0xf2, 0xdc, 0x97, 0x7d, 0xb1, 0xce, 0xbd, + /*6790:*/ 0xf2, 0x4d, 0xec, 0x19, 0xdc, 0x87, 0x15, 0x44, 0x0e, 0xe9, 0xbe, 0x14, 0x8a, 0xbb, 0x4b, 0x4b, + /*67a0:*/ 0x65, 0x64, 0x90, 0x12, 0x6c, 0xd5, 0x34, 0x33, 0xde, 0xd4, 0x66, 0x8c, 0x0e, 0xef, 0xfe, 0xa6, + /*67b0:*/ 0x95, 0x1b, 0x81, 0x0e, 0xa1, 0xa2, 0xf8, 0x3c, 0xd4, 0xa9, 0xea, 0xc6, 0x39, 0x10, 0x36, 0x08, + /*67c0:*/ 0xd0, 0xce, 0x40, 0x1e, 0x2e, 0x83, 0x19, 0x64, 0x1d, 0x64, 0x65, 0xc2, 0xda, 0xad, 0xc4, 0x0a, + /*67d0:*/ 0x64, 0xe6, 0x58, 0x26, 0x05, 0x6b, 0xec, 0x41, 0xea, 0x55, 0x4d, 0x4c, 0x1a, 0xac, 0x7c, 0x72, + /*67e0:*/ 0x4c, 0x4d, 0x56, 0xab, 0x0a, 0x2d, 0x17, 0xe9, 0x2a, 0x9d, 0xe1, 0xc1, 0x84, 0xb0, 0xd9, 0x95, + /*67f0:*/ 0x7d, 0x4a, 0x11, 0x77, 0xeb, 0x93, 0x02, 0x9b, 0xb1, 0xfb, 0xd2, 0xa9, 0xf1, 0xde, 0x59, 0x25, + /*6800:*/ 0x5a, 0x49, 0x62, 0xc1, 0xad, 0xbb, 0x50, 0x5f, 0xaf, 0x8e, 0xb7, 0xdf, 0x11, 0x55, 0xf4, 0xb9, + /*6810:*/ 0x29, 0xc3, 0xc8, 0x70, 0xea, 0xcd, 0x9c, 0x65, 0x72, 0x29, 0xfb, 0x3b, 0x12, 0x69, 0xf4, 0x4c, + /*6820:*/ 0xbc, 0x6d, 0xbf, 0xce, 0xc9, 0x09, 0x38, 0xf1, 0x00, 0x81, 0x47, 0x24, 0x60, 0x46, 0x2c, 0x14, + /*6830:*/ 0xf1, 0xd5, 0x92, 0xdd, 0x44, 0x68, 0x20, 0x44, 0x70, 0xf1, 0xd2, 0x0e, 0x32, 0x1f, 0x60, 0xed, + /*6840:*/ 0x58, 0x02, 0x5a, 0x79, 0x2c, 0xa1, 0x3c, 0x70, 0x3e, 0xb5, 0xf4, 0x64, 0xa1, 0x69, 0x56, 0x76, + /*6850:*/ 0xd3, 0xf9, 0x61, 0xc4, 0xe7, 0x11, 0x07, 0x10, 0x1f, 0x87, 0xa2, 0x8d, 0x2a, 0xb1, 0x6d, 0x4a, + /*6860:*/ 0xa8, 0x79, 0x62, 0x7c, 0xf6, 0xfc, 0x22, 0x18, 0xa0, 0x22, 0x91, 0x33, 0xb9, 0x8a, 0xe6, 0xc6, + /*6870:*/ 0x98, 0x2d, 0x80, 0x49, 0x53, 0x2f, 0x76, 0xd0, 0x9a, 0x4b, 0x5c, 0x5b, 0x21, 0xe1, 0x19, 0xb3, + /*6880:*/ 0x76, 0x20, 0x90, 0xe3, 0xd7, 0xa5, 0x83, 0xcb, 0x0c, 0x9c, 0x04, 0x63, 0xf0, 0x1d, 0xfb, 0x07, + /*6890:*/ 0xd7, 0xae, 0x43, 0xfe, 0x97, 0x1e, 0x6e, 0xb4, 0xb3, 0xea, 0xf7, 0x7c, 0x31, 0x75, 0xf3, 0x04, + /*68a0:*/ 0x93, 0x40, 0xd7, 0x18, 0x3d, 0xaf, 0x3f, 0x22, 0x4e, 0x7f, 0x34, 0xb7, 0xb1, 0x43, 0x9f, 0xc3, + /*68b0:*/ 0xeb, 0x05, 0x6e, 0xb0, 0xdd, 0xa5, 0x0d, 0x0d, 0x80, 0x78, 0x3a, 0xdc, 0x8e, 0xb1, 0x8d, 0x40, + /*68c0:*/ 0x4b, 0x94, 0xfb, 0x04, 0xf5, 0x34, 0x39, 0x90, 0x02, 0x56, 0xd4, 0xd8, 0xd3, 0x9d, 0x51, 0x10, + /*68d0:*/ 0x36, 0x6c, 0x12, 0xcc, 0x8c, 0x80, 0x8b, 0xee, 0x60, 0xdc, 0x6b, 0x38, 0x2e, 0xe0, 0x4d, 0x1f, + /*68e0:*/ 0x9f, 0x83, 0x6b, 0x3d, 0x7e, 0xc2, 0x56, 0x01, 0xe2, 0x80, 0xf6, 0xd2, 0xbf, 0x0f, 0x52, 0x78, + /*68f0:*/ 0x28, 0xe3, 0xaf, 0x74, 0x74, 0x56, 0x98, 0x62, 0x53, 0x10, 0x48, 0xb3, 0xcd, 0xc7, 0x63, 0x37, + /*6900:*/ 0x4c, 0x7b, 0x4a, 0x13, 0x52, 0x46, 0xaf, 0xd8, 0xbb, 0x27, 0x12, 0x87, 0x02, 0x9a, 0xae, 0xff, + /*6910:*/ 0x49, 0xcc, 0x5f, 0xd2, 0x09, 0x10, 0x08, 0xe6, 0x70, 0x53, 0x36, 0xf2, 0x0e, 0x54, 0x34, 0x66, + /*6920:*/ 0x42, 0x26, 0x59, 0x1b, 0xdf, 0x88, 0x33, 0x9a, 0xb1, 0xaf, 0xa6, 0xdb, 0x71, 0xa9, 0xea, 0x89, + /*6930:*/ 0xe8, 0xdb, 0xb9, 0xcf, 0x78, 0x03, 0x5c, 0x33, 0x9b, 0x2c, 0x1e, 0x84, 0x97, 0x99, 0xc8, 0xdb, + /*6940:*/ 0xdd, 0x94, 0x98, 0xf3, 0x8f, 0x1f, 0xfb, 0xf2, 0x45, 0x46, 0x66, 0xb9, 0x24, 0x4d, 0x2f, 0x69, + /*6950:*/ 0x3a, 0xb7, 0x5c, 0x0e, 0x53, 0xf9, 0xdb, 0x65, 0xbb, 0x13, 0xd0, 0x18, 0x61, 0x5c, 0x95, 0xa4, + /*6960:*/ 0x1b, 0xdf, 0x9b, 0x3d, 0x8c, 0x62, 0x39, 0x19, 0x80, 0xec, 0x37, 0xa7, 0x60, 0xa4, 0x56, 0xf1, + /*6970:*/ 0xf5, 0x4b, 0x1f, 0xd2, 0x1d, 0x5c, 0x83, 0x7c, 0xc3, 0xbe, 0xe6, 0x6f, 0x02, 0x1f, 0xfc, 0xbd, + /*6980:*/ 0xad, 0x2a, 0x56, 0x61, 0x3f, 0xfd, 0x73, 0xac, 0x38, 0x89, 0xe5, 0x13, 0x14, 0xcd, 0x3e, 0x94, + /*6990:*/ 0x43, 0x37, 0xb1, 0x29, 0x9e, 0xbf, 0xa5, 0xc2, 0x10, 0x4e, 0xac, 0xc8, 0x5e, 0x72, 0xa5, 0x85, + /*69a0:*/ 0x30, 0xe2, 0xcb, 0x49, 0x0e, 0x7a, 0x30, 0x32, 0x03, 0x0b, 0xf7, 0xec, 0x54, 0x07, 0xc5, 0xd5, + /*69b0:*/ 0xb3, 0x86, 0xe6, 0x22, 0x3c, 0x69, 0x39, 0xa4, 0xda, 0xa8, 0xea, 0xc9, 0xcc, 0x67, 0xda, 0xf4, + /*69c0:*/ 0xbd, 0xf4, 0xd4, 0x6d, 0x4d, 0x89, 0x9c, 0xcb, 0x5a, 0x22, 0x9a, 0x29, 0x6d, 0x70, 0xff, 0x43, + /*69d0:*/ 0xc8, 0xdb, 0x38, 0x2e, 0x44, 0x8c, 0x19, 0x50, 0x82, 0xc1, 0x0a, 0xa5, 0xdf, 0x0e, 0xd2, 0x49, + /*69e0:*/ 0x08, 0x39, 0xdb, 0xf6, 0xc3, 0xa9, 0xad, 0x58, 0x17, 0x0c, 0xac, 0x0c, 0x61, 0x18, 0xaf, 0x6f, + /*69f0:*/ 0xbc, 0x52, 0x8e, 0x80, 0x6b, 0x8b, 0xd9, 0x94, 0x1c, 0x83, 0x13, 0xe9, 0x1e, 0xd6, 0x83, 0x3d, + /*6a00:*/ 0x32, 0x59, 0x6f, 0x6d, 0x8d, 0xa0, 0x4e, 0x1b, 0x7b, 0x14, 0xda, 0x28, 0x6a, 0x15, 0x56, 0xc2, + /*6a10:*/ 0x89, 0x65, 0xc1, 0x42, 0x01, 0x3a, 0x2a, 0xc3, 0x29, 0xd1, 0x3e, 0x65, 0xae, 0x00, 0xbf, 0x67, + /*6a20:*/ 0xbd, 0xd4, 0x20, 0xfd, 0xf8, 0x46, 0x06, 0x2b, 0xe5, 0x31, 0x6f, 0x70, 0x3b, 0x81, 0x81, 0x4a, + /*6a30:*/ 0xc7, 0xcf, 0x72, 0x99, 0x2c, 0x2d, 0x4b, 0xdf, 0xc3, 0x09, 0xe3, 0x5b, 0x29, 0x1d, 0x59, 0xd3, + /*6a40:*/ 0xe0, 0x89, 0x7e, 0xc4, 0x8c, 0x30, 0x46, 0x8a, 0x6b, 0x3b, 0xd0, 0x1b, 0x30, 0xe5, 0x14, 0x51, + /*6a50:*/ 0x34, 0xbc, 0x4c, 0xd5, 0x4b, 0x04, 0x2f, 0x1b, 0x7c, 0x50, 0x01, 0xdf, 0x5f, 0xa2, 0xdf, 0x10, + /*6a60:*/ 0x56, 0xbc, 0xde, 0x26, 0x5a, 0x11, 0xa7, 0xc8, 0xc9, 0x78, 0xa0, 0x5a, 0xb4, 0xfc, 0x6b, 0xa6, + /*6a70:*/ 0xb0, 0x08, 0xbc, 0xd8, 0xfd, 0xf2, 0xb0, 0xa2, 0xd5, 0xc3, 0x92, 0x0f, 0xcc, 0x6d, 0xbf, 0xb0, + /*6a80:*/ 0xc9, 0x9f, 0xc2, 0x4e, 0xf6, 0x5a, 0xc1, 0x26, 0x16, 0x3d, 0x90, 0x50, 0x65, 0x53, 0xd4, 0x66, + /*6a90:*/ 0xab, 0x4d, 0xce, 0x70, 0xd3, 0x91, 0x56, 0x4f, 0x14, 0x29, 0x4c, 0x8f, 0x8c, 0xf7, 0xcb, 0xad, + /*6aa0:*/ 0xca, 0x87, 0x67, 0x0d, 0x48, 0xc1, 0x15, 0xa1, 0xbd, 0x22, 0xb4, 0xa7, 0x41, 0x10, 0xfc, 0x49, + /*6ab0:*/ 0x35, 0x01, 0xc5, 0xa7, 0xf1, 0xd1, 0x92, 0xa3, 0x19, 0xf0, 0x75, 0x65, 0xf0, 0xe3, 0xec, 0x64, + /*6ac0:*/ 0xd9, 0x9d, 0x3f, 0x5e, 0x89, 0x5e, 0x30, 0xad, 0x98, 0x83, 0xca, 0x09, 0xc4, 0x80, 0x7d, 0x3f, + /*6ad0:*/ 0x9b, 0x74, 0x59, 0xde, 0xdf, 0x75, 0xad, 0xf2, 0x09, 0x1d, 0xff, 0xaf, 0x80, 0x71, 0x77, 0x0b, + /*6ae0:*/ 0xc1, 0x47, 0xad, 0xde, 0x6c, 0x59, 0x06, 0x38, 0x59, 0x8e, 0xe8, 0x99, 0x77, 0xd4, 0xf1, 0xab, + /*6af0:*/ 0x24, 0x2a, 0x51, 0x46, 0x9f, 0x9c, 0x00, 0x24, 0x86, 0x93, 0x82, 0xbf, 0x52, 0x68, 0x46, 0xdf, + /*6b00:*/ 0xd7, 0x3f, 0xb1, 0x23, 0x2b, 0xd4, 0xc7, 0xb1, 0x4a, 0x9b, 0x31, 0xe0, 0x20, 0x8a, 0xaa, 0xc2, + /*6b10:*/ 0x9e, 0x4d, 0xd8, 0x14, 0xfd, 0x89, 0xfc, 0xfa, 0x3a, 0x42, 0xe3, 0xed, 0x21, 0x23, 0x17, 0xe4, + /*6b20:*/ 0xe8, 0xd2, 0x88, 0xea, 0x58, 0x9f, 0xb4, 0xff, 0xfc, 0xce, 0x9d, 0x8d, 0x9a, 0xa4, 0x8c, 0xaf, + /*6b30:*/ 0x17, 0xf3, 0x80, 0x16, 0x9b, 0xcf, 0x16, 0x25, 0x88, 0x2e, 0x37, 0x59, 0x64, 0x27, 0x1b, 0xb5, + /*6b40:*/ 0xba, 0x9e, 0x89, 0xbd, 0xc2, 0xfd, 0x65, 0x31, 0x8b, 0xc8, 0xc2, 0x6b, 0x11, 0xfd, 0xf6, 0x86, + /*6b50:*/ 0x64, 0xdd, 0xe4, 0xb8, 0xa8, 0x9b, 0x64, 0x47, 0xce, 0x85, 0x01, 0xb9, 0xa2, 0xf1, 0xe4, 0x40, + /*6b60:*/ 0x6a, 0x46, 0x60, 0x6d, 0x28, 0xea, 0x53, 0xf7, 0x47, 0x28, 0x48, 0x72, 0xe7, 0x71, 0x61, 0xb9, + /*6b70:*/ 0x24, 0xd6, 0xc6, 0xc6, 0x0d, 0x5f, 0x07, 0xe6, 0xa0, 0xcf, 0x50, 0x2e, 0x8a, 0xb1, 0xa1, 0x64, + /*6b80:*/ 0x8c, 0xf4, 0x82, 0x81, 0xed, 0x60, 0xe6, 0x1c, 0xc0, 0x16, 0x98, 0x43, 0x6c, 0x26, 0x7d, 0xc1, + /*6b90:*/ 0x2a, 0xa5, 0xbb, 0x2b, 0x30, 0xa5, 0xd3, 0xf2, 0x00, 0x7b, 0x37, 0xe8, 0x8b, 0x15, 0xdc, 0xaf, + /*6ba0:*/ 0xc7, 0x08, 0x83, 0x66, 0x5f, 0x9b, 0x7b, 0xbb, 0x2d, 0x4c, 0x14, 0xb7, 0xb1, 0x18, 0x82, 0x62, + /*6bb0:*/ 0x0a, 0xfa, 0x55, 0x8a, 0xc8, 0x61, 0xe6, 0x18, 0x1f, 0xcc, 0xe0, 0xf1, 0x66, 0x73, 0x08, 0xac, + /*6bc0:*/ 0x66, 0x0d, 0x3e, 0x4f, 0xfc, 0xbe, 0xd8, 0x0b, 0xad, 0x84, 0xcd, 0x31, 0x6e, 0x78, 0x54, 0xa7, + /*6bd0:*/ 0x1e, 0x23, 0x0b, 0x2d, 0x19, 0x70, 0xaa, 0x27, 0x7a, 0x46, 0x7d, 0x0d, 0x98, 0xfe, 0x60, 0x7e, + /*6be0:*/ 0x61, 0x05, 0xce, 0x71, 0x2e, 0x96, 0x01, 0x99, 0x38, 0x5e, 0x09, 0x03, 0x38, 0x7d, 0x07, 0xbf, + /*6bf0:*/ 0x19, 0xc9, 0xa3, 0x48, 0x56, 0x6f, 0xc1, 0xc2, 0x67, 0x38, 0xfb, 0xa8, 0x45, 0xc2, 0xd9, 0x7d, + /*6c00:*/ 0x4b, 0xb7, 0x69, 0xad, 0x47, 0x6d, 0x2d, 0xe8, 0xcb, 0x35, 0x27, 0x14, 0x1a, 0x70, 0x20, 0x58, + /*6c10:*/ 0xfb, 0x58, 0xa1, 0x40, 0x1f, 0x58, 0x7a, 0xfd, 0x05, 0x58, 0xbe, 0x82, 0xb6, 0x4b, 0x93, 0x0d, + /*6c20:*/ 0xe0, 0x84, 0xed, 0xf8, 0x33, 0x76, 0x6c, 0x59, 0x8a, 0xab, 0x2e, 0x26, 0x40, 0xea, 0xb0, 0x43, + /*6c30:*/ 0x99, 0xf5, 0xbe, 0x65, 0xe7, 0x78, 0xdc, 0x77, 0x0b, 0xf5, 0xed, 0x37, 0x61, 0x4e, 0x08, 0x1f, + /*6c40:*/ 0x03, 0xfd, 0xa4, 0x53, 0xa6, 0x00, 0x50, 0x49, 0xb5, 0xe3, 0x7d, 0x62, 0xef, 0x0f, 0xc9, 0x76, + /*6c50:*/ 0x60, 0x3a, 0x23, 0x42, 0x68, 0xb0, 0xfa, 0x0e, 0x2b, 0x6c, 0x3b, 0xed, 0x68, 0x12, 0x06, 0x59, + /*6c60:*/ 0xf2, 0x6a, 0xf0, 0xae, 0xe1, 0x16, 0xc3, 0x56, 0xe2, 0x59, 0xec, 0x1d, 0x0e, 0x8e, 0x81, 0xb3, + /*6c70:*/ 0xce, 0xe3, 0x73, 0x98, 0x9c, 0xd7, 0x61, 0xe1, 0xac, 0x9c, 0x9c, 0xd2, 0x1e, 0x4a, 0x14, 0x47, + /*6c80:*/ 0x65, 0x44, 0x0a, 0x75, 0x89, 0x0a, 0x1f, 0x57, 0x5d, 0x7e, 0x8f, 0x04, 0x9c, 0xd1, 0x85, 0x98, + /*6c90:*/ 0x01, 0x6d, 0x62, 0xd2, 0xb6, 0x90, 0xc4, 0xbf, 0xe3, 0x68, 0xb4, 0x28, 0x2f, 0x12, 0x05, 0x63, + /*6ca0:*/ 0x27, 0x85, 0xf5, 0x01, 0xda, 0xea, 0x64, 0xf4, 0x0e, 0x10, 0x8b, 0xd7, 0x0a, 0x7b, 0x49, 0xff, + /*6cb0:*/ 0xbe, 0xf9, 0x9d, 0xfd, 0x76, 0xa8, 0x69, 0x04, 0x9e, 0xf1, 0x42, 0xd4, 0x5f, 0x14, 0x54, 0x76, + /*6cc0:*/ 0x7f, 0x9d, 0xc0, 0xe3, 0x2c, 0xda, 0x53, 0x1b, 0x7a, 0x15, 0x30, 0x64, 0xab, 0xce, 0x8b, 0x93, + /*6cd0:*/ 0x3c, 0x5b, 0x08, 0x58, 0x89, 0x94, 0xb6, 0xb2, 0x93, 0xd0, 0x29, 0x7f, 0x0c, 0x5b, 0xa6, 0x1d, + /*6ce0:*/ 0xe4, 0x20, 0x8d, 0x45, 0xc8, 0xb1, 0xee, 0xa7, 0x1f, 0x1e, 0x20, 0x3e, 0xef, 0x44, 0x23, 0x0a, + /*6cf0:*/ 0x6a, 0x13, 0x75, 0x8e, 0x80, 0xfc, 0x00, 0x7b, 0xff, 0x0a, 0xb4, 0x78, 0x2f, 0x00, 0x43, 0xde, + /*6d00:*/ 0x54, 0x85, 0x90, 0xbe, 0x67, 0x1f, 0xfa, 0xc5, 0x4b, 0xb7, 0x10, 0x8c, 0xb7, 0x09, 0xe0, 0xbb, + /*6d10:*/ 0x9e, 0xa8, 0xb4, 0x57, 0x34, 0x69, 0x47, 0x62, 0x59, 0x45, 0x75, 0x8e, 0x3d, 0x1f, 0xd7, 0xe9, + /*6d20:*/ 0xc4, 0xb2, 0x21, 0x5b, 0x96, 0x09, 0xd0, 0x4d, 0x22, 0x5e, 0xf3, 0xa2, 0x7b, 0x53, 0x0c, 0x6a, + /*6d30:*/ 0x91, 0xba, 0xd2, 0x4d, 0x9d, 0x3a, 0x68, 0xbd, 0x6a, 0xb7, 0x64, 0x7c, 0xd9, 0x18, 0xb3, 0x64, + /*6d40:*/ 0x2c, 0x81, 0x53, 0xdc, 0x01, 0xe6, 0x72, 0x6e, 0xcb, 0xb0, 0x6b, 0xce, 0x35, 0x2f, 0x15, 0xeb, + /*6d50:*/ 0xae, 0xfc, 0x7c, 0x34, 0xda, 0xde, 0xd8, 0x11, 0xc4, 0xb9, 0xf8, 0x73, 0x51, 0xdf, 0x45, 0x99, + /*6d60:*/ 0xae, 0x86, 0x8d, 0x80, 0x3e, 0xc1, 0x7e, 0x63, 0xae, 0xdd, 0x24, 0xbe, 0xe1, 0xfe, 0x71, 0x99, + /*6d70:*/ 0xaf, 0xf9, 0xec, 0x67, 0x14, 0xe2, 0x17, 0x3b, 0x0b, 0x5a, 0xb4, 0x40, 0x5d, 0x29, 0x05, 0x67, + /*6d80:*/ 0xae, 0x25, 0xef, 0xbf, 0x41, 0x47, 0x3d, 0x12, 0xd3, 0x80, 0xed, 0x57, 0xfa, 0x3e, 0x9c, 0x32, + /*6d90:*/ 0x3b, 0x04, 0xf0, 0xc8, 0x96, 0x67, 0x5a, 0x32, 0x04, 0x88, 0xa8, 0x81, 0x1f, 0x3f, 0xe7, 0xd5, + /*6da0:*/ 0x0f, 0xc5, 0x78, 0x8a, 0x95, 0x24, 0x72, 0xf2, 0x0b, 0xd4, 0xa5, 0xa9, 0x5a, 0xf1, 0xef, 0x53, + /*6db0:*/ 0x45, 0x53, 0x2b, 0xd2, 0xd7, 0x33, 0x02, 0x55, 0xcd, 0xd5, 0x11, 0x80, 0xa3, 0xbb, 0xf1, 0xed, + /*6dc0:*/ 0x5e, 0x4c, 0x50, 0xa2, 0x18, 0xd1, 0xcd, 0xd2, 0x30, 0x87, 0x49, 0x99, 0xd2, 0x33, 0x96, 0x50, + /*6dd0:*/ 0x71, 0xe4, 0x19, 0x8b, 0x59, 0x95, 0xd4, 0x88, 0x4d, 0x7b, 0x19, 0xdb, 0x09, 0x22, 0x02, 0x36, + /*6de0:*/ 0xc7, 0x60, 0xde, 0xfc, 0x22, 0x2c, 0x06, 0xa8, 0x75, 0x07, 0xe4, 0x3a, 0xa3, 0xfa, 0xa1, 0x85, + /*6df0:*/ 0x1e, 0x0c, 0x8d, 0x27, 0xa2, 0xa3, 0x0f, 0x68, 0x54, 0xee, 0xb5, 0x17, 0x48, 0x36, 0x7e, 0x9e, + /*6e00:*/ 0x7f, 0xe1, 0x8f, 0x09, 0xaa, 0xfe, 0x4f, 0x5d, 0xfd, 0x17, 0xe9, 0x42, 0x57, 0xa8, 0x3f, 0x18, + /*6e10:*/ 0xb6, 0x52, 0xf5, 0xa9, 0xcd, 0xd4, 0x30, 0x39, 0xa4, 0xc7, 0x1a, 0x6c, 0x7a, 0x81, 0xb7, 0xfb, + /*6e20:*/ 0xca, 0xab, 0xb8, 0xeb, 0x8b, 0x2b, 0x20, 0x4f, 0x0d, 0xbb, 0x44, 0x2f, 0xc7, 0x2c, 0x7c, 0x8a, + /*6e30:*/ 0x92, 0x48, 0x85, 0x92, 0xea, 0xd2, 0xde, 0x4e, 0xad, 0xec, 0x90, 0xe4, 0xe2, 0x9d, 0x4b, 0x7b, + /*6e40:*/ 0xce, 0xab, 0x43, 0x19, 0x65, 0xc2, 0xc2, 0xe2, 0x3c, 0xea, 0x7c, 0xd3, 0xd7, 0x76, 0x56, 0x5c, + /*6e50:*/ 0xd4, 0xad, 0x31, 0xb7, 0xeb, 0x3b, 0x54, 0x01, 0x18, 0x9f, 0x0a, 0xec, 0xb2, 0x0b, 0xcb, 0x5e, + /*6e60:*/ 0xf9, 0x2f, 0x13, 0x10, 0xce, 0xa5, 0x73, 0x89, 0x3a, 0x8f, 0x69, 0xa3, 0x61, 0xcc, 0x05, 0x10, + /*6e70:*/ 0x96, 0x67, 0x61, 0xfb, 0xde, 0x0d, 0xdc, 0x19, 0x7e, 0xc2, 0xf6, 0x0f, 0x00, 0x07, 0x52, 0x90, + /*6e80:*/ 0x36, 0xda, 0x40, 0xc5, 0x99, 0xa7, 0xd5, 0xd2, 0x13, 0x40, 0x8a, 0x49, 0xae, 0xd2, 0x53, 0x54, + /*6e90:*/ 0x37, 0x66, 0x64, 0x1c, 0x75, 0xb3, 0x31, 0xf6, 0x80, 0x86, 0xe3, 0xb1, 0x1d, 0xfb, 0x1b, 0x36, + /*6ea0:*/ 0x9b, 0x7d, 0x7a, 0x67, 0x64, 0x6a, 0x31, 0xd4, 0xc9, 0xc8, 0x11, 0x91, 0xb4, 0x78, 0x2a, 0x3f, + /*6eb0:*/ 0xef, 0x4f, 0x12, 0x7d, 0x03, 0xe9, 0x8c, 0x2a, 0x27, 0xd5, 0x70, 0x5c, 0x3b, 0x87, 0xc6, 0x7e, + /*6ec0:*/ 0xfb, 0x7e, 0x46, 0x08, 0x06, 0x17, 0x89, 0x29, 0x6c, 0x5d, 0xac, 0x0e, 0x96, 0x53, 0x77, 0x0f, + /*6ed0:*/ 0x6b, 0xd7, 0x07, 0xe7, 0xf4, 0xbd, 0xdf, 0x40, 0xbf, 0xf9, 0x91, 0x38, 0xdb, 0xb5, 0x0d, 0x0b, + /*6ee0:*/ 0x04, 0xcc, 0x5e, 0x4b, 0x62, 0xeb, 0xd1, 0xf6, 0xc9, 0x91, 0xf6, 0x27, 0xf1, 0x71, 0xf7, 0xe3, + /*6ef0:*/ 0x6f, 0xb0, 0x85, 0xa2, 0x79, 0x45, 0xe8, 0x0c, 0x15, 0xbf, 0x65, 0x29, 0xfa, 0x4f, 0xed, 0xea, + /*6f00:*/ 0x51, 0xe2, 0xc9, 0x57, 0x47, 0x84, 0x5f, 0x4d, 0x04, 0xb2, 0xa4, 0xc4, 0xc6, 0x6a, 0xef, 0x15, + /*6f10:*/ 0x27, 0xf3, 0x1c, 0xc6, 0x39, 0xd9, 0x26, 0xee, 0x32, 0xde, 0x51, 0x9c, 0x51, 0x64, 0x4b, 0xc7, + /*6f20:*/ 0xf1, 0xc3, 0x69, 0xcb, 0xce, 0x9c, 0x81, 0x1d, 0x5b, 0x25, 0xe8, 0x17, 0xbc, 0xf4, 0x42, 0x0a, + /*6f30:*/ 0x6f, 0x6a, 0x51, 0x99, 0x62, 0x29, 0x97, 0x39, 0x88, 0xc3, 0xc8, 0x4e, 0x58, 0x9a, 0x86, 0xe1, + /*6f40:*/ 0x36, 0xa6, 0x26, 0x6b, 0x06, 0x90, 0x56, 0x62, 0xc4, 0xb7, 0x24, 0x85, 0xd3, 0x37, 0x17, 0x36, + /*6f50:*/ 0x1a, 0xef, 0xce, 0x8c, 0xf3, 0x3f, 0x3c, 0x36, 0x19, 0x8f, 0xb7, 0x29, 0x69, 0x83, 0x31, 0xb1, + /*6f60:*/ 0x87, 0x8d, 0xc5, 0x2e, 0x6e, 0x0e, 0x4f, 0xdb, 0xee, 0xcd, 0x96, 0xbc, 0x59, 0x85, 0x80, 0xef, + /*6f70:*/ 0xe5, 0xcf, 0xa1, 0x9d, 0xf9, 0xe0, 0x2d, 0xe3, 0x2c, 0x38, 0xf2, 0x0a, 0x11, 0x1b, 0x3e, 0x58, + /*6f80:*/ 0x1b, 0x8a, 0x19, 0x32, 0x6c, 0x64, 0xb3, 0x78, 0xf1, 0x66, 0xbd, 0x9b, 0x69, 0xbe, 0x85, 0x53, + /*6f90:*/ 0xf7, 0x92, 0xa6, 0xd9, 0xc3, 0xac, 0x77, 0xba, 0x52, 0x64, 0x89, 0x30, 0xd6, 0x30, 0x4f, 0xa6, + /*6fa0:*/ 0xc2, 0xec, 0xd9, 0x96, 0x50, 0xfb, 0x30, 0xe4, 0xb6, 0xea, 0xb9, 0x37, 0xfe, 0x5c, 0x0f, 0x8c, + /*6fb0:*/ 0x1b, 0xae, 0x0a, 0x82, 0xc6, 0x00, 0x2c, 0x9c, 0xca, 0xb2, 0x44, 0xc0, 0x87, 0x5d, 0x9e, 0x81, + /*6fc0:*/ 0x0b, 0x08, 0x2d, 0xf0, 0xde, 0x57, 0xd7, 0x67, 0x02, 0xf8, 0x8d, 0x14, 0x4e, 0x37, 0xef, 0x06, + /*6fd0:*/ 0x7b, 0xfe, 0x96, 0x0f, 0x7b, 0xc0, 0x28, 0xe6, 0x4e, 0x88, 0xba, 0xc9, 0x78, 0x3c, 0x3e, 0x35, + /*6fe0:*/ 0x82, 0x92, 0x27, 0x11, 0x95, 0x5d, 0x4b, 0x3d, 0xb6, 0x70, 0x57, 0x05, 0xfd, 0x2f, 0x8a, 0xd4, + /*6ff0:*/ 0xa4, 0xd5, 0x80, 0x1f, 0xde, 0xb8, 0x8c, 0xaa, 0x46, 0x75, 0x23, 0x34, 0x7a, 0x67, 0xf5, 0x08, + /*7000:*/ 0xed, 0x66, 0xd7, 0x1e, 0x1d, 0x17, 0x75, 0x41, 0x8e, 0xaa, 0x72, 0x6b, 0xeb, 0x46, 0x33, 0x33, + /*7010:*/ 0x5b, 0xb4, 0x19, 0x3f, 0x1b, 0x51, 0xdf, 0x9c, 0x74, 0x3a, 0x8c, 0x43, 0x72, 0xf6, 0xf4, 0xb4, + /*7020:*/ 0x53, 0x29, 0x76, 0x5f, 0x71, 0x61, 0x79, 0x8a, 0x29, 0xe7, 0x06, 0x81, 0xe2, 0xc7, 0xd4, 0x4d, + /*7030:*/ 0x86, 0x5a, 0xcb, 0xf8, 0xcd, 0x90, 0x0d, 0x7c, 0x72, 0x04, 0xf3, 0xc0, 0x0a, 0x7f, 0xb1, 0xca, + /*7040:*/ 0xab, 0x5c, 0x81, 0x6a, 0x66, 0x1e, 0x09, 0x66, 0xbd, 0x39, 0x3b, 0xec, 0x9e, 0xa1, 0xf7, 0xfa, + /*7050:*/ 0x1d, 0xbe, 0x5c, 0x31, 0x08, 0xcd, 0x9b, 0x32, 0xf7, 0x1f, 0x50, 0x3a, 0x59, 0xbd, 0x6a, 0xa0, + /*7060:*/ 0xea, 0xcc, 0xcd, 0x50, 0x2c, 0x54, 0x5b, 0x2d, 0x0f, 0xc2, 0x68, 0xe4, 0xe1, 0x2c, 0xf9, 0xbf, + /*7070:*/ 0x50, 0x55, 0x2c, 0x53, 0x9a, 0x07, 0xb2, 0xe4, 0x9d, 0x0f, 0xde, 0xc4, 0x9e, 0xe5, 0xe8, 0x26, + /*7080:*/ 0xb3, 0x7a, 0x40, 0x35, 0xc1, 0x1b, 0x28, 0xc0, 0xe4, 0x83, 0x07, 0x32, 0xc0, 0xfb, 0xb5, 0x68, + /*7090:*/ 0xba, 0xf2, 0xab, 0xe2, 0xe5, 0xaf, 0x17, 0x4e, 0x0a, 0x9d, 0xf9, 0x7d, 0x8a, 0x8b, 0xc4, 0x5d, + /*70a0:*/ 0x36, 0x14, 0xe2, 0x96, 0x91, 0xd2, 0x3d, 0x39, 0x6e, 0xda, 0xb4, 0xe3, 0xcb, 0x43, 0x73, 0xb4, + /*70b0:*/ 0x99, 0xa2, 0x4a, 0x4b, 0x78, 0x35, 0x09, 0xe6, 0x37, 0xa7, 0xe3, 0xf5, 0x1b, 0xac, 0x0e, 0x0f, + /*70c0:*/ 0x84, 0xd4, 0xd3, 0xf8, 0x37, 0xee, 0x8d, 0x80, 0x6a, 0xd0, 0xd5, 0xb6, 0x67, 0xeb, 0x4b, 0xc0, + /*70d0:*/ 0x69, 0x9f, 0xe6, 0x45, 0xb8, 0xe0, 0x84, 0x3c, 0xe3, 0xab, 0x9e, 0xd7, 0x83, 0x5b, 0x75, 0x48, + /*70e0:*/ 0xdd, 0xde, 0x89, 0x82, 0x1e, 0x68, 0x96, 0x20, 0x29, 0x3b, 0xa8, 0x8a, 0xfc, 0xd3, 0x85, 0x69, + /*70f0:*/ 0x3a, 0x94, 0x7e, 0x1c, 0xe1, 0x00, 0xb8, 0xdf, 0xe7, 0xa8, 0x5f, 0x87, 0xce, 0x95, 0xf1, 0xb7, + /*7100:*/ 0x69, 0x97, 0xac, 0x98, 0xdb, 0x50, 0x77, 0x37, 0x99, 0xae, 0xe8, 0x7e, 0xb1, 0x95, 0xf3, 0x10, + /*7110:*/ 0x8b, 0x97, 0x7d, 0xfd, 0x2b, 0x9c, 0xb5, 0x09, 0x5f, 0x9d, 0x0a, 0xa1, 0x08, 0x37, 0x89, 0xe4, + /*7120:*/ 0x17, 0xaf, 0xd3, 0x33, 0xd2, 0xe5, 0x33, 0x9a, 0xe1, 0xab, 0x83, 0xdc, 0x20, 0xdd, 0xe1, 0xdf, + /*7130:*/ 0x25, 0x7d, 0x72, 0x29, 0x7e, 0x69, 0x97, 0x69, 0xd4, 0xdc, 0x8b, 0xda, 0x92, 0x99, 0x21, 0xec, + /*7140:*/ 0xe1, 0x3c, 0x7f, 0x9c, 0xc3, 0xac, 0x3a, 0x55, 0xde, 0x82, 0xb7, 0x98, 0x1f, 0xd3, 0xa9, 0x7c, + /*7150:*/ 0xdb, 0x71, 0x5b, 0xd8, 0xe9, 0xb9, 0x01, 0x0d, 0xb7, 0x36, 0x9d, 0xa4, 0xde, 0x90, 0x57, 0x43, + /*7160:*/ 0x88, 0xdf, 0xd4, 0xaf, 0xbf, 0xd1, 0x4d, 0xdd, 0x25, 0xd1, 0xf0, 0x6b, 0x99, 0xc2, 0x1e, 0xda, + /*7170:*/ 0x22, 0x52, 0xc1, 0xbc, 0x09, 0xbd, 0xdf, 0x2b, 0x76, 0xfc, 0xbf, 0xc4, 0x43, 0x0b, 0x8f, 0x22, + /*7180:*/ 0x09, 0x8d, 0x31, 0x30, 0x82, 0x56, 0x96, 0x5d, 0x65, 0xa5, 0x1f, 0xa2, 0x6c, 0x18, 0x95, 0x07, + /*7190:*/ 0x5f, 0xd1, 0xa5, 0x6b, 0xbc, 0x7a, 0xbb, 0x90, 0xbb, 0x75, 0xc6, 0xba, 0xac, 0xcb, 0x78, 0x3c, + /*71a0:*/ 0xa2, 0x10, 0x68, 0x07, 0x5a, 0xf5, 0x61, 0xc9, 0x44, 0x90, 0x44, 0x2c, 0xe3, 0x00, 0x2d, 0xb1, + /*71b0:*/ 0x52, 0x64, 0x27, 0xd2, 0x0a, 0xc2, 0x0c, 0x75, 0x67, 0x5b, 0xaf, 0xea, 0x5f, 0xbe, 0xea, 0x35, + /*71c0:*/ 0x88, 0x19, 0x2d, 0x1c, 0xa5, 0x84, 0x06, 0xc5, 0x5c, 0x95, 0xc7, 0x4c, 0x30, 0xf1, 0x06, 0xed, + /*71d0:*/ 0xa9, 0x41, 0x66, 0x5e, 0x2c, 0x97, 0x8a, 0x87, 0x5e, 0xb6, 0xee, 0x5e, 0x86, 0xf4, 0xd0, 0xf2, + /*71e0:*/ 0x47, 0x1f, 0x3b, 0x1e, 0xc2, 0xfa, 0x49, 0x50, 0x28, 0x80, 0xd1, 0x9e, 0xf5, 0x5c, 0x55, 0xee, + /*71f0:*/ 0x1c, 0x49, 0x6d, 0xd2, 0xf2, 0x81, 0x3e, 0x19, 0x2a, 0x35, 0xd4, 0xae, 0xd2, 0xe8, 0xf7, 0x9f, + /*7200:*/ 0x08, 0x95, 0x97, 0x15, 0xb1, 0x16, 0x3e, 0xb3, 0x43, 0xf1, 0x95, 0xbf, 0xc8, 0x7b, 0xa9, 0x09, + /*7210:*/ 0xd5, 0x82, 0x6b, 0x0c, 0x4a, 0xe0, 0x74, 0xa7, 0xd8, 0x3d, 0x21, 0x9c, 0xf4, 0x9f, 0xf1, 0xa0, + /*7220:*/ 0x13, 0x7c, 0x48, 0x0d, 0x2c, 0x8b, 0xb7, 0x71, 0xb7, 0xe5, 0x1c, 0x30, 0x36, 0xe8, 0x2a, 0x72, + /*7230:*/ 0x92, 0x9b, 0xf0, 0x92, 0xdc, 0x9d, 0x3f, 0xd3, 0x3e, 0xe3, 0xc3, 0x22, 0xff, 0x20, 0x06, 0x91, + /*7240:*/ 0x7f, 0x39, 0xe4, 0x99, 0x68, 0xd2, 0xaa, 0x0b, 0x1c, 0x1c, 0xc2, 0x3b, 0xa0, 0x0b, 0x65, 0x47, + /*7250:*/ 0xf9, 0x25, 0x8e, 0xac, 0x71, 0x8f, 0x17, 0x4d, 0xed, 0x64, 0x35, 0xb8, 0x4f, 0x28, 0x90, 0x1d, + /*7260:*/ 0x44, 0x9b, 0xb3, 0xe5, 0x42, 0x5b, 0x77, 0x47, 0x3c, 0x17, 0x38, 0x9d, 0x13, 0xe7, 0xca, 0x9e, + /*7270:*/ 0xf1, 0x86, 0xcf, 0xe3, 0x21, 0x35, 0x9a, 0x3d, 0x9b, 0x0e, 0x40, 0xf7, 0x56, 0x30, 0x22, 0x48, + /*7280:*/ 0x0b, 0xd6, 0xae, 0x1b, 0xf9, 0x2d, 0xbd, 0x62, 0x4f, 0xc7, 0xd3, 0x59, 0x0a, 0x26, 0xc9, 0xc8, + /*7290:*/ 0x0e, 0xe0, 0x28, 0x8a, 0x8d, 0x46, 0x42, 0x48, 0xea, 0x78, 0x8d, 0x51, 0x3c, 0x34, 0x84, 0x96, + /*72a0:*/ 0x3e, 0xcc, 0xf0, 0x98, 0x94, 0x68, 0x81, 0xed, 0xd3, 0xe1, 0x0d, 0x46, 0x3d, 0xcb, 0xea, 0xf0, + /*72b0:*/ 0xc6, 0x7e, 0x15, 0x97, 0x86, 0x0d, 0xd0, 0x84, 0xcb, 0x1b, 0xa6, 0x0e, 0xce, 0xa4, 0x7c, 0xbd, + /*72c0:*/ 0x65, 0x0c, 0x9f, 0x98, 0x7d, 0x13, 0x8e, 0x7a, 0x0a, 0xa9, 0xa7, 0x20, 0x3b, 0xa1, 0x4b, 0xda, + /*72d0:*/ 0xe7, 0x8a, 0x2e, 0x3f, 0xe2, 0xff, 0x11, 0xb7, 0x08, 0x8b, 0x80, 0xc9, 0xa1, 0xb4, 0xf6, 0xde, + /*72e0:*/ 0xce, 0x58, 0xb7, 0xf6, 0x5e, 0x73, 0xdb, 0xfe, 0x18, 0x87, 0x1e, 0x45, 0xe7, 0xa1, 0x84, 0xc2, + /*72f0:*/ 0xfa, 0x6a, 0x90, 0x4b, 0x4e, 0x41, 0x28, 0xc0, 0x1c, 0xb7, 0x1d, 0xc2, 0xb6, 0xa2, 0x0b, 0x08, + /*7300:*/ 0x0b, 0x61, 0xcb, 0xf6, 0xd6, 0xa1, 0x3a, 0x36, 0x23, 0x9b, 0x5c, 0x08, 0x91, 0x34, 0xfa, 0xc5, + /*7310:*/ 0x46, 0x0c, 0x54, 0x67, 0x59, 0x7f, 0x90, 0xc3, 0x05, 0x58, 0x3a, 0xee, 0x28, 0x62, 0x7b, 0xf7, + /*7320:*/ 0x25, 0xd5, 0x31, 0x6c, 0x03, 0x15, 0x7a, 0xf5, 0x3d, 0xd5, 0x53, 0x5a, 0xe6, 0xd3, 0x95, 0x6d, + /*7330:*/ 0x56, 0xb9, 0x8b, 0x3a, 0xca, 0x52, 0xe5, 0xe2, 0x6d, 0xfe, 0xf0, 0x39, 0x54, 0x7c, 0xdc, 0x10, + /*7340:*/ 0xd5, 0x46, 0xe3, 0x3b, 0xad, 0x1a, 0x3b, 0x49, 0x55, 0x28, 0x7a, 0x03, 0x3e, 0x0f, 0x4e, 0x11, + /*7350:*/ 0x64, 0x1b, 0x27, 0xa5, 0x63, 0x48, 0x70, 0x41, 0xff, 0x45, 0x85, 0x91, 0xce, 0x5b, 0xbb, 0x69, + /*7360:*/ 0x84, 0x15, 0x9d, 0x80, 0xf1, 0x1e, 0xad, 0x8e, 0xca, 0x73, 0x6c, 0x9a, 0x15, 0xd8, 0x47, 0xc1, + /*7370:*/ 0x99, 0x46, 0x4a, 0xd1, 0x70, 0x03, 0x24, 0x59, 0x1c, 0x42, 0x43, 0xf0, 0x6d, 0x49, 0xb9, 0xe0, + /*7380:*/ 0x1a, 0x20, 0x4e, 0x53, 0x08, 0x12, 0x31, 0x45, 0x11, 0xdf, 0xd5, 0x40, 0x42, 0xf5, 0x96, 0xa8, + /*7390:*/ 0x6c, 0x00, 0x0f, 0xbc, 0x92, 0xdc, 0xb3, 0x08, 0x15, 0xd6, 0x36, 0xff, 0x6b, 0x34, 0xfc, 0x42, + /*73a0:*/ 0x90, 0x30, 0x27, 0x6d, 0xf5, 0x65, 0x3c, 0x49, 0x22, 0x0c, 0x26, 0x6c, 0x8a, 0xb7, 0x26, 0xf0, + /*73b0:*/ 0xec, 0xcc, 0x00, 0x5f, 0xbd, 0x54, 0x31, 0x04, 0xe6, 0x9c, 0xe4, 0x54, 0x7b, 0x3e, 0x41, 0xe6, + /*73c0:*/ 0xcd, 0xda, 0x15, 0x1c, 0xaa, 0xb7, 0x27, 0x5f, 0xfd, 0xf6, 0xde, 0x9f, 0x04, 0xdd, 0x0e, 0xad, + /*73d0:*/ 0xda, 0xda, 0x34, 0xd0, 0x61, 0x64, 0xfa, 0x34, 0x3a, 0x9e, 0x8b, 0xb7, 0xaa, 0x35, 0x00, 0xa8, + /*73e0:*/ 0x94, 0x62, 0xbc, 0xac, 0xcb, 0x94, 0xeb, 0x92, 0x66, 0xc5, 0xc5, 0x54, 0x05, 0xb7, 0x86, 0x6c, + /*73f0:*/ 0x98, 0xa5, 0xa6, 0xd4, 0x83, 0xf0, 0x0c, 0x80, 0xa2, 0x82, 0x8c, 0x51, 0x31, 0xad, 0xe0, 0xa0, + /*7400:*/ 0x95, 0x71, 0xd1, 0xb4, 0x12, 0xd5, 0xcd, 0x25, 0x2f, 0x09, 0xa3, 0xd5, 0x1c, 0xe4, 0x4c, 0x73, + /*7410:*/ 0x94, 0x19, 0x1f, 0xe5, 0xcb, 0x66, 0xfa, 0x14, 0xaa, 0x1c, 0xdf, 0xdb, 0x48, 0x95, 0x9c, 0x20, + /*7420:*/ 0xd8, 0xb3, 0x46, 0xc9, 0xc7, 0xf6, 0x0e, 0x63, 0x1c, 0xec, 0x4e, 0xbe, 0xdd, 0x08, 0xdb, 0x94, + /*7430:*/ 0x2d, 0x38, 0x86, 0xae, 0xd3, 0x76, 0x04, 0xb2, 0xc1, 0x0e, 0x63, 0x6c, 0x22, 0xd5, 0xc9, 0x7f, + /*7440:*/ 0x6f, 0x83, 0x54, 0x52, 0x9f, 0xc5, 0x0a, 0x43, 0xa1, 0xa8, 0x9c, 0x4a, 0x1e, 0x7a, 0x2f, 0xcf, + /*7450:*/ 0x56, 0x9a, 0x46, 0x83, 0xc0, 0x2e, 0x43, 0x62, 0x54, 0x16, 0x37, 0xdd, 0x9e, 0xcf, 0xcb, 0xc5, + /*7460:*/ 0xe1, 0x8e, 0x5f, 0x83, 0xc8, 0xac, 0x6e, 0xb3, 0xcf, 0xdc, 0x3d, 0x14, 0xb0, 0x99, 0x25, 0x47, + /*7470:*/ 0x1f, 0xd6, 0xa9, 0xe3, 0x8f, 0x29, 0x98, 0x6d, 0xf5, 0xac, 0x2d, 0x6b, 0x07, 0x15, 0x71, 0xa0, + /*7480:*/ 0x4b, 0x5d, 0xd7, 0x5f, 0x55, 0xcc, 0xca, 0xd2, 0x9e, 0xd5, 0x8c, 0x42, 0x61, 0xaf, 0xee, 0x46, + /*7490:*/ 0x2d, 0x10, 0xce, 0x31, 0xf8, 0xeb, 0x96, 0xdd, 0x29, 0x1d, 0xb6, 0x75, 0x79, 0x85, 0xf6, 0xc9, + /*74a0:*/ 0x28, 0x17, 0x8c, 0x23, 0x56, 0x0e, 0xc0, 0xb2, 0x96, 0xdf, 0x21, 0xbf, 0x14, 0x8b, 0x3e, 0xe3, + /*74b0:*/ 0x21, 0xe1, 0x48, 0x07, 0x1c, 0x47, 0x8d, 0x12, 0xc2, 0xdd, 0xfd, 0x8e, 0x22, 0xbf, 0x68, 0xa9, + /*74c0:*/ 0xe1, 0x2e, 0x96, 0x3a, 0x1d, 0xa0, 0x7e, 0x94, 0xfa, 0x9c, 0xbb, 0x72, 0xf2, 0xa1, 0xc7, 0x17, + /*74d0:*/ 0x65, 0x8a, 0xb6, 0x8f, 0xdf, 0x18, 0xdd, 0x27, 0x11, 0x9d, 0x32, 0xdf, 0x9d, 0xb1, 0x00, 0x83, + /*74e0:*/ 0x00, 0xe3, 0x2c, 0xc1, 0xd5, 0x6e, 0x7d, 0x05, 0x4e, 0x93, 0x48, 0x03, 0x86, 0x3c, 0xe7, 0xe2, + /*74f0:*/ 0x5a, 0x59, 0x25, 0x4e, 0xa9, 0xb5, 0x6a, 0x27, 0x3e, 0x06, 0x75, 0xea, 0xca, 0x1a, 0x70, 0x20, + /*7500:*/ 0xbb, 0x04, 0xca, 0x0d, 0x7c, 0xe3, 0x3e, 0x0b, 0xe7, 0xdb, 0xeb, 0xbe, 0x41, 0x4d, 0x04, 0xd5, + /*7510:*/ 0x6f, 0xa2, 0x2c, 0x42, 0x5f, 0xc5, 0x6b, 0x66, 0x10, 0xf4, 0xb9, 0x14, 0x44, 0x7d, 0xfc, 0xa3, + /*7520:*/ 0x42, 0x95, 0x2b, 0xc3, 0x9e, 0x31, 0x75, 0x8f, 0x92, 0x25, 0xfa, 0xf5, 0xde, 0x86, 0x5f, 0x57, + /*7530:*/ 0xa8, 0x26, 0x41, 0x39, 0xc9, 0xc7, 0x56, 0x1f, 0x4a, 0x52, 0x7a, 0x25, 0x82, 0x1d, 0xa2, 0xd1, + /*7540:*/ 0xcd, 0x35, 0xa4, 0x1b, 0x73, 0xd8, 0x8e, 0x17, 0x2d, 0xfb, 0x49, 0x60, 0x54, 0x60, 0x1a, 0x7d, + /*7550:*/ 0x16, 0xe3, 0x8a, 0xa5, 0xd0, 0x2f, 0x81, 0xc7, 0xb4, 0x75, 0xb6, 0xba, 0xfc, 0xae, 0x96, 0x25, + /*7560:*/ 0x4e, 0xba, 0x0d, 0x8a, 0x22, 0x59, 0xe8, 0xa3, 0xd3, 0xb0, 0x87, 0xc1, 0xa7, 0x72, 0x07, 0x51, + /*7570:*/ 0x60, 0xed, 0x1c, 0xd3, 0xb1, 0x2d, 0xfb, 0xb5, 0xbc, 0xb4, 0x01, 0x22, 0x0e, 0xfe, 0x75, 0xfa, + /*7580:*/ 0x9a, 0x4b, 0xe2, 0xb3, 0x89, 0xb9, 0xe9, 0x58, 0x63, 0xf5, 0x14, 0xec, 0x1f, 0x18, 0x4c, 0x3a, + /*7590:*/ 0xf0, 0xfd, 0x0f, 0x75, 0x29, 0x40, 0x51, 0x7e, 0x39, 0xfd, 0x74, 0xa1, 0xf5, 0x7d, 0xf5, 0x6b, + /*75a0:*/ 0x15, 0x91, 0xf1, 0xd5, 0x72, 0x23, 0x07, 0x58, 0xd8, 0x7b, 0x85, 0xe3, 0x66, 0x31, 0x2b, 0x8a, + /*75b0:*/ 0xa4, 0x79, 0x58, 0x71, 0x43, 0xdb, 0x81, 0xdd, 0xb4, 0x49, 0x7d, 0x6c, 0xd7, 0xea, 0x6c, 0x07, + /*75c0:*/ 0x01, 0xfe, 0x6b, 0x50, 0x43, 0x49, 0x37, 0xd4, 0x63, 0x4f, 0xaa, 0x59, 0x44, 0xa1, 0x89, 0xac, + /*75d0:*/ 0x4c, 0x41, 0x7c, 0x0a, 0x30, 0x95, 0xa9, 0xb1, 0x4b, 0x64, 0x1e, 0x5c, 0x4b, 0xee, 0xe0, 0x0c, + /*75e0:*/ 0x7b, 0xa0, 0xc8, 0x8b, 0x3c, 0xe7, 0xec, 0x19, 0xc1, 0x9b, 0x06, 0x1c, 0xae, 0x83, 0x11, 0xc4, + /*75f0:*/ 0x48, 0xb7, 0xda, 0x18, 0xd7, 0xf3, 0x77, 0x32, 0xf4, 0x15, 0xc3, 0x62, 0x0a, 0x01, 0x98, 0x5a, + /*7600:*/ 0x5f, 0x43, 0xfb, 0x25, 0x23, 0xde, 0xfe, 0xdb, 0x2c, 0x88, 0xaa, 0x5e, 0x57, 0xcc, 0x33, 0x3c, + /*7610:*/ 0x66, 0x4a, 0x85, 0x4f, 0xfe, 0xf3, 0x72, 0x2e, 0xba, 0x3e, 0x4c, 0x31, 0x7e, 0x48, 0xe4, 0xe3, + /*7620:*/ 0x2d, 0x6e, 0xbc, 0x1c, 0x0f, 0x88, 0x58, 0x12, 0x35, 0xfa, 0x3f, 0xe0, 0xe2, 0xc9, 0x62, 0xee, + /*7630:*/ 0xe3, 0x5d, 0x3b, 0x33, 0x21, 0x14, 0x29, 0x3f, 0x99, 0x5d, 0x81, 0x54, 0x27, 0xb8, 0xba, 0xc6, + /*7640:*/ 0xcb, 0x61, 0x60, 0x74, 0xee, 0xbc, 0x9b, 0xa7, 0x43, 0x5a, 0x05, 0xcb, 0x7b, 0x82, 0x80, 0xe3, + /*7650:*/ 0xea, 0xed, 0x26, 0x35, 0xa9, 0x0f, 0xb8, 0xf3, 0x3f, 0x6b, 0x06, 0xd7, 0x91, 0x7a, 0x29, 0x1f, + /*7660:*/ 0x37, 0x2e, 0x7a, 0xac, 0x48, 0xda, 0x47, 0x0f, 0x39, 0x50, 0x38, 0xa7, 0x3d, 0x3b, 0x4e, 0xbf, + /*7670:*/ 0x78, 0x1c, 0x62, 0x97, 0x46, 0xd9, 0x9a, 0x34, 0x68, 0x9e, 0x2d, 0x60, 0x8e, 0x74, 0xfd, 0xfa, + /*7680:*/ 0xf1, 0xad, 0x01, 0x6f, 0x71, 0xc5, 0xc1, 0xc0, 0x2c, 0x34, 0x3e, 0xe9, 0x26, 0xeb, 0xa6, 0xce, + /*7690:*/ 0xf7, 0x9c, 0x25, 0x0b, 0x9f, 0x38, 0x54, 0xda, 0x17, 0xf5, 0x57, 0x7e, 0xfc, 0xd2, 0x60, 0xaf, + /*76a0:*/ 0x67, 0x58, 0x29, 0x71, 0x49, 0xeb, 0x4e, 0x91, 0x01, 0x42, 0x35, 0xd6, 0x18, 0x77, 0x72, 0xb4, + /*76b0:*/ 0xad, 0x56, 0xde, 0xa7, 0x36, 0x13, 0xfd, 0x7d, 0x8b, 0xe3, 0xf3, 0x5d, 0xb5, 0xb5, 0x8e, 0x30, + /*76c0:*/ 0x60, 0x44, 0x24, 0x9f, 0x34, 0xc0, 0x55, 0xf7, 0xab, 0xd1, 0x50, 0xfa, 0x3b, 0x92, 0x84, 0x90, + /*76d0:*/ 0xc0, 0xc3, 0xca, 0x33, 0xec, 0x34, 0x88, 0x29, 0xcd, 0x62, 0xc9, 0xd6, 0xda, 0x1c, 0x36, 0x57, + /*76e0:*/ 0x33, 0x6a, 0xe5, 0x11, 0x52, 0x63, 0xed, 0xcf, 0x63, 0x07, 0x34, 0x72, 0xf5, 0xf8, 0xc2, 0xba, + /*76f0:*/ 0xd5, 0x20, 0xde, 0xcc, 0x8f, 0xc6, 0xf1, 0x20, 0x2b, 0x34, 0x78, 0xfb, 0x73, 0x42, 0x98, 0xa8, + /*7700:*/ 0x69, 0x4c, 0x1e, 0xd1, 0xdb, 0x9a, 0xe6, 0x3c, 0x68, 0x79, 0x10, 0x5f, 0xbb, 0xbc, 0x4f, 0x54, + /*7710:*/ 0x58, 0x0c, 0xee, 0x5e, 0x83, 0x47, 0x29, 0xd7, 0xee, 0xc7, 0xea, 0xc9, 0xd3, 0x94, 0xc5, 0x7a, + /*7720:*/ 0x73, 0xfd, 0x72, 0x43, 0x15, 0x7f, 0xfb, 0x5d, 0x05, 0x2f, 0x3a, 0x69, 0x9e, 0x58, 0xcc, 0xd3, + /*7730:*/ 0xf5, 0xbd, 0x47, 0x6f, 0xbd, 0x63, 0xfb, 0xbb, 0x5f, 0xe5, 0xa0, 0x28, 0x88, 0x29, 0x05, 0xa0, + /*7740:*/ 0x1d, 0xbc, 0x48, 0xd9, 0xbc, 0xd5, 0xa0, 0xcc, 0x27, 0x46, 0xf2, 0xca, 0xee, 0xe9, 0x6b, 0xa3, + /*7750:*/ 0x63, 0xed, 0xf5, 0xe8, 0x5e, 0x1b, 0x1d, 0x91, 0xa4, 0x50, 0xb1, 0x61, 0x95, 0x53, 0xb4, 0xd6, + /*7760:*/ 0xda, 0x3d, 0x56, 0x92, 0xbb, 0x85, 0x79, 0x86, 0x1d, 0x32, 0xcd, 0xeb, 0xfd, 0x86, 0x57, 0x2f, + /*7770:*/ 0x35, 0xd1, 0x6d, 0xd8, 0xab, 0x6a, 0x86, 0xec, 0xa3, 0xe9, 0x9b, 0x1b, 0xa7, 0x24, 0x1c, 0xc4, + /*7780:*/ 0xad, 0x5d, 0xc4, 0x71, 0xad, 0xe5, 0xff, 0xcf, 0x6e, 0xf8, 0x7b, 0xfb, 0x24, 0xb3, 0xe7, 0x49, + /*7790:*/ 0x6d, 0xe0, 0xfa, 0xe2, 0x32, 0xfc, 0xcb, 0xb8, 0x10, 0x30, 0x8b, 0x57, 0x45, 0x0c, 0xe6, 0x40, + /*77a0:*/ 0x45, 0x52, 0xbf, 0xab, 0x4d, 0x16, 0xc9, 0x89, 0x67, 0x3f, 0xb7, 0x01, 0x65, 0x3e, 0xa8, 0x60, + /*77b0:*/ 0x7d, 0x02, 0x1e, 0xba, 0xe7, 0x3d, 0x01, 0x7e, 0x84, 0x60, 0xce, 0xed, 0xac, 0xc3, 0x20, 0x4b, + /*77c0:*/ 0x2b, 0xcd, 0x7c, 0x48, 0xbe, 0xeb, 0x62, 0x4b, 0x1e, 0xea, 0x14, 0x52, 0xe9, 0xe5, 0xc0, 0xe7, + /*77d0:*/ 0xf8, 0x38, 0xf9, 0x9d, 0xaa, 0x1c, 0x5a, 0x45, 0xf7, 0x17, 0x34, 0xc4, 0xcd, 0x20, 0xa7, 0xa4, + /*77e0:*/ 0x63, 0xd8, 0xbd, 0x4b, 0xf1, 0xdb, 0x91, 0x00, 0xd7, 0x2e, 0x65, 0xa9, 0xbd, 0x50, 0xe5, 0x0a, + /*77f0:*/ 0xda, 0x2f, 0x8f, 0x30, 0xc2, 0xf3, 0xf1, 0xa5, 0x7f, 0x36, 0x82, 0x18, 0xb7, 0xbb, 0x28, 0xb5, + /*7800:*/ 0xd5, 0x8d, 0x06, 0xcb, 0x99, 0x9a, 0xa6, 0xc5, 0x56, 0xfe, 0xca, 0x08, 0x92, 0x79, 0x32, 0xdd, + /*7810:*/ 0xbc, 0x82, 0x04, 0x70, 0x2c, 0xfd, 0x26, 0x47, 0x0c, 0xa2, 0x4c, 0xf5, 0xb3, 0x86, 0x86, 0xdf, + /*7820:*/ 0xd0, 0x43, 0x37, 0xd4, 0x5c, 0x34, 0xae, 0x35, 0x13, 0xc1, 0xc5, 0xa8, 0xca, 0x63, 0x8e, 0xb6, + /*7830:*/ 0xb3, 0xb5, 0x1d, 0xd0, 0x79, 0x77, 0xef, 0x84, 0x88, 0xf0, 0xba, 0xe9, 0xd0, 0x9a, 0x6c, 0x55, + /*7840:*/ 0xa0, 0xd9, 0x0e, 0x5d, 0x9e, 0x6d, 0x6e, 0x1f, 0x9d, 0xcc, 0x1c, 0x68, 0x16, 0xa5, 0xe5, 0x86, + /*7850:*/ 0x24, 0x83, 0x2b, 0xb7, 0xc6, 0xac, 0xa4, 0xa7, 0x38, 0xca, 0xdf, 0xec, 0x9e, 0x7c, 0x7d, 0x63, + /*7860:*/ 0x6e, 0x5e, 0xb2, 0x59, 0x24, 0xb5, 0xed, 0x8e, 0xa7, 0xf0, 0x63, 0x85, 0x48, 0x73, 0x6c, 0xa8, + /*7870:*/ 0xe6, 0x95, 0x6c, 0xd6, 0xf4, 0x7e, 0xdc, 0xa2, 0x61, 0x00, 0xf1, 0x9f, 0xf4, 0x51, 0x5b, 0x1a, + /*7880:*/ 0x47, 0xdc, 0x57, 0x16, 0xf1, 0x8f, 0x0c, 0xfa, 0xa3, 0xb3, 0x3d, 0xe8, 0xd5, 0xc8, 0x6a, 0x52, + /*7890:*/ 0xb8, 0xcb, 0x57, 0x9a, 0x81, 0xb3, 0x5e, 0x47, 0xb2, 0xcb, 0x64, 0x7e, 0x2f, 0x92, 0xb2, 0x57, + /*78a0:*/ 0xd1, 0x3a, 0x9f, 0x6f, 0xc6, 0xeb, 0x5e, 0xbf, 0x84, 0xf9, 0x7d, 0x31, 0x63, 0x96, 0x3d, 0x4c, + /*78b0:*/ 0x17, 0x38, 0x91, 0xd3, 0xde, 0xe6, 0x04, 0xf6, 0xe9, 0xa2, 0x7e, 0xd6, 0xe9, 0xd4, 0x50, 0x61, + /*78c0:*/ 0x5c, 0x75, 0x57, 0xee, 0x7e, 0x03, 0xe9, 0x06, 0x8c, 0x57, 0x4a, 0x8d, 0xc8, 0x54, 0x08, 0xca, + /*78d0:*/ 0x17, 0xa8, 0x9c, 0x27, 0x28, 0xc3, 0xe4, 0x85, 0xd1, 0x2d, 0x33, 0x44, 0x74, 0xc6, 0x50, 0x42, + /*78e0:*/ 0xd9, 0x29, 0x00, 0x38, 0xa4, 0xe6, 0xb9, 0xf3, 0xfa, 0x40, 0xb9, 0x83, 0x20, 0xed, 0x22, 0xb7, + /*78f0:*/ 0xf0, 0xf4, 0xe7, 0x10, 0x73, 0xc3, 0xe9, 0x5a, 0xe6, 0xed, 0x21, 0x7e, 0x7c, 0xc6, 0x78, 0x00, + /*7900:*/ 0x94, 0x02, 0x42, 0x91, 0xa0, 0x24, 0x71, 0x85, 0x14, 0x97, 0x94, 0xfa, 0x75, 0x84, 0xbc, 0x36, + /*7910:*/ 0xd1, 0x69, 0xb3, 0x13, 0xf2, 0x67, 0x0a, 0xc3, 0xcf, 0xe5, 0x4c, 0x9f, 0x49, 0xc3, 0xc2, 0x35, + /*7920:*/ 0xdf, 0xb2, 0xb5, 0x0e, 0xf6, 0x05, 0x77, 0x6e, 0x5f, 0x84, 0x58, 0x8c, 0x99, 0xee, 0xb4, 0xe7, + /*7930:*/ 0x38, 0xa1, 0xa6, 0x31, 0x62, 0x20, 0x1f, 0x13, 0x4b, 0xc8, 0x44, 0x6b, 0x06, 0x3d, 0xd3, 0x69, + /*7940:*/ 0x89, 0x24, 0xa1, 0xa3, 0x78, 0x1f, 0x0b, 0x49, 0x0b, 0x59, 0xa7, 0x75, 0x02, 0x13, 0x33, 0xe2, + /*7950:*/ 0x5c, 0x20, 0x5b, 0xe5, 0x92, 0x61, 0x7a, 0x82, 0xaf, 0x4a, 0x08, 0x91, 0xc8, 0x1f, 0x66, 0xd5, + /*7960:*/ 0xf8, 0x3b, 0xb3, 0x65, 0xcf, 0xc6, 0x01, 0xfa, 0x32, 0x27, 0xfe, 0xec, 0x0f, 0xbf, 0xd0, 0x99, + /*7970:*/ 0xf5, 0x5b, 0xd0, 0x78, 0xa3, 0x0f, 0x0d, 0xac, 0x12, 0x6c, 0xa5, 0x50, 0xc5, 0x89, 0x32, 0x5e, + /*7980:*/ 0x9f, 0x76, 0xcf, 0x66, 0x81, 0xca, 0xdf, 0x7a, 0x29, 0xf3, 0x1b, 0xe9, 0xfb, 0x53, 0x68, 0x72, + /*7990:*/ 0xdf, 0x88, 0x6a, 0xbb, 0x55, 0x9b, 0xd2, 0x8f, 0xca, 0x84, 0xcd, 0x66, 0x67, 0x37, 0x04, 0x20, + /*79a0:*/ 0x99, 0xb2, 0x70, 0x70, 0x50, 0x93, 0x54, 0x27, 0x7f, 0xe2, 0x9e, 0x9e, 0xaf, 0xe6, 0xd0, 0x4a, + /*79b0:*/ 0x8c, 0x64, 0x3e, 0xfe, 0xb7, 0xbf, 0xdf, 0x0a, 0x86, 0x72, 0xf2, 0x9f, 0x96, 0xdb, 0x13, 0x73, + /*79c0:*/ 0x75, 0xfe, 0x7e, 0xa8, 0xce, 0xa4, 0x24, 0x54, 0xe2, 0x72, 0x76, 0xfa, 0x75, 0x23, 0xd6, 0xa9, + /*79d0:*/ 0x63, 0xf0, 0x5a, 0xdf, 0x80, 0xb7, 0x6d, 0x42, 0x87, 0x7e, 0x53, 0xcf, 0xaa, 0x0b, 0x42, 0x2a, + /*79e0:*/ 0x6f, 0xe9, 0x11, 0xd7, 0xb8, 0xbd, 0x70, 0xe0, 0x0d, 0xdc, 0x2e, 0x3e, 0x83, 0x79, 0x9b, 0x1e, + /*79f0:*/ 0xc9, 0x6b, 0x82, 0x5d, 0x85, 0x61, 0xd1, 0x80, 0xac, 0x64, 0xae, 0x89, 0xc6, 0x8a, 0x24, 0x0b, + /*7a00:*/ 0xc3, 0x24, 0xf9, 0xdb, 0x93, 0xc7, 0xd5, 0x09, 0xae, 0x72, 0xf9, 0x1c, 0x59, 0xd7, 0xa1, 0x45, + /*7a10:*/ 0x41, 0xff, 0xc2, 0xa7, 0x8d, 0x63, 0x9f, 0x6f, 0x84, 0x77, 0x42, 0xa3, 0x8f, 0x8b, 0xba, 0x5b, + /*7a20:*/ 0xdf, 0xc0, 0xad, 0xc8, 0x37, 0x34, 0x11, 0x02, 0xc3, 0xcd, 0xdc, 0x51, 0x98, 0xa2, 0xc8, 0x6e, + /*7a30:*/ 0x45, 0x71, 0xd3, 0x52, 0xa6, 0xdb, 0xa0, 0x5a, 0x9b, 0x5b, 0xe5, 0x2e, 0x6c, 0x94, 0xd6, 0xe8, + /*7a40:*/ 0xd1, 0xcf, 0x3a, 0x9a, 0x92, 0x99, 0x76, 0x71, 0xb7, 0x76, 0x0a, 0x69, 0xbe, 0x76, 0x9a, 0x6f, + /*7a50:*/ 0xa3, 0xc0, 0x30, 0xef, 0x79, 0xf8, 0xc0, 0xd4, 0x01, 0xd5, 0x32, 0x75, 0xfc, 0x94, 0x95, 0x77, + /*7a60:*/ 0x25, 0x93, 0xfa, 0x16, 0x82, 0xac, 0xa7, 0xad, 0x30, 0xd2, 0xfe, 0xed, 0x90, 0x5b, 0xf1, 0xca, + /*7a70:*/ 0x6c, 0x9b, 0x49, 0x5b, 0x63, 0x1c, 0xbd, 0xeb, 0x59, 0x56, 0xd2, 0x48, 0xf0, 0xfb, 0x76, 0xe9, + /*7a80:*/ 0x84, 0xdf, 0xd8, 0xa8, 0x1a, 0x69, 0x09, 0x3c, 0x62, 0x89, 0x15, 0x7c, 0x8b, 0x37, 0x40, 0x6a, + /*7a90:*/ 0x00, 0xc6, 0x8d, 0xe8, 0x34, 0xc1, 0x89, 0xa8, 0x9e, 0xe1, 0x0c, 0x48, 0x63, 0xc0, 0xc2, 0xf7, + /*7aa0:*/ 0x8c, 0xe2, 0xed, 0x3c, 0xaf, 0xbf, 0xef, 0xf9, 0xd8, 0xa0, 0x44, 0xfc, 0x3f, 0xc2, 0x00, 0xa6, + /*7ab0:*/ 0x14, 0xa3, 0xf0, 0xf4, 0xf3, 0x08, 0x21, 0x65, 0xb4, 0xae, 0x40, 0xfd, 0x1f, 0x20, 0xbc, 0x1c, + /*7ac0:*/ 0xa6, 0x61, 0xec, 0x33, 0xa4, 0xa5, 0xd7, 0x47, 0x2b, 0x7a, 0x67, 0x0c, 0xd9, 0xbf, 0x4e, 0xf2, + /*7ad0:*/ 0x08, 0x2f, 0xf0, 0xa3, 0x3b, 0xf3, 0xf0, 0xf9, 0x8d, 0xad, 0x6e, 0x2f, 0x99, 0x65, 0x8d, 0x53, + /*7ae0:*/ 0xe3, 0xec, 0x7f, 0xf2, 0xff, 0x58, 0x38, 0x17, 0xd0, 0xc8, 0xd5, 0xe6, 0x92, 0x75, 0xe9, 0x77, + /*7af0:*/ 0x90, 0x1b, 0xa2, 0xbe, 0x35, 0xc9, 0x39, 0x0c, 0x67, 0x35, 0x9a, 0xb8, 0x7c, 0x6f, 0xe3, 0x46, + /*7b00:*/ 0xc3, 0xa7, 0x83, 0x1e, 0xe1, 0x61, 0x6a, 0x74, 0xcc, 0x1d, 0x57, 0xa4, 0xaa, 0x0c, 0x4b, 0x70, + /*7b10:*/ 0xa0, 0xa3, 0xc9, 0xa0, 0x95, 0xcf, 0xa6, 0xfa, 0x2b, 0x7e, 0x0d, 0x32, 0xe0, 0xdc, 0x23, 0xfc, + /*7b20:*/ 0x61, 0x93, 0xfa, 0xf7, 0x13, 0x26, 0xb0, 0xd8, 0xff, 0xbb, 0xc8, 0xfa, 0xfa, 0x91, 0x31, 0xcf, + /*7b30:*/ 0xcd, 0x54, 0x8c, 0xfc, 0x6d, 0x6b, 0x30, 0x00, 0x11, 0x43, 0x8c, 0xdc, 0x86, 0xf8, 0x11, 0x18, + /*7b40:*/ 0xee, 0xd5, 0xef, 0x9b, 0x79, 0x10, 0xc0, 0x2f, 0x08, 0xaa, 0xe3, 0xc5, 0x53, 0x7e, 0x61, 0xa0, + /*7b50:*/ 0xe2, 0xf0, 0xab, 0x8d, 0x70, 0x51, 0xd6, 0x2c, 0x6a, 0xbb, 0x2b, 0x26, 0x21, 0x61, 0x3f, 0x42, + /*7b60:*/ 0x3b, 0xd9, 0x24, 0x7d, 0xe6, 0x2c, 0x6d, 0xbb, 0xcc, 0xf4, 0x17, 0x12, 0x9e, 0xb0, 0x1e, 0xac, + /*7b70:*/ 0x28, 0xf0, 0xe6, 0x12, 0xf8, 0xde, 0x1f, 0xf4, 0x10, 0x43, 0xcb, 0x1f, 0xb6, 0xb3, 0x93, 0x18, + /*7b80:*/ 0x37, 0x3a, 0xe4, 0xc2, 0x7c, 0xaf, 0x0f, 0xea, 0x9c, 0x41, 0x78, 0x56, 0x46, 0x23, 0xeb, 0xce, + /*7b90:*/ 0x9e, 0x4b, 0xfb, 0x68, 0x3e, 0x68, 0x75, 0xe5, 0xfb, 0x9c, 0xf1, 0x5a, 0xba, 0x50, 0x82, 0x26, + /*7ba0:*/ 0x06, 0x0f, 0xfb, 0x39, 0x04, 0x17, 0x6d, 0x73, 0xa6, 0x7a, 0x57, 0x7b, 0xe7, 0xe3, 0x77, 0x23, + /*7bb0:*/ 0xfa, 0x99, 0x7f, 0x16, 0xa8, 0xbe, 0x80, 0xb1, 0x0d, 0x56, 0xb4, 0x5e, 0xd2, 0x1e, 0x73, 0xc7, + /*7bc0:*/ 0xe8, 0x07, 0xea, 0x35, 0xde, 0xd1, 0xc2, 0x0f, 0x40, 0x05, 0x64, 0x8d, 0x4f, 0x2a, 0xd8, 0x91, + /*7bd0:*/ 0x85, 0xa0, 0xca, 0x88, 0xad, 0xd5, 0xbc, 0x64, 0xcf, 0x62, 0xce, 0x57, 0x3d, 0xc9, 0x08, 0x51, + /*7be0:*/ 0x3f, 0x0c, 0xb1, 0xbf, 0xb3, 0xc0, 0x53, 0xe4, 0xd9, 0x28, 0xc6, 0x5f, 0xd9, 0x23, 0x87, 0x19, + /*7bf0:*/ 0x3b, 0xbc, 0x81, 0x46, 0xbe, 0x15, 0x84, 0x60, 0xc6, 0x9b, 0x8c, 0x50, 0x5f, 0xff, 0x94, 0xd4, + /*7c00:*/ 0x7c, 0xbe, 0x72, 0x2d, 0x08, 0x63, 0xba, 0x21, 0x0a, 0x18, 0x23, 0x06, 0x47, 0x37, 0x74, 0x67, + /*7c10:*/ 0xa4, 0xf1, 0x95, 0xcc, 0x92, 0x9e, 0x36, 0x51, 0xaf, 0xbc, 0x8b, 0x20, 0x0f, 0x88, 0x92, 0x03, + /*7c20:*/ 0xa5, 0xbf, 0x0e, 0xa6, 0x48, 0xb5, 0xc7, 0x73, 0xab, 0x12, 0x3e, 0x24, 0x45, 0xb4, 0x65, 0x35, + /*7c30:*/ 0x7d, 0xb8, 0xb0, 0x0e, 0xc6, 0xb9, 0x66, 0x7f, 0x7a, 0x42, 0x43, 0xf0, 0xf2, 0x5b, 0x07, 0xe1, + /*7c40:*/ 0x4c, 0xb4, 0xc6, 0x3c, 0x67, 0xca, 0x6b, 0xe4, 0x01, 0xd6, 0x4d, 0x55, 0x3b, 0xc8, 0x73, 0x9b, + /*7c50:*/ 0x79, 0x58, 0xee, 0x29, 0x78, 0xe6, 0x7e, 0xf3, 0xc6, 0x60, 0xe0, 0xb6, 0x27, 0xca, 0x6c, 0x49, + /*7c60:*/ 0xb5, 0x36, 0x1d, 0x16, 0x44, 0xc0, 0x17, 0xf0, 0xfe, 0x35, 0xd4, 0x04, 0xb7, 0x4a, 0x0c, 0x41, + /*7c70:*/ 0xe1, 0x71, 0x56, 0x26, 0xfd, 0x92, 0xaa, 0xc5, 0x97, 0x16, 0x55, 0xc6, 0x8c, 0xb3, 0x4b, 0x12, + /*7c80:*/ 0xb9, 0x6f, 0xca, 0x13, 0x41, 0x7c, 0x39, 0x55, 0x23, 0x6a, 0xe0, 0xc8, 0x11, 0x03, 0xb7, 0xf0, + /*7c90:*/ 0x01, 0x7b, 0x90, 0xa0, 0xa4, 0x77, 0xbe, 0x09, 0xa8, 0xcb, 0xd6, 0x24, 0x12, 0x26, 0xc9, 0x4d, + /*7ca0:*/ 0xd3, 0xb0, 0x09, 0x0b, 0x02, 0x1a, 0xbe, 0x7c, 0x0f, 0x24, 0xad, 0xa7, 0xf0, 0x20, 0xaa, 0xae, + /*7cb0:*/ 0xa4, 0x50, 0x0f, 0xe9, 0xfb, 0x54, 0x0e, 0x05, 0x32, 0xc7, 0x14, 0xfe, 0x5f, 0xd7, 0x5b, 0x3d, + /*7cc0:*/ 0x34, 0x72, 0xa7, 0x11, 0xc4, 0x20, 0x6a, 0x26, 0x9a, 0x27, 0x43, 0x11, 0xdd, 0xd4, 0x98, 0xad, + /*7cd0:*/ 0x3c, 0x00, 0x61, 0x33, 0xe7, 0x9f, 0x9b, 0xef, 0xb3, 0xe4, 0x24, 0x09, 0x40, 0x62, 0x84, 0x9d, + /*7ce0:*/ 0x00, 0x00, 0xf9, 0xb9, 0x7a, 0xca, 0x31, 0x0f, 0x3d, 0x6e, 0x28, 0x94, 0x2a, 0xb4, 0x44, 0xd5, + /*7cf0:*/ 0xab, 0x39, 0xf5, 0xf6, 0xe2, 0x90, 0x42, 0x01, 0x04, 0x8f, 0x0e, 0x29, 0xcc, 0xbd, 0x73, 0x3c, + /*7d00:*/ 0x08, 0x60, 0x9a, 0x31, 0x96, 0xb8, 0x1d, 0xcb, 0xcb, 0x30, 0xba, 0xdc, 0x15, 0xec, 0x1c, 0x2d, + /*7d10:*/ 0x72, 0x31, 0x7d, 0x93, 0xf5, 0x4f, 0x67, 0x11, 0x28, 0x09, 0x2d, 0x11, 0xc1, 0x94, 0xee, 0xa3, + /*7d20:*/ 0xac, 0x13, 0xbb, 0xb3, 0x86, 0x00, 0x98, 0xd7, 0x09, 0xc0, 0xd7, 0x7c, 0x56, 0x5b, 0x80, 0x1c, + /*7d30:*/ 0x40, 0x52, 0xc5, 0x99, 0x1e, 0x5f, 0x77, 0x0c, 0x6c, 0x66, 0xe4, 0x5d, 0x92, 0x86, 0xcb, 0x33, + /*7d40:*/ 0x57, 0x64, 0xdf, 0x12, 0xcd, 0x80, 0xf3, 0x49, 0xc2, 0x9e, 0x63, 0xe6, 0xb7, 0xbe, 0x9d, 0x77, + /*7d50:*/ 0xe5, 0xd4, 0xe3, 0xc5, 0x7d, 0x0f, 0x41, 0x33, 0xc7, 0x4d, 0x64, 0x47, 0x23, 0x5a, 0xd1, 0x37, + /*7d60:*/ 0x3f, 0xb9, 0xb8, 0x0a, 0xbf, 0x6f, 0xff, 0xe8, 0x85, 0xae, 0x31, 0x77, 0xf6, 0xc2, 0xbe, 0x0c, + /*7d70:*/ 0x52, 0xdb, 0x9e, 0x63, 0xbd, 0xe5, 0x1a, 0xdc, 0x78, 0x07, 0x46, 0x25, 0x2e, 0x2c, 0xe1, 0xdc, + /*7d80:*/ 0x76, 0x81, 0xd6, 0x5c, 0xf8, 0x81, 0x84, 0xea, 0x30, 0x90, 0xda, 0x6c, 0x5b, 0x55, 0xb4, 0x18, + /*7d90:*/ 0x89, 0x7b, 0xe0, 0x77, 0x6f, 0x9e, 0xfc, 0x88, 0x8f, 0x03, 0xd8, 0xaa, 0x16, 0xb9, 0x44, 0xb1, + /*7da0:*/ 0x4e, 0x3f, 0x60, 0x73, 0xe5, 0xe7, 0x97, 0xe8, 0x37, 0x42, 0x46, 0x92, 0x91, 0xf4, 0x03, 0xff, + /*7db0:*/ 0xdd, 0xed, 0x76, 0xce, 0x37, 0xbd, 0x06, 0xa6, 0x46, 0x97, 0xe0, 0xed, 0x2b, 0xdf, 0x04, 0x5e, + /*7dc0:*/ 0x97, 0x6c, 0x96, 0xee, 0x99, 0x79, 0x33, 0xba, 0x0a, 0x56, 0x4a, 0xa4, 0x8a, 0x2e, 0x4d, 0x94, + /*7dd0:*/ 0xab, 0x2d, 0xf0, 0x34, 0xc1, 0x11, 0xb1, 0xc9, 0x99, 0xfe, 0x6f, 0xf8, 0x70, 0x4e, 0x8f, 0x52, + /*7de0:*/ 0x0d, 0xa5, 0xb4, 0xbb, 0x7e, 0x26, 0x04, 0x80, 0xdc, 0x3d, 0x24, 0xc0, 0x7a, 0x40, 0x0d, 0x89, + /*7df0:*/ 0x9a, 0x0c, 0x12, 0xa7, 0x56, 0x76, 0xb8, 0x3d, 0xac, 0xba, 0xbf, 0x23, 0x81, 0x2c, 0xe9, 0x18, + /*7e00:*/ 0xac, 0x48, 0xbc, 0xaf, 0x78, 0xcd, 0xd2, 0x31, 0x05, 0x9a, 0x75, 0x50, 0x90, 0x48, 0x7a, 0xd0, + /*7e10:*/ 0x87, 0x86, 0x25, 0xaa, 0xd2, 0x41, 0x36, 0x85, 0x77, 0x76, 0x68, 0x06, 0xdf, 0x7b, 0xfa, 0x4f, + /*7e20:*/ 0x1e, 0x99, 0xe4, 0x93, 0x43, 0xde, 0x4a, 0x4c, 0x97, 0xdb, 0x1f, 0x2c, 0xa4, 0x40, 0x02, 0xcd, + /*7e30:*/ 0xf4, 0x85, 0x40, 0xbe, 0x28, 0xa4, 0x10, 0x5c, 0x62, 0x6f, 0x83, 0x9d, 0x5b, 0xbf, 0xec, 0xf6, + /*7e40:*/ 0xb5, 0xec, 0x11, 0x6f, 0x10, 0x10, 0xe9, 0x25, 0x28, 0x05, 0xfa, 0x2d, 0xf8, 0x9f, 0x9e, 0xa5, + /*7e50:*/ 0x0e, 0x9c, 0x7a, 0x27, 0x10, 0xaa, 0x6b, 0x9d, 0xcc, 0x3f, 0x02, 0xdd, 0x62, 0x53, 0x16, 0xfc, + /*7e60:*/ 0x3a, 0x6a, 0x9e, 0x44, 0xfd, 0x02, 0x72, 0x20, 0xd3, 0x86, 0xe4, 0xaf, 0x4e, 0xba, 0x06, 0x97, + /*7e70:*/ 0xc7, 0x7f, 0x53, 0xd5, 0x0d, 0xd3, 0x14, 0xad, 0x58, 0xfc, 0x86, 0x4c, 0x4d, 0x67, 0x54, 0xa2, + /*7e80:*/ 0x6e, 0xbc, 0x6c, 0x46, 0xbf, 0x41, 0xad, 0xf3, 0x8a, 0x1d, 0x82, 0x46, 0xde, 0x33, 0x4c, 0x63, + /*7e90:*/ 0xea, 0x15, 0xad, 0xf4, 0x9e, 0x8e, 0x9f, 0x95, 0xa7, 0x77, 0x02, 0xee, 0x22, 0x7f, 0xfb, 0x62, + /*7ea0:*/ 0x1e, 0x47, 0x4b, 0xb7, 0x60, 0xc7, 0xa4, 0xa6, 0x9a, 0x6c, 0x27, 0x1f, 0x6e, 0x72, 0xb3, 0x91, + /*7eb0:*/ 0x3c, 0x54, 0xf5, 0x78, 0x9c, 0x52, 0x80, 0xb7, 0xc0, 0x60, 0x12, 0xc2, 0x87, 0x41, 0x76, 0xd8, + /*7ec0:*/ 0x5f, 0x34, 0x4b, 0xf5, 0x81, 0x64, 0x81, 0x97, 0xa6, 0x3e, 0x27, 0x7f, 0x79, 0x90, 0xd9, 0xda, + /*7ed0:*/ 0xd4, 0x06, 0xbb, 0x54, 0x37, 0xd2, 0x65, 0x64, 0x70, 0xaa, 0x8d, 0xd0, 0x29, 0x5f, 0xa3, 0x53, + /*7ee0:*/ 0x93, 0xf6, 0x80, 0x35, 0x02, 0x59, 0x7a, 0x66, 0x57, 0xcd, 0x5a, 0xfb, 0xca, 0x1f, 0x5a, 0xdc, + /*7ef0:*/ 0xc8, 0x54, 0xb1, 0xf6, 0xb6, 0x42, 0xe8, 0x2b, 0x24, 0xee, 0x82, 0xe1, 0xf0, 0xf8, 0x51, 0x22, + /*7f00:*/ 0x0c, 0x8b, 0x6b, 0x30, 0xab, 0xb8, 0x54, 0xfe, 0x44, 0x03, 0xd8, 0x17, 0xa7, 0x15, 0xe7, 0xa1, + /*7f10:*/ 0xe6, 0xe4, 0x59, 0x36, 0xfd, 0xd3, 0x49, 0xe3, 0x73, 0x41, 0xa9, 0x30, 0xe4, 0xc5, 0x5b, 0x68, + /*7f20:*/ 0x63, 0x4e, 0xd4, 0x19, 0x3c, 0x1a, 0xf5, 0xde, 0x0a, 0x4f, 0x97, 0x59, 0x3b, 0x3f, 0xb1, 0x66, + /*7f30:*/ 0x9f, 0x0e, 0x56, 0xd8, 0xaf, 0x45, 0x60, 0x79, 0x74, 0xbd, 0x3d, 0xd1, 0xa9, 0x74, 0x4b, 0xa3, + /*7f40:*/ 0xd4, 0xfe, 0x1e, 0xc3, 0x8a, 0x63, 0x2e, 0x13, 0xe3, 0x57, 0xd3, 0xd0, 0x99, 0x17, 0x34, 0xa8, + /*7f50:*/ 0x01, 0x4a, 0xa6, 0x04, 0x77, 0x1f, 0xf0, 0xaa, 0x47, 0xfe, 0x93, 0xcb, 0x04, 0x4d, 0x89, 0x3d, + /*7f60:*/ 0xfc, 0x97, 0xc9, 0x64, 0x64, 0x4d, 0x92, 0x29, 0x88, 0xf4, 0x0c, 0xcc, 0x1b, 0x93, 0xdd, 0xb2, + /*7f70:*/ 0x84, 0x1a, 0x41, 0x88, 0xfa, 0xa5, 0x02, 0xf5, 0x01, 0x0a, 0x53, 0xc3, 0x3d, 0x3c, 0x56, 0x41, + /*7f80:*/ 0xde, 0x46, 0xfd, 0xdb, 0x5f, 0xe7, 0xf9, 0xc7, 0xb7, 0x16, 0x07, 0xd9, 0x60, 0xd6, 0xde, 0xea, + /*7f90:*/ 0x3d, 0xb8, 0xcb, 0xaf, 0x78, 0x2a, 0xeb, 0x60, 0x7e, 0xf4, 0x81, 0x81, 0x0b, 0xa2, 0x3a, 0xdb, + /*7fa0:*/ 0xc0, 0x4f, 0x30, 0x19, 0x37, 0xab, 0xc3, 0x61, 0x6f, 0xeb, 0x89, 0x08, 0x8a, 0xab, 0x5c, 0xb0, + /*7fb0:*/ 0x37, 0x16, 0x05, 0x4b, 0x4f, 0x03, 0x9d, 0x0e, 0x79, 0x88, 0x2c, 0x1b, 0xe7, 0x20, 0x9c, 0xff, + /*7fc0:*/ 0xce, 0x91, 0x6a, 0x6b, 0x73, 0x5a, 0x7b, 0xa0, 0x6a, 0x3e, 0xab, 0xb4, 0x8d, 0x3a, 0xce, 0x53, + /*7fd0:*/ 0x43, 0x57, 0x2f, 0x93, 0xae, 0x51, 0x28, 0xd9, 0xb8, 0x1e, 0x0d, 0x35, 0x6a, 0x22, 0x00, 0x12, + /*7fe0:*/ 0x36, 0x4e, 0xed, 0x2d, 0x98, 0xd1, 0x68, 0xbe, 0x34, 0x81, 0xea, 0x36, 0xab, 0xd2, 0x8c, 0x1a, + /*7ff0:*/ 0xf0, 0x19, 0x85, 0x36, 0x02, 0xff, 0x87, 0x6a, 0x84, 0x20, 0x5a, 0xa0, 0x57, 0xba, 0xa3, 0x04, + /*8000:*/ 0x84, 0x34, 0x21, 0xef, 0xbc, 0x7b, 0xde, 0xec, 0x8c, 0x4b, 0x65, 0x20, 0x4d, 0x3f, 0x2a, 0xae, + /*8010:*/ 0x0c, 0xad, 0x59, 0xce, 0x99, 0x77, 0x05, 0xb8, 0xc8, 0x18, 0xf9, 0xe0, 0xac, 0xcd, 0xbc, 0xfe, + /*8020:*/ 0xa1, 0x37, 0xc5, 0xba, 0xa5, 0xb3, 0xf2, 0x01, 0x81, 0x17, 0x79, 0xa7, 0x22, 0x9d, 0x04, 0x05, + /*8030:*/ 0x8f, 0xf6, 0xc1, 0x74, 0x42, 0xb5, 0xa3, 0x4d, 0x41, 0x5e, 0x98, 0x5e, 0xa7, 0xd3, 0xb0, 0xb5, + /*8040:*/ 0x8d, 0xf9, 0xc8, 0x20, 0x47, 0x50, 0x32, 0x4a, 0x9c, 0x10, 0xe7, 0x8d, 0x1b, 0xcf, 0xd8, 0x75, + /*8050:*/ 0x9d, 0x3d, 0x56, 0x88, 0xe6, 0x9b, 0xa1, 0xf1, 0xd0, 0x74, 0x26, 0x87, 0xfa, 0xab, 0xea, 0x8f, + /*8060:*/ 0xaf, 0x3c, 0x38, 0xd5, 0xe2, 0xe6, 0x05, 0xbd, 0x57, 0x0c, 0x05, 0x80, 0xc3, 0xd7, 0xde, 0x66, + /*8070:*/ 0x14, 0x67, 0x4a, 0x3e, 0x4a, 0xe6, 0xe0, 0x54, 0xfa, 0xce, 0x09, 0x8a, 0x75, 0xd0, 0x87, 0x39, + /*8080:*/ 0xb1, 0xfb, 0x0c, 0x54, 0xed, 0x69, 0x96, 0x68, 0x5c, 0x1b, 0xcf, 0xa3, 0x56, 0xdd, 0x0b, 0x78, + /*8090:*/ 0x9c, 0x5d, 0x7d, 0x9d, 0x05, 0x79, 0x72, 0xb9, 0xa9, 0x6e, 0xd1, 0xfb, 0x0c, 0x28, 0x2b, 0xa9, + /*80a0:*/ 0xf4, 0xb3, 0x41, 0xb1, 0x12, 0xe0, 0xe3, 0xf4, 0xf0, 0x6c, 0x86, 0x50, 0xf0, 0xaf, 0x23, 0x87, + /*80b0:*/ 0x67, 0x91, 0xe2, 0x07, 0x6c, 0x77, 0x16, 0xf9, 0x5f, 0x83, 0x8a, 0x46, 0xb6, 0xe3, 0x02, 0x59, + /*80c0:*/ 0x77, 0xaf, 0x3e, 0x98, 0x33, 0x3f, 0xb6, 0xf4, 0x02, 0x23, 0x50, 0xd8, 0x4b, 0xc9, 0x4e, 0xd9, + /*80d0:*/ 0x00, 0xe9, 0x68, 0x13, 0x44, 0xed, 0x2c, 0x4d, 0xd7, 0x60, 0xb4, 0x69, 0xc6, 0xd4, 0xe7, 0xc6, + /*80e0:*/ 0x57, 0xe4, 0xb0, 0x5d, 0x74, 0x51, 0xb5, 0x09, 0x54, 0x11, 0x58, 0x1b, 0xab, 0xf6, 0x54, 0xfb, + /*80f0:*/ 0xe4, 0xaa, 0x99, 0xb0, 0xc2, 0xa8, 0xc3, 0x2d, 0x52, 0x95, 0x39, 0x51, 0x4b, 0x18, 0x83, 0xe6, + /*8100:*/ 0xfc, 0x55, 0xd5, 0x0a, 0xae, 0x93, 0x70, 0x97, 0x60, 0x65, 0x63, 0x61, 0x72, 0x65, 0x9a, 0xe8, + /*8110:*/ 0x13, 0x86, 0x99, 0x14, 0x75, 0xca, 0xe2, 0x9b, 0x40, 0xaf, 0x63, 0x49, 0x50, 0xfc, 0x1d, 0x9b, + /*8120:*/ 0x2a, 0x26, 0xee, 0xbc, 0x88, 0x78, 0x1d, 0xd8, 0xd6, 0x51, 0x8b, 0x8f, 0x45, 0xf9, 0xe0, 0x4b, + /*8130:*/ 0x29, 0x6a, 0x46, 0xf6, 0x9b, 0x5b, 0x6e, 0x2c, 0x83, 0xbf, 0x03, 0x82, 0x8f, 0xb6, 0xe4, 0x76, + /*8140:*/ 0x6b, 0x70, 0xaf, 0x88, 0x69, 0x6e, 0x82, 0x00, 0x44, 0x71, 0x3d, 0xf3, 0x05, 0x0d, 0xa0, 0x33, + /*8150:*/ 0x92, 0x10, 0x87, 0x70, 0xda, 0x2d, 0x0c, 0x97, 0x41, 0x1f, 0x5c, 0x2f, 0x3d, 0x8b, 0xe8, 0x53, + /*8160:*/ 0xf3, 0x01, 0x1e, 0x79, 0x47, 0x60, 0xf1, 0x72, 0x9e, 0x0d, 0x5d, 0x45, 0x93, 0xb9, 0x5f, 0x57, + /*8170:*/ 0x88, 0xaf, 0x23, 0x27, 0x0e, 0xaa, 0xab, 0x4b, 0x29, 0x37, 0x10, 0xe0, 0x81, 0xd1, 0xd0, 0x4d, + /*8180:*/ 0xdf, 0x72, 0xe9, 0xbb, 0xc2, 0x80, 0x3b, 0x42, 0xc2, 0x61, 0x10, 0xd0, 0x07, 0xb9, 0x0b, 0x05, + /*8190:*/ 0x09, 0xb8, 0xa6, 0x11, 0x92, 0x90, 0x22, 0x73, 0xd2, 0x02, 0xfc, 0x4a, 0x99, 0x28, 0x7e, 0x0a, + /*81a0:*/ 0xa6, 0x24, 0xe8, 0xc4, 0xa2, 0xe0, 0x5c, 0x32, 0x5d, 0x3a, 0xc2, 0xd7, 0x6c, 0x77, 0x9a, 0xa7, + /*81b0:*/ 0x3e, 0xa2, 0x42, 0xd8, 0x14, 0x84, 0x0a, 0x46, 0x0e, 0x0f, 0x94, 0x5f, 0x0e, 0x4c, 0x5a, 0x9a, + /*81c0:*/ 0x75, 0x50, 0x8f, 0xe4, 0x5c, 0xaa, 0xf4, 0x99, 0x29, 0x14, 0x8a, 0xac, 0xd3, 0x5b, 0xcc, 0x87, + /*81d0:*/ 0x03, 0xc2, 0x58, 0xd3, 0x63, 0x09, 0x92, 0x1f, 0xb4, 0x59, 0x5e, 0x5c, 0x5a, 0x03, 0x32, 0x30, + /*81e0:*/ 0x28, 0xb8, 0xdb, 0x8a, 0xdc, 0x93, 0x74, 0xf6, 0xe9, 0x3c, 0xfa, 0x31, 0xef, 0xa7, 0xf4, 0x79, + /*81f0:*/ 0x11, 0x97, 0x4a, 0xbd, 0xa3, 0x95, 0x3e, 0x40, 0x6a, 0x72, 0xe0, 0x7c, 0x2b, 0xe8, 0xa4, 0x0d, + /*8200:*/ 0x01, 0x74, 0x6f, 0x3d, 0x70, 0x89, 0x04, 0x37, 0x1b, 0x1b, 0x05, 0x69, 0x89, 0x9b, 0xa0, 0x48, + /*8210:*/ 0x5b, 0x5f, 0x25, 0x8f, 0xb7, 0xc1, 0xe7, 0xf3, 0x04, 0x3b, 0xf7, 0x18, 0xfe, 0x44, 0xc7, 0x60, + /*8220:*/ 0x6d, 0xae, 0x7d, 0x08, 0xe3, 0x6f, 0xc6, 0x4f, 0x36, 0xe5, 0x86, 0xbc, 0x99, 0x12, 0x1a, 0xb6, + /*8230:*/ 0x06, 0x4c, 0xe6, 0x52, 0xeb, 0x42, 0xfb, 0x66, 0x87, 0x8b, 0x67, 0x0e, 0xac, 0xd5, 0xb8, 0x02, + /*8240:*/ 0x5e, 0xc8, 0xed, 0x80, 0x66, 0x7c, 0x83, 0x0b, 0x85, 0x28, 0x84, 0x2d, 0xbd, 0xfc, 0x2e, 0x13, + /*8250:*/ 0x4a, 0x09, 0x39, 0x52, 0x88, 0xc1, 0xb5, 0xc6, 0x81, 0x56, 0xed, 0xfd, 0xdb, 0x55, 0xa5, 0x57, + /*8260:*/ 0x1a, 0xaa, 0xec, 0x95, 0x96, 0xca, 0x51, 0xfa, 0xd0, 0x88, 0xe8, 0xd2, 0x85, 0x8c, 0xc9, 0x73, + /*8270:*/ 0x98, 0x99, 0xc0, 0x5b, 0xef, 0x4e, 0xe9, 0xd0, 0x25, 0x0b, 0x9d, 0xdd, 0x8a, 0xc3, 0x06, 0x2b, + /*8280:*/ 0x2f, 0x45, 0xb2, 0x7b, 0x2c, 0x49, 0x41, 0xa9, 0x5c, 0xcf, 0x00, 0x6f, 0xbe, 0x9f, 0x9f, 0x3c, + /*8290:*/ 0x10, 0xd7, 0xf1, 0x80, 0x8e, 0x9c, 0x99, 0xb8, 0xc5, 0xee, 0x98, 0x46, 0x49, 0xf3, 0x33, 0xea, + /*82a0:*/ 0x6c, 0xc2, 0x8b, 0x3b, 0x14, 0x45, 0xbd, 0xce, 0x5f, 0x2c, 0xec, 0x88, 0x2f, 0x9d, 0x5d, 0xd5, + /*82b0:*/ 0xee, 0x8f, 0x0d, 0x07, 0xaa, 0x04, 0xdd, 0xaa, 0x2f, 0x80, 0xd8, 0xd3, 0xa2, 0xb1, 0x90, 0xdd, + /*82c0:*/ 0x0b, 0x0e, 0xd8, 0x70, 0x4a, 0x22, 0x8a, 0x49, 0x85, 0xcd, 0xf6, 0x63, 0x14, 0x3a, 0x28, 0x8c, + /*82d0:*/ 0x65, 0x7f, 0x18, 0x90, 0x3d, 0xa2, 0x7d, 0x1c, 0x1f, 0x04, 0xc3, 0xc4, 0xbc, 0x0e, 0xb1, 0x19, + /*82e0:*/ 0xae, 0x35, 0xa7, 0xf7, 0x3f, 0x4d, 0x6a, 0xb5, 0x57, 0x98, 0x44, 0x62, 0x6d, 0xbd, 0x29, 0x5a, + /*82f0:*/ 0x7a, 0x82, 0x40, 0xb9, 0x5d, 0xa2, 0x61, 0x1e, 0xea, 0xff, 0x9a, 0xd7, 0x85, 0x8b, 0x2a, 0x88, + /*8300:*/ 0x6a, 0xbc, 0xdb, 0x16, 0x1b, 0x43, 0x02, 0xbd, 0x36, 0xa1, 0x9e, 0x86, 0x45, 0x15, 0x4b, 0x07, + /*8310:*/ 0xaf, 0x96, 0x11, 0xcb, 0xb7, 0x23, 0xb1, 0xb2, 0xcf, 0x25, 0x99, 0xd5, 0x31, 0xc9, 0xde, 0x7a, + /*8320:*/ 0x7b, 0x74, 0x80, 0x3d, 0xcd, 0x17, 0xab, 0x63, 0xe6, 0x27, 0x17, 0xce, 0x07, 0xb3, 0x12, 0xec, + /*8330:*/ 0x5f, 0x5f, 0xe7, 0xcb, 0x92, 0xb1, 0xe9, 0x58, 0x57, 0x40, 0xb4, 0x43, 0xcb, 0x61, 0x45, 0xd8, + /*8340:*/ 0x15, 0xe3, 0xd9, 0xc1, 0x65, 0x88, 0x33, 0x6b, 0xc5, 0x9d, 0x93, 0x49, 0xd6, 0x95, 0xb5, 0x5a, + /*8350:*/ 0x07, 0xae, 0x98, 0xe8, 0xda, 0x3e, 0x7c, 0x5c, 0x29, 0xfb, 0xd1, 0xbf, 0x2d, 0x45, 0x2f, 0xb2, + /*8360:*/ 0xcc, 0xfd, 0x93, 0xb3, 0x5d, 0x4e, 0x68, 0xce, 0xa7, 0x6b, 0xf5, 0xf4, 0xa8, 0x4c, 0x9f, 0x2f, + /*8370:*/ 0xe4, 0xf6, 0x4a, 0x0d, 0xe8, 0xb1, 0x07, 0xb0, 0x5a, 0xc7, 0x2e, 0xbe, 0x32, 0xc6, 0x84, 0x7b, + /*8380:*/ 0x19, 0xba, 0x32, 0x9d, 0x2b, 0x01, 0x53, 0x5d, 0x91, 0x21, 0x21, 0xed, 0xe7, 0x71, 0xe5, 0xe0, + /*8390:*/ 0xae, 0x15, 0x51, 0xec, 0xfb, 0x4c, 0xe3, 0x35, 0xa3, 0x04, 0x70, 0x22, 0x26, 0x38, 0xa8, 0x3d, + /*83a0:*/ 0x41, 0x39, 0xc0, 0x87, 0xc3, 0x33, 0x8a, 0x3a, 0x73, 0xb4, 0x20, 0x99, 0x3d, 0xe8, 0xbd, 0x19, + /*83b0:*/ 0xa7, 0xa2, 0x06, 0xb1, 0xd7, 0xa4, 0x09, 0x04, 0xfa, 0x48, 0xa6, 0xd0, 0xa9, 0xbb, 0xeb, 0x42, + /*83c0:*/ 0x33, 0xf9, 0x10, 0x6e, 0xda, 0x32, 0x8e, 0x31, 0x71, 0xfb, 0x91, 0x8a, 0x3b, 0xe2, 0x27, 0x4d, + /*83d0:*/ 0xb2, 0x5d, 0x40, 0x1c, 0x3b, 0xf2, 0xb8, 0x30, 0x90, 0x59, 0xe4, 0xa3, 0xa7, 0x80, 0x89, 0xbb, + /*83e0:*/ 0xaa, 0x6a, 0x85, 0x9e, 0x93, 0x92, 0xe0, 0x72, 0x2f, 0x32, 0x49, 0xa9, 0x91, 0x72, 0xc8, 0xf7, + /*83f0:*/ 0x06, 0x28, 0x9d, 0x81, 0xb1, 0x2a, 0x25, 0x60, 0x45, 0x83, 0xec, 0x2b, 0x7e, 0x4b, 0x4c, 0xc9, + /*8400:*/ 0x68, 0x27, 0xc6, 0x76, 0x9d, 0x4b, 0x7f, 0x22, 0x5e, 0x29, 0xad, 0x2f, 0x4c, 0xf2, 0x40, 0xea, + /*8410:*/ 0x27, 0x0f, 0xed, 0xb4, 0x65, 0x07, 0x05, 0x8d, 0x12, 0x5f, 0x71, 0x2d, 0x75, 0x6d, 0x3f, 0xef, + /*8420:*/ 0xd0, 0xd5, 0xd8, 0x3e, 0x54, 0x85, 0xc1, 0x50, 0xd3, 0x56, 0x39, 0xd1, 0x10, 0x84, 0x2d, 0xbb, + /*8430:*/ 0x7c, 0xd4, 0x6a, 0x49, 0x40, 0xc6, 0xdd, 0xb3, 0xd5, 0x80, 0x58, 0x0b, 0xa2, 0x98, 0x34, 0xbc, + /*8440:*/ 0xf6, 0x31, 0xde, 0xa7, 0xed, 0x6e, 0xc0, 0x74, 0x33, 0x9f, 0x25, 0x8f, 0xf1, 0xf2, 0x27, 0x95, + /*8450:*/ 0xe3, 0x25, 0xe4, 0x3d, 0x28, 0x05, 0xe7, 0x68, 0x8e, 0xdf, 0xbe, 0x45, 0xe4, 0x11, 0x71, 0x19, + /*8460:*/ 0x6d, 0x34, 0xd6, 0x56, 0x52, 0x04, 0xaf, 0x5d, 0x4e, 0x22, 0x22, 0x98, 0xd3, 0x52, 0x26, 0xf4, + /*8470:*/ 0xd1, 0x73, 0xa1, 0x97, 0xa0, 0x3c, 0xef, 0xfa, 0x80, 0x7a, 0xe4, 0x1d, 0xe8, 0x53, 0x04, 0x19, + /*8480:*/ 0x4d, 0x65, 0x55, 0xf4, 0xf2, 0x55, 0x94, 0xf6, 0xcb, 0x1e, 0xfe, 0x91, 0x42, 0x83, 0xa7, 0x5a, + /*8490:*/ 0x8d, 0x81, 0xba, 0xd6, 0xaa, 0x4c, 0xb8, 0xfd, 0x36, 0xfc, 0x0e, 0x42, 0xe3, 0xd4, 0xdf, 0xfc, + /*84a0:*/ 0xb3, 0x71, 0x22, 0x91, 0xe5, 0xea, 0xce, 0xa0, 0xb7, 0xfb, 0x03, 0x19, 0xa7, 0x0a, 0xb0, 0xf5, + /*84b0:*/ 0x26, 0xfe, 0x01, 0xe9, 0x05, 0xc4, 0x09, 0x61, 0xb5, 0x29, 0x07, 0xcb, 0xce, 0x14, 0x7d, 0x49, + /*84c0:*/ 0xfd, 0xe1, 0x91, 0x10, 0x62, 0x0d, 0xf8, 0x37, 0x8f, 0xed, 0xf2, 0x5e, 0x31, 0x6e, 0x80, 0xeb, + /*84d0:*/ 0x08, 0x10, 0x7c, 0x07, 0x61, 0x7e, 0xd2, 0xf4, 0xfc, 0xc8, 0xf1, 0x88, 0xdb, 0x02, 0xe5, 0xa8, + /*84e0:*/ 0x63, 0x91, 0x43, 0x24, 0x77, 0x61, 0x05, 0x56, 0x73, 0xfa, 0x9c, 0x50, 0x9c, 0x93, 0x75, 0x5b, + /*84f0:*/ 0xb2, 0x6c, 0xec, 0x9d, 0x7d, 0x33, 0x1d, 0xb4, 0xa8, 0x1c, 0xc8, 0x4d, 0x9b, 0xde, 0xa8, 0x9e, + /*8500:*/ 0x6d, 0xef, 0x92, 0xd5, 0x2f, 0xdf, 0x14, 0xc3, 0xa0, 0xd7, 0x42, 0x31, 0xec, 0xc9, 0x1e, 0x63, + /*8510:*/ 0x99, 0x1e, 0xd7, 0xce, 0xaf, 0x03, 0xd8, 0x59, 0x74, 0xa3, 0x50, 0xd9, 0x5b, 0x38, 0xc8, 0xbe, + /*8520:*/ 0xa0, 0xfd, 0xa9, 0x08, 0x97, 0xf3, 0x58, 0x28, 0xa7, 0xc3, 0x3c, 0x92, 0x99, 0x45, 0x13, 0xfd, + /*8530:*/ 0xae, 0xb3, 0xe9, 0x27, 0xa6, 0xa2, 0x9c, 0x81, 0x8f, 0x78, 0x1d, 0x8a, 0x26, 0x73, 0x04, 0x67, + /*8540:*/ 0xbd, 0xe8, 0x02, 0xb2, 0x69, 0xf4, 0x6b, 0xad, 0xd8, 0xd8, 0x34, 0x5e, 0xff, 0xb3, 0xbe, 0x82, + /*8550:*/ 0xd4, 0xde, 0x4c, 0xd1, 0x83, 0xc9, 0x94, 0x12, 0xfe, 0x7d, 0x15, 0xd1, 0x70, 0x75, 0x2c, 0x1b, + /*8560:*/ 0xd6, 0x5b, 0x0e, 0x96, 0x8d, 0xf4, 0x29, 0x61, 0xca, 0x50, 0xe4, 0x00, 0xa5, 0x56, 0x4f, 0xf8, + /*8570:*/ 0xcb, 0xef, 0xe8, 0x56, 0x77, 0x99, 0x28, 0x91, 0x05, 0xb8, 0xc2, 0x70, 0xaf, 0x0a, 0x55, 0x02, + /*8580:*/ 0xa1, 0x1f, 0x38, 0x04, 0x2e, 0xc5, 0x69, 0xbe, 0xca, 0xa2, 0x15, 0x08, 0x71, 0xe4, 0x90, 0xed, + /*8590:*/ 0x5c, 0x54, 0x54, 0x72, 0x6f, 0x42, 0x75, 0x7e, 0xc7, 0x87, 0x23, 0xce, 0x3b, 0xc8, 0xe1, 0x2f, + /*85a0:*/ 0xc8, 0x18, 0xf8, 0x13, 0x52, 0xbf, 0x6f, 0x2b, 0xae, 0x40, 0x3a, 0x3e, 0x51, 0x59, 0x44, 0xd1, + /*85b0:*/ 0xca, 0x6f, 0x40, 0x7e, 0xaa, 0x2f, 0x3e, 0xc2, 0xa8, 0x6d, 0xb6, 0x7b, 0xc4, 0xcd, 0xec, 0xd4, + /*85c0:*/ 0x6d, 0x3e, 0x8e, 0x17, 0x9c, 0x08, 0x97, 0xe6, 0x07, 0x70, 0x93, 0xe0, 0xf3, 0x33, 0xa2, 0x17, + /*85d0:*/ 0x1c, 0x3d, 0x67, 0x8f, 0xdc, 0x9e, 0x6a, 0x9c, 0x1d, 0xb4, 0x1d, 0x0d, 0x62, 0x63, 0xd8, 0x34, + /*85e0:*/ 0xd0, 0xb9, 0x84, 0x72, 0xa9, 0xef, 0x53, 0x6d, 0x0b, 0xc3, 0xd7, 0xe4, 0x4d, 0x66, 0x14, 0x1c, + /*85f0:*/ 0x86, 0x4b, 0x41, 0xa5, 0x61, 0x42, 0x50, 0xa1, 0x70, 0xe9, 0x6e, 0xf1, 0x01, 0xfd, 0x1a, 0x92, + /*8600:*/ 0x8a, 0x68, 0xf6, 0x21, 0x27, 0x77, 0xb6, 0x35, 0x41, 0xd4, 0xd9, 0x01, 0xcc, 0x5f, 0x23, 0x82, + /*8610:*/ 0xc5, 0xca, 0x09, 0x4e, 0x67, 0x10, 0xfa, 0x7c, 0xcb, 0xde, 0x53, 0x53, 0xe2, 0x3c, 0x0f, 0x65, + /*8620:*/ 0x08, 0x4b, 0x8c, 0x5b, 0xd0, 0x36, 0xce, 0x2c, 0x90, 0x03, 0x0b, 0x7c, 0x02, 0x84, 0x02, 0x97, + /*8630:*/ 0xb0, 0xcd, 0xbe, 0xa1, 0x44, 0x0e, 0x56, 0x0e, 0xe9, 0x72, 0xc1, 0xd8, 0xd4, 0x25, 0xac, 0xfb, + /*8640:*/ 0x04, 0xe3, 0xba, 0x9a, 0x11, 0x4a, 0x16, 0x83, 0xdd, 0xcf, 0x77, 0x9e, 0xe7, 0x2d, 0xf4, 0xfd, + /*8650:*/ 0xa1, 0x70, 0xac, 0xc6, 0xb8, 0x8e, 0x40, 0xdc, 0x6b, 0x1a, 0x9e, 0x09, 0x4b, 0x6b, 0xed, 0xbd, + /*8660:*/ 0xb8, 0xc5, 0x50, 0x59, 0x7f, 0x71, 0x67, 0xbb, 0xac, 0x74, 0x06, 0xa6, 0x2b, 0x2b, 0x6f, 0xb9, + /*8670:*/ 0x92, 0xdb, 0xac, 0x6e, 0x88, 0x56, 0x80, 0x7c, 0xcd, 0x6f, 0x01, 0x5c, 0xa8, 0x10, 0x66, 0xe1, + /*8680:*/ 0x4e, 0x28, 0x32, 0xd4, 0xf0, 0x1f, 0x71, 0x3b, 0xcb, 0x80, 0x86, 0x00, 0xe5, 0x85, 0xd5, 0xf6, + /*8690:*/ 0x69, 0x62, 0xbf, 0x3a, 0x52, 0x6e, 0xcd, 0x21, 0xde, 0x16, 0xe2, 0x6b, 0x64, 0x0e, 0xae, 0x4e, + /*86a0:*/ 0xf3, 0xaa, 0xb4, 0xbe, 0xc7, 0xd0, 0xe1, 0xc4, 0x41, 0xf0, 0xaa, 0x83, 0xf3, 0xfa, 0x36, 0x97, + /*86b0:*/ 0x10, 0x36, 0x9a, 0xad, 0xd4, 0x61, 0xf2, 0x19, 0x0e, 0xce, 0xa5, 0x31, 0x24, 0x69, 0xf2, 0xde, + /*86c0:*/ 0xb7, 0x90, 0xd1, 0x0b, 0x2b, 0xc7, 0x16, 0x95, 0xf2, 0xa9, 0x54, 0x59, 0x8c, 0x03, 0x66, 0xb5, + /*86d0:*/ 0xf4, 0x5c, 0x10, 0x9c, 0xae, 0x19, 0xdd, 0x81, 0xbf, 0x82, 0x6b, 0x3d, 0xf2, 0x52, 0xe3, 0xb4, + /*86e0:*/ 0x59, 0x3e, 0x9b, 0x5f, 0x6a, 0x49, 0xa7, 0xb9, 0x5b, 0xae, 0xd7, 0xc0, 0x9f, 0xd5, 0x73, 0x7c, + /*86f0:*/ 0x9f, 0xba, 0xcc, 0x8f, 0x8a, 0x87, 0x91, 0xac, 0x5e, 0x24, 0x89, 0xe6, 0x8c, 0x7a, 0x61, 0x04, + /*8700:*/ 0x0d, 0xd0, 0x28, 0x83, 0xe0, 0x78, 0x7c, 0x7c, 0x97, 0xf6, 0x8c, 0x24, 0x56, 0x47, 0xb3, 0x6e, + /*8710:*/ 0xcb, 0xd3, 0x5c, 0x36, 0xb2, 0xe9, 0x2c, 0x6b, 0xae, 0xf8, 0x09, 0xb2, 0x1c, 0xa9, 0x5b, 0xbc, + /*8720:*/ 0xde, 0x9b, 0x8b, 0xcc, 0xc3, 0x05, 0x3d, 0xb9, 0x3d, 0x7b, 0xba, 0xd3, 0xb0, 0x89, 0xfc, 0xb4, + /*8730:*/ 0x0a, 0x90, 0x19, 0x7d, 0x96, 0x67, 0x0f, 0x0f, 0x1b, 0x0f, 0x7c, 0xef, 0xed, 0x9f, 0x5f, 0x4e, + /*8740:*/ 0x27, 0x5e, 0x64, 0xd9, 0xc5, 0xd8, 0xe8, 0x70, 0xfc, 0xe0, 0xca, 0x69, 0x16, 0x4a, 0xae, 0x0d, + /*8750:*/ 0x53, 0x2f, 0x1b, 0x51, 0x0e, 0x4c, 0xcc, 0x4d, 0x5c, 0x43, 0x63, 0x0a, 0x69, 0x10, 0x5a, 0xe9, + /*8760:*/ 0x90, 0x93, 0xd0, 0x14, 0xc8, 0x36, 0x30, 0xce, 0xfa, 0x29, 0x88, 0xa8, 0x19, 0xff, 0x32, 0x9c, + /*8770:*/ 0xbf, 0xa0, 0xc3, 0x09, 0x7d, 0x6a, 0xb0, 0xbd, 0x42, 0x6f, 0xdd, 0x59, 0x6b, 0xe7, 0xae, 0x05, + /*8780:*/ 0x7b, 0xcd, 0x9e, 0xeb, 0xcd, 0xf5, 0x4c, 0x19, 0xce, 0xc3, 0x6f, 0x1c, 0x66, 0x55, 0x9b, 0x17, + /*8790:*/ 0xd5, 0x5b, 0xaf, 0xa9, 0x84, 0xf6, 0x80, 0xfd, 0x6f, 0x3e, 0xc1, 0x8e, 0x7b, 0x05, 0x8c, 0x63, + /*87a0:*/ 0xf3, 0xb8, 0x7e, 0x91, 0x1c, 0x26, 0x25, 0x96, 0xf9, 0xab, 0xce, 0x80, 0xba, 0x61, 0x03, 0xd9, + /*87b0:*/ 0xb8, 0x72, 0x4b, 0x40, 0xea, 0x4b, 0x8c, 0x2d, 0x83, 0x70, 0x50, 0x5f, 0x42, 0x6f, 0x0d, 0xdf, + /*87c0:*/ 0xa4, 0xdc, 0x3d, 0x01, 0x51, 0x5f, 0x94, 0x0e, 0x7f, 0xc0, 0x2e, 0xa1, 0xe2, 0x5b, 0x99, 0xf5, + /*87d0:*/ 0x32, 0xad, 0x9a, 0x2f, 0x7c, 0xcd, 0x09, 0xb4, 0x71, 0x3b, 0x2e, 0xba, 0xbd, 0xf8, 0xce, 0xba, + /*87e0:*/ 0x34, 0x93, 0xd6, 0x2d, 0x35, 0xac, 0x33, 0x99, 0x3a, 0x1a, 0x94, 0xf6, 0x9a, 0x59, 0xf0, 0xcc, + /*87f0:*/ 0xe5, 0x46, 0xde, 0xfb, 0x31, 0x7f, 0x0c, 0x95, 0x66, 0x2c, 0xc2, 0x84, 0x00, 0xf6, 0x12, 0xfa, + /*8800:*/ 0xb8, 0xbd, 0x24, 0xd3, 0xdd, 0x4d, 0xfc, 0xc9, 0x38, 0xfe, 0x14, 0xd4, 0xb6, 0xe2, 0xc3, 0x2a, + /*8810:*/ 0x3f, 0xc3, 0x7e, 0x66, 0x30, 0x4b, 0x3a, 0x14, 0x3d, 0xbb, 0x6f, 0x30, 0x3f, 0xce, 0x27, 0xc4, + /*8820:*/ 0xd2, 0xc0, 0x60, 0x41, 0x86, 0x83, 0x11, 0x0c, 0x7e, 0x1a, 0x16, 0xca, 0xb9, 0x44, 0xde, 0xbe, + /*8830:*/ 0x84, 0xac, 0x43, 0x67, 0x49, 0x07, 0xb4, 0xc9, 0x75, 0x19, 0xf1, 0x70, 0x95, 0xfb, 0x06, 0x73, + /*8840:*/ 0x3d, 0x0a, 0x5b, 0x66, 0x13, 0x7c, 0x0e, 0x10, 0x62, 0x26, 0x30, 0x26, 0x3e, 0xd7, 0x27, 0x57, + /*8850:*/ 0xd3, 0xd4, 0x83, 0x31, 0x42, 0xcd, 0x95, 0xcf, 0xbd, 0xf7, 0x46, 0x36, 0x93, 0x91, 0xfc, 0x36, + /*8860:*/ 0x34, 0x4b, 0xb8, 0x3a, 0x20, 0xcb, 0x4d, 0x91, 0x78, 0x9e, 0xa7, 0xb4, 0x1a, 0xe4, 0xe2, 0x4a, + /*8870:*/ 0x1a, 0xee, 0x39, 0x3a, 0x39, 0xac, 0xa0, 0x4d, 0x12, 0xdf, 0xe6, 0xad, 0xdc, 0xf3, 0x71, 0xa7, + /*8880:*/ 0xcb, 0x34, 0xc8, 0xd2, 0xc8, 0x35, 0x82, 0x2a, 0xef, 0x42, 0x32, 0x8a, 0x6c, 0x57, 0xbc, 0xb5, + /*8890:*/ 0xd4, 0x8f, 0xca, 0x10, 0x5a, 0x4e, 0x41, 0xc1, 0x1c, 0x50, 0x3a, 0xca, 0x62, 0x95, 0x6b, 0x29, + /*88a0:*/ 0x25, 0xbb, 0xfd, 0xc3, 0xbe, 0x2b, 0xce, 0xf6, 0x83, 0xd5, 0xfa, 0x26, 0x30, 0xfa, 0x36, 0xa9, + /*88b0:*/ 0xe7, 0x26, 0x4e, 0x95, 0xbb, 0x73, 0xbe, 0x56, 0xc6, 0x26, 0xb4, 0xa7, 0x60, 0x27, 0x19, 0x8f, + /*88c0:*/ 0x1d, 0x49, 0xe2, 0xfd, 0x99, 0xce, 0xb1, 0x75, 0x20, 0x34, 0xcf, 0x55, 0xa1, 0xab, 0x4b, 0x4b, + /*88d0:*/ 0x89, 0x8b, 0x5e, 0x24, 0xe6, 0x8f, 0xbe, 0x6a, 0xfb, 0x23, 0x9b, 0x52, 0xe2, 0xcd, 0x37, 0xb8, + /*88e0:*/ 0xa1, 0xc3, 0xf6, 0x6b, 0xb8, 0x11, 0x33, 0x1f, 0xa6, 0xd2, 0xed, 0x54, 0x0c, 0xce, 0xba, 0xe2, + /*88f0:*/ 0x20, 0xb6, 0xca, 0x6d, 0x69, 0xde, 0xc6, 0x7e, 0xa4, 0xd0, 0xbb, 0xb3, 0x31, 0x81, 0xc7, 0x17, + /*8900:*/ 0x07, 0x76, 0xc3, 0x72, 0xaf, 0x66, 0x3c, 0x9f, 0x9b, 0x95, 0x51, 0xdc, 0x94, 0xbf, 0xd0, 0x84, + /*8910:*/ 0xb8, 0x7c, 0x88, 0xda, 0x3d, 0x2b, 0x15, 0x20, 0xb7, 0x26, 0x9d, 0x3f, 0xd0, 0x5c, 0x10, 0x26, + /*8920:*/ 0x42, 0x4a, 0xfc, 0x1f, 0xf9, 0xe3, 0x25, 0x1b, 0xe2, 0x4e, 0x35, 0x76, 0xdf, 0x4c, 0xcc, 0x7e, + /*8930:*/ 0x13, 0x46, 0x8d, 0x40, 0xdf, 0xa4, 0xbd, 0x71, 0x6d, 0xa3, 0x8b, 0x0b, 0x2c, 0x31, 0x8c, 0xbd, + /*8940:*/ 0x5e, 0x3c, 0x19, 0x0b, 0x2b, 0x59, 0x9d, 0xb2, 0x7f, 0xb7, 0xe1, 0xe4, 0x42, 0x9a, 0x20, 0xcd, + /*8950:*/ 0x9e, 0x49, 0x9b, 0x4e, 0x3f, 0xca, 0xc3, 0x45, 0x23, 0xd3, 0x56, 0xd8, 0xe9, 0x83, 0xae, 0x53, + /*8960:*/ 0x7e, 0x53, 0x83, 0x37, 0xa0, 0x03, 0x06, 0x26, 0x7b, 0x4d, 0x87, 0x50, 0x48, 0xab, 0x50, 0x7b, + /*8970:*/ 0x5b, 0x91, 0x69, 0xeb, 0xbc, 0xce, 0x22, 0x12, 0x36, 0xbc, 0x36, 0xb1, 0xde, 0xf3, 0x92, 0xce, + /*8980:*/ 0x8e, 0x4b, 0x5c, 0xdc, 0xa5, 0x46, 0xab, 0x1d, 0x60, 0x0b, 0xf2, 0x2b, 0xbe, 0xf4, 0xa5, 0xa2, + /*8990:*/ 0x69, 0xf1, 0x7e, 0x5f, 0x53, 0x28, 0xd9, 0xec, 0xb7, 0xf5, 0x8b, 0x9d, 0x87, 0x18, 0xac, 0x7c, + /*89a0:*/ 0x33, 0x1e, 0x8b, 0xfc, 0x77, 0x4c, 0xae, 0xbc, 0x33, 0xae, 0x25, 0xa0, 0x7a, 0x91, 0xd3, 0x22, + /*89b0:*/ 0xc4, 0xbf, 0x18, 0xb3, 0xa3, 0x6a, 0x79, 0x22, 0xb5, 0x07, 0x30, 0xd8, 0x71, 0x79, 0xf7, 0xd2, + /*89c0:*/ 0x35, 0xab, 0x51, 0xce, 0x51, 0xcb, 0xd6, 0x22, 0x61, 0xf8, 0x92, 0xe7, 0xeb, 0xb0, 0x15, 0x9a, + /*89d0:*/ 0xb4, 0x6f, 0x5c, 0x9c, 0x0f, 0xad, 0x41, 0x61, 0xbe, 0xbd, 0x0e, 0xc4, 0xb0, 0x15, 0x34, 0xc4, + /*89e0:*/ 0xf7, 0x8c, 0xf0, 0x26, 0xbe, 0x7f, 0x99, 0xd0, 0x04, 0x5a, 0x90, 0x9d, 0x16, 0xe8, 0x93, 0x8a, + /*89f0:*/ 0x39, 0xb0, 0x2c, 0xfa, 0x03, 0x78, 0xb3, 0x2e, 0x5d, 0x06, 0x6a, 0x21, 0x3b, 0x8a, 0x7a, 0x22, + /*8a00:*/ 0x10, 0x70, 0x82, 0x1c, 0x69, 0x88, 0x89, 0x51, 0x11, 0x43, 0x7c, 0x9c, 0x3e, 0xcd, 0x7e, 0x7a, + /*8a10:*/ 0x99, 0xb4, 0x1c, 0xf3, 0xd8, 0xd3, 0x1b, 0xfa, 0x9d, 0xec, 0xd4, 0x36, 0xcc, 0xac, 0x5e, 0xc3, + /*8a20:*/ 0xd9, 0x45, 0x7b, 0xc6, 0x7b, 0x1d, 0xfe, 0xa5, 0xac, 0xb9, 0x22, 0xe0, 0x18, 0xc0, 0x1d, 0x04, + /*8a30:*/ 0xfe, 0x9a, 0xb9, 0xc8, 0x40, 0xa2, 0xcc, 0x3e, 0xb4, 0x81, 0xfe, 0x0f, 0xf8, 0xc4, 0xe0, 0x89, + /*8a40:*/ 0xfc, 0xfd, 0x93, 0x2d, 0xd0, 0x00, 0x52, 0x70, 0x5a, 0x95, 0x41, 0x4e, 0xbd, 0xd3, 0x76, 0x2b, + /*8a50:*/ 0xa4, 0xa3, 0x56, 0x22, 0x50, 0x6d, 0xc2, 0xd2, 0x59, 0xea, 0xe8, 0x32, 0x9c, 0x84, 0xdc, 0x93, + /*8a60:*/ 0xad, 0xdb, 0xaf, 0xba, 0xb3, 0x0e, 0x38, 0x0a, 0xac, 0xde, 0xe7, 0xff, 0x87, 0xcd, 0x9b, 0x80, + /*8a70:*/ 0xea, 0x72, 0x10, 0x66, 0xff, 0x63, 0x7f, 0xe6, 0x33, 0x88, 0xd2, 0xc0, 0xdc, 0xd6, 0xcb, 0xe6, + /*8a80:*/ 0xcb, 0x37, 0x70, 0x74, 0x72, 0x26, 0xac, 0x73, 0xbf, 0x1d, 0x6f, 0x75, 0x6c, 0xe5, 0xb5, 0x37, + /*8a90:*/ 0x4e, 0xc3, 0x85, 0x58, 0x79, 0x2a, 0x21, 0x51, 0xe1, 0x16, 0x00, 0x31, 0x75, 0x0e, 0x79, 0x5e, + /*8aa0:*/ 0x3d, 0x84, 0x19, 0x22, 0x2b, 0x97, 0x4a, 0x59, 0x2b, 0xa0, 0x79, 0x53, 0x45, 0x34, 0x35, 0x2f, + /*8ab0:*/ 0x8a, 0xfd, 0x64, 0xf2, 0x0b, 0xb5, 0xe4, 0xb9, 0x73, 0xe9, 0xee, 0x47, 0xb0, 0x51, 0x5a, 0x5f, + /*8ac0:*/ 0xf9, 0x2a, 0xe1, 0xd5, 0x5a, 0xee, 0x67, 0xaf, 0xb5, 0xfa, 0x28, 0x8a, 0xec, 0xec, 0x5f, 0x38, + /*8ad0:*/ 0x4a, 0xdb, 0x0e, 0x1a, 0xbd, 0x57, 0x09, 0xcc, 0x02, 0x09, 0xa4, 0x1f, 0xe1, 0x5b, 0x4d, 0x80, + /*8ae0:*/ 0xb0, 0x85, 0x97, 0xbb, 0x7e, 0x3e, 0x14, 0x18, 0xe6, 0xc8, 0x84, 0x57, 0x88, 0x3c, 0xe8, 0x09, + /*8af0:*/ 0x91, 0x93, 0xda, 0x5a, 0x77, 0x9a, 0x23, 0x77, 0x18, 0x1c, 0x16, 0xb8, 0x22, 0xf6, 0xc5, 0x73, + /*8b00:*/ 0xc3, 0xc4, 0x44, 0x4b, 0x8b, 0xa5, 0x4f, 0xdc, 0xa1, 0x65, 0xc1, 0x99, 0xfb, 0x97, 0xf8, 0x4f, + /*8b10:*/ 0xe9, 0xd0, 0xc4, 0x66, 0xd4, 0xed, 0x3e, 0x58, 0x8d, 0x6c, 0x09, 0xe7, 0xad, 0xde, 0x66, 0xa6, + /*8b20:*/ 0x82, 0xfc, 0xc2, 0xf8, 0x04, 0x6f, 0x5c, 0x6a, 0xeb, 0x96, 0x85, 0x28, 0x03, 0xc7, 0x3f, 0xa7, + /*8b30:*/ 0x31, 0x75, 0x71, 0x56, 0x8d, 0x98, 0x0d, 0x08, 0x21, 0x1f, 0x59, 0x0c, 0x99, 0x72, 0x6a, 0xa4, + /*8b40:*/ 0xa7, 0x6f, 0x34, 0x70, 0x5e, 0x5a, 0xb5, 0x73, 0x01, 0xcb, 0xea, 0xa9, 0x59, 0x14, 0xa1, 0xfb, + /*8b50:*/ 0xda, 0x5d, 0x7d, 0x22, 0x35, 0x83, 0xd1, 0x16, 0x8a, 0x15, 0x2f, 0x4a, 0xb8, 0xfa, 0xf6, 0x6f, + /*8b60:*/ 0x92, 0x64, 0xbb, 0x32, 0xcb, 0x56, 0xd8, 0xec, 0xda, 0xec, 0xb7, 0x52, 0x77, 0x90, 0x36, 0x29, + /*8b70:*/ 0x65, 0x47, 0xdc, 0xc8, 0x31, 0x6b, 0xa5, 0xff, 0xf3, 0x00, 0x8d, 0x49, 0xb5, 0x70, 0xa7, 0x48, + /*8b80:*/ 0x53, 0x05, 0x6b, 0x0f, 0x49, 0x50, 0xb2, 0xdb, 0x8d, 0x77, 0x6d, 0x45, 0x03, 0xc4, 0x5a, 0xc0, + /*8b90:*/ 0x1f, 0x1d, 0x0f, 0x13, 0xc3, 0x7d, 0x0f, 0x75, 0xfc, 0xc5, 0xf1, 0x73, 0xcc, 0x14, 0x97, 0xc3, + /*8ba0:*/ 0x87, 0x45, 0xc7, 0x9e, 0xd5, 0x6b, 0x9b, 0x84, 0xd4, 0x00, 0x77, 0x0f, 0x67, 0xb1, 0x2c, 0xc8, + /*8bb0:*/ 0xdc, 0xa5, 0x13, 0xb0, 0x61, 0x61, 0x2b, 0x9c, 0xda, 0x51, 0xad, 0xfc, 0x49, 0x05, 0xc0, 0x47, + /*8bc0:*/ 0xb2, 0x43, 0x1c, 0x54, 0x47, 0xd4, 0xfb, 0x5a, 0xb3, 0x95, 0xda, 0xee, 0x0b, 0x0a, 0x4a, 0x94, + /*8bd0:*/ 0x4d, 0x3d, 0xdf, 0xf0, 0xb3, 0xb0, 0xb8, 0x60, 0xf7, 0x80, 0x97, 0xa8, 0xea, 0xdf, 0xde, 0x5e, + /*8be0:*/ 0x61, 0xff, 0x2a, 0x17, 0x6d, 0xfe, 0x53, 0x98, 0x4e, 0x2c, 0x22, 0x09, 0xc7, 0x09, 0x5b, 0xa0, + /*8bf0:*/ 0x2f, 0x90, 0xce, 0xb8, 0x70, 0xf1, 0xb2, 0x7c, 0xa0, 0x91, 0x8d, 0x9b, 0x26, 0x1a, 0x5c, 0x5b, + /*8c00:*/ 0xbc, 0x3d, 0xa8, 0xbb, 0x47, 0xde, 0x20, 0x1c, 0x22, 0xb7, 0xdf, 0xdf, 0x04, 0x5e, 0x97, 0xf7, + /*8c10:*/ 0xa7, 0xbb, 0x2e, 0x78, 0x62, 0xe9, 0xad, 0x73, 0x60, 0x37, 0x8d, 0x2c, 0x5d, 0x3e, 0xe3, 0x40, + /*8c20:*/ 0xdd, 0xb4, 0xc6, 0x1d, 0xe4, 0x8c, 0x79, 0x12, 0x3e, 0xe2, 0x38, 0x2e, 0xd4, 0xec, 0xcc, 0xeb, + /*8c30:*/ 0xe4, 0x37, 0xd5, 0x6e, 0x1b, 0x05, 0x20, 0xa3, 0x36, 0x45, 0x0f, 0xcf, 0xad, 0x31, 0x5b, 0xb6, + /*8c40:*/ 0x6f, 0x10, 0xc4, 0x95, 0x3b, 0xef, 0x07, 0xf4, 0xae, 0x4e, 0xb8, 0x93, 0x88, 0x30, 0x6a, 0x92, + /*8c50:*/ 0x83, 0xcd, 0xab, 0x19, 0xca, 0x30, 0xd2, 0x1d, 0x27, 0x00, 0x22, 0x42, 0xe8, 0x5f, 0x60, 0x54, + /*8c60:*/ 0x0d, 0xa1, 0xcf, 0x27, 0xb2, 0x95, 0xd2, 0x65, 0x1d, 0xb4, 0xb4, 0xc2, 0x57, 0x61, 0x7e, 0x12, + /*8c70:*/ 0x5e, 0x84, 0x0f, 0xa3, 0x02, 0xfe, 0x2e, 0x3c, 0xf2, 0x0e, 0xd7, 0x22, 0xb9, 0xae, 0xb6, 0xed, + /*8c80:*/ 0x48, 0xfd, 0xe3, 0x02, 0x42, 0xf4, 0x5e, 0x84, 0xb5, 0xce, 0xe4, 0x39, 0xa1, 0x26, 0x57, 0xc2, + /*8c90:*/ 0xe1, 0x05, 0x82, 0x66, 0x53, 0x6b, 0x7b, 0x26, 0x32, 0x58, 0x6f, 0x1c, 0x9c, 0x79, 0xa8, 0xd5, + /*8ca0:*/ 0x0b, 0xab, 0x75, 0xed, 0x34, 0x55, 0xc4, 0x55, 0x8a, 0x08, 0xb5, 0xdd, 0x96, 0xc8, 0xf0, 0x0f, + /*8cb0:*/ 0x3b, 0xe9, 0x03, 0xc5, 0x21, 0xcb, 0x52, 0xac, 0x80, 0x1a, 0x05, 0x81, 0x44, 0x75, 0x19, 0xb4, + /*8cc0:*/ 0x9e, 0x2e, 0x40, 0x50, 0xbf, 0xb2, 0x56, 0x1d, 0xd0, 0xc6, 0xcb, 0x09, 0x95, 0x55, 0xfd, 0xcc, + /*8cd0:*/ 0xd0, 0x5e, 0x3a, 0xab, 0x13, 0xf0, 0xdc, 0xb6, 0xfd, 0x80, 0x92, 0xf5, 0x24, 0xd9, 0xcc, 0xd2, + /*8ce0:*/ 0xf9, 0x37, 0xef, 0x42, 0x56, 0x0a, 0xf3, 0x67, 0xf4, 0x09, 0x0a, 0x3b, 0x24, 0x46, 0x85, 0x4c, + /*8cf0:*/ 0x54, 0x2b, 0x1d, 0xee, 0xc6, 0x2c, 0xe2, 0x30, 0x42, 0x20, 0xda, 0x3c, 0xe5, 0xac, 0x84, 0x9e, + /*8d00:*/ 0x64, 0xc1, 0xf8, 0xbc, 0x2b, 0xcb, 0xb1, 0x92, 0xa6, 0x82, 0x9f, 0x31, 0xec, 0x5b, 0x82, 0x41, + /*8d10:*/ 0x9b, 0x59, 0xe8, 0x70, 0x87, 0xcf, 0xd0, 0xd3, 0xfc, 0xc9, 0xbe, 0x8a, 0xba, 0x8e, 0x81, 0x7c, + /*8d20:*/ 0x54, 0xf3, 0x96, 0x66, 0xec, 0x3e, 0x0c, 0x7d, 0xdf, 0x46, 0xe3, 0xdf, 0xad, 0x64, 0x10, 0xc1, + /*8d30:*/ 0x7e, 0x71, 0x62, 0xd4, 0xc9, 0x92, 0x6f, 0xae, 0x46, 0x33, 0x44, 0xfd, 0xb2, 0x68, 0x4e, 0xd4, + /*8d40:*/ 0xdf, 0x00, 0x1e, 0xda, 0xfd, 0x25, 0x01, 0x56, 0x2e, 0xd6, 0xec, 0xa0, 0xca, 0x47, 0x3e, 0x9f, + /*8d50:*/ 0x0e, 0xd8, 0x91, 0x51, 0xb3, 0x5e, 0xf1, 0x09, 0x6a, 0xa2, 0x66, 0x90, 0xe7, 0x5d, 0x89, 0x97, + /*8d60:*/ 0x4e, 0xb1, 0x2b, 0xe4, 0x2b, 0x0a, 0x5e, 0x29, 0x19, 0xd7, 0xbd, 0x72, 0xc4, 0xf4, 0xdd, 0xbf, + /*8d70:*/ 0x2f, 0x9c, 0x37, 0x41, 0xed, 0x5e, 0x6f, 0x8e, 0x54, 0xdb, 0x4b, 0x60, 0x5b, 0x24, 0x5e, 0x7c, + /*8d80:*/ 0x8f, 0xf5, 0x6a, 0xb8, 0x1a, 0x31, 0xd9, 0x64, 0xb6, 0x5a, 0x47, 0x59, 0xf9, 0x19, 0xc8, 0x67, + /*8d90:*/ 0xc3, 0x92, 0x0d, 0xb7, 0x27, 0xfa, 0x88, 0x10, 0x96, 0x27, 0x76, 0xf9, 0x0a, 0x29, 0x09, 0x36, + /*8da0:*/ 0x93, 0xe2, 0x00, 0x29, 0xdc, 0x27, 0x35, 0x82, 0x45, 0x27, 0xc9, 0xf9, 0x87, 0xdb, 0x02, 0x2c, + /*8db0:*/ 0xcd, 0x80, 0x60, 0x8f, 0xab, 0x34, 0x59, 0xb1, 0x95, 0x50, 0xc7, 0x7f, 0x8b, 0xd5, 0x32, 0x1a, + /*8dc0:*/ 0xed, 0xd5, 0xef, 0x9a, 0x0b, 0x5f, 0x67, 0x53, 0xdf, 0xe3, 0xa0, 0xa0, 0x45, 0xef, 0xd0, 0x96, + /*8dd0:*/ 0xf2, 0x4a, 0x03, 0xe7, 0x88, 0xe1, 0x0d, 0xcc, 0x37, 0x8a, 0x2b, 0x83, 0x45, 0x23, 0x99, 0x2a, + /*8de0:*/ 0xc0, 0x57, 0xd0, 0xea, 0xd5, 0xb7, 0xc4, 0x38, 0xae, 0xe5, 0x2c, 0x77, 0x97, 0xc2, 0x7b, 0xcf, + /*8df0:*/ 0x76, 0x5f, 0x29, 0xf4, 0xbb, 0xb8, 0xcf, 0xb4, 0xd7, 0xe5, 0x58, 0x02, 0xf0, 0x10, 0xe8, 0xda, + /*8e00:*/ 0x29, 0x06, 0xc3, 0x56, 0xf1, 0x1b, 0x22, 0xc9, 0x83, 0x3d, 0x68, 0xca, 0x32, 0x1c, 0x3a, 0x2b, + /*8e10:*/ 0xbe, 0x83, 0xb6, 0x19, 0x0b, 0xad, 0xa7, 0x0e, 0x7b, 0x4e, 0x9e, 0xa5, 0xaa, 0xc6, 0xb8, 0x33, + /*8e20:*/ 0x66, 0x57, 0xca, 0x1e, 0x61, 0xef, 0x4b, 0x1b, 0xb9, 0x4a, 0xc1, 0x84, 0x65, 0x43, 0x38, 0xa2, + /*8e30:*/ 0x13, 0x05, 0x4e, 0xe4, 0xe8, 0xac, 0x47, 0xd9, 0xb8, 0x3e, 0x14, 0xd4, 0x0c, 0x98, 0xdc, 0x1f, + /*8e40:*/ 0x92, 0x74, 0x92, 0xaf, 0xa6, 0x56, 0x36, 0xc4, 0xf0, 0xd5, 0x14, 0x66, 0xb2, 0xc9, 0x68, 0x51, + /*8e50:*/ 0xaf, 0x93, 0xa6, 0xe7, 0x76, 0x74, 0x18, 0x84, 0xc6, 0xb3, 0x93, 0x19, 0xc8, 0xe8, 0x92, 0x31, + /*8e60:*/ 0x84, 0xb2, 0xd2, 0x1a, 0x6d, 0x70, 0x95, 0xaa, 0x16, 0x63, 0x2d, 0xa9, 0x90, 0x9e, 0x66, 0x80, + /*8e70:*/ 0x71, 0xe0, 0xc6, 0xc4, 0x50, 0xf8, 0x20, 0x80, 0xcd, 0xbe, 0x08, 0x5d, 0xdd, 0x69, 0x51, 0xbb, + /*8e80:*/ 0x1a, 0xd0, 0x28, 0x7f, 0x02, 0x0f, 0xac, 0x90, 0xb6, 0xfc, 0xaa, 0x81, 0x09, 0x3e, 0xc5, 0x72, + /*8e90:*/ 0x7e, 0x30, 0xe3, 0x42, 0x81, 0x8b, 0x03, 0x8b, 0x1f, 0x96, 0x02, 0xfa, 0xe1, 0xf3, 0xc5, 0x1e, + /*8ea0:*/ 0xfd, 0x5e, 0x30, 0xfe, 0xec, 0x09, 0x86, 0x83, 0x48, 0x78, 0x41, 0x48, 0xf7, 0x42, 0xa0, 0xe5, + /*8eb0:*/ 0xc7, 0x50, 0x5b, 0x60, 0xa8, 0xb1, 0xdc, 0xe4, 0xc3, 0x30, 0xca, 0x3b, 0xdc, 0x16, 0x13, 0xf7, + /*8ec0:*/ 0xca, 0xff, 0x1f, 0x74, 0x73, 0x47, 0x52, 0x2c, 0x54, 0x2f, 0x1b, 0xe2, 0xb5, 0xaf, 0xaf, 0xc7, + /*8ed0:*/ 0x2c, 0x53, 0x16, 0x0f, 0xf7, 0xe7, 0x99, 0x7d, 0x57, 0x88, 0xe6, 0x39, 0xe7, 0x66, 0x73, 0xaf, + /*8ee0:*/ 0xab, 0x9f, 0x74, 0x4f, 0x0a, 0xd9, 0x0d, 0x9d, 0xc1, 0x5c, 0x43, 0x8d, 0x7a, 0x90, 0x56, 0xe2, + /*8ef0:*/ 0xd7, 0x8e, 0x76, 0xd9, 0xe9, 0x7f, 0x93, 0x66, 0x1c, 0x32, 0x1e, 0xda, 0x25, 0xbf, 0x28, 0x85, + /*8f00:*/ 0xea, 0xe8, 0x72, 0x9b, 0x7b, 0x32, 0xd7, 0xac, 0x20, 0xc2, 0x2e, 0x08, 0x27, 0x0e, 0xa6, 0x80, + /*8f10:*/ 0x6c, 0x15, 0x49, 0x20, 0xda, 0x01, 0xae, 0x5f, 0x07, 0x1e, 0xc2, 0x13, 0xcf, 0x51, 0xbe, 0xca, + /*8f20:*/ 0x68, 0x22, 0x59, 0xff, 0x0c, 0x05, 0xe2, 0x3a, 0xa3, 0xce, 0x60, 0xde, 0x7b, 0xa7, 0x89, 0xa1, + /*8f30:*/ 0x8b, 0xad, 0xc0, 0x5d, 0x5e, 0x31, 0x52, 0x64, 0x1a, 0xc1, 0x0e, 0xd2, 0xb2, 0x56, 0x4c, 0x01, + /*8f40:*/ 0xd9, 0x0e, 0xa8, 0x1b, 0x64, 0x7b, 0xa7, 0xcd, 0x02, 0x6f, 0x43, 0xbe, 0xfa, 0x46, 0x5c, 0xdd, + /*8f50:*/ 0xae, 0x5b, 0xe7, 0x53, 0x11, 0x3a, 0xc9, 0x03, 0xfb, 0x64, 0xfd, 0xfc, 0x89, 0x45, 0xf5, 0x8b, + /*8f60:*/ 0x54, 0x41, 0x15, 0xa2, 0x68, 0x72, 0x35, 0x21, 0xcf, 0xa5, 0x20, 0xb5, 0xbc, 0x3c, 0x0d, 0xa0, + /*8f70:*/ 0xed, 0xf5, 0xe9, 0xfd, 0xb2, 0x8e, 0x12, 0xc3, 0xcf, 0x9a, 0x96, 0x2f, 0x19, 0x9f, 0x2a, 0xdc, + /*8f80:*/ 0x1d, 0x7e, 0x2d, 0x98, 0x7d, 0x88, 0x6a, 0x84, 0x4a, 0xb5, 0xca, 0xaf, 0x77, 0x83, 0xea, 0x92, + /*8f90:*/ 0x10, 0xd9, 0x81, 0xc5, 0x8b, 0x38, 0x01, 0xc6, 0x4b, 0x00, 0x85, 0x58, 0xaa, 0x79, 0xe4, 0x95, + /*8fa0:*/ 0x09, 0x31, 0x93, 0x5e, 0x74, 0xee, 0x87, 0x26, 0x91, 0xd7, 0x82, 0x89, 0x77, 0x99, 0xf7, 0xc2, + /*8fb0:*/ 0x3e, 0x0b, 0xd9, 0xe6, 0x67, 0x15, 0x8b, 0x62, 0xe7, 0x1f, 0xde, 0x9c, 0xf4, 0xee, 0x19, 0x06, + /*8fc0:*/ 0xec, 0x04, 0x9f, 0xe2, 0xcd, 0x27, 0xce, 0x57, 0xb2, 0xa8, 0x8c, 0xac, 0x9f, 0x26, 0xdb, 0xc7, + /*8fd0:*/ 0x44, 0xcc, 0x03, 0x0b, 0x44, 0xff, 0xa5, 0x52, 0x79, 0x7d, 0xea, 0x54, 0x31, 0xa0, 0xe9, 0xbb, + /*8fe0:*/ 0x89, 0x05, 0x07, 0x7a, 0x29, 0x3f, 0xa1, 0xd2, 0xff, 0xd2, 0x5b, 0x1a, 0x86, 0xca, 0x96, 0x6b, + /*8ff0:*/ 0x86, 0x59, 0x7a, 0x43, 0x82, 0xd4, 0x63, 0x9f, 0x92, 0xfa, 0x54, 0x92, 0x72, 0x2b, 0x1b, 0x4d, + /*9000:*/ 0x98, 0x22, 0x9f, 0xbf, 0x4e, 0xd9, 0x15, 0xbf, 0x77, 0x18, 0xf3, 0x40, 0x25, 0xfc, 0x32, 0xe1, + /*9010:*/ 0x6e, 0xc5, 0xd4, 0xc7, 0x92, 0xf3, 0xa3, 0x44, 0x29, 0xe3, 0xdb, 0x95, 0xe9, 0x9d, 0xdf, 0x6a, + /*9020:*/ 0x46, 0xd6, 0xcd, 0x67, 0x36, 0x09, 0xfa, 0xa1, 0x01, 0xc4, 0x55, 0x84, 0x1c, 0xb4, 0x02, 0x7e, + /*9030:*/ 0x5f, 0x70, 0x25, 0xc1, 0x61, 0x9c, 0xfc, 0xa2, 0xa2, 0x15, 0x17, 0x7d, 0x9c, 0x5f, 0x67, 0x41, + /*9040:*/ 0xca, 0x60, 0x0b, 0x9e, 0x48, 0x71, 0x16, 0xc6, 0x0b, 0xf4, 0x03, 0x86, 0xb5, 0x0e, 0xad, 0xc6, + /*9050:*/ 0xf8, 0xbd, 0x96, 0x46, 0xe1, 0xc6, 0xe0, 0x96, 0x0a, 0x95, 0xda, 0x5f, 0xba, 0x0b, 0x56, 0xc1, + /*9060:*/ 0x39, 0x20, 0xd0, 0xa8, 0xf4, 0x06, 0x7c, 0xc7, 0x02, 0xed, 0x5a, 0x7b, 0xaa, 0x0f, 0x4c, 0x71, + /*9070:*/ 0xf7, 0x8a, 0xeb, 0x95, 0xd9, 0x08, 0xfa, 0x57, 0xd4, 0x0a, 0xed, 0x10, 0xda, 0xf8, 0x3e, 0xa0, + /*9080:*/ 0xeb, 0xf2, 0x27, 0x2f, 0x7f, 0x65, 0x47, 0x76, 0x33, 0x0f, 0x96, 0xc7, 0x6e, 0xbe, 0x07, 0xe7, + /*9090:*/ 0xd5, 0xdc, 0x49, 0xc3, 0x94, 0x32, 0xc0, 0xa0, 0xb1, 0x80, 0xab, 0x0a, 0xd7, 0x7b, 0x88, 0x10, + /*90a0:*/ 0xa1, 0x0b, 0x23, 0x5b, 0x2f, 0x61, 0x67, 0xd0, 0x01, 0xd9, 0xb4, 0xc3, 0xda, 0x34, 0xb3, 0x09, + /*90b0:*/ 0x58, 0x9f, 0x7b, 0x65, 0x4e, 0x8b, 0xc2, 0xb7, 0x19, 0x6f, 0x27, 0x72, 0x8e, 0x20, 0x32, 0x23, + /*90c0:*/ 0xcb, 0xbd, 0x3a, 0x97, 0xf6, 0xb0, 0xc0, 0xab, 0x23, 0x2d, 0x37, 0x1f, 0x00, 0x54, 0xbc, 0x51, + /*90d0:*/ 0x17, 0xd1, 0x79, 0xbe, 0x2b, 0x24, 0xe7, 0xfc, 0x2a, 0x61, 0x04, 0xc9, 0xc5, 0x95, 0x7e, 0x09, + /*90e0:*/ 0x53, 0x9f, 0x6c, 0x93, 0x26, 0x48, 0xa1, 0x21, 0x84, 0xcc, 0x3c, 0xbc, 0x48, 0x67, 0xdb, 0x82, + /*90f0:*/ 0x73, 0xdf, 0x42, 0xe4, 0xf0, 0x34, 0x28, 0xff, 0xa5, 0x32, 0x4d, 0x6f, 0xa7, 0x09, 0x07, 0xa9, + /*9100:*/ 0x70, 0xaf, 0x1a, 0xd4, 0x41, 0x92, 0x7a, 0x7e, 0x6b, 0x7b, 0x43, 0xd1, 0xa8, 0x79, 0xdd, 0x29, + /*9110:*/ 0xf9, 0x37, 0xb3, 0x3f, 0xad, 0x3c, 0x59, 0xc2, 0x01, 0x5c, 0x50, 0xbd, 0x65, 0x57, 0xbe, 0x63, + /*9120:*/ 0x62, 0x8e, 0x3f, 0x66, 0xf3, 0xd7, 0x38, 0xa4, 0x65, 0x67, 0xab, 0x24, 0xbb, 0x5c, 0x94, 0x38, + /*9130:*/ 0xda, 0x46, 0x36, 0xc3, 0x06, 0x88, 0x7e, 0xba, 0x7c, 0x2c, 0xc1, 0x47, 0x78, 0x1d, 0x9f, 0x5b, + /*9140:*/ 0xd8, 0x58, 0xc7, 0xd4, 0x7c, 0x47, 0xab, 0x05, 0xe2, 0xcb, 0x44, 0xe2, 0xbf, 0x9b, 0xc8, 0xe9, + /*9150:*/ 0x45, 0xe7, 0x3f, 0x27, 0x8a, 0xbe, 0xed, 0x82, 0x09, 0xa3, 0xa4, 0x71, 0x65, 0x4d, 0x8f, 0xdd, + /*9160:*/ 0x52, 0xfa, 0x4f, 0xfb, 0x47, 0x70, 0x03, 0x34, 0x34, 0xc2, 0x3a, 0xf4, 0xb5, 0xa2, 0xa5, 0xc6, + /*9170:*/ 0x82, 0xea, 0x76, 0x1b, 0x89, 0x14, 0xd4, 0xec, 0x2e, 0x47, 0xb1, 0x22, 0xde, 0xaf, 0xa0, 0x36, + /*9180:*/ 0x8d, 0xcf, 0xc1, 0xe0, 0x49, 0x07, 0xbf, 0x7c, 0xad, 0xf9, 0xf5, 0x10, 0x70, 0x49, 0x5e, 0x76, + /*9190:*/ 0x0a, 0x64, 0xa1, 0xde, 0x47, 0xde, 0x42, 0xc4, 0xc9, 0x0e, 0xcc, 0x97, 0x16, 0xa3, 0x72, 0x94, + /*91a0:*/ 0xde, 0x16, 0x03, 0xa1, 0xf6, 0x87, 0x97, 0x5c, 0x6a, 0xed, 0x99, 0x94, 0x48, 0x27, 0xc9, 0x33, + /*91b0:*/ 0x42, 0xdc, 0x13, 0x8b, 0xef, 0x93, 0x21, 0xa1, 0x53, 0x8f, 0xd8, 0xcb, 0xb1, 0xef, 0x66, 0xfa, + /*91c0:*/ 0xc5, 0x01, 0xa9, 0x11, 0xfc, 0x52, 0x91, 0x28, 0x82, 0x00, 0x7d, 0xeb, 0xfc, 0xbb, 0x03, 0x3c, + /*91d0:*/ 0x90, 0x83, 0x0d, 0x37, 0x10, 0xdc, 0xdf, 0xd3, 0x6d, 0xb8, 0x36, 0xc1, 0xad, 0x4e, 0xf5, 0x54, + /*91e0:*/ 0xed, 0x2b, 0x85, 0x14, 0xe4, 0x50, 0x80, 0x88, 0x7e, 0x9d, 0x0c, 0x41, 0x13, 0x8b, 0x2b, 0x32, + /*91f0:*/ 0x2e, 0xc6, 0x52, 0x2e, 0x3f, 0x12, 0x53, 0xee, 0x63, 0x6d, 0xad, 0xfb, 0x04, 0xf9, 0xc0, 0xc4, + /*9200:*/ 0x7e, 0x71, 0x59, 0x9f, 0x28, 0xc8, 0xde, 0x50, 0xd3, 0xe3, 0xeb, 0xdd, 0x01, 0x55, 0x83, 0x8b, + /*9210:*/ 0xed, 0x76, 0x01, 0x02, 0xc4, 0x94, 0xb1, 0x47, 0xfe, 0xa8, 0x0e, 0x95, 0xdf, 0xaa, 0x82, 0x44, + /*9220:*/ 0x9b, 0x61, 0x65, 0xbc, 0x4b, 0xbc, 0x86, 0x85, 0xbd, 0x45, 0xee, 0x87, 0xd0, 0x76, 0x68, 0xe1, + /*9230:*/ 0xa7, 0x19, 0x0a, 0x75, 0xc4, 0x22, 0x32, 0x75, 0x01, 0x03, 0x8c, 0x98, 0xfa, 0x13, 0x79, 0x17, + /*9240:*/ 0x43, 0x8a, 0x76, 0x6e, 0xa7, 0x22, 0x46, 0x29, 0x0f, 0xb3, 0x1f, 0xa5, 0xf6, 0x34, 0x6d, 0x03, + /*9250:*/ 0xef, 0xf9, 0xcf, 0x52, 0x17, 0xef, 0x65, 0x01, 0xd9, 0x9d, 0xc1, 0x74, 0x10, 0x96, 0x5a, 0x60, + /*9260:*/ 0xc1, 0xc1, 0x79, 0xcc, 0xfe, 0x44, 0x80, 0x12, 0x15, 0x12, 0xf3, 0xa4, 0x6f, 0x45, 0x53, 0x03, + /*9270:*/ 0xbf, 0xcb, 0xbc, 0xaf, 0x11, 0xab, 0x2d, 0x56, 0x12, 0xeb, 0xd8, 0x16, 0x40, 0xd1, 0x2b, 0xfb, + /*9280:*/ 0xc5, 0x76, 0x7d, 0xc3, 0xe1, 0xcc, 0xd4, 0x0a, 0x15, 0xef, 0x78, 0x64, 0xdb, 0x1b, 0x67, 0x40, + /*9290:*/ 0x7c, 0xb9, 0x01, 0xc8, 0xaf, 0x29, 0xcc, 0x06, 0x74, 0x72, 0xd1, 0xf8, 0x9e, 0x77, 0x0a, 0xe4, + /*92a0:*/ 0x4d, 0x3e, 0xc5, 0x35, 0xd1, 0x3e, 0xcd, 0x8b, 0xd6, 0x75, 0x18, 0x0c, 0xdd, 0xc1, 0x1a, 0x2a, + /*92b0:*/ 0x83, 0x26, 0x64, 0x6b, 0x3a, 0x53, 0x04, 0x13, 0xb2, 0x51, 0x89, 0x17, 0xfd, 0xe7, 0x8e, 0x8b, + /*92c0:*/ 0xfb, 0xd1, 0x17, 0x61, 0x42, 0x30, 0x0b, 0xcb, 0x1d, 0x4b, 0x95, 0xbe, 0x60, 0xce, 0xf9, 0x53, + /*92d0:*/ 0xd5, 0x46, 0x7a, 0x46, 0x20, 0xed, 0x2b, 0xb0, 0x7a, 0x76, 0x07, 0x50, 0xcf, 0x72, 0x29, 0x93, + /*92e0:*/ 0x6d, 0x49, 0x43, 0xde, 0xb5, 0x06, 0x7a, 0xed, 0x99, 0x4e, 0x1b, 0x87, 0x71, 0xc8, 0x60, 0xb4, + /*92f0:*/ 0xd4, 0x3b, 0xe8, 0xbd, 0x2a, 0x21, 0x23, 0xba, 0x42, 0x81, 0xde, 0xe8, 0x60, 0xd7, 0xfd, 0xfd, + /*9300:*/ 0x99, 0x2b, 0x50, 0xfc, 0xa6, 0xa0, 0x03, 0xa2, 0x29, 0xdf, 0x0e, 0x2c, 0x02, 0x06, 0x33, 0xe7, + /*9310:*/ 0x34, 0x9a, 0x54, 0x43, 0x0c, 0xeb, 0xf0, 0xe8, 0x61, 0x05, 0x6a, 0x60, 0xb5, 0x64, 0xc7, 0x58, + /*9320:*/ 0xd0, 0x24, 0xe0, 0xfe, 0x6a, 0xd8, 0xb0, 0xa5, 0xe0, 0xbf, 0x3b, 0x54, 0xba, 0x0c, 0x93, 0x12, + /*9330:*/ 0x4e, 0x80, 0xf4, 0xd4, 0x17, 0x6b, 0x78, 0x48, 0x37, 0x41, 0x69, 0x73, 0xc8, 0xee, 0xaf, 0x71, + /*9340:*/ 0x5e, 0xe1, 0x3a, 0x70, 0x9a, 0x67, 0x9d, 0x7e, 0x26, 0xb9, 0x0f, 0x81, 0x2f, 0x53, 0x4b, 0x8b, + /*9350:*/ 0xf8, 0x64, 0x5f, 0x1e, 0xfe, 0xef, 0xf8, 0x31, 0xbc, 0x43, 0x1e, 0xf7, 0x38, 0x82, 0x8d, 0xb9, + /*9360:*/ 0x30, 0x99, 0xc8, 0x13, 0xb0, 0xde, 0x00, 0x93, 0xe3, 0x0b, 0xb9, 0x12, 0x92, 0x9f, 0xb3, 0x8e, + /*9370:*/ 0xd6, 0xda, 0xfa, 0x7b, 0x13, 0xb4, 0xcc, 0x9e, 0x8a, 0x65, 0xb0, 0x4e, 0x07, 0xda, 0xa6, 0x6d, + /*9380:*/ 0x29, 0xae, 0xf2, 0xbc, 0xd9, 0xde, 0xfc, 0x45, 0x20, 0x25, 0x2f, 0x21, 0x5c, 0x74, 0x95, 0x6b, + /*9390:*/ 0x9c, 0xa4, 0xa3, 0x06, 0xf8, 0x83, 0x09, 0x9f, 0x4c, 0xcc, 0x7b, 0xdb, 0xd7, 0x08, 0xd7, 0x79, + /*93a0:*/ 0x3e, 0x57, 0xef, 0xdb, 0x4d, 0xc6, 0x4b, 0x3e, 0xdd, 0xb4, 0x2a, 0xd2, 0x61, 0x72, 0x82, 0xff, + /*93b0:*/ 0x29, 0xf5, 0x8d, 0xbe, 0x68, 0xd2, 0x14, 0x53, 0x29, 0x15, 0x03, 0xfd, 0x04, 0x14, 0x24, 0x6a, + /*93c0:*/ 0x2d, 0xe4, 0x26, 0x4a, 0xba, 0x1a, 0xf9, 0x09, 0x8c, 0x48, 0x34, 0xc4, 0x86, 0xcc, 0xb3, 0x80, + /*93d0:*/ 0x14, 0x9e, 0xd4, 0xd0, 0x9f, 0xac, 0xdb, 0xc1, 0xfa, 0x25, 0xb2, 0x09, 0x9e, 0x69, 0xa5, 0x2c, + /*93e0:*/ 0x13, 0x6c, 0xec, 0x2e, 0x2d, 0xfa, 0xe6, 0x3b, 0xa0, 0x03, 0xeb, 0x79, 0xf3, 0x62, 0x81, 0xd1, + /*93f0:*/ 0x72, 0x11, 0xd0, 0xaa, 0xd3, 0xf0, 0x6b, 0xb4, 0xc7, 0x88, 0xa6, 0x0f, 0x50, 0x92, 0x55, 0x59, + /*9400:*/ 0x85, 0xe2, 0xf8, 0x6a, 0x32, 0xa9, 0xa6, 0xde, 0xdd, 0x2e, 0x0e, 0x3d, 0xbc, 0x66, 0x70, 0xfc, + /*9410:*/ 0x79, 0xdb, 0xc7, 0x01, 0x86, 0xdb, 0xb5, 0xd3, 0x28, 0xf2, 0xbd, 0x01, 0xe5, 0x6e, 0x47, 0xef, + /*9420:*/ 0x96, 0x22, 0x86, 0x63, 0x7b, 0xa3, 0x8a, 0xa0, 0x54, 0x2c, 0x4f, 0x22, 0xd0, 0x1a, 0xb4, 0x76, + /*9430:*/ 0xca, 0x51, 0x0b, 0x59, 0x86, 0x73, 0xf9, 0x29, 0xa1, 0xc0, 0xcc, 0xe9, 0xbd, 0x50, 0x4b, 0xfd, + /*9440:*/ 0x3b, 0x57, 0xae, 0x82, 0xc1, 0xcc, 0x6d, 0xbc, 0xd6, 0x5f, 0x18, 0x30, 0xd9, 0xb8, 0x29, 0x1f, + /*9450:*/ 0x33, 0x7e, 0x73, 0xf2, 0x14, 0xb2, 0xce, 0x04, 0x0d, 0x53, 0x5b, 0x0d, 0x8c, 0x0f, 0x79, 0xe2, + /*9460:*/ 0x95, 0x96, 0xf9, 0x78, 0xc5, 0x48, 0x05, 0xc1, 0xd4, 0x3c, 0x69, 0x80, 0x24, 0x11, 0x3e, 0xdb, + /*9470:*/ 0x14, 0x91, 0x2f, 0xc8, 0xcc, 0x76, 0xd3, 0x8b, 0x31, 0x49, 0x6d, 0x4a, 0xbc, 0x8e, 0xe7, 0x35, + /*9480:*/ 0xe2, 0xf2, 0x6d, 0x13, 0x23, 0xa0, 0x7a, 0xa7, 0x65, 0x19, 0x4b, 0xee, 0xe5, 0xc3, 0xdc, 0xce, + /*9490:*/ 0x91, 0x51, 0x2c, 0x1c, 0x52, 0xcd, 0x10, 0x2c, 0xc0, 0x13, 0x00, 0x98, 0xbb, 0xa4, 0x8b, 0xad, + /*94a0:*/ 0x56, 0x76, 0x2a, 0xc4, 0xeb, 0xef, 0xa4, 0x8e, 0xf1, 0x12, 0x01, 0x6a, 0xd6, 0xb8, 0x3d, 0xfc, + /*94b0:*/ 0x03, 0x78, 0x75, 0xef, 0x67, 0xe6, 0xeb, 0xf2, 0xf9, 0xb8, 0x80, 0xfe, 0x7c, 0xac, 0x30, 0xb3, + /*94c0:*/ 0x90, 0xc6, 0x6b, 0xd8, 0xf9, 0xad, 0x80, 0x93, 0x6e, 0x88, 0x62, 0xb7, 0xf7, 0xe8, 0x01, 0x3a, + /*94d0:*/ 0x6f, 0x97, 0x7b, 0x0a, 0x20, 0x95, 0x5e, 0x1f, 0xdd, 0x71, 0x59, 0xd4, 0x51, 0x14, 0xe4, 0xa6, + /*94e0:*/ 0xf3, 0x01, 0x9f, 0x7f, 0x57, 0x59, 0x85, 0xf0, 0x72, 0x17, 0xa7, 0xc0, 0x4c, 0x15, 0x15, 0x7e, + /*94f0:*/ 0xd3, 0xbb, 0xc8, 0xc2, 0x31, 0x3c, 0x2a, 0x10, 0x89, 0xf7, 0xa2, 0x22, 0x81, 0x45, 0xa0, 0xdd, + /*9500:*/ 0xd2, 0x4e, 0x50, 0xc1, 0x4e, 0xdf, 0xc0, 0x2e, 0x54, 0x14, 0x07, 0x99, 0x03, 0x37, 0x6c, 0x8f, + /*9510:*/ 0x43, 0x86, 0x08, 0xbe, 0x29, 0xfa, 0x91, 0xdc, 0x00, 0x65, 0x04, 0xa6, 0xc0, 0x20, 0x47, 0x1a, + /*9520:*/ 0x0d, 0x08, 0x91, 0x87, 0x14, 0x90, 0xe4, 0x92, 0xed, 0x79, 0x1b, 0xed, 0x98, 0xca, 0xfc, 0x57, + /*9530:*/ 0x81, 0xf1, 0x2c, 0xda, 0xc7, 0x02, 0xde, 0xf3, 0xd4, 0xda, 0xd2, 0x88, 0x3d, 0x8e, 0x47, 0xaa, + /*9540:*/ 0x50, 0x59, 0x14, 0xf8, 0x41, 0x37, 0xfb, 0x57, 0x47, 0xf3, 0x51, 0xb4, 0x80, 0x5a, 0x24, 0xbb, + /*9550:*/ 0x66, 0xe7, 0x06, 0x32, 0x2d, 0x86, 0x1b, 0x8c, 0x88, 0x39, 0x0a, 0x87, 0x26, 0xee, 0xda, 0x54, + /*9560:*/ 0x8c, 0x0a, 0x8b, 0x3d, 0x2b, 0x26, 0x72, 0x46, 0xe0, 0xdc, 0x8e, 0xd4, 0xb7, 0x10, 0x8d, 0x3c, + /*9570:*/ 0x37, 0x53, 0xd4, 0x11, 0xd6, 0x3e, 0x62, 0xc9, 0x55, 0xc3, 0xdd, 0x28, 0x6d, 0xb9, 0x65, 0x0c, + /*9580:*/ 0xa5, 0x3f, 0xdb, 0xfd, 0xf9, 0x5f, 0x72, 0xf7, 0xeb, 0xd6, 0x2c, 0xdc, 0xc6, 0xa1, 0x3d, 0xd9, + /*9590:*/ 0x35, 0x01, 0xff, 0xe6, 0x8b, 0x7d, 0x4f, 0x38, 0x9a, 0x34, 0xd0, 0x12, 0xdf, 0xbd, 0x98, 0xc3, + /*95a0:*/ 0x91, 0xd5, 0xc6, 0x81, 0x09, 0xf4, 0x62, 0x6a, 0x0c, 0x5f, 0x40, 0xcc, 0x5e, 0xe3, 0x06, 0x38, + /*95b0:*/ 0xc1, 0xfe, 0xf7, 0xac, 0x7e, 0x82, 0xc2, 0x87, 0x56, 0x4b, 0x2a, 0x10, 0x70, 0xc2, 0x2c, 0x9c, + /*95c0:*/ 0x7f, 0x55, 0x5e, 0x58, 0x54, 0xc8, 0x38, 0x2c, 0x02, 0xbd, 0xe2, 0x2d, 0xb9, 0x47, 0x64, 0xe5, + /*95d0:*/ 0x0a, 0x3e, 0xb4, 0xc4, 0x85, 0x2d, 0x22, 0xd3, 0x2f, 0x58, 0xdd, 0xca, 0x40, 0x8a, 0x8f, 0x46, + /*95e0:*/ 0x32, 0x9f, 0x2b, 0x87, 0x6f, 0x90, 0x19, 0xcf, 0x4e, 0x7a, 0x6d, 0x45, 0xc5, 0x3d, 0x12, 0x3e, + /*95f0:*/ 0x82, 0x23, 0x6a, 0x69, 0x21, 0x29, 0x94, 0x1c, 0x8b, 0x95, 0xbd, 0x06, 0x24, 0xb1, 0xbc, 0x12, + /*9600:*/ 0x6a, 0x25, 0xd5, 0x56, 0xbf, 0xb6, 0xde, 0x8d, 0xc9, 0xa9, 0x88, 0x8d, 0x93, 0xe8, 0x55, 0x7a, + /*9610:*/ 0x5c, 0xe5, 0xae, 0x4b, 0xa0, 0xfc, 0xbe, 0xea, 0x6d, 0x89, 0xa6, 0x02, 0xfa, 0x73, 0xa4, 0x77, + /*9620:*/ 0x90, 0x5a, 0x1b, 0x0c, 0x7e, 0x2f, 0xa6, 0xad, 0x96, 0x9d, 0x3e, 0x59, 0x27, 0x4b, 0x72, 0x2d, + /*9630:*/ 0xd3, 0xb3, 0x01, 0x6d, 0x07, 0x31, 0xe4, 0x52, 0x43, 0xe0, 0x95, 0x46, 0x0e, 0x15, 0x1b, 0x24, + /*9640:*/ 0xb0, 0x4c, 0xc9, 0x93, 0xeb, 0x19, 0xb1, 0xf7, 0xe1, 0x7f, 0x90, 0xaa, 0x46, 0x39, 0xd7, 0x87, + /*9650:*/ 0xc8, 0xc0, 0xb4, 0x55, 0x6f, 0x7b, 0xff, 0x49, 0xa4, 0xca, 0x8c, 0xe2, 0x87, 0x03, 0x56, 0x4e, + /*9660:*/ 0x21, 0x17, 0xbb, 0x15, 0xec, 0x10, 0x87, 0x15, 0xe3, 0x94, 0x75, 0x1a, 0x28, 0x44, 0x8f, 0xeb, + /*9670:*/ 0xfb, 0x27, 0x43, 0xdf, 0x1a, 0xcd, 0x79, 0x6b, 0x3e, 0x92, 0x09, 0xc5, 0xd5, 0x32, 0x30, 0x91, + /*9680:*/ 0xb5, 0x53, 0x1b, 0xfb, 0x4a, 0x1d, 0x57, 0x9b, 0x66, 0x68, 0x69, 0x6f, 0xca, 0x7f, 0xe0, 0xb1, + /*9690:*/ 0x20, 0xdf, 0x9e, 0xb2, 0x14, 0xaa, 0xdc, 0x0a, 0xab, 0x55, 0x25, 0xeb, 0xd7, 0xcc, 0x82, 0x9f, + /*96a0:*/ 0xfe, 0xbd, 0x49, 0x89, 0x82, 0xb9, 0xc0, 0x97, 0xf6, 0x36, 0x87, 0x25, 0x09, 0xf7, 0xd8, 0xa0, + /*96b0:*/ 0xb5, 0x47, 0x3b, 0x7c, 0x7d, 0x7a, 0xbe, 0xed, 0x13, 0x7f, 0xb0, 0x86, 0xd8, 0x9c, 0x52, 0x4b, + /*96c0:*/ 0xa6, 0xad, 0x90, 0x16, 0x28, 0xbe, 0x75, 0x6f, 0x41, 0xdc, 0x0f, 0x71, 0x00, 0xcd, 0xae, 0x1d, + /*96d0:*/ 0x56, 0x8d, 0x7a, 0xc5, 0xec, 0xe3, 0xef, 0x55, 0x97, 0x6f, 0x8e, 0x55, 0xc3, 0xdc, 0x97, 0x5a, + /*96e0:*/ 0x86, 0x91, 0x38, 0xda, 0xc9, 0x1c, 0x98, 0x62, 0xe1, 0xc9, 0x45, 0x26, 0x2d, 0x19, 0xcd, 0x83, + /*96f0:*/ 0x81, 0x25, 0x2f, 0x93, 0xa2, 0x34, 0x74, 0x01, 0x96, 0x30, 0x18, 0xc3, 0xa7, 0xd9, 0xd7, 0x5b, + /*9700:*/ 0xcf, 0x33, 0x35, 0x0b, 0xfa, 0xdd, 0x4a, 0x14, 0xdb, 0x05, 0xf4, 0x34, 0xde, 0xa8, 0xeb, 0xaa, + /*9710:*/ 0x35, 0x82, 0xf6, 0x47, 0x28, 0x84, 0x56, 0x8f, 0xbe, 0xf7, 0xc8, 0xaa, 0xdd, 0x39, 0x9b, 0x40, + /*9720:*/ 0xe9, 0x80, 0x16, 0xe6, 0x1e, 0x3a, 0xfb, 0x82, 0x62, 0x73, 0x05, 0x92, 0x13, 0x1d, 0x46, 0x29, + /*9730:*/ 0x04, 0xcf, 0xc3, 0x8b, 0xb3, 0xb4, 0x95, 0x66, 0xcd, 0x07, 0x10, 0x18, 0x03, 0x19, 0xb7, 0x3f, + /*9740:*/ 0x43, 0x30, 0x87, 0xd8, 0x37, 0x1d, 0x57, 0x4d, 0x9d, 0x94, 0x5f, 0xe7, 0xf9, 0xa3, 0xa3, 0xe9, + /*9750:*/ 0xa4, 0x23, 0x3d, 0x53, 0xe2, 0xe0, 0xd9, 0x12, 0xbb, 0x38, 0xc1, 0xe9, 0xbb, 0x44, 0xdf, 0x87, + /*9760:*/ 0x2c, 0x8f, 0x38, 0x34, 0x9e, 0xd5, 0xcc, 0x1f, 0x24, 0x42, 0x1e, 0xa6, 0xf3, 0x2f, 0xd0, 0xc2, + /*9770:*/ 0xf4, 0x11, 0x5f, 0xa6, 0x10, 0x78, 0xc4, 0x78, 0x3a, 0xad, 0x14, 0xf5, 0x1b, 0xb2, 0x19, 0x20, + /*9780:*/ 0x8b, 0xbd, 0x38, 0xe4, 0x8d, 0x62, 0x00, 0xe9, 0x34, 0xab, 0x3d, 0x43, 0x75, 0x5d, 0xa7, 0xc6, + /*9790:*/ 0x0f, 0x2b, 0x30, 0x0e, 0xd7, 0x9b, 0x94, 0x9e, 0x84, 0xc7, 0xe1, 0x83, 0x24, 0x3c, 0xaa, 0x0f, + /*97a0:*/ 0x60, 0x22, 0x6d, 0x12, 0xd7, 0xec, 0x95, 0x82, 0xff, 0xa7, 0x87, 0xef, 0xf4, 0x7c, 0xd7, 0x13, + /*97b0:*/ 0x3f, 0x5f, 0x59, 0xc1, 0x73, 0x4a, 0x8f, 0x34, 0x2e, 0x25, 0xa0, 0xb5, 0xea, 0xd0, 0x0e, 0x46, + /*97c0:*/ 0xba, 0x74, 0x40, 0x2f, 0xab, 0x21, 0xc8, 0x3e, 0x05, 0x41, 0xe8, 0x6b, 0x2c, 0x6f, 0x85, 0x3c, + /*97d0:*/ 0xbb, 0x8f, 0xa3, 0x58, 0x86, 0x9d, 0x7b, 0xfc, 0x21, 0xe6, 0x7b, 0x7e, 0xad, 0xe3, 0x16, 0x68, + /*97e0:*/ 0x06, 0xad, 0x90, 0xc4, 0x31, 0xaf, 0xcd, 0x25, 0xaf, 0x79, 0x22, 0x0a, 0xb8, 0xc8, 0x07, 0xa1, + /*97f0:*/ 0x84, 0xbc, 0x99, 0x79, 0x99, 0x64, 0xd4, 0x26, 0xec, 0x5c, 0x0e, 0x3d, 0xa3, 0xd9, 0x08, 0xd5, + /*9800:*/ 0x30, 0xa2, 0xb5, 0x6d, 0x52, 0x5f, 0x4a, 0x3b, 0xc3, 0x2f, 0x20, 0xcf, 0x28, 0xfc, 0xd4, 0x1c, + /*9810:*/ 0xfa, 0xc0, 0x18, 0xa3, 0x44, 0x4a, 0xaf, 0xa5, 0xaa, 0x52, 0xe8, 0xee, 0x84, 0x9b, 0x28, 0xf7, + /*9820:*/ 0xc1, 0x48, 0x69, 0xaa, 0xe6, 0x16, 0xf0, 0xf8, 0x9d, 0x02, 0x09, 0xf0, 0xad, 0xa3, 0x51, 0x2a, + /*9830:*/ 0x15, 0x1a, 0x4e, 0xcf, 0x96, 0x33, 0xeb, 0x66, 0x10, 0x58, 0xc0, 0x17, 0xe9, 0x57, 0x6e, 0xbc, + /*9840:*/ 0xe1, 0x2a, 0xd9, 0x78, 0x55, 0xd8, 0xef, 0x29, 0x70, 0xa6, 0xdc, 0x12, 0x89, 0xce, 0xfd, 0x7a, + /*9850:*/ 0x14, 0xe6, 0x0e, 0x03, 0xc9, 0xb3, 0x21, 0x8b, 0xfd, 0x01, 0xfa, 0x12, 0x34, 0x9b, 0x47, 0x23, + /*9860:*/ 0x3c, 0x3a, 0x70, 0x72, 0x70, 0x45, 0xf0, 0xa2, 0x04, 0xf9, 0xe6, 0x3f, 0x22, 0xf6, 0x41, 0x71, + /*9870:*/ 0x10, 0xe1, 0x44, 0x5d, 0xd7, 0x03, 0xa9, 0x07, 0x34, 0x5e, 0x50, 0xb9, 0x1b, 0x77, 0x18, 0x05, + /*9880:*/ 0x90, 0x8d, 0xfe, 0x48, 0x63, 0xe8, 0xbd, 0xe1, 0x59, 0xa9, 0x6b, 0xe2, 0xb9, 0xdf, 0x28, 0x1b, + /*9890:*/ 0xe9, 0x74, 0x48, 0x42, 0xed, 0x66, 0xc4, 0xf6, 0xaf, 0x72, 0xf7, 0x8a, 0x14, 0xf4, 0xb1, 0x3a, + /*98a0:*/ 0x9d, 0x10, 0xb9, 0x37, 0xe6, 0x53, 0xe3, 0x08, 0x0d, 0xf4, 0x43, 0x02, 0x07, 0x18, 0x9c, 0x42, + /*98b0:*/ 0xdb, 0xa9, 0x34, 0xfa, 0x14, 0x63, 0xfd, 0xb5, 0x0d, 0x93, 0xc3, 0x20, 0x5d, 0xc4, 0x05, 0xb1, + /*98c0:*/ 0x35, 0x37, 0xa0, 0x7a, 0x2f, 0xa3, 0x0f, 0xf9, 0xa0, 0x1e, 0x96, 0x79, 0xe1, 0x6a, 0xf0, 0xec, + /*98d0:*/ 0x73, 0x20, 0xa5, 0x76, 0xd6, 0xe8, 0x0e, 0x63, 0xe9, 0x0c, 0x6b, 0xf7, 0x61, 0x92, 0xee, 0xf3, + /*98e0:*/ 0x94, 0x53, 0xbd, 0x4e, 0x9c, 0xc9, 0xd4, 0x30, 0x07, 0x6f, 0xcf, 0xf8, 0x14, 0xf7, 0xfc, 0xdd, + /*98f0:*/ 0x3d, 0x77, 0x0c, 0x49, 0xc2, 0x90, 0xa2, 0xfa, 0x04, 0x3a, 0x63, 0xeb, 0x94, 0xc0, 0x2c, 0xfa, + /*9900:*/ 0x7c, 0x86, 0x94, 0x0f, 0x47, 0x38, 0x7d, 0xee, 0x5c, 0xa7, 0xa4, 0x6c, 0x7c, 0x12, 0xaa, 0x45, + /*9910:*/ 0xfb, 0xd0, 0x5d, 0xa9, 0xb5, 0x92, 0xef, 0x89, 0x61, 0x0b, 0xf2, 0xf4, 0xeb, 0x42, 0x96, 0x34, + /*9920:*/ 0x14, 0xa8, 0xed, 0x8e, 0x41, 0x87, 0x72, 0xd0, 0x13, 0x7b, 0x7d, 0x76, 0x1e, 0x5b, 0xb2, 0xee, + /*9930:*/ 0xbc, 0x84, 0xc0, 0xbd, 0xb1, 0x6a, 0x67, 0x08, 0xee, 0x0b, 0x0e, 0xf8, 0x27, 0x61, 0xff, 0x81, + /*9940:*/ 0xc0, 0xc2, 0xa1, 0x32, 0xfb, 0x00, 0x32, 0x62, 0x58, 0xc6, 0x8c, 0xe3, 0x25, 0x28, 0x91, 0x32, + /*9950:*/ 0x56, 0xba, 0x80, 0x5e, 0x91, 0xeb, 0x2b, 0x77, 0x3e, 0x80, 0x91, 0x40, 0x0d, 0x05, 0x92, 0xf6, + /*9960:*/ 0x9a, 0xf4, 0x7b, 0x03, 0x24, 0xdd, 0x02, 0xf0, 0x33, 0x82, 0x6f, 0xc8, 0x6d, 0x35, 0xe8, 0xd3, + /*9970:*/ 0xe6, 0x1e, 0x16, 0x5b, 0x97, 0x32, 0xea, 0xa2, 0xf4, 0xfb, 0x87, 0xff, 0x17, 0x96, 0xa5, 0xe0, + /*9980:*/ 0xfe, 0xdd, 0x12, 0xcc, 0x01, 0xd5, 0xb2, 0x00, 0xcd, 0x17, 0xc3, 0x05, 0x2e, 0x3b, 0x83, 0x7f, + /*9990:*/ 0x38, 0xe2, 0xfc, 0xf7, 0xa4, 0x14, 0xd9, 0x24, 0x44, 0xbd, 0x7f, 0x58, 0xfb, 0xbd, 0x5d, 0x55, + /*99a0:*/ 0xc6, 0x58, 0x09, 0x2d, 0x37, 0x84, 0x8f, 0x16, 0x3f, 0xa6, 0xac, 0x43, 0x36, 0xda, 0x5e, 0x61, + /*99b0:*/ 0x81, 0x0c, 0xeb, 0xa9, 0x5f, 0xb1, 0xee, 0xd6, 0xee, 0x11, 0xaf, 0x05, 0x76, 0x76, 0x4d, 0xa9, + /*99c0:*/ 0xd1, 0xd5, 0x5e, 0x15, 0x35, 0xc1, 0x08, 0x01, 0x51, 0x0d, 0xbe, 0x00, 0x04, 0xb9, 0xf0, 0xc3, + /*99d0:*/ 0x1f, 0xc2, 0xeb, 0x76, 0xb3, 0xa6, 0xca, 0xd0, 0x41, 0xc5, 0x75, 0x48, 0x75, 0x5b, 0x68, 0x9e, + /*99e0:*/ 0x84, 0xe7, 0xda, 0xe2, 0x03, 0x0b, 0xf5, 0x86, 0x22, 0x4d, 0x1e, 0x92, 0xd8, 0xc4, 0x1a, 0x9b, + /*99f0:*/ 0x3e, 0x1c, 0x5d, 0x53, 0x39, 0xeb, 0xb3, 0xd5, 0x84, 0x93, 0x17, 0xe2, 0x2e, 0x0a, 0xed, 0xb0, + /*9a00:*/ 0x6e, 0xb7, 0x27, 0x0b, 0x85, 0x5d, 0x8f, 0x0b, 0x5a, 0x52, 0x25, 0xc5, 0x11, 0xa0, 0xd9, 0xe8, + /*9a10:*/ 0xd5, 0x02, 0x07, 0x27, 0x21, 0x80, 0x3c, 0xd0, 0x43, 0x9c, 0x32, 0xd4, 0x95, 0xa0, 0xca, 0x0e, + /*9a20:*/ 0x25, 0x72, 0x08, 0x38, 0x86, 0x25, 0xf5, 0x18, 0x3b, 0x7d, 0x13, 0x19, 0x3f, 0xed, 0xc3, 0x6f, + /*9a30:*/ 0x54, 0x03, 0x64, 0xf1, 0x2a, 0x69, 0x9f, 0x58, 0x5f, 0x68, 0xdf, 0x39, 0x6b, 0x2c, 0xb5, 0x39, + /*9a40:*/ 0xeb, 0x49, 0x37, 0xbb, 0x1a, 0xc1, 0x3b, 0xb0, 0x71, 0xa4, 0x1d, 0x17, 0xfd, 0x23, 0xba, 0x5c, + /*9a50:*/ 0xde, 0x7a, 0x9e, 0x57, 0x8e, 0x6d, 0x1c, 0x4e, 0x41, 0xe4, 0xa2, 0xd4, 0xee, 0xbf, 0x9c, 0x8c, + /*9a60:*/ 0x66, 0x76, 0xf8, 0x62, 0x21, 0xae, 0xad, 0x3e, 0x2a, 0x64, 0xcf, 0xa1, 0x32, 0x69, 0xe4, 0xb3, + /*9a70:*/ 0xe3, 0xff, 0xf7, 0xd7, 0x85, 0x5f, 0xd8, 0x9c, 0xe9, 0xe7, 0x5b, 0xc1, 0xd2, 0x2e, 0xbb, 0xc9, + /*9a80:*/ 0xeb, 0xbf, 0x81, 0x51, 0x14, 0x6c, 0xf6, 0x23, 0x4e, 0xed, 0x68, 0x29, 0xb6, 0x90, 0x05, 0x24, + /*9a90:*/ 0x98, 0x53, 0xf3, 0x2a, 0x09, 0x88, 0xb5, 0xe1, 0x19, 0xc5, 0xac, 0x15, 0xb3, 0x12, 0x78, 0x25, + /*9aa0:*/ 0xb6, 0x09, 0xc7, 0x50, 0x39, 0x61, 0xee, 0x82, 0x85, 0x59, 0x7f, 0x10, 0x4f, 0xb7, 0x4c, 0xa6, + /*9ab0:*/ 0xb2, 0xce, 0x19, 0x5e, 0x3b, 0x94, 0xd2, 0x1f, 0x3b, 0xa2, 0xd6, 0x06, 0xe8, 0x04, 0xeb, 0x10, + /*9ac0:*/ 0xaa, 0x1b, 0x92, 0x0b, 0x98, 0x20, 0x7c, 0x02, 0x40, 0x2a, 0x9e, 0xbd, 0xeb, 0x73, 0x27, 0x6b, + /*9ad0:*/ 0x6d, 0xc5, 0x3e, 0x99, 0x06, 0x82, 0x22, 0xe6, 0xb8, 0x54, 0x88, 0x03, 0x7f, 0xf9, 0x8c, 0xda, + /*9ae0:*/ 0xc4, 0xfe, 0xd7, 0x94, 0x52, 0xca, 0x5a, 0x73, 0xba, 0x76, 0xb7, 0x90, 0x82, 0xaf, 0xb1, 0x02, + /*9af0:*/ 0xc4, 0x11, 0x84, 0x19, 0x65, 0xf3, 0x6c, 0x2d, 0x57, 0x11, 0x9e, 0xa5, 0x39, 0x74, 0xcd, 0x98, + /*9b00:*/ 0x6b, 0x89, 0x7c, 0x59, 0xea, 0x89, 0x41, 0x51, 0xbb, 0xd1, 0xc5, 0x01, 0xa0, 0xad, 0x35, 0xcd, + /*9b10:*/ 0x0a, 0x05, 0x28, 0xa1, 0x02, 0xb0, 0xf5, 0xf3, 0xd6, 0xb4, 0x8b, 0x05, 0xd5, 0x72, 0xa7, 0x9a, + /*9b20:*/ 0xb6, 0x13, 0xc6, 0xa0, 0xd4, 0x73, 0xa0, 0xd1, 0x15, 0x53, 0x2b, 0xb0, 0x43, 0x75, 0xfb, 0xb5, + /*9b30:*/ 0x81, 0x85, 0x30, 0xd0, 0xd4, 0x8c, 0x84, 0xea, 0x89, 0xb1, 0x9f, 0x9c, 0xc7, 0x5a, 0x56, 0x88, + /*9b40:*/ 0xa1, 0x74, 0xb3, 0x41, 0xdb, 0x6e, 0x7b, 0x02, 0x16, 0x6c, 0xbc, 0x95, 0x21, 0x5d, 0x83, 0x62, + /*9b50:*/ 0x56, 0x4c, 0xd5, 0x2a, 0xd3, 0xe3, 0xa0, 0xad, 0x49, 0x95, 0x12, 0x84, 0x81, 0xcd, 0xc1, 0x49, + /*9b60:*/ 0xcd, 0xc8, 0x77, 0x75, 0x67, 0x80, 0x3e, 0x83, 0x92, 0x4a, 0xe9, 0xa1, 0xa6, 0xe5, 0xa5, 0x7c, + /*9b70:*/ 0xf4, 0x33, 0x63, 0x69, 0x91, 0x08, 0x12, 0xfa, 0xe0, 0x8e, 0x4f, 0xaf, 0xfb, 0x24, 0x96, 0xcd, + /*9b80:*/ 0xf8, 0xb9, 0xa7, 0xbb, 0xc1, 0x59, 0xe8, 0x6f, 0xbc, 0xee, 0x25, 0x3f, 0xa0, 0x52, 0x92, 0x3e, + /*9b90:*/ 0xf3, 0x4b, 0xc3, 0x11, 0xa4, 0x94, 0x40, 0x24, 0x47, 0x9e, 0x71, 0xc5, 0x76, 0x57, 0xf1, 0xef, + /*9ba0:*/ 0x11, 0x53, 0x1a, 0x7f, 0x39, 0x23, 0x36, 0x13, 0x06, 0xe2, 0x20, 0x9e, 0x3b, 0x6d, 0x85, 0xef, + /*9bb0:*/ 0x80, 0x42, 0xaa, 0x08, 0x51, 0x91, 0x0c, 0xad, 0x68, 0xbe, 0xb8, 0xe2, 0x5f, 0xb1, 0xbb, 0xc8, + /*9bc0:*/ 0x0a, 0x32, 0x10, 0xbb, 0xb3, 0x07, 0x1c, 0x50, 0x4d, 0xca, 0x26, 0xf4, 0x5a, 0x20, 0x99, 0x95, + /*9bd0:*/ 0xe5, 0x2c, 0xbb, 0x80, 0x59, 0xef, 0x7d, 0x0c, 0x46, 0x4c, 0xa3, 0xcf, 0xc6, 0x9e, 0x6a, 0x0a, + /*9be0:*/ 0xa3, 0x17, 0x40, 0x77, 0x0e, 0xf6, 0x19, 0x93, 0x9a, 0x06, 0xc9, 0x3c, 0xc5, 0xcb, 0x33, 0x6e, + /*9bf0:*/ 0xb3, 0xfa, 0xeb, 0xbf, 0x63, 0x16, 0xad, 0x55, 0x79, 0xee, 0x5b, 0x15, 0x4e, 0xe1, 0x65, 0xa9, + /*9c00:*/ 0x69, 0x00, 0x7a, 0x99, 0xbf, 0x32, 0x32, 0x24, 0x66, 0xc0, 0xf0, 0x63, 0x3c, 0x94, 0xdf, 0xb2, + /*9c10:*/ 0x4b, 0xc8, 0x9a, 0xdd, 0xac, 0x0b, 0x6a, 0x20, 0x9e, 0xb9, 0x88, 0x9e, 0x60, 0x51, 0x04, 0xbc, + /*9c20:*/ 0x87, 0xd2, 0x9f, 0x53, 0x8d, 0x3f, 0x47, 0x5d, 0x17, 0xe0, 0xf8, 0xe1, 0x5f, 0xa9, 0x5a, 0xc3, + /*9c30:*/ 0xdf, 0xfc, 0x7f, 0xbe, 0x9c, 0x0d, 0x56, 0xe6, 0x7f, 0xe3, 0xf4, 0xfb, 0x5b, 0x4c, 0xd8, 0x3f, + /*9c40:*/ 0xc5, 0xc7, 0x7d, 0xc5, 0xa4, 0x74, 0x20, 0xe7, 0xb8, 0x35, 0x3d, 0xd0, 0xfe, 0x97, 0xb3, 0x7c, + /*9c50:*/ 0x5b, 0xba, 0x6f, 0x58, 0x1c, 0x47, 0xc8, 0xb7, 0x16, 0xf4, 0xa5, 0xb3, 0xb1, 0x51, 0x8a, 0x7d, + /*9c60:*/ 0x31, 0x9c, 0x20, 0x0e, 0x5a, 0x9d, 0x70, 0xea, 0xe2, 0x55, 0xe5, 0x0e, 0xe3, 0x0c, 0x62, 0x5b, + /*9c70:*/ 0xf3, 0xd3, 0x48, 0xfc, 0x20, 0xc0, 0x75, 0x6e, 0x16, 0xe8, 0xe8, 0xce, 0xf0, 0x1d, 0x4c, 0xdc, + /*9c80:*/ 0x82, 0xe0, 0x22, 0x34, 0xf6, 0x0a, 0x8b, 0xe5, 0x0c, 0x44, 0xc0, 0x8d, 0x77, 0xd9, 0xf3, 0x68, + /*9c90:*/ 0x04, 0xe2, 0xd1, 0x10, 0x0a, 0xbd, 0x34, 0xac, 0xcb, 0x0b, 0xcf, 0xab, 0xb7, 0x30, 0x73, 0x53, + /*9ca0:*/ 0x3a, 0xc2, 0x37, 0x21, 0x48, 0x8e, 0xf9, 0xa6, 0x4b, 0x85, 0xe4, 0x6c, 0xf3, 0x58, 0x71, 0xdb, + /*9cb0:*/ 0xe9, 0x4f, 0xc4, 0x80, 0xe1, 0xad, 0x5d, 0xe5, 0x82, 0xc9, 0x6f, 0xa6, 0xc7, 0xaf, 0x7d, 0x58, + /*9cc0:*/ 0xbc, 0xaa, 0x21, 0x43, 0x7f, 0xe5, 0x4c, 0x2e, 0x51, 0x52, 0xfe, 0xdd, 0x4f, 0xe0, 0xd7, 0xce, + /*9cd0:*/ 0x1e, 0x20, 0xcd, 0x24, 0x7d, 0xf8, 0xa2, 0x34, 0x80, 0xf0, 0x00, 0xef, 0x43, 0x97, 0xd6, 0xb6, + /*9ce0:*/ 0xd5, 0x4d, 0x14, 0xd3, 0x2f, 0x77, 0x74, 0xbb, 0xa4, 0x51, 0x72, 0x2b, 0x5d, 0x9c, 0xe2, 0x61, + /*9cf0:*/ 0xe8, 0xac, 0xf0, 0x96, 0x45, 0x92, 0xab, 0x9d, 0x6c, 0x86, 0xb6, 0x0d, 0x43, 0xdb, 0xe4, 0x86, + /*9d00:*/ 0x87, 0xe4, 0xc5, 0xd2, 0x92, 0x3c, 0x7e, 0x63, 0x2a, 0x07, 0x00, 0xf8, 0xfb, 0x9a, 0x99, 0x32, + /*9d10:*/ 0xe8, 0xf9, 0xb1, 0x88, 0x56, 0xb5, 0x7f, 0xcf, 0x6c, 0xe8, 0x63, 0xeb, 0x67, 0x4a, 0x53, 0xb1, + /*9d20:*/ 0x5f, 0x79, 0x73, 0x9e, 0xfa, 0xd3, 0x59, 0x00, 0xb6, 0xf6, 0x70, 0x20, 0x2d, 0x1b, 0x8e, 0x71, + /*9d30:*/ 0xea, 0xf0, 0x11, 0x2f, 0x12, 0xf3, 0xd2, 0x16, 0x51, 0xcd, 0x75, 0x70, 0x82, 0x06, 0x82, 0xa6, + /*9d40:*/ 0x03, 0x84, 0xc6, 0x5d, 0x54, 0xf5, 0xbe, 0xcd, 0x9e, 0x23, 0x69, 0xe2, 0x62, 0xfc, 0x86, 0x69, + /*9d50:*/ 0xb8, 0xfd, 0x6c, 0x67, 0x3a, 0x70, 0x74, 0xad, 0x0d, 0xce, 0xaa, 0x92, 0xd2, 0xc8, 0xfc, 0xeb, + /*9d60:*/ 0x32, 0xc7, 0x8f, 0x51, 0x7c, 0xf8, 0x94, 0x13, 0x49, 0xd2, 0xd0, 0x92, 0x47, 0x74, 0x65, 0x0f, + /*9d70:*/ 0x4d, 0xf2, 0x78, 0x30, 0x0c, 0xca, 0xe3, 0x12, 0x73, 0x46, 0x90, 0xac, 0xc1, 0x0b, 0x9e, 0xed, + /*9d80:*/ 0x2a, 0x32, 0xa0, 0x01, 0xdb, 0x4b, 0x80, 0x6d, 0xc3, 0x1b, 0x11, 0xad, 0x81, 0x84, 0xdd, 0x20, + /*9d90:*/ 0x21, 0x90, 0x7c, 0xda, 0x2d, 0x59, 0x89, 0x61, 0x66, 0x4d, 0x35, 0x8d, 0xcd, 0x59, 0xed, 0x6c, + /*9da0:*/ 0x2b, 0xde, 0xd1, 0x71, 0xf6, 0x62, 0x18, 0x6d, 0x2a, 0xfa, 0xcf, 0xd2, 0x78, 0x2e, 0x91, 0xed, + /*9db0:*/ 0xef, 0x42, 0xaf, 0x27, 0x5f, 0xe8, 0xc8, 0xd4, 0x49, 0xae, 0x29, 0xeb, 0x55, 0x53, 0x48, 0xdc, + /*9dc0:*/ 0x5d, 0xa0, 0xf9, 0x8a, 0x2b, 0x88, 0x65, 0x88, 0x94, 0x45, 0x38, 0xa9, 0xb4, 0xc4, 0xcf, 0x8e, + /*9dd0:*/ 0x56, 0x2a, 0x92, 0x76, 0x1e, 0x68, 0x50, 0x89, 0x7f, 0x99, 0x3b, 0xf1, 0x74, 0xdd, 0xf1, 0x0e, + /*9de0:*/ 0xb5, 0xd2, 0x0f, 0x80, 0x65, 0xe8, 0xe3, 0xc5, 0x66, 0x69, 0x75, 0xeb, 0x78, 0x2e, 0xc5, 0xbf, + /*9df0:*/ 0x35, 0xb9, 0x39, 0x0c, 0x7f, 0x81, 0x03, 0xbf, 0x14, 0xd1, 0x99, 0x4b, 0xd6, 0xaf, 0x44, 0x1e, + /*9e00:*/ 0x04, 0xe6, 0xd0, 0x26, 0x69, 0xe9, 0x35, 0xca, 0xe0, 0x39, 0xa6, 0x74, 0x2c, 0x5e, 0xe8, 0xeb, + /*9e10:*/ 0x53, 0x8e, 0xce, 0xc9, 0xd6, 0xa8, 0xe5, 0x78, 0x8a, 0xf8, 0xe1, 0x62, 0xe0, 0x71, 0xcf, 0xa2, + /*9e20:*/ 0x87, 0xf9, 0x51, 0x52, 0x94, 0x64, 0xde, 0xce, 0xa3, 0x09, 0x3c, 0x16, 0x7d, 0xce, 0xbb, 0xf9, + /*9e30:*/ 0x81, 0xb8, 0x86, 0xe3, 0x5f, 0xf9, 0x24, 0x8d, 0xfc, 0xbd, 0x5f, 0xd7, 0x15, 0x1a, 0x3e, 0x9f, + /*9e40:*/ 0x11, 0xab, 0xc4, 0xee, 0x23, 0x3b, 0x66, 0x66, 0xbb, 0x52, 0xfa, 0x75, 0x78, 0x37, 0x54, 0x71, + /*9e50:*/ 0x47, 0x4a, 0x9a, 0x8a, 0x7a, 0x7b, 0x1a, 0x18, 0x45, 0x4b, 0xf5, 0x91, 0x3a, 0xf1, 0x1a, 0x9f, + /*9e60:*/ 0x0e, 0x00, 0xc2, 0xa0, 0xc9, 0xfa, 0x95, 0x89, 0x8b, 0x59, 0x3b, 0x52, 0x16, 0xb8, 0x20, 0x89, + /*9e70:*/ 0xee, 0x83, 0xda, 0xda, 0x37, 0x5f, 0x8a, 0x7e, 0x9f, 0xbe, 0x7e, 0x20, 0xca, 0xb8, 0x52, 0xd4, + /*9e80:*/ 0x3d, 0x4d, 0xe2, 0x6e, 0xe9, 0x63, 0xfc, 0xaa, 0x74, 0xb2, 0x49, 0xac, 0x95, 0xd4, 0xb9, 0xf1, + /*9e90:*/ 0x97, 0xe7, 0xc8, 0x87, 0xab, 0xc5, 0xd2, 0x70, 0xe2, 0x8b, 0xe3, 0x3a, 0xa4, 0x58, 0x98, 0x31, + /*9ea0:*/ 0xce, 0x21, 0xbd, 0xf1, 0xc2, 0x7f, 0x87, 0x7a, 0xc9, 0x9f, 0xb2, 0x0b, 0x49, 0x1d, 0xff, 0x5a, + /*9eb0:*/ 0x60, 0x39, 0x77, 0x7e, 0x6f, 0xa3, 0x1a, 0x44, 0x81, 0x25, 0xac, 0x67, 0x9a, 0xa1, 0xbe, 0x9d, + /*9ec0:*/ 0x9e, 0xa4, 0x37, 0x7e, 0xb7, 0xdc, 0xd0, 0xbf, 0x57, 0x62, 0x9e, 0x6c, 0x8c, 0x4e, 0x2e, 0x3c, + /*9ed0:*/ 0xd3, 0x38, 0x91, 0x0c, 0xf4, 0x57, 0x91, 0x87, 0x00, 0x26, 0xd4, 0x0c, 0x22, 0x21, 0x0b, 0xab, + /*9ee0:*/ 0x1f, 0x3a, 0xe2, 0xcd, 0x41, 0x4c, 0xae, 0xfe, 0x9d, 0x11, 0xd1, 0x9b, 0xca, 0xc0, 0x95, 0x56, + /*9ef0:*/ 0xf9, 0xff, 0x70, 0xcd, 0xe2, 0x2b, 0x67, 0x5a, 0x1e, 0x5e, 0xb1, 0x70, 0x7f, 0x80, 0xb8, 0xd9, + /*9f00:*/ 0x85, 0x4f, 0x6a, 0xc5, 0xb1, 0xd3, 0x93, 0x11, 0x81, 0xf0, 0x9a, 0xf8, 0xf5, 0x97, 0x95, 0x63, + /*9f10:*/ 0x23, 0x45, 0x77, 0x19, 0x92, 0xdd, 0x33, 0x83, 0x48, 0x6e, 0xc7, 0xbd, 0x6a, 0xa8, 0x82, 0xb1, + /*9f20:*/ 0x5c, 0x64, 0x36, 0xda, 0xa2, 0x11, 0xbe, 0xc8, 0x9e, 0xc6, 0x43, 0x62, 0xe0, 0x02, 0x5f, 0x2f, + /*9f30:*/ 0x18, 0x29, 0xda, 0x32, 0x0e, 0xe5, 0x6c, 0xfa, 0x74, 0x79, 0x8b, 0xd2, 0x89, 0x3c, 0x88, 0xe3, + /*9f40:*/ 0xb5, 0x1d, 0x90, 0xce, 0x8d, 0x82, 0x41, 0xeb, 0x83, 0x90, 0x5e, 0xba, 0x6a, 0xb7, 0x1a, 0xb5, + /*9f50:*/ 0x54, 0xd7, 0x3c, 0x26, 0x63, 0x3c, 0x22, 0x80, 0x0a, 0x9e, 0xf8, 0x24, 0x82, 0x54, 0x64, 0x84, + /*9f60:*/ 0x51, 0xa9, 0x89, 0x2d, 0x39, 0x83, 0x35, 0x15, 0x1b, 0x95, 0x03, 0xf1, 0xb6, 0x2d, 0xd4, 0x96, + /*9f70:*/ 0x9b, 0x80, 0x13, 0x5c, 0x06, 0xf5, 0xa0, 0x76, 0xad, 0x2a, 0x02, 0x73, 0x96, 0x47, 0xe5, 0x38, + /*9f80:*/ 0xb8, 0x5d, 0x22, 0x37, 0xa5, 0x4c, 0x17, 0x36, 0xb2, 0x17, 0xd4, 0x6d, 0x5f, 0x54, 0xc2, 0xc7, + /*9f90:*/ 0x60, 0xe4, 0xd6, 0x53, 0x51, 0x20, 0x29, 0x3a, 0xa3, 0x15, 0x73, 0x13, 0xcc, 0xb6, 0xda, 0x81, + /*9fa0:*/ 0xcc, 0xe7, 0xd0, 0x9b, 0xb4, 0x52, 0xc9, 0x5a, 0x10, 0xda, 0x05, 0x08, 0xc9, 0x6e, 0x56, 0x9a, + /*9fb0:*/ 0xe8, 0x5f, 0xa4, 0x29, 0xff, 0x31, 0xad, 0x4a, 0x25, 0x46, 0x72, 0xab, 0xa1, 0xbf, 0x3a, 0x36, + /*9fc0:*/ 0x0b, 0x1d, 0x06, 0x90, 0xc3, 0x8b, 0x8e, 0x8e, 0x84, 0x60, 0xcf, 0x2d, 0xa3, 0x93, 0x2f, 0x68, + /*9fd0:*/ 0x53, 0x89, 0xb6, 0x2e, 0xde, 0xbc, 0x18, 0x7c, 0xbd, 0x66, 0x54, 0x92, 0xed, 0x0f, 0xf5, 0x82, + /*9fe0:*/ 0xdf, 0xba, 0x99, 0xc9, 0x8c, 0x63, 0xc2, 0x3b, 0x25, 0x6e, 0x86, 0x83, 0xf9, 0xe0, 0x1c, 0x34, + /*9ff0:*/ 0x8e, 0x27, 0xe0, 0x76, 0xe5, 0xa3, 0x23, 0x89, 0x5a, 0x0c, 0x7d, 0x37, 0xcc, 0x74, 0xeb, 0x22, + /*a000:*/ 0x13, 0x21, 0xa9, 0x64, 0x68, 0x50, 0xaa, 0x35, 0x5b, 0x57, 0x29, 0xff, 0xc1, 0x83, 0xb8, 0x00, + /*a010:*/ 0x11, 0x85, 0xa8, 0xe7, 0xbb, 0xc7, 0x9f, 0x8e, 0x73, 0x0b, 0x23, 0xfe, 0x4c, 0x59, 0x1e, 0x31, + /*a020:*/ 0x55, 0x74, 0x50, 0xf0, 0xb1, 0x95, 0xae, 0x8e, 0xbf, 0x46, 0x82, 0x05, 0xab, 0x19, 0x33, 0xe4, + /*a030:*/ 0x7f, 0xf5, 0xbd, 0x83, 0xa9, 0x0f, 0xf3, 0xe7, 0x88, 0x41, 0x47, 0xa7, 0x7f, 0xf3, 0xa3, 0x49, + /*a040:*/ 0x23, 0x18, 0xe7, 0x31, 0xba, 0xbf, 0x77, 0x47, 0x43, 0xa7, 0x79, 0x9e, 0xf7, 0xfb, 0x86, 0xfa, + /*a050:*/ 0x78, 0xe0, 0x7d, 0x89, 0xc4, 0xb5, 0x1d, 0xd5, 0xf9, 0x78, 0xbf, 0x24, 0x7c, 0xb0, 0xf7, 0x6c, + /*a060:*/ 0x95, 0xce, 0xe4, 0x98, 0xa8, 0xb1, 0x8d, 0x13, 0x16, 0xcf, 0x1c, 0xc8, 0x13, 0xf0, 0xfa, 0x10, + /*a070:*/ 0x64, 0x10, 0xd4, 0xb9, 0xab, 0xb2, 0x5d, 0x52, 0x92, 0x69, 0x18, 0xec, 0x27, 0xa7, 0x73, 0xde, + /*a080:*/ 0x2e, 0xfb, 0xa3, 0xe3, 0xc7, 0xf9, 0xb1, 0x16, 0xdf, 0x5c, 0x60, 0xfa, 0x3a, 0x1d, 0x1a, 0x51, + /*a090:*/ 0x6d, 0x00, 0xaf, 0x1d, 0x17, 0x7d, 0x99, 0xb2, 0x8e, 0x39, 0x84, 0x86, 0x81, 0xdb, 0x4b, 0xe6, + /*a0a0:*/ 0xc9, 0xa4, 0x6d, 0x0a, 0x53, 0xe3, 0x5e, 0x2b, 0x5b, 0x01, 0x81, 0x75, 0x0a, 0x84, 0xda, 0x5c, + /*a0b0:*/ 0x9b, 0x42, 0x5c, 0xab, 0x7b, 0xb8, 0x65, 0x41, 0xb2, 0x6e, 0x74, 0x64, 0x45, 0xc0, 0xe7, 0x24, + /*a0c0:*/ 0xf4, 0x64, 0xd8, 0x95, 0x0c, 0x7a, 0xf9, 0x8c, 0x08, 0xf6, 0xd1, 0xe8, 0x36, 0xbc, 0x9f, 0x1e, + /*a0d0:*/ 0x46, 0xa8, 0xfa, 0xe9, 0xf6, 0x36, 0x00, 0xf3, 0x1d, 0x5b, 0x63, 0xdc, 0xe0, 0xe7, 0x3f, 0xb6, + /*a0e0:*/ 0xb3, 0x2b, 0x74, 0x8d, 0xfb, 0x5e, 0x37, 0x41, 0x51, 0x1f, 0x82, 0x89, 0x37, 0x26, 0x7d, 0x1e, + /*a0f0:*/ 0x7e, 0x37, 0xf1, 0xb4, 0xcc, 0x65, 0x19, 0xe5, 0x99, 0x41, 0x4d, 0x93, 0x52, 0x7b, 0x2b, 0xa4, + /*a100:*/ 0xb7, 0x31, 0x13, 0x64, 0xdd, 0xed, 0x04, 0x94, 0x22, 0x7e, 0x35, 0xdb, 0xb5, 0xc7, 0xf2, 0x82, + /*a110:*/ 0x8d, 0xdf, 0x99, 0x41, 0x65, 0x8c, 0xd7, 0xbe, 0x8b, 0xbf, 0xf8, 0x28, 0x07, 0x33, 0x76, 0x7b, + /*a120:*/ 0x17, 0xc5, 0x83, 0x06, 0x63, 0xf5, 0x0c, 0x6a, 0xc8, 0x56, 0x42, 0x13, 0xa5, 0x28, 0x85, 0xba, + /*a130:*/ 0xb2, 0x25, 0x2d, 0x95, 0xf2, 0xff, 0x40, 0x20, 0x68, 0xd8, 0x11, 0xfc, 0xf4, 0x02, 0x76, 0x99, + /*a140:*/ 0xcf, 0x58, 0x0a, 0xa0, 0x6e, 0x2e, 0x13, 0xfd, 0x57, 0x66, 0x0b, 0xea, 0x05, 0x52, 0xc9, 0x8d, + /*a150:*/ 0xf8, 0xff, 0x68, 0x08, 0xc4, 0x10, 0xfd, 0x6d, 0x11, 0xa7, 0x40, 0xcb, 0xe6, 0xc6, 0x67, 0xbc, + /*a160:*/ 0x5b, 0xaa, 0xfc, 0xaf, 0xa9, 0x0e, 0xe0, 0x41, 0x8e, 0xa3, 0x83, 0x3e, 0xd6, 0x53, 0xe6, 0x77, + /*a170:*/ 0xfb, 0x1e, 0xcd, 0xfe, 0x06, 0x71, 0x0d, 0xc4, 0xf5, 0xff, 0xbc, 0xef, 0xbf, 0x0c, 0x58, 0xee, + /*a180:*/ 0xe2, 0x51, 0xf5, 0x32, 0xe9, 0x14, 0x46, 0x13, 0xc7, 0x2a, 0xd9, 0x91, 0x2b, 0xf1, 0x68, 0xce, + /*a190:*/ 0x14, 0xfd, 0xf7, 0x48, 0x1b, 0x08, 0x26, 0xdb, 0xc6, 0xdf, 0x1d, 0x4a, 0xc8, 0xac, 0xf2, 0x9b, + /*a1a0:*/ 0x23, 0xce, 0x72, 0xff, 0x3d, 0xdc, 0x4a, 0x9b, 0xe6, 0x6b, 0xcd, 0x3d, 0x07, 0xb3, 0x65, 0x58, + /*a1b0:*/ 0x08, 0x00, 0xea, 0x68, 0x65, 0x40, 0xb0, 0x0e, 0xfc, 0x37, 0x9a, 0x3b, 0xe2, 0x14, 0x9c, 0xdf, + /*a1c0:*/ 0x74, 0x1b, 0x7a, 0xc2, 0xf6, 0x5d, 0x2e, 0xdd, 0xdd, 0xf1, 0x9d, 0x7b, 0x6c, 0xf5, 0xe8, 0xc2, + /*a1d0:*/ 0x3f, 0x5b, 0xb3, 0xe0, 0xc7, 0xf4, 0xc3, 0x60, 0x81, 0x9a, 0xff, 0x4a, 0x50, 0xbf, 0xff, 0x14, + /*a1e0:*/ 0x9a, 0xea, 0x5e, 0x7b, 0x5f, 0xeb, 0xad, 0xf1, 0x40, 0x19, 0x67, 0x45, 0x6b, 0x69, 0x18, 0x55, + /*a1f0:*/ 0xb6, 0x39, 0x32, 0x15, 0xd0, 0xad, 0xb5, 0x66, 0xb2, 0x43, 0x13, 0x27, 0x90, 0xc8, 0x82, 0x7f, + /*a200:*/ 0x65, 0x0e, 0xc4, 0x4f, 0xec, 0xa5, 0xa0, 0x93, 0x72, 0x4e, 0x1c, 0xfd, 0xae, 0x29, 0x7f, 0x52, + /*a210:*/ 0xde, 0x65, 0xd4, 0xc4, 0x41, 0x48, 0xf3, 0xe7, 0x7b, 0xe9, 0xcc, 0x40, 0xd4, 0xfd, 0xa9, 0x72, + /*a220:*/ 0xe9, 0x22, 0x3a, 0xc9, 0xd2, 0x95, 0xd7, 0x84, 0xf4, 0x00, 0x05, 0x1c, 0xd7, 0x06, 0xa5, 0x02, + /*a230:*/ 0x41, 0xf2, 0x95, 0xb9, 0x46, 0x25, 0xf1, 0x27, 0x4f, 0xaa, 0x34, 0x8d, 0x1d, 0x06, 0x1f, 0x43, + /*a240:*/ 0x69, 0x13, 0x99, 0xcd, 0x6a, 0xd2, 0xa0, 0x6f, 0x47, 0x36, 0x39, 0xda, 0xdd, 0x73, 0x07, 0x58, + /*a250:*/ 0x6e, 0x4c, 0x2a, 0xd1, 0x8a, 0x1b, 0xfc, 0xcd, 0x22, 0xed, 0xb9, 0x43, 0xb6, 0x28, 0xfd, 0x58, + /*a260:*/ 0xa5, 0x03, 0x30, 0xd4, 0x5a, 0xca, 0x12, 0xb2, 0x8d, 0x06, 0x42, 0x26, 0x72, 0x71, 0xef, 0xf5, + /*a270:*/ 0x09, 0x89, 0x86, 0xf1, 0xd9, 0xb2, 0xa6, 0xc1, 0x7d, 0xa2, 0x8c, 0xbc, 0x31, 0xfa, 0x2a, 0xd2, + /*a280:*/ 0x3c, 0xd3, 0xf4, 0x60, 0x9c, 0x23, 0xf7, 0xc8, 0x17, 0xf0, 0xd2, 0x89, 0x25, 0xff, 0x45, 0x26, + /*a290:*/ 0x5a, 0xa7, 0x68, 0x96, 0x72, 0xca, 0xba, 0x5e, 0xab, 0x97, 0x6d, 0xba, 0xb9, 0x05, 0x91, 0x92, + /*a2a0:*/ 0xa5, 0xa1, 0x02, 0x1a, 0x82, 0xaa, 0xa9, 0xf2, 0x51, 0x96, 0x78, 0x25, 0xae, 0x82, 0x89, 0x55, + /*a2b0:*/ 0xba, 0x05, 0xd0, 0x4c, 0x86, 0x6b, 0x61, 0x9b, 0x77, 0x4c, 0x8d, 0x6f, 0x7a, 0xac, 0x58, 0x82, + /*a2c0:*/ 0xcb, 0xf3, 0xca, 0xe2, 0x7f, 0x9f, 0xbb, 0x69, 0x77, 0x23, 0x15, 0x5b, 0x72, 0x2d, 0x6c, 0x4f, + /*a2d0:*/ 0x20, 0x38, 0x5a, 0x5a, 0x37, 0xd8, 0x2e, 0x71, 0x33, 0x4a, 0x14, 0x56, 0xbb, 0x04, 0xc7, 0xb3, + /*a2e0:*/ 0xd8, 0x33, 0x1c, 0xa4, 0xd5, 0x57, 0xbf, 0x10, 0xda, 0x1c, 0x30, 0x15, 0x87, 0x87, 0xc2, 0x28, + /*a2f0:*/ 0xf6, 0x6c, 0x0d, 0x11, 0x1f, 0xb9, 0x87, 0x86, 0x67, 0x77, 0xbf, 0xee, 0xf6, 0x6d, 0x01, 0x6c, + /*a300:*/ 0xb4, 0x00, 0x91, 0x0e, 0xf4, 0x0b, 0x45, 0x85, 0x9e, 0x47, 0x4b, 0xe0, 0x73, 0xc8, 0x7f, 0xc3, + /*a310:*/ 0xd7, 0x38, 0x5c, 0x3d, 0x75, 0x0a, 0x48, 0xc6, 0x25, 0xb1, 0x2d, 0xdf, 0xc1, 0xd2, 0xfe, 0xd8, + /*a320:*/ 0x63, 0xf0, 0x46, 0xe8, 0x63, 0xb6, 0x72, 0xe3, 0x82, 0xbb, 0x31, 0x2f, 0x12, 0xfb, 0x10, 0x01, + /*a330:*/ 0xe4, 0xe2, 0x73, 0xe2, 0x08, 0x2d, 0x1e, 0x60, 0x90, 0x8a, 0x49, 0x9f, 0xf3, 0x9a, 0x97, 0x4d, + /*a340:*/ 0x62, 0xa2, 0x8a, 0xee, 0x27, 0x5f, 0x17, 0xfb, 0x36, 0x2b, 0xef, 0x7d, 0xcf, 0x74, 0xce, 0xa0, + /*a350:*/ 0x4d, 0x99, 0x34, 0x50, 0xa9, 0x49, 0x57, 0x20, 0x44, 0xd3, 0x84, 0xc9, 0xac, 0xba, 0xe6, 0x5b, + /*a360:*/ 0xd2, 0xd1, 0x91, 0xc6, 0x7a, 0xea, 0x3c, 0x0f, 0x4a, 0xc6, 0x30, 0xaa, 0x80, 0xbd, 0x72, 0x0d, + /*a370:*/ 0x83, 0xa2, 0x65, 0x47, 0x47, 0x80, 0x80, 0xf5, 0xab, 0xf6, 0x4c, 0x15, 0x6d, 0x99, 0x63, 0x06, + /*a380:*/ 0xea, 0xb7, 0x5a, 0x6e, 0x5b, 0x70, 0x4c, 0x00, 0x72, 0x0d, 0x27, 0xb7, 0xd0, 0x81, 0xe9, 0xee, + /*a390:*/ 0x23, 0x95, 0xce, 0xc6, 0xa7, 0x71, 0xb5, 0xd9, 0x8f, 0xe5, 0xed, 0xba, 0x88, 0x62, 0x44, 0xbd, + /*a3a0:*/ 0x1a, 0x76, 0x49, 0x41, 0xfd, 0x4f, 0x9e, 0x1d, 0x6e, 0xfc, 0x9e, 0x62, 0xc2, 0xd3, 0x54, 0x1b, + /*a3b0:*/ 0xf4, 0x69, 0xf0, 0x29, 0xf4, 0xbb, 0x32, 0x5a, 0x1f, 0x5f, 0x70, 0xe3, 0xe6, 0x86, 0x03, 0xe7, + /*a3c0:*/ 0x85, 0xbd, 0x29, 0x9c, 0x1a, 0xb3, 0xae, 0xa6, 0xca, 0xbf, 0x4f, 0x47, 0xc1, 0xb3, 0x52, 0xd2, + /*a3d0:*/ 0xf1, 0x50, 0x51, 0x23, 0xd6, 0x60, 0x55, 0x61, 0x41, 0xec, 0xf3, 0x23, 0xb7, 0x8f, 0x1c, 0x15, + /*a3e0:*/ 0x60, 0x8c, 0xd7, 0x79, 0x0b, 0x77, 0x19, 0x4e, 0x04, 0x42, 0xb0, 0x5c, 0xb9, 0x0c, 0xb9, 0x4a, + /*a3f0:*/ 0x0b, 0x2b, 0xf3, 0xd7, 0x4a, 0xd1, 0x46, 0xc2, 0x80, 0xf1, 0xab, 0xac, 0x19, 0xb6, 0x69, 0x2b, + /*a400:*/ 0x7d, 0x0b, 0x05, 0xbb, 0x27, 0x37, 0x80, 0x65, 0x98, 0x60, 0x25, 0xe3, 0xab, 0x75, 0x2a, 0xac, + /*a410:*/ 0x6a, 0xb0, 0x3a, 0x41, 0x09, 0xcb, 0x85, 0x49, 0xa8, 0x88, 0x6f, 0x9c, 0x07, 0xef, 0x96, 0xca, + /*a420:*/ 0xd6, 0x14, 0x41, 0xbf, 0xe7, 0x3a, 0x35, 0xc1, 0x7a, 0x75, 0x3a, 0x2e, 0x9f, 0x7a, 0xd2, 0xfc, + /*a430:*/ 0xb0, 0x9d, 0x46, 0xd6, 0xb8, 0xa9, 0x69, 0x19, 0x4a, 0x1d, 0x48, 0xf5, 0xbb, 0x22, 0x78, 0x41, + /*a440:*/ 0x21, 0xbc, 0x25, 0xd2, 0xb9, 0x00, 0x4b, 0xcd, 0x4e, 0x16, 0x06, 0x91, 0x2b, 0xb9, 0x12, 0xbc, + /*a450:*/ 0x57, 0xa0, 0x41, 0x60, 0x88, 0x76, 0xa0, 0xe7, 0xe6, 0xc9, 0x16, 0x62, 0x70, 0x79, 0x56, 0xe3, + /*a460:*/ 0xa4, 0x03, 0x9d, 0x46, 0x62, 0xb3, 0x1b, 0x42, 0x1b, 0x2d, 0x11, 0x83, 0xba, 0x35, 0xa7, 0x8d, + /*a470:*/ 0x38, 0xb7, 0xfa, 0xa4, 0x4c, 0x02, 0x1c, 0x60, 0x47, 0x62, 0x96, 0xbe, 0x83, 0x15, 0x9f, 0x31, + /*a480:*/ 0xd5, 0x84, 0x2a, 0x8e, 0x7e, 0xb1, 0xba, 0x69, 0x09, 0xa2, 0x68, 0xfa, 0xf9, 0xf0, 0xd3, 0x47, + /*a490:*/ 0x3c, 0x10, 0x50, 0x4c, 0x7f, 0x3b, 0x2d, 0x56, 0x0f, 0xa4, 0xea, 0x83, 0xc5, 0x94, 0x02, 0x86, + /*a4a0:*/ 0x24, 0x10, 0xae, 0x94, 0x7e, 0x8e, 0xdb, 0xe1, 0xda, 0x9f, 0xd5, 0x79, 0x1f, 0x74, 0x75, 0x81, + /*a4b0:*/ 0x86, 0x71, 0xce, 0xf6, 0x47, 0x93, 0xb4, 0xad, 0x0e, 0x3f, 0x02, 0x8b, 0xd9, 0xaa, 0xea, 0x19, + /*a4c0:*/ 0x94, 0x6e, 0x43, 0xaa, 0xd6, 0x85, 0x5c, 0x07, 0x52, 0xd0, 0xde, 0xad, 0x23, 0x14, 0x09, 0x0c, + /*a4d0:*/ 0xf9, 0xab, 0x4b, 0x77, 0x4d, 0x26, 0xa3, 0x05, 0x61, 0x06, 0x32, 0xe4, 0xac, 0x89, 0xb8, 0xbe, + /*a4e0:*/ 0x85, 0x80, 0xde, 0xf0, 0xdb, 0x36, 0x1b, 0x68, 0x62, 0x86, 0xa0, 0x72, 0x71, 0x62, 0x7f, 0xd3, + /*a4f0:*/ 0xbf, 0x14, 0x3b, 0x1f, 0x84, 0x63, 0x47, 0x20, 0x09, 0x42, 0x57, 0xb6, 0x72, 0x09, 0xa8, 0xac, + /*a500:*/ 0xb0, 0x9b, 0xdf, 0x64, 0x4f, 0x47, 0xe4, 0x03, 0x72, 0x91, 0x88, 0x9d, 0x71, 0x13, 0x9f, 0xf2, + /*a510:*/ 0xf0, 0x90, 0x1b, 0xf8, 0x3c, 0x98, 0xff, 0x75, 0x63, 0xb4, 0x83, 0x9c, 0x28, 0x0a, 0x3b, 0x7d, + /*a520:*/ 0xda, 0xcc, 0xff, 0x1b, 0x5b, 0x20, 0x19, 0xb9, 0x54, 0xcf, 0xf6, 0x56, 0x9c, 0xb7, 0x73, 0xa3, + /*a530:*/ 0xbc, 0x12, 0x86, 0x03, 0xe5, 0x00, 0x9f, 0xf5, 0x27, 0xdd, 0xa0, 0xbd, 0x33, 0xe4, 0x31, 0x8e, + /*a540:*/ 0x04, 0xb7, 0x98, 0x16, 0x6d, 0x8c, 0x6c, 0x27, 0x91, 0x34, 0x70, 0x90, 0xca, 0x5f, 0x80, 0x9a, + /*a550:*/ 0xf9, 0x33, 0xf5, 0x26, 0xcd, 0xee, 0x48, 0xfc, 0xde, 0x3d, 0x69, 0xd7, 0x57, 0x94, 0x8e, 0xa1, + /*a560:*/ 0xda, 0x9e, 0x53, 0x93, 0x45, 0x53, 0x43, 0xa7, 0x33, 0x9c, 0x2d, 0x4b, 0x77, 0xe4, 0x65, 0x3f, + /*a570:*/ 0xce, 0x65, 0xa7, 0x47, 0xe1, 0x25, 0xbe, 0x56, 0xd8, 0xa6, 0xb7, 0x81, 0x8b, 0x77, 0x74, 0x74, + /*a580:*/ 0xa9, 0x66, 0xe5, 0x57, 0xa8, 0x69, 0x41, 0xc1, 0xff, 0x69, 0xa7, 0x76, 0x10, 0xd5, 0xab, 0x08, + /*a590:*/ 0x15, 0xb1, 0x7f, 0xa2, 0x33, 0xbe, 0x71, 0xae, 0x2c, 0x49, 0x45, 0x17, 0xba, 0x0c, 0xe0, 0xc1, + /*a5a0:*/ 0x6c, 0x2f, 0x12, 0x72, 0xa8, 0x84, 0x96, 0x8e, 0x33, 0x13, 0xb2, 0xea, 0x3a, 0x6a, 0x47, 0xb3, + /*a5b0:*/ 0xf3, 0x79, 0xbf, 0xf6, 0x61, 0x97, 0xbf, 0xd4, 0xe0, 0xcc, 0x23, 0xa8, 0x37, 0x21, 0xeb, 0x6e, + /*a5c0:*/ 0x20, 0x07, 0x4f, 0x93, 0x2d, 0x42, 0xf0, 0xba, 0x97, 0x8e, 0xfe, 0x33, 0xe5, 0x70, 0x6c, 0x1f, + /*a5d0:*/ 0x1f, 0xac, 0xd2, 0x48, 0xee, 0x4d, 0x50, 0xc2, 0x26, 0x93, 0x11, 0x08, 0x1a, 0x5d, 0x05, 0x4c, + /*a5e0:*/ 0xf9, 0x2a, 0x27, 0xfa, 0x1f, 0xfa, 0xcd, 0x60, 0xee, 0xa1, 0xf8, 0x61, 0xed, 0xc4, 0xb3, 0x6f, + /*a5f0:*/ 0x53, 0xb2, 0xd2, 0x4a, 0x62, 0xbe, 0x11, 0xd3, 0x88, 0x1f, 0x64, 0xb2, 0xc9, 0x42, 0x87, 0xa8, + /*a600:*/ 0xa0, 0xd6, 0xb3, 0x78, 0x9d, 0xcb, 0x7f, 0xec, 0x7f, 0xb9, 0xad, 0x23, 0x78, 0x1f, 0x5f, 0xd0, + /*a610:*/ 0x3f, 0x61, 0x45, 0xf3, 0x55, 0xee, 0xd1, 0xd6, 0x2c, 0x59, 0x20, 0x1c, 0x6e, 0xd7, 0xaa, 0xf0, + /*a620:*/ 0xf2, 0x4b, 0x77, 0x95, 0x93, 0x68, 0x0a, 0xc8, 0x31, 0x06, 0x01, 0xf9, 0x58, 0xc8, 0xb0, 0x49, + /*a630:*/ 0xe3, 0x87, 0x5f, 0x5e, 0xd1, 0x95, 0xbe, 0xf6, 0xcc, 0xf2, 0xbb, 0xb9, 0x5d, 0xa7, 0x9e, 0x4d, + /*a640:*/ 0xde, 0x0e, 0x52, 0xe0, 0xf2, 0x88, 0x3b, 0xca, 0x7c, 0x74, 0x0f, 0x76, 0x6c, 0xb5, 0xa2, 0xab, + /*a650:*/ 0xb2, 0x02, 0xdc, 0xae, 0x83, 0x7b, 0xd8, 0x01, 0x24, 0x11, 0x49, 0xe9, 0x58, 0x00, 0xad, 0x54, + /*a660:*/ 0x89, 0xa6, 0x84, 0x7e, 0x79, 0x20, 0x6a, 0xf8, 0x5e, 0xc3, 0x25, 0x29, 0xb7, 0x15, 0x8b, 0xaa, + /*a670:*/ 0x67, 0xf4, 0x08, 0x88, 0x75, 0xe0, 0xee, 0x5e, 0x40, 0xb0, 0x93, 0x77, 0x44, 0x1e, 0xe6, 0x92, + /*a680:*/ 0xe9, 0x54, 0xfc, 0x8c, 0x9c, 0x03, 0x2b, 0x8e, 0x4a, 0x04, 0x3d, 0x76, 0xa4, 0x07, 0xe2, 0x62, + /*a690:*/ 0xfb, 0x17, 0xab, 0x7c, 0x32, 0x69, 0xb7, 0xb8, 0x53, 0x4a, 0x6a, 0xe2, 0x9c, 0xd8, 0xf1, 0x7c, + /*a6a0:*/ 0x31, 0xfd, 0x2e, 0xdc, 0xb8, 0xce, 0xf0, 0xa3, 0x90, 0xe4, 0xc1, 0xa1, 0xf8, 0xda, 0xb9, 0x74, + /*a6b0:*/ 0x95, 0x9e, 0x2f, 0xcf, 0x74, 0x90, 0x5e, 0x10, 0x2c, 0xf7, 0x8f, 0x82, 0xa6, 0x6d, 0x97, 0xb2, + /*a6c0:*/ 0x25, 0x44, 0x5b, 0xae, 0x03, 0x6a, 0x09, 0xe8, 0x69, 0x9b, 0xdf, 0x34, 0x57, 0x5e, 0x1b, 0x58, + /*a6d0:*/ 0x36, 0x4a, 0x79, 0x26, 0x1a, 0x6f, 0x4e, 0xa1, 0xf6, 0xfd, 0xa9, 0x6a, 0xd4, 0xb6, 0x2c, 0x1e, + /*a6e0:*/ 0x54, 0xee, 0x6a, 0x3d, 0x13, 0xed, 0x98, 0xb9, 0xd1, 0xc7, 0x40, 0x3b, 0xb1, 0x08, 0x74, 0xf2, + /*a6f0:*/ 0x9e, 0x23, 0x70, 0x0f, 0xfe, 0xcf, 0xe0, 0x42, 0x94, 0xb9, 0xfb, 0x1a, 0xf5, 0xfa, 0xee, 0xe5, + /*a700:*/ 0x60, 0xf3, 0x74, 0x2e, 0x8a, 0x6b, 0x45, 0xbe, 0x6f, 0x0e, 0x98, 0xa8, 0xe4, 0x39, 0x81, 0xdf, + /*a710:*/ 0xd1, 0x0e, 0x17, 0xfc, 0xd1, 0xfe, 0x65, 0xa6, 0xe0, 0xe0, 0x3a, 0xd2, 0xe6, 0xb5, 0xe7, 0x50, + /*a720:*/ 0x08, 0x6a, 0x16, 0x66, 0x2e, 0x7f, 0x9d, 0x24, 0xbb, 0x88, 0xa8, 0x39, 0xac, 0xe4, 0x83, 0xf1, + /*a730:*/ 0x82, 0x24, 0x25, 0xbc, 0x70, 0x61, 0x83, 0xf8, 0x33, 0x88, 0xee, 0xd7, 0x03, 0x31, 0x88, 0x22, + /*a740:*/ 0x06, 0xee, 0x65, 0x98, 0x1c, 0x79, 0x74, 0x8d, 0x62, 0xda, 0x8c, 0x4d, 0xa6, 0x65, 0x39, 0x0b, + /*a750:*/ 0xbb, 0xaa, 0x7b, 0x3e, 0xc7, 0x21, 0x34, 0xbc, 0x1a, 0xd0, 0x83, 0x0d, 0x28, 0x32, 0x03, 0xd6, + /*a760:*/ 0x1d, 0x57, 0x40, 0x62, 0xd3, 0xba, 0x59, 0xdd, 0x21, 0x3a, 0xb6, 0xcc, 0x9f, 0xd9, 0x48, 0xa1, + /*a770:*/ 0x5f, 0x79, 0xb0, 0x25, 0x6f, 0x8b, 0x9c, 0x9a, 0x38, 0x02, 0x45, 0xfb, 0xc4, 0x4c, 0x19, 0x6a, + /*a780:*/ 0x80, 0x89, 0x53, 0xfc, 0x16, 0x92, 0xa2, 0x65, 0x6f, 0x49, 0xca, 0x34, 0x44, 0xd7, 0x47, 0xb1, + /*a790:*/ 0xca, 0xcb, 0x6f, 0x1b, 0x4e, 0xad, 0x40, 0x93, 0x3e, 0x17, 0x51, 0x24, 0xc7, 0xa4, 0x91, 0x94, + /*a7a0:*/ 0x85, 0xbc, 0x2e, 0x1a, 0xc0, 0x60, 0x26, 0xb9, 0x50, 0x3b, 0x40, 0xb0, 0x35, 0x85, 0xb7, 0x1f, + /*a7b0:*/ 0x06, 0x30, 0x1e, 0x8e, 0x23, 0xf2, 0xad, 0x79, 0xe5, 0x6e, 0xfa, 0xf6, 0x68, 0x11, 0xdc, 0xce, + /*a7c0:*/ 0x35, 0xe2, 0x8e, 0xcb, 0x2d, 0xe1, 0x00, 0x4b, 0x47, 0xeb, 0x86, 0x23, 0x94, 0xfb, 0xa2, 0x30, + /*a7d0:*/ 0xf5, 0x36, 0x9e, 0x94, 0xc9, 0x80, 0x16, 0xdc, 0x57, 0x9e, 0xb5, 0x8a, 0x0c, 0x0e, 0xcb, 0x28, + /*a7e0:*/ 0xf4, 0x5f, 0x4d, 0xc2, 0xa3, 0x6a, 0x07, 0x86, 0xda, 0xf4, 0x6c, 0x4e, 0xc8, 0xa1, 0xac, 0x9b, + /*a7f0:*/ 0x15, 0xd7, 0x86, 0x2c, 0x83, 0x2d, 0x5a, 0x83, 0x51, 0x6a, 0xd5, 0x1b, 0x92, 0xf7, 0x63, 0x8b, + /*a800:*/ 0x1d, 0x94, 0xc5, 0x1c, 0x6d, 0x85, 0xb1, 0x77, 0x54, 0x86, 0x46, 0xc4, 0x42, 0x73, 0x6e, 0xf2, + /*a810:*/ 0x81, 0x4a, 0xb0, 0xac, 0x34, 0x32, 0xe6, 0x00, 0x93, 0x55, 0xe6, 0x78, 0x31, 0xb8, 0xc4, 0x9c, + /*a820:*/ 0xe0, 0xdd, 0x9d, 0xa4, 0x67, 0x6c, 0x8c, 0x64, 0xf1, 0xd6, 0x5d, 0x4a, 0x2e, 0xff, 0x6e, 0x7e, + /*a830:*/ 0xc5, 0x09, 0x8e, 0x27, 0xbe, 0x1e, 0xc4, 0xe3, 0x8b, 0x6b, 0x4b, 0x72, 0xb6, 0x18, 0xf3, 0x69, + /*a840:*/ 0x0e, 0x2e, 0xda, 0xb3, 0x0b, 0x35, 0x1a, 0xb2, 0x17, 0xa6, 0x25, 0x96, 0xbc, 0xe8, 0x41, 0xdb, + /*a850:*/ 0xc5, 0x76, 0xa3, 0xe9, 0x11, 0xf1, 0xc1, 0xe0, 0xde, 0x91, 0x1b, 0x26, 0x93, 0x9c, 0xd6, 0xe9, + /*a860:*/ 0x3a, 0xb8, 0x91, 0xd5, 0x02, 0x1b, 0x7a, 0x0c, 0x3e, 0x0a, 0x01, 0xe0, 0x4b, 0xdc, 0xd7, 0xa4, + /*a870:*/ 0x41, 0x19, 0x3a, 0xd5, 0xa9, 0x3d, 0x9e, 0x51, 0x01, 0xa2, 0xb4, 0xbf, 0xf3, 0xbf, 0x54, 0xe0, + /*a880:*/ 0xdc, 0x29, 0xdc, 0x44, 0xd9, 0x6d, 0xd0, 0x93, 0x45, 0x59, 0x78, 0xa7, 0xce, 0x43, 0x2e, 0x60, + /*a890:*/ 0xae, 0xab, 0x59, 0x9f, 0x4b, 0xfe, 0x8e, 0x43, 0x5c, 0xd8, 0xbd, 0x59, 0xa4, 0x6e, 0x9d, 0xab, + /*a8a0:*/ 0xf1, 0xb6, 0x24, 0x4a, 0x05, 0x39, 0x4b, 0xbd, 0x66, 0x55, 0xcf, 0x43, 0xd4, 0x59, 0xc6, 0x0d, + /*a8b0:*/ 0x1b, 0x08, 0xe5, 0x5b, 0x15, 0xc9, 0x40, 0x30, 0xc4, 0x82, 0xfb, 0xf9, 0xd8, 0xee, 0x89, 0x81, + /*a8c0:*/ 0x9c, 0xa1, 0x5c, 0xd5, 0x4a, 0x76, 0x1d, 0x57, 0xa0, 0x9e, 0xb8, 0x7d, 0x10, 0x86, 0x99, 0x5b, + /*a8d0:*/ 0x96, 0x08, 0x92, 0x19, 0xca, 0xb4, 0xef, 0x92, 0x4f, 0x80, 0x80, 0x5f, 0xe1, 0xf8, 0x89, 0x72, + /*a8e0:*/ 0xc0, 0x51, 0xf5, 0xa4, 0xda, 0x24, 0xca, 0x43, 0xf3, 0x4e, 0x3a, 0x72, 0x88, 0x3d, 0x1d, 0x36, + /*a8f0:*/ 0xa6, 0xdb, 0x52, 0x3e, 0x8c, 0x41, 0x16, 0xb7, 0x5c, 0x0a, 0x64, 0x2a, 0x53, 0x62, 0x28, 0x67, + /*a900:*/ 0xa4, 0x5d, 0x75, 0x75, 0x4e, 0x45, 0x80, 0x6b, 0xb7, 0xc8, 0x84, 0xaa, 0xe9, 0x53, 0x7e, 0x86, + /*a910:*/ 0x2e, 0x80, 0x39, 0x72, 0x3b, 0x03, 0xd2, 0x8a, 0xe9, 0xa6, 0xd0, 0xfc, 0x2e, 0xe4, 0x87, 0xd1, + /*a920:*/ 0xc3, 0x2b, 0x42, 0x46, 0xe6, 0xe4, 0x38, 0xa1, 0x0c, 0x18, 0xe4, 0x31, 0xd4, 0xd1, 0xd3, 0x50, + /*a930:*/ 0xcb, 0xd0, 0x67, 0x68, 0x15, 0x8e, 0x47, 0x85, 0x4b, 0x94, 0x13, 0x8b, 0x2c, 0x66, 0xa0, 0x2f, + /*a940:*/ 0xd3, 0xf8, 0x7a, 0xcc, 0xb4, 0xb4, 0x26, 0xb7, 0xbd, 0x2c, 0xff, 0xaa, 0x93, 0xfb, 0xa0, 0xc0, + /*a950:*/ 0xc3, 0x55, 0x3b, 0x98, 0xe6, 0xac, 0x75, 0xd0, 0x0b, 0x3a, 0x7c, 0xd0, 0xe1, 0x45, 0x3f, 0x4b, + /*a960:*/ 0xc2, 0xe1, 0x72, 0xbd, 0xda, 0x91, 0xd8, 0x4d, 0x1e, 0x37, 0xdb, 0x09, 0xf6, 0xb6, 0x84, 0x90, + /*a970:*/ 0xdb, 0xde, 0xb4, 0x45, 0xed, 0x6b, 0x85, 0x15, 0x41, 0x8e, 0x04, 0x62, 0x10, 0x31, 0x75, 0x75, + /*a980:*/ 0xa2, 0xce, 0x16, 0xa0, 0xdd, 0x28, 0x98, 0x39, 0xf8, 0x15, 0xcc, 0x93, 0x75, 0xc4, 0xf1, 0xa1, + /*a990:*/ 0xc7, 0xab, 0x0e, 0x86, 0x54, 0x70, 0x2f, 0x39, 0x76, 0x49, 0x20, 0x87, 0x42, 0x6e, 0x37, 0x7b, + /*a9a0:*/ 0x31, 0x8d, 0x72, 0xf3, 0x97, 0xae, 0x38, 0xb7, 0x63, 0x38, 0xb3, 0x65, 0x86, 0xa2, 0x0b, 0xaa, + /*a9b0:*/ 0x6a, 0x16, 0xf0, 0xe6, 0xf4, 0xd0, 0x29, 0x66, 0xbb, 0x6c, 0xd0, 0x2e, 0x86, 0x44, 0xe8, 0x39, + /*a9c0:*/ 0xd1, 0x37, 0x50, 0xd3, 0x5c, 0xdd, 0x5a, 0xf4, 0xc0, 0x08, 0x35, 0x82, 0xd9, 0xdf, 0x76, 0xc8, + /*a9d0:*/ 0x65, 0x54, 0x18, 0xf3, 0xf3, 0x48, 0xfc, 0x03, 0x0d, 0x2e, 0xee, 0xdb, 0xd8, 0x89, 0x47, 0x1a, + /*a9e0:*/ 0xd1, 0x90, 0xaf, 0xe7, 0x87, 0x92, 0xb0, 0x32, 0x02, 0x7d, 0x5b, 0xd1, 0x75, 0xa9, 0xd0, 0xfc, + /*a9f0:*/ 0x0e, 0x02, 0x64, 0x31, 0xba, 0xc0, 0x40, 0xfc, 0x48, 0xc5, 0x74, 0x6c, 0xbb, 0x76, 0x05, 0x2b, + /*aa00:*/ 0x92, 0xd0, 0xed, 0xd4, 0x1e, 0x87, 0x63, 0xba, 0x01, 0x0a, 0xf9, 0xb3, 0xe3, 0x3a, 0xbf, 0x34, + /*aa10:*/ 0x4d, 0x92, 0x00, 0xc4, 0xf4, 0x13, 0x65, 0x72, 0xaf, 0x4f, 0x1e, 0xa9, 0x35, 0xc9, 0x3b, 0x76, + /*aa20:*/ 0xba, 0x0b, 0x34, 0x4f, 0xaf, 0xcf, 0x13, 0x39, 0x4a, 0xb0, 0xf3, 0x4c, 0x2e, 0x88, 0xfa, 0x4a, + /*aa30:*/ 0xde, 0xa1, 0x3b, 0xcf, 0x21, 0x2c, 0x0f, 0x2e, 0x32, 0xe6, 0x24, 0x83, 0xe5, 0x6b, 0x36, 0x21, + /*aa40:*/ 0x7f, 0xe1, 0x25, 0xa5, 0x49, 0xf0, 0xb5, 0x9f, 0x93, 0xe9, 0x59, 0x09, 0x19, 0x8f, 0x71, 0x6b, + /*aa50:*/ 0x08, 0x53, 0xfd, 0x6e, 0xdc, 0x53, 0x7b, 0xfe, 0x0f, 0xa2, 0x2b, 0x16, 0xca, 0xca, 0x31, 0x3d, + /*aa60:*/ 0x79, 0x13, 0x0b, 0x8a, 0x39, 0x1d, 0x9f, 0x70, 0x94, 0xc5, 0x3c, 0xa0, 0x3d, 0x2f, 0x73, 0xe0, + /*aa70:*/ 0x27, 0x37, 0x49, 0xe4, 0x84, 0xf5, 0xe6, 0x68, 0xfb, 0xab, 0x15, 0x76, 0xee, 0x65, 0x3c, 0xbf, + /*aa80:*/ 0x30, 0x90, 0x0c, 0x6d, 0x15, 0xfc, 0xa0, 0x1b, 0xb6, 0xa5, 0xea, 0x32, 0x63, 0x4f, 0x6b, 0x20, + /*aa90:*/ 0x0d, 0x04, 0xff, 0xaf, 0x95, 0xe4, 0x9b, 0xe8, 0xae, 0x91, 0x85, 0x3a, 0x6b, 0x9d, 0xa7, 0x3a, + /*aaa0:*/ 0x3b, 0x88, 0xd6, 0xc4, 0x28, 0x02, 0x17, 0x20, 0xfc, 0x2b, 0x8d, 0x73, 0x2f, 0xcb, 0xd4, 0x31, + /*aab0:*/ 0x4a, 0x30, 0xa5, 0x52, 0x56, 0xbd, 0xed, 0xb2, 0x88, 0x5d, 0xa7, 0xf6, 0xcf, 0xe2, 0x70, 0x7b, + /*aac0:*/ 0x46, 0x4f, 0x24, 0x65, 0xdb, 0xaf, 0x56, 0xef, 0x07, 0x30, 0x0b, 0xa6, 0x8f, 0xc3, 0x9e, 0x39, + /*aad0:*/ 0x0c, 0x91, 0xd8, 0x2b, 0x14, 0xa0, 0xc9, 0x93, 0x8a, 0x94, 0x22, 0xee, 0x81, 0x74, 0xbc, 0x12, + /*aae0:*/ 0x69, 0x0b, 0x3f, 0x4a, 0x3b, 0x79, 0x9b, 0x6f, 0x2f, 0x0d, 0x6f, 0xd0, 0x3f, 0xf8, 0x2d, 0x50, + /*aaf0:*/ 0x0a, 0xa0, 0xda, 0xb4, 0x0a, 0xf4, 0xda, 0xdb, 0x21, 0x85, 0x8b, 0xf9, 0x61, 0xa4, 0xe6, 0xda, + /*ab00:*/ 0x42, 0xf8, 0x02, 0x1e, 0x78, 0x34, 0x8c, 0xd2, 0xbd, 0xf0, 0x3b, 0x75, 0x5b, 0x0b, 0x7e, 0x91, + /*ab10:*/ 0x60, 0xcd, 0x20, 0xab, 0x04, 0x61, 0x9b, 0x45, 0x04, 0x53, 0x0d, 0x27, 0x27, 0x18, 0x27, 0x44, + /*ab20:*/ 0x14, 0xb0, 0xe2, 0x54, 0x7d, 0x41, 0xbc, 0x44, 0xf4, 0x94, 0xfe, 0xf3, 0xfa, 0x6a, 0x0f, 0xda, + /*ab30:*/ 0xe1, 0x7c, 0x5e, 0x72, 0x64, 0xe2, 0xe7, 0xd7, 0x81, 0x49, 0x69, 0x94, 0x9e, 0xee, 0xb6, 0x8a, + /*ab40:*/ 0x20, 0xf8, 0x19, 0x48, 0xc5, 0x9c, 0x7e, 0x25, 0xb6, 0xf6, 0xe6, 0x92, 0xba, 0xb0, 0x0d, 0x47, + /*ab50:*/ 0x9f, 0x4e, 0x40, 0x7f, 0x90, 0x6b, 0x56, 0xdc, 0x07, 0x4f, 0x88, 0xcb, 0xf0, 0x1f, 0x09, 0x1d, + /*ab60:*/ 0xad, 0x14, 0x36, 0x7e, 0x19, 0x32, 0xdd, 0x75, 0x3a, 0xc2, 0x46, 0xc6, 0xb4, 0xce, 0x11, 0xee, + /*ab70:*/ 0x5d, 0x15, 0xdd, 0xd0, 0xc5, 0xfc, 0x59, 0x39, 0x14, 0x0b, 0x87, 0x37, 0x71, 0x24, 0x33, 0x5d, + /*ab80:*/ 0xb6, 0x71, 0xea, 0x4c, 0xd8, 0x5b, 0x73, 0x3e, 0x7d, 0x40, 0x8b, 0x65, 0x16, 0xa1, 0x08, 0xf1, + /*ab90:*/ 0xfd, 0x2f, 0xab, 0xed, 0x8f, 0xeb, 0x7e, 0xfb, 0x40, 0x26, 0x66, 0xce, 0x05, 0x07, 0x6b, 0x65, + /*aba0:*/ 0x93, 0x00, 0x69, 0xbc, 0xdf, 0x11, 0x67, 0xf5, 0x39, 0x9a, 0xce, 0x51, 0xcf, 0x63, 0x90, 0xa5, + /*abb0:*/ 0xcc, 0x0b, 0xf9, 0x00, 0x44, 0xe4, 0x14, 0xc1, 0x16, 0xa6, 0x3f, 0x1b, 0x15, 0x2e, 0x7d, 0x3e, + /*abc0:*/ 0x86, 0xbd, 0xc5, 0x4a, 0x3b, 0xff, 0x2f, 0x9b, 0x73, 0x2b, 0x40, 0x1b, 0xa0, 0xb1, 0x51, 0x84, + /*abd0:*/ 0x76, 0x8b, 0x5e, 0x61, 0x32, 0xc1, 0xcc, 0xb6, 0xd8, 0x39, 0xce, 0xbb, 0xe6, 0x82, 0xf0, 0x72, + /*abe0:*/ 0x09, 0x07, 0xe5, 0x25, 0x98, 0x60, 0x02, 0x37, 0x29, 0x5a, 0x9f, 0xca, 0x83, 0x90, 0x85, 0x28, + /*abf0:*/ 0xa7, 0x88, 0xae, 0xb8, 0x77, 0xee, 0x61, 0x85, 0x32, 0x57, 0xb6, 0xf8, 0x3c, 0x69, 0x39, 0xc0, + /*ac00:*/ 0x3d, 0x78, 0x30, 0x86, 0x7a, 0x8f, 0x86, 0x4b, 0xe7, 0x0d, 0xb1, 0x6f, 0x4a, 0x21, 0x56, 0x40, + /*ac10:*/ 0xb8, 0xd6, 0x1e, 0x36, 0xca, 0xb0, 0x94, 0xb0, 0x1c, 0x84, 0x6b, 0x45, 0xe7, 0xee, 0x10, 0xf6, + /*ac20:*/ 0xdd, 0xa0, 0x32, 0x58, 0x04, 0xad, 0x5e, 0xd2, 0x99, 0x74, 0x78, 0x56, 0x78, 0x7e, 0x81, 0x0f, + /*ac30:*/ 0x2d, 0x2b, 0x86, 0x0d, 0x67, 0xd3, 0x00, 0xf8, 0xe5, 0xb0, 0x2b, 0xf9, 0x86, 0x8f, 0xf7, 0x48, + /*ac40:*/ 0x7d, 0xc0, 0xf6, 0x65, 0x55, 0xe2, 0xed, 0xb3, 0x17, 0xb5, 0x5c, 0xc7, 0xc2, 0xba, 0xf6, 0x51, + /*ac50:*/ 0xf9, 0x9b, 0x63, 0xd9, 0xf9, 0x31, 0xfe, 0xe2, 0x70, 0x50, 0x81, 0x09, 0x4c, 0xf6, 0x5a, 0x8c, + /*ac60:*/ 0x9c, 0xcf, 0x66, 0x48, 0xb7, 0x7c, 0x95, 0x9d, 0xbd, 0x3f, 0x65, 0x5d, 0x6b, 0x3d, 0xe1, 0x3e, + /*ac70:*/ 0x5c, 0x3a, 0xff, 0xcc, 0x19, 0xef, 0x3f, 0xa5, 0xe0, 0xaf, 0xa9, 0x58, 0x9f, 0xae, 0xb7, 0x7d, + /*ac80:*/ 0xad, 0xde, 0x83, 0x6f, 0xfa, 0x44, 0x1a, 0x44, 0x8f, 0x46, 0xed, 0x15, 0x73, 0xb4, 0x3d, 0x92, + /*ac90:*/ 0x56, 0xb5, 0x56, 0x42, 0xe6, 0x3d, 0xc4, 0x5a, 0xd9, 0xa7, 0x57, 0x01, 0x50, 0x06, 0x76, 0xf2, + /*aca0:*/ 0x20, 0xa5, 0x8f, 0xb0, 0xc5, 0xe8, 0x44, 0x51, 0xec, 0xf8, 0x36, 0x6f, 0x0e, 0xf6, 0xa8, 0xd4, + /*acb0:*/ 0x60, 0xe3, 0x01, 0xe5, 0xaf, 0xf9, 0xae, 0x1e, 0x6e, 0x5c, 0x6f, 0x2f, 0x29, 0xc3, 0xc3, 0xa5, + /*acc0:*/ 0xf4, 0xb8, 0x5f, 0x8e, 0x12, 0xab, 0x00, 0xaa, 0xbd, 0x06, 0x8a, 0x1e, 0xbb, 0x43, 0xc4, 0xbd, + /*acd0:*/ 0x9d, 0xe5, 0x6d, 0x6f, 0xad, 0xf7, 0x87, 0xfd, 0xc4, 0xd4, 0x65, 0x1e, 0xa5, 0xbc, 0x79, 0x88, + /*ace0:*/ 0x01, 0xdb, 0xd9, 0xaa, 0x2c, 0xde, 0x23, 0xfb, 0xee, 0x54, 0x92, 0x24, 0x70, 0x65, 0xd7, 0xbb, + /*acf0:*/ 0xfd, 0x33, 0x1e, 0x61, 0xa5, 0xd6, 0x97, 0x71, 0x1f, 0x9a, 0xf8, 0x72, 0xe1, 0x42, 0x40, 0x16, + /*ad00:*/ 0x73, 0xda, 0x68, 0xca, 0xe0, 0x46, 0xf0, 0xaa, 0x64, 0x0b, 0x8e, 0x0a, 0x36, 0x82, 0xd9, 0x63, + /*ad10:*/ 0x06, 0xc5, 0x84, 0x65, 0xea, 0xd7, 0xd1, 0x29, 0x00, 0xf1, 0xf3, 0x27, 0x7d, 0x1a, 0x7d, 0x42, + /*ad20:*/ 0xc3, 0x80, 0x5f, 0xb8, 0xaf, 0x37, 0x43, 0x96, 0x83, 0x65, 0xff, 0xe0, 0x71, 0x43, 0x83, 0x64, + /*ad30:*/ 0xe7, 0x88, 0x6e, 0xf5, 0x18, 0x92, 0x78, 0xd0, 0x1c, 0xa3, 0x3d, 0x5a, 0x01, 0xd0, 0xb6, 0xf2, + /*ad40:*/ 0xd7, 0x14, 0x28, 0x8c, 0x2c, 0xac, 0xdb, 0x35, 0x3e, 0x26, 0x52, 0x18, 0xfb, 0x5d, 0x07, 0x49, + /*ad50:*/ 0x19, 0x4c, 0x0c, 0x62, 0xab, 0x3b, 0x6c, 0x7b, 0x90, 0x41, 0x47, 0x30, 0xf9, 0x41, 0xe0, 0x59, + /*ad60:*/ 0xc9, 0xeb, 0x0a, 0xa6, 0x23, 0xad, 0x2d, 0xd5, 0x87, 0x20, 0xd4, 0xf9, 0x76, 0x7d, 0xfc, 0xfe, + /*ad70:*/ 0x19, 0x77, 0xef, 0x35, 0xb8, 0xeb, 0xca, 0x15, 0xd1, 0x46, 0xcb, 0x34, 0xef, 0xcf, 0x18, 0x8f, + /*ad80:*/ 0x77, 0xfe, 0x62, 0xb8, 0xa9, 0xcd, 0x47, 0xd7, 0x0c, 0xb6, 0x36, 0xaf, 0xde, 0x5a, 0x1d, 0x55, + /*ad90:*/ 0x76, 0x51, 0x64, 0x77, 0x90, 0x93, 0xab, 0x38, 0xeb, 0x97, 0x73, 0xcc, 0xa7, 0x1b, 0x0d, 0x1f, + /*ada0:*/ 0x8d, 0x77, 0x40, 0xb4, 0x66, 0x85, 0xbc, 0xda, 0x3a, 0xd4, 0xb0, 0x00, 0x5e, 0x9a, 0x97, 0xf1, + /*adb0:*/ 0x94, 0xb3, 0x1c, 0x53, 0x46, 0xf3, 0xbd, 0x4b, 0xa5, 0x92, 0xf1, 0xba, 0xad, 0xbf, 0xdd, 0x83, + /*adc0:*/ 0x45, 0x20, 0x58, 0x52, 0x23, 0xbf, 0x86, 0x9f, 0xe8, 0xb4, 0xef, 0x72, 0x17, 0xae, 0x86, 0x54, + /*add0:*/ 0xba, 0x7e, 0x47, 0x08, 0x21, 0x68, 0x39, 0x5d, 0x8a, 0x4a, 0x19, 0x7e, 0x82, 0x5d, 0xdf, 0x81, + /*ade0:*/ 0x58, 0xfe, 0xe3, 0xd4, 0x99, 0xa8, 0x4b, 0x3e, 0x95, 0xea, 0xba, 0x72, 0x4c, 0x87, 0xfc, 0x8b, + /*adf0:*/ 0x8d, 0x92, 0x0a, 0xbe, 0xe5, 0xdf, 0xa9, 0xbc, 0x55, 0x24, 0x14, 0xcc, 0xb1, 0x74, 0xaa, 0x47, + /*ae00:*/ 0x87, 0x3f, 0x81, 0xe7, 0x5a, 0xd2, 0x38, 0x8c, 0x98, 0x90, 0x71, 0xe1, 0x5f, 0xd7, 0xbb, 0x15, + /*ae10:*/ 0xd0, 0xf7, 0x87, 0xac, 0xe1, 0xd6, 0xec, 0xa5, 0xcf, 0x1c, 0xd4, 0x26, 0xb7, 0x34, 0x01, 0xaf, + /*ae20:*/ 0xf5, 0x27, 0x01, 0xaf, 0xa7, 0xfb, 0xde, 0x81, 0xb3, 0xa7, 0x72, 0x13, 0x0f, 0xbe, 0x73, 0x80, + /*ae30:*/ 0xb5, 0xfc, 0xd7, 0xee, 0xed, 0x32, 0x73, 0xe3, 0x8e, 0x8f, 0x0e, 0x28, 0xa8, 0x20, 0x3a, 0xf7, + /*ae40:*/ 0xbc, 0xe2, 0x2b, 0x87, 0xce, 0x46, 0xb6, 0x75, 0xd8, 0x55, 0x9b, 0x32, 0xbd, 0x30, 0x94, 0x83, + /*ae50:*/ 0x39, 0xfb, 0x28, 0xc9, 0x23, 0xeb, 0x9a, 0x55, 0xc2, 0x40, 0xa6, 0x5a, 0x04, 0xad, 0xab, 0x00, + /*ae60:*/ 0xb3, 0x51, 0xbf, 0x07, 0x9e, 0xbd, 0x44, 0x76, 0x2f, 0x23, 0x26, 0x92, 0x57, 0xdc, 0x92, 0xe8, + /*ae70:*/ 0x50, 0x21, 0xbb, 0x03, 0x6c, 0x23, 0xa1, 0xb4, 0xbd, 0x48, 0x24, 0x8f, 0xfe, 0x9b, 0x3c, 0x67, + /*ae80:*/ 0x32, 0xaf, 0x9e, 0x9a, 0x64, 0x1d, 0xb7, 0xe1, 0x81, 0x76, 0x26, 0x33, 0x3d, 0x6d, 0xbf, 0x80, + /*ae90:*/ 0x14, 0x66, 0xef, 0x49, 0xca, 0x69, 0xe9, 0xdc, 0xb5, 0x4c, 0x94, 0xa8, 0x97, 0x27, 0x5e, 0x1d, + /*aea0:*/ 0x02, 0xe9, 0x8b, 0x07, 0x0e, 0xbb, 0xb4, 0x59, 0x28, 0x68, 0x61, 0xb5, 0x11, 0x23, 0xb4, 0xde, + /*aeb0:*/ 0x83, 0x0c, 0xbf, 0x91, 0xfd, 0xf2, 0x3a, 0x3a, 0xd7, 0xe4, 0xc6, 0x90, 0x95, 0x7d, 0x35, 0x8b, + /*aec0:*/ 0x1a, 0x42, 0xf4, 0xfc, 0x90, 0xe3, 0x1a, 0xe3, 0x5d, 0xd2, 0x0e, 0xcd, 0xbd, 0x18, 0x46, 0x20, + /*aed0:*/ 0x1b, 0x0f, 0x82, 0x79, 0xca, 0x8d, 0xac, 0x92, 0x8e, 0x7b, 0x81, 0xf9, 0xde, 0x7d, 0x9a, 0xa6, + /*aee0:*/ 0x95, 0x31, 0x49, 0x54, 0x28, 0x27, 0x22, 0x04, 0xdf, 0xf2, 0x1a, 0xb7, 0x7f, 0xf0, 0x94, 0x00, + /*aef0:*/ 0x25, 0x16, 0x5c, 0x2a, 0x36, 0x5b, 0xec, 0x7f, 0xd7, 0x79, 0x12, 0x6c, 0x25, 0x25, 0xa6, 0x5c, + /*af00:*/ 0x7c, 0xe8, 0x94, 0x0d, 0x7b, 0xe7, 0x8d, 0x57, 0x60, 0xaf, 0x88, 0xbc, 0xf1, 0x8b, 0xd8, 0x40, + /*af10:*/ 0x62, 0x77, 0xb1, 0xa7, 0x6b, 0xee, 0x26, 0xca, 0x6b, 0x33, 0xa0, 0x92, 0x28, 0x6d, 0x45, 0xf6, + /*af20:*/ 0x6d, 0xd5, 0x3a, 0x9c, 0x7c, 0xc1, 0x1c, 0xe2, 0x46, 0x00, 0x3c, 0xb8, 0x7b, 0xc7, 0x44, 0xd4, + /*af30:*/ 0xa8, 0x82, 0xab, 0x08, 0x11, 0x75, 0x29, 0x08, 0x99, 0xfb, 0x60, 0xed, 0x2b, 0x93, 0xa1, 0x4b, + /*af40:*/ 0x1d, 0x25, 0xee, 0xef, 0x64, 0xb5, 0x5d, 0xa8, 0x9f, 0xcf, 0x5b, 0xc7, 0x2d, 0x7c, 0x69, 0x66, + /*af50:*/ 0xc4, 0x64, 0x13, 0xd8, 0xad, 0x60, 0x57, 0x56, 0x18, 0x09, 0x72, 0x15, 0x43, 0x4c, 0x6b, 0x6d, + /*af60:*/ 0xc1, 0x24, 0x15, 0x4d, 0x7b, 0x0f, 0x8c, 0x46, 0x52, 0xff, 0x6c, 0xfa, 0x3d, 0xb0, 0xfd, 0x3a, + /*af70:*/ 0x72, 0x48, 0x5f, 0x88, 0x39, 0x72, 0x2a, 0x37, 0x1b, 0x95, 0x4e, 0x06, 0xa0, 0x9a, 0xdb, 0x1b, + /*af80:*/ 0x01, 0xcb, 0xc1, 0x98, 0x30, 0xaf, 0xfe, 0xb5, 0x2a, 0xaa, 0xc9, 0xed, 0x80, 0x9e, 0x43, 0xcb, + /*af90:*/ 0x63, 0x52, 0xf8, 0x63, 0xa0, 0x4d, 0x00, 0xa8, 0xc6, 0xf4, 0xfe, 0x47, 0xfc, 0x23, 0xc7, 0xba, + /*afa0:*/ 0x23, 0x81, 0x12, 0x13, 0xe3, 0xe7, 0xea, 0x47, 0xd3, 0x59, 0xb8, 0xcc, 0xb4, 0xb3, 0x8c, 0xcb, + /*afb0:*/ 0xc0, 0x0a, 0x8f, 0x34, 0xe4, 0xd8, 0x0e, 0x6f, 0x1e, 0x08, 0xc4, 0xc6, 0xb9, 0x98, 0x40, 0x16, + /*afc0:*/ 0x60, 0x1d, 0xc1, 0x8e, 0x43, 0xdf, 0xd1, 0x86, 0x04, 0x6e, 0x50, 0xc0, 0xe9, 0x99, 0x1d, 0x55, + /*afd0:*/ 0x9b, 0x2f, 0xdf, 0x0b, 0x6a, 0xcc, 0x9f, 0x54, 0xdf, 0x8a, 0x75, 0xaa, 0x3d, 0x7f, 0xf8, 0x49, + /*afe0:*/ 0x4b, 0x91, 0x58, 0x67, 0x32, 0x61, 0xae, 0x0a, 0x5c, 0x81, 0x05, 0x49, 0x2c, 0x90, 0x62, 0xdb, + /*aff0:*/ 0x79, 0x55, 0xa3, 0xb5, 0x6a, 0x74, 0x24, 0x81, 0x24, 0xa0, 0xcf, 0x14, 0xe3, 0x0a, 0xf0, 0xdd, + /*b000:*/ 0x23, 0x98, 0xfc, 0x13, 0x94, 0xe0, 0x73, 0xc2, 0x44, 0x25, 0x79, 0x88, 0x6c, 0xe8, 0xb4, 0x5e, + /*b010:*/ 0x57, 0xcf, 0xd3, 0x3b, 0xa1, 0x81, 0xbf, 0xa7, 0x96, 0xd3, 0x06, 0xfe, 0xa9, 0x4e, 0xe7, 0x0f, + /*b020:*/ 0x26, 0x4a, 0x73, 0x60, 0x4c, 0x95, 0x0e, 0xf3, 0x75, 0x29, 0x63, 0x50, 0x54, 0xbb, 0xc0, 0x88, + /*b030:*/ 0x55, 0x7e, 0xf0, 0x09, 0x14, 0x7a, 0xdb, 0x31, 0x76, 0xfa, 0x86, 0x28, 0xf2, 0x2a, 0x01, 0xcb, + /*b040:*/ 0x21, 0xa3, 0x39, 0xa1, 0x26, 0xb7, 0x5d, 0x54, 0xae, 0x2b, 0xe6, 0xd7, 0x7d, 0xb3, 0x8f, 0x8a, + /*b050:*/ 0x0e, 0x8e, 0x12, 0x31, 0x8e, 0x75, 0x7e, 0x66, 0xa0, 0xfe, 0x66, 0x90, 0xde, 0x47, 0x00, 0xa6, + /*b060:*/ 0x14, 0xa3, 0x49, 0xe7, 0xe3, 0xd0, 0xdc, 0x99, 0xbc, 0x64, 0xaf, 0xd7, 0xdc, 0x73, 0x36, 0x05, + /*b070:*/ 0x13, 0xd7, 0xac, 0xd5, 0x55, 0x6a, 0xda, 0xb0, 0x10, 0xe6, 0x6b, 0x17, 0xe9, 0xf1, 0x80, 0x19, + /*b080:*/ 0xcf, 0xfb, 0x15, 0x61, 0xf6, 0x3b, 0xa3, 0xc2, 0x21, 0x63, 0xe0, 0xb0, 0x89, 0xe4, 0xd2, 0xf8, + /*b090:*/ 0xc8, 0x14, 0x1a, 0xb5, 0xfa, 0x1f, 0x83, 0xd7, 0x9c, 0x5b, 0x3c, 0x5c, 0x28, 0x62, 0x5e, 0x56, + /*b0a0:*/ 0x7d, 0x17, 0x5f, 0x8e, 0xd3, 0x6c, 0x17, 0xa4, 0xd7, 0xde, 0xb8, 0xf3, 0xbb, 0x27, 0x45, 0x74, + /*b0b0:*/ 0x24, 0x50, 0x6a, 0x4c, 0xf0, 0xf6, 0xe6, 0x47, 0x23, 0x77, 0x41, 0x1c, 0xcc, 0x0b, 0x24, 0xe2, + /*b0c0:*/ 0x09, 0x99, 0x72, 0x69, 0x5f, 0x9b, 0x88, 0x45, 0x4b, 0x29, 0x79, 0x98, 0xb2, 0x51, 0xbf, 0x14, + /*b0d0:*/ 0x27, 0x74, 0xa9, 0x98, 0x98, 0x1d, 0x34, 0xd3, 0x1c, 0x86, 0xf5, 0x00, 0xa9, 0x46, 0x1e, 0xd9, + /*b0e0:*/ 0x76, 0x27, 0xe7, 0x05, 0x47, 0xe8, 0x2f, 0xe0, 0x75, 0x15, 0x79, 0x29, 0x6a, 0xca, 0xed, 0xf5, + /*b0f0:*/ 0xf9, 0xca, 0x2d, 0x1d, 0x92, 0x6f, 0xcb, 0xd4, 0xec, 0x9a, 0x79, 0xa4, 0x3a, 0xb6, 0x7b, 0x38, + /*b100:*/ 0x53, 0x59, 0x02, 0x02, 0x00, 0x3f, 0x03, 0x1e, 0x05, 0x0e, 0x89, 0x00, 0x01, 0x01, 0xff, 0x0a, + /*b110:*/ 0x1f, 0x03, 0xff, 0x04, 0x1e, 0x06, 0x2d, 0x72, 0x0f, 0x7b, 0x02, 0x01, 0x31, 0xff, 0x31, 0xff, + /*b120:*/ 0x78, 0x43, 0xfd, 0x43, 0x84, 0xe4, 0x6c, 0xe8, 0x00, 0x70, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x04, + /*b130:*/ 0x0c, 0x32, 0x70, 0x17, 0x0a, 0x0a, 0x05, 0x80, 0x0c, 0x46, 0x00, 0x80, 0x0c, 0x5a, 0x00, 0x28, + /*b140:*/ 0x0a, 0x8c, 0x00, 0xb8, 0x0b, 0x96, 0x00, 0x1e, 0x1e, 0x64, 0x00, 0xf4, 0x01, 0x14, 0x0a, 0x04, + /*b150:*/ 0x29, 0x1a, 0x0a, 0x64, 0x03, 0x66, 0x64, 0xc0, 0x20, 0x02, 0x87, 0x00, 0x80, 0x02, 0x0e, 0x1f, + /*b160:*/ 0x01, 0x2a, 0x00, 0x20, 0x0a, 0x1b, 0x00, 0x80, 0x0a, 0xa8, 0xa0, 0x80, 0x88, 0x88, 0x88, 0x68, + /*b170:*/ 0x68, 0x2e, 0x2d, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x25, 0x01, 0x04, 0x07, 0x09, 0x0b, 0x0d, 0x0f, + /*b180:*/ 0x13, 0x00, 0xe8, 0x03, 0x00, 0x14, 0x00, 0xe8, 0x03, 0x9a, 0x64, 0xda, 0xb8, 0x0b, 0x00, 0xc0, + /*b190:*/ 0x80, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + /*b1a0:*/ 0x10, 0x5a, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d, 0x39, 0x00, 0x1e, 0x00, 0x10, 0x0a, 0x17, 0x00, + /*b1b0:*/ 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x30, 0x04, 0x20, 0x40, 0x03, 0x04, 0x03, 0x00, + /*b1c0:*/ 0x1d, 0x2b, 0x1d, 0x2c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x7d, 0x51, 0x51, 0x51, 0xcd, + /*b1d0:*/ 0x0d, 0x04, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + /*b1e0:*/ 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + /*b1f0:*/ 0x1d, 0x1e, 0x1f, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x29, 0x2a, 0x2b, 0x2c, 0xff, 0xff, + /*b200:*/ 0xff, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x14, 0x12, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, + /*b210:*/ 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x1d, 0xff, 0xff, 0xff, 0x00, + /*b220:*/ 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /*b230:*/ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /*b240:*/ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /*b250:*/ 0x80, 0x80, 0x80, 0x80, 0x80, 0x66, 0x66, 0x6d, 0x6d, 0x73, 0x73, 0x7a, 0x7a, 0x80, 0x80, 0x86, + /*b260:*/ 0x86, 0x8d, 0x8d, 0x93, 0x93, 0x9a, 0x9a, 0xa0, 0xa0, 0xa6, 0xa6, 0xad, 0xad, 0xb3, 0xb3, 0x80, + /*b270:*/ 0x80, 0x80, 0x80, 0x04, 0x02, 0xff, 0x08, 0xff, 0xff, 0x03, 0x1c, 0x43, 0x80, 0x08, 0x10, 0x0a, + /*b280:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b290:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b2f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x5d, 0xdc, 0x9d, + /*b300:*/ 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b310:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b320:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b330:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b340:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b350:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b360:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b370:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b380:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b390:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b3f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b400:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b410:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b420:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b430:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b440:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b450:*/ 0x04, 0x3f, 0x03, 0x1e, 0x05, 0x0e, 0x08, 0x00, 0x19, 0x19, 0x00, 0x10, 0xe2, 0x04, 0xb6, 0x08, + /*b460:*/ 0x1e, 0x05, 0x28, 0xf5, 0x28, 0x1e, 0x05, 0x01, 0x30, 0x00, 0x30, 0x00, 0x00, 0x50, 0x00, 0x50, + /*b470:*/ 0xf0, 0xd2, 0xf0, 0xd2, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x04, 0xc0, 0x0f, 0x49, 0x00, + /*b480:*/ 0x00, 0x00, 0x85, 0x03, 0x2e, 0x1e, 0x0a, 0x64, 0x07, 0x00, 0x00, 0x56, 0x35, 0x05, 0x10, 0x00, + /*b490:*/ 0x00, 0x0b, 0x20, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, + /*b4a0:*/ 0x37, 0x33, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x03, 0x0f, 0x00, 0x03, 0x00, 0x00, + /*b4b0:*/ 0x00, 0xf0, 0x15, 0x1e, 0x2e, 0x4c, 0x40, 0xff, 0x4b, 0x20, 0x0c, 0x18, 0x09, 0x04, 0x00, 0x00, + /*b4c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b4d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x8a, 0x56, + /*b4e0:*/ 0x15, 0x21, 0x11, 0x94, 0x89, 0x50, 0x13, 0x01, 0x01, 0x8b, 0x00, 0x4c, 0x00, 0x01, 0x34, 0x00, + /*b4f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b500:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5e, 0x01, 0x80, + /*b510:*/ 0x03, 0x0e, 0x1f, 0x00, 0xde, 0x01, 0x19, 0x04, 0x1b, 0x00, 0x10, 0x0a, 0xc0, 0x00, 0x00, 0x00, + /*b520:*/ 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b530:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, + /*b540:*/ 0xff, 0x00, 0xc0, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + /*b550:*/ 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x10, + /*b560:*/ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x04, 0x40, 0x40, 0x03, + /*b570:*/ 0x00, 0x2e, 0x1e, 0x44, 0x00, 0x19, 0x01, 0x01, 0xbe, 0x00, 0xde, 0x3d, 0x90, 0x80, 0x08, 0x03, + /*b580:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b590:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b5e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x70, 0x0b, 0x00, 0x01, 0x54, 0x00, + /*b5f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b600:*/ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x51, 0x51, + /*b610:*/ 0x51, 0x51, 0x51, 0xcd, 0x0d, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x04, 0xff, 0x2e, + /*b620:*/ 0x1e, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b630:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b640:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b650:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b660:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b670:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b680:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b690:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b6e0:*/ 0x00, 0x00, 0x00, 0x1f, 0x1c, 0x16, 0x00, 0x01, 0x55, 0x1d, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x00, + /*b6f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b700:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b710:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b720:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0xff, 0xff, 0x03, 0x32, + /*b730:*/ 0x00, 0x80, 0x08, 0x10, 0x0a, 0x04, 0x28, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b740:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b750:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b760:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b770:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b780:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b790:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7a0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7b0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7c0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7d0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b7e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x28, 0x00, 0x00, 0x51, 0x00, + /*b7f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*b800:*/ 0xff}; +#else const char *rmi_config_ver = "N80XX_SY_0518"; const u8 rmi_fw[] = { @@ -2917,4 +11765,5 @@ const u8 rmi_fw[] = { /*b5e0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xb4, 0x0b, 0x00, 0x01, 0x54, 0x00, /*b5f0:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*b600:*/ 0xff}; -#endif /* __RMI_FW_H */ \ No newline at end of file + #endif + #endif /* __RMI_FW_H */ diff --git a/drivers/input/touchscreen/synaptics_fw_updater.c b/drivers/input/touchscreen/synaptics_fw_updater.c index 1a15fdc..2b8293f 100644 --- a/drivers/input/touchscreen/synaptics_fw_updater.c +++ b/drivers/input/touchscreen/synaptics_fw_updater.c @@ -399,39 +399,79 @@ int synaptics_fw_updater(struct synaptics_drv_data *data, u8 *fw_data) { struct synaptics_ts_fw_block *fw; int irq = gpio_to_irq(data->gpio); - bool update = true; + bool update = false; fw = kzalloc(sizeof(struct synaptics_ts_fw_block), GFP_KERNEL); data->fw = fw; if (NULL == fw_data) { - u8 *buf, *fw_version; - buf = kzalloc(4, GFP_KERNEL); - fw_version = kzalloc(4, GFP_KERNEL); + u8 buf[5] = {0, }; +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + if (data->pdata->support_extend_button) { + fw->fw_data = (u8 *)rmi_fw_button; + + /* set firmware data */ + data->firm_version[0] = rmi_fw_button[0xb100]; + data->firm_version[1] = rmi_fw_button[0xb101]; + data->firm_version[2] = rmi_fw_button[0xb102]; + data->firm_version[3] = rmi_fw_button[0xb103]; + data->firm_version[4] = '\0'; + + strncpy(data->firm_config, rmi_config_ver_button, + sizeof(data->firm_config)); + } else { + fw->fw_data = (u8 *)rmi_fw; + + data->firm_version[0] = rmi_fw[0xb100]; + data->firm_version[1] = rmi_fw[0xb101]; + data->firm_version[2] = rmi_fw[0xb102]; + data->firm_version[3] = rmi_fw[0xb103]; + data->firm_version[4] = '\0'; + + strncpy(data->firm_config, rmi_config_ver, + sizeof(data->firm_config)); + } +#else fw->fw_data = (u8 *)rmi_fw; - strncpy(fw_version, &rmi_fw[0xb100], - sizeof(fw_version)); - strncpy(data->firm_version, fw_version, - sizeof(data->firm_version)); + + data->firm_version[0] = rmi_fw[0xb100]; + data->firm_version[1] = rmi_fw[0xb101]; + data->firm_version[2] = rmi_fw[0xb102]; + data->firm_version[3] = rmi_fw[0xb103]; + data->firm_version[4] = '\0'; + strncpy(data->firm_config, rmi_config_ver, sizeof(data->firm_config)); - synaptics_ts_read_block(data, +#endif + if (synaptics_ts_read_block(data, data->f34.control_base_addr, - buf, 4); - - printk(KERN_DEBUG "[TSP] IC FW. : [%s], new FW. : [%s]\n", - buf, fw_version); - - if (strncmp((char *)fw_version, (char *)buf, 4) == 0) - update = false; - - kfree(buf); - kfree(fw_version); - - } else + buf, 4) > 0) + printk(KERN_DEBUG "[TSP] block read success!\n"); + else + printk(KERN_DEBUG "[TSP] block read failed!\n"); + + printk(KERN_DEBUG "[TSP] IC FW. : [%c%c%.2d%.2d00], new FW. : [%c%c%.2d%.2d00]\n", + buf[0],buf[1],buf[2],buf[3], + data->firm_version[0],data->firm_version[1], + data->firm_version[2],data->firm_version[3]); + + /* update firm > tsp */ + /* + if (strcmp(data->firm_version, buf) > 0) { + printk(KERN_DEBUG "[TSP] update!\n"); + update = true; + } + */ + /* update if firm != tsp */ + if (strncmp(data->firm_version, buf, 4) != 0) + update = true; + } else { fw->fw_data = fw_data; - + update = true; + } + if (update) { + printk(KERN_DEBUG "[TSP] tsp update!!\n"); disable_irq(irq); wake_lock(&data->wakelock); synaptics_fw_initialize(data); @@ -463,6 +503,13 @@ int synaptics_fw_updater(struct synaptics_drv_data *data, u8 *fw_data) void forced_fw_update(struct synaptics_drv_data *data) { +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + if (data->pdata->support_extend_button) + synaptics_fw_updater(data, (u8 *)rmi_fw_button); + else + synaptics_fw_updater(data, (u8 *)rmi_fw); +#else synaptics_fw_updater(data, (u8 *)rmi_fw); +#endif } diff --git a/drivers/input/touchscreen/synaptics_s7301.c b/drivers/input/touchscreen/synaptics_s7301.c index bd2bf8f..fb152e1 100644 --- a/drivers/input/touchscreen/synaptics_s7301.c +++ b/drivers/input/touchscreen/synaptics_s7301.c @@ -15,6 +15,14 @@ #include +#define REPORT_MT_NOZ(x, y, w_max, w_min) \ +do { \ + input_report_abs(data->input, ABS_MT_POSITION_X, x); \ + input_report_abs(data->input, ABS_MT_POSITION_Y, y); \ + input_report_abs(data->input, ABS_MT_TOUCH_MAJOR, w_max); \ + input_report_abs(data->input, ABS_MT_TOUCH_MINOR, w_min); \ +} while (0) + #define REPORT_MT(x, y, z, w_max, w_min) \ do { \ input_report_abs(data->input, ABS_MT_POSITION_X, x); \ @@ -185,6 +193,29 @@ void set_dvfs_lock(struct synaptics_drv_data *data, bool en) } #endif /* CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK */ +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) +static void forced_release_buttons(struct synaptics_drv_data *data) +{ + int i; +#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP) + printk(KERN_DEBUG "[TSP] %s\n", __func__); +#endif + if (data->pdata->support_extend_button) { + for (i = 0; i < data->pdata->extend_button_map->nbuttons; i++) { + input_report_key(data->input, + data->pdata->extend_button_map->map[i], + 0); + } + } else { + for (i = 0; i < data->pdata->button_map->nbuttons; i++) { + input_report_key(data->input, + data->pdata->button_map->map[i], 0); + } + } + input_sync(data->input); +} +#endif + static void forced_release_fingers(struct synaptics_drv_data *data) { int i; @@ -200,6 +231,9 @@ static void forced_release_fingers(struct synaptics_drv_data *data) data->finger[i].z = 0; } input_sync(data->input); +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + forced_release_buttons(data); +#endif set_dvfs_lock(data, false); return ; } @@ -212,9 +246,9 @@ static int synaptics_ts_set_func_info(struct synaptics_drv_data *data) u16 base_addr = FUNC_ADDR_FIRST; u16 last_addr = FUNC_ADDR_LAST; - for (i = 0; i <= PAGE_MAX; i += PAGE_MAX) { - base_addr += i; - last_addr += i; + for (i = 0; i <= PAGE_MAX; i += NEXT_PAGE) { + base_addr = i + FUNC_ADDR_FIRST; + last_addr = i + FUNC_ADDR_LAST; for (addr = base_addr; addr >= last_addr; addr -= FUNC_ADDR_SIZE) { synaptics_ts_read_block(data, @@ -245,6 +279,12 @@ static int synaptics_ts_set_func_info(struct synaptics_drv_data *data) SET_FUNC_ADDR(11, i); break; +#if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + case 0x1a: + SET_FUNC_ADDR(1a, i); + break; +#endif + case 0x34: SET_FUNC_ADDR(34, i); break; @@ -253,12 +293,26 @@ static int synaptics_ts_set_func_info(struct synaptics_drv_data *data) SET_FUNC_ADDR(54, i); break; +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + case 0x51: + SET_FUNC_ADDR(51, i); + break; +#endif + default: break; } } } - return cnt; +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + cnt--; +#endif + +#if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + return (5 != cnt); +#else + return (4 != cnt); +#endif } static int synaptics_ts_read_dummy(struct synaptics_drv_data *data) @@ -314,17 +368,43 @@ static void inform_charger_connection(struct charger_callbacks *cb, int mode) struct synaptics_drv_data, callbacks); data->charger_connection = !!mode; - if (data->ready) + if (data->ready) { +#if !defined(CONFIG_MACH_KONA) set_charger_connection_bit(data); +#endif + } } +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) +static void set_palm_threshold(struct synaptics_drv_data *data) +{ + u8 threshold = data->pdata->palm_threshold; + + synaptics_ts_write_data(data, + data->f11.control_base_addr + 17, threshold); +} +#endif + static int synaptics_ts_set_func(struct synaptics_drv_data *data) { int i = 0; - + int retry_count = 10; + int ret = 0; + printk(KERN_DEBUG "[TSP] %s\n", __func__); - - if (synaptics_ts_set_func_info(data) != 4) { + + while(retry_count--) { + ret = synaptics_ts_set_func_info(data); + + if (ret) { + pr_err("[TSP] failed to get function info retry_count = %d \n",retry_count); + continue; + } else { + break; + } + } + + if (ret) { pr_err("[TSP] failed to get function info.\n"); forced_fw_update(data); synaptics_ts_set_func_info(data); @@ -340,40 +420,159 @@ static int synaptics_ts_set_func(struct synaptics_drv_data *data) return synaptics_ts_read_dummy(data); } +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) +static void synaptics_ts_check_buttons(struct synaptics_drv_data *data) +{ + int ret = 0, i, pos_button = 1; + u16 touch_key_addr = data->f1a.data_base_addr; + u8 touch_key_data; + u8 check_mask_data; + + ret = synaptics_ts_read_block(data, + touch_key_addr, &touch_key_data, 1); + + if (ret < 0) { + pr_err("[TSP] failed to read button data\n"); + return ; + } + +#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP) + printk(KERN_DEBUG "[TSP] button [0x%x]\n", touch_key_data); +#endif + + if (data->pdata->support_extend_button) { + if (data->pdata->enable_extend_button_event) { + for (i = 0; i < data->pdata->extend_button_map->nbuttons; i++) { + if ((touch_key_data & (pos_button<input, + data->pdata->extend_button_map->map[i], + 1); + } else { + input_report_key(data->input, + data->pdata->extend_button_map->map[i], + 0); + } + input_sync(data->input); + } + } else { + /* check mask data and return */ + check_mask_data = touch_key_data & + data->pdata->extend_button_map->button_mask; + + if (check_mask_data != 0) { + printk(KERN_DEBUG "[TSP] igb\n"); + return; + } + + for (i = 0; i < data->pdata->extend_button_map->nbuttons; i++) { + if ((data->pdata->extend_button_map->button_mask & (pos_button<input, + data->pdata->extend_button_map->map[i], + 1); + printk(KERN_DEBUG "[TSP] b[%d][%c]\n", i, 'p'); + } else { + input_report_key(data->input, + data->pdata->extend_button_map->map[i], + 0); + printk(KERN_DEBUG "[TSP] b[%d][%c]\n", i, 'r'); + } + input_sync(data->input); + } + } + } else { + for (i = 0; i < data->pdata->button_map->nbuttons; i++) { + if ((touch_key_data & (pos_button<input, + data->pdata->button_map->map[i], 1); + else + input_report_key(data->input, + data->pdata->button_map->map[i], 0); + input_sync(data->input); + } + } +} +#endif + static int check_interrupt_status(struct synaptics_drv_data *data, u32 *finger_status) { int ret = 0; u8 buf[3]; + u8 tmp; u16 addr = 0; + int analog_int = 0; /* read the interrupt status */ addr = data->f01.data_base_addr + 1; ret = synaptics_ts_read_data(data, - addr, buf); + addr, &tmp); if (ret < 0) { pr_err("[TSP] failed to read i2c data(%d)\n", __LINE__); return -EIO; } - /* read the finger states */ - addr = data->f11.data_base_addr; - ret = synaptics_ts_read_block(data, - addr, buf, 3); - if (ret < 0) { - pr_err("[TSP] failed to read i2c data(%d)\n", __LINE__); - return -EIO; +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + /* check button */ + if ((tmp & 0x10) != 0) { + synaptics_ts_check_buttons(data); } +#endif - *finger_status = (u32) (buf[0] | (buf[1] << 8) | - ((buf[2] & 0xf) << 16)); + /* check analog interrupt */ + if (tmp & 0x4) + analog_int = 1; - if (data->debug) - printk(KERN_DEBUG - "[TSP] finger_status : 0x%x\n", - *finger_status); +#if defined(CONFIG_MACH_KONA) + /* check interrupt status register */ + if ((tmp & 0x0F) == 0x2) { + addr = data->f01.data_base_addr; + /* check esd status register */ + ret = synaptics_ts_read_data(data, + addr, &tmp); + if (ret < 0) { + pr_err("[TSP] failed to read i2c data(%d)\n", __LINE__); + return -EIO; + } else if ((tmp & 0x3) == 0x3) { + pr_err("[TSP] esd detect\n"); + forced_release_fingers(data); + data->pdata->hw_reset(); + return 0; + } + } +#else + /* esd detect */ + if ((tmp & 0x0F) == 0x03) { + pr_err("[TSP] esd detect\n"); + data->pdata->hw_reset(); + return 0; + } +#endif - return 0; + if (analog_int) { + /* read the finger states */ + addr = data->f11.data_base_addr; + ret = synaptics_ts_read_block(data, + addr, buf, 3); + if (ret < 0) { + pr_err("[TSP] failed to read i2c data(%d)\n", __LINE__); + return -EIO; + } + + *finger_status = (u32) (buf[0] | (buf[1] << 8) | + ((buf[2] & 0xf) << 16)); + + if (data->debug) + printk(KERN_DEBUG + "[TSP] finger_status : [%d] 0x%x\n", analog_int, + *finger_status); + } + if (analog_int == 1) + return 1; + else + return 0; } static void synaptics_ts_read_points(struct synaptics_drv_data *data, @@ -383,10 +582,33 @@ static void synaptics_ts_read_points(struct synaptics_drv_data *data, bool finger_pressed = false; int ret = 0; int id = 0; +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + u8 palm; + u8 surface_data[4]; + u16 palm_addr = data->f11.data_base_addr + 53; + u16 surface_addr = data->f51.data_base_addr; + int angle = 0; +#endif u16 addr = data->f11.data_base_addr + 3; + u16 x = 0, y = 0; + +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + ret = synaptics_ts_read_block(data, + palm_addr, &palm, 1); + if (ret < 0) { + pr_err("[TSP] failed to read palm data\n"); + return ; + } + + palm = (palm & 0x02) ? 1 : 0; +#endif for (id = 0; id < MAX_TOUCH_NUM; id++, addr += sizeof(struct finger_data)) { +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND) + if ((finger_status & (0x3 << (id * 2))) == 0x3) + continue; +#endif if (finger_status & (0x3 << (id * 2))) { ret = synaptics_ts_read_block(data, addr, (u8 *) &buf, 5); @@ -394,6 +616,15 @@ static void synaptics_ts_read_points(struct synaptics_drv_data *data, pr_err("[TSP] failed to read finger[%u]\n", id); return ; } +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + ret = synaptics_ts_read_block(data, + surface_addr + (id * 4), + surface_data, 4); + if (ret < 0) { + pr_err("[TSP] failed to read surface data\n"); + return ; + } +#endif #if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP) if (data->debug) @@ -405,13 +636,47 @@ static void synaptics_ts_read_points(struct synaptics_drv_data *data, buf.z); #endif - data->finger[id].x = - (buf.x_msb << 4) + - (buf.xy_lsb & 0x0F); - data->finger[id].y = - (buf.y_msb << 4) + - (buf.xy_lsb >> 4); + x = (buf.x_msb << 4) + (buf.xy_lsb & 0x0F); + y = (buf.y_msb << 4) + (buf.xy_lsb >> 4); + + if (data->pdata->swap_xy) + swap(x, y); + + if (data->pdata->invert_x) + x = data->pdata->max_x - x; + + if (data->pdata->invert_y) + y = data->pdata->max_y - y; + data->finger[id].x = x; + data->finger[id].y = y; + +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + data->finger[id].w_max = surface_data[2]; + data->finger[id].w_min = surface_data[3]; + if (data->pdata->support_extend_button) { + if (surface_data[1] >= 90 && surface_data[1] <= 180) + angle = surface_data[1] - 90; + else if (surface_data[1] < 90) + angle = -(90 - surface_data[1]); + else + printk(KERN_DEBUG "[TSP] wrong TSP angle data [%d][%d]\n", id, + surface_data[1]); + } else { + if (surface_data[1] <= 90) + angle = surface_data[1]; + else if (surface_data[1] > 168 && surface_data[1] < 256) + angle = -(256 - surface_data[1]); + else + printk(KERN_DEBUG "[TSP] wrong TSP angle data [%d][%d]\n", id, + surface_data[1]); + } + + if (data->finger[id].w_max < + data->finger[id].w_min) + swap(data->finger[id].w_max, + data->finger[id].w_min); +#else if ((buf.w >> 4) > (buf.w & 0x0F)) { data->finger[id].w_max = @@ -424,7 +689,12 @@ static void synaptics_ts_read_points(struct synaptics_drv_data *data, data->finger[id].w_max = (buf.w & 0x0F); } - +#endif +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + data->finger[id].angle = angle; + data->finger[id].width = surface_data[0]; +#endif + data->finger[id].z = buf.z; if (data->finger[id].z) { if (MT_STATUS_INACTIVE == @@ -438,19 +708,35 @@ static void synaptics_ts_read_points(struct synaptics_drv_data *data, data->finger[id].x, data->finger[id].y, data->finger[id].z); +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + printk(KERN_DEBUG + "[TSP] palm %d, surface_data %d, %d\n", + palm, + surface_data[0], + surface_data[1]); +#endif #else printk(KERN_DEBUG "s7301 %d P\n", id); #endif } #if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP) - else if (data->debug) + else if (data->debug) { printk(KERN_DEBUG "[TSP] ID: %d, x: %d, y: %d, z: %d\n", id, data->finger[id].x, data->finger[id].y, data->finger[id].z); +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + printk(KERN_DEBUG + "[TSP] palm %d, surface_data %d, %d, %d\n", + palm, + surface_data[0], + surface_data[1], + angle); +#endif + } #endif } } else if (MT_STATUS_PRESS == data->finger[id].status) { @@ -464,7 +750,29 @@ static void synaptics_ts_read_points(struct synaptics_drv_data *data, } } +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + if (palm) { + if (data->palm_flag == 3) + data->palm_flag = 1; + else { + data->palm_flag = 3; + palm = 3; + } + } else { + if (data->palm_flag == 2) + data->palm_flag = 0; + else { + data->palm_flag = 2; + palm = 2; + } + } +#endif + for (id = 0; id < MAX_TOUCH_NUM; ++id) { +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND) + if ((finger_status & (0x3 << (id * 2))) == 0x3) + continue; +#endif if (MT_STATUS_INACTIVE == data->finger[id].status) continue; @@ -477,12 +785,30 @@ static void synaptics_ts_read_points(struct synaptics_drv_data *data, case MT_STATUS_PRESS: case MT_STATUS_MOVE: finger_pressed = true; +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND) + if (0 == !!data->finger[id].z) + break; + + REPORT_MT_NOZ( + data->finger[id].x, + data->finger[id].y, + data->finger[id].w_max, + data->finger[id].w_min); +#else REPORT_MT( data->finger[id].x, data->finger[id].y, data->finger[id].z, data->finger[id].w_max, data->finger[id].w_min); +#endif +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + input_report_abs(data->input, ABS_MT_WIDTH_MAJOR, + data->finger[id].width); + input_report_abs(data->input, ABS_MT_ANGLE, + data->finger[id].angle); + input_report_abs(data->input, ABS_MT_PALM, palm); +#endif break; case MT_STATUS_RELEASE: @@ -496,11 +822,17 @@ static void synaptics_ts_read_points(struct synaptics_drv_data *data, set_dvfs_lock(data, finger_pressed); } +#if 0 +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + synaptics_ts_check_buttons(data); +#endif +#endif + static irqreturn_t synaptics_ts_irq_handler(int irq, void *_data) { struct synaptics_drv_data *data = (struct synaptics_drv_data *)_data; u32 finger_status = 0; - if (!check_interrupt_status(data, &finger_status)) + if (check_interrupt_status(data, &finger_status) == 1) synaptics_ts_read_points(data, finger_status); return IRQ_HANDLED; } @@ -510,6 +842,13 @@ static void synaptics_ts_early_suspend(struct early_suspend *h) { struct synaptics_drv_data *data = container_of(h, struct synaptics_drv_data, early_suspend); +#if defined(CONFIG_MACH_KONA) + disable_irq(data->client->irq); + forced_release_fingers(data); + if (!wake_lock_active(&data->wakelock)) { + data->pdata->set_power(0); + } +#else printk(KERN_DEBUG "[TSP] %s\n", __func__); cancel_delayed_work_sync(&data->resume_dwork); mutex_lock(&data->mutex); @@ -522,6 +861,7 @@ static void synaptics_ts_early_suspend(struct early_suspend *h) } } mutex_unlock(&data->mutex); +#endif } static void synaptics_ts_late_resume(struct early_suspend *h) @@ -531,11 +871,20 @@ static void synaptics_ts_late_resume(struct early_suspend *h) printk(KERN_DEBUG "[TSP] %s\n", __func__); +#if defined(CONFIG_MACH_KONA) + /* turned on tsp power */ + data->pdata->set_power(1); + + mdelay(200); + enable_irq(data->client->irq); +#else if (data->suspend) { if (data->pdata->set_power(1)) data->pdata->hw_reset(); } + schedule_delayed_work(&data->resume_dwork, HZ / 10); +#endif } #endif @@ -572,7 +921,12 @@ static void init_function_data_dwork(struct work_struct *work) #endif data->ready = true; +#if !defined(CONFIG_MACH_KONA) set_charger_connection_bit(data); +#endif +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + set_palm_threshold(data); +#endif if (data->client->irq) { ret = request_threaded_irq(data->client->irq, NULL, @@ -602,8 +956,10 @@ static void synaptics_ts_resume_dwork(struct work_struct *work) mutex_lock(&data->mutex); if (data->suspend) { data->suspend = false; +#if !defined(CONFIG_MACH_KONA) set_charger_connection_bit(data); synaptics_ts_drawing_mode(data); +#endif synaptics_ts_read_dummy(data); enable_irq(data->client->irq); } @@ -619,6 +975,19 @@ static void synaptics_ts_noti_dwork(struct work_struct *work) set_charger_connection_bit(data); } +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND) +static void synaptics_reset_ts_dwork(struct work_struct *work) +{ + struct synaptics_drv_data *data = + container_of(work, struct synaptics_drv_data, + reset_dwork.work); + + if (data->firmware_update_check != true) { + data->pdata->hw_reset(); + } +} +#endif + static int synaptics_ts_open(struct input_dev *dev) { struct synaptics_drv_data *data = @@ -671,6 +1040,11 @@ static int __init synaptics_ts_probe(struct i2c_client *client, ddata->gpio = pdata->gpio_attn; ddata->x_line = pdata->x_line; ddata->y_line = pdata->y_line; +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + ddata->palm_flag = 0; +#endif + if (pdata->swap_xy) + swap(pdata->x_line, pdata->y_line); /* Register callbacks */ /* To inform tsp , charger connection status*/ @@ -702,18 +1076,48 @@ static int __init synaptics_ts_probe(struct i2c_client *client, __set_bit(EV_KEY, input->evbit); __set_bit(MT_TOOL_FINGER, input->keybit); __set_bit(INPUT_PROP_DIRECT, input->propbit); + +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED) + if (pdata->led_event) { + __set_bit(EV_LED, input->evbit); + __set_bit(LED_MISC, input->ledbit); + } +#endif input_mt_init_slots(input, MAX_TOUCH_NUM); input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->max_x, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->max_y, 0, 0); +#if !defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND) input_set_abs_params(input, ABS_MT_PRESSURE, 0, - pdata->max_pressure, 0, 0); + pdata->max_pressure, 0, 0); +#endif input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, pdata->max_width, 0, 0); input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, pdata->max_width, 0, 0); +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, + pdata->x_line * pdata->y_line, 0, 0); + input_set_abs_params(input, ABS_MT_ANGLE, + MIN_ANGLE, MAX_ANGLE, 0, 0); + input_set_abs_params(input, ABS_MT_PALM, + 0, 1, 0, 0); +#endif +#if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + if (pdata->support_extend_button) { + for (ret = 0; ret < pdata->extend_button_map->nbuttons; ret++) { + if (pdata->extend_button_map->map[ret] != KEY_RESERVED) + input_set_capability(input, EV_KEY, + pdata->extend_button_map->map[ret]); + } + } else { + for (ret = 0; ret < pdata->button_map->nbuttons; ret++) + input_set_capability(input, EV_KEY, + pdata->button_map->map[ret]); + } +#endif ret = input_register_device(input); if (ret) { @@ -727,8 +1131,16 @@ static int __init synaptics_ts_probe(struct i2c_client *client, INIT_DELAYED_WORK(&ddata->init_dwork, init_function_data_dwork); INIT_DELAYED_WORK(&ddata->resume_dwork, synaptics_ts_resume_dwork); +#if !defined(CONFIG_MACH_KONA) INIT_DELAYED_WORK(&ddata->noti_dwork, synaptics_ts_noti_dwork); +#endif schedule_delayed_work(&ddata->init_dwork, HZ); + +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_WORKAROUND) + pdata->hw_reset(); +// INIT_DELAYED_WORK(&ddata->reset_dwork, synaptics_reset_ts_dwork); +// schedule_delayed_work(&ddata->reset_dwork, HZ*10); +#endif ret = set_tsp_sysfs(ddata); if (ret) { diff --git a/drivers/input/touchscreen/synaptics_sysfs.c b/drivers/input/touchscreen/synaptics_sysfs.c index 510bc98..be82954 100644 --- a/drivers/input/touchscreen/synaptics_sysfs.c +++ b/drivers/input/touchscreen/synaptics_sysfs.c @@ -18,6 +18,10 @@ #include #include "synaptics_sysfs.h" +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED) +struct device *synaptics_with_gpio_led_device; +#endif + const char *sec_sysfs_cmd_list[] = { "fw_update", "get_fw_ver_bin", @@ -50,7 +54,11 @@ static int synaptics_ts_load_fw(struct synaptics_drv_data *data) old_fs = get_fs(); set_fs(KERNEL_DS); +#if defined(CONFIG_MACH_KONA) + fp = filp_open(SYNAPTICS_FW2, O_RDONLY, S_IRUSR); +#else fp = filp_open(SYNAPTICS_FW, O_RDONLY, S_IRUSR); +#endif if (IS_ERR(fp)) { printk(KERN_ERR "[TSP] failed to open %s.\n", SYNAPTICS_FW); error = -ENOENT; @@ -63,8 +71,14 @@ static int synaptics_ts_load_fw(struct synaptics_drv_data *data) fw_data = kzalloc(fw_size, GFP_KERNEL); nread = vfs_read(fp, (char __user *)fw_data, fw_size, &fp->f_pos); +#if defined(CONFIG_MACH_KONA) + printk(KERN_DEBUG "[TSP] start, file path %s, size %u Bytes\n", + SYNAPTICS_FW2, fw_size); +#else printk(KERN_DEBUG "[TSP] start, file path %s, size %u Bytes\n", SYNAPTICS_FW, fw_size); +#endif + if (nread != fw_size) { printk(KERN_ERR "[TSP] failed to read firmware file, nread %u Bytes\n", @@ -142,9 +156,69 @@ static void soft_reset(struct synaptics_drv_data *data) static void check_all_raw_cap(struct synaptics_drv_data *data) { - int i; + int i, j, k=0; u16 temp = 0; - u16 length = data->x_line * data->y_line * 2; + u16 length; + +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + u8 escape_rx_line; + + if (data->pdata->support_extend_button) + escape_rx_line = data->pdata->extend_button_map->nbuttons; + else + escape_rx_line = data->pdata->button_map->nbuttons; + + length = data->x_line * (data->y_line + escape_rx_line) * 2; + + if (NULL == data->references) + data->references = kzalloc(length, GFP_KERNEL); + + data->refer_min = 0xffff; + data->refer_max = 0x0; + + /* set the index */ + set_report_index(data, 0x0000); + + /* Set the GetReport bit to run the AutoScan */ + set_report_mode(data, 0x01, 0x00); + + /* read all report data */ + synaptics_ts_read_block(data, + data->f54.data_base_addr + 3, + data->references, length); + + for (i = 0; i < data->x_line; i++) { + for (j = 0; j < data->y_line + escape_rx_line; j++) { + temp = (u16)(data->references[k] | + (data->references[k+1] << 8)); + + if (k != 0 && j !=0) { + if (j >= data->y_line) { + if (data->debug) { + printk(KERN_DEBUG + "[TSP][skip] raw cap[%d] : %u\n", + k, temp); + } + k += 2; + continue; + } + } + if (data->debug) { + if (data->debug) { + printk(KERN_DEBUG + "[TSP] raw cap[%d] : %u\n", + k, temp); + } + } + if (temp < data->refer_min) + data->refer_min = temp; + if (temp > data->refer_max) + data->refer_max = temp; + k += 2; + } + } +#else + length = data->x_line * data->y_line * 2; if (NULL == data->references) data->references = kzalloc(length, GFP_KERNEL); @@ -179,6 +253,7 @@ static void check_all_raw_cap(struct synaptics_drv_data *data) if (temp > data->refer_max) data->refer_max = temp; } +#endif printk(KERN_DEBUG "[TSP] min : %u, max : %u\n", data->refer_min, data->refer_max); } @@ -333,6 +408,56 @@ static void check_rx_to_rx(struct synaptics_drv_data *data) kfree(buff); } +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) +static void check_delta_cap(struct synaptics_drv_data *data) +{ + int i, k=0; + u16 temp = 0; + u16 length; + u8 escape_rx_line; + u8 *btn_data; + int start_button_data; + + if (data->pdata->support_extend_button) + escape_rx_line = data->pdata->extend_button_map->nbuttons; + else + escape_rx_line = data->pdata->button_map->nbuttons; + + length = escape_rx_line * 2; + + btn_data = kzalloc(length, GFP_KERNEL); + + data->refer_min = 0xffff; + data->refer_max = 0x0; + + start_button_data = ((data->x_line * (data->y_line + escape_rx_line)) + data->y_line) * 2; + + /* set the index */ + set_report_index(data, start_button_data); + + /* Set the GetReport bit to run the AutoScan */ + set_report_mode(data, 0x01, 0x00); + + /* read all report data */ + synaptics_ts_read_block(data, + data->f54.data_base_addr + 3, + btn_data, length); + + for (i = 0; i < escape_rx_line; i++) { + temp = (u16)(btn_data[k] | (btn_data[k+1] << 8)); + printk(KERN_DEBUG "[TSP] index[btn:%d] data[0x%x]\n", i, temp); + + if (temp > BUTTON_THRESHOLD_LIMIT) + data->pdata->button_pressure[i] = BUTTON_THRESHOLD_MIN; + else + data->pdata->button_pressure[i] = temp; + k = k + 2; + } + + kfree(btn_data); +} +#endif + static void check_diagnostics_mode(struct synaptics_drv_data *data) { /* Set report mode */ @@ -355,6 +480,12 @@ static void check_diagnostics_mode(struct synaptics_drv_data *data) check_rx_to_rx(data); break; +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + case REPORT_TYPE_DELTA_CAP: + check_delta_cap(data); + break; +#endif + default: break; } @@ -427,11 +558,25 @@ static u16 get_value(struct synaptics_drv_data *data, u32 pos_x, u32 pos_y) { u16 tmp = 0; + u8 escape_rx_line; switch (data->cmd_report_type) { case REPORT_TYPE_RAW_CAP: { - u16 position = (u16)(data->y_line * pos_x) + pos_y; + u16 position; +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + if (data->pdata->support_extend_button) + escape_rx_line = + data->pdata->extend_button_map->nbuttons; + else + escape_rx_line = + data->pdata->button_map->nbuttons; + + position = (u16)((data->y_line + + escape_rx_line) * pos_x) + pos_y; +#else + position = (u16)(data->y_line * pos_x) + pos_y; +#endif position *= 2; tmp = (u16)(data->references[position] | (data->references[position+1] << 8)); @@ -845,6 +990,263 @@ static struct attribute_group sec_sysfs_attr_group = { .attrs = sec_sysfs_attributes, }; +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED) +static ssize_t sec_touchkey_sensitivity_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + printk(KERN_INFO "[TSP] do noting!\n"); + return size; +} + +static ssize_t sec_touchkey_back_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + int irq = gpio_to_irq(data->gpio); + + disable_irq(irq); + synaptics_ts_write_data(data, 0xf0, 0x01); + data->cmd_report_type = REPORT_TYPE_DELTA_CAP; + check_diagnostics_mode(data); + synaptics_ts_write_data(data, 0xf0, 0x00); + enable_irq(irq); + + if (data->pdata->support_extend_button) + return sprintf(buf, "%d\n", data->pdata->button_pressure[BUTTON4]); + else + return sprintf(buf, "%d\n", data->pdata->button_pressure[BUTTON2]); +} + +static ssize_t sec_touchkey_menu_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + int irq = gpio_to_irq(data->gpio); + + disable_irq(irq); + synaptics_ts_write_data(data, 0xf0, 0x01); + data->cmd_report_type = REPORT_TYPE_DELTA_CAP; + check_diagnostics_mode(data); + synaptics_ts_write_data(data, 0xf0, 0x00); + enable_irq(irq); + + if (data->pdata->support_extend_button) + return sprintf(buf, "%d\n", data->pdata->button_pressure[BUTTON2]); + else + return sprintf(buf, "%d\n", data->pdata->button_pressure[BUTTON1]); +} + +static ssize_t sec_touchkey_threshold_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + + if (data->pdata->support_extend_button) + return sprintf(buf, "%d %d %d %d %d\n", + BUTTON5_0_THRESHOLD, + BUTTON5_1_THRESHOLD, + BUTTON5_2_THRESHOLD, + BUTTON5_3_THRESHOLD, + BUTTON5_4_THRESHOLD); + else + return sprintf(buf, "%d %d\n", + BUTTON2_0_THRESHOLD, + BUTTON2_1_THRESHOLD); +} + +static ssize_t sec_touchkey_dummy_btn1_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + int irq = gpio_to_irq(data->gpio); + + disable_irq(irq); + synaptics_ts_write_data(data, 0xf0, 0x01); + data->cmd_report_type = REPORT_TYPE_DELTA_CAP; + check_diagnostics_mode(data); + synaptics_ts_write_data(data, 0xf0, 0x00); + enable_irq(irq); + + if (data->pdata->support_extend_button) + return sprintf(buf, "%d\n", data->pdata->button_pressure[BUTTON1]); + else { + printk(KERN_DEBUG "[TSP] dummy btn1 not supported\n"); + return 0; + } +} + +static ssize_t sec_touchkey_dummy_btn3_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + int irq = gpio_to_irq(data->gpio); + + disable_irq(irq); + synaptics_ts_write_data(data, 0xf0, 0x01); + data->cmd_report_type = REPORT_TYPE_DELTA_CAP; + check_diagnostics_mode(data); + synaptics_ts_write_data(data, 0xf0, 0x00); + enable_irq(irq); + + if (data->pdata->support_extend_button) + return sprintf(buf, "%d\n", data->pdata->button_pressure[BUTTON3]); + else { + printk(KERN_DEBUG "[TSP] dummy btn3 not supported\n"); + return 0; + } +} + +static ssize_t sec_touchkey_dummy_btn5_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + int irq = gpio_to_irq(data->gpio); + + disable_irq(irq); + synaptics_ts_write_data(data, 0xf0, 0x01); + data->cmd_report_type = REPORT_TYPE_DELTA_CAP; + check_diagnostics_mode(data); + synaptics_ts_write_data(data, 0xf0, 0x00); + enable_irq(irq); + + if (data->pdata->support_extend_button) + return sprintf(buf, "%d\n", data->pdata->button_pressure[BUTTON5]); + else { + printk(KERN_DEBUG "[TSP] dummy btn5 not supported\n"); + return 0; + } +} + +static ssize_t sec_touchkey_button_all_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + int irq = gpio_to_irq(data->gpio); + + disable_irq(irq); + synaptics_ts_write_data(data, 0xf0, 0x01); + data->cmd_report_type = REPORT_TYPE_DELTA_CAP; + check_diagnostics_mode(data); + synaptics_ts_write_data(data, 0xf0, 0x00); + enable_irq(irq); + + if (data->pdata->support_extend_button) + return sprintf(buf, "%d %d %d %d %d\n", + data->pdata->button_pressure[BUTTON1], + data->pdata->button_pressure[BUTTON2], + data->pdata->button_pressure[BUTTON3], + data->pdata->button_pressure[BUTTON4], + data->pdata->button_pressure[BUTTON5]); + else + return sprintf(buf, "%d %d\n", + data->pdata->button_pressure[BUTTON1], + data->pdata->button_pressure[BUTTON2]); +} + +static ssize_t sec_touchkey_button_status_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + u8 int_status = 0; + u8 button_status = 0; + + /* check interrupt status */ + synaptics_ts_read_data(data, + data->f01.data_base_addr + 1, + &int_status); + + /* check button status */ + synaptics_ts_read_data(data, + data->f1a.data_base_addr, + &button_status); + + return sprintf(buf, "%d %d\n", + int_status, + button_status); +} + +static ssize_t sec_brightness_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + int on_off; + + if (sscanf(buf, "%d\n", &on_off) == 1) { + //printk(KERN_DEBUG "[TSPLED] touch_led_on [%d]\n", on_off); + data->pdata->led_control(on_off); + } else { + printk(KERN_DEBUG "[TSPLED] buffer read failed\n"); + } + return size; +} + +static ssize_t sec_extra_button_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int extra_event; + + if (sscanf(buf, "%d\n", &extra_event) == 1) { + printk(KERN_DEBUG "[TSP] extra event [%d]\n", extra_event); + } else { + printk(KERN_DEBUG "[TSP] buffer read failed\n"); + } + return size; +} + +static DEVICE_ATTR(touch_sensitivity, S_IRUGO | S_IWUSR, + NULL, sec_touchkey_sensitivity_store); +static DEVICE_ATTR(touchkey_back, S_IRUGO | S_IWUSR, + sec_touchkey_back_show, NULL); +static DEVICE_ATTR(touchkey_menu, S_IRUGO | S_IWUSR, + sec_touchkey_menu_show, NULL); +static DEVICE_ATTR(touchkey_threshold, S_IRUGO | S_IWUSR, + sec_touchkey_threshold_show, NULL); +static DEVICE_ATTR(touchkey_dummy_btn1, S_IRUGO | S_IWUSR, + sec_touchkey_dummy_btn1_show, NULL); +static DEVICE_ATTR(touchkey_dummy_btn3, S_IRUGO | S_IWUSR, + sec_touchkey_dummy_btn3_show, NULL); +static DEVICE_ATTR(touchkey_dummy_btn5, S_IRUGO | S_IWUSR, + sec_touchkey_dummy_btn5_show, NULL); +static DEVICE_ATTR(touchkey_button_all, S_IRUGO | S_IWUSR, + sec_touchkey_button_all_show, NULL); +static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR, + NULL, sec_brightness_store); +static DEVICE_ATTR(extra_button_event, S_IRUGO | S_IWUSR, + NULL, sec_extra_button_store); +static DEVICE_ATTR(touchkey_button_status, S_IRUGO | S_IWUSR, + sec_touchkey_button_status_show, NULL); + +static struct attribute *sec_touchkey_sysfs_attributes[] = { + &dev_attr_touch_sensitivity.attr, + &dev_attr_touchkey_back.attr, + &dev_attr_touchkey_menu.attr, + &dev_attr_touchkey_threshold.attr, + &dev_attr_touchkey_dummy_btn1.attr, + &dev_attr_touchkey_dummy_btn3.attr, + &dev_attr_touchkey_dummy_btn5.attr, + &dev_attr_touchkey_button_all.attr, + &dev_attr_brightness.attr, + &dev_attr_extra_button_event.attr, + &dev_attr_touchkey_button_status.attr, + NULL, +}; + +static struct attribute_group sec_touchkey_sysfs_attr_group = { + .attrs = sec_touchkey_sysfs_attributes, +}; +#endif + int set_tsp_sysfs(struct synaptics_drv_data *data) { int ret = 0; @@ -861,6 +1263,23 @@ int set_tsp_sysfs(struct synaptics_drv_data *data) pr_err("[TSP] failed to create sysfs group\n"); goto err_device_create; } +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED) + synaptics_with_gpio_led_device = device_create(sec_class, + NULL, 0, data, "sec_touchkey"); + if (IS_ERR(synaptics_with_gpio_led_device)) { + pr_err("[TSP] failed to create device for tsp_touchkey sysfs\n"); + ret = -ENODEV; + goto err_device_create; + } + + ret = sysfs_create_group(&synaptics_with_gpio_led_device->kobj, + &sec_touchkey_sysfs_attr_group); + if (ret) { + pr_err("[TSP] failed to create sec_touchkey sysfs group\n"); + goto err_device_create; + } +#endif + return 0; err_device_create: @@ -877,6 +1296,10 @@ void remove_tsp_sysfs(struct synaptics_drv_data *data) kfree(data->tx_to_gnd); sysfs_remove_group(&data->dev->kobj, &sec_sysfs_attr_group); +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED) + sysfs_remove_group(&synaptics_with_gpio_led_device->kobj, + &sec_touchkey_sysfs_attr_group); +#endif put_device(data->dev); device_unregister(data->dev); } diff --git a/drivers/input/touchscreen/synaptics_sysfs.h b/drivers/input/touchscreen/synaptics_sysfs.h index 6d212c8..0f62b54 100644 --- a/drivers/input/touchscreen/synaptics_sysfs.h +++ b/drivers/input/touchscreen/synaptics_sysfs.h @@ -15,6 +15,7 @@ #include #define SYNAPTICS_FW "/sdcard/firmware/synaptics_fw" +#define SYNAPTICS_FW2 "/sdcard/synaptics_fw.img" #define FULL_RAW_CAP_LOWER_LIMIT 1000 #define FULL_RAW_CAP_UPPER_LIMIT 3000 #define MAX_RX_SIZE 45 diff --git a/drivers/input/touchscreen/wacom/w9002_flash.c b/drivers/input/touchscreen/wacom/w9002_flash.c new file mode 100644 index 0000000..e2fe54d --- /dev/null +++ b/drivers/input/touchscreen/wacom/w9002_flash.c @@ -0,0 +1,1253 @@ +/* + * w9002_flash.c - Wacom Digitizer Controller Flash Driver + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include "w9002_flash.h" + +static int wacom_i2c_flash_chksum(struct wacom_i2c *wac_i2c, + unsigned char *flash_data, + unsigned long *max_address) +{ + unsigned long i; + unsigned long chksum = 0; + + for (i = 0x0000; i <= *max_address; i++) + chksum += flash_data[i]; + + chksum &= 0xFFFF; + + return (int)chksum; +} + +static int wacom_flash_cmd(struct wacom_i2c *wac_i2c) +{ + int rv, len, i; + u8 buf[10]; + bool i2c_mode = WACOM_I2C_MODE_BOOT; + +#if defined(CONFIG_MACH_KONA) + buf[0] = 0x0d; + buf[1] = FLASH_START0; + buf[2] = FLASH_START1; + buf[3] = FLASH_START2; + buf[4] = FLASH_START3; + buf[5] = FLASH_START4; + buf[6] = FLASH_START5; + buf[7] = 0x0d; + + len = 8; + rv = wacom_i2c_send(wac_i2c, buf, len, i2c_mode); +#else + + for (i = 0; i < 2; ++i) { + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x32; + buf[len++] = CMD_SET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, i2c_mode); + if (rv < 0) { + printk(KERN_DEBUG "epen:fail change to normal:%d\n", + rv); + + i2c_mode = WACOM_I2C_MODE_NORMAL; + continue; + } + + len = 0; + buf[len++] = 5; + buf[len++] = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 2; + buf[len++] = 2; + + rv = wacom_i2c_send(wac_i2c, buf, len, i2c_mode); + if (rv < 0) { + printk(KERN_DEBUG "epen:fail change to normal:%d\n", + rv); + i2c_mode = WACOM_I2C_MODE_NORMAL; + continue; + } + } +#endif + if (rv < 0) { + printk(KERN_ERR + "Sending flash command failed\n"); + return -1; + } + + printk(KERN_DEBUG "epen:flash cmd sent:%d\n", rv); + msleep(500); + + return 0; +} + +static bool flash_query(struct wacom_i2c *wac_i2c) +{ + int rv, ECH; + u8 buf[4]; + u16 len; + unsigned char command[CMD_SIZE]; + unsigned char response[RSP_SIZE]; + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x37; + buf[len++] = CMD_SET_FEATURE; + + printk(KERN_DEBUG "epen: %s\n", __func__); + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 1 rv:%d\n", rv); + return false; + } + + command[0] = 5; + command[1] = 0; + command[2] = 5; + command[3] = 0; + command[4] = BOOT_CMD_REPORT_ID; + command[5] = BOOT_QUERY; + command[6] = ECH = 7; + + rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 2 rv:%d\n", rv); + return false; + } + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x38; + buf[len++] = CMD_GET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 3 rv:%d\n", rv); + return false; + } + + len = 0; + buf[len++] = 5; + buf[len++] = 0; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 4 rv:%d\n", rv); + return false; + } + + usleep_range(10000, 10000); + + rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 5 rv:%d\n", rv); + return false; + } + + if ((response[3] != QUERY_CMD) || (response[4] != ECH)) { + printk(KERN_DEBUG "epen: res3:%d res4:%d\n", response[3], + response[4]); + return false; + } + if (response[5] != QUERY_RSP) { + printk(KERN_DEBUG "epen: res5:%d\n", response[5]); + return false; + } + + return true; +} + +static bool flash_blver(struct wacom_i2c *wac_i2c, int *blver) +{ + int rv, ECH; + u8 buf[4]; + u16 len; + unsigned char command[CMD_SIZE]; + unsigned char response[RSP_SIZE]; + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x37; + buf[len++] = CMD_SET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 1 rv:%d\n", rv); + return false; + } + + command[0] = 5; + command[1] = 0; + command[2] = 5; + command[3] = 0; + command[4] = BOOT_CMD_REPORT_ID; + command[5] = BOOT_BLVER; + command[6] = ECH = 7; + + rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 2 rv:%d\n", rv); + return false; + } + + usleep_range(10000, 10000); + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x38; + buf[len++] = CMD_GET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 3 rv:%d\n", rv); + return false; + } + + len = 0; + buf[len++] = 5; + buf[len++] = 0; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 4 rv:%d\n", rv); + return false; + } + + usleep_range(10000, 10000); + + rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 5 rv:%d\n", rv); + return false; + } + + if ((response[3] != BOOT_CMD) || (response[4] != ECH)) + return false; + + *blver = (int)response[5]; + + return true; +} + +static bool flash_mputype(struct wacom_i2c *wac_i2c, int *pMpuType) +{ + int rv, ECH; + u8 buf[4]; + u16 len; + unsigned char command[CMD_SIZE]; + unsigned char response[RSP_SIZE]; + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x37; + buf[len++] = CMD_SET_FEATURE; /* Command-MSB, SET_REPORT */ + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 1 rv:%d\n", rv); + return false; + } + + command[0] = 5; + command[1] = 0; + command[2] = 5; + command[3] = 0; + command[4] = BOOT_CMD_REPORT_ID; + command[5] = BOOT_MPU; + command[6] = ECH = 7; + + rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 2 rv:%d\n", rv); + return false; + } + + usleep_range(10000, 10000); + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x38; + buf[len++] = CMD_GET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 3 rv:%d\n", rv); + return false; + } + + len = 0; + buf[len++] = 5; + buf[len++] = 0; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 4 rv:%d\n", rv); + return false; + } + + usleep_range(1000, 1000); + + rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 5 rv:%d\n", rv); + return false; + } + + if ((response[3] != MPU_CMD) || (response[4] != ECH)) + return false; + + *pMpuType = (int)response[5]; + + return true; +} + +static bool flash_security_unlock(struct wacom_i2c *wac_i2c, int *status) +{ + int rv, ECH; + u8 buf[4]; + u16 len; + unsigned char command[CMD_SIZE]; + unsigned char response[RSP_SIZE]; + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x37; + buf[len++] = CMD_SET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 1 rv:%d\n", rv); + return false; + } + + command[0] = 5; + command[1] = 0; + command[2] = 5; + command[3] = 0; + command[4] = BOOT_CMD_REPORT_ID; + command[5] = BOOT_SECURITY_UNLOCK; + command[6] = ECH = 7; + + rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 2 rv:%d\n", rv); + return false; + } + + usleep_range(10000, 10000); + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x38; + buf[len++] = CMD_GET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 3 rv:%d\n", rv); + return 0; + } + + len = 0; + buf[len++] = 5; + buf[len++] = 0; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 4 rv:%d\n", rv); + return false; + } + + usleep_range(1000, 1000); + + rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 5 rv:%d\n", rv); + return false; + } + + if ((response[3] != SEC_CMD) || (response[4] != ECH)) + return false; + + *status = (int)response[5]; + + return true; +} + +static bool flash_end(struct wacom_i2c *wac_i2c) +{ + int rv, ECH; + u8 buf[4]; + u16 len; + unsigned char command[CMD_SIZE]; + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x37; + buf[len++] = CMD_SET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 1 rv:%d\n", rv); + return false; + } + + command[0] = 5; + command[1] = 0; + command[2] = 5; + command[3] = 0; + command[4] = BOOT_CMD_REPORT_ID; + command[5] = BOOT_EXIT; + command[6] = ECH = 7; + + rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 2 rv:%d\n", rv); + return false; + } + + return true; +} + +static int GetBLVersion(struct wacom_i2c *wac_i2c, int *pBLVer) +{ + int rv; + int retry = 0; + + wacom_flash_cmd(wac_i2c); + do { + msleep(100); + rv = flash_query(wac_i2c); + retry++; + } while (rv < 0 && retry < 10); + + if (rv < 0) + return EXIT_FAIL_GET_BOOT_LOADER_VERSION; + + rv = flash_blver(wac_i2c, pBLVer); + if (rv) + return EXIT_OK; + else + return EXIT_FAIL_GET_BOOT_LOADER_VERSION; +} + +static int GetMpuType(struct wacom_i2c *wac_i2c, int *pMpuType) +{ + int rv; + + if (!flash_query(wac_i2c)) { + if (!wacom_flash_cmd(wac_i2c)) { + return EXIT_FAIL_ENTER_FLASH_MODE; + } else { + msleep(100); + if (!flash_query(wac_i2c)) + return EXIT_FAIL_FLASH_QUERY; + } + } + + rv = flash_mputype(wac_i2c, pMpuType); + if (rv) + return EXIT_OK; + else + return EXIT_FAIL_GET_MPU_TYPE; +} + +static int SetSecurityUnlock(struct wacom_i2c *wac_i2c, int *pStatus) +{ + int rv; + + if (!flash_query(wac_i2c)) { + if (!wacom_flash_cmd(wac_i2c)) { + return EXIT_FAIL_ENTER_FLASH_MODE; + } else { + msleep(100); + if (!flash_query(wac_i2c)) + return EXIT_FAIL_FLASH_QUERY; + } + } + + rv = flash_security_unlock(wac_i2c, pStatus); + if (rv) + return EXIT_OK; + else + return EXIT_FAIL; +} + +static bool flash_erase(struct wacom_i2c *wac_i2c, bool bAllUserArea, + int *eraseBlock, int num) +{ + int rv, ECH; + unsigned char sum; + unsigned char buf[72]; + unsigned char cmd_chksum; + u16 len; + int i, j; + unsigned char command[CMD_SIZE]; + unsigned char response[RSP_SIZE]; + + for (i = 0; i < num; i++) { + /*msleep(500);*/ +retry: + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x37; + buf[len++] = CMD_SET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: failing 1:%d\n", i); + return false; + } + + command[0] = 5; + command[1] = 0; + command[2] = 7; + command[3] = 0; + command[4] = BOOT_CMD_REPORT_ID; + command[5] = BOOT_ERASE_FLASH; + command[6] = ECH = i; + command[7] = *eraseBlock; + eraseBlock++; + + sum = 0; + for (j = 0; j < 8; j++) + sum += command[j]; + cmd_chksum = ~sum + 1; + command[8] = cmd_chksum; + + rv = wacom_i2c_send(wac_i2c, command, 9, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: failing 2:%d\n", i); + return false; + } + + switch (i) { + case 0: + msleep(3000); + break; + + case 1: + msleep(3000); + break; + + case 2: + msleep(5000); + break; + + case 3: + msleep(500); + break; + + default: + msleep(5000); + break; + } + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x38; + buf[len++] = CMD_GET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: failing 3:%d\n", i); + return false; + } + + len = 0; + buf[len++] = 5; + buf[len++] = 0; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: failing 4:%d\n", i); + return false; + } + + rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: failing 5:%d\n", i); + return false; + } + + if ((response[3] != ERS_CMD) || (response[4] != ECH)) { + printk(KERN_DEBUG "epen: failing 6:%d\n", i); + return false; + } + + if (response[5] == 0x80) { + printk(KERN_DEBUG "epen: retry\n"); + goto retry; + } + if (response[5] != ACK) { + printk(KERN_DEBUG "epen: failing 7:%d res5:%d\n", i, + response[5]); + return false; + } + } + return true; +} + +static bool is_flash_marking(struct wacom_i2c *wac_i2c, + size_t data_size, bool *bMarking, int iMpuID) +{ + const int MAX_CMD_SIZE = (12 + FLASH_BLOCK_SIZE + 2); + int rv, ECH; + unsigned char flash_data[FLASH_BLOCK_SIZE]; + unsigned char buf[300]; + unsigned char sum; + int len; + unsigned int i, j; + unsigned char response[RSP_SIZE]; + unsigned char command[MAX_CMD_SIZE]; + + *bMarking = false; + + printk(KERN_DEBUG "epen: started\n"); + for (i = 0; i < FLASH_BLOCK_SIZE; i++) + flash_data[i] = 0xFF; + + flash_data[56] = 0x00; + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x37; + buf[len++] = CMD_SET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 1 rv:%d\n", rv); + return false; + } + + command[0] = 5; + command[1] = 0; + command[2] = 76; + command[3] = 0; + command[4] = BOOT_CMD_REPORT_ID; + command[5] = BOOT_VERIFY_FLASH; + command[6] = ECH = 1; + command[7] = 0xC0; + command[8] = 0x1F; + command[9] = 0x01; + command[10] = 0x00; + command[11] = 8; + + sum = 0; + for (j = 0; j < 12; j++) + sum += command[j]; + + command[MAX_CMD_SIZE - 2] = ~sum + 1; + + sum = 0; + printk(KERN_DEBUG "epen: start writing command\n"); + for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) { + command[i] = flash_data[i - 12]; + sum += flash_data[i - 12]; + } + command[MAX_CMD_SIZE - 1] = ~sum + 1; + + printk(KERN_DEBUG "epen: sending command\n"); + rv = wacom_i2c_send(wac_i2c, command, MAX_CMD_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 2 rv:%d\n", rv); + return false; + } + + usleep_range(10000, 10000); + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x38; + buf[len++] = CMD_GET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 3 rv:%d\n", rv); + return false; + } + + len = 0; + buf[len++] = 5; + buf[len++] = 0; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 4 rv:%d\n", rv); + return false; + } + + rv = wacom_i2c_recv(wac_i2c, response, RSP_SIZE, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 5 rv:%d\n", rv); + return false; + } + + printk(KERN_DEBUG "epen: checking response\n"); + if ((response[3] != MARK_CMD) || + (response[4] != ECH) || (response[5] != ACK)) { + printk(KERN_DEBUG "epen: fails res3:%d res4:%d res5:%d\n", + response[3], response[4], response[5]); + return false; + } + + *bMarking = true; + return true; +} + +static bool flash_write_block(struct wacom_i2c *wac_i2c, char *flash_data, + unsigned long ulAddress, u8 *pcommand_id) +{ + const int MAX_COM_SIZE = (12 + FLASH_BLOCK_SIZE + 2); + int len, ECH; + unsigned char buf[300]; + int rv; + unsigned char sum; + unsigned char command[MAX_COM_SIZE]; + unsigned char response[RSP_SIZE]; + unsigned int i; + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x37; + buf[len++] = CMD_SET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) + return false; + + command[0] = 5; + command[1] = 0; + command[2] = 76; + command[3] = 0; + command[4] = BOOT_CMD_REPORT_ID; + command[5] = BOOT_WRITE_FLASH; + command[6] = ECH = ++(*pcommand_id); + command[7] = ulAddress & 0x000000ff; + command[8] = (ulAddress & 0x0000ff00) >> 8; + command[9] = (ulAddress & 0x00ff0000) >> 16; + command[10] = (ulAddress & 0xff000000) >> 24; + command[11] = 8; + sum = 0; + for (i = 0; i < 12; i++) + sum += command[i]; + command[MAX_COM_SIZE - 2] = ~sum + 1; + + sum = 0; + for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) { + command[i] = flash_data[ulAddress + (i - 12)]; + sum += flash_data[ulAddress + (i - 12)]; + } + command[MAX_COM_SIZE - 1] = ~sum + 1; + + rv = wacom_i2c_send(wac_i2c, command, BOOT_CMD_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 1 rv:%d\n", rv); + return false; + } + + usleep_range(10000, 10000); + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x38; + buf[len++] = CMD_GET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 2 rv:%d\n", rv); + return false; + } + + len = 0; + buf[len++] = 5; + buf[len++] = 0; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 3 rv:%d\n", rv); + return false; + } + + rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 4 rv:%d\n", rv); + return false; + } + + if ((response[3] != WRITE_CMD) || + (response[4] != ECH) || response[5] != ACK) + return false; + + return true; + +} + +static bool flash_write(struct wacom_i2c *wac_i2c, + unsigned char *flash_data, size_t data_size, + unsigned long start_address, unsigned long *max_address, + int mpuType) +{ + unsigned long ulAddress; + int i; + bool rv; + unsigned long pageNo = 0; + u8 command_id = 0; + + printk(KERN_DEBUG "epen: flash_write start\n"); + + for (ulAddress = start_address; ulAddress < *max_address; + ulAddress += FLASH_BLOCK_SIZE) { + unsigned int j; + bool bWrite = false; + + /* Wacom 2012/10/04: skip if all each data locating on + from ulAddr to ulAddr+Block_SIZE_W are 0xff */ + for (i = 0; i < FLASH_BLOCK_SIZE; i++) { + if (flash_data[ulAddress + i] != 0xFF) + break; + } + if (i == (FLASH_BLOCK_SIZE)) { + /*printk(KERN_DEBUG"epen:BLOCK PASSED\n"); */ + continue; + } + /* Wacom 2012/10/04 */ + + for (j = 0; j < FLASH_BLOCK_SIZE; j++) { + if (flash_data[ulAddress + j] == 0xFF) + continue; + else { + bWrite = true; + break; + } + } + + if (!bWrite) { + pageNo++; + continue; + } + + rv = flash_write_block(wac_i2c, flash_data, ulAddress, + &command_id); + if (!rv) + return false; + + pageNo++; + } + + return true; +} + +static bool flash_verify(struct wacom_i2c *wac_i2c, + unsigned char *flash_data, size_t data_size, + unsigned long start_address, + unsigned long *max_address, int mpuType) +{ + int ECH; + unsigned long ulAddress; + int rv; + unsigned long pageNo = 0; + u8 command_id = 0; + printk(KERN_DEBUG "epen: verify starts\n"); + for (ulAddress = start_address; ulAddress < *max_address; + ulAddress += FLASH_BLOCK_SIZE) { + const int MAX_CMD_SIZE = 12 + FLASH_BLOCK_SIZE + 2; + unsigned char buf[300]; + unsigned char sum; + int len; + unsigned int i, j; + unsigned char command[MAX_CMD_SIZE]; + unsigned char response[RSP_SIZE]; + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x37; + buf[len++] = CMD_SET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 1 rv:%d\n", rv); + return false; + } + + command[0] = 5; + command[1] = 0; + command[2] = 76; + command[3] = 0; + command[4] = BOOT_CMD_REPORT_ID; + command[5] = BOOT_VERIFY_FLASH; + command[6] = ECH = ++command_id; + command[7] = ulAddress & 0x000000ff; + command[8] = (ulAddress & 0x0000ff00) >> 8; + command[9] = (ulAddress & 0x00ff0000) >> 16; + command[10] = (ulAddress & 0xff000000) >> 24; + command[11] = 8; + + sum = 0; + for (j = 0; j < 12; j++) + sum += command[j]; + command[MAX_CMD_SIZE - 2] = ~sum + 1; + + sum = 0; + for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) { + command[i] = flash_data[ulAddress + (i - 12)]; + sum += flash_data[ulAddress + (i - 12)]; + } + command[MAX_CMD_SIZE - 1] = ~sum + 1; + + rv = wacom_i2c_send(wac_i2c, command, BOOT_CMD_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 2 rv:%d\n", rv); + return false; + } + + if (ulAddress <= 0x0ffff) + ndelay(250000); + else if (ulAddress >= 0x10000 && ulAddress <= 0x20000) + ndelay(350000); + else + usleep_range(10000, 10000); + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x38; + buf[len++] = CMD_GET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 3 rv:%d\n", rv); + return false; + } + + len = 0; + buf[len++] = 5; + buf[len++] = 0; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 4 rv:%d\n", rv); + return false; + } + + rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 5 rv:%d\n", rv); + return false; + } + + if ((response[3] != VERIFY_CMD) || + (response[4] != ECH) || (response[5] != ACK)) { + printk(KERN_DEBUG "epen: res3:%d res4:%d res5:%d\n", + response[3], response[4], response[5]); + return false; + } + pageNo++; + } + + return true; +} + +static bool flash_marking(struct wacom_i2c *wac_i2c, + size_t data_size, bool bMarking, int iMpuID) +{ + const int MAX_CMD_SIZE = 12 + FLASH_BLOCK_SIZE + 2; + int rv, ECH; + unsigned char flash_data[FLASH_BLOCK_SIZE]; + unsigned char buf[300]; + unsigned char response[RSP_SIZE]; + unsigned char sum; + int len; + unsigned int i, j; + unsigned char command[MAX_CMD_SIZE]; + + for (i = 0; i < FLASH_BLOCK_SIZE; i++) + flash_data[i] = 0xFF; + + if (bMarking) + flash_data[56] = 0x00; + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x37; + buf[len++] = CMD_SET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 1 rv:%d\n", rv); + return false; + } + + command[0] = 5; + command[1] = 0; + command[2] = 76; + command[3] = 0; + command[4] = BOOT_CMD_REPORT_ID; + command[5] = BOOT_WRITE_FLASH; + command[6] = ECH = 1; + command[7] = 0xC0; + command[8] = 0x1F; + command[9] = 0x01; + command[10] = 0x00; + command[11] = 8; + + sum = 0; + for (j = 0; j < 12; j++) + sum += command[j]; + command[MAX_CMD_SIZE - 2] = ~sum + 1; + + sum = 0; + for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) { + command[i] = flash_data[i - 12]; + sum += flash_data[i - 12]; + } + command[MAX_CMD_SIZE - 1] = ~sum + 1; + + rv = wacom_i2c_send(wac_i2c, command, BOOT_CMD_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 2 rv:%d\n", rv); + return false; + } + + usleep_range(10000, 10000); + + len = 0; + buf[len++] = 4; + buf[len++] = 0; + buf[len++] = 0x38; + buf[len++] = CMD_GET_FEATURE; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 3 rv:%d\n", rv); + return false; + } + + len = 0; + buf[len++] = 5; + buf[len++] = 0; + + rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT); + if (rv < 0) { + printk(KERN_DEBUG "epen: 4 rv:%d\n", rv); + return false; + } + + printk(KERN_DEBUG "epen: confirming marking\n"); + rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE, + WACOM_I2C_MODE_BOOT); + if (rv < 0) + return false; + + if ((response[3] != 1) || (response[4] != ECH)\ + || (response[5] != ACK)) { + printk(KERN_DEBUG "epen: failing res3:%d res4:%d res5:%d\n", + response[3], response[4], response[5]); + return false; + } + + return true; +} + +int wacom_i2c_flash(struct wacom_i2c *wac_i2c) +{ + unsigned long max_address = 0; + unsigned long start_address = 0x4000; + int eraseBlock[50], eraseBlockNum; + bool bRet; + int iChecksum; + int iBLVer, iMpuType, iStatus; + bool bMarking; + int iRet; + unsigned long ulMaxRange; + + if (Binary == NULL) { + printk(KERN_ERR"[E-PEN] Data is NULL. Exit.\n"); + return -1; + } + +#ifdef WACOM_HAVE_FWE_PIN + if (wac_i2c->have_fwe_pin) { + wac_i2c->wac_pdata->compulsory_flash_mode(true); + /*Reset */ + wac_i2c->wac_pdata->reset_platform_hw(); + msleep(200); + printk(KERN_DEBUG "epen: Set FWE\n"); + } +#endif + wake_lock(&wac_i2c->wakelock); + + printk(KERN_DEBUG "epen:start getting the boot loader version\n"); + /*Obtain boot loader version */ + iRet = GetBLVersion(wac_i2c, &iBLVer); + if (iRet != EXIT_OK) { + printk(KERN_DEBUG "epen:failed to get Boot Loader version\n"); + goto fw_update_error; + } + + printk(KERN_DEBUG "epen: start getting the MPU version\n"); + /*Obtain MPU type: this can be manually done in user space */ + iRet = GetMpuType(wac_i2c, &iMpuType); + if (iRet != EXIT_OK) { + printk(KERN_DEBUG "epen: failed to get MPU type\n"); + goto fw_update_error; + } + + /*Set start and end address and block numbers */ + eraseBlockNum = 0; + start_address = 0x4000; + max_address = 0x12FFF; + eraseBlock[eraseBlockNum++] = 2; + eraseBlock[eraseBlockNum++] = 1; + eraseBlock[eraseBlockNum++] = 0; + eraseBlock[eraseBlockNum++] = 3; + + printk(KERN_DEBUG "epen: obtaining the checksum\n"); + /*Calculate checksum */ + iChecksum = wacom_i2c_flash_chksum(wac_i2c, Binary, &max_address); + printk(KERN_DEBUG "epen: Checksum is :%d\n", iChecksum); + + bRet = true; + + printk(KERN_DEBUG "epen: setting the security unlock\n"); + /*Unlock security */ + iRet = SetSecurityUnlock(wac_i2c, &iStatus); + if (iRet != EXIT_OK) { + printk(KERN_DEBUG "epen: failed to set security unlock\n"); + goto fw_update_error; + } + + /*Set adress range */ + ulMaxRange = max_address; + ulMaxRange -= start_address; + ulMaxRange >>= 6; + if (max_address > (ulMaxRange << 6)) + ulMaxRange++; + + printk(KERN_DEBUG "epen: connecting to Wacom Digitizer\n"); + printk(KERN_DEBUG "epen: erasing the current firmware\n"); + /*Erase the old program */ + bRet = flash_erase(wac_i2c, true, eraseBlock, eraseBlockNum); + if (!bRet) { + printk(KERN_DEBUG "epen: failed to erase the user program\n"); + iRet = EXIT_FAIL_ERASE; + goto fw_update_error; + } + printk(KERN_DEBUG "epen: erasing done\n"); + + max_address = 0x11FC0; + + printk(KERN_DEBUG "epen: writing new firmware\n"); + /*Write the new program */ + bRet = + flash_write(wac_i2c, Binary, DATA_SIZE, start_address, &max_address, + iMpuType); + if (!bRet) { + printk(KERN_DEBUG "epen: failed to write firmware\n"); + iRet = EXIT_FAIL_WRITE_FIRMWARE; + goto fw_update_error; + } + + printk(KERN_DEBUG "epen: start marking\n"); + /*Set mark in writing process */ + bRet = flash_marking(wac_i2c, DATA_SIZE, true, iMpuType); + if (!bRet) { + printk(KERN_DEBUG "epen: failed to mark firmware\n"); + iRet = EXIT_FAIL_WRITE_FIRMWARE; + goto fw_update_error; + } + + /*Set the address for verify */ + start_address = 0x4000; + max_address = 0x11FBF; + + printk(KERN_DEBUG "epen: start the verification\n"); + /*Verify the written program */ + bRet = + flash_verify(wac_i2c, Binary, DATA_SIZE, start_address, + &max_address, iMpuType); + if (!bRet) { + printk(KERN_DEBUG "epen: failed to verify the firmware\n"); + iRet = EXIT_FAIL_VERIFY_FIRMWARE; + goto fw_update_error; + } + + printk(KERN_DEBUG "epen: checking the mark\n"); + /*Set mark */ + bRet = is_flash_marking(wac_i2c, DATA_SIZE, &bMarking, iMpuType); + if (!bRet) { + printk(KERN_DEBUG "epen: marking firmwrae failed\n"); + iRet = EXIT_FAIL_WRITING_MARK_NOT_SET; + goto fw_update_error; + } + + /*Enable */ + printk(KERN_DEBUG "epen: closing the boot mode\n"); + bRet = flash_end(wac_i2c); + if (!bRet) { + printk(KERN_DEBUG "epen: closing boot mode failed\n"); + iRet = EXIT_FAIL_WRITING_MARK_NOT_SET; + goto fw_update_error; + } + iRet = EXIT_OK; + printk(KERN_DEBUG "epen: write and verify completed\n"); + +fw_update_error: + wake_unlock(&wac_i2c->wakelock); + +#ifdef WACOM_HAVE_FWE_PIN + if (wac_i2c->have_fwe_pin) { + wac_i2c->wac_pdata->compulsory_flash_mode(false); + /*Reset */ + wac_i2c->wac_pdata->reset_platform_hw(); + msleep(200); + } +#endif + return iRet; +} diff --git a/drivers/input/touchscreen/wacom/w9002_flash.h b/drivers/input/touchscreen/wacom/w9002_flash.h new file mode 100644 index 0000000..a6d0e49 --- /dev/null +++ b/drivers/input/touchscreen/wacom/w9002_flash.h @@ -0,0 +1,211 @@ +/* + * w9002_flash.h + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "wacom_i2c_func.h" +#include "wacom_i2c_firm.h" + +#ifndef _WACOM_I2C_FLASH_H +#define _WACOM_I2C_FLASH_H + +#define WACOM_CMD_QUERY0 0x04 +#define WACOM_CMD_QUERY1 0x00 +#define WACOM_CMD_QUERY2 0x33 +#define WACOM_CMD_QUERY3 0x02 +#define WACOM_CMD_THROW0 0x05 +#define WACOM_CMD_THROW1 0x00 +#define WACOM_QUERY_SIZE 19 +#define WACOM_RETRY_CNT 100 + +struct flash { + int BLen; + unsigned long size; + unsigned char *data; +}; + +#define FLASH_START0 'f' +#define FLASH_START1 'l' +#define FLASH_START2 'a' +#define FLASH_START3 's' +#define FLASH_START4 'h' +#define FLASH_START5 '\r' +#define FLASH_ACK 0x06 + +#define pana_QUERY 0x11 + +#define flash_END 0x80 +#define flash_VERIFY 0x81 +#define flash_WRITE 0x82 +#define flash_READ 0x83 +#define flash_ERASE 0x84 +#define flash_SET_INFO 0x85 +#define flash_END_TO_BOOT 0x87 +#define flash_BAUDRATE 0x88 + +#define flash_QUERY 0xE0 +#define flash_BLVER 0xE1 +#define flash_UNITID 0xE2 +#define flash_GET_INFO 0xE3 +#define flash_FWVER 0xE4 +#define flash_MPU 0xE8 + +#define pen_QUERY '*' + +#define V09 0 +#define V095 1 + +#define HIDIIC_VERSION V095 + +#define FLASH_BLOCK_SIZE 64 + +#define ASCINT_ON 0x0 +#define ASCINT_OFF 0x1 +#define ASCINT_ERROR 0xFF + +/*#define WRITE 0*/ +#define VERIFY 1 +#define WRITEVERIFY 2 +#define ERASE 3 +#define GETVERSION 4 + +#define USER_ADDRESS 0x56 +#define BOOT_ADDRESS 0x57 + +#define CMD_GET_FEATURE 2 +#define CMD_SET_FEATURE 3 + +#define ACK 0 + +#define BOOT_CMD_SIZE 78 +#define BOOT_RSP_SIZE 6 + +#define BOOT_CMD_REPORT_ID 7 + +#define BOOT_ERASE_FLASH 0 +#define BOOT_WRITE_FLASH 1 +#define BOOT_VERIFY_FLASH 2 +#define BOOT_EXIT 3 +#define BOOT_BLVER 4 +#define BOOT_MPU 5 +#define BOOT_SECURITY_UNLOCK 6 +#define BOOT_QUERY 7 + +#define QUERY_CMD 0x07 +#define QUERY_ECH 'D' +#define QUERY_RSP 0x06 + +#define BOOT_CMD 0x04 +#define BOOT_ECH 'D' + +#define MPU_CMD 0x05 +#define MPU_ECH 'D' + +#define SEC_CMD 0x06 +#define SEC_ECH 'D' +#define SEC_RSP 0x00 + +#define ERS_CMD 0x00 +#define ERS_ECH 'D' +#define ERS_RSP 0x00 + +#define MARK_CMD 0x02 +#define MARK_ECH 'D' +#define MARK_RSP 0x00 + +#define WRITE_CMD 0x01 +#define WRITE_ECH 'D' +#define WRITE_RSP 0x00 + +#define VERIFY_CMD 0x02 +#define VERIFY_ECH 'D' +#define VERIFY_RSP 0x00 + +#define CMD_SIZE (72+6) +#define RSP_SIZE 6 + +#define DATA_SIZE (65536 * 2) + +/*exit codes*/ +#define EXIT_OK (0) +#define EXIT_REBOOT (1) +#define EXIT_FAIL (2) +#define EXIT_USAGE (3) +#define EXIT_NO_SUCH_FILE (4) +#define EXIT_NO_INTEL_HEX (5) +#define EXIT_FAIL_OPEN_COM_PORT (6) +#define EXIT_FAIL_ENTER_FLASH_MODE (7) +#define EXIT_FAIL_FLASH_QUERY (8) +#define EXIT_FAIL_BAUDRATE_CHANGE (9) +#define EXIT_FAIL_WRITE_FIRMWARE (10) +#define EXIT_FAIL_EXIT_FLASH_MODE (11) +#define EXIT_CANCEL_UPDATE (12) +#define EXIT_SUCCESS_UPDATE (13) +#define EXIT_FAIL_HID2SERIAL (14) +#define EXIT_FAIL_VERIFY_FIRMWARE (15) +#define EXIT_FAIL_MAKE_WRITING_MARK (16) +#define EXIT_FAIL_ERASE_WRITING_MARK (17) +#define EXIT_FAIL_READ_WRITING_MARK (18) +#define EXIT_EXIST_MARKING (19) +#define EXIT_FAIL_MISMATCHING (20) +#define EXIT_FAIL_ERASE (21) +#define EXIT_FAIL_GET_BOOT_LOADER_VERSION (22) +#define EXIT_FAIL_GET_MPU_TYPE (23) +#define EXIT_MISMATCH_BOOTLOADER (24) +#define EXIT_MISMATCH_MPUTYPE (25) +#define EXIT_FAIL_ERASE_BOOT (26) +#define EXIT_FAIL_WRITE_BOOTLOADER (27) +#define EXIT_FAIL_SWAP_BOOT (28) +#define EXIT_FAIL_WRITE_DATA (29) +#define EXIT_FAIL_GET_FIRMWARE_VERSION (30) +#define EXIT_FAIL_GET_UNIT_ID (31) +#define EXIT_FAIL_SEND_STOP_COMMAND (32) +#define EXIT_FAIL_SEND_QUERY_COMMAND (33) +#define EXIT_NOT_FILE_FOR_535 (34) +#define EXIT_NOT_FILE_FOR_514 (35) +#define EXIT_NOT_FILE_FOR_503 (36) +#define EXIT_MISMATCH_MPU_TYPE (37) +#define EXIT_NOT_FILE_FOR_515 (38) +#define EXIT_NOT_FILE_FOR_1024 (39) +#define EXIT_FAIL_VERIFY_WRITING_MARK (40) +#define EXIT_DEVICE_NOT_FOUND (41) +#define EXIT_FAIL_WRITING_MARK_NOT_SET (42) + +/*For Report Descreptor of HID over I2C*/ +#define HID_USAGE_UNDEFINED 0x00 +#define HID_USAGE_PAGE 0x05 +#define HID_USAGE_PAGE_DIGITIZER 0x0d +#define HID_USAGE_PAGE_DESKTOP 0x01 +#define HID_USAGE 0x09 +#define HID_USAGE_X 0x30 +#define HID_USAGE_Y 0x31 +#define HID_USAGE_X_TILT 0x3d +#define HID_USAGE_Y_TILT 0x3e +#define HID_USAGE_FINGER 0x22 +#define HID_USAGE_STYLUS 0x20 +#define HID_USAGE_TIP_PRESSURE 0x30 +#define HID_COLLECTION 0xc0 + +#define I2C_REQ_GET_REPORT 0x01 +#define I2C_REQ_SET_REPORT 0x09 + +#define WAC_HID_FEATURE_REPORT 0x03 +#define WAC_MSG_RETRIES 5 + +extern int wacom_i2c_flash(struct wacom_i2c *wac_i2c); + +#endif /*_WACOM_I2C_FLASH_H*/ diff --git a/drivers/input/touchscreen/wacom/wacom_i2c.c b/drivers/input/touchscreen/wacom/wacom_i2c.c index e0dd530..4a47709 100644 --- a/drivers/input/touchscreen/wacom/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom/wacom_i2c.c @@ -25,7 +25,11 @@ #include #include #include "wacom_i2c_func.h" +#ifdef CONFIG_EPEN_WACOM_G9PL +#include "w9002_flash.h" +#else #include "wacom_i2c_flash.h" +#endif #ifdef WACOM_IMPORT_FW_ALGO #include "wacom_i2c_coord_tables.h" #endif @@ -151,13 +155,19 @@ int wacom_i2c_get_ums_data(struct wacom_i2c *wac_i2c, u8 **ums_data) "[E-PEN] start, file path %s, size %ld Bytes\n", WACOM_FW_PATH, fsize); +#ifndef CONFIG_MACH_KONA if (fsize != nSize) { printk(KERN_ERR "[E-PEN] UMS firmware size is different\n"); ret = -EFBIG; goto size_error; } +#endif +#ifdef CONFIG_MACH_KONA + *ums_data = kmalloc(65536*2, GFP_KERNEL); +#else *ums_data = kmalloc(fsize, GFP_KERNEL); +#endif if (IS_ERR(*ums_data)) { printk(KERN_ERR "[E-PEN] %s, kmalloc failed\n", __func__); @@ -165,6 +175,10 @@ int wacom_i2c_get_ums_data(struct wacom_i2c *wac_i2c, u8 **ums_data) goto malloc_error; } +#ifdef CONFIG_MACH_KONA + memset((void *)*ums_data, 0xff, 65536*2); +#endif + nread = vfs_read(fp, (char __user *)*ums_data, fsize, &fp->f_pos); printk(KERN_NOTICE "[E-PEN] nread %ld Bytes\n", nread); @@ -223,12 +237,25 @@ int wacom_i2c_fw_update_UMS(struct wacom_i2c *wac_i2c) return 0; } -#if defined(CONFIG_MACH_Q1_BD) || defined(CONFIG_MACH_T0) +#if defined(CONFIG_MACH_Q1_BD) || defined(CONFIG_MACH_T0)\ + || defined(CONFIG_MACH_KONA) int wacom_i2c_firm_update(struct wacom_i2c *wac_i2c) { int ret; int retry = 3; const struct firmware *firm_data = NULL; + +#if defined(CONFIG_MACH_KONA) + u8 *flash_data; + + flash_data = kmalloc(65536*2, GFP_KERNEL); + if (IS_ERR(flash_data)) { + printk(KERN_ERR + "[E-PEN] %s, kmalloc failed\n", __func__); + return -1; + } + memset((void *)flash_data, 0xff, 65536*2); +#endif firmware_updating_state = true; @@ -242,8 +269,14 @@ int wacom_i2c_firm_update(struct wacom_i2c *wac_i2c) ret, retry); continue; } +#if defined(CONFIG_MACH_KONA) + memcpy((void *)flash_data, + (const void *)firm_data->data, + firm_data->size); + wacom_i2c_set_firm_data((unsigned char *)flash_data); +#else wacom_i2c_set_firm_data((unsigned char *)firm_data->data); - +#endif ret = wacom_i2c_flash(wac_i2c); if (ret == 0) { @@ -259,6 +292,10 @@ int wacom_i2c_firm_update(struct wacom_i2c *wac_i2c) } firmware_updating_state = false; + +#if defined(CONFIG_MACH_KONA) + kfree(flash_data); +#endif if (ret < 0) return -1; @@ -535,6 +572,14 @@ static void wacom_i2c_set_input_values(struct i2c_client *client, /* __set_bit(BTN_STYLUS2, input_dev->keybit); */ /* __set_bit(ABS_MISC, input_dev->absbit); */ + + /*softkey*/ +#ifdef WACOM_USE_SOFTKEY + __set_bit(EV_LED, input_dev->evbit); + __set_bit(LED_MISC, input_dev->ledbit); + __set_bit(KEY_MENU, input_dev->keybit); + __set_bit(KEY_BACK, input_dev->keybit); +#endif } static int wacom_check_emr_prox(struct wacom_g5_callbacks *cb) @@ -1349,6 +1394,9 @@ static int wacom_i2c_probe(struct i2c_client *client, /*Set switch type*/ wac_i2c->invert_pen_insert = wacom_i2c_invert_by_switch_type(); +#elif defined(CONFIG_MACH_KONA) + wac_i2c->wac_pdata->late_resume_platform_hw(); + msleep(200); #endif #ifdef WACOM_PDCT_WORK_AROUND wac_i2c->pen_pdct = PDCT_NOSIGNAL; @@ -1447,7 +1495,7 @@ static int wacom_i2c_probe(struct i2c_client *client, printk(KERN_ERR "[E-PEN] exynos_cpufreq_get_level Error\n"); #ifdef SEC_BUS_LOCK wac_i2c->dvfs_lock_status = false; -#if defined(CONFIG_MACH_P4NOTE) +#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA) wac_i2c->bus_dev = dev_get("exynos-busfreq"); #endif /* CONFIG_MACH_P4NOTE */ #endif /* SEC_BUS_LOCK */ diff --git a/drivers/input/touchscreen/wacom/wacom_i2c_firm.c b/drivers/input/touchscreen/wacom/wacom_i2c_firm.c index fddb8c9..f826f86 100644 --- a/drivers/input/touchscreen/wacom/wacom_i2c_firm.c +++ b/drivers/input/touchscreen/wacom/wacom_i2c_firm.c @@ -71,6 +71,13 @@ char Firmware_checksum[] = { 0x1F, 0x27, 0x85, 0x8B, 0xFB, }; const char B713X_checksum[] = { 0x1F, 0xB5, 0x84, 0x38, 0x34, }; /*checksum for 0x16*/ const char B660X_checksum[] = { 0x1F, 0x83, 0x88, 0xD4, 0x67, }; +#elif defined(CONFIG_MACH_KONA) +const unsigned int Binary_nLength = 0xCBCB; +const unsigned char Mpu_type = 0x00; +unsigned int Firmware_version_of_file = 0x65D; +unsigned char *firmware_name = "epen/W9002_B781.bin"; + +char Firmware_checksum[] = { 0x1F, 0x72, 0xCD, 0x6E, 0xE3, }; #endif void wacom_i2c_set_firm_data(unsigned char *Binary_new) diff --git a/drivers/input/touchscreen/wacom/wacom_i2c_flash.c b/drivers/input/touchscreen/wacom/wacom_i2c_flash.c index 691e66c..cf92018 100644 --- a/drivers/input/touchscreen/wacom/wacom_i2c_flash.c +++ b/drivers/input/touchscreen/wacom/wacom_i2c_flash.c @@ -73,6 +73,28 @@ int wacom_i2c_flash_cmd(struct wacom_i2c *wac_i2c) int ret, len, i; u8 buf[10], flashq; + +#if defined(CONFIG_MACH_KONA) + buf[0] = 0x0d; + buf[1] = FLASH_START0; + buf[2] = FLASH_START1; + buf[3] = FLASH_START2; + buf[4] = FLASH_START3; + buf[5] = FLASH_START4; + buf[6] = FLASH_START5; + buf[7] = 0x0d; + + printk(KERN_DEBUG "[E-PEN][jjals] w9002 running!!\n"); + + len = 8; + ret = i2c_master_send(wac_i2c->client, buf, len); + + if (ret < 0) { + printk(KERN_ERR + "Sending flash command failed\n"); + return -1; + } +#else buf[0] = 0x0d; buf[1] = FLASH_START0; @@ -110,8 +132,7 @@ int wacom_i2c_flash_cmd(struct wacom_i2c *wac_i2c) printk(KERN_DEBUG "[E-PEN]: flash send?:%d\n", ret); msleep(270); } - - wac_i2c->boot_mode = true; +#endif return 0; } @@ -174,6 +195,9 @@ int wacom_i2c_flash_enter(struct wacom_i2c *wac_i2c) { if (wacom_i2c_flash_query(wac_i2c, FLASH_QUERY, FLASH_ACK) == -1) return ERR_NOT_FLASH; + + wac_i2c->boot_mode = true; + return 0; } diff --git a/drivers/input/touchscreen/wacom/wacom_i2c_func.c b/drivers/input/touchscreen/wacom/wacom_i2c_func.c index 18a7900..a981cbc 100644 --- a/drivers/input/touchscreen/wacom/wacom_i2c_func.c +++ b/drivers/input/touchscreen/wacom/wacom_i2c_func.c @@ -381,7 +381,8 @@ int wacom_i2c_query(struct wacom_i2c *wac_i2c) #if defined(CONFIG_MACH_Q1_BD)\ || defined(CONFIG_MACH_P4NOTE)\ - || defined(CONFIG_MACH_T0) + || defined(CONFIG_MACH_T0)\ + || defined(CONFIG_MACH_KONA) wac_feature->x_max = (u16) WACOM_MAX_COORD_X; wac_feature->y_max = (u16) WACOM_MAX_COORD_Y; #else @@ -425,7 +426,7 @@ int wacom_i2c_query(struct wacom_i2c *wac_i2c) } wac_i2c->query_status = true; -#if defined(CONFIG_MACH_P4NOTE) +#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA) wacom_checksum(wac_i2c); #endif @@ -797,6 +798,9 @@ static bool wacom_i2c_coord_range(s16 *x, s16 *y) #if defined(CONFIG_MACH_T0) if ((*x >= 0) && (*y >= 0) && (*x <= WACOM_POSX_MAX) && (*y <= WACOM_POSY_MAX - 50)) +#elif defined(CONFIG_MACH_KONA) + if ((*x >= WACOM_POSX_OFFSET) && (*y >= WACOM_POSX_OFFSET) && + (*x <= WACOM_POSY_MAX) && (*y <= WACOM_POSX_MAX)) #else if ((*x <= WACOM_POSX_MAX) && (*y <= WACOM_POSY_MAX)) #endif @@ -805,6 +809,29 @@ static bool wacom_i2c_coord_range(s16 *x, s16 *y) return false; } +#ifdef WACOM_USE_SOFTKEY +static int keycode[] = { + KEY_MENU, KEY_BACK, +}; +void wacom_i2c_softkey(struct wacom_i2c *wac_i2c, s16 key, s16 pressed) +{ + if (gpio_get_value(wac_i2c->wac_pdata->gpio_pendct) && pressed) + forced_release(wac_i2c); + + input_report_key(wac_i2c->input_dev, + keycode[key], pressed); + input_sync(wac_i2c->input_dev); + +#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP) + printk(KERN_DEBUG "[E-PEN] keycode:%d pressed:%d\n", + keycode[key], pressed); +#else + printk(KERN_DEBUG "[E-PEN] pressed:%d\n", + pressed); +#endif +} +#endif + int wacom_i2c_coord(struct wacom_i2c *wac_i2c) { bool prox = false; @@ -817,6 +844,9 @@ int wacom_i2c_coord(struct wacom_i2c *wac_i2c) u8 gain = 0; u8 height = 0; int aveStrength = 2; +#ifdef WACOM_USE_SOFTKEY + static s16 softkey, pressed, keycode; +#endif #ifdef WACOM_IRQ_WORK_AROUND cancel_delayed_work(&wac_i2c->pendct_dwork); @@ -854,6 +884,15 @@ int wacom_i2c_coord(struct wacom_i2c *wac_i2c) pr_debug("[E-PEN] is in(%d)\n", wac_i2c->tool); #endif } +#ifdef WACOM_USE_SOFTKEY + softkey = !!(data[5] & 0x80); + if (softkey) { + pressed = !!(data[5] & 0x40); + keycode = (data[5] & 0x30) >> 4; + wacom_i2c_softkey(wac_i2c, keycode, pressed); + return 0; + } +#endif prox = !!(data[0] & 0x10); stylus = !!(data[0] & 0x20); @@ -976,9 +1015,16 @@ int wacom_i2c_coord(struct wacom_i2c *wac_i2c) wac_i2c->side_pressed = stylus; } #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) - else + else { printk(KERN_DEBUG "[E-PEN] raw data x=%d, y=%d\n", x, y); +#ifdef CONFIG_MACH_KONA + /* Pen should be released in the NOT AA area even if rdy value is 1. */ + if (wac_i2c->pen_pressed || wac_i2c->side_pressed + || wac_i2c->pen_prox) + forced_release(wac_i2c); +#endif + } #endif } else { diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index aeedd90..cc7c047 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -652,6 +652,15 @@ config VIDEO_SLP_S5C73M3 ---help--- This driver supports s5c73m3 ISP camera module with MIPI CSI-2 as well +config VIDEO_SR130PC20 + tristate "SR130PC20 camera driver" + depends on I2C && VIDEO_V4L2 + ---help--- + This driver supports SR130PC20 SoC camera module. + The SR130PC20 camera module uses siliconfile camera sensor + supporting 1.3M capture with MIPI interface. And also, It support + VGA recording with 25fps. + config VIDEO_IMPROVE_STREAMOFF bool "Improve shtter lag" depends on VIDEO_FIMC_MIPI diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 64f0f5b..7ce4839 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -92,6 +92,7 @@ obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3.o obj-$(CONFIG_VIDEO_ISX012) += isx012.o obj-$(CONFIG_VIDEO_S5C73M3_SPI) += s5c73m3_spi.o +obj-$(CONFIG_VIDEO_SR130PC20) += sr130pc20.o obj-$(CONFIG_VIDEO_SLP_S5C73M3) += slp_s5c73m3.o obj-$(CONFIG_VIDEO_SLP_S5K4ECGX) += slp_s5k4ecgx.o obj-$(CONFIG_VIDEO_SLP_DB8131M) += slp_db8131m.o diff --git a/drivers/media/video/isx012.c b/drivers/media/video/isx012.c index 427d59b..e33a430 100644 --- a/drivers/media/video/isx012.c +++ b/drivers/media/video/isx012.c @@ -28,6 +28,7 @@ #define isx012_wait_ae_stable_cap(sd) isx012_wait_ae_stable(sd, false, false) static int dbg_level; +static u32 VendorID; static const struct isx012_fps isx012_framerates[] = { { I_FPS_0, FRAME_RATE_AUTO }, @@ -42,6 +43,11 @@ static const struct isx012_framesize isx012_preview_frmsizes[] = { { PREVIEW_SZ_320x240, 320, 240 }, { PREVIEW_SZ_CIF, 352, 288 }, { PREVIEW_SZ_528x432, 528, 432 }, +#if defined(CONFIG_MACH_P4NOTELTE_KOR_SKT) \ + || defined(CONFIG_MACH_P4NOTELTE_KOR_KT) \ + || defined(CONFIG_MACH_P4NOTELTE_KOR_LGT) /*For 4G VT call in Domestic*/ + { PREVIEW_SZ_VERTICAL_VGA, 480, 640 }, +#endif { PREVIEW_SZ_VGA, 640, 480 }, { PREVIEW_SZ_D1, 720, 480 }, { PREVIEW_SZ_880x720, 880, 720 }, @@ -83,154 +89,167 @@ static struct isx012_control isx012_ctrls[] = { static const struct isx012_regs reg_datas = { .ev = { ISX012_REGSET(GET_EV_INDEX(EV_MINUS_4), - ISX012_ExpSetting_M4Step), + ISX012_ExpSetting_M4Step, 0), ISX012_REGSET(GET_EV_INDEX(EV_MINUS_3), - ISX012_ExpSetting_M3Step), + ISX012_ExpSetting_M3Step, 0), ISX012_REGSET(GET_EV_INDEX(EV_MINUS_2), - ISX012_ExpSetting_M2Step), + ISX012_ExpSetting_M2Step, 0), ISX012_REGSET(GET_EV_INDEX(EV_MINUS_1), - ISX012_ExpSetting_M1Step), + ISX012_ExpSetting_M1Step, 0), ISX012_REGSET(GET_EV_INDEX(EV_DEFAULT), - ISX012_ExpSetting_Default), + ISX012_ExpSetting_Default, 0), ISX012_REGSET(GET_EV_INDEX(EV_PLUS_1), - ISX012_ExpSetting_P1Step), + ISX012_ExpSetting_P1Step, 0), ISX012_REGSET(GET_EV_INDEX(EV_PLUS_2), - ISX012_ExpSetting_P2Step), + ISX012_ExpSetting_P2Step, 0), ISX012_REGSET(GET_EV_INDEX(EV_PLUS_3), - ISX012_ExpSetting_P3Step), + ISX012_ExpSetting_P3Step, 0), ISX012_REGSET(GET_EV_INDEX(EV_PLUS_4), - ISX012_ExpSetting_P4Step), + ISX012_ExpSetting_P4Step, 0), }, .metering = { - ISX012_REGSET(METERING_MATRIX, isx012_Metering_Matrix), - ISX012_REGSET(METERING_CENTER, isx012_Metering_Center), - ISX012_REGSET(METERING_SPOT, isx012_Metering_Spot), + ISX012_REGSET(METERING_MATRIX, isx012_Metering_Matrix, 0), + ISX012_REGSET(METERING_CENTER, isx012_Metering_Center, 0), + ISX012_REGSET(METERING_SPOT, isx012_Metering_Spot, 0), }, .iso = { - ISX012_REGSET(ISO_AUTO, isx012_ISO_Auto), - ISX012_REGSET(ISO_50, isx012_ISO_50), - ISX012_REGSET(ISO_100, isx012_ISO_100), - ISX012_REGSET(ISO_200, isx012_ISO_200), - ISX012_REGSET(ISO_400, isx012_ISO_400), + ISX012_REGSET(ISO_AUTO, isx012_ISO_Auto, 0), + ISX012_REGSET(ISO_50, isx012_ISO_50, 0), + ISX012_REGSET(ISO_100, isx012_ISO_100, 0), + ISX012_REGSET(ISO_200, isx012_ISO_200, 0), + ISX012_REGSET(ISO_400, isx012_ISO_400, 0), }, .effect = { - ISX012_REGSET(IMAGE_EFFECT_NONE, isx012_Effect_Normal), - ISX012_REGSET(IMAGE_EFFECT_BNW, isx012_Effect_Black_White), - ISX012_REGSET(IMAGE_EFFECT_SEPIA, isx012_Effect_Sepia), + ISX012_REGSET(IMAGE_EFFECT_NONE, isx012_Effect_Normal, 0), + ISX012_REGSET(IMAGE_EFFECT_BNW, isx012_Effect_Black_White, 0), + ISX012_REGSET(IMAGE_EFFECT_SEPIA, isx012_Effect_Sepia, 0), ISX012_REGSET(IMAGE_EFFECT_NEGATIVE, - ISX012_Effect_Negative), - ISX012_REGSET(IMAGE_EFFECT_SOLARIZE, isx012_Effect_Solar), - ISX012_REGSET(IMAGE_EFFECT_SKETCH, isx012_Effect_Sketch), - ISX012_REGSET(IMAGE_EFFECT_POINT_COLOR_3, isx012_Effect_Pastel), + ISX012_Effect_Negative, 0), + ISX012_REGSET(IMAGE_EFFECT_SOLARIZE, isx012_Effect_Solar, 0), + ISX012_REGSET(IMAGE_EFFECT_SKETCH, isx012_Effect_Sketch, 0), + ISX012_REGSET(IMAGE_EFFECT_POINT_COLOR_3, + isx012_Effect_Pastel, 0), }, .white_balance = { - ISX012_REGSET(WHITE_BALANCE_AUTO, isx012_WB_Auto), - ISX012_REGSET(WHITE_BALANCE_SUNNY, isx012_WB_Sunny), - ISX012_REGSET(WHITE_BALANCE_CLOUDY, isx012_WB_Cloudy), + ISX012_REGSET(WHITE_BALANCE_AUTO, isx012_WB_Auto, 0), + ISX012_REGSET(WHITE_BALANCE_SUNNY, isx012_WB_Sunny, 0), + ISX012_REGSET(WHITE_BALANCE_CLOUDY, isx012_WB_Cloudy, 0), ISX012_REGSET(WHITE_BALANCE_TUNGSTEN, - isx012_WB_Tungsten), + isx012_WB_Tungsten, 0), ISX012_REGSET(WHITE_BALANCE_FLUORESCENT, - isx012_WB_Fluorescent), + isx012_WB_Fluorescent, 0), }, .scene_mode = { - ISX012_REGSET(SCENE_MODE_NONE, isx012_Scene_Default), - ISX012_REGSET(SCENE_MODE_PORTRAIT, isx012_Scene_Portrait), - ISX012_REGSET(SCENE_MODE_NIGHTSHOT, isx012_Scene_Nightshot), - ISX012_REGSET(SCENE_MODE_BACK_LIGHT, isx012_Scene_Backlight), - ISX012_REGSET(SCENE_MODE_LANDSCAPE, isx012_Scene_Landscape), - ISX012_REGSET(SCENE_MODE_SPORTS, isx012_Scene_Sports), + ISX012_REGSET(SCENE_MODE_NONE, isx012_Scene_Default, 0), + ISX012_REGSET(SCENE_MODE_PORTRAIT, isx012_Scene_Portrait, 0), + ISX012_REGSET(SCENE_MODE_NIGHTSHOT, isx012_Scene_Nightshot, 0), + ISX012_REGSET(SCENE_MODE_BACK_LIGHT, isx012_Scene_Backlight, 0), + ISX012_REGSET(SCENE_MODE_LANDSCAPE, isx012_Scene_Landscape, 0), + ISX012_REGSET(SCENE_MODE_SPORTS, isx012_Scene_Sports, 0), ISX012_REGSET(SCENE_MODE_PARTY_INDOOR, - isx012_Scene_Party_Indoor), - ISX012_REGSET(SCENE_MODE_BEACH_SNOW, isx012_Scene_Beach_Snow), - ISX012_REGSET(SCENE_MODE_SUNSET, isx012_Scene_Sunset), - ISX012_REGSET(SCENE_MODE_DUSK_DAWN, isx012_Scene_Duskdawn), - ISX012_REGSET(SCENE_MODE_FALL_COLOR, isx012_Scene_Fall_Color), - ISX012_REGSET(SCENE_MODE_FIREWORKS, isx012_Scene_Fireworks), - ISX012_REGSET(SCENE_MODE_TEXT, isx012_Scene_Text), + isx012_Scene_Party_Indoor, 0), + ISX012_REGSET(SCENE_MODE_BEACH_SNOW, + isx012_Scene_Beach_Snow, 0), + ISX012_REGSET(SCENE_MODE_SUNSET, isx012_Scene_Sunset, 0), + ISX012_REGSET(SCENE_MODE_DUSK_DAWN, isx012_Scene_Duskdawn, 0), + ISX012_REGSET(SCENE_MODE_FALL_COLOR, + isx012_Scene_Fall_Color, 0), + ISX012_REGSET(SCENE_MODE_FIREWORKS, isx012_Scene_Fireworks, 0), + ISX012_REGSET(SCENE_MODE_TEXT, isx012_Scene_Text, 0), ISX012_REGSET(SCENE_MODE_CANDLE_LIGHT, - isx012_Scene_Candle_Light), + isx012_Scene_Candle_Light, 0), }, .saturation = { - ISX012_REGSET(SATURATION_MINUS_2, isx012_Saturation_Minus_2), - ISX012_REGSET(SATURATION_MINUS_1, isx012_Saturation_Minus_1), - ISX012_REGSET(SATURATION_DEFAULT, isx012_Saturation_Default), - ISX012_REGSET(SATURATION_PLUS_1, isx012_Saturation_Plus_1), - ISX012_REGSET(SATURATION_PLUS_2, isx012_Saturation_Plus_2), + ISX012_REGSET(SATURATION_MINUS_2, isx012_Saturation_Minus_2, 0), + ISX012_REGSET(SATURATION_MINUS_1, isx012_Saturation_Minus_1, 0), + ISX012_REGSET(SATURATION_DEFAULT, isx012_Saturation_Default, 0), + ISX012_REGSET(SATURATION_PLUS_1, isx012_Saturation_Plus_1, 0), + ISX012_REGSET(SATURATION_PLUS_2, isx012_Saturation_Plus_2, 0), }, .contrast = { - ISX012_REGSET(CONTRAST_MINUS_2, isx012_Contrast_Minus_2), - ISX012_REGSET(CONTRAST_MINUS_1, isx012_Contrast_Minus_1), - ISX012_REGSET(CONTRAST_DEFAULT, isx012_Contrast_Default), - ISX012_REGSET(CONTRAST_PLUS_1, isx012_Contrast_Plus_1), - ISX012_REGSET(CONTRAST_PLUS_2, isx012_Contrast_Plus_2), + ISX012_REGSET(CONTRAST_MINUS_2, isx012_Contrast_Minus_2, 0), + ISX012_REGSET(CONTRAST_MINUS_1, isx012_Contrast_Minus_1, 0), + ISX012_REGSET(CONTRAST_DEFAULT, isx012_Contrast_Default, 0), + ISX012_REGSET(CONTRAST_PLUS_1, isx012_Contrast_Plus_1, 0), + ISX012_REGSET(CONTRAST_PLUS_2, isx012_Contrast_Plus_2, 0), }, .sharpness = { - ISX012_REGSET(SHARPNESS_MINUS_2, isx012_Sharpness_Minus_2), - ISX012_REGSET(SHARPNESS_MINUS_1, isx012_Sharpness_Minus_1), - ISX012_REGSET(SHARPNESS_DEFAULT, isx012_Sharpness_Default), - ISX012_REGSET(SHARPNESS_PLUS_1, isx012_Sharpness_Plus_1), - ISX012_REGSET(SHARPNESS_PLUS_2, isx012_Sharpness_Plus_2), + ISX012_REGSET(SHARPNESS_MINUS_2, isx012_Sharpness_Minus_2, 0), + ISX012_REGSET(SHARPNESS_MINUS_1, isx012_Sharpness_Minus_1, 0), + ISX012_REGSET(SHARPNESS_DEFAULT, isx012_Sharpness_Default, 0), + ISX012_REGSET(SHARPNESS_PLUS_1, isx012_Sharpness_Plus_1, 0), + ISX012_REGSET(SHARPNESS_PLUS_2, isx012_Sharpness_Plus_2, 0), }, .fps = { - ISX012_REGSET(I_FPS_0, isx012_fps_auto), - ISX012_REGSET(I_FPS_7, isx012_fps_7fix), - ISX012_REGSET(I_FPS_15, isx012_fps_15fix), - ISX012_REGSET(I_FPS_25, isx012_fps_25fix), - ISX012_REGSET(I_FPS_30, isx012_fps_30fix), + ISX012_REGSET(I_FPS_0, isx012_fps_auto, 0), + ISX012_REGSET(I_FPS_7, isx012_fps_7fix, 0), + ISX012_REGSET(I_FPS_15, isx012_fps_15fix, 0), + ISX012_REGSET(I_FPS_25, isx012_fps_25fix, 0), + ISX012_REGSET(I_FPS_30, isx012_fps_30fix, 0), }, .preview_size = { - ISX012_REGSET(PREVIEW_SZ_320x240, isx012_320_Preview), - ISX012_REGSET(PREVIEW_SZ_VGA, isx012_640_Preview), - ISX012_REGSET(PREVIEW_SZ_D1, isx012_720_Preview), - ISX012_REGSET(PREVIEW_SZ_XGA, isx012_1024_768_Preview), - ISX012_REGSET(PREVIEW_SZ_PVGA, isx012_1280_Preview_E), + ISX012_REGSET(PREVIEW_SZ_320x240, isx012_320_Preview, 0), +#if defined(CONFIG_MACH_P4NOTELTE_KOR_SKT) \ + || defined(CONFIG_MACH_P4NOTELTE_KOR_KT) \ + || defined(CONFIG_MACH_P4NOTELTE_KOR_LGT) /*For 4G VT call in Domestic*/ + ISX012_REGSET(PREVIEW_SZ_VERTICAL_VGA, isx012_480_Preview, 0), +#endif + ISX012_REGSET(PREVIEW_SZ_VGA, isx012_640_Preview, 0), + ISX012_REGSET(PREVIEW_SZ_D1, isx012_720_Preview, 0), + ISX012_REGSET(PREVIEW_SZ_XGA, isx012_1024_768_Preview, 0), + ISX012_REGSET(PREVIEW_SZ_PVGA, isx012_1280_Preview_E, 0), }, .capture_size = { - ISX012_REGSET(CAPTURE_SZ_VGA, isx012_VGA_Capture), - ISX012_REGSET(CAPTURE_SZ_960_720, isx012_960_720_Capture), - ISX012_REGSET(CAPTURE_SZ_3MP, isx012_3M_Capture), - ISX012_REGSET(CAPTURE_SZ_5MP, isx012_5M_Capture), + ISX012_REGSET(CAPTURE_SZ_VGA, isx012_VGA_Capture, 0), + ISX012_REGSET(CAPTURE_SZ_960_720, isx012_960_720_Capture, 0), + ISX012_REGSET(CAPTURE_SZ_3MP, isx012_3M_Capture, 0), + ISX012_REGSET(CAPTURE_SZ_5MP, isx012_5M_Capture, 0), }, /* AF */ - .af_window_reset = ISX012_REGSET_TABLE(ISX012_AF_Window_Reset), - .af_winddow_set = ISX012_REGSET_TABLE(ISX012_AF_Window_Set), - .af_restart = ISX012_REGSET_TABLE(ISX012_AF_ReStart), - .af_saf_off = ISX012_REGSET_TABLE(ISX012_AF_SAF_OFF), - .af_touch_saf_off = ISX012_REGSET_TABLE(ISX012_AF_TouchSAF_OFF), - .cancel_af_macro = ISX012_REGSET_TABLE(ISX012_AF_Cancel_Macro_ON), - .cancel_af_normal = ISX012_REGSET_TABLE(ISX012_AF_Cancel_Macro_OFF), - .af_macro_mode = ISX012_REGSET_TABLE(ISX012_AF_Macro_ON), - .af_normal_mode = ISX012_REGSET_TABLE(ISX012_AF_Macro_OFF), - .af_camcorder_start = ISX012_REGSET_TABLE(ISX012_Camcorder_SAF_Start), + .af_window_reset = ISX012_REGSET_TABLE(ISX012_AF_Window_Reset, 1), + .af_winddow_set = ISX012_REGSET_TABLE(ISX012_AF_Window_Set, 0), + .af_restart = ISX012_REGSET_TABLE(ISX012_AF_ReStart, 0), + .af_saf_off = ISX012_REGSET_TABLE(ISX012_AF_SAF_OFF, 0), + .af_touch_saf_off = ISX012_REGSET_TABLE(ISX012_AF_TouchSAF_OFF, 0), + .cancel_af_macro = ISX012_REGSET_TABLE(ISX012_AF_Cancel_Macro_ON, 0), + .cancel_af_normal = ISX012_REGSET_TABLE(ISX012_AF_Cancel_Macro_OFF, 0), + .af_macro_mode = ISX012_REGSET_TABLE(ISX012_AF_Macro_ON, 0), + .af_normal_mode = ISX012_REGSET_TABLE(ISX012_AF_Macro_OFF, 0), + .af_camcorder_start = ISX012_REGSET_TABLE( + ISX012_Camcorder_SAF_Start, 0), /* Flash */ - .flash_ae_line = ISX012_REGSET_TABLE(ISX012_Flash_AELINE), - .flash_on = ISX012_REGSET_TABLE(ISX012_Flash_ON), - .flash_off = ISX012_REGSET_TABLE(ISX012_Flash_OFF), - .ae_manual = ISX012_REGSET_TABLE(ISX012_ae_manual_mode), - .flash_fast_ae_awb = ISX012_REGSET_TABLE(ISX012_flash_fast_ae_awb), + .flash_ae_line = ISX012_REGSET_TABLE(ISX012_Flash_AELINE, 0), + .flash_on = ISX012_REGSET_TABLE(ISX012_Flash_ON, 1), + .flash_off = ISX012_REGSET_TABLE(ISX012_Flash_OFF, 1), + .ae_manual = ISX012_REGSET_TABLE(ISX012_ae_manual_mode, 0), + .flash_fast_ae_awb = ISX012_REGSET_TABLE(ISX012_flash_fast_ae_awb, 0), - .init_reg = ISX012_REGSET_TABLE(ISX012_Init_Reg), + .init_reg = ISX012_REGSET_TABLE(ISX012_Init_Reg, 1), /* Camera mode */ - .preview_mode = ISX012_REGSET_TABLE(ISX012_Preview_Mode), - .capture_mode = ISX012_REGSET_TABLE(ISX012_Capture_Mode), + .preview_mode = ISX012_REGSET_TABLE(ISX012_Preview_Mode, 0), + .capture_mode = ISX012_REGSET_TABLE(ISX012_Capture_Mode, 0), .capture_mode_night = - ISX012_REGSET_TABLE(ISX012_Lowlux_Night_Capture_Mode), - .halfrelease_mode = ISX012_REGSET_TABLE(ISX012_Halfrelease_Mode), + ISX012_REGSET_TABLE(ISX012_Lowlux_Night_Capture_Mode, 0), + .halfrelease_mode = ISX012_REGSET_TABLE(ISX012_Halfrelease_Mode, 0), .halfrelease_mode_night = - ISX012_REGSET_TABLE(ISX012_Lowlux_night_Halfrelease_Mode), - .camcorder_on = ISX012_REGSET_TABLE(ISX012_Camcorder_Mode_ON), - .camcorder_off = ISX012_REGSET_TABLE(ISX012_Camcorder_Mode_OFF), - - .lowlux_night_reset = ISX012_REGSET_TABLE(ISX012_Lowlux_Night_Reset), - - .set_pll_4 = ISX012_REGSET_TABLE(ISX012_Pll_Setting_4), - .softlanding = ISX012_REGSET_TABLE(ISX012_Sensor_Off_VCM), + ISX012_REGSET_TABLE(ISX012_Lowlux_night_Halfrelease_Mode, 0), + .camcorder_on = ISX012_REGSET_TABLE(ISX012_Camcorder_Mode_ON, 1), + .camcorder_off = ISX012_REGSET_TABLE(ISX012_Camcorder_Mode_OFF, 1), + + .lowlux_night_reset = ISX012_REGSET_TABLE(ISX012_Lowlux_Night_Reset, 0), + + .set_pll_4 = ISX012_REGSET_TABLE(ISX012_Pll_Setting_4, 1), + .shading_0 = ISX012_REGSET_TABLE(ISX012_Shading_0, 1), + .shading_1 = ISX012_REGSET_TABLE(ISX012_Shading_1, 1), + .shading_2 = ISX012_REGSET_TABLE(ISX012_Shading_2, 1), + .shading_nocal = ISX012_REGSET_TABLE(ISX012_Shading_Nocal, 1), + .softlanding = ISX012_REGSET_TABLE(ISX012_Sensor_Off_VCM, 0), #if 0 /* def CONFIG_VIDEO_ISX012_P8*/ - .antibanding = ISX012_REGSET_TABLE(ISX012_ANTIBANDING_REG), + .antibanding = ISX012_REGSET_TABLE(ISX012_ANTIBANDING_REG, 0), #endif }; @@ -854,6 +873,8 @@ static int isx012_i2c_burst_write_list(struct v4l2_subdev *sd, struct i2c_msg msg = {isx012_client->addr, 0, 4, buf}; + cam_trace("%s\n", name); + if (!isx012_client->adapter) { printk(KERN_ERR "%s: %d can't search i2c client adapter\n", __func__, __LINE__); return -EIO; @@ -965,7 +986,12 @@ static int isx012_set_from_table(struct v4l2_subdev *sd, table->name); # endif /* DEBUG_WRITE_REGS */ - err = isx012_write_regs(sd, table->reg, table->array_size); + if (table->burst) { + err = isx012_i2c_burst_write_list(sd, + table->reg, table->array_size, setting_name); + } else + err = isx012_write_regs(sd, table->reg, table->array_size); + CHECK_ERR_MSG(err, "write regs(%s), err=%d\n", setting_name, err); return 0; @@ -2098,11 +2124,11 @@ static int isx012_do_af(struct v4l2_subdev *sd, u32 touch) break; af_dbg("AF state= %d(0x%X)\n", read_value, read_value); - msleep_debug(30, false); + msleep_debug(10, false); } if (unlikely(count >= AF_SEARCH_COUNT)) { - cam_warn("warning, AF check failed. val=0x%X\n\n", read_value); + cam_warn("warning, AF check timeout. val=0x%X\n\n", read_value); isx012_writeb(sd, REG_INTCLR, 0x10); goto check_fail; } @@ -2195,6 +2221,13 @@ static int isx012_set_af(struct v4l2_subdev *sd, s32 val) state->focus.start = val; if (val == AUTO_FOCUS_ON) { + if ((state->runmode != RUNMODE_RUNNING) && + (state->runmode != RUNMODE_RECORDING)) { + cam_err("error, AF can't start, not in preview\n"); + state->focus.start = AUTO_FOCUS_OFF; + return -ESRCH; + } + err = queue_work(state->workqueue, &state->af_work); if (likely(err)) state->focus.status = AF_RESULT_DOING; @@ -2604,6 +2637,10 @@ static int isx012_control_stream(struct v4l2_subdev *sd, u32 cmd) #if !defined(CONFIG_VIDEO_IMPROVE_STREAMOFF) state->capture.pre_req = 0; #endif + + if (state->focus.status == AF_RESULT_DOING) + isx012_set_af(sd, AUTO_FOCUS_OFF); + if (!((state->runmode == RUNMODE_RUNNING) && state->capture.pre_req)) { isx012_writeb(sd, 0x00BF, 0x01); @@ -3126,8 +3163,10 @@ static int isx012_s_mbus_fmt(struct v4l2_subdev *sd, isx012_set_framesize(sd, isx012_preview_frmsizes, ARRAY_SIZE(isx012_preview_frmsizes), true); - if (previous_index != state->preview.frmsize->index) + if ((state->preview.frmsize != NULL) && + (previous_index != state->preview.frmsize->index)) state->preview.update_frmsize = 1; + } else { /* * In case of image capture mode, @@ -3136,6 +3175,15 @@ static int isx012_s_mbus_fmt(struct v4l2_subdev *sd, isx012_set_framesize(sd, isx012_capture_frmsizes, ARRAY_SIZE(isx012_capture_frmsizes), false); + /* for maket app. + * Samsung camera app does not use unmatched ratio.*/ + if (unlikely(NULL == state->preview.frmsize)) { + cam_warn("warning, capture without preview resolution\n"); + } else if (unlikely(FRM_RATIO(state->preview.frmsize) + != FRM_RATIO(state->capture.frmsize))) { + cam_warn("warning, capture ratio " \ + "is different with preview ratio\n"); + } } return 0; @@ -3540,22 +3588,9 @@ static int isx012_s_stream(struct v4l2_subdev *sd, int enable) return 0; } -#if 0 /* DSLIM */ -static int isx012_reset(struct v4l2_subdev *sd, u32 val) -{ - struct isx012_state *state = to_state(sd); - - cam_trace("EX\n"); - - isx012_return_focus(sd); - state->initialized = 0; - - return 0; -} -#endif - void isx012_Sensor_Calibration(struct v4l2_subdev *sd) { + struct isx012_state *state = to_state(sd); int status = 0; int temp = 0; @@ -3573,11 +3608,14 @@ void isx012_Sensor_Calibration(struct v4l2_subdev *sd) /* Write Shading Table */ if (temp == 0x0) - ISX012_BURST_WRITE_LIST(ISX012_Shading_0); + isx012_set_from_table(sd, "Shading_0", + &state->regs->shading_0, 1, 0); else if (temp == 0x1) - ISX012_BURST_WRITE_LIST(ISX012_Shading_1); + isx012_set_from_table(sd, "Shading_1", + &state->regs->shading_1, 1, 0); else if (temp == 0x2) - ISX012_BURST_WRITE_LIST(ISX012_Shading_2); + isx012_set_from_table(sd, "Shading_2", + &state->regs->shading_2, 1, 0); /* Write NorR */ isx012_readw(sd, 0x0054, &status); @@ -3615,11 +3653,14 @@ void isx012_Sensor_Calibration(struct v4l2_subdev *sd) /* Write Shading Table */ if (temp == 0x0) - ISX012_BURST_WRITE_LIST(ISX012_Shading_0); + isx012_set_from_table(sd, "Shading_0", + &state->regs->shading_0, 1, 0); else if (temp == 0x1) - ISX012_BURST_WRITE_LIST(ISX012_Shading_1); + isx012_set_from_table(sd, "Shading_1", + &state->regs->shading_1, 1, 0); else if (temp == 0x2) - ISX012_BURST_WRITE_LIST(ISX012_Shading_2); + isx012_set_from_table(sd, "Shading_2", + &state->regs->shading_2, 1, 0); /* Write NorR */ isx012_readw(sd, 0x0045, &status); @@ -3645,7 +3686,8 @@ void isx012_Sensor_Calibration(struct v4l2_subdev *sd) boot_dbg("Cal: PreB read : %x\n", temp); isx012_writew(sd, 0x680A, temp); } else - ISX012_BURST_WRITE_LIST(ISX012_Shading_Nocal); + isx012_set_from_table(sd, "Shading_nocal", + &state->regs->shading_nocal, 1, 0); } } @@ -3658,10 +3700,46 @@ static inline int isx012_check_i2c(struct v4l2_subdev *sd, u16 data) if (unlikely(err)) return err; - cam_info("version: 0x%04X is 0x6017?\n", val); + cam_dbg("version: 0x%04X is 0x6017?\n", val); + return 0; +} + +static int isx012_check_vendorid(struct v4l2_subdev *sd) +{ + struct isx012_state *state = to_state(sd); + int status = 0; + int temp = 0; + int temp_msb = 0; + int temp_lsb = 0; + + /* Read OTP version */ + isx012_readw(sd, 0x004F, &status); + cam_dbg("OTP : 0x004F read 0x%04X\n", status); + if ((status & 0x10) == 0x10) { + isx012_readw(sd, 0x0051, &status); + temp = (status&0xFFFC); + cam_dbg("OTP1 : 0x0051 read : 0x%04X\n", temp); + } else { + isx012_readw(sd, 0x0042, &status); + temp = status&0xFFFC; + cam_dbg("OTP0 : 0x0042 read : 0x%04X\n", temp); + } + + temp_msb = (temp&0x03FC) << 6; + temp_lsb = (temp&0xFC00) >> 10; + VendorID = temp_msb | temp_lsb; + cam_info("Vendor ID: 0x%04X\n", VendorID); + return 0; } +u32 isx012_get_vendorid(void) +{ + cam_dbg("VendorID: 0x%04X\n", VendorID); + + return VendorID; +} + static int isx012_post_poweron(struct v4l2_subdev *sd) { struct isx012_state *state = to_state(sd); @@ -3675,7 +3753,14 @@ static int isx012_post_poweron(struct v4l2_subdev *sd) cam_err("%s: error, I2C check fail\n", __func__); return err; } - cam_info("I2C check success!\n"); + cam_dbg("I2C check success!\n"); + + err = isx012_check_vendorid(sd); + if (err) { + cam_err("%s: error, VendorID check fail\n", __func__); + return err; + } + cam_dbg("VendorID check success!\n"); msleep_debug(10, false); err = isx012_is_om_changed(sd); @@ -3953,8 +4038,8 @@ static int is_sysdev(struct device *dev, void *str) return !strcmp(dev_name(dev), (char *)str) ? 1 : 0; } -ssize_t cam_loglevel_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t cam_loglevel_show(struct device *dev, + struct device_attribute *attr, char *buf) { char temp_buf[60] = {0,}; @@ -3980,8 +4065,9 @@ ssize_t cam_loglevel_show(struct device *dev, struct device_attribute *attr, return strlen(buf); } -ssize_t cam_loglevel_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t cam_loglevel_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { printk(KERN_DEBUG "CAM buf=%s, count=%d\n", buf, count); @@ -4056,6 +4142,6 @@ static void __exit v4l2_i2c_drv_cleanup(void) module_init(v4l2_i2c_drv_init); module_exit(v4l2_i2c_drv_cleanup); -MODULE_DESCRIPTION("LSI ISX012 3MP SOC camera driver"); +MODULE_DESCRIPTION("SONY ISX012 5MP SOC camera driver"); MODULE_AUTHOR("Dong-Seong Lim "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/isx012.h b/drivers/media/video/isx012.h index 5e65195..e427cc2 100644 --- a/drivers/media/video/isx012.h +++ b/drivers/media/video/isx012.h @@ -38,9 +38,9 @@ /* #define CONFIG_DEBUG_NO_FRAME */ /** Debuging Feature **/ -/* #define CONFIG_CAM_DEBUG */ -/* #define CONFIG_CAM_TRACE */ /* Enable it with CONFIG_CAM_DEBUG */ -/* #define CONFIG_CAM_AF_DEBUG *//* Enable it with CONFIG_CAM_DEBUG */ +#define CONFIG_CAM_DEBUG +#define CONFIG_CAM_TRACE /* Enable it with CONFIG_CAM_DEBUG */ +#define CONFIG_CAM_AF_DEBUG //* Enable it with CONFIG_CAM_DEBUG */ /* #define DEBUG_WRITE_REGS */ /***********************************/ @@ -193,6 +193,11 @@ enum isx012_preview_frame_size { PREVIEW_SZ_320x240, /* 320x240 */ PREVIEW_SZ_CIF, /* 352x288 */ PREVIEW_SZ_528x432, /* 528x432 */ +#if defined(CONFIG_MACH_P4NOTELTE_KOR_SKT) \ + || defined(CONFIG_MACH_P4NOTELTE_KOR_KT) \ + || defined(CONFIG_MACH_P4NOTELTE_KOR_LGT) /*For 4G VT call in Domestic*/ + PREVIEW_SZ_VERTICAL_VGA, /* 480x640 */ +#endif PREVIEW_SZ_VGA, /* 640x480 */ PREVIEW_SZ_D1, /* 720x480 */ PREVIEW_SZ_880x720, /* 880x720 */ @@ -458,12 +463,12 @@ struct regset_table { const char *const name; }; -#define ISX012_REGSET(x, y) \ +#define ISX012_REGSET(x, y, z) \ [(x)] = { \ .name = #y, \ } -#define ISX012_REGSET_TABLE(y) \ +#define ISX012_REGSET_TABLE(y, z) \ { \ .name = #y, \ } @@ -476,31 +481,36 @@ struct regset_table { #ifdef DEBUG_WRITE_REGS const char * const name; #endif + const u32 burst; /* on/off */ }; #ifdef DEBUG_WRITE_REGS -#define ISX012_REGSET(x, y) \ +#define ISX012_REGSET(x, y, z) \ [(x)] = { \ .reg = (y), \ .array_size = ARRAY_SIZE((y)), \ .name = #y, \ + .burst = z, \ } -#define ISX012_REGSET_TABLE(y) \ +#define ISX012_REGSET_TABLE(y, z) \ { \ .reg = (y), \ .array_size = ARRAY_SIZE((y)), \ .name = #y, \ + .burst = z, \ } #else /* !DEBUG_WRITE_REGS */ -#define ISX012_REGSET(x, y) \ +#define ISX012_REGSET(x, y, z) \ [(x)] = { \ .reg = (y), \ .array_size = ARRAY_SIZE((y)), \ + .burst = z, \ } -#define ISX012_REGSET_TABLE(y) \ +#define ISX012_REGSET_TABLE(y, z) \ { \ .reg = (y), \ .array_size = ARRAY_SIZE((y)), \ + .burst = z, \ } #endif /* DEBUG_WRITE_REGS */ @@ -558,6 +568,11 @@ struct isx012_regs { struct regset_table init_reg; struct regset_table set_pll_4; + struct regset_table shading_0; + struct regset_table shading_1; + struct regset_table shading_2; + struct regset_table shading_nocal; + #ifdef CONFIG_VIDEO_ISX012_P8 struct regset_table antibanding; #endif /* CONFIG_VIDEO_ISX012_P8 */ @@ -658,7 +673,7 @@ extern int isx012_create_file(struct class *cls); #define ISX012_CNT_CM_CHECK 280 /* 160 -> 180 */ #define ISX012_CNT_STREAMOFF 300 -#define AF_SEARCH_COUNT 200 +#define AF_SEARCH_COUNT 550 /* about 6s */ #define AE_STABLE_SEARCH_COUNT 7 /* Sensor AF first,second window size. @@ -736,6 +751,10 @@ extern int isx012_create_file(struct class *cls); #define TUNING_FILE_PATH "/mnt/sdcard/isx012_regs.h" #endif /* CONFIG_LOAD_FILE*/ +#ifdef CONFIG_MACH_KONA +#include "isx012_regs_kona.h" +#else /* P4NOTE */ #include "isx012_regs.h" +#endif #endif /* __ISX012_H__ */ diff --git a/drivers/media/video/isx012_regs.h b/drivers/media/video/isx012_regs.h index fa8de0c..0bb1a28 100644 --- a/drivers/media/video/isx012_regs.h +++ b/drivers/media/video/isx012_regs.h @@ -28,7 +28,7 @@ /* change 4129 to 4802 */ #define AE_SCL_SUBRACT_VALUE 4802 -const uint16_t aeoffset_table[] = { // normal 4.6times +static const uint16_t aeoffset_table[] = { /* normal 4.6times */ 0, 35, 70, 103, 136, 167, 198, 228, 257, 285, 313, 339, 366, 391, 416, 441, 465, 488, 511, 533, 555, 576, 597, 618, 638, 657, 677, 696, 714, 732, @@ -4760,7 +4760,6 @@ static const isx012_regset_t isx012_720_Preview[] = { {0x0090,0x02D0,0x02}, //HSIZE_MONI : 720 {0x0096,0x01E0,0x02}, //VSIZE_MONI : 480 - }; static const isx012_regset_t isx012_640_Preview[] = @@ -4769,6 +4768,15 @@ static const isx012_regset_t isx012_640_Preview[] = {0x0096,0x01E0,0x02}, //VSIZE_MONI : 480 }; +#if defined(CONFIG_MACH_P4NOTELTE_KOR_SKT) \ + || defined(CONFIG_MACH_P4NOTELTE_KOR_KT) \ + || defined(CONFIG_MACH_P4NOTELTE_KOR_LGT) /*For 4G VT call in Domestic*/ +static const isx012_regset_t isx012_480_Preview[] = { +{0x0090, 0x01E0, 0x02}, /* HSIZE_MONI : 480 */ +{0x0096, 0x0280, 0x02}, /* VSIZE_MONI : 640 */ +}; +#endif + static const isx012_regset_t isx012_320_Preview[] = { {0x0090,0x0140,0x02}, //HSIZE_MONI : 320 @@ -11223,7 +11231,7 @@ static const isx012_regset_t ISX012_ae_manual_mode[] = static const isx012_regset_t ISX012_flash_fast_ae_awb[] = { {0x5E32,0x0A,0x01}, -{0x5E3D,0x05,0x01}, +{0x5E3D,0x05,0x01}, /* Don't fix me. 0x05 */ {0x0181,0x01,0x01}, // CAP_HALF_AE_CTRL {0x00B2,0x03,0x01}, //AFMODE_MONI : AF OFF diff --git a/drivers/media/video/isx012_regs_kona.h b/drivers/media/video/isx012_regs_kona.h new file mode 100644 index 0000000..9d9496b --- /dev/null +++ b/drivers/media/video/isx012_regs_kona.h @@ -0,0 +1,11284 @@ +/* drivers/media/video/s5k5ccgx_regs-p4w.h + * + * Driver for s5k5ccgx (5MP Camera) from SEC(LSI), firmware EVT1.1 + * + * Copyright (C) 2010, SAMSUNG ELECTRONICS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Change Date: 2012.06.28 + */ + +#ifndef __ISX012_REGS_H__ +#define __ISX012_REGS_H__ + +#define AE_OFSETVAL 3450 //for tuning // max 5.1times +#define AE_MAXDIFF 4000 //for tuning // max =< 5000 +#define GLOWLIGHT_DEFAULT 0x002B //for tuning +#define GLOWLIGHT_ISO50 0xB52A //for tuning +#define GLOWLIGHT_ISO100 0x9DBA //for tuning +#define GLOWLIGHT_ISO200 0x864A //for tuning +#define GLOWLIGHT_ISO400 0x738A //for tuning + +#define ESD_VALUE 0xA6A6 + +/* change 4129 to 4802 */ +#define AE_SCL_SUBRACT_VALUE 4802 + +static const uint16_t aeoffset_table[] = { /* normal 4.6times */ + 0, 35, 70, 103, 136, 167, 198, 228, 257, 285, + 313, 339, 366, 391, 416, 441, 465, 488, 511, 533, + 555, 576, 597, 618, 638, 657, 677, 696, 714, 732, + 750, 768, 785, 802, 818, 835, 851, 866, 882, 897, + 912, 927, 941, 955, 969, 983, 997, 1010, 1023, 1036, + 1049, 1061, 1074, 1086, 1098, 1109, 1121, 1133, 1144, 1155, + 1166, 1177, 1187, 1198, 1208, 1219, 1229, 1239, 1248, 1258, + 1268, 1277, 1286, 1296, 1305, 1314, 1322, 1331, 1340, 1348, + 1357, 1365, 1373, 1381, 1389, 1397, 1405, 1413, 1420, 1428, + 1435, 1443, 1450, 1457, 1464, 1471, 1478, 1485, 1492, 1499, + 1505, 1512, 1518, 1525, 1531, 1538, 1544, 1550, 1556, 1562, + 1568, 1574, 1580, 1585, 1591, 1597, 1602, 1608, 1613, 1619, + 1624, 1629, 1635, 1640, 1645, 1650, 1655, 1660, 1665, 1670, + 1675, 1679, 1684, 1689, 1693, 1698, 1703, 1707, 1712, 1716, + 1720, 1725, 1729, 1733, 1737, 1742, 1746, 1750, 1754, 1758, + 1762, 1766, 1770, 1774, 1777, 1781, 1785, 1789, 1792, 1796, + 1800, 1803, 1807, 1810, 1814, 1817, 1821, 1824, 1828, 1831, + 1834, 1837, 1841, 1844, 1847, 1850, 1853, 1856, 1860, 1863, + 1866, 1869, 1872, 1875, 1877, 1880, 1883, 1886, 1889, 1892, + 1894, 1897, 1900, 1903, 1905, 1908, 1911, 1913, 1916, 1918, + 1921, 1923, 1926, 1928, 1931, 1933, 1936, 1938, 1941, 1943, + 1945, 1948, 1950, 1952, 1954, 1957, 1959, 1961, 1963, 1965, + 1968, 1970, 1972, 1974, 1976, 1978, 1980, 1982, 1984, 1986, + 1988, 1990, 1992, 1994, 1996, 1998, 2000, 2002, 2003, 2005, + 2007, 2009, 2011, 2013, 2014, 2016, 2018, 2020, 2021, 2023, + 2025, 2026, 2028, 2030, 2031, 2033, 2034, 2036, 2038, 2039, + 2041, 2042, 2044, 2045, 2047, 2048, 2050, 2051, 2053, 2054, + 2056, 2057, 2059, 2060, 2061, 2063, 2064, 2066, 2067, 2068, + 2070, 2071, 2072, 2074, 2075, 2076, 2077, 2079, 2080, 2081, + 2082, 2084, 2085, 2086, 2087, 2089, 2090, 2091, 2092, 2093, + 2094, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, + 2105, 2106, 2107, 2109, 2110, 2111, 2112, 2113, 2114, 2115, + 2116, 2117, 2118, 2119, 2120, 2120, 2121, 2122, 2123, 2124, + 2125, 2126, 2127, 2128, 2129, 2130, 2130, 2131, 2132, 2133, + 2134, 2135, 2136, 2136, 2137, 2138, 2139, 2140, 2141, 2141, + 2142, 2143, 2144, 2144, 2145, 2146, 2147, 2148, 2148, 2149, + 2150, 2150, 2151, 2152, 2153, 2153, 2154, 2155, 2155, 2156, + 2157, 2158, 2158, 2159, 2160, 2160, 2161, 2162, 2162, 2163, + 2163, 2164, 2165, 2165, 2166, 2167, 2167, 2168, 2168, 2169, + 2170, 2170, 2171, 2171, 2172, 2172, 2173, 2174, 2174, 2175, + 2175, 2176, 2176, 2177, 2177, 2178, 2179, 2179, 2180, 2180, + 2181, 2181, 2182, 2182, 2183, 2183, 2184, 2184, 2185, 2185, + 2186, 2186, 2186, 2187, 2187, 2188, 2188, 2189, 2189, 2190, + 2190, 2191, 2191, 2191, 2192, 2192, 2193, 2193, 2194, 2194, + 2194, 2195, 2195, 2196, 2196, 2196, 2197, 2197, 2198, 2198, + 2198, 2199, 2199, 2200, 2200, 2200, 2201, 2201, 2201, 2202, + 2202, 2203, 2203, 2203, 2204, 2204, 2204, 2205, 2205, 2205, + 2206, 2206, 2206, 2207, 2207, 2207, 2208, 2208, 2208, 2209, + 2209, 2209, 2210, 2210, 2210, 2210, 2211, 2211, 2211, 2212, + 2212, 2212, 2213, 2213, 2213, 2213, 2214, 2214, 2214, 2214, +}; + +static const isx012_regset_t ISX012_Init_Reg[] = +{ +///////////////////////////////////// +//AF driver setting//³»ºÎ AF driver// +///////////////////////////////////// +{0x66C2,0x0C,0x01},//AF_INTERNAL_LENSDRV_ADRS +{0x66C3,0x02,0x01},//AF_INTERNAL_LENSDRV_SIZE +{0x66C5,0x14,0x01},//AF_INTERNAL_LENSDRV_SHIFT +{0x66C8,0x0000,0x02},//AF_INTERNAL_LENSDRV_FIXEDPTN +{0x66CA,0x000F,0x02}, +{0x000B,0x01,0x01},//AF_EXT : AF driver start + +////////////////////////////////////////// +// ISX012_Initial_Setting.ini // +////////////////////////////////////////// +// AE window add V02 +{0x6000,0x06,0x01}, // CENTER_FIXWEIGHT_00_TYPE1 : +{0x6001,0x06,0x01}, // CENTER_FIXWEIGHT_01_TYPE1 : +{0x6002,0x06,0x01}, // CENTER_FIXWEIGHT_02_TYPE1 : +{0x6003,0x06,0x01}, // CENTER_FIXWEIGHT_03_TYPE1 : +{0x6004,0x06,0x01}, // CENTER_FIXWEIGHT_04_TYPE1 : +{0x6005,0x06,0x01}, // CENTER_FIXWEIGHT_05_TYPE1 : +{0x6006,0x06,0x01}, // CENTER_FIXWEIGHT_06_TYPE1 : +{0x6007,0x06,0x01}, // CENTER_FIXWEIGHT_07_TYPE1 : +{0x6008,0x06,0x01}, // CENTER_FIXWEIGHT_08_TYPE1 : +{0x6009,0x0C,0x01}, // CENTER_FIXWEIGHT_09_TYPE1 : +{0x600A,0x0C,0x01}, // CENTER_FIXWEIGHT_10_TYPE1 : +{0x600B,0x0C,0x01}, // CENTER_FIXWEIGHT_11_TYPE1 : +{0x600C,0x10,0x01}, // CENTER_FIXWEIGHT_12_TYPE1 : +{0x600D,0x10,0x01}, // CENTER_FIXWEIGHT_13_TYPE1 : +{0x600E,0x10,0x01}, // CENTER_FIXWEIGHT_14_TYPE1 : +{0x600F,0x0C,0x01}, // CENTER_FIXWEIGHT_15_TYPE1 : +{0x6010,0x0C,0x01}, // CENTER_FIXWEIGHT_16_TYPE1 : +{0x6011,0x0C,0x01}, // CENTER_FIXWEIGHT_17_TYPE1 : +{0x6012,0x0C,0x01}, // CENTER_FIXWEIGHT_18_TYPE1 : +{0x6013,0x0C,0x01}, // CENTER_FIXWEIGHT_19_TYPE1 : +{0x6014,0x18,0x01}, // CENTER_FIXWEIGHT_20_TYPE1 : +{0x6015,0x18,0x01}, // CENTER_FIXWEIGHT_21_TYPE1 : +{0x6016,0x18,0x01}, // CENTER_FIXWEIGHT_22_TYPE1 : +{0x6017,0x18,0x01}, // CENTER_FIXWEIGHT_23_TYPE1 : +{0x6018,0x18,0x01}, // CENTER_FIXWEIGHT_24_TYPE1 : +{0x6019,0x0C,0x01}, // CENTER_FIXWEIGHT_25_TYPE1 : +{0x601A,0x0C,0x01}, // CENTER_FIXWEIGHT_26_TYPE1 : +{0x601B,0x0C,0x01}, // CENTER_FIXWEIGHT_27_TYPE1 : +{0x601C,0x18,0x01}, // CENTER_FIXWEIGHT_28_TYPE1 : +{0x601D,0x18,0x01}, // CENTER_FIXWEIGHT_29_TYPE1 : +{0x601E,0x1E,0x01}, // CENTER_FIXWEIGHT_30_TYPE1 : +{0x601F,0x1E,0x01}, // CENTER_FIXWEIGHT_31_TYPE1 : +{0x6020,0x1E,0x01}, // CENTER_FIXWEIGHT_32_TYPE1 : +{0x6021,0x18,0x01}, // CENTER_FIXWEIGHT_33_TYPE1 : +{0x6022,0x18,0x01}, // CENTER_FIXWEIGHT_34_TYPE1 : +{0x6023,0x0C,0x01}, // CENTER_FIXWEIGHT_35_TYPE1 : +{0x6024,0x0C,0x01}, // CENTER_FIXWEIGHT_36_TYPE1 : +{0x6025,0x18,0x01}, // CENTER_FIXWEIGHT_37_TYPE1 : +{0x6026,0x18,0x01}, // CENTER_FIXWEIGHT_38_TYPE1 : +{0x6027,0x1E,0x01}, // CENTER_FIXWEIGHT_39_TYPE1 : +{0x6028,0x1E,0x01}, // CENTER_FIXWEIGHT_40_TYPE1 : +{0x6029,0x1E,0x01}, // CENTER_FIXWEIGHT_41_TYPE1 : +{0x602A,0x18,0x01}, // CENTER_FIXWEIGHT_42_TYPE1 : +{0x602B,0x18,0x01}, // CENTER_FIXWEIGHT_43_TYPE1 : +{0x602C,0x0C,0x01}, // CENTER_FIXWEIGHT_44_TYPE1 : +{0x602D,0x0C,0x01}, // CENTER_FIXWEIGHT_45_TYPE1 : +{0x602E,0x0C,0x01}, // CENTER_FIXWEIGHT_46_TYPE1 : +{0x602F,0x18,0x01}, // CENTER_FIXWEIGHT_47_TYPE1 : +{0x6030,0x18,0x01}, // CENTER_FIXWEIGHT_48_TYPE1 : +{0x6031,0x18,0x01}, // CENTER_FIXWEIGHT_49_TYPE1 : +{0x6032,0x18,0x01}, // CENTER_FIXWEIGHT_50_TYPE1 : +{0x6033,0x18,0x01}, // CENTER_FIXWEIGHT_51_TYPE1 : +{0x6034,0x0C,0x01}, // CENTER_FIXWEIGHT_52_TYPE1 : +{0x6035,0x0C,0x01}, // CENTER_FIXWEIGHT_53_TYPE1 : +{0x6036,0x0C,0x01}, // CENTER_FIXWEIGHT_54_TYPE1 : +{0x6037,0x0C,0x01}, // CENTER_FIXWEIGHT_55_TYPE1 : +{0x6038,0x0C,0x01}, // CENTER_FIXWEIGHT_56_TYPE1 : +{0x6039,0x0C,0x01}, // CENTER_FIXWEIGHT_57_TYPE1 : +{0x603A,0x0C,0x01}, // CENTER_FIXWEIGHT_58_TYPE1 : +{0x603B,0x0C,0x01}, // CENTER_FIXWEIGHT_59_TYPE1 : +{0x603C,0x0C,0x01}, // CENTER_FIXWEIGHT_60_TYPE1 : +{0x603D,0x0C,0x01}, // CENTER_FIXWEIGHT_61_TYPE1 : +{0x603E,0x0C,0x01}, // CENTER_FIXWEIGHT_62_TYPE1 : + + +//AF filter +{0x6D14,0x0001,0x02}, // HPF_HBPF_CORSL_Y1 : +{0x6D16,0x0001,0x02}, // HPF_HBPF_CORSL_Y2 : +{0x6D18,0x0002,0x02}, // HPF_HBPF_CORSL_Y3 : +{0x6D1A,0x0005,0x02}, // HPF_HBPF_CORSL_Y4 : + +{0x6D20,0x0004,0x02}, // HPF_HBPF_CORL_Y1 : +{0x6D22,0x0004,0x02}, // HPF_HBPF_CORL_Y2 : +{0x6D24,0x000F,0x02}, // HPF_HBPF_CORL_Y3 : +{0x6D26,0x001E,0x02}, // HPF_HBPF_CORL_Y4 : + +{0x6D2C,0x000E,0x02}, // HPF_HBPF_CORH_Y1 : +{0x6D2E,0x000F,0x02}, // HPF_HBPF_CORH_Y2 : +{0x6D30,0x0022,0x02}, // HPF_HBPF_CORH_Y3 : +{0x6D32,0x004D,0x02}, // HPF_HBPF_CORH_Y4 : + +{0x6D44,0x0001,0x02}, // HPF_LBPF_CORSL_Y1 : +{0x6D46,0x0001,0x02}, // HPF_LBPF_CORSL_Y2 : +{0x6D48,0x0002,0x02}, // HPF_LBPF_CORSL_Y3 : +{0x6D4A,0x0004,0x02}, // HPF_LBPF_CORSL_Y4 : + +{0x6D50,0x03FF,0x02}, // HPF_LBPF_CORL_Y1 : +{0x6D52,0x03FF,0x02}, // HPF_LBPF_CORL_Y2 : +{0x6D54,0x03FF,0x02}, // HPF_LBPF_CORL_Y3 : +{0x6D56,0x03FF,0x02}, // HPF_LBPF_CORL_Y4 : + +{0x6D5C,0x03FF,0x02}, // HPF_LBPF_CORH_Y1 : +{0x6D5E,0x03FF,0x02}, // HPF_LBPF_CORH_Y2 : +{0x6D60,0x03FF,0x02}, // HPF_LBPF_CORH_Y3 : +{0x6D62,0x03FF,0x02}, // HPF_LBPF_CORH_Y4 : + +{0x6D74,0x0001,0x02}, // HPF_VHBPF_CORSL_Y1 : +{0x6D76,0x0001,0x02}, // HPF_VHBPF_CORSL_Y2 : +{0x6D78,0x0002,0x02}, // HPF_VHBPF_CORSL_Y3 : +{0x6D7A,0x0005,0x02}, // HPF_VHBPF_CORSL_Y4 : + +{0x6D80,0x0004,0x02}, // HPF_VHBPF_CORL_Y1 : +{0x6D82,0x0005,0x02}, // HPF_VHBPF_CORL_Y2 : +{0x6D84,0x000C,0x02}, // HPF_VHBPF_CORL_Y3 : +{0x6D86,0x001C,0x02}, // HPF_VHBPF_CORL_Y4 : + +{0x6D8C,0x000D,0x02}, // HPF_VHBPF_CORH_Y1 : +{0x6D8E,0x0010,0x02}, // HPF_VHBPF_CORH_Y2 : +{0x6D90,0x0026,0x02}, // HPF_VHBPF_CORH_Y3 : +{0x6D92,0x004D,0x02}, // HPF_VHBPF_CORH_Y4 : + +// CAF Ãß°¡ºÎºÐ +{0x6622,0x0004,0x02}, // AF_CAF_PARAM_WOBBLE_STEP : +{0x6624,0x0008,0x02}, // AF_CAF_CLIMB_STEP : +{0x6687,0x01,0x01}, // AF_CAF_CLIMB_PEAK_BACK_STEP_ENABLE : +{0x6698,0x00,0x01}, // AF_CAF_WOBBLE_FILTER_ENABLE : +{0x66A4,0x06,0x01}, // AF_CAF_OPD_FLAT_MOVE_ENABLE : +{0x66B0,0x0002,0x02}, // AF_CAF_WAIT_FOR_AF_STABLE_TH : +{0x5003,0x04,0x01}, // Z1_HOLD = 1 +//110819 +{0x6696,0x16,0x01}, //AF_CAF_WOBBLE_START_INTERVAL_COUNTER +{0x6716,0x0000,0x02}, // CAF_LVD_WOB_HBPF_VAL1 : +{0x6718,0x0000,0x02}, // CAF_LVD_WOB_HBPF_VAL2 : +{0x671A,0x00C8,0x02}, // CAF_LVD_WOB_HBPF_RATE1 : +{0x671C,0x00C8,0x02}, // CAF_LVD_WOB_HBPF_RATE2 : +{0x671E,0x00,0x01}, // CAF_LVD_WOB_HBPF_SHIFT : +{0x6720,0x0000,0x02}, // CAF_LVD_WOB_LBPF_VAL1 : +{0x6722,0x0000,0x02}, // CAF_LVD_WOB_LBPF_VAL2 : +{0x6724,0x0014,0x02}, // CAF_LVD_WOB_LBPF_RATE1 : +{0x6726,0x0014,0x02}, // CAF_LVD_WOB_LBPF_RATE2 : +{0x6728,0x00,0x01}, // CAF_LVD_WOB_LBPF_SHIFT : +{0x672A,0x0000,0x02}, // CAF_LVD_CLMP_HBPF_VAL1 : +{0x672C,0x0000,0x02}, // CAF_LVD_CLMP_HBPF_VAL2 : +{0x672E,0x012C,0x02}, // CAF_LVD_CLMP_HBPF_RATE1 : +{0x6730,0x012C,0x02}, // CAF_LVD_CLMP_HBPF_RATE2 : +{0x6732,0x00,0x01}, // CAF_LVD_CLMP_HBPF_SHIFT : +{0x6734,0x0000,0x02}, // CAF_LVD_CLMP_LBPF_VAL1 : +{0x6736,0x0000,0x02}, // CAF_LVD_CLMP_LBPF_VAL2 : +{0x6738,0x0046,0x02}, // CAF_LVD_CLMP_LBPF_RATE1 : +{0x673A,0x0046,0x02}, // CAF_LVD_CLMP_LBPF_RATE2 : +{0x673C,0x00,0x01}, // CAF_LVD_CLMP_LBPF_SHIFT : +{0x661E,0x00C8,0x02}, //AF_CAF_FAR_POSITION +{0x6620,0x02BC,0x02}, //AF_CAF_NEAR_POSITION + +//Ãß°¡¼ÂÆúκРSAFºÎºÐ +{0x00B2,0x02,0x01}, // AFMODE_MONI : manual AF mode +{0x028E,0x00,0x01}, // AF_SN1_2 : +{0x028F,0x00,0x01}, // AF_SN3_4 : +{0x0290,0x00,0x01}, // AF_SN5_6 : +{0x0291,0x00,0x01}, // AF_SN7_8 : +{0x0292,0x00,0x01}, // AF_SN9_10 : +{0x0293,0x00,0x01}, // AF_SN11_12 : +{0x6604,0x00,0x01}, // AF_SEARCH_DIR : +{0x6616,0x01,0x01}, // AF_DIRECTBACK_F :On=1 +{0x661B,0x03,0x01}, // AF_OPDDATA_SAVE : +{0x661C,0x00,0x01}, // AF_MONOTONY_POS : +{0x663E,0x00,0x01}, // AF_SEARCH_SECOND_DIR : +{0x663F,0x01,0x01}, // AF_DIRECTBACK_SECOND_F : +{0x6674,0x00,0x01}, // AF_MONICHG_MOVE_F : AF off½Ã zero positionÀ¸·Î °¥Áö(01) ÇöÀ§Ä¡¿¡ ÀÖÀ»Áö(00) Á¤ÇÔ +{0x6675,0x01,0x01}, // CAP_AF_CANCEL_F : 1·Î ¼³Á¤½Ã capture¸ðµå¿¡¼­ AFÀÚµ¿ ĵ½½ +{0x6676,0x02,0x01}, // AF_SAxF_MODE : +{0x669E,0x02,0x01}, // AF_SECOND_WND_CHK : +{0x6600,0x00C8,0x02}, // AF_SEARCH_AREA_LOW : +{0x6602,0x02BC,0x02}, // AF_SEARCH_AREA_HIGH : +{0x6640,0x02,0x01}, // AF_DROPN_ON_PEAK_DETECT_SECOND : +{0x6641,0x02,0x01}, // AF_UPN_ON_PEAK_DETECT_SECOND : +{0x6642,0x02,0x01}, //AF_DROPRATE_ON_DETECT_SECOND_HBPF +{0x6643,0x02,0x01}, //AF_DROPRATE_ON_DETECT_SECOND_LBPF +{0x6644,0x14,0x01}, // AF_UPRATE_ON_PEAK_DETECT_HBPF_SECOND : +{0x6646,0x08,0x01}, // AF_OPD_WEIGHT_TH : +{0x664A,0x04,0x01}, // AF_DROPN_ON_PEAK_DETECT : +{0x664B,0x02,0x01}, // AF_UPN_ON_PEAK_DETECT : +{0x664C,0xFF,0x01}, // AF_UPRATE_ON_PEAK_DETECT_HBPF : +{0x665A,0x00C8,0x02}, // AF_LENSPOS_ON_AFNG : +{0x665C,0x0018,0x02}, // AF_DRV_AMOUNT_TONEAR_F : +{0x665E,0x0003,0x02}, // AF_DRV_AMOUNT_TONEAR_S : +{0x6660,0x0018,0x02}, // AF_DRV_AMOUNT_TOFAR_F : +{0x6662,0x0003,0x02}, // AF_DRV_AMOUNT_TOFAR_S : +{0x6666,0x00C8,0x02}, // AF_AREA_LOW_TYPE1 : +{0x6668,0x02BC,0x02}, // AF_AREA_HIGH_TYPE1 : +{0x669A,0x01F4,0x02}, // AF_OPD_MONOTONYUP_HBPF_TH : +{0x66E4,0x50,0x01}, // AF_TH_1STDEPEND_HBPF_RATE : +{0x66EE,0x03E8,0x02}, // AF_LVD_HBPF_VAL1_1ST : +{0x66F0,0x4E20,0x02}, // AF_LVD_HBPF_VAL2_1ST : +{0x66F2,0x004C,0x02}, // AF_LVD_HBPF_RATE1_1ST : +{0x66F4,0x0019,0x02}, // AF_LVD_HBPF_RATE2_1ST : +{0x66F6,0x00,0x01}, // AF_LVD_HBPF_SHIFT_1ST : +{0x6702,0x03E8,0x02}, // AF_LVD_HBPF_VAL1_2ND : +{0x6704,0x4E20,0x02}, // AF_LVD_HBPF_VAL2_2ND : +{0x6706,0x0003,0x02}, // AF_LVD_HBPF_RATE1_2ND : +{0x6708,0x0003,0x02}, // AF_LVD_HBPF_RATE2_2ND : +{0x670A,0x00,0x01}, // AF_LVD_HBPF_SHIFT_2ND : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +//chooys add +{0x6677,0x00,0x01}, // AF_SEND_PARTITION : Use=1 +{0x6678,0x20,0x01}, // AF_SENDNUM_ALL +{0x6679,0x01,0x01}, // AF_SENDNUM_UP +{0x667A,0x01,0x01}, // AF_SENDNUM_DOWN +{0x667C,0x0002,0x02}, // AF_SENDAMOUNT_ADDLIMIT +{0x667E,0x0020,0x02}, //AF_SENDLINE + +// AF opd_TH +{0x660E,0x5A,0x01}, // AF_HBPF_PEAK_OPD_TH_MIN +{0x6610,0x5A,0x01}, // AF_HBPF_PEAK_OPD_TH_MAX + +{0x66E4,0xC8,0x01}, +{0x66E5,0xC8,0x01}, + +//AF opd window setting +{0x6A30,0x044E,0x02}, // AF_OPD0_HDELAY : +{0x6A32,0x02E5,0x02}, // AF_OPD0_VDELAY : +{0x6A34,0x01D8,0x02}, // AF_OPD0_HVALID : +{0x6A36,0x01D8,0x02}, // AF_OPD0_VVALID : +{0x6A38,0x0412,0x02}, // AF_OPD1_HDELAY : +{0x6A3A,0x02A9,0x02}, // AF_OPD1_VDELAY : +{0x6A3C,0x0251,0x02}, // AF_OPD1_HVALID : +{0x6A3E,0x0251,0x02}, // AF_OPD1_VVALID : +{0x6A40,0x04B4,0x02}, // AF_OPD2_HDELAY : +{0x6A42,0x0114,0x02}, // AF_OPD2_VDELAY : +{0x6A44,0x0118,0x02}, // AF_OPD2_HVALID : +{0x6A46,0x0118,0x02}, // AF_OPD2_VVALID : +{0x6A48,0x0469,0x02}, // AF_OPD3_HDELAY : +{0x6A4A,0x00C9,0x02}, // AF_OPD3_VDELAY : +{0x6A4C,0x01AE,0x02}, // AF_OPD3_HVALID : +{0x6A4E,0x01AE,0x02}, // AF_OPD3_VVALID : +{0x6A50,0x04C6,0x02}, // AF_OPD4_HDELAY : +{0x6A52,0x035D,0x02}, // AF_OPD4_VDELAY : +{0x6A54,0x00E6,0x02}, // AF_OPD4_HVALID : +{0x6A56,0x00E6,0x02}, // AF_OPD4_VVALID : +{0x6A58,0x048A,0x02}, // AF_OPD5_HDELAY : +{0x6A5A,0x0321,0x02}, // AF_OPD5_VDELAY : +{0x6A5C,0x015F,0x02}, // AF_OPD5_HVALID : +{0x6A5E,0x015F,0x02}, // AF_OPD5_VVALID : +{0x6A60,0x04B4,0x02}, // AF_OPD6_HDELAY : +{0x6A62,0x0579,0x02}, // AF_OPD6_VDELAY : +{0x6A64,0x0118,0x02}, // AF_OPD6_HVALID : +{0x6A66,0x0118,0x02}, // AF_OPD6_VVALID : +{0x6A68,0x0469,0x02}, // AF_OPD7_HDELAY : +{0x6A6A,0x052C,0x02}, // AF_OPD7_VDELAY : +{0x6A6C,0x01AE,0x02}, // AF_OPD7_HVALID : +{0x6A6E,0x01AE,0x02}, // AF_OPD7_VVALID : +{0x6A70,0x021D,0x02}, // AF_OPD8_HDELAY : +{0x6A72,0x02F5,0x02}, // AF_OPD8_VDELAY : +{0x6A74,0x01AE,0x02}, // AF_OPD8_HVALID : +{0x6A76,0x01AE,0x02}, // AF_OPD8_VVALID : +{0x6A78,0x06A4,0x02}, // AF_OPD9_HDELAY : +{0x6A7A,0x02F5,0x02}, // AF_OPD9_VDELAY : +{0x6A7C,0x01AE,0x02}, // AF_OPD9_HVALID : +{0x6A7E,0x01AE,0x02}, // AF_OPD9_VVALID : +{0x6A80,0x06,0x01}, // AF_OPD1A_WEIGHT : +{0x6A81,0x05,0x01}, // AF_OPD1B_WEIGHT : +{0x6A82,0x02,0x01}, // AF_OPD2A_WEIGHT : +{0x6A83,0x02,0x01}, // AF_OPD2B_WEIGHT : +{0x6A84,0x08,0x01}, // AF_OPD3A_WEIGHT : +{0x6A85,0x07,0x01}, // AF_OPD3B_WEIGHT : +{0x6A86,0x04,0x01}, // AF_OPD4A_WEIGHT : +{0x6A87,0x03,0x01}, // AF_OPD4B_WEIGHT : +{0x6A88,0x01,0x01}, // AF_OPD5A_WEIGHT : +{0x6A89,0x01,0x01}, // AF_OPD5B_WEIGHT : + + +//lee haknoh add +{0x661C,0x00,0x01}, +//S,66BE,0F,8, //AF_JUDGE_CONF +//S,669A,01F4,16, //AF_OPD_MONOTONYUP_HBPF_TH +//S,669C,03E8,16, //AF_OPD_MONOTONYUP_LBPF_TH +{0x673D,0x01,0x01}, //AF_MANUAL_MOVE_TYTPE : manual mode½Ã AF_MANUAL_POS·Î À̵¿ÇÒÁö ¼³Á¤ +{0x6648,0x00C8,0x02}, //AF_MANUAL_POS +{0x66E0,0x00C8,0x02}, //AF_POS_INF_SET +{0x66E2,0x02BC,0x02}, //AF_POS_MACRO_SET +{0x00B2,0x02,0x01}, //AFMODE_MONI : Manual AF mode + + +//Ãß°¡ ¼¼Æà ºÎºÐ +{0x00F7,0x52,0x01}, // INIT_QLTY0 : Standard 82 +{0x00F8,0x59,0x01}, // INIT_QLTY1 : Fine 89 +{0x00F9,0x5F,0x01}, // INIT_QLTY2 : SuperFine 95 + +//minimum shutter speed +{0x6800,0x03,0x01}, //SHTMINLINE + +/////// Normal AE Line ////// +// normal capture AE line +{0x0326,0x21,0x01}, // SHTCTRLTIME1_TYPE1 : +{0x0327,0x19,0x01}, // AGCGAIN1_TYPE1 : +{0x0328,0x52,0x01}, // SHTCTRLTIME2_TYPE1 : +{0x0329,0x23,0x01}, // AGCGAIN2_TYPE1 : +{0x032A,0x3E,0x01}, // SHTCTRLTIME3_TYPE1 : +{0x032B,0x3F,0x01}, // AGCGAIN3_TYPE1 : + +// normal preview AE line +{0x032C,0x7C,0x01}, // SHTCTRLTIME1_TYPE2 +{0x032D,0x3D,0x01}, // AGCGAIN1_TYPE2 +{0x032E,0x7C,0x01}, // SHTCTRLTIME2_TYPE2 +{0x032F,0x3D,0x01}, // AGCGAIN2_TYPE2 +{0x0330,0x3E,0x01}, // SHTCTRLTIME3_TYPE2 +{0x0331,0x3F,0x01}, // AGCGAIN3_TYPE2 + +// flash ae line +{0x0332,0x42,0x01}, // SHTCTRLTIME1_TYPE3 : +{0x0333,0x3C,0x01}, // AGCGAIN1_TYPE3 : +{0x0334,0x42,0x01}, // SHTCTRLTIME2_TYPE3 : +{0x0335,0x3C,0x01}, // AGCGAIN2_TYPE3 : +{0x0336,0x21,0x01}, // SHTCTRLTIME3_TYPE3 : +{0x0337,0x3C,0x01}, // AGCGAIN3_TYPE3 : + +//sports ae line +{0x0338,0x00,0x01}, // SHTCTRLTIME1_TYPE4 +{0x0339,0x14,0x01}, // AGCGAIN1_TYPE4 +{0x033A,0x21,0x01}, // SHTCTRLTIME2_TYPE4 +{0x033B,0x19,0x01}, // AGCGAIN2_TYPE4 +{0x033C,0x3E,0x01}, // SHTCTRLTIME3_TYPE4 +{0x033D,0x3D,0x01}, // AGCGAIN3_TYPE4 + +//night mode AF ae line +{0x033E,0xFF,0x01}, // SHTCTRLTIME1_TYPE5 : +{0x033F,0x00,0x01}, // AGCGAIN1_TYPE5 : +{0x0340,0xFF,0x01}, // SHTCTRLTIME2_TYPE5 : +{0x0341,0x00,0x01}, // AGCGAIN2_TYPE5 : +{0x0342,0xA6,0x01}, // SHTCTRLTIME3_TYPE5 : +{0x0343,0x49,0x01}, // AGCGAIN3_TYPE5 : + +//night mode capture ae line +{0x0344,0xFF,0x01}, // SHTCTRLTIME1_TYPE6 : +{0x0345,0x00,0x01}, // AGCGAIN1_TYPE6 : +{0x0346,0xFF,0x01}, // SHTCTRLTIME2_TYPE6 : +{0x0347,0x00,0x01}, // AGCGAIN2_TYPE6 : +{0x0348,0xFA,0x01}, // SHTCTRLTIME3_TYPE6 : +{0x0349,0x3B,0x01}, // AGCGAIN3_TYPE6 : + +// fire mode line +{0x0356,0x01,0x01}, // SHTCTRLTIME1_TYPE9 : +{0x0357,0x04,0x01}, // AGCGAIN1_TYPE9 : +{0x0358,0x01,0x01}, // SHTCTRLTIME2_TYPE9 : +{0x0359,0x04,0x01}, // AGCGAIN2_TYPE9 : +{0x035A,0xF8,0x01}, // SHTCTRLTIME3_TYPE9 : +{0x035B,0x04,0x01}, // AGCGAIN3_TYPE9 : + +// fire mode AF line +{0x035C,0x01,0x01}, // SHTCTRLTIME1_TYPE10 : +{0x035D,0x04,0x01}, // AGCGAIN1_TYPE10 : +{0x035E,0x01,0x01}, // SHTCTRLTIME2_TYPE10 : +{0x035F,0x04,0x01}, // AGCGAIN2_TYPE10 : +{0x0360,0x21,0x01}, // SHTCTRLTIME3_TYPE10 : +{0x0361,0x3E,0x01}, // AGCGAIN3_TYPE10 : + + +//AE ref tunning +{0x5E8A,0x02,0x01}, // EVREF_GAIN_A : +{0x5E8B,0x02,0x01}, // EVREF_GAIN_B : +{0x5E8C,0xFD,0x01}, // EVREF_GAIN_C : +{0x5E8D,0xFD,0x01}, // EVREF_GAIN_D : +{0x5E8E,0xFD,0x01}, // EVREF_GAIN_E : +{0x5E8F,0x90,0x01}, // EVREF_TH_A : +{0x5E90,0x94,0x01}, // EVREF_TH_B : +{0x5E91,0xA5,0x01}, // EVREF_TH_C : +{0x5E92,0xC0,0x01}, // EVREF_TH_D : +{0x5E93,0xD5,0x01}, // EVREF_TH_E : + + +//gamma Ilumi +{0x9211,0x58,0x01}, // GAIN_TH_A_TYPE3 : +{0x9212,0x63,0x01}, // GAIN_TH_B_TYPE3 : +{0x9213,0x9F,0x01}, // GAIN_TH_C_TYPE3 : + +{0x984E,0x0A,0x01}, // GAMMA0_0CLIP_A : +{0x984F,0x0A,0x01}, // GAMMA0_0CLIP_B : +{0x9850,0x05,0x01}, // GAMMA0_0CLIP_C : +{0x9851,0x1E,0x01}, // GAMMA0_SLOPE_A : +{0x9852,0x1E,0x01}, // GAMMA0_SLOPE_B : +{0x9853,0x1E,0x01}, // GAMMA0_SLOPE_C : +{0x9854,0x0A,0x01}, // GAMMA1_0CLIP_A : +{0x9855,0x0F,0x01}, // GAMMA1_0CLIP_B : +{0x9856,0x0F,0x01}, // GAMMA1_0CLIP_C : +{0x9857,0x32,0x01}, // GAMMA1_SLOPE_A : +{0x9858,0x1E,0x01}, // GAMMA1_SLOPE_B : +{0x9859,0x1E,0x01}, // GAMMA1_SLOPE_C : + + +//Gammma Table 0 +{0x7000,0x0000,0x02}, // G0_KNOT_G0 : +{0x7002,0x0015,0x02}, // G0_KNOT_G1 : +{0x7004,0x002C,0x02}, // G0_KNOT_G2 : +{0x7006,0x0041,0x02}, // G0_KNOT_G3 : +{0x7008,0x004D,0x02}, // G0_KNOT_G4 : +{0x700A,0x005B,0x02}, // G0_KNOT_G5 : +{0x700C,0x0060,0x02}, // G0_KNOT_G6 : +{0x700E,0x0068,0x02}, // G0_KNOT_G7 : +{0x7010,0x006F,0x02}, // G0_KNOT_G8 : +{0x7012,0x0078,0x02}, // G0_KNOT_G9 : +{0x7014,0x0057,0x02}, // G0_KNOT_G10 : +{0x7016,0x0090,0x02}, // G0_KNOT_G11 : +{0x7018,0x00BB,0x02}, // G0_KNOT_G12 : +{0x701A,0x00D6,0x02}, // G0_KNOT_G13 : +{0x701C,0x00E5,0x02}, // G0_KNOT_G14 : +{0x701E,0x00F0,0x02}, // G0_KNOT_G15 : +{0x7020,0x00F9,0x02}, // G0_KNOT_G16 : +{0x7022,0x0103,0x02}, // G0_KNOT_G17 : +{0x7024,0x010C,0x02}, // G0_KNOT_G18 : +{0x7026,0x00,0x01}, // G0_KNOT_R0_OFFSET : +{0x7027,0x00,0x01}, // G0_KNOT_R2_OFFSET : +{0x7028,0x00,0x01}, // G0_KNOT_R4_OFFSET : +{0x7029,0x00,0x01}, // G0_KNOT_R6_OFFSET : +{0x702A,0x00,0x01}, // G0_KNOT_R8_OFFSET : +{0x702B,0x00,0x01}, // G0_KNOT_R10_OFFSET : +{0x702C,0x00,0x01}, // G0_KNOT_R12_OFFSET : +{0x702D,0x00,0x01}, // G0_KNOT_R14_OFFSET : +{0x702E,0x00,0x01}, // G0_KNOT_R16_OFFSET : +{0x702F,0x00,0x01}, // G0_KNOT_R18_OFFSET : +{0x7030,0x00,0x01}, // G0_KNOT_B0_OFFSET : +{0x7031,0x00,0x01}, // G0_KNOT_B2_OFFSET : +{0x7032,0x00,0x01}, // G0_KNOT_B4_OFFSET : +{0x7033,0x00,0x01}, // G0_KNOT_B6_OFFSET : +{0x7034,0x00,0x01}, // G0_KNOT_B8_OFFSET : +{0x7035,0x00,0x01}, // G0_KNOT_B10_OFFSET : +{0x7036,0x00,0x01}, // G0_KNOT_B12_OFFSET : +{0x7037,0x00,0x01}, // G0_KNOT_B14_OFFSET : +{0x7038,0x00,0x01}, // G0_KNOT_B16_OFFSET : +{0x7039,0x00,0x01}, // G0_KNOT_B18_OFFSET : +{0x703A,0x0611,0x02}, // G0_LOWGM_ON_R : +{0x703C,0x1E0A,0x02}, // G0_0CLIP_R : +{0x703E,0x0611,0x02}, // G0_LOWGM_ON_G : +{0x7040,0x1E0A,0x02}, // G0_0CLIP_G : +{0x7042,0x0611,0x02}, // G0_LOWGM_ON_B : +{0x7044,0x1E0A,0x02}, // G0_0CLIP_B : +{0x7046,0x9C,0x01}, // G0_KNOT_GAINCTRL_TH_L : +{0x7047,0xA1,0x01}, // G0_KNOT_GAINCTRL_TH_H : +{0x7048,0x0000,0x02}, // G0_KNOT_L_G0 : +{0x704A,0x0007,0x02}, // G0_KNOT_L_G1 : +{0x704C,0x0016,0x02}, // G0_KNOT_L_G2 : +{0x704E,0x002A,0x02}, // G0_KNOT_L_G3 : +{0x7050,0x0039,0x02}, // G0_KNOT_L_G4 : +{0x7052,0x004A,0x02}, // G0_KNOT_L_G5 : +{0x7054,0x0051,0x02}, // G0_KNOT_L_G6 : +{0x7056,0x005D,0x02}, // G0_KNOT_L_G7 : +{0x7058,0x0065,0x02}, // G0_KNOT_L_G8 : +{0x705A,0x006C,0x02}, // G0_KNOT_L_G9 : +{0x705C,0x004E,0x02}, // G0_KNOT_L_G10 : +{0x705E,0x0083,0x02}, // G0_KNOT_L_G11 : +{0x7060,0x00AA,0x02}, // G0_KNOT_L_G12 : +{0x7062,0x00C8,0x02}, // G0_KNOT_L_G13 : +{0x7064,0x00E1,0x02}, // G0_KNOT_L_G14 : +{0x7066,0x00F5,0x02}, // G0_KNOT_L_G15 : +{0x7068,0x0100,0x02}, // G0_KNOT_L_G16 : +{0x706A,0x0106,0x02}, // G0_KNOT_L_G17 : +{0x706C,0x010C,0x02}, // G0_KNOT_L_G18 : + +//Gammma Table 1 +{0x7200,0x0000,0x02}, // G1_KNOT_G0 : +{0x7202,0x0008,0x02}, // G1_KNOT_G1 : +{0x7204,0x0020,0x02}, // G1_KNOT_G2 : +{0x7206,0x0037,0x02}, // G1_KNOT_G3 : +{0x7208,0x004D,0x02}, // G1_KNOT_G4 : +{0x720A,0x0064,0x02}, // G1_KNOT_G5 : +{0x720C,0x006E,0x02}, // G1_KNOT_G6 : +{0x720E,0x0072,0x02}, // G1_KNOT_G7 : +{0x7210,0x007A,0x02}, // G1_KNOT_G8 : +{0x7212,0x007E,0x02}, // G1_KNOT_G9 : +{0x7214,0x0064,0x02}, // G1_KNOT_G10 : +{0x7216,0x0093,0x02}, // G1_KNOT_G11 : +{0x7218,0x00B7,0x02}, // G1_KNOT_G12 : +{0x721A,0x00CD,0x02}, // G1_KNOT_G13 : +{0x721C,0x00DD,0x02}, // G1_KNOT_G14 : +{0x721E,0x00ED,0x02}, // G1_KNOT_G15 : +{0x7220,0x00F9,0x02}, // G1_KNOT_G16 : +{0x7222,0x0102,0x02}, // G1_KNOT_G17 : +{0x7224,0x0101,0x02}, // G1_KNOT_G18 : +{0x7226,0x00,0x01}, // G1_KNOT_R0_OFFSET : +{0x7227,0x00,0x01}, // G1_KNOT_R2_OFFSET : +{0x7228,0x00,0x01}, // G1_KNOT_R4_OFFSET : +{0x7229,0x00,0x01}, // G1_KNOT_R6_OFFSET : +{0x722A,0x00,0x01}, // G1_KNOT_R8_OFFSET : +{0x722B,0x00,0x01}, // G1_KNOT_R10_OFFSET : +{0x722C,0x00,0x01}, // G1_KNOT_R12_OFFSET : +{0x722D,0x00,0x01}, // G1_KNOT_R14_OFFSET : +{0x722E,0x00,0x01}, // G1_KNOT_R16_OFFSET : +{0x722F,0x00,0x01}, // G1_KNOT_R18_OFFSET : +{0x7230,0x00,0x01}, // G1_KNOT_B0_OFFSET : +{0x7231,0x00,0x01}, // G1_KNOT_B2_OFFSET : +{0x7232,0x00,0x01}, // G1_KNOT_B4_OFFSET : +{0x7233,0x00,0x01}, // G1_KNOT_B6_OFFSET : +{0x7234,0x00,0x01}, // G1_KNOT_B8_OFFSET : +{0x7235,0x00,0x01}, // G1_KNOT_B10_OFFSET : +{0x7236,0x00,0x01}, // G1_KNOT_B12_OFFSET : +{0x7237,0x00,0x01}, // G1_KNOT_B14_OFFSET : +{0x7238,0x00,0x01}, // G1_KNOT_B16_OFFSET : +{0x7239,0x00,0x01}, // G1_KNOT_B18_OFFSET : +{0x723A,0x0321,0x02}, // G1_LOWGM_ON_R : +{0x723C,0x0C00,0x02}, // G1_0CLIP_R : +{0x723E,0x0321,0x02}, // G1_LOWGM_ON_G : +{0x7240,0x0C00,0x02}, // G1_0CLIP_G : +{0x7242,0x0321,0x02}, // G1_LOWGM_ON_B : +{0x7244,0x0C00,0x02}, // G1_0CLIP_B : + + +//Gammma Table 2 +{0x7400,0x0000,0x02}, // G2_KNOT_G0 : +{0x7402,0x000A,0x02}, // G2_KNOT_G1 : +{0x7404,0x0023,0x02}, // G2_KNOT_G2 : +{0x7406,0x0038,0x02}, // G2_KNOT_G3 : +{0x7408,0x003F,0x02}, // G2_KNOT_G4 : +{0x740A,0x0047,0x02}, // G2_KNOT_G5 : +{0x740C,0x004F,0x02}, // G2_KNOT_G6 : +{0x740E,0x0058,0x02}, // G2_KNOT_G7 : +{0x7410,0x005F,0x02}, // G2_KNOT_G8 : +{0x7412,0x0068,0x02}, // G2_KNOT_G9 : +{0x7414,0x0044,0x02}, // G2_KNOT_G10 : +{0x7416,0x0083,0x02}, // G2_KNOT_G11 : +{0x7418,0x00B6,0x02}, // G2_KNOT_G12 : +{0x741A,0x00D1,0x02}, // G2_KNOT_G13 : +{0x741C,0x00E4,0x02}, // G2_KNOT_G14 : +{0x741E,0x00F0,0x02}, // G2_KNOT_G15 : +{0x7420,0x00F9,0x02}, // G2_KNOT_G16 : +{0x7422,0x0103,0x02}, // G2_KNOT_G17 : +{0x7424,0x010C,0x02}, // G2_KNOT_G18 : +{0x7426,0x00,0x01}, // G2_KNOT_R0_OFFSET : +{0x7427,0x00,0x01}, // G2_KNOT_R2_OFFSET : +{0x7428,0x00,0x01}, // G2_KNOT_R4_OFFSET : +{0x7429,0x00,0x01}, // G2_KNOT_R6_OFFSET : +{0x742A,0x00,0x01}, // G2_KNOT_R8_OFFSET : +{0x742B,0x00,0x01}, // G2_KNOT_R10_OFFSET : +{0x742C,0x00,0x01}, // G2_KNOT_R12_OFFSET : +{0x742D,0x00,0x01}, // G2_KNOT_R14_OFFSET : +{0x742E,0x00,0x01}, // G2_KNOT_R16_OFFSET : +{0x742F,0x00,0x01}, // G2_KNOT_R18_OFFSET : +{0x7430,0x00,0x01}, // G2_KNOT_B0_OFFSET : +{0x7431,0x00,0x01}, // G2_KNOT_B2_OFFSET : +{0x7432,0x00,0x01}, // G2_KNOT_B4_OFFSET : +{0x7433,0x00,0x01}, // G2_KNOT_B6_OFFSET : +{0x7434,0x00,0x01}, // G2_KNOT_B8_OFFSET : +{0x7435,0x00,0x01}, // G2_KNOT_B10_OFFSET : +{0x7436,0x00,0x01}, // G2_KNOT_B12_OFFSET : +{0x7437,0x00,0x01}, // G2_KNOT_B14_OFFSET : +{0x7438,0x00,0x01}, // G2_KNOT_B16_OFFSET : +{0x7439,0x00,0x01}, // G2_KNOT_B18_OFFSET : +{0x743A,0x0611,0x02}, // G2_LOWGM_ON_R : +{0x743C,0x1E0A,0x02}, // G2_0CLIP_R : +{0x743E,0x0611,0x02}, // G2_LOWGM_ON_G : +{0x7440,0x1E0A,0x02}, // G2_0CLIP_G : +{0x7442,0x0611,0x02}, // G2_LOWGM_ON_B : +{0x7444,0x1E0A,0x02}, // G2_0CLIP_B : + + +//AWB tuning +{0x64A4,0xFF,0x01}, // OUTFRM_LEFT00 : +{0x64A5,0xFF,0x01}, // OUTFRM_LEFT01 : +{0x64A6,0xFF,0x01}, // OUTFRM_LEFT02 : +{0x64A7,0xFF,0x01}, // OUTFRM_LEFT03 : +{0x64A8,0xFF,0x01}, // OUTFRM_LEFT04 : +{0x64A9,0xFF,0x01}, // OUTFRM_LEFT05 : +{0x64AA,0xFF,0x01}, // OUTFRM_LEFT06 : +{0x64AB,0xFF,0x01}, // OUTFRM_LEFT07 : +{0x64AC,0xFF,0x01}, // OUTFRM_LEFT08 : +{0x64AD,0xFD,0x01}, // OUTFRM_LEFT09 : +{0x64AE,0xCB,0x01}, // OUTFRM_LEFT10 : +{0x64AF,0xA9,0x01}, // OUTFRM_LEFT11 : +{0x64B0,0x90,0x01}, // OUTFRM_LEFT12 : +{0x64B1,0x7D,0x01}, // OUTFRM_LEFT13 : +{0x64B2,0x70,0x01}, // OUTFRM_LEFT14 : +{0x64B3,0x65,0x01}, // OUTFRM_LEFT15 : +{0x64B4,0x5C,0x01}, // OUTFRM_LEFT16 : +{0x64B5,0x55,0x01}, // OUTFRM_LEFT17 : +{0x64B6,0x4F,0x01}, // OUTFRM_LEFT18 : +{0x64B7,0x32,0x01}, // OUTFRM_LEFT19 : +{0x64B8,0x4D,0x01}, // OUTFRM_LEFT20 : +{0x64B9,0x40,0x01}, // OUTFRM_LEFT21 : +{0x64BA,0x2D,0x01}, // OUTFRM_LEFT22 : +{0x64BB,0x2B,0x01}, // OUTFRM_LEFT23 : +{0x64BC,0x29,0x01}, // OUTFRM_LEFT24 : +{0x64BD,0x27,0x01}, // OUTFRM_LEFT25 : +{0x64BE,0x25,0x01}, // OUTFRM_LEFT26 : +{0x64BF,0x23,0x01}, // OUTFRM_LEFT27 : +{0x64C0,0x21,0x01}, // OUTFRM_LEFT28 : +{0x64C1,0x1F,0x01}, // OUTFRM_LEFT29 : +{0x64C2,0x1D,0x01}, // OUTFRM_LEFT30 : +{0x64C3,0x1B,0x01}, // OUTFRM_LEFT31 : +{0x64C4,0x1A,0x01}, // OUTFRM_LEFT32 : +{0x64C5,0x1A,0x01}, // OUTFRM_LEFT33 : +{0x64C6,0x1A,0x01}, // OUTFRM_LEFT34 : +{0x64C7,0x28,0x01}, // OUTFRM_LEFT35 : +{0x64C8,0x27,0x01}, // OUTFRM_LEFT36 : +{0x64C9,0x26,0x01}, // OUTFRM_LEFT37 : +{0x64CA,0xFF,0x01}, // OUTFRM_RIGHT00 : +{0x64CB,0xFF,0x01}, // OUTFRM_RIGHT01 : +{0x64CC,0xFF,0x01}, // OUTFRM_RIGHT02 : +{0x64CD,0xFF,0x01}, // OUTFRM_RIGHT03 : +{0x64CE,0xFF,0x01}, // OUTFRM_RIGHT04 : +{0x64CF,0xFF,0x01}, // OUTFRM_RIGHT05 : +{0x64D0,0xFF,0x01}, // OUTFRM_RIGHT06 : +{0x64D1,0xFF,0x01}, // OUTFRM_RIGHT07 : +{0x64D2,0xFF,0x01}, // OUTFRM_RIGHT08 : +{0x64D3,0xFF,0x01}, // OUTFRM_RIGHT09 : +{0x64D4,0xD3,0x01}, // OUTFRM_RIGHT10 : +{0x64D5,0xB1,0x01}, // OUTFRM_RIGHT11 : +{0x64D6,0x98,0x01}, // OUTFRM_RIGHT12 : +{0x64D7,0x85,0x01}, // OUTFRM_RIGHT13 : +{0x64D8,0x78,0x01}, // OUTFRM_RIGHT14 : +{0x64D9,0x6D,0x01}, // OUTFRM_RIGHT15 : +{0x64DA,0x64,0x01}, // OUTFRM_RIGHT16 : +{0x64DB,0x5D,0x01}, // OUTFRM_RIGHT17 : +{0x64DC,0x57,0x01}, // OUTFRM_RIGHT18 : +{0x64DD,0x63,0x01}, // OUTFRM_RIGHT19 : +{0x64DE,0x5E,0x01}, // OUTFRM_RIGHT20 : +{0x64DF,0x5A,0x01}, // OUTFRM_RIGHT21 : +{0x64E0,0x56,0x01}, // OUTFRM_RIGHT22 : +{0x64E1,0x52,0x01}, // OUTFRM_RIGHT23 : +{0x64E2,0x50,0x01}, // OUTFRM_RIGHT24 : +{0x64E3,0x4E,0x01}, // OUTFRM_RIGHT25 : +{0x64E4,0x4C,0x01}, // OUTFRM_RIGHT26 : +{0x64E5,0x4A,0x01}, // OUTFRM_RIGHT27 : +{0x64E6,0x48,0x01}, // OUTFRM_RIGHT28 : +{0x64E7,0x46,0x01}, // OUTFRM_RIGHT29 : +{0x64E8,0x44,0x01}, // OUTFRM_RIGHT30 : +{0x64E9,0x43,0x01}, // OUTFRM_RIGHT31 : +{0x64EA,0x42,0x01}, // OUTFRM_RIGHT32 : +{0x64EB,0x42,0x01}, // OUTFRM_RIGHT33 : +{0x64EC,0x42,0x01}, // OUTFRM_RIGHT34 : +{0x64ED,0x30,0x01}, // OUTFRM_RIGHT35 : +{0x64EE,0x2F,0x01}, // OUTFRM_RIGHT36 : +{0x64EF,0x2E,0x01}, // OUTFRM_RIGHT37 : +{0x64F0,0x2163,0x02}, // OUTFRM_TOP : +{0x64F2,0x1400,0x02}, // OUTFRM_BOTM : +{0x64F4,0x19,0x01}, // OUTFRM_FLTOP : +{0x64F5,0x14,0x01}, // OUTFRM_FLBOTM : +{0x64F6,0xFF,0x01}, // OUTAIM_LEFT00 : +{0x64F7,0xFF,0x01}, // OUTAIM_LEFT01 : +{0x64F8,0xFF,0x01}, // OUTAIM_LEFT02 : +{0x64F9,0xFF,0x01}, // OUTAIM_LEFT03 : +{0x64FA,0xFF,0x01}, // OUTAIM_LEFT04 : +{0x64FB,0xFF,0x01}, // OUTAIM_LEFT05 : +{0x64FC,0xFF,0x01}, // OUTAIM_LEFT06 : +{0x64FD,0xFF,0x01}, // OUTAIM_LEFT07 : +{0x64FE,0xFF,0x01}, // OUTAIM_LEFT08 : +{0x64FF,0xFF,0x01}, // OUTAIM_LEFT09 : +{0x6500,0x91,0x01}, // OUTAIM_LEFT10 : +{0x6501,0x91,0x01}, // OUTAIM_LEFT11 : +{0x6502,0x91,0x01}, // OUTAIM_LEFT12 : +{0x6503,0x66,0x01}, // OUTAIM_LEFT13 : +{0x6504,0x5D,0x01}, // OUTAIM_LEFT14 : +{0x6505,0x3C,0x01}, // OUTAIM_LEFT15 : +{0x6506,0x3C,0x01}, // OUTAIM_LEFT16 : +{0x6507,0x3C,0x01}, // OUTAIM_LEFT17 : +{0x6508,0x3A,0x01}, // OUTAIM_LEFT18 : +{0x6509,0x39,0x01}, // OUTAIM_LEFT19 : +{0x650A,0x40,0x01}, // OUTAIM_LEFT20 : +{0x650B,0x46,0x01}, // OUTAIM_LEFT21 : +{0x650C,0x42,0x01}, // OUTAIM_LEFT22 : +{0x650D,0x3D,0x01}, // OUTAIM_LEFT23 : +{0x650E,0x3A,0x01}, // OUTAIM_LEFT24 : +{0x650F,0x3E,0x01}, // OUTAIM_LEFT25 : +{0x6510,0x38,0x01}, // OUTAIM_LEFT26 : +{0x6511,0x36,0x01}, // OUTAIM_LEFT27 : +{0x6512,0x34,0x01}, // OUTAIM_LEFT28 : +{0x6513,0x32,0x01}, // OUTAIM_LEFT29 : +{0x6514,0x30,0x01}, // OUTAIM_LEFT30 : +{0x6515,0x2F,0x01}, // OUTAIM_LEFT31 : +{0x6516,0x2D,0x01}, // OUTAIM_LEFT32 : +{0x6517,0x2C,0x01}, // OUTAIM_LEFT33 : +{0x6518,0x2B,0x01}, // OUTAIM_LEFT34 : +{0x6519,0x2A,0x01}, // OUTAIM_LEFT35 : +{0x651A,0x29,0x01}, // OUTAIM_LEFT36 : +{0x651B,0x28,0x01}, // OUTAIM_LEFT37 : +{0x651C,0xFF,0x01}, // OUTAIM_RIGHT00 : +{0x651D,0xFF,0x01}, // OUTAIM_RIGHT01 : +{0x651E,0xFF,0x01}, // OUTAIM_RIGHT02 : +{0x651F,0xFF,0x01}, // OUTAIM_RIGHT03 : +{0x6520,0xFF,0x01}, // OUTAIM_RIGHT04 : +{0x6521,0xFF,0x01}, // OUTAIM_RIGHT05 : +{0x6522,0xFF,0x01}, // OUTAIM_RIGHT06 : +{0x6523,0xFF,0x01}, // OUTAIM_RIGHT07 : +{0x6524,0xFF,0x01}, // OUTAIM_RIGHT08 : +{0x6525,0xFF,0x01}, // OUTAIM_RIGHT09 : +{0x6526,0xD9,0x01}, // OUTAIM_RIGHT10 : +{0x6527,0xB7,0x01}, // OUTAIM_RIGHT11 : +{0x6528,0x96,0x01}, // OUTAIM_RIGHT12 : +{0x6529,0x6C,0x01}, // OUTAIM_RIGHT13 : +{0x652A,0x64,0x01}, // OUTAIM_RIGHT14 : +{0x652B,0x62,0x01}, // OUTAIM_RIGHT15 : +{0x652C,0x62,0x01}, // OUTAIM_RIGHT16 : +{0x652D,0x61,0x01}, // OUTAIM_RIGHT17 : +{0x652E,0x60,0x01}, // OUTAIM_RIGHT18 : +{0x652F,0x5E,0x01}, // OUTAIM_RIGHT19 : +{0x6530,0x5B,0x01}, // OUTAIM_RIGHT20 : +{0x6531,0x4F,0x01}, // OUTAIM_RIGHT21 : +{0x6532,0x48,0x01}, // OUTAIM_RIGHT22 : +{0x6533,0x43,0x01}, // OUTAIM_RIGHT23 : +{0x6534,0x41,0x01}, // OUTAIM_RIGHT24 : +{0x6535,0x40,0x01}, // OUTAIM_RIGHT25 : +{0x6536,0x3D,0x01}, // OUTAIM_RIGHT26 : +{0x6537,0x3B,0x01}, // OUTAIM_RIGHT27 : +{0x6538,0x39,0x01}, // OUTAIM_RIGHT28 : +{0x6539,0x37,0x01}, // OUTAIM_RIGHT29 : +{0x653A,0x36,0x01}, // OUTAIM_RIGHT30 : +{0x653B,0x35,0x01}, // OUTAIM_RIGHT31 : +{0x653C,0x33,0x01}, // OUTAIM_RIGHT32 : +{0x653D,0x32,0x01}, // OUTAIM_RIGHT33 : +{0x653E,0x31,0x01}, // OUTAIM_RIGHT34 : +{0x653F,0x30,0x01}, // OUTAIM_RIGHT35 : +{0x6540,0x2F,0x01}, // OUTAIM_RIGHT36 : +{0x6541,0x2E,0x01}, // OUTAIM_RIGHT37 : +{0x6542,0x1F40,0x02}, // OUTAIM_TOP : +{0x6544,0x1752,0x02}, // OUTAIM_BOTM : +{0x6546,0x19,0x01}, // OUTAIM_FLTOP : +{0x6547,0x17,0x01}, // OUTAIM_FLBOTM : + +{0x657A,0x82,0x01}, // IN_CTMP_FRM_BG0 : +{0x657B,0x78,0x01}, // IN_CTMP_FRM_BG1 : +{0x657C,0x65,0x01}, // IN_CTMP_FRM_BG2 : +{0x657D,0x5B,0x01}, // IN_CTMP_FRM_BG3 : +{0x657E,0x55,0x01}, // IN_CTMP_FRM_BG4 : +{0x657F,0x4F,0x01}, // IN_CTMP_FRM_BG5 : +{0x6580,0x49,0x01}, // IN_CTMP_FRM_BG6 : +{0x6581,0x43,0x01}, // IN_CTMP_FRM_BG7 : +{0x6582,0x3E,0x01}, // IN_CTMP_FRM_BG8 : +{0x6583,0x35,0x01}, // IN_CTMP_FRM_BG9 : +{0x6584,0x30,0x01}, // IN_CTMP_FRM_BG10 : +{0x6585,0x23,0x01}, // IN_CTMP_FRM_RG0 : +{0x6586,0x33,0x01}, // IN_CTMP_FRM_RG1 : +{0x6587,0x3F,0x01}, // IN_CTMP_FRM_RG2 : +{0x6588,0x53,0x01}, // IN_CTMP_FRM_RG3 : +{0x6589,0x63,0x01}, // IN_CTMP_FRM_RG4 : +{0x658A,0x76,0x01}, // IN_CTMP_FRM_RG5 : +{0x658B,0x9A,0x01}, // IN_CTMP_FRM_RG6 : +{0x658C,0x00,0x01}, // IN_CTMP_WEIGHT00_01 : +{0x658D,0x00,0x01}, // IN_CTMP_WEIGHT02_03 : +{0x658E,0x00,0x01}, // IN_CTMP_WEIGHT04_05 : +{0x658F,0x00,0x01}, // IN_CTMP_WEIGHT06_07 : +{0x6590,0x00,0x01}, // IN_CTMP_WEIGHT08_09 : +{0x6591,0x00,0x01}, // IN_CTMP_WEIGHT10_11 : +{0x6592,0x00,0x01}, // IN_CTMP_WEIGHT12_13 : +{0x6593,0x00,0x01}, // IN_CTMP_WEIGHT14_15 : +{0x6594,0x00,0x01}, // IN_CTMP_WEIGHT16_17 : +{0x6595,0x00,0x01}, // IN_CTMP_WEIGHT18_19 : +{0x6596,0x00,0x01}, // IN_CTMP_WEIGHT20_21 : +{0x6597,0x00,0x01}, // IN_CTMP_WEIGHT22_23 : +{0x6598,0x00,0x01}, // IN_CTMP_WEIGHT24_25 : +{0x6599,0x00,0x01}, // IN_CTMP_WEIGHT26_27 : +{0x659A,0x00,0x01}, // IN_CTMP_WEIGHT28_29 : +{0x659B,0x00,0x01}, // IN_CTMP_WEIGHT30_31 : +{0x659C,0x00,0x01}, // IN_CTMP_WEIGHT32_33 : +{0x659D,0x00,0x01}, // IN_CTMP_WEIGHT34_35 : +{0x659E,0x00,0x01}, // IN_CTMP_WEIGHT36_37 : +{0x659F,0x00,0x01}, // IN_CTMP_WEIGHT38_39 : +{0x65A0,0x00,0x01}, // IN_CTMP_WEIGHT40_41 : +{0x65A1,0x00,0x01}, // IN_CTMP_WEIGHT42_43 : +{0x65A2,0x00,0x01}, // IN_CTMP_WEIGHT44_45 : +{0x65A3,0x00,0x01}, // IN_CTMP_WEIGHT46_47 : +{0x65A4,0x00,0x01}, // IN_CTMP_WEIGHT48_49 : +{0x65A5,0x00,0x01}, // IN_CTMP_WEIGHT50_51 : +{0x65A6,0x00,0x01}, // IN_CTMP_WEIGHT52_53 : +{0x65A7,0x00,0x01}, // IN_CTMP_WEIGHT54_55 : +{0x65A8,0x00,0x01}, // IN_CTMP_WEIGHT56_57 : +{0x65A9,0x10,0x01}, // IN_CTMP_WEIGHT58_59 : + +{0x65AA,0x78,0x01}, // OUT_CTMP_FRM_BG0 : +{0x65AB,0x74,0x01}, // OUT_CTMP_FRM_BG1 : +{0x65AC,0x70,0x01}, // OUT_CTMP_FRM_BG2 : +{0x65AD,0x6D,0x01}, // OUT_CTMP_FRM_BG3 : +{0x65AE,0x69,0x01}, // OUT_CTMP_FRM_BG4 : +{0x65AF,0x66,0x01}, // OUT_CTMP_FRM_BG5 : +{0x65B0,0x61,0x01}, // OUT_CTMP_FRM_BG6 : +{0x65B1,0x5D,0x01}, // OUT_CTMP_FRM_BG7 : +{0x65B2,0x52,0x01}, // OUT_CTMP_FRM_BG8 : +{0x65B3,0x4B,0x01}, // OUT_CTMP_FRM_BG9 : +{0x65B4,0x44,0x01}, // OUT_CTMP_FRM_BG10 : +{0x65B5,0x19,0x01}, // OUT_CTMP_FRM_RG0 : +{0x65B6,0x27,0x01}, // OUT_CTMP_FRM_RG1 : +{0x65B7,0x32,0x01}, // OUT_CTMP_FRM_RG2 : +{0x65B8,0x3A,0x01}, // OUT_CTMP_FRM_RG3 : +{0x65B9,0x43,0x01}, // OUT_CTMP_FRM_RG4 : +{0x65BA,0x4A,0x01}, // OUT_CTMP_FRM_RG5 : +{0x65BB,0x5E,0x01}, // OUT_CTMP_FRM_RG6 : +{0x65BC,0x00,0x01}, // OUT_CTMP_WEIGHT00_01 : +{0x65BD,0x00,0x01}, // OUT_CTMP_WEIGHT02_03 : +{0x65BE,0x00,0x01}, // OUT_CTMP_WEIGHT04_05 : +{0x65BF,0x00,0x01}, // OUT_CTMP_WEIGHT06_07 : +{0x65C0,0x33,0x01}, // OUT_CTMP_WEIGHT08_09 : +{0x65C1,0x00,0x01}, // OUT_CTMP_WEIGHT10_11 : +{0x65C2,0x30,0x01}, // OUT_CTMP_WEIGHT12_13 : +{0x65C3,0x33,0x01}, // OUT_CTMP_WEIGHT14_15 : +{0x65C4,0x00,0x01}, // OUT_CTMP_WEIGHT16_17 : +{0x65C5,0x30,0x01}, // OUT_CTMP_WEIGHT18_19 : +{0x65C6,0x33,0x01}, // OUT_CTMP_WEIGHT20_21 : +{0x65C7,0x00,0x01}, // OUT_CTMP_WEIGHT22_23 : +{0x65C8,0x30,0x01}, // OUT_CTMP_WEIGHT24_25 : +{0x65C9,0x33,0x01}, // OUT_CTMP_WEIGHT26_27 : +{0x65CA,0x00,0x01}, // OUT_CTMP_WEIGHT28_29 : +{0x65CB,0x30,0x01}, // OUT_CTMP_WEIGHT30_31 : +{0x65CC,0x44,0x01}, // OUT_CTMP_WEIGHT32_33 : +{0x65CD,0x00,0x01}, // OUT_CTMP_WEIGHT34_35 : +{0x65CE,0x40,0x01}, // OUT_CTMP_WEIGHT36_37 : +{0x65CF,0x55,0x01}, // OUT_CTMP_WEIGHT38_39 : +{0x65D0,0x05,0x01}, // OUT_CTMP_WEIGHT40_41 : +{0x65D1,0x20,0x01}, // OUT_CTMP_WEIGHT42_43 : +{0x65D2,0x72,0x01}, // OUT_CTMP_WEIGHT44_45 : +{0x65D3,0x07,0x01}, // OUT_CTMP_WEIGHT46_47 : +{0x65D4,0x00,0x01}, // OUT_CTMP_WEIGHT48_49 : +{0x65D5,0x00,0x01}, // OUT_CTMP_WEIGHT50_51 : +{0x65D6,0x00,0x01}, // OUT_CTMP_WEIGHT52_53 : +{0x65D7,0x00,0x01}, // OUT_CTMP_WEIGHT54_55 : +{0x65D8,0x00,0x01}, // OUT_CTMP_WEIGHT56_57 : +{0x65D9,0x00,0x01}, // OUT_CTMP_WEIGHT58_59 : + +{0x6400,0xAA,0x01}, // INFRM_LEFT00 : +{0x6401,0xAA,0x01}, // INFRM_LEFT01 : +{0x6402,0xAA,0x01}, // INFRM_LEFT02 : +{0x6403,0xAA,0x01}, // INFRM_LEFT03 : +{0x6404,0xAA,0x01}, // INFRM_LEFT04 : +{0x6405,0xAA,0x01}, // INFRM_LEFT05 : +{0x6406,0xAA,0x01}, // INFRM_LEFT06 : +{0x6407,0xAA,0x01}, // INFRM_LEFT07 : +{0x6408,0xAA,0x01}, // INFRM_LEFT08 : +{0x6409,0xAE,0x01}, // INFRM_LEFT09 : +{0x640A,0xA0,0x01}, // INFRM_LEFT10 : +{0x640B,0x8C,0x01}, // INFRM_LEFT11 : +{0x640C,0x72,0x01}, // INFRM_LEFT12 : +{0x640D,0x64,0x01}, // INFRM_LEFT13 : +{0x640E,0x5A,0x01}, // INFRM_LEFT14 : +{0x640F,0x52,0x01}, // INFRM_LEFT15 : +{0x6410,0x48,0x01}, // INFRM_LEFT16 : +{0x6411,0x43,0x01}, // INFRM_LEFT17 : +{0x6412,0x3D,0x01}, // INFRM_LEFT18 : +{0x6413,0x37,0x01}, // INFRM_LEFT19 : +{0x6414,0x33,0x01}, // INFRM_LEFT20 : +{0x6415,0x30,0x01}, // INFRM_LEFT21 : +{0x6416,0x2E,0x01}, // INFRM_LEFT22 : +{0x6417,0x2B,0x01}, // INFRM_LEFT23 : +{0x6418,0x28,0x01}, // INFRM_LEFT24 : +{0x6419,0x26,0x01}, // INFRM_LEFT25 : +{0x641A,0x24,0x01}, // INFRM_LEFT26 : +{0x641B,0x23,0x01}, // INFRM_LEFT27 : +{0x641C,0x22,0x01}, // INFRM_LEFT28 : +{0x641D,0x22,0x01}, // INFRM_LEFT29 : +{0x641E,0x21,0x01}, // INFRM_LEFT30 : +{0x641F,0x20,0x01}, // INFRM_LEFT31 : +{0x6420,0x1D,0x01}, // INFRM_LEFT32 : +{0x6421,0x1A,0x01}, // INFRM_LEFT33 : +{0x6422,0x18,0x01}, // INFRM_LEFT34 : +{0x6423,0x17,0x01}, // INFRM_LEFT35 : +{0x6424,0x16,0x01}, // INFRM_LEFT36 : +{0x6425,0x17,0x01}, // INFRM_LEFT37 : +{0x6426,0xAF,0x01}, // INFRM_RIGHT00 : +{0x6427,0xAF,0x01}, // INFRM_RIGHT01 : +{0x6428,0xAF,0x01}, // INFRM_RIGHT02 : +{0x6429,0xAF,0x01}, // INFRM_RIGHT03 : +{0x642A,0xAF,0x01}, // INFRM_RIGHT04 : +{0x642B,0xAF,0x01}, // INFRM_RIGHT05 : +{0x642C,0xAF,0x01}, // INFRM_RIGHT06 : +{0x642D,0xAF,0x01}, // INFRM_RIGHT07 : +{0x642E,0xAF,0x01}, // INFRM_RIGHT08 : +{0x642F,0xAA,0x01}, // INFRM_RIGHT09 : +{0x6430,0xB2,0x01}, // INFRM_RIGHT10 : +{0x6431,0xB4,0x01}, // INFRM_RIGHT11 : +{0x6432,0xB6,0x01}, // INFRM_RIGHT12 : +{0x6433,0xB4,0x01}, // INFRM_RIGHT13 : +{0x6434,0x9B,0x01}, // INFRM_RIGHT14 : +{0x6435,0x8E,0x01}, // INFRM_RIGHT15 : +{0x6436,0x84,0x01}, // INFRM_RIGHT16 : +{0x6437,0x7A,0x01}, // INFRM_RIGHT17 : +{0x6438,0x72,0x01}, // INFRM_RIGHT18 : +{0x6439,0x6A,0x01}, // INFRM_RIGHT19 : +{0x643A,0x63,0x01}, // INFRM_RIGHT20 : +{0x643B,0x5E,0x01}, // INFRM_RIGHT21 : +{0x643C,0x58,0x01}, // INFRM_RIGHT22 : +{0x643D,0x53,0x01}, // INFRM_RIGHT23 : +{0x643E,0x4E,0x01}, // INFRM_RIGHT24 : +{0x643F,0x4A,0x01}, // INFRM_RIGHT25 : +{0x6440,0x46,0x01}, // INFRM_RIGHT26 : +{0x6441,0x42,0x01}, // INFRM_RIGHT27 : +{0x6442,0x3F,0x01}, // INFRM_RIGHT28 : +{0x6443,0x3C,0x01}, // INFRM_RIGHT29 : +{0x6444,0x3A,0x01}, // INFRM_RIGHT30 : +{0x6445,0x38,0x01}, // INFRM_RIGHT31 : +{0x6446,0x37,0x01}, // INFRM_RIGHT32 : +{0x6447,0x35,0x01}, // INFRM_RIGHT33 : +{0x6448,0x33,0x01}, // INFRM_RIGHT34 : +{0x6449,0x32,0x01}, // INFRM_RIGHT35 : +{0x644A,0x32,0x01}, // INFRM_RIGHT36 : +{0x644B,0x32,0x01}, // INFRM_RIGHT37 : +{0x644C,0x24FA,0x02}, // INFRM_TOP : +{0x644E,0x0940,0x02}, // INFRM_BOTM : +{0x6450,0x19,0x01}, // INFRM_FLTOP : +{0x6451,0x10,0x01}, // INFRM_FLBOTM : +{0x6452,0x91,0x01}, // INAIM_LEFT00 : +{0x6453,0x91,0x01}, // INAIM_LEFT01 : +{0x6454,0x91,0x01}, // INAIM_LEFT02 : +{0x6455,0x91,0x01}, // INAIM_LEFT03 : +{0x6456,0x91,0x01}, // INAIM_LEFT04 : +{0x6457,0x91,0x01}, // INAIM_LEFT05 : +{0x6458,0x91,0x01}, // INAIM_LEFT06 : +{0x6459,0x91,0x01}, // INAIM_LEFT07 : +{0x645A,0x91,0x01}, // INAIM_LEFT08 : +{0x645B,0x91,0x01}, // INAIM_LEFT09 : +{0x645C,0x91,0x01}, // INAIM_LEFT10 : +{0x645D,0x91,0x01}, // INAIM_LEFT11 : +{0x645E,0x91,0x01}, // INAIM_LEFT12 : +{0x645F,0x66,0x01}, // INAIM_LEFT13 : +{0x6460,0x71,0x01}, // INAIM_LEFT14 : +{0x6461,0x5A,0x01}, // INAIM_LEFT15 : +{0x6462,0x4E,0x01}, // INAIM_LEFT16 : +{0x6463,0x47,0x01}, // INAIM_LEFT17 : +{0x6464,0x42,0x01}, // INAIM_LEFT18 : +{0x6465,0x3C,0x01}, // INAIM_LEFT19 : +{0x6466,0x38,0x01}, // INAIM_LEFT20 : +{0x6467,0x36,0x01}, // INAIM_LEFT21 : +{0x6468,0x33,0x01}, // INAIM_LEFT22 : +{0x6469,0x30,0x01}, // INAIM_LEFT23 : +{0x646A,0x2F,0x01}, // INAIM_LEFT24 : +{0x646B,0x2B,0x01}, // INAIM_LEFT25 : +{0x646C,0x29,0x01}, // INAIM_LEFT26 : +{0x646D,0x27,0x01}, // INAIM_LEFT27 : +{0x646E,0x26,0x01}, // INAIM_LEFT28 : +{0x646F,0x28,0x01}, // INAIM_LEFT29 : +{0x6470,0x2A,0x01}, // INAIM_LEFT30 : +{0x6471,0x28,0x01}, // INAIM_LEFT31 : +{0x6472,0x26,0x01}, // INAIM_LEFT32 : +{0x6473,0x24,0x01}, // INAIM_LEFT33 : +{0x6474,0x29,0x01}, // INAIM_LEFT34 : +{0x6475,0x28,0x01}, // INAIM_LEFT35 : +{0x6476,0x29,0x01}, // INAIM_LEFT36 : +{0x6477,0x26,0x01}, // INAIM_LEFT37 : +{0x6478,0xFF,0x01}, // INAIM_RIGHT00 : +{0x6479,0xFF,0x01}, // INAIM_RIGHT01 : +{0x647A,0xFF,0x01}, // INAIM_RIGHT02 : +{0x647B,0xFF,0x01}, // INAIM_RIGHT03 : +{0x647C,0xFF,0x01}, // INAIM_RIGHT04 : +{0x647D,0xFF,0x01}, // INAIM_RIGHT05 : +{0x647E,0xFF,0x01}, // INAIM_RIGHT06 : +{0x647F,0xFF,0x01}, // INAIM_RIGHT07 : +{0x6480,0xFF,0x01}, // INAIM_RIGHT08 : +{0x6481,0xFF,0x01}, // INAIM_RIGHT09 : +{0x6482,0xD9,0x01}, // INAIM_RIGHT10 : +{0x6483,0xB7,0x01}, // INAIM_RIGHT11 : +{0x6484,0x96,0x01}, // INAIM_RIGHT12 : +{0x6485,0x68,0x01}, // INAIM_RIGHT13 : +{0x6486,0x72,0x01}, // INAIM_RIGHT14 : +{0x6487,0x71,0x01}, // INAIM_RIGHT15 : +{0x6488,0x6E,0x01}, // INAIM_RIGHT16 : +{0x6489,0x6A,0x01}, // INAIM_RIGHT17 : +{0x648A,0x65,0x01}, // INAIM_RIGHT18 : +{0x648B,0x60,0x01}, // INAIM_RIGHT19 : +{0x648C,0x5B,0x01}, // INAIM_RIGHT20 : +{0x648D,0x56,0x01}, // INAIM_RIGHT21 : +{0x648E,0x51,0x01}, // INAIM_RIGHT22 : +{0x648F,0x4C,0x01}, // INAIM_RIGHT23 : +{0x6490,0x47,0x01}, // INAIM_RIGHT24 : +{0x6491,0x44,0x01}, // INAIM_RIGHT25 : +{0x6492,0x41,0x01}, // INAIM_RIGHT26 : +{0x6493,0x3E,0x01}, // INAIM_RIGHT27 : +{0x6494,0x3B,0x01}, // INAIM_RIGHT28 : +{0x6495,0x39,0x01}, // INAIM_RIGHT29 : +{0x6496,0x37,0x01}, // INAIM_RIGHT30 : +{0x6497,0x34,0x01}, // INAIM_RIGHT31 : +{0x6498,0x33,0x01}, // INAIM_RIGHT32 : +{0x6499,0x32,0x01}, // INAIM_RIGHT33 : +{0x649A,0x31,0x01}, // INAIM_RIGHT34 : +{0x649B,0x30,0x01}, // INAIM_RIGHT35 : +{0x649C,0x2F,0x01}, // INAIM_RIGHT36 : +{0x649D,0x2E,0x01}, // INAIM_RIGHT37 : +{0x649E,0x1E00,0x02}, // INAIM_TOP : +{0x64A0,0x0DFF,0x02}, // INAIM_BOTM : +{0x64A2,0x18,0x01}, // INAIM_FLTOP : +{0x64A3,0x09,0x01}, // INAIM_FLBOTM : + +//AWB setting +{0x629A,0x13,0x01}, // CAT_AWB_2 : OPDG ±â´É off +{0x629B,0x41,0x01}, // CAT_AWB_3 : outdoor_°¡ÁßÄ¡ on +{0x625F,0x15,0x01}, // CAT_AWB_1 : MWB½Ã userÁÂÇ¥·Î ÁÂÇ¥ °íÁ¤(AWB½Ã¿¡´Â ¿µÇâ ¹«) +{0x629C,0x80,0x01}, // FRMOUT_RATIO_BLEND1_OUT +{0x6224,0x04,0x01}, // ATW_DELAY +{0x6226,0x08,0x01}, // ATW_GAINS_IN_NR : +{0x6227,0x04,0x01}, // ATW_GAINS_IN : +{0x6228,0x08,0x01}, // ATW_GAINS_OUT_NR : +{0x6229,0x04,0x01}, // ATW_GAINS_OUT : + +//Bluesky threshold º¯°æ +{0x6548,0x18F7,0x02}, // OUTAIM_TOP_BLUESKY : + +//Hue, Gain setting +{0x6E86,0x0000,0x02}, // IBYHUE1_POS1 : +{0x6E88,0xFFF5,0x02}, // IRYHUE1_POS1 : +{0x6E8A,0xFFF8,0x02}, // IBYHUE2_POS1 : +{0x6E8C,0xFFF5,0x02}, // IRYHUE2_POS1 : +{0x6E8E,0xFFF8,0x02}, // IBYHUE3_POS1 : +{0x6E90,0xFFEE,0x02}, // IRYHUE3_POS1 : +{0x6E92,0x0000,0x02}, // IBYHUE4_POS1 : +{0x6E94,0xFFEC,0x02}, // IRYHUE4_POS1 : +{0x6E96,0x0000,0x02}, // IBYHUE1_POS2 : +{0x6E98,0xFFF5,0x02}, // IRYHUE1_POS2 : +{0x6E9A,0xFFFD,0x02}, // IBYHUE2_POS2 : +{0x6E9C,0xFFF5,0x02}, // IRYHUE2_POS2 : +{0x6E9E,0xFFFD,0x02}, // IBYHUE3_POS2 : +{0x6EA0,0xFFEE,0x02}, // IRYHUE3_POS2 : +{0x6EA2,0x0000,0x02}, // IBYHUE4_POS2 : +{0x6EA4,0xFFEC,0x02}, // IRYHUE4_POS2 : +{0x6EA6,0x0000,0x02}, // IBYHUE1_POS3 : +{0x6EA8,0xFFF5,0x02}, // IRYHUE1_POS3 : +{0x6EAA,0xFFF8,0x02}, // IBYHUE2_POS3 : +{0x6EAC,0xFFF5,0x02}, // IRYHUE2_POS3 : +{0x6EAE,0xFFF8,0x02}, // IBYHUE3_POS3 : +{0x6EB0,0xFFEE,0x02}, // IRYHUE3_POS3 : +{0x6EB2,0x0000,0x02}, // IBYHUE4_POS3 : +{0x6EB4,0xFFEC,0x02}, // IRYHUE4_POS3 : +{0x6EB6,0x0000,0x02}, // IBYHUE1_POS4 : +{0x6EB8,0xFFF5,0x02}, // IRYHUE1_POS4 : +{0x6EBA,0xFFF8,0x02}, // IBYHUE2_POS4 : +{0x6EBC,0xFFF5,0x02}, // IRYHUE2_POS4 : +{0x6EBE,0xFFF8,0x02}, // IBYHUE3_POS4 : +{0x6EC0,0xFFEE,0x02}, // IRYHUE3_POS4 : +{0x6EC2,0x0000,0x02}, // IBYHUE4_POS4 : +{0x6EC4,0xFFEC,0x02}, // IRYHUE4_POS4 : +{0x6EC6,0x0000,0x02}, // IBYHUE1_POS5 : +{0x6EC8,0xFFF5,0x02}, // IRYHUE1_POS5 : +{0x6ECA,0xFFF8,0x02}, // IBYHUE2_POS5 : +{0x6ECC,0xFFF5,0x02}, // IRYHUE2_POS5 : +{0x6ECE,0xFFF8,0x02}, // IBYHUE3_POS5 : +{0x6ED0,0xFFEE,0x02}, // IRYHUE3_POS5 : +{0x6ED2,0x0000,0x02}, // IBYHUE4_POS5 : +{0x6ED4,0xFFEC,0x02}, // IRYHUE4_POS5 : +{0x6ED6,0x0000,0x02}, // IBYHUE1_POS6 : +{0x6ED8,0xFFF5,0x02}, // IRYHUE1_POS6 : +{0x6EDA,0xFFF8,0x02}, // IBYHUE2_POS6 : +{0x6EDC,0xFFF5,0x02}, // IRYHUE2_POS6 : +{0x6EDE,0xFFF8,0x02}, // IBYHUE3_POS6 : +{0x6EE0,0xFFEE,0x02}, // IRYHUE3_POS6 : +{0x6EE2,0x0000,0x02}, // IBYHUE4_POS6 : +{0x6EE4,0xFFEC,0x02}, // IRYHUE4_POS6 : +{0x6EE6,0x0000,0x02}, // IBYHUE1_POS7 : +{0x6EE8,0xFFF5,0x02}, // IRYHUE1_POS7 : +{0x6EEA,0xFFEA,0x02}, // IBYHUE2_POS7 : +{0x6EEC,0xFFF5,0x02}, // IRYHUE2_POS7 : +{0x6EEE,0xFFEA,0x02}, // IBYHUE3_POS7 : +{0x6EF0,0xFFEE,0x02}, // IRYHUE3_POS7 : +{0x6EF2,0x0000,0x02}, // IBYHUE4_POS7 : +{0x6EF4,0xFFEC,0x02}, // IRYHUE4_POS7 : +{0x6EF6,0xFFF2,0x02}, // IBYHUE1_OUT : +{0x6EF8,0x0000,0x02}, // IRYHUE1_OUT : +{0x6EFA,0xFFFA,0x02}, // IBYHUE2_OUT : +{0x6EFC,0x0000,0x02}, // IRYHUE2_OUT : +{0x6EFE,0xFFFA,0x02}, // IBYHUE3_OUT : +{0x6F00,0xFFE7,0x02}, // IRYHUE3_OUT : +{0x6F02,0xFFF2,0x02}, // IBYHUE4_OUT : +{0x6F04,0xFFE7,0x02}, // IRYHUE4_OUT : +{0x6F06,0x0000,0x02}, // IBYHUE1_R2_POS4 : +{0x6F08,0xFFF5,0x02}, // IRYHUE1_R2_POS4 : +{0x6F0A,0xFFF8,0x02}, // IBYHUE2_R2_POS4 : +{0x6F0C,0xFFF5,0x02}, // IRYHUE2_R2_POS4 : +{0x6F0E,0xFFF8,0x02}, // IBYHUE3_R2_POS4 : +{0x6F10,0xFFEE,0x02}, // IRYHUE3_R2_POS4 : +{0x6F12,0x0000,0x02}, // IBYHUE4_R2_POS4 : +{0x6F14,0xFFEC,0x02}, // IRYHUE4_R2_POS4 : +{0x6F16,0x0000,0x02}, // IBYHUE1_R2_POS5 : +{0x6F18,0xFFF5,0x02}, // IRYHUE1_R2_POS5 : +{0x6F1A,0xFFF8,0x02}, // IBYHUE2_R2_POS5 : +{0x6F1C,0xFFF5,0x02}, // IRYHUE2_R2_POS5 : +{0x6F1E,0xFFF8,0x02}, // IBYHUE3_R2_POS5 : +{0x6F20,0xFFEE,0x02}, // IRYHUE3_R2_POS5 : +{0x6F22,0x0000,0x02}, // IBYHUE4_R2_POS5 : +{0x6F24,0xFFEC,0x02}, // IRYHUE4_R2_POS5 : +{0x6F26,0x4B,0x01}, // IRYGAIN1_POS1 : +{0x6F27,0x50,0x01}, // IBYGAIN1_POS1 : +{0x6F28,0x4B,0x01}, // IRYGAIN2_POS1 : +{0x6F29,0x57,0x01}, // IBYGAIN2_POS1 : +{0x6F2A,0x56,0x01}, // IRYGAIN3_POS1 : +{0x6F2B,0x57,0x01}, // IBYGAIN3_POS1 : +{0x6F2C,0x56,0x01}, // IRYGAIN4_POS1 : +{0x6F2D,0x50,0x01}, // IBYGAIN4_POS1 : +{0x6F2E,0x4B,0x01}, // IRYGAIN1_POS2 : +{0x6F2F,0x50,0x01}, // IBYGAIN1_POS2 : +{0x6F30,0x4B,0x01}, // IRYGAIN2_POS2 : +{0x6F31,0x57,0x01}, // IBYGAIN2_POS2 : +{0x6F32,0x54,0x01}, // IRYGAIN3_POS2 : +{0x6F33,0x57,0x01}, // IBYGAIN3_POS2 : +{0x6F34,0x54,0x01}, // IRYGAIN4_POS2 : +{0x6F35,0x50,0x01}, // IBYGAIN4_POS2 : +{0x6F36,0x4B,0x01}, // IRYGAIN1_POS3 : +{0x6F37,0x50,0x01}, // IBYGAIN1_POS3 : +{0x6F38,0x4B,0x01}, // IRYGAIN2_POS3 : +{0x6F39,0x57,0x01}, // IBYGAIN2_POS3 : +{0x6F3A,0x50,0x01}, // IRYGAIN3_POS3 : +{0x6F3B,0x57,0x01}, // IBYGAIN3_POS3 : +{0x6F3C,0x50,0x01}, // IRYGAIN4_POS3 : +{0x6F3D,0x50,0x01}, // IBYGAIN4_POS3 : +{0x6F3E,0x4B,0x01}, // IRYGAIN1_POS4 : +{0x6F3F,0x50,0x01}, // IBYGAIN1_POS4 : +{0x6F40,0x4B,0x01}, // IRYGAIN2_POS4 : +{0x6F41,0x57,0x01}, // IBYGAIN2_POS4 : +{0x6F42,0x50,0x01}, // IRYGAIN3_POS4 : +{0x6F43,0x57,0x01}, // IBYGAIN3_POS4 : +{0x6F44,0x50,0x01}, // IRYGAIN4_POS4 : +{0x6F45,0x50,0x01}, // IBYGAIN4_POS4 : +{0x6F46,0x4B,0x01}, // IRYGAIN1_POS5 : +{0x6F47,0x50,0x01}, // IBYGAIN1_POS5 : +{0x6F48,0x4B,0x01}, // IRYGAIN2_POS5 : +{0x6F49,0x57,0x01}, // IBYGAIN2_POS5 : +{0x6F4A,0x50,0x01}, // IRYGAIN3_POS5 : +{0x6F4B,0x57,0x01}, // IBYGAIN3_POS5 : +{0x6F4C,0x50,0x01}, // IRYGAIN4_POS5 : +{0x6F4D,0x50,0x01}, // IBYGAIN4_POS5 : +{0x6F4E,0x4B,0x01}, // IRYGAIN1_POS6 : +{0x6F4F,0x50,0x01}, // IBYGAIN1_POS6 : +{0x6F50,0x4B,0x01}, // IRYGAIN2_POS6 : +{0x6F51,0x57,0x01}, // IBYGAIN2_POS6 : +{0x6F52,0x50,0x01}, // IRYGAIN3_POS6 : +{0x6F53,0x57,0x01}, // IBYGAIN3_POS6 : +{0x6F54,0x50,0x01}, // IRYGAIN4_POS6 : +{0x6F55,0x50,0x01}, // IBYGAIN4_POS6 : +{0x6F56,0x4B,0x01}, // IRYGAIN1_POS7 : +{0x6F57,0x50,0x01}, // IBYGAIN1_POS7 : +{0x6F58,0x4B,0x01}, // IRYGAIN2_POS7 : +{0x6F59,0x57,0x01}, // IBYGAIN2_POS7 : +{0x6F5A,0x50,0x01}, // IRYGAIN3_POS7 : +{0x6F5B,0x57,0x01}, // IBYGAIN3_POS7 : +{0x6F5C,0x50,0x01}, // IRYGAIN4_POS7 : +{0x6F5D,0x50,0x01}, // IBYGAIN4_POS7 : +{0x6F5E,0x50,0x01}, // IRYGAIN1_OUT : +{0x6F5F,0x5A,0x01}, // IBYGAIN1_OUT : +{0x6F60,0x50,0x01}, // IRYGAIN2_OUT : +{0x6F61,0x51,0x01}, // IBYGAIN2_OUT : +{0x6F62,0x64,0x01}, // IRYGAIN3_OUT : +{0x6F63,0x51,0x01}, // IBYGAIN3_OUT : +{0x6F64,0x64,0x01}, // IRYGAIN4_OUT : +{0x6F65,0x5A,0x01}, // IBYGAIN4_OUT : +{0x6F66,0x4B,0x01}, // IRYGAIN1_R2_POS4 : +{0x6F67,0x50,0x01}, // IBYGAIN1_R2_POS4 : +{0x6F68,0x4B,0x01}, // IRYGAIN2_R2_POS4 : +{0x6F69,0x57,0x01}, // IBYGAIN2_R2_POS4 : +{0x6F6A,0x50,0x01}, // IRYGAIN3_R2_POS4 : +{0x6F6B,0x57,0x01}, // IBYGAIN3_R2_POS4 : +{0x6F6C,0x50,0x01}, // IRYGAIN4_R2_POS4 : +{0x6F6D,0x50,0x01}, // IBYGAIN4_R2_POS4 : +{0x6F6E,0x4B,0x01}, // IRYGAIN1_R2_POS5 : +{0x6F6F,0x50,0x01}, // IBYGAIN1_R2_POS5 : +{0x6F70,0x4B,0x01}, // IRYGAIN2_R2_POS5 : +{0x6F71,0x57,0x01}, // IBYGAIN2_R2_POS5 : +{0x6F72,0x50,0x01}, // IRYGAIN3_R2_POS5 : +{0x6F73,0x57,0x01}, // IBYGAIN3_R2_POS5 : +{0x6F74,0x50,0x01}, // IRYGAIN4_R2_POS5 : +{0x6F75,0x50,0x01}, // IBYGAIN4_R2_POS5 : + + +//LMT outdoor setting +{0x6E54,0xFFB1,0x02}, // LM_GRG_OUT : +{0x6E56,0x0015,0x02}, // LM_GRB_OUT : +{0x6E58,0xFFE5,0x02}, // LM_GGR_OUT : +{0x6E5A,0xFFFA,0x02}, // LM_GGB_OUT : +{0x6E5C,0xFFDA,0x02}, // LM_GBR_OUT : +{0x6E5E,0xFFE9,0x02}, // LM_GBG_OUT : + +//MC3 ON&OFF +{0x6C49,0xF5,0x01}, // MAIN_CONFIG4 : + + +//////////////////////////////////////////////////////////////// + +{0x941F,0x00,0x01}, // AP_N_GC_POS_CORE_A : < 0x6 +{0x5C05,0x05,0x01}, // RGTCLKPREPARE : //0x5C05 0x3 -> 0x5 +{0x5C06,0x14,0x01}, // RGTCLKZERO : +{0x5C07,0x02,0x01}, // RGTCLKPRE : +{0x5C08,0x0D,0x01}, // RGTCLKPOST : //0x5C08 0x11 -> 0xD +{0x5C09,0x07,0x01}, // RGTCLKTRAIL : //0x5C09 0x5 -> 0x7 +{0x5C0A,0x0A,0x01}, // RGTHSEXIT : //0x5C0A 0x7 -> 0xA +{0x5C0B,0x05,0x01}, // RGTHSPREPARE : //0x5C0B 0x3 -> 0x5 +{0x5C0C,0x08,0x01}, // RGTHSZERO : //0x5C0C 0x7 -> 0x8 +{0x5C0D,0x07,0x01}, // RGTHSTRAIL : //0x5C0D 0x5 -> 0x7 + +{0x0009,0x01,0x01}, // EXT_PLL_CKSEL : PLL 648MHz +{0x00D0,0x11,0x01}, // VIF_CLKCONFIG_EXT1 : VIFSEL and VIFDIV setting value with full frame pixel setting for JPG and interleave mode +{0x00D1,0x11,0x01}, // VIF_CLKCONFIG_EXT2 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for JPG and interleave mode +{0x00D4,0x11,0x01}, // VIF_CLKCONFIG_EXT5 : VIFSEL and VIFDIV setting value with full frame pixel setting for JPG mode +{0x00D5,0x11,0x01}, // VIF_CLKCONFIG_EXT6 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for JPG mode +{0x00D8,0x11,0x01}, // VIF_CLKCONFIG_EXT9 : VIFSEL and VIFDIV setting value with full frame pixel setting for other than JPG +{0x00D9,0x11,0x01}, // VIF_CLKCONFIG_EXT10 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for other than JPG + +//init Preview setting +{0x0089,0x00,0x01},//OUTFMT_MONI +{0x0090,0x0280,0x02},//HSIZE_MONI : 640 +{0x0096,0x01E0,0x02},//VSIZE_MONI : 480 +{0x0083,0x01,0x01},//SENSMODE_MONI +{0x0086,0x02,0x01},//FPSTYPE_MONI +{0x0081,0x00,0x01},//MODESEL +{0x0082,0x01,0x01},//MONI_REFRESH + +//jpeg setting +//Apex40 is not Jpeg Capture + +//Fast mode setting +{0x500A,0x00,0x01}, // FAST_MODECHG_EN +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x500C,0x00FA,0x02}, // FAST_SHT_LIMIT_COUNT + +//Select sensor inversion link control +{0x501A,0x00,0x01}, //SENS_REVERSE_CTRL + +//shading +{0x6DBC,0x03,0x01}, // WHITE_EDGE_MAX : +{0x6DF6,0xFF,0x01}, // WHITE_SHD_JUDGE_BODY_COLOR_RATIO : +{0x6DF7,0xF0,0x01}, // WHITE_SHD_JUDGE_RED_RATIO : +{0x6DAD,0x0C,0x01}, // WHITE_OFSET1_UP : +{0x6DAE,0x0C,0x01}, // WHITE_OFSET1_DOWN : +{0x6DAF,0x11,0x01}, // WHITE_OFSET1_RIGHT : +{0x6DB0,0x1B,0x01}, // WHITE_OFSET1_LEFT : +{0x6DB1,0x0D,0x01}, // WHITE_OFSET2_UP : +{0x6DB2,0x13,0x01}, // WHITE_OFSET2_DOWN : +{0x6DB3,0x11,0x01}, // WHITE_OFSET2_RIGHT : +{0x6DB4,0x17,0x01}, // WHITE_OFSET2_LEFT : + +//addtional code +{0xF200,0xB9B9,0x02}, +{0xF202,0x4E12,0x02}, +{0xF204,0x6055,0x02}, +{0xF206,0x008B,0x02}, +{0xF208,0xF177,0x02}, +{0xF20A,0xFA70,0x02}, +{0xF20C,0x0000,0x02}, +{0xF20E,0x0000,0x02}, +{0xF210,0x0000,0x02}, +{0xF212,0x0000,0x02}, +{0xF214,0x0000,0x02}, +{0xF216,0x0000,0x02}, +{0xF218,0x0000,0x02}, +{0xF21A,0x0000,0x02}, +{0xF21C,0x0000,0x02}, +{0xF21E,0x0000,0x02}, +{0xF220,0x0000,0x02}, +{0xF222,0x0000,0x02}, +{0xF224,0x0000,0x02}, +{0xF226,0x0000,0x02}, +{0xF228,0x0000,0x02}, +{0xF22A,0x0000,0x02}, +{0xF22C,0x0000,0x02}, +{0xF22E,0x0000,0x02}, +{0xF230,0x0000,0x02}, +{0xF232,0x0000,0x02}, +{0xF234,0x0000,0x02}, +{0xF236,0x0000,0x02}, +{0xF238,0x0000,0x02}, +{0xF23A,0x0000,0x02}, +{0xF23C,0x0000,0x02}, +{0xF23E,0x0000,0x02}, +{0xF240,0x0000,0x02}, +{0xF242,0x0000,0x02}, +{0xF244,0xB47E,0x02}, +{0xF246,0x4808,0x02}, +{0xF248,0x7800,0x02}, +{0xF24A,0x07C0,0x02}, +{0xF24C,0x0FC0,0x02}, +{0xF24E,0xF687,0x02}, +{0xF250,0xF8ED,0x02}, +{0xF252,0xF68E,0x02}, +{0xF254,0xFE2B,0x02}, +{0xF256,0xF688,0x02}, +{0xF258,0xFF6B,0x02}, +{0xF25A,0xF693,0x02}, +{0xF25C,0xFB6B,0x02}, +{0xF25E,0xF687,0x02}, +{0xF260,0xF947,0x02}, +{0xF262,0xBC7E,0x02}, +{0xF264,0xF688,0x02}, +{0xF266,0xFD8F,0x02}, +{0xF268,0x239C,0x02}, +{0xF26A,0x0018,0x02}, + + +{0x0006,0x16,0x01}, //INCK_SET : 24MHz +}; + +// ISX012-0 +// MIPI 2LANE 432/LANE +// PLL 432MHz +// DCK 54 +// inifile +// size address data +// +static const isx012_regset_t ISX012_Pll_Setting_3[] = +{ +{0x0007,0x00,0x01}, // PLL_CKSEL : PLL 432MHz +{0x0008,0x00,0x01}, // SRCCK_DIV : 1/5 frequency + +{0x0004,0x03,0x01}, //I2C_ADR_SEL 2: 0x3C MIPI selected, 3: 0x3D MIPI selected +{0x5008,0x00,0x01}, //ENDIAN_SEL : 0:Little Endian +{0x6DA8,0x01,0x01}, //SHD_CoEF (OTP shading ON flag) +{0x6DA9,0x09,0x01}, // WHITE_CTRL +{0x6DCB,0x22,0x01}, // YGAM_CONFIG2 : + +{0x00C4,0x11,0x01}, // VIF_CLKCONFIG1 : VIFSEL and VIFDIV setting value with full frame pixel setting for other then JPG +{0x00C5,0x11,0x01}, // VIF_CLKCONFIG2 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for other then JPG +{0x00C6,0x11,0x01}, // VIF_CLKCONFIG3 : VIFSEL and VIFDIV setting value with 1/4 sub-sampling setting for other then JPG +{0x00C7,0x11,0x01}, // VIF_CLKCONFIG4 : VIFSEL and VIFDIV setting value with 1/8 sub-sampling setting for other then JPG +{0x00C8,0x11,0x01}, // VIF_CLKCONFIG5 : VIFSEL and VIFDIV setting value with full frame pixel setting for JPG mode +{0x00C9,0x11,0x01}, // VIF_CLKCONFIG6 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for JPG mode +{0x00CA,0x11,0x01}, // VIF_CLKCONFIG7 : VIFSEL and VIFDIV setting value with 1/4 sub-sampling setting for JPG mode +{0x00CC,0x11,0x01}, // VIF_CLKCONFIG9 : VIFSEL and VIFDIV setting value with full frame pixel setting for JPG and interleave mode +{0x00CD,0x11,0x01}, // VIF_CLKCONFIG10 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for JPG and interleave mode +{0x6A12,0x11,0x01}, // VIF_CLKCONFIG13 for RAW8 : VIFSEL and VIFDIV setting value with full frame pixel setting for RAW mode +{0x6A13,0x11,0x01}, // VIF_CLKCONFIG14 for RAW8 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for RAW mode +{0x6A14,0x11,0x01}, // VIF_CLKCONFIG15 for RAW8 : VIFSEL and VIFDIV setting value with 1/4 sub-sampling setting for RAW mode +{0x6A15,0x11,0x01}, // VIF_CLKCONFIG16 for RAW8 : VIFSEL and VIFDIV setting value with 1/8 sub-sampling setting for RAW mode +{0x018C,0x0000,0x02}, // VADJ_SENS_1_1 : VMAX adjustment value for full frame pixel +{0x018E,0x0012,0x02}, // VADJ_SENS_1_2 : VMAX adjustment value for 1/2 sub-sampling +{0x0190,0x0000,0x02}, // VADJ_SENS_1_4 : VMAX adjustment value for 1/4 sub-sampling +{0x0192,0x0000,0x02}, // VADJ_SENS_1_8 : VMAX adjustment value for 1/8 sub-sampling +{0x0194,0x0027,0x02}, // VADJ_SENS_HD_1_1 : VMAX adjustment value for HD full frame pixel +{0x0196,0x0015,0x02}, // VADJ_SENS_HD_1_2 : VMAX adjustment value for HD 1/2 sub-sampling +{0x6A16,0x0440,0x02}, // FLC_OPD_HEIGHT_NORMAL_1_1 : Detection window vertical size with all 32 windows for FLC full frame pixel +{0x6A18,0x03C0,0x02}, // FLC_OPD_HEIGHT_NORMAL_1_2 : Detection window vertical size with all 32 windows for FLC 1/2 sub-sampling +{0x6A1A,0x01E0,0x02}, // FLC_OPD_HEIGHT_NORMAL_1_4 : Detection window vertical size with all 32 windows for FLC 1/4 sub-sampling +{0x6A1C,0x00E0,0x02}, // FLC_OPD_HEIGHT_NORMAL_1_8 : Detection window vertical size with all 32 windows for FLC 1/8 sub-sampling +{0x6A1E,0x0420,0x02}, // FLC_OPD_HEIGHT_HD_1_1 : Detection window vertical size with all 32 windows for FLC HD full frame pixel +{0x6A20,0x02C0,0x02}, // FLC_OPD_HEIGHT_HD_1_2 : Detection window vertical size with all 32 windows for FLC HD 1/2 sub-sampling +{0x0016,0x0010,0x02}, // GPIO_FUNCSEL : GPIO setting +{0x5C01,0x00,0x01}, // RGLANESEL : +{0x5C04,0x04,0x01}, // RGTLPX : +{0x5C05,0x03,0x01}, // RGTCLKPREPARE : +{0x5C06,0x0E,0x01}, // RGTCLKZERO : +{0x5C07,0x02,0x01}, // RGTCLKPRE : +{0x5C08,0x0B,0x01}, // RGTCLKPOST : +{0x5C09,0x05,0x01}, // RGTCLKTRAIL : +{0x5C0A,0x07,0x01}, // RGTHSEXIT : +{0x5C0B,0x03,0x01}, // RGTHSPREPARE : +{0x5C0C,0x07,0x01}, // RGTHSZERO : +{0x5C0D,0x05,0x01}, // RGTHSTRAIL : + +{0x0009,0x01,0x01}, // +{0x000A,0x03,0x01}, // EXT_SRCCK_DIV : 1/8 frequency +{0x00D8,0x11,0x01}, // VIF_CLKCONFIG_EXT9 : VIFSEL and VIFDIV setting value with full frame pixel setting for other than JPG +{0x00D9,0x11,0x01}, // VIF_CLKCONFIG_EXT10 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for other than JPG +{0x00DA,0x11,0x01}, // VIF_CLKCONFIG_EXT11 : VIFSEL and VIFDIV setting value with 1/4 sub-sampling setting for other than JPG +{0x00DB,0x11,0x01}, // VIF_CLKCONFIG_EXT12 : VIFSEL and VIFDIV setting value with 1/8 sub-sampling setting for other than JPG +{0x00AC,0x02,0x01}, // + +//init Preview setting +{0x0089,0x00,0x01},//OUTFMT_MONI +{0x0090,0x0280,0x02},//HSIZE_MONI : 640 +{0x0096,0x01E0,0x02},//VSIZE_MONI : 480 +{0x0083,0x01,0x01},//SENSMODE_MONI +{0x0086,0x02,0x01},//FPSTYPE_MONI +{0x0081,0x00,0x01},//MODESEL +{0x0082,0x01,0x01},//MONI_REFRESH + +//jpeg setting +//Apex40 is not Jpeg Capture + +//Fast mode setting +{0x500A,0x00,0x01}, // FAST_MODECHG_EN +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x500C,0x00FA,0x02}, // FAST_SHT_LIMIT_COUNT + +//Select sensor inversion link control +{0x501A,0x00,0x01}, //SENS_REVERSE_CTRL + +//shading +{0x6DBC,0x03,0x01}, // WHITE_EDGE_MAX : +{0x6DF6,0xFF,0x01}, // WHITE_SHD_JUDGE_BODY_COLOR_RATIO : +{0x6DF7,0xF0,0x01}, // WHITE_SHD_JUDGE_RED_RATIO : +{0x6DAD,0x0C,0x01}, // WHITE_OFSET1_UP : +{0x6DAE,0x0C,0x01}, // WHITE_OFSET1_DOWN : +{0x6DAF,0x11,0x01}, // WHITE_OFSET1_RIGHT : +{0x6DB0,0x1B,0x01}, // WHITE_OFSET1_LEFT : +{0x6DB1,0x0D,0x01}, // WHITE_OFSET2_UP : +{0x6DB2,0x13,0x01}, // WHITE_OFSET2_DOWN : +{0x6DB3,0x11,0x01}, // WHITE_OFSET2_RIGHT : +{0x6DB4,0x17,0x01}, // WHITE_OFSET2_LEFT : + +//additional code +{0xF200,0xB9B9,0x02}, +{0xF202,0x4E12,0x02}, +{0xF204,0x6055,0x02}, +{0xF206,0x008B,0x02}, +{0xF208,0xF177,0x02}, +{0xF20A,0xFA70,0x02}, +{0xF20C,0x0000,0x02}, +{0xF20E,0x0000,0x02}, +{0xF210,0x0000,0x02}, +{0xF212,0x0000,0x02}, +{0xF214,0x0000,0x02}, +{0xF216,0x0000,0x02}, +{0xF218,0x0000,0x02}, +{0xF21A,0x0000,0x02}, +{0xF21C,0x0000,0x02}, +{0xF21E,0x0000,0x02}, +{0xF220,0x0000,0x02}, +{0xF222,0x0000,0x02}, +{0xF224,0x0000,0x02}, +{0xF226,0x0000,0x02}, +{0xF228,0x0000,0x02}, +{0xF22A,0x0000,0x02}, +{0xF22C,0x0000,0x02}, +{0xF22E,0x0000,0x02}, +{0xF230,0x0000,0x02}, +{0xF232,0x0000,0x02}, +{0xF234,0x0000,0x02}, +{0xF236,0x0000,0x02}, +{0xF238,0x0000,0x02}, +{0xF23A,0x0000,0x02}, +{0xF23C,0x0000,0x02}, +{0xF23E,0x0000,0x02}, +{0xF240,0x0000,0x02}, +{0xF242,0x0000,0x02}, +{0xF244,0xB47E,0x02}, +{0xF246,0x4808,0x02}, +{0xF248,0x7800,0x02}, +{0xF24A,0x07C0,0x02}, +{0xF24C,0x0FC0,0x02}, +{0xF24E,0xF687,0x02}, +{0xF250,0xF8ED,0x02}, +{0xF252,0xF68E,0x02}, +{0xF254,0xFE2B,0x02}, +{0xF256,0xF688,0x02}, +{0xF258,0xFF6B,0x02}, +{0xF25A,0xF693,0x02}, +{0xF25C,0xFB6B,0x02}, +{0xF25E,0xF687,0x02}, +{0xF260,0xF947,0x02}, +{0xF262,0xBC7E,0x02}, +{0xF264,0xF688,0x02}, +{0xF266,0xFD8F,0x02}, +{0xF268,0x239C,0x02}, +{0xF26A,0x0018,0x02}, + +{0x0006,0x16,0x01}, //INCK_SET : 24MHz +}; + +// ISX012-0 +// MIPI 2LANE 432/LANE +// PLL 432MHz +// DCK 54 +// inifile +// size address data +// +static const isx012_regset_t ISX012_Pll_Setting_4[] = +{ +{0x0007,0x00,0x01}, // PLL_CKSEL : PLL 432MHz +{0x0008,0x00,0x01}, // SRCCK_DIV : 1/5 frequency + +{0x0004,0x03,0x01}, //I2C_ADR_SEL 2: 0x3C MIPI selected, 3: 0x3D MIPI selected +{0x5008,0x00,0x01}, //ENDIAN_SEL : 0:Little Endian +{0x6DA8,0x01,0x01}, //SHD_CoEF (OTP shading ON flag) +{0x6DA9,0x09,0x01}, // WHITE_CTRL +{0x6DCB,0x22,0x01}, // YGAM_CONFIG2 : + +{0x00C4,0x11,0x01}, // VIF_CLKCONFIG1 : VIFSEL and VIFDIV setting value with full frame pixel setting for other then JPG +{0x00C5,0x11,0x01}, // VIF_CLKCONFIG2 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for other then JPG +{0x00C6,0x11,0x01}, // VIF_CLKCONFIG3 : VIFSEL and VIFDIV setting value with 1/4 sub-sampling setting for other then JPG +{0x00C7,0x11,0x01}, // VIF_CLKCONFIG4 : VIFSEL and VIFDIV setting value with 1/8 sub-sampling setting for other then JPG +{0x00C8,0x11,0x01}, // VIF_CLKCONFIG5 : VIFSEL and VIFDIV setting value with full frame pixel setting for JPG mode +{0x00C9,0x11,0x01}, // VIF_CLKCONFIG6 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for JPG mode +{0x00CA,0x11,0x01}, // VIF_CLKCONFIG7 : VIFSEL and VIFDIV setting value with 1/4 sub-sampling setting for JPG mode +{0x00CC,0x11,0x01}, // VIF_CLKCONFIG9 : VIFSEL and VIFDIV setting value with full frame pixel setting for JPG and interleave mode +{0x00CD,0x11,0x01}, // VIF_CLKCONFIG10 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for JPG and interleave mode +{0x6A12,0x11,0x01}, // VIF_CLKCONFIG13 for RAW8 : VIFSEL and VIFDIV setting value with full frame pixel setting for RAW mode +{0x6A13,0x11,0x01}, // VIF_CLKCONFIG14 for RAW8 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for RAW mode +{0x6A14,0x11,0x01}, // VIF_CLKCONFIG15 for RAW8 : VIFSEL and VIFDIV setting value with 1/4 sub-sampling setting for RAW mode +{0x6A15,0x11,0x01}, // VIF_CLKCONFIG16 for RAW8 : VIFSEL and VIFDIV setting value with 1/8 sub-sampling setting for RAW mode +{0x018C,0x0026,0x02}, // VADJ_SENS_1_1 : VMAX adjustment value for full frame pixel +{0x018E,0x0012,0x02}, // VADJ_SENS_1_2 : VMAX adjustment value for 1/2 sub-sampling +{0x0190,0x0000,0x02}, // VADJ_SENS_1_4 : VMAX adjustment value for 1/4 sub-sampling +{0x0192,0x0000,0x02}, // VADJ_SENS_1_8 : VMAX adjustment value for 1/8 sub-sampling +{0x0194,0x0027,0x02}, // VADJ_SENS_HD_1_1 : VMAX adjustment value for HD full frame pixel +{0x0196,0x0015,0x02}, // VADJ_SENS_HD_1_2 : VMAX adjustment value for HD 1/2 sub-sampling +{0x6A16,0x0440,0x02}, // FLC_OPD_HEIGHT_NORMAL_1_1 : Detection window vertical size with all 32 windows for FLC full frame pixel +{0x6A18,0x03C0,0x02}, // FLC_OPD_HEIGHT_NORMAL_1_2 : Detection window vertical size with all 32 windows for FLC 1/2 sub-sampling +{0x6A1A,0x01E0,0x02}, // FLC_OPD_HEIGHT_NORMAL_1_4 : Detection window vertical size with all 32 windows for FLC 1/4 sub-sampling +{0x6A1C,0x00E0,0x02}, // FLC_OPD_HEIGHT_NORMAL_1_8 : Detection window vertical size with all 32 windows for FLC 1/8 sub-sampling +{0x6A1E,0x0420,0x02}, // FLC_OPD_HEIGHT_HD_1_1 : Detection window vertical size with all 32 windows for FLC HD full frame pixel +{0x6A20,0x02C0,0x02}, // FLC_OPD_HEIGHT_HD_1_2 : Detection window vertical size with all 32 windows for FLC HD 1/2 sub-sampling +{0x0016,0x0010,0x02}, // GPIO_FUNCSEL : GPIO setting +{0x5C01,0x00,0x01}, // RGLANESEL : +{0x5C04,0x04,0x01}, // RGTLPX : +{0x5C05,0x03,0x01}, // RGTCLKPREPARE : +{0x5C06,0x0E,0x01}, // RGTCLKZERO : +{0x5C07,0x02,0x01}, // RGTCLKPRE : +{0x5C08,0x0B,0x01}, // RGTCLKPOST : +{0x5C09,0x05,0x01}, // RGTCLKTRAIL : +{0x5C0A,0x07,0x01}, // RGTHSEXIT : +{0x5C0B,0x03,0x01}, // RGTHSPREPARE : +{0x5C0C,0x07,0x01}, // RGTHSZERO : +{0x5C0D,0x05,0x01}, // RGTHSTRAIL : + +{0x6A9E,0x15C0,0x02}, //HMAX_1_1(0x6A9E)=0x15C0 + +{0x0009,0x01,0x01}, // +{0x000A,0x03,0x01}, // EXT_SRCCK_DIV : 1/8 frequency +{0x00D8,0x11,0x01}, // VIF_CLKCONFIG_EXT9 : VIFSEL and VIFDIV setting value with full frame pixel setting for other than JPG +{0x00D9,0x11,0x01}, // VIF_CLKCONFIG_EXT10 : VIFSEL and VIFDIV setting value with 1/2 sub-sampling setting for other than JPG +{0x00DA,0x11,0x01}, // VIF_CLKCONFIG_EXT11 : VIFSEL and VIFDIV setting value with 1/4 sub-sampling setting for other than JPG +{0x00DB,0x11,0x01}, // VIF_CLKCONFIG_EXT12 : VIFSEL and VIFDIV setting value with 1/8 sub-sampling setting for other than JPG +{0x00AC,0x00,0x01}, // + +//init Preview setting +{0x0089,0x00,0x01},//OUTFMT_MONI +{0x0090,0x0280,0x02},//HSIZE_MONI : 640 +{0x0096,0x01E0,0x02},//VSIZE_MONI : 480 +{0x0083,0x01,0x01},//SENSMODE_MONI +{0x0086,0x02,0x01},//FPSTYPE_MONI +{0x0081,0x00,0x01},//MODESEL +{0x0082,0x01,0x01},//MONI_REFRESH + +//jpeg setting +//Apex40 is not Jpeg Capture + +//Fast mode setting +{0x500A,0x00,0x01}, // FAST_MODECHG_EN +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x500C,0x00FA,0x02}, // FAST_SHT_LIMIT_COUNT + +//Select sensor inversion link control +{0x501A,0x00,0x01}, //SENS_REVERSE_CTRL + +//shading +{0x6DBC,0x03,0x01}, // WHITE_EDGE_MAX : +{0x6DF6,0xFF,0x01}, // WHITE_SHD_JUDGE_BODY_COLOR_RATIO : +{0x6DF7,0xF0,0x01}, // WHITE_SHD_JUDGE_RED_RATIO : +{0x6DAD,0x0C,0x01}, // WHITE_OFSET1_UP : +{0x6DAE,0x0C,0x01}, // WHITE_OFSET1_DOWN : +{0x6DAF,0x11,0x01}, // WHITE_OFSET1_RIGHT : +{0x6DB0,0x1B,0x01}, // WHITE_OFSET1_LEFT : +{0x6DB1,0x0D,0x01}, // WHITE_OFSET2_UP : +{0x6DB2,0x13,0x01}, // WHITE_OFSET2_DOWN : +{0x6DB3,0x11,0x01}, // WHITE_OFSET2_RIGHT : +{0x6DB4,0x17,0x01}, // WHITE_OFSET2_LEFT : + +//additional code +{0xF200,0xB9B9,0x02}, +{0xF202,0x4E12,0x02}, +{0xF204,0x6055,0x02}, +{0xF206,0x008B,0x02}, +{0xF208,0xF177,0x02}, +{0xF20A,0xFA70,0x02}, +{0xF20C,0x0000,0x02}, +{0xF20E,0x0000,0x02}, +{0xF210,0x0000,0x02}, +{0xF212,0x0000,0x02}, +{0xF214,0x0000,0x02}, +{0xF216,0x0000,0x02}, +{0xF218,0x0000,0x02}, +{0xF21A,0x0000,0x02}, +{0xF21C,0x0000,0x02}, +{0xF21E,0x0000,0x02}, +{0xF220,0x0000,0x02}, +{0xF222,0x0000,0x02}, +{0xF224,0x0000,0x02}, +{0xF226,0x0000,0x02}, +{0xF228,0x0000,0x02}, +{0xF22A,0x0000,0x02}, +{0xF22C,0x0000,0x02}, +{0xF22E,0x0000,0x02}, +{0xF230,0x0000,0x02}, +{0xF232,0x0000,0x02}, +{0xF234,0x0000,0x02}, +{0xF236,0x0000,0x02}, +{0xF238,0x0000,0x02}, +{0xF23A,0x0000,0x02}, +{0xF23C,0x0000,0x02}, +{0xF23E,0x0000,0x02}, +{0xF240,0x0000,0x02}, +{0xF242,0x0000,0x02}, +{0xF244,0xB47E,0x02}, +{0xF246,0x4808,0x02}, +{0xF248,0x7800,0x02}, +{0xF24A,0x07C0,0x02}, +{0xF24C,0x0FC0,0x02}, +{0xF24E,0xF687,0x02}, +{0xF250,0xF8ED,0x02}, +{0xF252,0xF68E,0x02}, +{0xF254,0xFE2B,0x02}, +{0xF256,0xF688,0x02}, +{0xF258,0xFF6B,0x02}, +{0xF25A,0xF693,0x02}, +{0xF25C,0xFB6B,0x02}, +{0xF25E,0xF687,0x02}, +{0xF260,0xF947,0x02}, +{0xF262,0xBC7E,0x02}, +{0xF264,0xF688,0x02}, +{0xF266,0xFD8F,0x02}, +{0xF268,0x239C,0x02}, +{0xF26A,0x0018,0x02}, + +{0x0006,0x16,0x01}, //INCK_SET : 24MHz +}; + +static const isx012_regset_t ISX012_Preview_SizeSetting[] = +{ +{0x0090,0x0280,0x02}, //HSIZE_MONI : 640 +{0x0096,0x01E0,0x02}, //VSIZE_MONI : 480 +}; + +static const isx012_regset_t ISX012_Preview_Mode[] = +{ +{0x5000,0x00,0x01}, /* CPUEXT, added by SAMSUNG TN */ +{0x5E32,0x0F,0x01}, /* for Fast-AE reset */ +{0x5E3D,0x0A,0x01}, /* for Fast-AE reset */ +{0x0181,0x00,0x01}, // CAP_HALF_AE_CTRL + +{0x0089,0x00,0x01}, //OUTFMT_MONI +{0x0083,0x01,0x01}, //SENSMODE_MONI +{0x0086,0x02,0x01}, //FPSTYPE_MONI +{0x0012,0xFF,0x01}, //INTCLR0 +{0x00F7,0x52,0x01}, // INIT_QLTY0 : Standard 82 +{0x00F8,0x59,0x01}, // INIT_QLTY1 : Fine 89 +{0x00F9,0x5F,0x01}, // INIT_QLTY2 : SuperFine 95 +{0x0081,0x00,0x01}, //MODESEL +{0x0082,0x01,0x01}, //MONI_REFRESH +{0xFFFF,0x1E,0x01}, //$wait,30 +}; + +static const isx012_regset_t ISX012_Camcorder_Mode_ON[] = +{ +//SN setting +{0x0308,0x02,0x01}, // AELINE_MONI_SN1_2 : +{0x0320,0x02,0x01}, // AELINE_MONI_SN1_2 : +{0x00B2,0x02,0x01}, /* AFMODE_MONI : manual mode */ + +//BRIGHTNESS setting +{0x01C6,0x10,0x01}, //UIBRIGHTNESS + +//AE speed +{0x02AC,0x00,0x01}, // AE_SUB_SN1 : +{0x5E2D,0x0C,0x01}, // AEMOVECNT : +{0x5E2E,0x20,0x01}, // AEINDEADBAND : +{0x5E2F,0x08,0x01}, // AEOUTDEADBAND : +{0x5E30,0xA0,0x01}, // AESPEED : + +{0x5E31,0x0F,0x01}, // AESPEED_INIT : +{0x5E32,0x0F,0x01}, // AESPEED_FAST : + +{0x621E,0x18,0x01}, // AIM_NR_TH_UP : +{0x621F,0x18,0x01}, // AIM_NR_TH_DOWN : +{0x6220,0x18,0x01}, // AIM_NR_TH_RIGHT : +{0x6221,0x18,0x01}, // AIM_NR_TH_LEFT : + +//AWB speed +{0x6222,0x00,0x01}, // INIT_AIMW : +{0x6223,0x04,0x01}, // INIT_GAINS : +{0x6224,0x10,0x01}, // ATW_DELAY : +{0x6225,0x00,0x01}, // ATW_AIMW : + +{0x6226,0x20,0x01}, // ATW_GAINS_IN_NR : +{0x6227,0x30,0x01}, // ATW_GAINS_IN : +{0x6228,0x20,0x01}, // ATW_GAINS_OUT_NR : +{0x6229,0x30,0x01}, // ATW_GAINS_OUT : +{0x622A,0x0D,0x01}, // ALLWB_GAINS : + +//Gammma Table 0 +{0x7000,0x0000,0x02}, // G0_KNOT_G0 : +{0x7002,0x0000,0x02}, // G0_KNOT_G1 : +{0x7004,0x001E,0x02}, // G0_KNOT_G2 : +{0x7006,0x0038,0x02}, // G0_KNOT_G3 : +{0x7008,0x0046,0x02}, // G0_KNOT_G4 : +{0x700A,0x0053,0x02}, // G0_KNOT_G5 : +{0x700C,0x005A,0x02}, // G0_KNOT_G6 : +{0x700E,0x0063,0x02}, // G0_KNOT_G7 : +{0x7010,0x006D,0x02}, // G0_KNOT_G8 : +{0x7012,0x0076,0x02}, // G0_KNOT_G9 : +{0x7014,0x0055,0x02}, // G0_KNOT_G10 : +{0x7016,0x008E,0x02}, // G0_KNOT_G11 : +{0x7018,0x00B9,0x02}, // G0_KNOT_G12 : +{0x701A,0x00D5,0x02}, // G0_KNOT_G13 : +{0x701C,0x00E4,0x02}, // G0_KNOT_G14 : +{0x701E,0x00F0,0x02}, // G0_KNOT_G15 : +{0x7020,0x00F9,0x02}, // G0_KNOT_G16 : +{0x7022,0x0103,0x02}, // G0_KNOT_G17 : +{0x7024,0x010C,0x02}, // G0_KNOT_G18 : +{0x7026,0x00,0x01}, // G0_KNOT_R0_OFFSET : +{0x7027,0x00,0x01}, // G0_KNOT_R2_OFFSET : +{0x7028,0x00,0x01}, // G0_KNOT_R4_OFFSET : +{0x7029,0x00,0x01}, // G0_KNOT_R6_OFFSET : +{0x702A,0x00,0x01}, // G0_KNOT_R8_OFFSET : +{0x702B,0x00,0x01}, // G0_KNOT_R10_OFFSET : +{0x702C,0x00,0x01}, // G0_KNOT_R12_OFFSET : +{0x702D,0x00,0x01}, // G0_KNOT_R14_OFFSET : +{0x702E,0x00,0x01}, // G0_KNOT_R16_OFFSET : +{0x702F,0x00,0x01}, // G0_KNOT_R18_OFFSET : +{0x7030,0x00,0x01}, // G0_KNOT_B0_OFFSET : +{0x7031,0x00,0x01}, // G0_KNOT_B2_OFFSET : +{0x7032,0x00,0x01}, // G0_KNOT_B4_OFFSET : +{0x7033,0x00,0x01}, // G0_KNOT_B6_OFFSET : +{0x7034,0x00,0x01}, // G0_KNOT_B8_OFFSET : +{0x7035,0x00,0x01}, // G0_KNOT_B10_OFFSET : +{0x7036,0x00,0x01}, // G0_KNOT_B12_OFFSET : +{0x7037,0x00,0x01}, // G0_KNOT_B14_OFFSET : +{0x7038,0x00,0x01}, // G0_KNOT_B16_OFFSET : +{0x7039,0x00,0x01}, // G0_KNOT_B18_OFFSET : +{0x703A,0x0611,0x02}, // G0_LOWGM_ON_R : +{0x703C,0x1E0A,0x02}, // G0_0CLIP_R : +{0x703E,0x0611,0x02}, // G0_LOWGM_ON_G : +{0x7040,0x1E0A,0x02}, // G0_0CLIP_G : +{0x7042,0x0611,0x02}, // G0_LOWGM_ON_B : +{0x7044,0x1E0A,0x02}, // G0_0CLIP_B : +{0x7046,0x91,0x01}, // G0_KNOT_GAINCTRL_TH_L : +{0x7047,0x96,0x01}, // G0_KNOT_GAINCTRL_TH_H : +{0x7048,0x0000,0x02}, // G0_KNOT_L_G0 : +{0x704A,0x0000,0x02}, // G0_KNOT_L_G1 : +{0x704C,0x000E,0x02}, // G0_KNOT_L_G2 : +{0x704E,0x002F,0x02}, // G0_KNOT_L_G3 : +{0x7050,0x003D,0x02}, // G0_KNOT_L_G4 : +{0x7052,0x004A,0x02}, // G0_KNOT_L_G5 : +{0x7054,0x0051,0x02}, // G0_KNOT_L_G6 : +{0x7056,0x005A,0x02}, // G0_KNOT_L_G7 : +{0x7058,0x0061,0x02}, // G0_KNOT_L_G8 : +{0x705A,0x006A,0x02}, // G0_KNOT_L_G9 : +{0x705C,0x0049,0x02}, // G0_KNOT_L_G10 : +{0x705E,0x0082,0x02}, // G0_KNOT_L_G11 : +{0x7060,0x00AD,0x02}, // G0_KNOT_L_G12 : +{0x7062,0x00CC,0x02}, // G0_KNOT_L_G13 : +{0x7064,0x00E1,0x02}, // G0_KNOT_L_G14 : +{0x7066,0x00ED,0x02}, // G0_KNOT_L_G15 : +{0x7068,0x00F6,0x02}, // G0_KNOT_L_G16 : +{0x706A,0x0106,0x02}, // G0_KNOT_L_G17 : +{0x706C,0x010C,0x02}, // G0_KNOT_L_G18 : + + +{0x6400,0x00,0x01}, // INFRM_LEFT00 : +{0x6401,0x00,0x01}, // INFRM_LEFT01 : +{0x6402,0x00,0x01}, // INFRM_LEFT02 : +{0x6403,0x00,0x01}, // INFRM_LEFT03 : +{0x6404,0x00,0x01}, // INFRM_LEFT04 : +{0x6405,0x00,0x01}, // INFRM_LEFT05 : +{0x6406,0x00,0x01}, // INFRM_LEFT06 : +{0x6407,0x00,0x01}, // INFRM_LEFT07 : +{0x6408,0x00,0x01}, // INFRM_LEFT08 : +{0x6409,0x00,0x01}, // INFRM_LEFT09 : +{0x640A,0x00,0x01}, // INFRM_LEFT10 : +{0x640B,0x00,0x01}, // INFRM_LEFT11 : +{0x640C,0x00,0x01}, // INFRM_LEFT12 : +{0x640D,0x00,0x01}, // INFRM_LEFT13 : +{0x640E,0x00,0x01}, // INFRM_LEFT14 : +{0x640F,0x00,0x01}, // INFRM_LEFT15 : +{0x6410,0x00,0x01}, // INFRM_LEFT16 : +{0x6411,0x00,0x01}, // INFRM_LEFT17 : +{0x6412,0x00,0x01}, // INFRM_LEFT18 : +{0x6413,0x00,0x01}, // INFRM_LEFT19 : +{0x6414,0x00,0x01}, // INFRM_LEFT20 : +{0x6415,0x00,0x01}, // INFRM_LEFT21 : +{0x6416,0x00,0x01}, // INFRM_LEFT22 : +{0x6417,0x00,0x01}, // INFRM_LEFT23 : +{0x6418,0x00,0x01}, // INFRM_LEFT24 : +{0x6419,0x00,0x01}, // INFRM_LEFT25 : +{0x641A,0x00,0x01}, // INFRM_LEFT26 : +{0x641B,0x00,0x01}, // INFRM_LEFT27 : +{0x641C,0x00,0x01}, // INFRM_LEFT28 : +{0x641D,0x00,0x01}, // INFRM_LEFT29 : +{0x641E,0x00,0x01}, // INFRM_LEFT30 : +{0x641F,0x00,0x01}, // INFRM_LEFT31 : +{0x6420,0x00,0x01}, // INFRM_LEFT32 : +{0x6421,0x00,0x01}, // INFRM_LEFT33 : +{0x6422,0x00,0x01}, // INFRM_LEFT34 : +{0x6423,0x00,0x01}, // INFRM_LEFT35 : +{0x6424,0x00,0x01}, // INFRM_LEFT36 : +{0x6425,0x00,0x01}, // INFRM_LEFT37 : +{0x6426,0xFF,0x01}, // INFRM_RIGHT00 : +{0x6427,0xFF,0x01}, // INFRM_RIGHT01 : +{0x6428,0xFF,0x01}, // INFRM_RIGHT02 : +{0x6429,0xFF,0x01}, // INFRM_RIGHT03 : +{0x642A,0xFF,0x01}, // INFRM_RIGHT04 : +{0x642B,0xFF,0x01}, // INFRM_RIGHT05 : +{0x642C,0xFF,0x01}, // INFRM_RIGHT06 : +{0x642D,0xFF,0x01}, // INFRM_RIGHT07 : +{0x642E,0xFF,0x01}, // INFRM_RIGHT08 : +{0x642F,0xFF,0x01}, // INFRM_RIGHT09 : +{0x6430,0xFF,0x01}, // INFRM_RIGHT10 : +{0x6431,0xFF,0x01}, // INFRM_RIGHT11 : +{0x6432,0xFF,0x01}, // INFRM_RIGHT12 : +{0x6433,0xFF,0x01}, // INFRM_RIGHT13 : +{0x6434,0xFF,0x01}, // INFRM_RIGHT14 : +{0x6435,0xFF,0x01}, // INFRM_RIGHT15 : +{0x6436,0xFF,0x01}, // INFRM_RIGHT16 : +{0x6437,0xFF,0x01}, // INFRM_RIGHT17 : +{0x6438,0xFF,0x01}, // INFRM_RIGHT18 : +{0x6439,0xFF,0x01}, // INFRM_RIGHT19 : +{0x643A,0xFF,0x01}, // INFRM_RIGHT20 : +{0x643B,0xFF,0x01}, // INFRM_RIGHT21 : +{0x643C,0xFF,0x01}, // INFRM_RIGHT22 : +{0x643D,0xFF,0x01}, // INFRM_RIGHT23 : +{0x643E,0xFF,0x01}, // INFRM_RIGHT24 : +{0x643F,0xFF,0x01}, // INFRM_RIGHT25 : +{0x6440,0xFF,0x01}, // INFRM_RIGHT26 : +{0x6441,0xFF,0x01}, // INFRM_RIGHT27 : +{0x6442,0xFF,0x01}, // INFRM_RIGHT28 : +{0x6443,0xFF,0x01}, // INFRM_RIGHT29 : +{0x6444,0xFF,0x01}, // INFRM_RIGHT30 : +{0x6445,0xFF,0x01}, // INFRM_RIGHT31 : +{0x6446,0xFF,0x01}, // INFRM_RIGHT32 : +{0x6447,0xFF,0x01}, // INFRM_RIGHT33 : +{0x6448,0xFF,0x01}, // INFRM_RIGHT34 : +{0x6449,0xFF,0x01}, // INFRM_RIGHT35 : +{0x644A,0xFF,0x01}, // INFRM_RIGHT36 : +{0x644B,0xFF,0x01}, // INFRM_RIGHT37 : +{0x644C,0xFFFF,0x02}, // INFRM_TOP : +{0x644E,0x0000,0x02}, // INFRM_BOTM : +{0x6450,0x25,0x01}, // INFRM_FLTOP : +{0x6451,0x00,0x01}, // INFRM_FLBOTM : +{0x6452,0x91,0x01}, // INAIM_LEFT00 : +{0x6453,0x91,0x01}, // INAIM_LEFT01 : +{0x6454,0x91,0x01}, // INAIM_LEFT02 : +{0x6455,0x91,0x01}, // INAIM_LEFT03 : +{0x6456,0x91,0x01}, // INAIM_LEFT04 : +{0x6457,0x91,0x01}, // INAIM_LEFT05 : +{0x6458,0x91,0x01}, // INAIM_LEFT06 : +{0x6459,0x91,0x01}, // INAIM_LEFT07 : +{0x645A,0x91,0x01}, // INAIM_LEFT08 : +{0x645B,0x91,0x01}, // INAIM_LEFT09 : +{0x645C,0x91,0x01}, // INAIM_LEFT10 : +{0x645D,0x91,0x01}, // INAIM_LEFT11 : +{0x645E,0x91,0x01}, // INAIM_LEFT12 : +{0x645F,0x66,0x01}, // INAIM_LEFT13 : +{0x6460,0x5D,0x01}, // INAIM_LEFT14 : +{0x6461,0x69,0x01}, // INAIM_LEFT15 : +{0x6462,0x54,0x01}, // INAIM_LEFT16 : +{0x6463,0x4B,0x01}, // INAIM_LEFT17 : +{0x6464,0x42,0x01}, // INAIM_LEFT18 : +{0x6465,0x3C,0x01}, // INAIM_LEFT19 : +{0x6466,0x38,0x01}, // INAIM_LEFT20 : +{0x6467,0x36,0x01}, // INAIM_LEFT21 : +{0x6468,0x35,0x01}, // INAIM_LEFT22 : +{0x6469,0x33,0x01}, // INAIM_LEFT23 : +{0x646A,0x32,0x01}, // INAIM_LEFT24 : +{0x646B,0x30,0x01}, // INAIM_LEFT25 : +{0x646C,0x2F,0x01}, // INAIM_LEFT26 : +{0x646D,0x2D,0x01}, // INAIM_LEFT27 : +{0x646E,0x2C,0x01}, // INAIM_LEFT28 : +{0x646F,0x2B,0x01}, // INAIM_LEFT29 : +{0x6470,0x2A,0x01}, // INAIM_LEFT30 : +{0x6471,0x28,0x01}, // INAIM_LEFT31 : +{0x6472,0x26,0x01}, // INAIM_LEFT32 : +{0x6473,0x24,0x01}, // INAIM_LEFT33 : +{0x6474,0x29,0x01}, // INAIM_LEFT34 : +{0x6475,0x28,0x01}, // INAIM_LEFT35 : +{0x6476,0x29,0x01}, // INAIM_LEFT36 : +{0x6477,0x26,0x01}, // INAIM_LEFT37 : +{0x6478,0xFF,0x01}, // INAIM_RIGHT00 : +{0x6479,0xFF,0x01}, // INAIM_RIGHT01 : +{0x647A,0xFF,0x01}, // INAIM_RIGHT02 : +{0x647B,0xFF,0x01}, // INAIM_RIGHT03 : +{0x647C,0xFF,0x01}, // INAIM_RIGHT04 : +{0x647D,0xFF,0x01}, // INAIM_RIGHT05 : +{0x647E,0xFF,0x01}, // INAIM_RIGHT06 : +{0x647F,0xFF,0x01}, // INAIM_RIGHT07 : +{0x6480,0xFF,0x01}, // INAIM_RIGHT08 : +{0x6481,0xFF,0x01}, // INAIM_RIGHT09 : +{0x6482,0xD9,0x01}, // INAIM_RIGHT10 : +{0x6483,0xB7,0x01}, // INAIM_RIGHT11 : +{0x6484,0x96,0x01}, // INAIM_RIGHT12 : +{0x6485,0x68,0x01}, // INAIM_RIGHT13 : +{0x6486,0x70,0x01}, // INAIM_RIGHT14 : +{0x6487,0x72,0x01}, // INAIM_RIGHT15 : +{0x6488,0x71,0x01}, // INAIM_RIGHT16 : +{0x6489,0x6B,0x01}, // INAIM_RIGHT17 : +{0x648A,0x65,0x01}, // INAIM_RIGHT18 : +{0x648B,0x60,0x01}, // INAIM_RIGHT19 : +{0x648C,0x5B,0x01}, // INAIM_RIGHT20 : +{0x648D,0x56,0x01}, // INAIM_RIGHT21 : +{0x648E,0x51,0x01}, // INAIM_RIGHT22 : +{0x648F,0x4C,0x01}, // INAIM_RIGHT23 : +{0x6490,0x47,0x01}, // INAIM_RIGHT24 : +{0x6491,0x44,0x01}, // INAIM_RIGHT25 : +{0x6492,0x41,0x01}, // INAIM_RIGHT26 : +{0x6493,0x3E,0x01}, // INAIM_RIGHT27 : +{0x6494,0x3B,0x01}, // INAIM_RIGHT28 : +{0x6495,0x39,0x01}, // INAIM_RIGHT29 : +{0x6496,0x37,0x01}, // INAIM_RIGHT30 : +{0x6497,0x34,0x01}, // INAIM_RIGHT31 : +{0x6498,0x33,0x01}, // INAIM_RIGHT32 : +{0x6499,0x32,0x01}, // INAIM_RIGHT33 : +{0x649A,0x31,0x01}, // INAIM_RIGHT34 : +{0x649B,0x30,0x01}, // INAIM_RIGHT35 : +{0x649C,0x2F,0x01}, // INAIM_RIGHT36 : +{0x649D,0x2E,0x01}, // INAIM_RIGHT37 : +{0x649E,0x1E00,0x02}, // INAIM_TOP : +{0x64A0,0x0F48,0x02}, // INAIM_BOTM : +{0x64A2,0x18,0x01}, // INAIM_FLTOP : +{0x64A3,0x11,0x01}, // INAIM_FLBOTM : +{0x64A4,0x00,0x01}, // OUTFRM_LEFT00 : +{0x64A5,0x00,0x01}, // OUTFRM_LEFT01 : +{0x64A6,0x00,0x01}, // OUTFRM_LEFT02 : +{0x64A7,0x00,0x01}, // OUTFRM_LEFT03 : +{0x64A8,0x00,0x01}, // OUTFRM_LEFT04 : +{0x64A9,0x00,0x01}, // OUTFRM_LEFT05 : +{0x64AA,0x00,0x01}, // OUTFRM_LEFT06 : +{0x64AB,0x00,0x01}, // OUTFRM_LEFT07 : +{0x64AC,0x00,0x01}, // OUTFRM_LEFT08 : +{0x64AD,0x00,0x01}, // OUTFRM_LEFT09 : +{0x64AE,0x00,0x01}, // OUTFRM_LEFT10 : +{0x64AF,0x00,0x01}, // OUTFRM_LEFT11 : +{0x64B0,0x00,0x01}, // OUTFRM_LEFT12 : +{0x64B1,0x00,0x01}, // OUTFRM_LEFT13 : +{0x64B2,0x00,0x01}, // OUTFRM_LEFT14 : +{0x64B3,0x00,0x01}, // OUTFRM_LEFT15 : +{0x64B4,0x00,0x01}, // OUTFRM_LEFT16 : +{0x64B5,0x00,0x01}, // OUTFRM_LEFT17 : +{0x64B6,0x00,0x01}, // OUTFRM_LEFT18 : +{0x64B7,0x00,0x01}, // OUTFRM_LEFT19 : +{0x64B8,0x00,0x01}, // OUTFRM_LEFT20 : +{0x64B9,0x00,0x01}, // OUTFRM_LEFT21 : +{0x64BA,0x00,0x01}, // OUTFRM_LEFT22 : +{0x64BB,0x00,0x01}, // OUTFRM_LEFT23 : +{0x64BC,0x00,0x01}, // OUTFRM_LEFT24 : +{0x64BD,0x00,0x01}, // OUTFRM_LEFT25 : +{0x64BE,0x00,0x01}, // OUTFRM_LEFT26 : +{0x64BF,0x00,0x01}, // OUTFRM_LEFT27 : +{0x64C0,0x00,0x01}, // OUTFRM_LEFT28 : +{0x64C1,0x00,0x01}, // OUTFRM_LEFT29 : +{0x64C2,0x00,0x01}, // OUTFRM_LEFT30 : +{0x64C3,0x00,0x01}, // OUTFRM_LEFT31 : +{0x64C4,0x00,0x01}, // OUTFRM_LEFT32 : +{0x64C5,0x00,0x01}, // OUTFRM_LEFT33 : +{0x64C6,0x00,0x01}, // OUTFRM_LEFT34 : +{0x64C7,0x00,0x01}, // OUTFRM_LEFT35 : +{0x64C8,0x00,0x01}, // OUTFRM_LEFT36 : +{0x64C9,0x00,0x01}, // OUTFRM_LEFT37 : +{0x64CA,0xFF,0x01}, // OUTFRM_RIGHT00 : +{0x64CB,0xFF,0x01}, // OUTFRM_RIGHT01 : +{0x64CC,0xFF,0x01}, // OUTFRM_RIGHT02 : +{0x64CD,0xFF,0x01}, // OUTFRM_RIGHT03 : +{0x64CE,0xFF,0x01}, // OUTFRM_RIGHT04 : +{0x64CF,0xFF,0x01}, // OUTFRM_RIGHT05 : +{0x64D0,0xFF,0x01}, // OUTFRM_RIGHT06 : +{0x64D1,0xFF,0x01}, // OUTFRM_RIGHT07 : +{0x64D2,0xFF,0x01}, // OUTFRM_RIGHT08 : +{0x64D3,0xFF,0x01}, // OUTFRM_RIGHT09 : +{0x64D4,0xFF,0x01}, // OUTFRM_RIGHT10 : +{0x64D5,0xFF,0x01}, // OUTFRM_RIGHT11 : +{0x64D6,0xFF,0x01}, // OUTFRM_RIGHT12 : +{0x64D7,0xFF,0x01}, // OUTFRM_RIGHT13 : +{0x64D8,0xFF,0x01}, // OUTFRM_RIGHT14 : +{0x64D9,0xFF,0x01}, // OUTFRM_RIGHT15 : +{0x64DA,0xFF,0x01}, // OUTFRM_RIGHT16 : +{0x64DB,0xFF,0x01}, // OUTFRM_RIGHT17 : +{0x64DC,0xFF,0x01}, // OUTFRM_RIGHT18 : +{0x64DD,0xFF,0x01}, // OUTFRM_RIGHT19 : +{0x64DE,0xFF,0x01}, // OUTFRM_RIGHT20 : +{0x64DF,0xFF,0x01}, // OUTFRM_RIGHT21 : +{0x64E0,0xFF,0x01}, // OUTFRM_RIGHT22 : +{0x64E1,0xFF,0x01}, // OUTFRM_RIGHT23 : +{0x64E2,0xFF,0x01}, // OUTFRM_RIGHT24 : +{0x64E3,0xFF,0x01}, // OUTFRM_RIGHT25 : +{0x64E4,0xFF,0x01}, // OUTFRM_RIGHT26 : +{0x64E5,0xFF,0x01}, // OUTFRM_RIGHT27 : +{0x64E6,0xFF,0x01}, // OUTFRM_RIGHT28 : +{0x64E7,0xFF,0x01}, // OUTFRM_RIGHT29 : +{0x64E8,0xFF,0x01}, // OUTFRM_RIGHT30 : +{0x64E9,0xFF,0x01}, // OUTFRM_RIGHT31 : +{0x64EA,0xFF,0x01}, // OUTFRM_RIGHT32 : +{0x64EB,0xFF,0x01}, // OUTFRM_RIGHT33 : +{0x64EC,0xFF,0x01}, // OUTFRM_RIGHT34 : +{0x64ED,0xFF,0x01}, // OUTFRM_RIGHT35 : +{0x64EE,0xFF,0x01}, // OUTFRM_RIGHT36 : +{0x64EF,0xFF,0x01}, // OUTFRM_RIGHT37 : +{0x64F0,0x24F0,0x02}, // OUTFRM_TOP : +{0x64F2,0x1400,0x02}, // OUTFRM_BOTM : +{0x64F4,0x37,0x01}, // OUTFRM_FLTOP : +{0x64F5,0x00,0x01}, // OUTFRM_FLBOTM : + +//AWB +{0x6232,0x07,0x01},//ATW_SFTLMT_OUT_NR +{0x6234,0x05,0x01},//ATW_SFTLMT_OUT + +/////MC3 Setting///// +{0x7600,0x07,0x01}, // MC3_PXDEF0_SEL : +{0x7601,0x07,0x01}, // MC3_PYDEF0_SEL : +{0x7602,0x07,0x01}, // MC3_PXDEF1_SEL : +{0x7603,0x07,0x01}, // MC3_PYDEF1_SEL : +{0x7604,0x07,0x01}, // MC3_PXDEF2_SEL : +{0x7605,0x07,0x01}, // MC3_PYDEF2_SEL : +{0x7606,0x07,0x01}, // MC3_PXDEF3_SEL : +{0x7607,0x07,0x01}, // MC3_PYDEF3_SEL : +{0x7608,0x40,0x01}, // MC3_PXDEF0_A : +{0x7609,0x40,0x01}, // MC3_PXDEF0_B : +{0x760A,0x40,0x01}, // MC3_PXDEF0_C : +{0x760B,0x40,0x01}, // MC3_PYDEF0_A : +{0x760C,0x40,0x01}, // MC3_PYDEF0_B : +{0x760D,0x40,0x01}, // MC3_PYDEF0_C : +{0x760E,0x40,0x01}, // MC3_PXDEF1_A : +{0x760F,0x40,0x01}, // MC3_PXDEF1_B : +{0x7610,0x40,0x01}, // MC3_PXDEF1_C : +{0x7611,0x40,0x01}, // MC3_PYDEF1_A : +{0x7612,0x40,0x01}, // MC3_PYDEF1_B : +{0x7613,0x40,0x01}, // MC3_PYDEF1_C : +{0x7614,0x40,0x01}, // MC3_PXDEF2_A : +{0x7615,0x40,0x01}, // MC3_PXDEF2_B : +{0x7616,0x40,0x01}, // MC3_PXDEF2_C : +{0x7617,0x40,0x01}, // MC3_PYDEF2_A : +{0x7618,0x40,0x01}, // MC3_PYDEF2_B : +{0x7619,0x40,0x01}, // MC3_PYDEF2_C : +{0x761A,0x40,0x01}, // MC3_PXDEF3_A : +{0x761B,0x40,0x01}, // MC3_PXDEF3_B : +{0x761C,0x40,0x01}, // MC3_PXDEF3_C : +{0x761D,0x40,0x01}, // MC3_PYDEF3_A : +{0x761E,0x40,0x01}, // MC3_PYDEF3_B : +{0x761F,0x40,0x01}, // MC3_PYDEF3_C : +{0x7620,0x00,0x01}, // MC3_LUMSL0_IN : +{0x7621,0x06,0x01}, // MC3_LUMSL1_IN : +{0x7622,0x03,0x01}, // MC3_LUMSL2_IN : +{0x7623,0x06,0x01}, // MC3_LUMSL3_IN : +{0x7624,0x00,0x01}, // MC3_LUMSL0_OUT : +{0x7625,0x03,0x01}, // MC3_LUMSL1_OUT : +{0x7626,0x00,0x01}, // MC3_LUMSL2_OUT : +{0x7627,0x00,0x01}, // MC3_LUMSL3_OUT : +{0x7628,0x0000,0x02}, // MC3_L0DEF0_IN : +{0x762A,0x008C,0x02}, // MC3_L0DEF1_IN : +{0x762C,0x0078,0x02}, // MC3_L0DEF2_IN : +{0x762E,0x00E6,0x02}, // MC3_L0DEF3_IN : +{0x7630,0x0000,0x02}, // MC3_L0DEF0_OUT : +{0x7632,0x0082,0x02}, // MC3_L0DEF1_OUT : +{0x7634,0x0000,0x02}, // MC3_L0DEF2_OUT : +{0x7636,0x0000,0x02}, // MC3_L0DEF3_OUT : +{0x7638,0x41,0x01}, // MC3_RDEF0_POS1 : +{0x7639,0x10,0x01}, // MC3_RDEF1_POS1 : +{0x763A,0x15,0x01}, // MC3_RDEF2_POS1 : +{0x763B,0x71,0x01}, // MC3_RDEF3_POS1 : +{0x763C,0x41,0x01}, // MC3_RDEF0_POS2 : +{0x763D,0x10,0x01}, // MC3_RDEF1_POS2 : +{0x763E,0x15,0x01}, // MC3_RDEF2_POS2 : +{0x763F,0x71,0x01}, // MC3_RDEF3_POS2 : +{0x7640,0x3C,0x01}, // MC3_RDEF0_POS3 : +{0x7641,0x10,0x01}, // MC3_RDEF1_POS3 : +{0x7642,0x15,0x01}, // MC3_RDEF2_POS3 : +{0x7643,0x71,0x01}, // MC3_RDEF3_POS3 : +{0x7644,0x46,0x01}, // MC3_RDEF0_POS4 : +{0x7645,0x32,0x01}, // MC3_RDEF1_POS4 : +{0x7646,0x15,0x01}, // MC3_RDEF2_POS4 : +{0x7647,0x71,0x01}, // MC3_RDEF3_POS4 : +{0x7648,0x46,0x01}, // MC3_RDEF0_POS5 : +{0x7649,0x32,0x01}, // MC3_RDEF1_POS5 : +{0x764A,0x15,0x01}, // MC3_RDEF2_POS5 : +{0x764B,0x71,0x01}, // MC3_RDEF3_POS5 : +{0x764C,0x46,0x01}, // MC3_RDEF0_POS6 : +{0x764D,0x10,0x01}, // MC3_RDEF1_POS6 : +{0x764E,0x15,0x01}, // MC3_RDEF2_POS6 : +{0x764F,0x71,0x01}, // MC3_RDEF3_POS6 : +{0x7650,0x46,0x01}, // MC3_RDEF0_POS7 : +{0x7651,0x10,0x01}, // MC3_RDEF1_POS7 : +{0x7652,0x15,0x01}, // MC3_RDEF2_POS7 : +{0x7653,0x71,0x01}, // MC3_RDEF3_POS7 : +{0x7654,0x2D,0x01}, // MC3_RDEF0_OUT : +{0x7655,0x10,0x01}, // MC3_RDEF1_OUT : +{0x7656,0x15,0x01}, // MC3_RDEF2_OUT : +{0x7657,0x54,0x01}, // MC3_RDEF3_OUT : +{0x7658,0x46,0x01}, // MC3_RDEF0_R2_POS4 : +{0x7659,0x32,0x01}, // MC3_RDEF1_R2_POS4 : +{0x765A,0x15,0x01}, // MC3_RDEF2_R2_POS4 : +{0x765B,0x71,0x01}, // MC3_RDEF3_R2_POS4 : +{0x765C,0x46,0x01}, // MC3_RDEF0_R2_POS5 : +{0x765D,0x32,0x01}, // MC3_RDEF1_R2_POS5 : +{0x765E,0x15,0x01}, // MC3_RDEF2_R2_POS5 : +{0x765F,0x71,0x01}, // MC3_RDEF3_R2_POS5 : +{0x7660,0xFFBA,0x02}, // MC3_X0DEF0_POS1 : +{0x7662,0xFFBA,0x02}, // MC3_Y0DEF0_POS1 : +{0x7664,0xFFFE,0x02}, // MC3_X0DEF1_POS1 : +{0x7666,0x000D,0x02}, // MC3_Y0DEF1_POS1 : +{0x7668,0x0002,0x02}, // MC3_X0DEF2_POS1 : +{0x766A,0xFFF6,0x02}, // MC3_Y0DEF2_POS1 : +{0x766C,0x003B,0x02}, // MC3_X0DEF3_POS1 : +{0x766E,0xFFBB,0x02}, // MC3_Y0DEF3_POS1 : +{0x7670,0xFFBA,0x02}, // MC3_X0DEF0_POS2 : +{0x7672,0xFFBA,0x02}, // MC3_Y0DEF0_POS2 : +{0x7674,0xFFFE,0x02}, // MC3_X0DEF1_POS2 : +{0x7676,0x000D,0x02}, // MC3_Y0DEF1_POS2 : +{0x7678,0x0002,0x02}, // MC3_X0DEF2_POS2 : +{0x767A,0xFFF6,0x02}, // MC3_Y0DEF2_POS2 : +{0x767C,0x003B,0x02}, // MC3_X0DEF3_POS2 : +{0x767E,0xFFBB,0x02}, // MC3_Y0DEF3_POS2 : +{0x7680,0xFFCE,0x02}, // MC3_X0DEF0_POS3 : +{0x7682,0xFFBA,0x02}, // MC3_Y0DEF0_POS3 : +{0x7684,0xFFFE,0x02}, // MC3_X0DEF1_POS3 : +{0x7686,0x000D,0x02}, // MC3_Y0DEF1_POS3 : +{0x7688,0x0002,0x02}, // MC3_X0DEF2_POS3 : +{0x768A,0xFFF6,0x02}, // MC3_Y0DEF2_POS3 : +{0x768C,0x003B,0x02}, // MC3_X0DEF3_POS3 : +{0x768E,0xFFBB,0x02}, // MC3_Y0DEF3_POS3 : +{0x7690,0xFFCE,0x02}, // MC3_X0DEF0_POS4 : +{0x7692,0xFFC9,0x02}, // MC3_Y0DEF0_POS4 : +{0x7694,0xFFD0,0x02}, // MC3_X0DEF1_POS4 : +{0x7696,0x0037,0x02}, // MC3_Y0DEF1_POS4 : +{0x7698,0x0002,0x02}, // MC3_X0DEF2_POS4 : +{0x769A,0xFFF6,0x02}, // MC3_Y0DEF2_POS4 : +{0x769C,0x003B,0x02}, // MC3_X0DEF3_POS4 : +{0x769E,0xFFBB,0x02}, // MC3_Y0DEF3_POS4 : +{0x76A0,0xFFCE,0x02}, // MC3_X0DEF0_POS5 : +{0x76A2,0xFFC9,0x02}, // MC3_Y0DEF0_POS5 : +{0x76A4,0xFFD0,0x02}, // MC3_X0DEF1_POS5 : +{0x76A6,0x0037,0x02}, // MC3_Y0DEF1_POS5 : +{0x76A8,0x0002,0x02}, // MC3_X0DEF2_POS5 : +{0x76AA,0xFFF6,0x02}, // MC3_Y0DEF2_POS5 : +{0x76AC,0x003B,0x02}, // MC3_X0DEF3_POS5 : +{0x76AE,0xFFBB,0x02}, // MC3_Y0DEF3_POS5 : +{0x76B0,0xFFCE,0x02}, // MC3_X0DEF0_POS6 : +{0x76B2,0xFFC9,0x02}, // MC3_Y0DEF0_POS6 : +{0x76B4,0xFFFE,0x02}, // MC3_X0DEF1_POS6 : +{0x76B6,0x000D,0x02}, // MC3_Y0DEF1_POS6 : +{0x76B8,0x0002,0x02}, // MC3_X0DEF2_POS6 : +{0x76BA,0xFFF6,0x02}, // MC3_Y0DEF2_POS6 : +{0x76BC,0x003B,0x02}, // MC3_X0DEF3_POS6 : +{0x76BE,0xFFBB,0x02}, // MC3_Y0DEF3_POS6 : +{0x76C0,0xFFCE,0x02}, // MC3_X0DEF0_POS7 : +{0x76C2,0xFFC9,0x02}, // MC3_Y0DEF0_POS7 : +{0x76C4,0xFFFE,0x02}, // MC3_X0DEF1_POS7 : +{0x76C6,0x000D,0x02}, // MC3_Y0DEF1_POS7 : +{0x76C8,0x0002,0x02}, // MC3_X0DEF2_POS7 : +{0x76CA,0xFFF6,0x02}, // MC3_Y0DEF2_POS7 : +{0x76CC,0x003B,0x02}, // MC3_X0DEF3_POS7 : +{0x76CE,0xFFBB,0x02}, // MC3_Y0DEF3_POS7 : +{0x76D0,0xFF7E,0x02}, // MC3_X0DEF0_OUT : +{0x76D2,0xFFE2,0x02}, // MC3_Y0DEF0_OUT : +{0x76D4,0xFFFE,0x02}, // MC3_X0DEF1_OUT : +{0x76D6,0x000D,0x02}, // MC3_Y0DEF1_OUT : +{0x76D8,0x0002,0x02}, // MC3_X0DEF2_OUT : +{0x76DA,0xFFF6,0x02}, // MC3_Y0DEF2_OUT : +{0x76DC,0xFFC4,0x02}, // MC3_X0DEF3_OUT : +{0x76DE,0xFFEC,0x02}, // MC3_Y0DEF3_OUT : +{0x76E0,0xFFCE,0x02}, // MC3_X0DEF0_R2_POS4 : +{0x76E2,0xFFC9,0x02}, // MC3_Y0DEF0_R2_POS4 : +{0x76E4,0xFFD0,0x02}, // MC3_X0DEF1_R2_POS4 : +{0x76E6,0x0037,0x02}, // MC3_Y0DEF1_R2_POS4 : +{0x76E8,0x0002,0x02}, // MC3_X0DEF2_R2_POS4 : +{0x76EA,0xFFF6,0x02}, // MC3_Y0DEF2_R2_POS4 : +{0x76EC,0x003B,0x02}, // MC3_X0DEF3_R2_POS4 : +{0x76EE,0xFFBB,0x02}, // MC3_Y0DEF3_R2_POS4 : +{0x76F0,0xFFCE,0x02}, // MC3_X0DEF0_R2_POS5 : +{0x76F2,0xFFC9,0x02}, // MC3_Y0DEF0_R2_POS5 : +{0x76F4,0xFFD0,0x02}, // MC3_X0DEF1_R2_POS5 : +{0x76F6,0x0037,0x02}, // MC3_Y0DEF1_R2_POS5 : +{0x76F8,0x0002,0x02}, // MC3_X0DEF2_R2_POS5 : +{0x76FA,0xFFF6,0x02}, // MC3_Y0DEF2_R2_POS5 : +{0x76FC,0x003B,0x02}, // MC3_X0DEF3_R2_POS5 : +{0x76FE,0xFFBB,0x02}, // MC3_Y0DEF3_R2_POS5 : +{0x7700,0x0019,0x02}, // MC3_PXDEF0_POS1 : +{0x7702,0xFF66,0x02}, // MC3_PYDEF0_POS1 : +{0x7704,0x0000,0x02}, // MC3_PXDEF1_POS1 : +{0x7706,0x0000,0x02}, // MC3_PYDEF1_POS1 : +{0x7708,0x0000,0x02}, // MC3_PXDEF2_POS1 : +{0x770A,0x0000,0x02}, // MC3_PYDEF2_POS1 : +{0x770C,0xFFD7,0x02}, // MC3_PXDEF3_POS1 : +{0x770E,0x0068,0x02}, // MC3_PYDEF3_POS1 : +{0x7710,0x0000,0x02}, // MC3_PXDEF0_POS2 : +{0x7712,0xFF66,0x02}, // MC3_PYDEF0_POS2 : +{0x7714,0x0033,0x02}, // MC3_PXDEF1_POS2 : +{0x7716,0xFF4C,0x02}, // MC3_PYDEF1_POS2 : +{0x7718,0x0000,0x02}, // MC3_PXDEF2_POS2 : +{0x771A,0x00B3,0x02}, // MC3_PYDEF2_POS2 : +{0x771C,0xFFD7,0x02}, // MC3_PXDEF3_POS2 : +{0x771E,0x0068,0x02}, // MC3_PYDEF3_POS2 : +{0x7720,0x0000,0x02}, // MC3_PXDEF0_POS3 : +{0x7722,0xFF80,0x02}, // MC3_PYDEF0_POS3 : +{0x7724,0x0000,0x02}, // MC3_PXDEF1_POS3 : +{0x7726,0x0000,0x02}, // MC3_PYDEF1_POS3 : +{0x7728,0x0000,0x02}, // MC3_PXDEF2_POS3 : +{0x772A,0x0000,0x02}, // MC3_PYDEF2_POS3 : +{0x772C,0xFFD7,0x02}, // MC3_PXDEF3_POS3 : +{0x772E,0x0068,0x02}, // MC3_PYDEF3_POS3 : +{0x7730,0x0000,0x02}, // MC3_PXDEF0_POS4 : +{0x7732,0xFFCC,0x02}, // MC3_PYDEF0_POS4 : +{0x7734,0x0000,0x02}, // MC3_PXDEF1_POS4 : +{0x7736,0x0000,0x02}, // MC3_PYDEF1_POS4 : +{0x7738,0x0000,0x02}, // MC3_PXDEF2_POS4 : +{0x773A,0x0000,0x02}, // MC3_PYDEF2_POS4 : +{0x773C,0xFFD7,0x02}, // MC3_PXDEF3_POS4 : +{0x773E,0x0068,0x02}, // MC3_PYDEF3_POS4 : +{0x7740,0x0000,0x02}, // MC3_PXDEF0_POS5 : +{0x7742,0xFFCC,0x02}, // MC3_PYDEF0_POS5 : +{0x7744,0x0000,0x02}, // MC3_PXDEF1_POS5 : +{0x7746,0x0000,0x02}, // MC3_PYDEF1_POS5 : +{0x7748,0x0000,0x02}, // MC3_PXDEF2_POS5 : +{0x774A,0x0000,0x02}, // MC3_PYDEF2_POS5 : +{0x774C,0xFFD7,0x02}, // MC3_PXDEF3_POS5 : +{0x774E,0x0068,0x02}, // MC3_PYDEF3_POS5 : +{0x7750,0xFFB3,0x02}, // MC3_PXDEF0_POS6 : +{0x7752,0x0000,0x02}, // MC3_PYDEF0_POS6 : +{0x7754,0x0033,0x02}, // MC3_PXDEF1_POS6 : +{0x7756,0xFF4C,0x02}, // MC3_PYDEF1_POS6 : +{0x7758,0x0000,0x02}, // MC3_PXDEF2_POS6 : +{0x775A,0x00B3,0x02}, // MC3_PYDEF2_POS6 : +{0x775C,0xFFD7,0x02}, // MC3_PXDEF3_POS6 : +{0x775E,0x0068,0x02}, // MC3_PYDEF3_POS6 : +{0x7760,0xFFB3,0x02}, // MC3_PXDEF0_POS7 : +{0x7762,0x0000,0x02}, // MC3_PYDEF0_POS7 : +{0x7764,0x0000,0x02}, // MC3_PXDEF1_POS7 : +{0x7766,0x0000,0x02}, // MC3_PYDEF1_POS7 : +{0x7768,0x0000,0x02}, // MC3_PXDEF2_POS7 : +{0x776A,0x0000,0x02}, // MC3_PYDEF2_POS7 : +{0x776C,0xFFD7,0x02}, // MC3_PXDEF3_POS7 : +{0x776E,0x0068,0x02}, // MC3_PYDEF3_POS7 : +{0x7770,0x0019,0x02}, // MC3_PXDEF0_OUT : +{0x7772,0xFFE6,0x02}, // MC3_PYDEF0_OUT : +{0x7774,0x0000,0x02}, // MC3_PXDEF1_OUT : +{0x7776,0x0000,0x02}, // MC3_PYDEF1_OUT : +{0x7778,0x0000,0x02}, // MC3_PXDEF2_OUT : +{0x777A,0x0000,0x02}, // MC3_PYDEF2_OUT : +{0x777C,0xFFE1,0x02}, // MC3_PXDEF3_OUT : +{0x777E,0xFFEB,0x02}, // MC3_PYDEF3_OUT : +{0x7780,0x0000,0x02}, // MC3_PXDEF0_R2_POS4 : +{0x7782,0xFFCC,0x02}, // MC3_PYDEF0_R2_POS4 : +{0x7784,0x0000,0x02}, // MC3_PXDEF1_R2_POS4 : +{0x7786,0x0000,0x02}, // MC3_PYDEF1_R2_POS4 : +{0x7788,0x0000,0x02}, // MC3_PXDEF2_R2_POS4 : +{0x778A,0x0000,0x02}, // MC3_PYDEF2_R2_POS4 : +{0x778C,0xFFD7,0x02}, // MC3_PXDEF3_R2_POS4 : +{0x778E,0x0068,0x02}, // MC3_PYDEF3_R2_POS4 : +{0x7790,0x0000,0x02}, // MC3_PXDEF0_R2_POS5 : +{0x7792,0xFFCC,0x02}, // MC3_PYDEF0_R2_POS5 : +{0x7794,0x0000,0x02}, // MC3_PXDEF1_R2_POS5 : +{0x7796,0x0000,0x02}, // MC3_PYDEF1_R2_POS5 : +{0x7798,0x0000,0x02}, // MC3_PXDEF2_R2_POS5 : +{0x779A,0x0000,0x02}, // MC3_PYDEF2_R2_POS5 : +{0x779C,0xFFD7,0x02}, // MC3_PXDEF3_R2_POS5 : +{0x779E,0x0068,0x02}, // MC3_PYDEF3_R2_POS5 : + +}; + +static const isx012_regset_t ISX012_Camcorder_Mode_OFF[] = { +//SN setting +{0x0308,0x11,0x01}, // AELINE_MONI_SN1_2 : +{0x0320,0x22,0x01}, // AELINE_MONI_SN1_2 : +{0x00B2,0x02,0x01}, // AFMODE_MONI : +//BRIGHTNESS setting +{0x01C6,0x00,0x01}, // UIBRIGHTNESS +//AE speed +{0x02AC,0x01,0x01}, // AE_SUB_SN1 : +{0x5E2D,0x08,0x01}, // AEMOVECNT : +{0x5E2E,0x1A,0x01}, // AEINDEADBAND : +{0x5E2F,0x04,0x01}, // AEOUTDEADBAND : +{0x5E30,0x20,0x01}, // AESPEED : +{0x5E31,0x0F,0x01}, // AESPEED_INIT : +{0x5E32,0x0F,0x01}, // AESPEED_FAST : +{0x621E,0x20,0x01}, // AIM_NR_TH_UP : +{0x621F,0x20,0x01}, // AIM_NR_TH_DOWN : +{0x6220,0x20,0x01}, // AIM_NR_TH_RIGHT : +{0x6221,0x20,0x01}, // AIM_NR_TH_LEFT : +//AWB speed +{0x6222,0x00,0x01}, // INIT_AIMW : +{0x6223,0x04,0x01}, // INIT_GAINS : +{0x6224,0x04,0x01}, // ATW_DELAY : +{0x6225,0x00,0x01}, // ATW_AIMW : +{0x6226,0x08,0x01}, // ATW_GAINS_IN_NR : +{0x6227,0x04,0x01}, // ATW_GAINS_IN : +{0x6228,0x08,0x01}, // ATW_GAINS_OUT_NR : +{0x6229,0x04,0x01}, // ATW_GAINS_OUT : +{0x622A,0x02,0x01}, // ALLWB_GAINS : +//Gammma Table 0 +{0x7000,0x0000,0x02}, // G0_KNOT_G0 : +{0x7002,0x0015,0x02}, // G0_KNOT_G1 : +{0x7004,0x002C,0x02}, // G0_KNOT_G2 : +{0x7006,0x0041,0x02}, // G0_KNOT_G3 : +{0x7008,0x004D,0x02}, // G0_KNOT_G4 : +{0x700A,0x005B,0x02}, // G0_KNOT_G5 : +{0x700C,0x0060,0x02}, // G0_KNOT_G6 : +{0x700E,0x0068,0x02}, // G0_KNOT_G7 : +{0x7010,0x006F,0x02}, // G0_KNOT_G8 : +{0x7012,0x0078,0x02}, // G0_KNOT_G9 : +{0x7014,0x0057,0x02}, // G0_KNOT_G10 : +{0x7016,0x0090,0x02}, // G0_KNOT_G11 : +{0x7018,0x00BB,0x02}, // G0_KNOT_G12 : +{0x701A,0x00D6,0x02}, // G0_KNOT_G13 : +{0x701C,0x00E5,0x02}, // G0_KNOT_G14 : +{0x701E,0x00F0,0x02}, // G0_KNOT_G15 : +{0x7020,0x00F9,0x02}, // G0_KNOT_G16 : +{0x7022,0x0103,0x02}, // G0_KNOT_G17 : +{0x7024,0x010C,0x02}, // G0_KNOT_G18 : +{0x7026,0x00,0x01}, // G0_KNOT_R0_OFFSET : +{0x7027,0x00,0x01}, // G0_KNOT_R2_OFFSET : +{0x7028,0x00,0x01}, // G0_KNOT_R4_OFFSET : +{0x7029,0x00,0x01}, // G0_KNOT_R6_OFFSET : +{0x702A,0x00,0x01}, // G0_KNOT_R8_OFFSET : +{0x702B,0x00,0x01}, // G0_KNOT_R10_OFFSET : +{0x702C,0x00,0x01}, // G0_KNOT_R12_OFFSET : +{0x702D,0x00,0x01}, // G0_KNOT_R14_OFFSET : +{0x702E,0x00,0x01}, // G0_KNOT_R16_OFFSET : +{0x702F,0x00,0x01}, // G0_KNOT_R18_OFFSET : +{0x7030,0x00,0x01}, // G0_KNOT_B0_OFFSET : +{0x7031,0x00,0x01}, // G0_KNOT_B2_OFFSET : +{0x7032,0x00,0x01}, // G0_KNOT_B4_OFFSET : +{0x7033,0x00,0x01}, // G0_KNOT_B6_OFFSET : +{0x7034,0x00,0x01}, // G0_KNOT_B8_OFFSET : +{0x7035,0x00,0x01}, // G0_KNOT_B10_OFFSET : +{0x7036,0x00,0x01}, // G0_KNOT_B12_OFFSET : +{0x7037,0x00,0x01}, // G0_KNOT_B14_OFFSET : +{0x7038,0x00,0x01}, // G0_KNOT_B16_OFFSET : +{0x7039,0x00,0x01}, // G0_KNOT_B18_OFFSET : +{0x703A,0x0611,0x02}, // G0_LOWGM_ON_R : +{0x703C,0x1E0A,0x02}, // G0_0CLIP_R : +{0x703E,0x0611,0x02}, // G0_LOWGM_ON_G : +{0x7040,0x1E0A,0x02}, // G0_0CLIP_G : +{0x7042,0x0611,0x02}, // G0_LOWGM_ON_B : +{0x7044,0x1E0A,0x02}, // G0_0CLIP_B : +{0x7046,0x9C,0x01}, // G0_KNOT_GAINCTRL_TH_L : +{0x7047,0xA1,0x01}, // G0_KNOT_GAINCTRL_TH_H : +{0x7048,0x0000,0x02}, // G0_KNOT_L_G0 : +{0x704A,0x0007,0x02}, // G0_KNOT_L_G1 : +{0x704C,0x0016,0x02}, // G0_KNOT_L_G2 : +{0x704E,0x002A,0x02}, // G0_KNOT_L_G3 : +{0x7050,0x0039,0x02}, // G0_KNOT_L_G4 : +{0x7052,0x004A,0x02}, // G0_KNOT_L_G5 : +{0x7054,0x0051,0x02}, // G0_KNOT_L_G6 : +{0x7056,0x005D,0x02}, // G0_KNOT_L_G7 : +{0x7058,0x0065,0x02}, // G0_KNOT_L_G8 : +{0x705A,0x006C,0x02}, // G0_KNOT_L_G9 : +{0x705C,0x004E,0x02}, // G0_KNOT_L_G10 : +{0x705E,0x0083,0x02}, // G0_KNOT_L_G11 : +{0x7060,0x00AA,0x02}, // G0_KNOT_L_G12 : +{0x7062,0x00C8,0x02}, // G0_KNOT_L_G13 : +{0x7064,0x00E1,0x02}, // G0_KNOT_L_G14 : +{0x7066,0x00F5,0x02}, // G0_KNOT_L_G15 : +{0x7068,0x0100,0x02}, // G0_KNOT_L_G16 : +{0x706A,0x0106,0x02}, // G0_KNOT_L_G17 : +{0x706C,0x010C,0x02}, // G0_KNOT_L_G18 : +{0x6400,0xAA,0x01}, // INFRM_LEFT00 : +{0x6401,0xAA,0x01}, // INFRM_LEFT01 : +{0x6402,0xAA,0x01}, // INFRM_LEFT02 : +{0x6403,0xAA,0x01}, // INFRM_LEFT03 : +{0x6404,0xAA,0x01}, // INFRM_LEFT04 : +{0x6405,0xAA,0x01}, // INFRM_LEFT05 : +{0x6406,0xAA,0x01}, // INFRM_LEFT06 : +{0x6407,0xAA,0x01}, // INFRM_LEFT07 : +{0x6408,0xAA,0x01}, // INFRM_LEFT08 : +{0x6409,0xAE,0x01}, // INFRM_LEFT09 : +{0x640A,0xA0,0x01}, // INFRM_LEFT10 : +{0x640B,0x8C,0x01}, // INFRM_LEFT11 : +{0x640C,0x72,0x01}, // INFRM_LEFT12 : +{0x640D,0x64,0x01}, // INFRM_LEFT13 : +{0x640E,0x5A,0x01}, // INFRM_LEFT14 : +{0x640F,0x52,0x01}, // INFRM_LEFT15 : +{0x6410,0x48,0x01}, // INFRM_LEFT16 : +{0x6411,0x43,0x01}, // INFRM_LEFT17 : +{0x6412,0x3D,0x01}, // INFRM_LEFT18 : +{0x6413,0x37,0x01}, // INFRM_LEFT19 : +{0x6414,0x33,0x01}, // INFRM_LEFT20 : +{0x6415,0x30,0x01}, // INFRM_LEFT21 : +{0x6416,0x2E,0x01}, // INFRM_LEFT22 : +{0x6417,0x2B,0x01}, // INFRM_LEFT23 : +{0x6418,0x28,0x01}, // INFRM_LEFT24 : +{0x6419,0x26,0x01}, // INFRM_LEFT25 : +{0x641A,0x24,0x01}, // INFRM_LEFT26 : +{0x641B,0x23,0x01}, // INFRM_LEFT27 : +{0x641C,0x22,0x01}, // INFRM_LEFT28 : +{0x641D,0x22,0x01}, // INFRM_LEFT29 : +{0x641E,0x21,0x01}, // INFRM_LEFT30 : +{0x641F,0x20,0x01}, // INFRM_LEFT31 : +{0x6420,0x1D,0x01}, // INFRM_LEFT32 : +{0x6421,0x1A,0x01}, // INFRM_LEFT33 : +{0x6422,0x18,0x01}, // INFRM_LEFT34 : +{0x6423,0x17,0x01}, // INFRM_LEFT35 : +{0x6424,0x16,0x01}, // INFRM_LEFT36 : +{0x6425,0x17,0x01}, // INFRM_LEFT37 : +{0x6426,0xAF,0x01}, // INFRM_RIGHT00 : +{0x6427,0xAF,0x01}, // INFRM_RIGHT01 : +{0x6428,0xAF,0x01}, // INFRM_RIGHT02 : +{0x6429,0xAF,0x01}, // INFRM_RIGHT03 : +{0x642A,0xAF,0x01}, // INFRM_RIGHT04 : +{0x642B,0xAF,0x01}, // INFRM_RIGHT05 : +{0x642C,0xAF,0x01}, // INFRM_RIGHT06 : +{0x642D,0xAF,0x01}, // INFRM_RIGHT07 : +{0x642E,0xAF,0x01}, // INFRM_RIGHT08 : +{0x642F,0xAA,0x01}, // INFRM_RIGHT09 : +{0x6430,0xB2,0x01}, // INFRM_RIGHT10 : +{0x6431,0xB4,0x01}, // INFRM_RIGHT11 : +{0x6432,0xB6,0x01}, // INFRM_RIGHT12 : +{0x6433,0xB4,0x01}, // INFRM_RIGHT13 : +{0x6434,0x9B,0x01}, // INFRM_RIGHT14 : +{0x6435,0x8E,0x01}, // INFRM_RIGHT15 : +{0x6436,0x84,0x01}, // INFRM_RIGHT16 : +{0x6437,0x7A,0x01}, // INFRM_RIGHT17 : +{0x6438,0x72,0x01}, // INFRM_RIGHT18 : +{0x6439,0x6A,0x01}, // INFRM_RIGHT19 : +{0x643A,0x63,0x01}, // INFRM_RIGHT20 : +{0x643B,0x5E,0x01}, // INFRM_RIGHT21 : +{0x643C,0x58,0x01}, // INFRM_RIGHT22 : +{0x643D,0x53,0x01}, // INFRM_RIGHT23 : +{0x643E,0x4E,0x01}, // INFRM_RIGHT24 : +{0x643F,0x4A,0x01}, // INFRM_RIGHT25 : +{0x6440,0x46,0x01}, // INFRM_RIGHT26 : +{0x6441,0x42,0x01}, // INFRM_RIGHT27 : +{0x6442,0x3F,0x01}, // INFRM_RIGHT28 : +{0x6443,0x3C,0x01}, // INFRM_RIGHT29 : +{0x6444,0x3A,0x01}, // INFRM_RIGHT30 : +{0x6445,0x38,0x01}, // INFRM_RIGHT31 : +{0x6446,0x37,0x01}, // INFRM_RIGHT32 : +{0x6447,0x35,0x01}, // INFRM_RIGHT33 : +{0x6448,0x33,0x01}, // INFRM_RIGHT34 : +{0x6449,0x32,0x01}, // INFRM_RIGHT35 : +{0x644A,0x32,0x01}, // INFRM_RIGHT36 : +{0x644B,0x32,0x01}, // INFRM_RIGHT37 : +{0x644C,0x24FA,0x02}, // INFRM_TOP : +{0x644E,0x0940,0x02}, // INFRM_BOTM : +{0x6450,0x19,0x01}, // INFRM_FLTOP : +{0x6451,0x10,0x01}, // INFRM_FLBOTM : +{0x6452,0x91,0x01}, // INAIM_LEFT00 : +{0x6453,0x91,0x01}, // INAIM_LEFT01 : +{0x6454,0x91,0x01}, // INAIM_LEFT02 : +{0x6455,0x91,0x01}, // INAIM_LEFT03 : +{0x6456,0x91,0x01}, // INAIM_LEFT04 : +{0x6457,0x91,0x01}, // INAIM_LEFT05 : +{0x6458,0x91,0x01}, // INAIM_LEFT06 : +{0x6459,0x91,0x01}, // INAIM_LEFT07 : +{0x645A,0x91,0x01}, // INAIM_LEFT08 : +{0x645B,0x91,0x01}, // INAIM_LEFT09 : +{0x645C,0x91,0x01}, // INAIM_LEFT10 : +{0x645D,0x91,0x01}, // INAIM_LEFT11 : +{0x645E,0x91,0x01}, // INAIM_LEFT12 : +{0x645F,0x66,0x01}, // INAIM_LEFT13 : +{0x6460,0x71,0x01}, // INAIM_LEFT14 : +{0x6461,0x5A,0x01}, // INAIM_LEFT15 : +{0x6462,0x4E,0x01}, // INAIM_LEFT16 : +{0x6463,0x47,0x01}, // INAIM_LEFT17 : +{0x6464,0x42,0x01}, // INAIM_LEFT18 : +{0x6465,0x3C,0x01}, // INAIM_LEFT19 : +{0x6466,0x38,0x01}, // INAIM_LEFT20 : +{0x6467,0x36,0x01}, // INAIM_LEFT21 : +{0x6468,0x33,0x01}, // INAIM_LEFT22 : +{0x6469,0x30,0x01}, // INAIM_LEFT23 : +{0x646A,0x2F,0x01}, // INAIM_LEFT24 : +{0x646B,0x2B,0x01}, // INAIM_LEFT25 : +{0x646C,0x29,0x01}, // INAIM_LEFT26 : +{0x646D,0x27,0x01}, // INAIM_LEFT27 : +{0x646E,0x26,0x01}, // INAIM_LEFT28 : +{0x646F,0x28,0x01}, // INAIM_LEFT29 : +{0x6470,0x2A,0x01}, // INAIM_LEFT30 : +{0x6471,0x28,0x01}, // INAIM_LEFT31 : +{0x6472,0x26,0x01}, // INAIM_LEFT32 : +{0x6473,0x24,0x01}, // INAIM_LEFT33 : +{0x6474,0x29,0x01}, // INAIM_LEFT34 : +{0x6475,0x28,0x01}, // INAIM_LEFT35 : +{0x6476,0x29,0x01}, // INAIM_LEFT36 : +{0x6477,0x26,0x01}, // INAIM_LEFT37 : +{0x6478,0xFF,0x01}, // INAIM_RIGHT00 : +{0x6479,0xFF,0x01}, // INAIM_RIGHT01 : +{0x647A,0xFF,0x01}, // INAIM_RIGHT02 : +{0x647B,0xFF,0x01}, // INAIM_RIGHT03 : +{0x647C,0xFF,0x01}, // INAIM_RIGHT04 : +{0x647D,0xFF,0x01}, // INAIM_RIGHT05 : +{0x647E,0xFF,0x01}, // INAIM_RIGHT06 : +{0x647F,0xFF,0x01}, // INAIM_RIGHT07 : +{0x6480,0xFF,0x01}, // INAIM_RIGHT08 : +{0x6481,0xFF,0x01}, // INAIM_RIGHT09 : +{0x6482,0xD9,0x01}, // INAIM_RIGHT10 : +{0x6483,0xB7,0x01}, // INAIM_RIGHT11 : +{0x6484,0x96,0x01}, // INAIM_RIGHT12 : +{0x6485,0x68,0x01}, // INAIM_RIGHT13 : +{0x6486,0x72,0x01}, // INAIM_RIGHT14 : +{0x6487,0x71,0x01}, // INAIM_RIGHT15 : +{0x6488,0x6E,0x01}, // INAIM_RIGHT16 : +{0x6489,0x6A,0x01}, // INAIM_RIGHT17 : +{0x648A,0x65,0x01}, // INAIM_RIGHT18 : +{0x648B,0x60,0x01}, // INAIM_RIGHT19 : +{0x648C,0x5B,0x01}, // INAIM_RIGHT20 : +{0x648D,0x56,0x01}, // INAIM_RIGHT21 : +{0x648E,0x51,0x01}, // INAIM_RIGHT22 : +{0x648F,0x4C,0x01}, // INAIM_RIGHT23 : +{0x6490,0x47,0x01}, // INAIM_RIGHT24 : +{0x6491,0x44,0x01}, // INAIM_RIGHT25 : +{0x6492,0x41,0x01}, // INAIM_RIGHT26 : +{0x6493,0x3E,0x01}, // INAIM_RIGHT27 : +{0x6494,0x3B,0x01}, // INAIM_RIGHT28 : +{0x6495,0x39,0x01}, // INAIM_RIGHT29 : +{0x6496,0x37,0x01}, // INAIM_RIGHT30 : +{0x6497,0x34,0x01}, // INAIM_RIGHT31 : +{0x6498,0x33,0x01}, // INAIM_RIGHT32 : +{0x6499,0x32,0x01}, // INAIM_RIGHT33 : +{0x649A,0x31,0x01}, // INAIM_RIGHT34 : +{0x649B,0x30,0x01}, // INAIM_RIGHT35 : +{0x649C,0x2F,0x01}, // INAIM_RIGHT36 : +{0x649D,0x2E,0x01}, // INAIM_RIGHT37 : +{0x649E,0x1E00,0x02}, // INAIM_TOP : +{0x64A0,0x0DFF,0x02}, // INAIM_BOTM : +{0x64A2,0x18,0x01}, // INAIM_FLTOP : +{0x64A3,0x09,0x01}, // INAIM_FLBOTM : +{0x64A4,0xFF,0x01}, // OUTFRM_LEFT00 : +{0x64A5,0xFF,0x01}, // OUTFRM_LEFT01 : +{0x64A6,0xFF,0x01}, // OUTFRM_LEFT02 : +{0x64A7,0xFF,0x01}, // OUTFRM_LEFT03 : +{0x64A8,0xFF,0x01}, // OUTFRM_LEFT04 : +{0x64A9,0xFF,0x01}, // OUTFRM_LEFT05 : +{0x64AA,0xFF,0x01}, // OUTFRM_LEFT06 : +{0x64AB,0xFF,0x01}, // OUTFRM_LEFT07 : +{0x64AC,0xFF,0x01}, // OUTFRM_LEFT08 : +{0x64AD,0xFD,0x01}, // OUTFRM_LEFT09 : +{0x64AE,0xCB,0x01}, // OUTFRM_LEFT10 : +{0x64AF,0xA9,0x01}, // OUTFRM_LEFT11 : +{0x64B0,0x90,0x01}, // OUTFRM_LEFT12 : +{0x64B1,0x7D,0x01}, // OUTFRM_LEFT13 : +{0x64B2,0x70,0x01}, // OUTFRM_LEFT14 : +{0x64B3,0x65,0x01}, // OUTFRM_LEFT15 : +{0x64B4,0x5C,0x01}, // OUTFRM_LEFT16 : +{0x64B5,0x55,0x01}, // OUTFRM_LEFT17 : +{0x64B6,0x4F,0x01}, // OUTFRM_LEFT18 : +{0x64B7,0x32,0x01}, // OUTFRM_LEFT19 : +{0x64B8,0x4D,0x01}, // OUTFRM_LEFT20 : +{0x64B9,0x40,0x01}, // OUTFRM_LEFT21 : +{0x64BA,0x2D,0x01}, // OUTFRM_LEFT22 : +{0x64BB,0x2B,0x01}, // OUTFRM_LEFT23 : +{0x64BC,0x29,0x01}, // OUTFRM_LEFT24 : +{0x64BD,0x27,0x01}, // OUTFRM_LEFT25 : +{0x64BE,0x25,0x01}, // OUTFRM_LEFT26 : +{0x64BF,0x23,0x01}, // OUTFRM_LEFT27 : +{0x64C0,0x21,0x01}, // OUTFRM_LEFT28 : +{0x64C1,0x1F,0x01}, // OUTFRM_LEFT29 : +{0x64C2,0x1D,0x01}, // OUTFRM_LEFT30 : +{0x64C3,0x1B,0x01}, // OUTFRM_LEFT31 : +{0x64C4,0x1A,0x01}, // OUTFRM_LEFT32 : +{0x64C5,0x1A,0x01}, // OUTFRM_LEFT33 : +{0x64C6,0x1A,0x01}, // OUTFRM_LEFT34 : +{0x64C7,0x28,0x01}, // OUTFRM_LEFT35 : +{0x64C8,0x27,0x01}, // OUTFRM_LEFT36 : +{0x64C9,0x26,0x01}, // OUTFRM_LEFT37 : +{0x64CA,0xFF,0x01}, // OUTFRM_RIGHT00 : +{0x64CB,0xFF,0x01}, // OUTFRM_RIGHT01 : +{0x64CC,0xFF,0x01}, // OUTFRM_RIGHT02 : +{0x64CD,0xFF,0x01}, // OUTFRM_RIGHT03 : +{0x64CE,0xFF,0x01}, // OUTFRM_RIGHT04 : +{0x64CF,0xFF,0x01}, // OUTFRM_RIGHT05 : +{0x64D0,0xFF,0x01}, // OUTFRM_RIGHT06 : +{0x64D1,0xFF,0x01}, // OUTFRM_RIGHT07 : +{0x64D2,0xFF,0x01}, // OUTFRM_RIGHT08 : +{0x64D3,0xFF,0x01}, // OUTFRM_RIGHT09 : +{0x64D4,0xD3,0x01}, // OUTFRM_RIGHT10 : +{0x64D5,0xB1,0x01}, // OUTFRM_RIGHT11 : +{0x64D6,0x98,0x01}, // OUTFRM_RIGHT12 : +{0x64D7,0x85,0x01}, // OUTFRM_RIGHT13 : +{0x64D8,0x78,0x01}, // OUTFRM_RIGHT14 : +{0x64D9,0x6D,0x01}, // OUTFRM_RIGHT15 : +{0x64DA,0x64,0x01}, // OUTFRM_RIGHT16 : +{0x64DB,0x5D,0x01}, // OUTFRM_RIGHT17 : +{0x64DC,0x57,0x01}, // OUTFRM_RIGHT18 : +{0x64DD,0x63,0x01}, // OUTFRM_RIGHT19 : +{0x64DE,0x5E,0x01}, // OUTFRM_RIGHT20 : +{0x64DF,0x5A,0x01}, // OUTFRM_RIGHT21 : +{0x64E0,0x56,0x01}, // OUTFRM_RIGHT22 : +{0x64E1,0x52,0x01}, // OUTFRM_RIGHT23 : +{0x64E2,0x50,0x01}, // OUTFRM_RIGHT24 : +{0x64E3,0x4E,0x01}, // OUTFRM_RIGHT25 : +{0x64E4,0x4C,0x01}, // OUTFRM_RIGHT26 : +{0x64E5,0x4A,0x01}, // OUTFRM_RIGHT27 : +{0x64E6,0x48,0x01}, // OUTFRM_RIGHT28 : +{0x64E7,0x46,0x01}, // OUTFRM_RIGHT29 : +{0x64E8,0x44,0x01}, // OUTFRM_RIGHT30 : +{0x64E9,0x43,0x01}, // OUTFRM_RIGHT31 : +{0x64EA,0x42,0x01}, // OUTFRM_RIGHT32 : +{0x64EB,0x42,0x01}, // OUTFRM_RIGHT33 : +{0x64EC,0x42,0x01}, // OUTFRM_RIGHT34 : +{0x64ED,0x30,0x01}, // OUTFRM_RIGHT35 : +{0x64EE,0x2F,0x01}, // OUTFRM_RIGHT36 : +{0x64EF,0x2E,0x01}, // OUTFRM_RIGHT37 : +{0x64F0,0x2163,0x02}, // OUTFRM_TOP : +{0x64F2,0x1400,0x02}, // OUTFRM_BOTM : +{0x64F4,0x19,0x01}, // OUTFRM_FLTOP : +{0x64F5,0x14,0x01}, // OUTFRM_FLBOTM : +//AWB +{0x6232,0xFF,0x01}, // ATW_SFTLMT_OUT_NR +{0x6234,0xFF,0x01}, // ATW_SFTLMT_OUT +/////MC3 Setting///// +{0x7600,0x07,0x01}, // MC3_PXDEF0_SEL : +{0x7601,0x07,0x01}, // MC3_PYDEF0_SEL : +{0x7602,0x07,0x01}, // MC3_PXDEF1_SEL : +{0x7603,0x07,0x01}, // MC3_PYDEF1_SEL : +{0x7604,0x07,0x01}, // MC3_PXDEF2_SEL : +{0x7605,0x07,0x01}, // MC3_PYDEF2_SEL : +{0x7606,0x07,0x01}, // MC3_PXDEF3_SEL : +{0x7607,0x07,0x01}, // MC3_PYDEF3_SEL : +{0x7608,0x40,0x01}, // MC3_PXDEF0_A : +{0x7609,0x40,0x01}, // MC3_PXDEF0_B : +{0x760A,0x40,0x01}, // MC3_PXDEF0_C : +{0x760B,0x40,0x01}, // MC3_PYDEF0_A : +{0x760C,0x40,0x01}, // MC3_PYDEF0_B : +{0x760D,0x40,0x01}, // MC3_PYDEF0_C : +{0x760E,0x40,0x01}, // MC3_PXDEF1_A : +{0x760F,0x40,0x01}, // MC3_PXDEF1_B : +{0x7610,0x40,0x01}, // MC3_PXDEF1_C : +{0x7611,0x40,0x01}, // MC3_PYDEF1_A : +{0x7612,0x40,0x01}, // MC3_PYDEF1_B : +{0x7613,0x40,0x01}, // MC3_PYDEF1_C : +{0x7614,0x40,0x01}, // MC3_PXDEF2_A : +{0x7615,0x40,0x01}, // MC3_PXDEF2_B : +{0x7616,0x40,0x01}, // MC3_PXDEF2_C : +{0x7617,0x40,0x01}, // MC3_PYDEF2_A : +{0x7618,0x40,0x01}, // MC3_PYDEF2_B : +{0x7619,0x40,0x01}, // MC3_PYDEF2_C : +{0x761A,0x40,0x01}, // MC3_PXDEF3_A : +{0x761B,0x40,0x01}, // MC3_PXDEF3_B : +{0x761C,0x40,0x01}, // MC3_PXDEF3_C : +{0x761D,0x40,0x01}, // MC3_PYDEF3_A : +{0x761E,0x40,0x01}, // MC3_PYDEF3_B : +{0x761F,0x40,0x01}, // MC3_PYDEF3_C : +{0x7620,0x00,0x01}, // MC3_LUMSL0_IN : +{0x7621,0x06,0x01}, // MC3_LUMSL1_IN : +{0x7622,0x03,0x01}, // MC3_LUMSL2_IN : +{0x7623,0x06,0x01}, // MC3_LUMSL3_IN : +{0x7624,0x00,0x01}, // MC3_LUMSL0_OUT : +{0x7625,0x03,0x01}, // MC3_LUMSL1_OUT : +{0x7626,0x00,0x01}, // MC3_LUMSL2_OUT : +{0x7627,0x00,0x01}, // MC3_LUMSL3_OUT : +{0x7628,0x0000,0x02}, // MC3_L0DEF0_IN : +{0x762A,0x008C,0x02}, // MC3_L0DEF1_IN : +{0x762C,0x0078,0x02}, // MC3_L0DEF2_IN : +{0x762E,0x00E6,0x02}, // MC3_L0DEF3_IN : +{0x7630,0x0000,0x02}, // MC3_L0DEF0_OUT : +{0x7632,0x0082,0x02}, // MC3_L0DEF1_OUT : +{0x7634,0x0000,0x02}, // MC3_L0DEF2_OUT : +{0x7636,0x0000,0x02}, // MC3_L0DEF3_OUT : +{0x7638,0x41,0x01}, // MC3_RDEF0_POS1 : +{0x7639,0x10,0x01}, // MC3_RDEF1_POS1 : +{0x763A,0x15,0x01}, // MC3_RDEF2_POS1 : +{0x763B,0x71,0x01}, // MC3_RDEF3_POS1 : +{0x763C,0x41,0x01}, // MC3_RDEF0_POS2 : +{0x763D,0x10,0x01}, // MC3_RDEF1_POS2 : +{0x763E,0x15,0x01}, // MC3_RDEF2_POS2 : +{0x763F,0x71,0x01}, // MC3_RDEF3_POS2 : +{0x7640,0x3C,0x01}, // MC3_RDEF0_POS3 : +{0x7641,0x10,0x01}, // MC3_RDEF1_POS3 : +{0x7642,0x15,0x01}, // MC3_RDEF2_POS3 : +{0x7643,0x71,0x01}, // MC3_RDEF3_POS3 : +{0x7644,0x46,0x01}, // MC3_RDEF0_POS4 : +{0x7645,0x32,0x01}, // MC3_RDEF1_POS4 : +{0x7646,0x15,0x01}, // MC3_RDEF2_POS4 : +{0x7647,0x71,0x01}, // MC3_RDEF3_POS4 : +{0x7648,0x46,0x01}, // MC3_RDEF0_POS5 : +{0x7649,0x32,0x01}, // MC3_RDEF1_POS5 : +{0x764A,0x15,0x01}, // MC3_RDEF2_POS5 : +{0x764B,0x71,0x01}, // MC3_RDEF3_POS5 : +{0x764C,0x46,0x01}, // MC3_RDEF0_POS6 : +{0x764D,0x10,0x01}, // MC3_RDEF1_POS6 : +{0x764E,0x15,0x01}, // MC3_RDEF2_POS6 : +{0x764F,0x71,0x01}, // MC3_RDEF3_POS6 : +{0x7650,0x46,0x01}, // MC3_RDEF0_POS7 : +{0x7651,0x10,0x01}, // MC3_RDEF1_POS7 : +{0x7652,0x15,0x01}, // MC3_RDEF2_POS7 : +{0x7653,0x71,0x01}, // MC3_RDEF3_POS7 : +{0x7654,0x2D,0x01}, // MC3_RDEF0_OUT : +{0x7655,0x10,0x01}, // MC3_RDEF1_OUT : +{0x7656,0x15,0x01}, // MC3_RDEF2_OUT : +{0x7657,0x54,0x01}, // MC3_RDEF3_OUT : +{0x7658,0x46,0x01}, // MC3_RDEF0_R2_POS4 : +{0x7659,0x32,0x01}, // MC3_RDEF1_R2_POS4 : +{0x765A,0x15,0x01}, // MC3_RDEF2_R2_POS4 : +{0x765B,0x71,0x01}, // MC3_RDEF3_R2_POS4 : +{0x765C,0x46,0x01}, // MC3_RDEF0_R2_POS5 : +{0x765D,0x32,0x01}, // MC3_RDEF1_R2_POS5 : +{0x765E,0x15,0x01}, // MC3_RDEF2_R2_POS5 : +{0x765F,0x71,0x01}, // MC3_RDEF3_R2_POS5 : +{0x7660,0xFFBA,0x02}, // MC3_X0DEF0_POS1 : +{0x7662,0xFFBA,0x02}, // MC3_Y0DEF0_POS1 : +{0x7664,0xFFFE,0x02}, // MC3_X0DEF1_POS1 : +{0x7666,0x000D,0x02}, // MC3_Y0DEF1_POS1 : +{0x7668,0x0002,0x02}, // MC3_X0DEF2_POS1 : +{0x766A,0xFFF6,0x02}, // MC3_Y0DEF2_POS1 : +{0x766C,0x003B,0x02}, // MC3_X0DEF3_POS1 : +{0x766E,0xFFBB,0x02}, // MC3_Y0DEF3_POS1 : +{0x7670,0xFFBA,0x02}, // MC3_X0DEF0_POS2 : +{0x7672,0xFFBA,0x02}, // MC3_Y0DEF0_POS2 : +{0x7674,0xFFFE,0x02}, // MC3_X0DEF1_POS2 : +{0x7676,0x000D,0x02}, // MC3_Y0DEF1_POS2 : +{0x7678,0x0002,0x02}, // MC3_X0DEF2_POS2 : +{0x767A,0xFFF6,0x02}, // MC3_Y0DEF2_POS2 : +{0x767C,0x003B,0x02}, // MC3_X0DEF3_POS2 : +{0x767E,0xFFBB,0x02}, // MC3_Y0DEF3_POS2 : +{0x7680,0xFFCE,0x02}, // MC3_X0DEF0_POS3 : +{0x7682,0xFFBA,0x02}, // MC3_Y0DEF0_POS3 : +{0x7684,0xFFFE,0x02}, // MC3_X0DEF1_POS3 : +{0x7686,0x000D,0x02}, // MC3_Y0DEF1_POS3 : +{0x7688,0x0002,0x02}, // MC3_X0DEF2_POS3 : +{0x768A,0xFFF6,0x02}, // MC3_Y0DEF2_POS3 : +{0x768C,0x003B,0x02}, // MC3_X0DEF3_POS3 : +{0x768E,0xFFBB,0x02}, // MC3_Y0DEF3_POS3 : +{0x7690,0xFFCE,0x02}, // MC3_X0DEF0_POS4 : +{0x7692,0xFFC9,0x02}, // MC3_Y0DEF0_POS4 : +{0x7694,0xFFD0,0x02}, // MC3_X0DEF1_POS4 : +{0x7696,0x0037,0x02}, // MC3_Y0DEF1_POS4 : +{0x7698,0x0002,0x02}, // MC3_X0DEF2_POS4 : +{0x769A,0xFFF6,0x02}, // MC3_Y0DEF2_POS4 : +{0x769C,0x003B,0x02}, // MC3_X0DEF3_POS4 : +{0x769E,0xFFBB,0x02}, // MC3_Y0DEF3_POS4 : +{0x76A0,0xFFCE,0x02}, // MC3_X0DEF0_POS5 : +{0x76A2,0xFFC9,0x02}, // MC3_Y0DEF0_POS5 : +{0x76A4,0xFFD0,0x02}, // MC3_X0DEF1_POS5 : +{0x76A6,0x0037,0x02}, // MC3_Y0DEF1_POS5 : +{0x76A8,0x0002,0x02}, // MC3_X0DEF2_POS5 : +{0x76AA,0xFFF6,0x02}, // MC3_Y0DEF2_POS5 : +{0x76AC,0x003B,0x02}, // MC3_X0DEF3_POS5 : +{0x76AE,0xFFBB,0x02}, // MC3_Y0DEF3_POS5 : +{0x76B0,0xFFCE,0x02}, // MC3_X0DEF0_POS6 : +{0x76B2,0xFFC9,0x02}, // MC3_Y0DEF0_POS6 : +{0x76B4,0xFFFE,0x02}, // MC3_X0DEF1_POS6 : +{0x76B6,0x000D,0x02}, // MC3_Y0DEF1_POS6 : +{0x76B8,0x0002,0x02}, // MC3_X0DEF2_POS6 : +{0x76BA,0xFFF6,0x02}, // MC3_Y0DEF2_POS6 : +{0x76BC,0x003B,0x02}, // MC3_X0DEF3_POS6 : +{0x76BE,0xFFBB,0x02}, // MC3_Y0DEF3_POS6 : +{0x76C0,0xFFCE,0x02}, // MC3_X0DEF0_POS7 : +{0x76C2,0xFFC9,0x02}, // MC3_Y0DEF0_POS7 : +{0x76C4,0xFFFE,0x02}, // MC3_X0DEF1_POS7 : +{0x76C6,0x000D,0x02}, // MC3_Y0DEF1_POS7 : +{0x76C8,0x0002,0x02}, // MC3_X0DEF2_POS7 : +{0x76CA,0xFFF6,0x02}, // MC3_Y0DEF2_POS7 : +{0x76CC,0x003B,0x02}, // MC3_X0DEF3_POS7 : +{0x76CE,0xFFBB,0x02}, // MC3_Y0DEF3_POS7 : +{0x76D0,0xFF7E,0x02}, // MC3_X0DEF0_OUT : +{0x76D2,0xFFE2,0x02}, // MC3_Y0DEF0_OUT : +{0x76D4,0xFFFE,0x02}, // MC3_X0DEF1_OUT : +{0x76D6,0x000D,0x02}, // MC3_Y0DEF1_OUT : +{0x76D8,0x0002,0x02}, // MC3_X0DEF2_OUT : +{0x76DA,0xFFF6,0x02}, // MC3_Y0DEF2_OUT : +{0x76DC,0xFFC4,0x02}, // MC3_X0DEF3_OUT : +{0x76DE,0xFFEC,0x02}, // MC3_Y0DEF3_OUT : +{0x76E0,0xFFCE,0x02}, // MC3_X0DEF0_R2_POS4 : +{0x76E2,0xFFC9,0x02}, // MC3_Y0DEF0_R2_POS4 : +{0x76E4,0xFFD0,0x02}, // MC3_X0DEF1_R2_POS4 : +{0x76E6,0x0037,0x02}, // MC3_Y0DEF1_R2_POS4 : +{0x76E8,0x0002,0x02}, // MC3_X0DEF2_R2_POS4 : +{0x76EA,0xFFF6,0x02}, // MC3_Y0DEF2_R2_POS4 : +{0x76EC,0x003B,0x02}, // MC3_X0DEF3_R2_POS4 : +{0x76EE,0xFFBB,0x02}, // MC3_Y0DEF3_R2_POS4 : +{0x76F0,0xFFCE,0x02}, // MC3_X0DEF0_R2_POS5 : +{0x76F2,0xFFC9,0x02}, // MC3_Y0DEF0_R2_POS5 : +{0x76F4,0xFFD0,0x02}, // MC3_X0DEF1_R2_POS5 : +{0x76F6,0x0037,0x02}, // MC3_Y0DEF1_R2_POS5 : +{0x76F8,0x0002,0x02}, // MC3_X0DEF2_R2_POS5 : +{0x76FA,0xFFF6,0x02}, // MC3_Y0DEF2_R2_POS5 : +{0x76FC,0x003B,0x02}, // MC3_X0DEF3_R2_POS5 : +{0x76FE,0xFFBB,0x02}, // MC3_Y0DEF3_R2_POS5 : +{0x7700,0x0019,0x02}, // MC3_PXDEF0_POS1 : +{0x7702,0xFF66,0x02}, // MC3_PYDEF0_POS1 : +{0x7704,0x0000,0x02}, // MC3_PXDEF1_POS1 : +{0x7706,0x0000,0x02}, // MC3_PYDEF1_POS1 : +{0x7708,0x0000,0x02}, // MC3_PXDEF2_POS1 : +{0x770A,0x0000,0x02}, // MC3_PYDEF2_POS1 : +{0x770C,0xFFD7,0x02}, // MC3_PXDEF3_POS1 : +{0x770E,0x0068,0x02}, // MC3_PYDEF3_POS1 : +{0x7710,0x0000,0x02}, // MC3_PXDEF0_POS2 : +{0x7712,0xFF66,0x02}, // MC3_PYDEF0_POS2 : +{0x7714,0x0033,0x02}, // MC3_PXDEF1_POS2 : +{0x7716,0xFF4C,0x02}, // MC3_PYDEF1_POS2 : +{0x7718,0x0000,0x02}, // MC3_PXDEF2_POS2 : +{0x771A,0x00B3,0x02}, // MC3_PYDEF2_POS2 : +{0x771C,0xFFD7,0x02}, // MC3_PXDEF3_POS2 : +{0x771E,0x0068,0x02}, // MC3_PYDEF3_POS2 : +{0x7720,0x0000,0x02}, // MC3_PXDEF0_POS3 : +{0x7722,0xFF80,0x02}, // MC3_PYDEF0_POS3 : +{0x7724,0x0000,0x02}, // MC3_PXDEF1_POS3 : +{0x7726,0x0000,0x02}, // MC3_PYDEF1_POS3 : +{0x7728,0x0000,0x02}, // MC3_PXDEF2_POS3 : +{0x772A,0x0000,0x02}, // MC3_PYDEF2_POS3 : +{0x772C,0xFFD7,0x02}, // MC3_PXDEF3_POS3 : +{0x772E,0x0068,0x02}, // MC3_PYDEF3_POS3 : +{0x7730,0x0000,0x02}, // MC3_PXDEF0_POS4 : +{0x7732,0xFFCC,0x02}, // MC3_PYDEF0_POS4 : +{0x7734,0x0000,0x02}, // MC3_PXDEF1_POS4 : +{0x7736,0x0000,0x02}, // MC3_PYDEF1_POS4 : +{0x7738,0x0000,0x02}, // MC3_PXDEF2_POS4 : +{0x773A,0x0000,0x02}, // MC3_PYDEF2_POS4 : +{0x773C,0xFFD7,0x02}, // MC3_PXDEF3_POS4 : +{0x773E,0x0068,0x02}, // MC3_PYDEF3_POS4 : +{0x7740,0x0000,0x02}, // MC3_PXDEF0_POS5 : +{0x7742,0xFFCC,0x02}, // MC3_PYDEF0_POS5 : +{0x7744,0x0000,0x02}, // MC3_PXDEF1_POS5 : +{0x7746,0x0000,0x02}, // MC3_PYDEF1_POS5 : +{0x7748,0x0000,0x02}, // MC3_PXDEF2_POS5 : +{0x774A,0x0000,0x02}, // MC3_PYDEF2_POS5 : +{0x774C,0xFFD7,0x02}, // MC3_PXDEF3_POS5 : +{0x774E,0x0068,0x02}, // MC3_PYDEF3_POS5 : +{0x7750,0xFFB3,0x02}, // MC3_PXDEF0_POS6 : +{0x7752,0x0000,0x02}, // MC3_PYDEF0_POS6 : +{0x7754,0x0033,0x02}, // MC3_PXDEF1_POS6 : +{0x7756,0xFF4C,0x02}, // MC3_PYDEF1_POS6 : +{0x7758,0x0000,0x02}, // MC3_PXDEF2_POS6 : +{0x775A,0x00B3,0x02}, // MC3_PYDEF2_POS6 : +{0x775C,0xFFD7,0x02}, // MC3_PXDEF3_POS6 : +{0x775E,0x0068,0x02}, // MC3_PYDEF3_POS6 : +{0x7760,0xFFB3,0x02}, // MC3_PXDEF0_POS7 : +{0x7762,0x0000,0x02}, // MC3_PYDEF0_POS7 : +{0x7764,0x0000,0x02}, // MC3_PXDEF1_POS7 : +{0x7766,0x0000,0x02}, // MC3_PYDEF1_POS7 : +{0x7768,0x0000,0x02}, // MC3_PXDEF2_POS7 : +{0x776A,0x0000,0x02}, // MC3_PYDEF2_POS7 : +{0x776C,0xFFD7,0x02}, // MC3_PXDEF3_POS7 : +{0x776E,0x0068,0x02}, // MC3_PYDEF3_POS7 : +{0x7770,0x0019,0x02}, // MC3_PXDEF0_OUT : +{0x7772,0xFFE6,0x02}, // MC3_PYDEF0_OUT : +{0x7774,0x0000,0x02}, // MC3_PXDEF1_OUT : +{0x7776,0x0000,0x02}, // MC3_PYDEF1_OUT : +{0x7778,0x0000,0x02}, // MC3_PXDEF2_OUT : +{0x777A,0x0000,0x02}, // MC3_PYDEF2_OUT : +{0x777C,0xFFE1,0x02}, // MC3_PXDEF3_OUT : +{0x777E,0xFFEB,0x02}, // MC3_PYDEF3_OUT : +{0x7780,0x0000,0x02}, // MC3_PXDEF0_R2_POS4 : +{0x7782,0xFFCC,0x02}, // MC3_PYDEF0_R2_POS4 : +{0x7784,0x0000,0x02}, // MC3_PXDEF1_R2_POS4 : +{0x7786,0x0000,0x02}, // MC3_PYDEF1_R2_POS4 : +{0x7788,0x0000,0x02}, // MC3_PXDEF2_R2_POS4 : +{0x778A,0x0000,0x02}, // MC3_PYDEF2_R2_POS4 : +{0x778C,0xFFD7,0x02}, // MC3_PXDEF3_R2_POS4 : +{0x778E,0x0068,0x02}, // MC3_PYDEF3_R2_POS4 : +{0x7790,0x0000,0x02}, // MC3_PXDEF0_R2_POS5 : +{0x7792,0xFFCC,0x02}, // MC3_PYDEF0_R2_POS5 : +{0x7794,0x0000,0x02}, // MC3_PXDEF1_R2_POS5 : +{0x7796,0x0000,0x02}, // MC3_PYDEF1_R2_POS5 : +{0x7798,0x0000,0x02}, // MC3_PXDEF2_R2_POS5 : +{0x779A,0x0000,0x02}, // MC3_PYDEF2_R2_POS5 : +{0x779C,0xFFD7,0x02}, // MC3_PXDEF3_R2_POS5 : +{0x779E,0x0068,0x02}, // MC3_PYDEF3_R2_POS5 : +}; + +static const isx012_regset_t ISX012_Halfrelease_Mode[] = +{ +{0x0082,0x01,0x01}, // MONI_REFRESH +{0x00B1,0x01,0x01}, //AF_RESTART_F : +{0x00B2,0x03,0x01}, //AFMODE_MONI : AF OFF +{0x00B3,0x00,0x01}, //AFMODE_HREL : +//{0xFFFF,0x42,0x01}, //$wait, 66 +{0x0081,0x01,0x01}, //MODESEL +}; + +static const isx012_regset_t ISX012_Barcode_SAF[] = +{ +{0x0082,0x01,0x01}, // MONI_REFRESH +{0x00B1,0x01,0x01}, //AF_RESTART_F : +//{0xFFFF,0x21,0x01}, //$wait, 33 +{0x00B2,0x00,0x01}, //AFMODE_MONI : +}; + +static const isx012_regset_t ISX012_Lowlux_night_Halfrelease_Mode[] = +{ +{0x660E,0x04,0x01}, // AF_HBPF_PEAK_OPD_TH_MIN +{0x6610,0x04,0x01}, // AF_HBPF_PEAK_OPD_TH_MAX +{0x664A,0x01,0x01}, // AF_DROPN_ON_PEAK_DETECT : +{0x6640,0x01,0x01}, // AF_DROPN_ON_PEAK_DETECT_SECOND : +{0x0289,0x21,0x01}, //AWB_SN8 +{0x6674,0x01,0x01}, // AF_MONICHG_MOVE_F +{0x0082,0x01,0x01}, // MONI_REFRESH +{0x00B1,0x01,0x01}, //AF_RESTART_F +{0x00B3,0x00,0x01}, //AFMODE_HREL : +//{0xFFFF,0x42,0x01}, //$wait, 66 +{0x0081,0x01,0x01}, //MODESEL +}; + +static const isx012_regset_t ISX012_AF_Cancel_Macro_ON[] = +{ +{0x6674,0x00,0x01}, // AF_MONICHG_MOVE_F +{0x0082,0x01,0x01}, // MONI_REFRESH +{0x00B2,0x02,0x01}, //AFMODE_MONI : Manual AF mode +{0x0081,0x00,0x01}, //MODESEL : Monitoring mode +{0x6648,0x02BC,0x02}, //AF_MANUAL_POS : MANUA AF search start position +{0x00B1,0x01,0x01}, //AF_RESTART_F +}; + +static const isx012_regset_t ISX012_AF_Cancel_Macro_OFF[] = +{ +{0x6674,0x00,0x01}, // AF_MONICHG_MOVE_F +{0x0082,0x01,0x01}, // MONI_REFRESH +{0x00B2,0x02,0x01}, //AFMODE_MONI : Manual AF mode +{0x0081,0x00,0x01}, //MODESEL : Monitoring mode +{0x6648,0x00C8,0x02}, //AF_MANUAL_POS : MANUA AF search start position +{0x00B1,0x01,0x01}, //AF_RESTART_F +}; + +static const isx012_regset_t ISX012_AF_ReStart[] = +{ +{0x00B1,0x01,0x01}, //AF_RESTART_F +{0x0082,0x01,0x01}, // MONI_REFRESH +}; + +static const isx012_regset_t ISX012_AF_Macro_OFF[] = +{ +{0x0081,0x00,0x01}, //MODESEL : Monitoring mode +{0x6648,0x00C8,0x02}, //AF_MANUAL_POS : MANUA AF search start position +{0x66DC,0x02BC,0x02}, //AF_JUDGE_MONO_POS_S +{0x665A,0x00C8,0x02}, // AF_LENSPOS_ON_AFNG : +{0x028E,0x00,0x01}, //AF_SEARCH_DIR : NEAR->FAR +{0x00B3,0x00,0x01}, //AFMODE_HREL : Manual AF mode +{0x00B2,0x02,0x01}, //AFMODE_MONI : Manual AF mode +//{0xFFFF,0x21,0x01}, //$wait, 33 +}; + +static const isx012_regset_t ISX012_AF_Macro_ON[] = +{ +{0x0081,0x00,0x01}, //MODESEL : Monitoring mode +{0x6648,0x02BC,0x02}, //AF_MANUAL_POS : MANUA AF search start position +{0x66DC,0x00C8,0x02}, //AF_JUDGE_MONO_POS_S +{0x665A,0x02BC,0x02}, // AF_LENSPOS_ON_AFNG : +{0x028E,0x01,0x01}, //AF_SEARCH_DIR : NEAR->FAR +{0x00B3,0x00,0x01}, //AFMODE_HREL : Manual AF mode +{0x00B2,0x02,0x01}, //AFMODE_MONI : Manual AF mode +//{0xFFFF,0x21,0x01}, //$wait, 33 +}; + +static const isx012_regset_t ISX012_AF_SAF[] = +{ +{0x0082,0x01,0x01}, // MONI_REFRESH +{0x00B1,0x01,0x01}, //AF_RESTART_F : +{0x00B2,0x03,0x01}, //AFMODE_MONI : AF OFF +{0x00B3,0x00,0x01}, //AFMODE_HREL : +//{0xFFFF,0x42,0x01}, //$wait, 66 +{0x0081,0x01,0x01}, //MODESEL +}; + +static const isx012_regset_t ISX012_AF_SAF_OFF[] = +{ +{0x6674,0x00,0x01}, // AF_MONICHG_MOVE_F +{0x0082,0x01,0x01}, // MONI_REFRESH +//{0xFFFF,0x42,0x01}, //$wait, 66 +{0x00B2,0x03,0x01}, //AFMODE_MONI : AF OFF +{0x00B3,0x03,0x01}, //AFMODE_HREL : AF OFF +}; + +static const isx012_regset_t ISX012_AF_TouchSAF_OFF[] = +{ +{0x6674,0x00,0x01}, // AF_MONICHG_MOVE_F +{0x0082,0x01,0x01}, // MONI_REFRESH +//{0xFFFF,0x42,0x01}, //$wait, 66 +{0x00B2,0x03,0x01}, //AFMODE_MONI : AF OFF +{0x00B3,0x03,0x01}, //AFMODE_HREL : AF OFF +{0x0081,0x00,0x01}, //MODESEL +}; + +static const isx012_regset_t ISX012_Camcorder_SAF_Start[] = +{ +{0x0082,0x01,0x01}, // MONI_REFRESH +{0x00B1,0x01,0x01}, /* AF_RESTART_F */ +//{0xFFFF,0x21,0x01}, /* $wait, 33 */ +{0x00B2,0x00,0x01}, /* AFMODE_MONI */ +}; + +static const isx012_regset_t ISX012_Camcorder_CAF_Start[] = +{ +{0x00B2,0x01,0x01}, /* AFMODE_MONI */ +}; + +static const isx012_regset_t ISX012_AF_Window_Reset[] = +{ +//AF opd window setting +{0x6A30,0x044E,0x02}, // AF_OPD0_HDELAY : +{0x6A32,0x02E5,0x02}, // AF_OPD0_VDELAY : +{0x6A34,0x01D8,0x02}, // AF_OPD0_HVALID : +{0x6A36,0x01D8,0x02}, // AF_OPD0_VVALID : +{0x6A38,0x0412,0x02}, // AF_OPD1_HDELAY : +{0x6A3A,0x02A9,0x02}, // AF_OPD1_VDELAY : +{0x6A3C,0x0251,0x02}, // AF_OPD1_HVALID : +{0x6A3E,0x0251,0x02}, // AF_OPD1_VVALID : +{0x6A40,0x04B4,0x02}, // AF_OPD2_HDELAY : +{0x6A42,0x0114,0x02}, // AF_OPD2_VDELAY : +{0x6A44,0x0118,0x02}, // AF_OPD2_HVALID : +{0x6A46,0x0118,0x02}, // AF_OPD2_VVALID : +{0x6A48,0x0469,0x02}, // AF_OPD3_HDELAY : +{0x6A4A,0x00C9,0x02}, // AF_OPD3_VDELAY : +{0x6A4C,0x01AE,0x02}, // AF_OPD3_HVALID : +{0x6A4E,0x01AE,0x02}, // AF_OPD3_VVALID : +{0x6A50,0x04C6,0x02}, // AF_OPD4_HDELAY : +{0x6A52,0x035D,0x02}, // AF_OPD4_VDELAY : +{0x6A54,0x00E6,0x02}, // AF_OPD4_HVALID : +{0x6A56,0x00E6,0x02}, // AF_OPD4_VVALID : +{0x6A58,0x048A,0x02}, // AF_OPD5_HDELAY : +{0x6A5A,0x0321,0x02}, // AF_OPD5_VDELAY : +{0x6A5C,0x015F,0x02}, // AF_OPD5_HVALID : +{0x6A5E,0x015F,0x02}, // AF_OPD5_VVALID : +{0x6A60,0x04B4,0x02}, // AF_OPD6_HDELAY : +{0x6A62,0x0579,0x02}, // AF_OPD6_VDELAY : +{0x6A64,0x0118,0x02}, // AF_OPD6_HVALID : +{0x6A66,0x0118,0x02}, // AF_OPD6_VVALID : +{0x6A68,0x0469,0x02}, // AF_OPD7_HDELAY : +{0x6A6A,0x052C,0x02}, // AF_OPD7_VDELAY : +{0x6A6C,0x01AE,0x02}, // AF_OPD7_HVALID : +{0x6A6E,0x01AE,0x02}, // AF_OPD7_VVALID : +{0x6A70,0x021D,0x02}, // AF_OPD8_HDELAY : +{0x6A72,0x02F5,0x02}, // AF_OPD8_VDELAY : +{0x6A74,0x01AE,0x02}, // AF_OPD8_HVALID : +{0x6A76,0x01AE,0x02}, // AF_OPD8_VVALID : +{0x6A78,0x06A4,0x02}, // AF_OPD9_HDELAY : +{0x6A7A,0x02F5,0x02}, // AF_OPD9_VDELAY : +{0x6A7C,0x01AE,0x02}, // AF_OPD9_HVALID : +{0x6A7E,0x01AE,0x02}, // AF_OPD9_VVALID : +{0x6A80,0x06,0x01}, // AF_OPD1A_WEIGHT : +{0x6A81,0x05,0x01}, // AF_OPD1B_WEIGHT : +{0x6A82,0x02,0x01}, // AF_OPD2A_WEIGHT : +{0x6A83,0x02,0x01}, // AF_OPD2B_WEIGHT : +{0x6A84,0x08,0x01}, // AF_OPD3A_WEIGHT : +{0x6A85,0x07,0x01}, // AF_OPD3B_WEIGHT : +{0x6A86,0x04,0x01}, // AF_OPD4A_WEIGHT : +{0x6A87,0x03,0x01}, // AF_OPD4B_WEIGHT : +{0x6A88,0x01,0x01}, // AF_OPD5A_WEIGHT : +{0x6A89,0x01,0x01}, // AF_OPD5B_WEIGHT : +{0x6646,0x08,0x01}, // AF_OPD_WEIGHT_TH : +}; + +/* Added by Samsung TN */ +static const isx012_regset_t ISX012_AF_Window_Set[] = +{ +{0x6A80,0x00,0x01}, +{0x6A81,0x00,0x01}, +{0x6A82,0x00,0x01}, +{0x6A83,0x00,0x01}, +{0x6A84,0x08,0x01}, +{0x6A85,0x00,0x01}, +{0x6A86,0x00,0x01}, +{0x6A87,0x00,0x01}, +{0x6A88,0x00,0x01}, +{0x6A89,0x00,0x01}, +{0x6646,0x08,0x01}, +}; + +static const isx012_regset_t isx012_Contrast_Minus_2[] = +{ +{0x01C7,0x58,0x01}, //UICONTRAST +}; + +static const isx012_regset_t isx012_Contrast_Minus_1[] = +{ +{0x01C7,0x6C,0x01}, //UICONTRAST +}; + +static const isx012_regset_t isx012_Contrast_Default[] = +{ +{0x01C7,0x80,0x01}, //UICONTRAST +}; + +static const isx012_regset_t isx012_Contrast_Plus_1[] = +{ +{0x01C7,0x94,0x01}, //UICONTRAST +}; + +static const isx012_regset_t isx012_Contrast_Plus_2[] = +{ +{0x01C7,0xA8,0x01}, //UICONTRAST +}; + +static const isx012_regset_t isx012_Effect_Sketch[] = +{ +{0x01C5,0x06,0x01}, /* FMODE */ +{0x6C5F,0x04,0x01}, /* SKETCH_APGAIN */ +}; + +static const isx012_regset_t isx012_Effect_Pastel[] = +{ +{0x01C5,0x05,0x01}, /* FMODE */ +}; + +static const isx012_regset_t isx012_Effect_Black_White[] = +{ +{0x01C5,0x04,0x01}, //FMODE +}; + +static const isx012_regset_t ISX012_Effect_Negative[] = +{ +{0x01C5,0x02,0x01}, //FMODE +}; + +static const isx012_regset_t isx012_Effect_Solar[] = +{ +{0x01C5,0x01,0x01}, /* FMODE */ +}; + +static const isx012_regset_t isx012_Effect_Normal[] = +{ +{0x01C5,0x00,0x01}, //FMODE +}; + +static const isx012_regset_t isx012_Effect_Sepia[] = +{ +{0x01C5,0x03,0x01}, //FMODE +}; + +static const isx012_regset_t isx012_Metering_Center[] = +{ +{0x02AC,0x01,0x01}, //AE_SUB_SN1 +{0x02B6,0x01,0x01}, //AE_SUB_SN11 +}; + +static const isx012_regset_t isx012_Metering_Matrix[] = +{ +{0x02AC,0x00,0x01}, //AE_SUB_SN1 +}; + +static const isx012_regset_t isx012_Metering_Spot[] = +{ +{0x02AC,0x02,0x01}, //AE_SUB_SN1 +{0x02B6,0x02,0x01}, //AE_SUB_SN11 +}; + +static const isx012_regset_t ISX012_ExpSetting_Default[] = +{ +{0x0180,0x00,0x01}, //EVSEL +}; + +static const isx012_regset_t ISX012_ExpSetting_M1Step[] = +{ +{0x0180,0xFF,0x01}, //EVSEL +}; + +static const isx012_regset_t ISX012_ExpSetting_M2Step[] = +{ +{0x0180,0xFE,0x01}, //EVSEL +}; + +static const isx012_regset_t ISX012_ExpSetting_M3Step[] = +{ +{0x0180,0xFD,0x01}, //EVSEL +}; + +static const isx012_regset_t ISX012_ExpSetting_M4Step[] = +{ +{0x0180,0xFC,0x01}, //EVSEL +}; + +static const isx012_regset_t ISX012_ExpSetting_P1Step[] = +{ +{0x0180,0x01,0x01}, //EVSEL +}; + +static const isx012_regset_t ISX012_ExpSetting_P2Step[] = +{ +{0x0180,0x02,0x01}, //EVSEL +}; + +static const isx012_regset_t ISX012_ExpSetting_P3Step[] = +{ +{0x0180,0x03,0x01}, //EVSEL +}; + +static const isx012_regset_t ISX012_ExpSetting_P4Step[] = +{ +{0x0180,0x04,0x01}, //EVSEL +}; + +static const isx012_regset_t isx012_ISO_50[] = +{ +{0x02A8,0x04,0x01}, //ISO_TYPE1 +{0x5E8A,0x00,0x01}, // EVREF_GAIN_A : +{0x5E8B,0x00,0x01}, // EVREF_GAIN_B : +{0x0362,0x57,0x01}, // PICT3_GAMMA_MONI0 : +{0x0365,0x57,0x01}, // PICT3_GAMMA_CAP0 : +}; + +static const isx012_regset_t isx012_ISO_100[] = +{ +{0x02A8,0x07,0x01}, //ISO_TYPE1 +{0x5E8A,0x00,0x01}, // EVREF_GAIN_A : +{0x5E8B,0x00,0x01}, // EVREF_GAIN_B : +{0x0362,0x57,0x01}, // PICT3_GAMMA_MONI0 : +{0x0365,0x57,0x01}, // PICT3_GAMMA_CAP0 : +}; + +static const isx012_regset_t isx012_ISO_200[] = +{ +{0x02A8,0x0A,0x01}, //ISO_TYPE1 +{0x5E8A,0x00,0x01}, // EVREF_GAIN_A : +{0x5E8B,0x00,0x01}, // EVREF_GAIN_B : +{0x0362,0x57,0x01}, // PICT3_GAMMA_MONI0 : +{0x0365,0x57,0x01}, // PICT3_GAMMA_CAP0 : +}; + +static const isx012_regset_t isx012_ISO_400[] = +{ +{0x02A8,0x0D,0x01}, //ISO_TYPE1 +{0x5E8A,0x00,0x01}, // EVREF_GAIN_A : +{0x5E8B,0x00,0x01}, // EVREF_GAIN_B : +{0x0362,0x57,0x01}, // PICT3_GAMMA_MONI0 : +{0x0365,0x57,0x01}, // PICT3_GAMMA_CAP0 : +}; + +#if 0 +static const isx012_regset_t ISX012_ISO_800[] = +{ +{0x02A8,0x10,0x01}, //ISO_TYPE1 +{0x5E8A,0x00,0x01}, // EVREF_GAIN_A : +{0x5E8B,0x00,0x01}, // EVREF_GAIN_B : +{0x0362,0x57,0x01}, // PICT3_GAMMA_MONI0 : +{0x0365,0x57,0x01}, // PICT3_GAMMA_CAP0 : +}; +#endif + +static const isx012_regset_t isx012_ISO_Auto[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 +{0x5E8A,0x02,0x01}, // EVREF_GAIN_A : +{0x5E8B,0x02,0x01}, // EVREF_GAIN_B : +{0x0362,0x55,0x01}, // PICT3_GAMMA_MONI0 : +{0x0365,0x55,0x01}, // PICT3_GAMMA_CAP0 : +}; + +static const isx012_regset_t ISX012_Capture_SizeSetting[] = +{ +{0x0092,0x0A20,0x02}, //HSIZE_CAP : 2592 +{0x0098,0x0798,0x02}, //VSIZE_CAP : 1944 +}; + +static const isx012_regset_t ISX012_Capture_Mode[] = +{ +{0x008A,0x00,0x01}, //OUTFMT_CAP +{0x0084,0x00,0x01}, //SENSMODE_CAP +{0x0087,0x03,0x01}, //FPSTYPE_CAP +{0x0012,0xFF,0x01}, //INTCLR0 +{0x0081,0x02,0x01}, //MODESEL +{0x0082,0x01,0x01}, //MONI_REFRESH +}; + +static const isx012_regset_t ISX012_Lowlux_Night_Capture_Mode[] = +{ +{0x03A0,0xA0,0x01}, //UISATURATION_TYPE3 : +{0x039D,0xF4,0x01}, //UIHUE_TYPE3 : +{0x982A,0xFFD8,0x02}, // CS_CBLLEV_A : +{0x9830,0xFFD8,0x02}, // CS_CRLLEV_A : +{0x9805,0x06,0x01}, // CS_SLP_C_A : +{0x008A,0x00,0x01}, //OUTFMT_CAP +{0x0084,0x00,0x01}, //SENSMODE_CAP +{0x0087,0x03,0x01}, //FPSTYPE_CAP +{0x0012,0xFF,0x01}, //INTCLR0 +{0x0081,0x02,0x01}, //MODESEL +{0x0082,0x01,0x01}, //MONI_REFRESH +}; + +static const isx012_regset_t isx012_Saturation_Default[] = +{ +{0x039E,0x80,0x01}, //UISATURATION_TYPE1 +}; + +static const isx012_regset_t isx012_Saturation_Minus_1[] = +{ +{0x039E,0x62,0x01}, //UISATURATION_TYPE1 +}; + +static const isx012_regset_t isx012_Saturation_Minus_2[] = +{ +{0x039E,0x44,0x01}, //UISATURATION_TYPE1 +}; + +static const isx012_regset_t isx012_Saturation_Plus_1[] = +{ +{0x039E,0x9E,0x01}, //UISATURATION_TYPE1 +}; + +static const isx012_regset_t isx012_Saturation_Plus_2[] = +{ +{0x039E,0xBC,0x01}, //UISATURATION_TYPE1 +}; + +static const isx012_regset_t isx012_Scene_Default[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x00,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Landscape[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x039F,0x9E,0x01}, //UISATURATION_TYPE2 : +{0x03A3,0x2C,0x01}, //UISHARPNESS_POS_TYPE3 : +1 +{0x03A6,0x2C,0x01}, //UISHARPNESS_NEG_TYPE3 : +1 +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x01,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Sports[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x02,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Party_Indoor[] = +{ +{0x02A8,0x0A,0x01}, //ISO_TYPE1 : ISO200 +{0x039F,0x9E,0x01}, //UISATURATION_TYPE2 : +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x04,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x00,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Beach_Snow[] = +{ +{0x02A8,0x04,0x01}, //ISO_TYPE1 : ISO50 +{0x039F,0x9E,0x01}, //UISATURATION_TYPE2 : +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x04,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Sunset[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x0287,0x25,0x01}, //AWB_SN6 : daylight +{0x0394,0x00,0x01}, //PICT1_SN6 : +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x05,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Duskdawn[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x0287,0x27,0x01}, //AWB_SN6 : CWF +{0x0394,0x00,0x01}, //PICT1_SN6 : +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x05,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Candle_Light[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x0287,0x25,0x01}, //AWB_SN6 : daylight +{0x0394,0x00,0x01}, //PICT1_SN6 : +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x05,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Fall_Color[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x039F,0xBC,0x01}, //UISATURATION_TYPE2 : +{0x0287,0x20,0x01}, //AWB_SN6 : AWB +{0x0394,0x04,0x01}, //PICT1_SN6 : +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x05,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Portrait[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x50,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x00,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Nightshot[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x00,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x07,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Fireworks[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : AUTO +{0x5E06,0x04,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x00,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x08,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Text[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x03A3,0x38,0x01}, //UISHARPNESS_POS_TYPE3 : +2 +{0x03A6,0x38,0x01}, //UISHARPNESS_NEG_TYPE3 : +2 +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0xA0,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x00,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Scene_Backlight[] = +{ +{0x02A8,0x00,0x01}, //ISO_TYPE1 : Auto +{0x5E06,0x02,0x01}, //SHTCTRLMAG3 +{0x038F,0x00,0x01}, //PICT1_SN1 : +{0x6742,0x0012,0x02}, // AF_SEARCH_OFFSET_FAR : +{0x6744,0x0006,0x02}, // AF_SEARCH_OFFSET_NEAR : +{0x500B,0x01,0x01}, // FAST_SHT_MODE_SEL +{0x0280,0x00,0x01}, //SCENE_SELECT +}; + +static const isx012_regset_t isx012_Sharpness_Default[] = +{ +{0x00A1,0x20,0x01}, //UISHARPNESS_POS_TYPE1 +{0x00A4,0x20,0x01}, //UISHARPNESS_NEG_TYPE1 +}; + +static const isx012_regset_t isx012_Sharpness_Minus_1[] = +{ +{0x00A1,0x14,0x01}, //UISHARPNESS_POS_TYPE1 +{0x00A4,0x14,0x01}, //UISHARPNESS_NEG_TYPE1 +}; + +static const isx012_regset_t isx012_Sharpness_Minus_2[] = +{ +{0x00A1,0x08,0x01}, //UISHARPNESS_POS_TYPE1 +{0x00A4,0x08,0x01}, //UISHARPNESS_NEG_TYPE1 +}; + +static const isx012_regset_t isx012_Sharpness_Plus_1[] = +{ +{0x00A1,0x2C,0x01}, //UISHARPNESS_POS_TYPE1 +{0x00A4,0x2C,0x01}, //UISHARPNESS_NEG_TYPE1 +}; + +static const isx012_regset_t isx012_Sharpness_Plus_2[] = +{ +{0x00A1,0x38,0x01}, //UISHARPNESS_POS_TYPE1 +{0x00A4,0x38,0x01}, //UISHARPNESS_NEG_TYPE1 +}; + +static const isx012_regset_t isx012_WB_Auto[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_WB_Cloudy[] = +{ +{0x0282,0x26,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_WB_Sunny[] = +{ +{0x0282,0x25,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_WB_Fluorescent[] = +{ +{0x0282,0x27,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_WB_Tungsten[] = +{ +{0x0282,0x28,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t ISX012_Image_Quality_Standard[] = +{ +{0x00F6,0x00,0x01}, //JPG_QLTY +{0x0082,0x01,0x01}, //MONI_REFRESH +}; + +static const isx012_regset_t ISX012_Image_Quality_Fine[] = +{ +{0x00F6,0x01,0x01}, //JPG_QLTY +{0x0082,0x01,0x01}, //MONI_REFRESH +}; + +static const isx012_regset_t ISX012_Image_Quality_Super_Fine[] = +{ +{0x00F6,0x02,0x01}, //JPG_QLTY +{0x0082,0x01,0x01}, //MONI_REFRESH +}; + +static const isx012_regset_t ISX012_Image_Quality_Table[] = +{ +{0x00F7,0x52,0x01}, // INIT_QLTY0 : Standard 82 +{0x00F8,0x59,0x01}, // INIT_QLTY1 : Fine 89 +{0x00F9,0x5F,0x01}, // INIT_QLTY2 : SuperFine 95 +}; + +static const isx012_regset_t ISX012_Sensor_Off_VCM[] = +{ +{0x6674,0x00,0x01}, // AF_MONICHG_MOVE_F +{0x00B2,0x02,0x01}, //AFMODE_MONI : Manual AF mode +{0x0081,0x00,0x01}, //MODESEL : Monitoring mode +{0x6600,0x0000,0x02}, // AF_SEARCH_AREA_LOW +{0x6666,0x0000,0x02}, // AF_AREA_LOW_TYPE1 +{0x6648,0x00C8,0x02}, // AF_MANUAL_POS : +{0x00B1,0x01,0x01}, //AF_RESTART_F +{0xFFFF,0x64,0x01}, // $wait, 100 +{0x6648,0x0019,0x02}, // AF_MANUAL_POS : +{0x00B1,0x01,0x01}, // AF_RESTART_F +{0xFFFF,0x64,0x01}, // $wait, 100 +}; + +static const isx012_regset_t isx012_1280_Preview_E[] = +{ +{0x0090,0x0500,0x02}, //HSIZE_MONI : 1280 +{0x0096,0x02D0,0x02}, //VSIZE_MONI : 720 +}; + +static const isx012_regset_t isx012_1024_768_Preview[] = { +{0x0090,0x0400,0x02}, /* HSIZE_MONI : 1024 */ +{0x0096,0x0300,0x02}, /* VSIZE_MONI : 768 */ +}; + +static const isx012_regset_t isx012_800_Preview[] = +{ +{0x0090,0x0320,0x02}, //HSIZE_MONI : 800 +{0x0096,0x01E0,0x02}, //VSIZE_MONI : 480 +}; + +static const isx012_regset_t isx012_720_Preview[] = +{ +{0x0090,0x02D0,0x02}, //HSIZE_MONI : 720 +{0x0096,0x01E0,0x02}, //VSIZE_MONI : 480 +}; + +static const isx012_regset_t isx012_640_Preview[] = +{ +{0x0090,0x0280,0x02}, //HSIZE_MONI : 640 +{0x0096,0x01E0,0x02}, //VSIZE_MONI : 480 +}; + +#if defined(CONFIG_MACH_P4NOTELTE_KOR_SKT) \ + || defined(CONFIG_MACH_P4NOTELTE_KOR_KT) \ + || defined(CONFIG_MACH_P4NOTELTE_KOR_LGT) /*For 4G VT call in Domestic*/ +static const isx012_regset_t isx012_480_Preview[] = { +{0x0090, 0x01E0, 0x02}, /* HSIZE_MONI : 480 */ +{0x0096, 0x0280, 0x02}, /* VSIZE_MONI : 640 */ +}; +#endif + +static const isx012_regset_t isx012_320_Preview[] = +{ +{0x0090,0x0140,0x02}, //HSIZE_MONI : 320 +{0x0096,0x00F0,0x02}, //VSIZE_MONI :240 + +}; +static const isx012_regset_t isx012_176_Preview[] = +{ +{0x0090,0x00B0,0x02}, //HSIZE_MONI : 176 +{0x0096,0x0090,0x02}, //VSIZE_MONI : 144 +}; + + +static const isx012_regset_t isx012_5M_Capture[] = { +{0x0092,0x0A00,0x02}, /* HSIZE_CAP: 2560 */ +{0x0098,0x0780,0x02}, /* VSIZE_CAP: 1920 */ +}; + +static const isx012_regset_t isx012_4M_WIDE_Capture[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_3M_Capture[] = { +{0x0092,0x0800,0x02}, /* HSIZE_CAP : 2048 */ +{0x0098,0x0600,0x02}, /* VSIZE_CAP : 1536 */ +}; + +static const isx012_regset_t isx012_2_4M_WIDE_Capture[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_1_5M_WIDE_Capture[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_960_720_Capture[] = { +{0x0092,0x03C0,0x02}, /* HSIZE_CAP : 960 */ +{0x0098,0x02D0,0x02}, /* VSIZE_CAP : 720 */ +}; + +static const isx012_regset_t isx012_1M_Capture[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_4K_WIDE_Capture[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_VGA_Capture[] = { +{0x0092,0x0280,0x02}, /* HSIZE_CAP : 640 */ +{0x0098,0x01E0,0x02}, /* VSIZE_CAP : 480 */ +}; + +static const isx012_regset_t isx012_QVGA_Capture[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_DTP_init[] = +{ +{0x01BC,0x50,0x01},//Shading Gain off +{0x5E00,0x07,0x01},//Flicker off + +// Pre-WB +{0x6804,0x1000,0x02}, // NORMR +{0x6806,0x1000,0x02}, // NORMB +{0x6808,0x0100,0x02}, // AWBPRER +{0x680A,0x0100,0x02}, // AWBPREB +{0x6818,0x00,0x01}, //REFERENCE SENSITIVITY RATIO OF SENSOR (R/G) +{0x6819,0x00,0x01}, //REFERENCE SENSITIVITY RATIO OF SENSOR (B/G) + +{0x036B,0x11,0x01}, +{0x0377,0x11,0x01}, +{0x0383,0x11,0x01}, + +// +{0x6C44,0x00,0x01}, // G_CTRL_SEL : + +//CNR +{0x6C4A,0x07,0x01}, // MAIN_CONFIG5 : + +//ITP NR +{0x5005,0xBB,0x01}, // DM_SW1 : +{0x5006,0x03,0x01}, // DM_SW2 : +{0x0362,0x00,0x01}, + +{0x6C0B,0x04,0x01}, // PICT_FLAG : +{0x9800,0x80,0x01}, // LMT_WEIGHT_A : +{0x9801,0x80,0x01}, // LMT_WEIGHT_B : + +{0x6C46,0x00,0x01}, // MAIN_CONFIG1 : +{0x6C47,0x00,0x01}, // MAIN_CONFIG2 : +{0x6C48,0x00,0x01}, // MAIN_CONFIG3 : +{0x6C49,0x00,0x01}, // MAIN_CONFIG4 : +{0x6C4A,0x00,0x01}, // MAIN_CONFIG5 : + + +{0x5001,0x04,0x01}, // MUTECNT : +{0x5002,0x00,0x01}, // WDT_EN : +{0x5003,0x07,0x01}, // Z1_SEL1 : +{0x5004,0x00,0x01}, // Z1_SEL2 : +{0x5005,0x00,0x01}, // DM_SW1 : +{0x5006,0x00,0x01}, // DM_SW2 : +{0x5007,0x00,0x01}, // CLMP_CTRL : +{0x5009,0x00,0x01}, // CPUSLEEP_EN : +{0x500A,0x00,0x01}, // FAST_MODECHG_EN : +{0x500B,0x00,0x01}, // FAST_SHT_MODE_SEL : +{0x500C,0x00FA,0x02}, // FAST_SHT_LIMIT_COUNT : +{0x500E,0x06D0,0x02}, // SYSINT3_VDLY_1_1 : +{0x5010,0x02F8,0x02}, // SYSINT3_VDLY_1_2 : +{0x5012,0x0118,0x02}, // SYSINT3_VDLY_1_4 : +{0x5014,0x0028,0x02}, // SYSINT3_VDLY_1_8 : +{0x5016,0x0370,0x02}, // SYSINT3_VDLY_1_1_HD : +{0x5018,0x0208,0x02}, // SYSINT3_VDLY_1_2_HD : +{0x501A,0x00,0x01}, // SENS_REVERSE_CTRL : +{0x501B,0x19,0x01}, // EEP_ADDRESS : +{0x501C,0x5180,0x02}, // SRCCK : +{0x501E,0x0001,0x02}, + +{0x6E86,0x0000,0x02}, // IBYHUE1_POS1 : +{0x6E88,0xFFF5,0x02}, // IRYHUE1_POS1 : +{0x6E8A,0xFFF8,0x02}, // IBYHUE2_POS1 : +{0x6E8C,0xFFF5,0x02}, // IRYHUE2_POS1 : +{0x6E8E,0xFFF8,0x02}, // IBYHUE3_POS1 : +{0x6E90,0xFFEE,0x02}, // IRYHUE3_POS1 : +{0x6E92,0x0000,0x02}, // IBYHUE4_POS1 : +{0x6E94,0xFFEC,0x02}, // IRYHUE4_POS1 : +{0x6F26,0x4E,0x01}, // IRYGAIN1_POS1 : +{0x6F27,0x50,0x01}, // IBYGAIN1_POS1 : +{0x6F28,0x4E,0x01}, // IRYGAIN2_POS1 : +{0x6F29,0x5A,0x01}, // IBYGAIN2_POS1 : +{0x6F2A,0x50,0x01}, // IRYGAIN3_POS1 : +{0x6F2B,0x5A,0x01}, // IBYGAIN3_POS1 : +{0x6F2C,0x50,0x01}, // IRYGAIN4_POS1 : +{0x6F2D,0x50,0x01}, // IBYGAIN4_POS1 : + +//ae +{0x5E12,0x0000,0x02}, +{0x5E14,0x0000,0x02}, +{0x0294,0x03,0x01}, + +//AWB +{0x625F,0x35,0x01},//CAT_AWB_1 +{0x0282,0x05,0x01},//AWB_SN1 +//S, 5000, 3F, 8, // CPUEXT : + + +{0x5021,0x00,0x01}, // PG_GAIN_SEL : +{0x5022,0x01,0x01}, // PG_WIDTH_SEL : +{0x5023,0x04,0x01}, // PG_MODE_SEL : +{0x5024,0x0000,0x02}, // PG_LEVEL_SEL : +{0x5026,0x00,0x01}, // PG_DATEN_OFF_SEL : +{0x5020,0x01,0x01}, // PGSEL : + +}; + +static const isx012_regset_t isx012_DTP_stop[] = +{ +{0x01BC,0x57,0x01}, // Shading Gain off +{0x5E00,0x00,0x01}, // Flicker off +{0x6804,0x11F0,0x02}, // NORMR +{0x6806,0x106F,0x02}, // NORMB +{0x6808,0x014C,0x02}, // AWBPRER +{0x680A,0x021E,0x02}, // AWBPREB +{0x6818,0x00,0x01}, // REFERENCE SENSITIVITY RATIO OF SENSOR (R/G) +{0x6819,0x00,0x01}, // REFERENCE SENSITIVITY RATIO OF SENSOR (B/G) +{0x036B,0x80,0x01}, // +{0x0377,0x80,0x01}, // +{0x0383,0x80,0x01}, // +{0x6C44,0x13,0x01}, // G_CTRL_SEL : +{0x6C4A,0x07,0x01}, // MAIN_CONFIG5 : +{0x5005,0xBB,0x01}, // DM_SW1 : +{0x5006,0x03,0x01}, // DM_SW2 : +{0x0362,0x55,0x01}, // +{0x6C0B,0x00,0x01}, // PICT_FLAG : +{0x9800,0x40,0x01}, // LMT_WEIGHT_A : +{0x9801,0x80,0x01}, // LMT_WEIGHT_B : +{0x6C46,0x1C,0x01}, // MAIN_CONFIG1 : +{0x6C47,0x0F,0x01}, // MAIN_CONFIG2 : +{0x6C48,0x03,0x01}, // MAIN_CONFIG3 : +{0x6C49,0xF5,0x01}, // MAIN_CONFIG4 : +{0x6C4A,0x07,0x01}, // MAIN_CONFIG5 : +{0x5001,0x04,0x01}, // MUTECNT : +{0x5002,0x01,0x01}, // WDT_EN : +{0x5003,0x04,0x01}, // Z1_SEL1 : +{0x5004,0x00,0x01}, // Z1_SEL2 : +{0x5005,0xBB,0x01}, // DM_SW1 : +{0x5006,0x03,0x01}, // DM_SW2 : +{0x5007,0x01,0x01}, // CLMP_CTRL : +{0x5009,0x00,0x01}, // CPUSLEEP_EN : +{0x500A,0x00,0x01}, // FAST_MODECHG_EN : +{0x500B,0x00,0x01}, // FAST_SHT_MODE_SEL : +{0x500C,0x00FA,0x02}, // FAST_SHT_LIMIT_COUNT : +{0x500E,0x06D0,0x02}, // SYSINT3_VDLY_1_1 : +{0x5010,0x02F8,0x02}, // SYSINT3_VDLY_1_2 : +{0x5012,0x0118,0x02}, // SYSINT3_VDLY_1_4 : +{0x5014,0x0028,0x02}, // SYSINT3_VDLY_1_8 : +{0x5016,0x0370,0x02}, // SYSINT3_VDLY_1_1_HD : +{0x5018,0x0208,0x02}, // SYSINT3_VDLY_1_2_HD : +{0x501A,0x00,0x01}, // SENS_REVERSE_CTRL : +{0x501B,0x50,0x01}, // EEP_ADDRESS : +{0x501C,0x5180,0x02}, // SRCCK : +{0x501E,0x0001,0x02}, +{0x6E86,0x0000,0x02}, // IBYHUE1_POS1 : +{0x6E88,0xFFF5,0x02}, // IRYHUE1_POS1 : +{0x6E8A,0xFFF8,0x02}, // IBYHUE2_POS1 : +{0x6E8C,0xFFF5,0x02}, // IRYHUE2_POS1 : +{0x6E8E,0xFFF8,0x02}, // IBYHUE3_POS1 : +{0x6E90,0xFFEE,0x02}, // IRYHUE3_POS1 : +{0x6E92,0x0000,0x02}, // IBYHUE4_POS1 : +{0x6E94,0xFFEC,0x02}, // IRYHUE4_POS1 : +{0x6F26,0x4E,0x01}, // IRYGAIN1_POS1 : +{0x6F27,0x50,0x01}, // IBYGAIN1_POS1 : +{0x6F28,0x4E,0x01}, // IRYGAIN2_POS1 : +{0x6F29,0x5A,0x01}, // IBYGAIN2_POS1 : +{0x6F2A,0x50,0x01}, // IRYGAIN3_POS1 : +{0x6F2B,0x5A,0x01}, // IBYGAIN3_POS1 : +{0x6F2C,0x50,0x01}, // IRYGAIN4_POS1 : +{0x6F2D,0x50,0x01}, // IBYGAIN4_POS1 : +{0x5E12,0x014A,0x02}, // +{0x5E14,0x000D,0x02}, // +{0x0294,0x00,0x01}, // +{0x625F,0x35,0x01}, // CAT_AWB_1 +{0x0282,0x20,0x01}, // AWB_SN1 +{0x5021,0x00,0x01}, // PG_GAIN_SEL : +{0x5022,0x00,0x01}, // PG_WIDTH_SEL : +{0x5023,0x00,0x01}, // PG_MODE_SEL : +{0x5024,0x0000,0x02}, // PG_LEVEL_SEL : +{0x5026,0x00,0x01}, // PG_DATEN_OFF_SEL : +{0x5020,0x00,0x01}, // PGSEL : + +}; + +static const isx012_regset_t isx012_Preview_Return[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 + +}; + +static const isx012_regset_t isx012_Capture_Start[] = +{ + {0x008A,0x00,0x01}, //OUTFMT_CAP + {0x0084,0x00,0x01}, //SENSMODE_CAP + {0x0087,0x03,0x01}, //FPSTYPE_CAP + {0x0012,0x06,0x01}, //INTCLR0 + {0x0081,0x02,0x01}, //MODESEL + {0x0082,0x01,0x01}, //MONI_REFRESH +}; +#if 0 +static const isx012_regset_t isx012_Preview_Return[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; +#endif + +static const isx012_regset_t isx012_fps_auto[] = +{ +{0x0308,0x11,0x01}, /* AELINE_MONI_SN1_2 */ +{0x018E,0x0012,0x02}, /* VADJ_SENS_1_2 */ +}; + +static const isx012_regset_t isx012_fps_7fix[] = +{ +{0x0308,0x02,0x01}, /* AELINE_MONI_SN1_2 */ +{0x018E,0x0D59,0x02}, /* VADJ_SENS_1_2 */ +}; + +static const isx012_regset_t isx012_fps_15fix[] = +{ +{0x0308,0x02,0x01}, /* AELINE_MONI_SN1_2 */ +{0x018E,0x041C,0x02}, /* VADJ_SENS_1_2 */ +}; + +static const isx012_regset_t isx012_fps_25fix[] = +{ +{0x0308,0x02,0x01}, /* AELINE_MONI_SN1_2 */ +{0x018E,0x00E1,0x02}, /* VADJ_SENS_1_2 */ +}; + +static const isx012_regset_t isx012_fps_30fix[] = +{ +{0x0308,0x02,0x01}, /* AELINE_MONI_SN1_2 */ +{0x018E,0x0012,0x02}, /* VADJ_SENS_1_2 */ +}; + +static const isx012_regset_t isx012_ae_lock[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_ae_unlock[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_awb_lock[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + +static const isx012_regset_t isx012_awb_unlock[] = +{ +{0x0282,0x20,0x01}, //AWB_SN1 +}; + + +static const isx012_regset_t ISX012_Shading_Nocal[] = +{ +{0x01BC,0x50,0x01}, // CXC OFF SHD OFF +{0xEB00,0x8282,0x02}, //valid_code +{0xEB02,0xFE,0x01}, +{0xEB03,0x84,0x01}, +{0xEB04,0x3F,0x01}, +{0xEB05,0x01,0x01}, +{0xEB06,0x50,0x01}, +{0xEB07,0x08,0x01}, +{0xEB08,0x14,0x01}, +{0xEB09,0xFF,0x01}, +{0xEB0A,0x45,0x01}, +{0xEB0B,0x80,0x01}, +{0xEB0C,0x01,0x01}, +{0xEB0D,0x68,0x01}, +{0xEB0E,0x04,0x01}, +{0xEB0F,0x1A,0x01}, +{0xEB10,0x81,0x01}, +{0xEB11,0x86,0x01}, +{0xEB12,0x3F,0x01}, +{0xEB13,0xE1,0x01}, +{0xEB14,0x4F,0x01}, +{0xEB15,0x00,0x01}, +{0xEB16,0x14,0x01}, +{0xEB17,0x02,0x01}, +{0xEB18,0xC5,0x01}, +{0xEB19,0x7F,0x01}, +{0xEB1A,0x11,0x01}, +{0xEB1B,0x60,0x01}, +{0xEB1C,0x00,0x01}, +{0xEB1D,0x1A,0x01}, +{0xEB1E,0x81,0x01}, +{0xEB1F,0x46,0x01}, +{0xEB20,0xA0,0x01}, +{0xEB21,0x01,0x01}, +{0xEB22,0x48,0x01}, +{0xEB23,0x00,0x01}, +{0xEB24,0x12,0x01}, +{0xEB25,0x81,0x01}, +{0xEB26,0x05,0x01}, +{0xEB27,0x20,0x01}, +{0xEB28,0xF1,0x01}, +{0xEB29,0x4F,0x01}, +{0xEB2A,0x00,0x01}, +{0xEB2B,0x14,0x01}, +{0xEB2C,0x82,0x01}, +{0xEB2D,0x85,0x01}, +{0xEB2E,0x80,0x01}, +{0xEB2F,0x21,0x01}, +{0xEB30,0x60,0x01}, +{0xEB31,0x04,0x01}, +{0xEB32,0x12,0x01}, +{0xEB33,0x81,0x01}, +{0xEB34,0x84,0x01}, +{0xEB35,0xE0,0x01}, +{0xEB36,0x00,0x01}, +{0xEB37,0x28,0x01}, +{0xEB38,0x04,0x01}, +{0xEB39,0x0C,0x01}, +{0xEB3A,0x82,0x01}, +{0xEB3B,0x43,0x01}, +{0xEB3C,0x20,0x01}, +{0xEB3D,0x11,0x01}, +{0xEB3E,0x68,0x01}, +{0xEB3F,0x04,0x01}, +{0xEB40,0x1A,0x01}, +{0xEB41,0x82,0x01}, +{0xEB42,0x83,0x01}, +{0xEB43,0xE0,0x01}, +{0xEB44,0x00,0x01}, +{0xEB45,0x20,0x01}, +{0xEB46,0x00,0x01}, +{0xEB47,0x06,0x01}, +{0xEB48,0xFF,0x01}, +{0xEB49,0x41,0x01}, +{0xEB4A,0x80,0x01}, +{0xEB4B,0x10,0x01}, +{0xEB4C,0x30,0x01}, +{0xEB4D,0x08,0x01}, +{0xEB4E,0x14,0x01}, +{0xEB4F,0x02,0x01}, +{0xEB50,0x45,0x01}, +{0xEB51,0xC0,0x01}, +{0xEB52,0x10,0x01}, +{0xEB53,0x30,0x01}, +{0xEB54,0x04,0x01}, +{0xEB55,0x04,0x01}, +{0xEB56,0x01,0x01}, +{0xEB57,0xC0,0x01}, +{0xEB58,0x3F,0x01}, +{0xEB59,0x10,0x01}, +{0xEB5A,0x10,0x01}, +{0xEB5B,0x04,0x01}, +{0xEB5C,0x0A,0x01}, +{0xEB5D,0x80,0x01}, +{0xEB5E,0x03,0x01}, +{0xEB5F,0xE0,0x01}, +{0xEB60,0x10,0x01}, +{0xEB61,0x28,0x01}, +{0xEB62,0x04,0x01}, +{0xEB63,0x0A,0x01}, +{0xEB64,0x81,0x01}, +{0xEB65,0x01,0x01}, +{0xEB66,0x00,0x01}, +{0xEB67,0x10,0x01}, +{0xEB68,0x00,0x01}, +{0xEB69,0x04,0x01}, +{0xEB6A,0x04,0x01}, +{0xEB6B,0x01,0x01}, +{0xEB6C,0x42,0x01}, +{0xEB6D,0xE0,0x01}, +{0xEB6E,0x10,0x01}, +{0xEB6F,0x38,0x01}, +{0xEB70,0xFC,0x01}, +{0xEB71,0x0D,0x01}, +{0xEB72,0x7F,0x01}, +{0xEB73,0x43,0x01}, +{0xEB74,0x60,0x01}, +{0xEB75,0x00,0x01}, +{0xEB76,0x08,0x01}, +{0xEB77,0x08,0x01}, +{0xEB78,0x02,0x01}, +{0xEB79,0x81,0x01}, +{0xEB7A,0x41,0x01}, +{0xEB7B,0x80,0x01}, +{0xEB7C,0x10,0x01}, +{0xEB7D,0x30,0x01}, +{0xEB7E,0x04,0x01}, +{0xEB7F,0x0C,0x01}, +{0xEB80,0x01,0x01}, +{0xEB81,0x43,0x01}, +{0xEB82,0xC0,0x01}, +{0xEB83,0x20,0x01}, +{0xEB84,0x28,0x01}, +{0xEB85,0x08,0x01}, +{0xEB86,0x06,0x01}, +{0xEB87,0x02,0x01}, +{0xEB88,0xC2,0x01}, +{0xEB89,0xA0,0x01}, +{0xEB8A,0x30,0x01}, +{0xEB8B,0x30,0x01}, +{0xEB8C,0x0C,0x01}, +{0xEB8D,0x12,0x01}, +{0xEB8E,0x83,0x01}, +{0xEB8F,0x84,0x01}, +{0xEB90,0x00,0x01}, +{0xEB91,0x21,0x01}, +{0xEB92,0x40,0x01}, +{0xEB93,0x0C,0x01}, +{0xEB94,0x0C,0x01}, +{0xEB95,0x82,0x01}, +{0xEB96,0x03,0x01}, +{0xEB97,0xC1,0x01}, +{0xEB98,0x40,0x01}, +{0xEB99,0x40,0x01}, +{0xEB9A,0x08,0x01}, +{0xEB9B,0x10,0x01}, +{0xEB9C,0x03,0x01}, +{0xEB9D,0xC4,0x01}, +{0xEB9E,0x00,0x01}, +{0xEB9F,0x21,0x01}, +{0xEBA0,0x38,0x01}, +{0xEBA1,0x08,0x01}, +{0xEBA2,0x0E,0x01}, +{0xEBA3,0x82,0x01}, +{0xEBA4,0xC3,0x01}, +{0xEBA5,0x20,0x01}, +{0xEBA6,0x41,0x01}, +{0xEBA7,0x48,0x01}, +{0xEBA8,0x00,0x01}, +{0xEBA9,0x14,0x01}, +{0xEBAA,0x83,0x01}, +{0xEBAB,0x44,0x01}, +{0xEBAC,0x20,0x01}, +{0xEBAD,0x11,0x01}, +{0xEBAE,0x48,0x01}, +{0xEBAF,0x08,0x01}, +{0xEBB0,0x0E,0x01}, +{0xEBB1,0x82,0x01}, +{0xEBB2,0x83,0x01}, +{0xEBB3,0xE0,0x01}, +{0xEBB4,0x30,0x01}, +{0xEBB5,0x48,0x01}, +{0xEBB6,0x10,0x01}, +{0xEBB7,0x12,0x01}, +{0xEBB8,0x00,0x01}, +{0xEBB9,0xC5,0x01}, +{0xEBBA,0x20,0x01}, +{0xEBBB,0x11,0x01}, +{0xEBBC,0x48,0x01}, +{0xEBBD,0x04,0x01}, +{0xEBBE,0x12,0x01}, +{0xEBBF,0x04,0x01}, +{0xEBC0,0x3B,0x01}, +{0xEBC1,0xC1,0x01}, +{0xEBC2,0x1E,0x01}, +{0xEBC3,0xC8,0x01}, +{0xEBC4,0x0F,0x01}, +{0xEBC5,0xF8,0x01}, +{0xEBC6,0x02,0x01}, +{0xEBC7,0xBB,0x01}, +{0xEBC8,0x60,0x01}, +{0xEBC9,0x0F,0x01}, +{0xEBCA,0xB8,0x01}, +{0xEBCB,0x0F,0x01}, +{0xEBCC,0xEA,0x01}, +{0xEBCD,0x83,0x01}, +{0xEBCE,0x3A,0x01}, +{0xEBCF,0xC1,0x01}, +{0xEBD0,0x4E,0x01}, +{0xEBD1,0xB0,0x01}, +{0xEBD2,0x07,0x01}, +{0xEBD3,0xF2,0x01}, +{0xEBD4,0x03,0x01}, +{0xEBD5,0xBE,0x01}, +{0xEBD6,0xC0,0x01}, +{0xEBD7,0x2E,0x01}, +{0xEBD8,0xD8,0x01}, +{0xEBD9,0x03,0x01}, +{0xEBDA,0xEE,0x01}, +{0xEBDB,0x83,0x01}, +{0xEBDC,0xFA,0x01}, +{0xEBDD,0xA0,0x01}, +{0xEBDE,0x2E,0x01}, +{0xEBDF,0xB0,0x01}, +{0xEBE0,0x0B,0x01}, +{0xEBE1,0xEC,0x01}, +{0xEBE2,0x05,0x01}, +{0xEBE3,0xBD,0x01}, +{0xEBE4,0x60,0x01}, +{0xEBE5,0x2F,0x01}, +{0xEBE6,0xD0,0x01}, +{0xEBE7,0x07,0x01}, +{0xEBE8,0xEC,0x01}, +{0xEBE9,0x02,0x01}, +{0xEBEA,0xBC,0x01}, +{0xEBEB,0x40,0x01}, +{0xEBEC,0x2F,0x01}, +{0xEBED,0xD0,0x01}, +{0xEBEE,0x13,0x01}, +{0xEBEF,0xEE,0x01}, +{0xEBF0,0x84,0x01}, +{0xEBF1,0xBB,0x01}, +{0xEBF2,0x00,0x01}, +{0xEBF3,0x1F,0x01}, +{0xEBF4,0xC8,0x01}, +{0xEBF5,0xFF,0x01}, +{0xEBF6,0xEF,0x01}, +{0xEBF7,0x00,0x01}, +{0xEBF8,0x7D,0x01}, +{0xEBF9,0x60,0x01}, +{0xEBFA,0x2F,0x01}, +{0xEBFB,0xD0,0x01}, +{0xEBFC,0x0B,0x01}, +{0xEBFD,0xF4,0x01}, +{0xEBFE,0x85,0x01}, +{0xEBFF,0x7D,0x01}, +{0xEC00,0x61,0x01}, +{0xEC01,0x0F,0x01}, +{0xEC02,0xC0,0x01}, +{0xEC03,0xFF,0x01}, +{0xEC04,0xF7,0x01}, +{0xEC05,0x7F,0x01}, +{0xEC06,0x3D,0x01}, +{0xEC07,0x40,0x01}, +{0xEC08,0xFF,0x01}, +{0xEC09,0xDF,0x01}, +{0xEC0A,0x07,0x01}, +{0xEC0B,0xFA,0x01}, +{0xEC0C,0x81,0x01}, +{0xEC0D,0x3E,0x01}, +{0xEC0E,0x61,0x01}, +{0xEC0F,0x4F,0x01}, +{0xEC10,0xD8,0x01}, +{0xEC11,0x0B,0x01}, +{0xEC12,0xFC,0x01}, +{0xEC13,0xFE,0x01}, +{0xEC14,0x3D,0x01}, +{0xEC15,0xC0,0x01}, +{0xEC16,0xFF,0x01}, +{0xEC17,0xFF,0x01}, +{0xEC18,0x03,0x01}, +{0xEC19,0xFC,0x01}, +{0xEC1A,0x82,0x01}, +{0xEC1B,0xBE,0x01}, +{0xEC1C,0xA0,0x01}, +{0xEC1D,0x6F,0x01}, +{0xEC1E,0xF8,0x01}, +{0xEC1F,0x1B,0x01}, +{0xEC20,0xFE,0x01}, +{0xEC21,0x83,0x01}, +{0xEC22,0xBF,0x01}, +{0xEC23,0xE0,0x01}, +{0xEC24,0x0F,0x01}, +{0xEC25,0x10,0x01}, +{0xEC26,0x00,0x01}, +{0xEC27,0x00,0x01}, +{0xEC28,0x82,0x01}, +{0xEC29,0xC0,0x01}, +{0xEC2A,0x60,0x01}, +{0xEC2B,0x30,0x01}, +{0xEC2C,0x18,0x01}, +{0xEC2D,0x20,0x01}, +{0xEC2E,0x04,0x01}, +{0xEC2F,0x08,0x01}, +{0xEC30,0x81,0x01}, +{0xEC31,0x21,0x01}, +{0xEC32,0x30,0x01}, +{0xEC33,0x08,0x01}, +{0xEC34,0x08,0x01}, +{0xEC35,0x08,0x01}, +{0xEC36,0x82,0x01}, +{0xEC37,0x01,0x01}, +{0xEC38,0x81,0x01}, +{0xEC39,0x50,0x01}, +{0xEC3A,0x08,0x01}, +{0xEC3B,0x14,0x01}, +{0xEC3C,0x02,0x01}, +{0xEC3D,0x09,0x01}, +{0xEC3E,0x41,0x01}, +{0xEC3F,0x42,0x01}, +{0xEC40,0x70,0x01}, +{0xEC41,0x20,0x01}, +{0xEC42,0x0C,0x01}, +{0xEC43,0x06,0x01}, +{0xEC44,0x84,0x01}, +{0xEC45,0x42,0x01}, +{0xEC46,0xE1,0x01}, +{0xEC47,0x40,0x01}, +{0xEC48,0x38,0x01}, +{0xEC49,0x1C,0x01}, +{0xEC4A,0x0C,0x01}, +{0xEC4B,0x07,0x01}, +{0xEC4C,0x03,0x01}, +{0xEC4D,0xA2,0x01}, +{0xEC4E,0x80,0x01}, +{0xEC4F,0x28,0x01}, +{0xEC50,0x18,0x01}, +{0xEC51,0x10,0x01}, +{0xEC52,0x87,0x01}, +{0xEC53,0x43,0x01}, +{0xEC54,0x61,0x01}, +{0xEC55,0x41,0x01}, +{0xEC56,0x48,0x01}, +{0xEC57,0x14,0x01}, +{0xEC58,0x10,0x01}, +{0xEC59,0x07,0x01}, +{0xEC5A,0xC2,0x01}, +{0xEC5B,0x81,0x01}, +{0xEC5C,0x80,0x01}, +{0xEC5D,0x30,0x01}, +{0xEC5E,0x20,0x01}, +{0xEC5F,0x0C,0x01}, +{0xEC60,0x87,0x01}, +{0xEC61,0x83,0x01}, +{0xEC62,0xC1,0x01}, +{0xEC63,0x40,0x01}, +{0xEC64,0x38,0x01}, +{0xEC65,0x14,0x01}, +{0xEC66,0x0A,0x01}, +{0xEC67,0x07,0x01}, +{0xEC68,0xC3,0x01}, +{0xEC69,0xC1,0x01}, +{0xEC6A,0x70,0x01}, +{0xEC6B,0x30,0x01}, +{0xEC6C,0x20,0x01}, +{0xEC6D,0x0C,0x01}, +{0xEC6E,0x08,0x01}, +{0xEC6F,0xC3,0x01}, +{0xEC70,0xE1,0x01}, +{0xEC71,0x60,0x01}, +{0xEC72,0x30,0x01}, +{0xEC73,0x10,0x01}, +{0xEC74,0x0E,0x01}, +{0xEC75,0x85,0x01}, +{0xEC76,0xC2,0x01}, +{0xEC77,0xC1,0x01}, +{0xEC78,0x70,0x01}, +{0xEC79,0x30,0x01}, +{0xEC7A,0x1C,0x01}, +{0xEC7B,0x0C,0x01}, + +//SHD1(from CO1) +{0xED02,0xE6,0x01}, +{0xED03,0x61,0x01}, +{0xED04,0x92,0x01}, +{0xED05,0x7C,0x01}, +{0xED06,0xBE,0x01}, +{0xED07,0xB4,0x01}, +{0xED08,0x9E,0x01}, +{0xED09,0x2C,0x01}, +{0xED0A,0x75,0x01}, +{0xED0B,0x47,0x01}, +{0xED0C,0x49,0x01}, +{0xED0D,0xD7,0x01}, +{0xED0E,0x61,0x01}, +{0xED0F,0x12,0x01}, +{0xED10,0x76,0x01}, +{0xED11,0xA8,0x01}, +{0xED12,0x34,0x01}, +{0xED13,0x1E,0x01}, +{0xED14,0x31,0x01}, +{0xED15,0xA1,0x01}, +{0xED16,0xC7,0x01}, +{0xED17,0x4C,0x01}, +{0xED18,0xDE,0x01}, +{0xED19,0xC1,0x01}, +{0xED1A,0xD2,0x01}, +{0xED1B,0x77,0x01}, +{0xED1C,0x76,0x01}, +{0xED1D,0x94,0x01}, +{0xED1E,0x9C,0x01}, +{0xED1F,0x10,0x01}, +{0xED20,0xC9,0x01}, +{0xED21,0xC6,0x01}, +{0xED22,0x40,0x01}, +{0xED23,0xA2,0x01}, +{0xED24,0x99,0x01}, +{0xED25,0x8F,0x01}, +{0xED26,0x66,0x01}, +{0xED27,0xDC,0x01}, +{0xED28,0xF3,0x01}, +{0xED29,0x19,0x01}, +{0xED2A,0xFC,0x01}, +{0xED2B,0xB0,0x01}, +{0xED2C,0xA6,0x01}, +{0xED2D,0x41,0x01}, +{0xED2E,0xC1,0x01}, +{0xED2F,0x49,0x01}, +{0xED30,0x91,0x01}, +{0xED31,0x75,0x01}, +{0xED32,0x8C,0x01}, +{0xED33,0x74,0x01}, +{0xED34,0x1C,0x01}, +{0xED35,0x0B,0x01}, +{0xED36,0x91,0x01}, +{0xED37,0x86,0x01}, +{0xED38,0x3D,0x01}, +{0xED39,0x87,0x01}, +{0xED3A,0x39,0x01}, +{0xED3B,0x4E,0x01}, +{0xED3C,0x5C,0x01}, +{0xED3D,0x50,0x01}, +{0xED3E,0x83,0x01}, +{0xED3F,0x16,0x01}, +{0xED40,0xCF,0x01}, +{0xED41,0xBC,0x01}, +{0xED42,0x45,0x01}, +{0xED43,0x35,0x01}, +{0xED44,0x83,0x01}, +{0xED45,0x41,0x01}, +{0xED46,0xCE,0x01}, +{0xED47,0x67,0x01}, +{0xED48,0xE8,0x01}, +{0xED49,0x33,0x01}, +{0xED4A,0x1C,0x01}, +{0xED4B,0x16,0x01}, +{0xED4C,0xC1,0x01}, +{0xED4D,0x86,0x01}, +{0xED4E,0x3E,0x01}, +{0xED4F,0x83,0x01}, +{0xED50,0xC1,0x01}, +{0xED51,0x0D,0x01}, +{0xED52,0x57,0x01}, +{0xED53,0x02,0x01}, +{0xED54,0x23,0x01}, +{0xED55,0x14,0x01}, +{0xED56,0xAE,0x01}, +{0xED57,0xE4,0x01}, +{0xED58,0x44,0x01}, +{0xED59,0x2A,0x01}, +{0xED5A,0x43,0x01}, +{0xED5B,0xF9,0x01}, +{0xED5C,0xCA,0x01}, +{0xED5D,0x56,0x01}, +{0xED5E,0x0C,0x01}, +{0xED5F,0x03,0x01}, +{0xED60,0x98,0x01}, +{0xED61,0xE2,0x01}, +{0xED62,0xA8,0x01}, +{0xED63,0x26,0x01}, +{0xED64,0x41,0x01}, +{0xED65,0x9E,0x01}, +{0xED66,0xC1,0x01}, +{0xED67,0xCE,0x01}, +{0xED68,0x59,0x01}, +{0xED69,0x1C,0x01}, +{0xED6A,0xB3,0x01}, +{0xED6B,0x93,0x01}, +{0xED6C,0xA7,0x01}, +{0xED6D,0x74,0x01}, +{0xED6E,0x04,0x01}, +{0xED6F,0x25,0x01}, +{0xED70,0x13,0x01}, +{0xED71,0xD9,0x01}, +{0xED72,0xC8,0x01}, +{0xED73,0x47,0x01}, +{0xED74,0x54,0x01}, +{0xED75,0xD2,0x01}, +{0xED76,0x93,0x01}, +{0xED77,0xAA,0x01}, +{0xED78,0x98,0x01}, +{0xED79,0xE5,0x01}, +{0xED7A,0x32,0x01}, +{0xED7B,0x9A,0x01}, +{0xED7C,0x29,0x01}, +{0xED7D,0xCF,0x01}, +{0xED7E,0x64,0x01}, +{0xED7F,0x8E,0x01}, +{0xED80,0x73,0x01}, +{0xED81,0x95,0x01}, +{0xED82,0xBB,0x01}, +{0xED83,0xA4,0x01}, +{0xED84,0xA4,0x01}, +{0xED85,0x26,0x01}, +{0xED86,0x0A,0x01}, +{0xED87,0x59,0x01}, +{0xED88,0x08,0x01}, +{0xED89,0x40,0x01}, +{0xED8A,0x00,0x01}, +{0xED8B,0xC2,0x01}, +{0xED8C,0x10,0x01}, +{0xED8D,0x88,0x01}, +{0xED8E,0xB0,0x01}, +{0xED8F,0x84,0x01}, +{0xED90,0x27,0x01}, +{0xED91,0x59,0x01}, +{0xED92,0xF1,0x01}, +{0xED93,0x0B,0x01}, +{0xED94,0x64,0x01}, +{0xED95,0xA2,0x01}, +{0xED96,0x43,0x01}, +{0xED97,0x99,0x01}, +{0xED98,0xE4,0x01}, +{0xED99,0x68,0x01}, +{0xED9A,0x25,0x01}, +{0xED9B,0x2F,0x01}, +{0xED9C,0x2B,0x01}, +{0xED9D,0xB1,0x01}, +{0xED9E,0xC9,0x01}, +{0xED9F,0x42,0x01}, +{0xEDA0,0x18,0x01}, +{0xEDA1,0x32,0x01}, +{0xEDA2,0x90,0x01}, +{0xEDA3,0x80,0x01}, +{0xEDA4,0x3C,0x01}, +{0xEDA5,0x24,0x01}, +{0xEDA6,0x22,0x01}, +{0xEDA7,0x2F,0x01}, +{0xEDA8,0xF1,0x01}, +{0xEDA9,0x09,0x01}, +{0xEDAA,0x57,0x01}, +{0xEDAB,0x00,0x01}, +{0xEDAC,0x53,0x01}, +{0xEDAD,0x99,0x01}, +{0xEDAE,0xEA,0x01}, +{0xEDAF,0x90,0x01}, +{0xEDB0,0xC6,0x01}, +{0xEDB1,0x3B,0x01}, +{0xEDB2,0x6D,0x01}, +{0xEDB3,0x99,0x01}, +{0xEDB4,0x4C,0x01}, +{0xEDB5,0x50,0x01}, +{0xEDB6,0xA4,0x01}, +{0xEDB7,0x32,0x01}, +{0xEDB8,0x12,0x01}, +{0xEDB9,0x94,0x01}, +{0xEDBA,0x64,0x01}, +{0xEDBB,0xA4,0x01}, +{0xEDBC,0x23,0x01}, +{0xEDBD,0x25,0x01}, +{0xEDBE,0x71,0x01}, +{0xEDBF,0x49,0x01}, +{0xEDC0,0x51,0x01}, +{0xEDC1,0xB2,0x01}, +{0xEDC2,0x02,0x01}, +{0xEDC3,0x17,0x01}, +{0xEDC4,0xCD,0x01}, +{0xEDC5,0x98,0x01}, +{0xEDC6,0x86,0x01}, +{0xEDC7,0x3D,0x01}, +{0xEDC8,0xBC,0x01}, +{0xEDC9,0x01,0x01}, +{0xEDCA,0x50,0x01}, +{0xEDCB,0x63,0x01}, +{0xEDCC,0x80,0x01}, +{0xEDCD,0x63,0x01}, +{0xEDCE,0x16,0x01}, +{0xEDCF,0xC3,0x01}, +{0xEDD0,0x2C,0x01}, +{0xEDD1,0x25,0x01}, +{0xEDD2,0x2C,0x01}, +{0xEDD3,0x43,0x01}, +{0xEDD4,0xB1,0x01}, +{0xEDD5,0x4A,0x01}, +{0xEDD6,0x53,0x01}, +{0xEDD7,0xCC,0x01}, +{0xEDD8,0x82,0x01}, +{0xEDD9,0x96,0x01}, +{0xEDDA,0xC7,0x01}, +{0xEDDB,0x40,0x01}, +{0xEDDC,0xA6,0x01}, +{0xEDDD,0x39,0x01}, +{0xEDDE,0xBE,0x01}, +{0xEDDF,0x91,0x01}, +{0xEDE0,0xD0,0x01}, +{0xEDE1,0x75,0x01}, +{0xEDE2,0x54,0x01}, +{0xEDE3,0x34,0x01}, +{0xEDE4,0x1B,0x01}, +{0xEDE5,0xFC,0x01}, +{0xEDE6,0x4C,0x01}, +{0xEDE7,0x46,0x01}, +{0xEDE8,0x39,0x01}, +{0xEDE9,0x7D,0x01}, +{0xEDEA,0x71,0x01}, +{0xEDEB,0x8D,0x01}, +{0xEDEC,0x5D,0x01}, +{0xEDED,0x46,0x01}, +{0xEDEE,0xE3,0x01}, +{0xEDEF,0x17,0x01}, +{0xEDF0,0xD9,0x01}, +{0xEDF1,0x50,0x01}, +{0xEDF2,0x86,0x01}, +{0xEDF3,0x3A,0x01}, +{0xEDF4,0xB3,0x01}, +{0xEDF5,0x09,0x01}, +{0xEDF6,0x50,0x01}, +{0xEDF7,0x76,0x01}, +{0xEDF8,0x6A,0x01}, +{0xEDF9,0xF4,0x01}, +{0xEDFA,0x1E,0x01}, +{0xEDFB,0x25,0x01}, +{0xEDFC,0x61,0x01}, +{0xEDFD,0x67,0x01}, +{0xEDFE,0x45,0x01}, +{0xEDFF,0xC0,0x01}, +{0xEE00,0x69,0x01}, +{0xEE01,0xD0,0x01}, +{0xEE02,0x6B,0x01}, +{0xEE03,0xF6,0x01}, +{0xEE04,0x93,0x01}, +{0xEE05,0x9A,0x01}, +{0xEE06,0xFA,0x01}, +{0xEE07,0xB8,0x01}, +{0xEE08,0x26,0x01}, +{0xEE09,0x40,0x01}, +{0xEE0A,0xC0,0x01}, +{0xEE0B,0xB9,0x01}, +{0xEE0C,0xD0,0x01}, +{0xEE0D,0x75,0x01}, +{0xEE0E,0x6E,0x01}, +{0xEE0F,0xE4,0x01}, +{0xEE10,0x9E,0x01}, +{0xEE11,0x2D,0x01}, +{0xEE12,0xE1,0x01}, +{0xEE13,0xA7,0x01}, +{0xEE14,0x49,0x01}, +{0xEE15,0xFD,0x01}, +{0xEE16,0xB9,0x01}, +{0xEE17,0x52,0x01}, +{0xEE18,0x7C,0x01}, +{0xEE19,0x98,0x01}, +{0xEE1A,0x64,0x01}, +{0xEE1B,0x1E,0x01}, +{0xEE1C,0x22,0x01}, +{0xEE1D,0x89,0x01}, +{0xEE1E,0xA7,0x01}, +{0xEE1F,0x48,0x01}, +{0xEE20,0xE4,0x01}, +{0xEE21,0x49,0x01}, +{0xEE22,0x12,0x01}, +{0xEE23,0x7D,0x01}, +{0xEE24,0xB4,0x01}, +{0xEE25,0xB4,0x01}, +{0xEE26,0x1F,0x01}, +{0xEE27,0x31,0x01}, +{0xEE28,0xC5,0x01}, +{0xEE29,0x47,0x01}, +{0xEE2A,0x4B,0x01}, +{0xEE2B,0xC2,0x01}, +{0xEE2C,0x19,0x01}, +{0xEE2D,0x0F,0x01}, +{0xEE2E,0x73,0x01}, +{0xEE2F,0xE2,0x01}, +{0xEE30,0x13,0x01}, +{0xEE31,0x1C,0x01}, +{0xEE32,0xF5,0x01}, +{0xEE33,0xE0,0x01}, +{0xEE34,0xC6,0x01}, +{0xEE35,0x3B,0x01}, +{0xEE36,0xB6,0x01}, +{0xEE37,0xB1,0x01}, +{0xEE38,0xCE,0x01}, +{0xEE39,0x6D,0x01}, +{0xEE3A,0xB8,0x01}, +{0xEE3B,0xF3,0x01}, +{0xEE3C,0x9B,0x01}, +{0xEE3D,0xF2,0x01}, +{0xEE3E,0x18,0x01}, +{0xEE3F,0x27,0x01}, +{0xEE40,0x3D,0x01}, +{0xEE41,0xBF,0x01}, +{0xEE42,0xE9,0x01}, +{0xEE43,0xCE,0x01}, +{0xEE44,0x6E,0x01}, +{0xEE45,0xBA,0x01}, +{0xEE46,0x83,0x01}, +{0xEE47,0x9A,0x01}, +{0xEE48,0xE4,0x01}, +{0xEE49,0x50,0x01}, +{0xEE4A,0x66,0x01}, +{0xEE4B,0x36,0x01}, +{0xEE4C,0x8A,0x01}, +{0xEE4D,0x29,0x01}, +{0xEE4E,0x4D,0x01}, +{0xEE4F,0x61,0x01}, +{0xEE50,0x3A,0x01}, +{0xEE51,0xA3,0x01}, +{0xEE52,0x18,0x01}, +{0xEE53,0xD2,0x01}, +{0xEE54,0x50,0x01}, +{0xEE55,0x26,0x01}, +{0xEE56,0x36,0x01}, +{0xEE57,0xA8,0x01}, +{0xEE58,0x21,0x01}, +{0xEE59,0xCE,0x01}, +{0xEE5A,0x6E,0x01}, +{0xEE5B,0xB2,0x01}, +{0xEE5C,0x03,0x01}, +{0xEE5D,0x9A,0x01}, +{0xEE5E,0xE0,0x01}, +{0xEE5F,0x1C,0x01}, +{0xEE60,0x46,0x01}, +{0xEE61,0x34,0x01}, +{0xEE62,0x72,0x01}, +{0xEE63,0x41,0x01}, +{0xEE64,0x8C,0x01}, +{0xEE65,0x58,0x01}, +{0xEE66,0xE8,0x01}, +{0xEE67,0xC2,0x01}, +{0xEE68,0x95,0x01}, +{0xEE69,0xB5,0x01}, +{0xEE6A,0x88,0x01}, +{0xEE6B,0x65,0x01}, +{0xEE6C,0x2E,0x01}, +{0xEE6D,0x72,0x01}, +{0xEE6E,0x39,0x01}, +{0xEE6F,0x8C,0x01}, +{0xEE70,0x62,0x01}, +{0xEE71,0x48,0x01}, +{0xEE72,0x83,0x01}, +{0xEE73,0x1A,0x01}, +{0xEE74,0xE4,0x01}, +{0xEE75,0x28,0x01}, +{0xEE76,0x06,0x01}, +{0xEE77,0x35,0x01}, +{0xEE78,0x6A,0x01}, +{0xEE79,0xF9,0x01}, +{0xEE7A,0x4B,0x01}, +{0xEE7B,0x53,0x01}, +{0xEE7C,0xB8,0x01}, +{0xEE7D,0x92,0x01}, +{0xEE7E,0x13,0x01}, +{0xEE7F,0xA2,0x01}, +{0xEE80,0xCC,0x01}, +{0xEE81,0x64,0x01}, +{0xEE82,0x27,0x01}, +{0xEE83,0x3B,0x01}, +{0xEE84,0x29,0x01}, +{0xEE85,0x0A,0x01}, +{0xEE86,0x54,0x01}, +{0xEE87,0xBC,0x01}, +{0xEE88,0xF2,0x01}, +{0xEE89,0x96,0x01}, +{0xEE8A,0xC1,0x01}, +{0xEE8B,0x40,0x01}, +{0xEE8C,0xA6,0x01}, +{0xEE8D,0x35,0x01}, +{0xEE8E,0x7A,0x01}, +{0xEE8F,0xB1,0x01}, +{0xEE90,0x8C,0x01}, +{0xEE91,0x54,0x01}, +{0xEE92,0xC8,0x01}, +{0xEE93,0xF2,0x01}, +{0xEE94,0x92,0x01}, +{0xEE95,0x9D,0x01}, +{0xEE96,0x64,0x01}, +{0xEE97,0xE4,0x01}, +{0xEE98,0x23,0x01}, +{0xEE99,0x13,0x01}, +{0xEE9A,0xA9,0x01}, +{0xEE9B,0x48,0x01}, +{0xEE9C,0x47,0x01}, +{0xEE9D,0x40,0x01}, +{0xEE9E,0x42,0x01}, +{0xEE9F,0x13,0x01}, +{0xEEA0,0x9F,0x01}, +{0xEEA1,0x58,0x01}, +{0xEEA2,0xE5,0x01}, +{0xEEA3,0x2C,0x01}, +{0xEEA4,0x7F,0x01}, +{0xEEA5,0xD9,0x01}, +{0xEEA6,0x8C,0x01}, +{0xEEA7,0x5B,0x01}, +{0xEEA8,0x12,0x01}, +{0xEEA9,0x43,0x01}, +{0xEEAA,0x14,0x01}, +{0xEEAB,0xAA,0x01}, +{0xEEAC,0x80,0x01}, +{0xEEAD,0x04,0x01}, +{0xEEAE,0x25,0x01}, +{0xEEAF,0x06,0x01}, +{0xEEB0,0x51,0x01}, +{0xEEB1,0x08,0x01}, +{0xEEB2,0x40,0x01}, +{0xEEB3,0x00,0x01}, +{0xEEB4,0xB2,0x01}, +{0xEEB5,0x10,0x01}, +{0xEEB6,0x86,0x01}, +{0xEEB7,0x98,0x01}, +{0xEEB8,0x64,0x01}, +{0xEEB9,0x25,0x01}, +{0xEEBA,0x4A,0x01}, +{0xEEBB,0xB9,0x01}, +{0xEEBC,0x0A,0x01}, +{0xEEBD,0x5D,0x01}, +{0xEEBE,0x1C,0x01}, +{0xEEBF,0x13,0x01}, +{0xEEC0,0x97,0x01}, +{0xEEC1,0xC4,0x01}, +{0xEEC2,0x18,0x01}, +{0xEEC3,0x85,0x01}, +{0xEEC4,0x2A,0x01}, +{0xEEC5,0x21,0x01}, +{0xEEC6,0x41,0x01}, +{0xEEC7,0xC9,0x01}, +{0xEEC8,0x41,0x01}, +{0xEEC9,0x12,0x01}, +{0xEECA,0x02,0x01}, +{0xEECB,0x10,0x01}, +{0xEECC,0x80,0x01}, +{0xEECD,0x2C,0x01}, +{0xEECE,0x64,0x01}, +{0xEECF,0x21,0x01}, +{0xEED0,0x27,0x01}, +{0xEED1,0x61,0x01}, +{0xEED2,0xC9,0x01}, +{0xEED3,0x52,0x01}, +{0xEED4,0xB0,0x01}, +{0xEED5,0x42,0x01}, +{0xEED6,0x17,0x01}, +{0xEED7,0xC8,0x01}, +{0xEED8,0x04,0x01}, +{0xEED9,0xE6,0x01}, +{0xEEDA,0x32,0x01}, +{0xEEDB,0x58,0x01}, +{0xEEDC,0x29,0x01}, +{0xEEDD,0xCB,0x01}, +{0xEEDE,0x4C,0x01}, +{0xEEDF,0x74,0x01}, +{0xEEE0,0x92,0x01}, +{0xEEE1,0x91,0x01}, +{0xEEE2,0x8E,0x01}, +{0xEEE3,0x48,0x01}, +{0xEEE4,0x84,0x01}, +{0xEEE5,0x22,0x01}, +{0xEEE6,0x1D,0x01}, +{0xEEE7,0x01,0x01}, +{0xEEE8,0xC9,0x01}, +{0xEEE9,0x4D,0x01}, +{0xEEEA,0x7E,0x01}, +{0xEEEB,0x82,0x01}, +{0xEEEC,0x15,0x01}, +{0xEEED,0xB5,0x01}, +{0xEEEE,0x04,0x01}, +{0xEEEF,0xE6,0x01}, +{0xEEF0,0x33,0x01}, +{0xEEF1,0x99,0x01}, +{0xEEF2,0x69,0x01}, +{0xEEF3,0x0D,0x01}, +{0xEEF4,0x5D,0x01}, +{0xEEF5,0x06,0x01}, +{0xEEF6,0x33,0x01}, +{0xEEF7,0x15,0x01}, +{0xEEF8,0xAF,0x01}, +{0xEEF9,0xEC,0x01}, +{0xEEFA,0xA4,0x01}, +{0xEEFB,0x28,0x01}, +{0xEEFC,0x35,0x01}, +{0xEEFD,0xE9,0x01}, +{0xEEFE,0x09,0x01}, +{0xEEFF,0x4F,0x01}, +{0xEF00,0x8E,0x01}, +{0xEF01,0x02,0x01}, +{0xEF02,0x95,0x01}, +{0xEF03,0xB1,0x01}, +{0xEF04,0xC4,0x01}, +{0xEF05,0x25,0x01}, +{0xEF06,0x31,0x01}, +{0xEF07,0x94,0x01}, +{0xEF08,0xB1,0x01}, +{0xEF09,0x4D,0x01}, +{0xEF0A,0x6C,0x01}, +{0xEF0B,0x94,0x01}, +{0xEF0C,0x43,0x01}, +{0xEF0D,0x99,0x01}, +{0xEF0E,0xD4,0x01}, +{0xEF0F,0xEC,0x01}, +{0xEF10,0xC5,0x01}, +{0xEF11,0x31,0x01}, +{0xEF12,0x69,0x01}, +{0xEF13,0xC9,0x01}, +{0xEF14,0x0B,0x01}, +{0xEF15,0x58,0x01}, +{0xEF16,0xE6,0x01}, +{0xEF17,0x52,0x01}, +{0xEF18,0x16,0x01}, +{0xEF19,0xBE,0x01}, +{0xEF1A,0xD4,0x01}, +{0xEF1B,0x45,0x01}, +{0xEF1C,0x32,0x01}, +{0xEF1D,0x8E,0x01}, +{0xEF1E,0x79,0x01}, +{0xEF1F,0x4D,0x01}, +{0xEF20,0x6A,0x01}, +{0xEF21,0xA4,0x01}, +{0xEF22,0x83,0x01}, +{0xEF23,0x1C,0x01}, +{0xEF24,0xF2,0x01}, +{0xEF25,0xDC,0x01}, +{0xEF26,0x26,0x01}, +{0xEF27,0x3A,0x01}, +{0xEF28,0xA3,0x01}, +{0xEF29,0xE1,0x01}, +{0xEF2A,0x4D,0x01}, +{0xEF2B,0x65,0x01}, +{0xEF2C,0x5C,0x01}, +{0xEF2D,0xC3,0x01}, +{0xEF2E,0x98,0x01}, +{0xEF2F,0xD4,0x01}, +{0xEF30,0x3C,0x01}, +{0xEF31,0xE6,0x01}, +{0xEF32,0x35,0x01}, +{0xEF33,0x9D,0x01}, +{0xEF34,0x09,0x01}, +{0xEF35,0x8E,0x01}, +{0xEF36,0x6B,0x01}, +{0xEF37,0xAC,0x01}, +{0xEF38,0xE3,0x01}, +{0xEF39,0x9B,0x01}, +{0xEF3A,0xF4,0x01}, +{0xEF3B,0x34,0x01}, +{0xEF3C,0x07,0x01}, +{0xEF3D,0x3E,0x01}, +{0xEF3E,0xDA,0x01}, +{0xEF3F,0xC1,0x01}, +{0xEF40,0x8F,0x01}, +{0xEF41,0x74,0x01}, +{0xEF42,0xEA,0x01}, +{0xEF43,0x13,0x01}, +{0xEF44,0x9C,0x01}, +{0xEF45,0xF4,0x01}, +{0xEF46,0xF0,0x01}, +{0xEF47,0xA6,0x01}, +{0xEF48,0x3C,0x01}, +{0xEF49,0xC0,0x01}, +{0xEF4A,0x49,0x01}, +{0xEF4B,0x0F,0x01}, +{0xEF4C,0x72,0x01}, +{0xEF4D,0xEA,0x01}, +{0xEF4E,0xD3,0x01}, +{0xEF4F,0x9C,0x01}, +{0xEF50,0xFE,0x01}, +{0xEF51,0x04,0x01}, +{0xEF52,0xA7,0x01}, +{0xEF53,0x3D,0x01}, + +//SHD2 CW+TL84 33:66 + +{0xED00,0x9191,0x02},// +{0xEF54,0x28,0x01}, +{0xEF55,0xC2,0x01}, +{0xEF56,0x11,0x01}, +{0xEF57,0x8C,0x01}, +{0xEF58,0x46,0x01}, +{0xEF59,0x34,0x01}, +{0xEF5A,0xA2,0x01}, +{0xEF5B,0x12,0x01}, +{0xEF5C,0xCD,0x01}, +{0xEF5D,0x08,0x01}, +{0xEF5E,0x47,0x01}, +{0xEF5F,0x27,0x01}, +{0xEF60,0xAA,0x01}, +{0xEF61,0x10,0x01}, +{0xEF62,0x7F,0x01}, +{0xEF63,0xC2,0x01}, +{0xEF64,0xF3,0x01}, +{0xEF65,0x1C,0x01}, +{0xEF66,0xE4,0x01}, +{0xEF67,0x40,0x01}, +{0xEF68,0x27,0x01}, +{0xEF69,0x3C,0x01}, +{0xEF6A,0xFB,0x01}, +{0xEF6B,0xA1,0x01}, +{0xEF6C,0x90,0x01}, +{0xEF6D,0x7C,0x01}, +{0xEF6E,0x92,0x01}, +{0xEF6F,0x63,0x01}, +{0xEF70,0x9A,0x01}, +{0xEF71,0xC5,0x01}, +{0xEF72,0x0C,0x01}, +{0xEF73,0x66,0x01}, +{0xEF74,0x31,0x01}, +{0xEF75,0xA4,0x01}, +{0xEF76,0x49,0x01}, +{0xEF77,0x0E,0x01}, +{0xEF78,0x7F,0x01}, +{0xEF79,0xA0,0x01}, +{0xEF7A,0xB3,0x01}, +{0xEF7B,0x19,0x01}, +{0xEF7C,0xB6,0x01}, +{0xEF7D,0x34,0x01}, +{0xEF7E,0x85,0x01}, +{0xEF7F,0x28,0x01}, +{0xEF80,0x4D,0x01}, +{0xEF81,0x61,0x01}, +{0xEF82,0x0B,0x01}, +{0xEF83,0x68,0x01}, +{0xEF84,0xB6,0x01}, +{0xEF85,0x73,0x01}, +{0xEF86,0x9B,0x01}, +{0xEF87,0xBB,0x01}, +{0xEF88,0x0C,0x01}, +{0xEF89,0x45,0x01}, +{0xEF8A,0x24,0x01}, +{0xEF8B,0x17,0x01}, +{0xEF8C,0x11,0x01}, +{0xEF8D,0x49,0x01}, +{0xEF8E,0x51,0x01}, +{0xEF8F,0xF4,0x01}, +{0xEF90,0xC2,0x01}, +{0xEF91,0x1B,0x01}, +{0xEF92,0xD4,0x01}, +{0xEF93,0x94,0x01}, +{0xEF94,0xC5,0x01}, +{0xEF95,0x25,0x01}, +{0xEF96,0x0B,0x01}, +{0xEF97,0x01,0x01}, +{0xEF98,0x48,0x01}, +{0xEF99,0x43,0x01}, +{0xEF9A,0x62,0x01}, +{0xEF9B,0x62,0x01}, +{0xEF9C,0x96,0x01}, +{0xEF9D,0xD5,0x01}, +{0xEF9E,0xA4,0x01}, +{0xEF9F,0xC6,0x01}, +{0xEFA0,0x2C,0x01}, +{0xEFA1,0x2F,0x01}, +{0xEFA2,0x51,0x01}, +{0xEFA3,0x48,0x01}, +{0xEFA4,0x40,0x01}, +{0xEFA5,0x1C,0x01}, +{0xEFA6,0x22,0x01}, +{0xEFA7,0x13,0x01}, +{0xEFA8,0xB4,0x01}, +{0xEFA9,0xC0,0x01}, +{0xEFAA,0x86,0x01}, +{0xEFAB,0x37,0x01}, +{0xEFAC,0x7B,0x01}, +{0xEFAD,0x29,0x01}, +{0xEFAE,0x8A,0x01}, +{0xEFAF,0x48,0x01}, +{0xEFB0,0x30,0x01}, +{0xEFB1,0x52,0x01}, +{0xEFB2,0x12,0x01}, +{0xEFB3,0xA4,0x01}, +{0xEFB4,0xF4,0x01}, +{0xEFB5,0x25,0x01}, +{0xEFB6,0x38,0x01}, +{0xEFB7,0xD9,0x01}, +{0xEFB8,0x01,0x01}, +{0xEFB9,0xCD,0x01}, +{0xEFBA,0x5B,0x01}, +{0xEFBB,0xA0,0x01}, +{0xEFBC,0x72,0x01}, +{0xEFBD,0x14,0x01}, +{0xEFBE,0xA9,0x01}, +{0xEFBF,0xCC,0x01}, +{0xEFC0,0xC5,0x01}, +{0xEFC1,0x34,0x01}, +{0xEFC2,0xE3,0x01}, +{0xEFC3,0xF1,0x01}, +{0xEFC4,0x0F,0x01}, +{0xEFC5,0x74,0x01}, +{0xEFC6,0x50,0x01}, +{0xEFC7,0xF3,0x01}, +{0xEFC8,0x98,0x01}, +{0xEFC9,0xC2,0x01}, +{0xEFCA,0x40,0x01}, +{0xEFCB,0x86,0x01}, +{0xEFCC,0x35,0x01}, +{0xEFCD,0xD4,0x01}, +{0xEFCE,0x29,0x01}, +{0xEFCF,0xD0,0x01}, +{0xEFD0,0x86,0x01}, +{0xEFD1,0xFE,0x01}, +{0xEFD2,0x23,0x01}, +{0xEFD3,0x9E,0x01}, +{0xEFD4,0xE8,0x01}, +{0xEFD5,0x28,0x01}, +{0xEFD6,0x87,0x01}, +{0xEFD7,0x3A,0x01}, +{0xEFD8,0xE7,0x01}, +{0xEFD9,0x21,0x01}, +{0xEFDA,0x10,0x01}, +{0xEFDB,0x89,0x01}, +{0xEFDC,0x3E,0x01}, +{0xEFDD,0x64,0x01}, +{0xEFDE,0xA2,0x01}, +{0xEFDF,0x0D,0x01}, +{0xEFE0,0x41,0x01}, +{0xEFE1,0xC8,0x01}, +{0xEFE2,0x41,0x01}, +{0xEFE3,0x14,0x01}, +{0xEFE4,0x02,0x01}, +{0xEFE5,0x11,0x01}, +{0xEFE6,0x8A,0x01}, +{0xEFE7,0x4C,0x01}, +{0xEFE8,0x04,0x01}, +{0xEFE9,0x00,0x01}, +{0xEFEA,0x00,0x01}, +{0xEFEB,0x00,0x01}, +{0xEFEC,0x00,0x01}, +{0xEFED,0x00,0x01}, + + +//SHD3 D65+TL84 C01// +{0xED00,0x9191,0x02},// +{0xEFEE,0x12,0x01}, +{0xEFEF,0x42,0x01}, +{0xEFF0,0x51,0x01}, +{0xEFF1,0x89,0x01}, +{0xEFF2,0x38,0x01}, +{0xEFF3,0xD4,0x01}, +{0xEFF4,0x21,0x01}, +{0xEFF5,0x10,0x01}, +{0xEFF6,0xAD,0x01}, +{0xEFF7,0xA8,0x01}, +{0xEFF8,0x45,0x01}, +{0xEFF9,0x18,0x01}, +{0xEFFA,0x4A,0x01}, +{0xEFFB,0x50,0x01}, +{0xEFFC,0x7D,0x01}, +{0xEFFD,0xBA,0x01}, +{0xEFFE,0xD3,0x01}, +{0xEFFF,0x1C,0x01}, +{0xF000,0xE4,0x01}, +{0xF001,0x40,0x01}, +{0xF002,0x27,0x01}, +{0xF003,0x3C,0x01}, +{0xF004,0xF8,0x01}, +{0xF005,0x69,0x01}, +{0xF006,0x10,0x01}, +{0xF007,0x7B,0x01}, +{0xF008,0x8E,0x01}, +{0xF009,0x63,0x01}, +{0xF00A,0x1A,0x01}, +{0xF00B,0xC6,0x01}, +{0xF00C,0x10,0x01}, +{0xF00D,0xA6,0x01}, +{0xF00E,0x31,0x01}, +{0xF00F,0xA6,0x01}, +{0xF010,0x59,0x01}, +{0xF011,0x8E,0x01}, +{0xF012,0x7E,0x01}, +{0xF013,0x9A,0x01}, +{0xF014,0xB3,0x01}, +{0xF015,0x19,0x01}, +{0xF016,0xB6,0x01}, +{0xF017,0x38,0x01}, +{0xF018,0xA5,0x01}, +{0xF019,0x28,0x01}, +{0xF01A,0x4F,0x01}, +{0xF01B,0x79,0x01}, +{0xF01C,0xCB,0x01}, +{0xF01D,0x68,0x01}, +{0xF01E,0xBA,0x01}, +{0xF01F,0x53,0x01}, +{0xF020,0x9B,0x01}, +{0xF021,0xBB,0x01}, +{0xF022,0x0C,0x01}, +{0xF023,0x65,0x01}, +{0xF024,0x24,0x01}, +{0xF025,0x17,0x01}, +{0xF026,0x21,0x01}, +{0xF027,0xC9,0x01}, +{0xF028,0x51,0x01}, +{0xF029,0xFC,0x01}, +{0xF02A,0xF2,0x01}, +{0xF02B,0x9B,0x01}, +{0xF02C,0xD3,0x01}, +{0xF02D,0x94,0x01}, +{0xF02E,0xC5,0x01}, +{0xF02F,0x25,0x01}, +{0xF030,0x0A,0x01}, +{0xF031,0x01,0x01}, +{0xF032,0x48,0x01}, +{0xF033,0x43,0x01}, +{0xF034,0x66,0x01}, +{0xF035,0x92,0x01}, +{0xF036,0x96,0x01}, +{0xF037,0xD7,0x01}, +{0xF038,0xA0,0x01}, +{0xF039,0xE6,0x01}, +{0xF03A,0x2C,0x01}, +{0xF03B,0x2F,0x01}, +{0xF03C,0x51,0x01}, +{0xF03D,0x48,0x01}, +{0xF03E,0x40,0x01}, +{0xF03F,0x1E,0x01}, +{0xF040,0x42,0x01}, +{0xF041,0x93,0x01}, +{0xF042,0xB5,0x01}, +{0xF043,0xCC,0x01}, +{0xF044,0x46,0x01}, +{0xF045,0x37,0x01}, +{0xF046,0x7C,0x01}, +{0xF047,0x29,0x01}, +{0xF048,0x8A,0x01}, +{0xF049,0x48,0x01}, +{0xF04A,0x32,0x01}, +{0xF04B,0x72,0x01}, +{0xF04C,0x12,0x01}, +{0xF04D,0xA5,0x01}, +{0xF04E,0x00,0x01}, +{0xF04F,0xA6,0x01}, +{0xF050,0x38,0x01}, +{0xF051,0xD7,0x01}, +{0xF052,0x01,0x01}, +{0xF053,0x0D,0x01}, +{0xF054,0x5C,0x01}, +{0xF055,0xA2,0x01}, +{0xF056,0x82,0x01}, +{0xF057,0x94,0x01}, +{0xF058,0xAA,0x01}, +{0xF059,0xD8,0x01}, +{0xF05A,0x45,0x01}, +{0xF05B,0x35,0x01}, +{0xF05C,0xE5,0x01}, +{0xF05D,0xC9,0x01}, +{0xF05E,0xCF,0x01}, +{0xF05F,0x73,0x01}, +{0xF060,0x50,0x01}, +{0xF061,0x03,0x01}, +{0xF062,0x99,0x01}, +{0xF063,0xC3,0x01}, +{0xF064,0x4C,0x01}, +{0xF065,0xE6,0x01}, +{0xF066,0x35,0x01}, +{0xF067,0xD7,0x01}, +{0xF068,0x21,0x01}, +{0xF069,0x10,0x01}, +{0xF06A,0x84,0x01}, +{0xF06B,0xF2,0x01}, +{0xF06C,0x03,0x01}, +{0xF06D,0x9E,0x01}, +{0xF06E,0xE8,0x01}, +{0xF06F,0x2C,0x01}, +{0xF070,0xA7,0x01}, +{0xF071,0x3A,0x01}, +{0xF072,0xE8,0x01}, +{0xF073,0x11,0x01}, +{0xF074,0x90,0x01}, +{0xF075,0x87,0x01}, +{0xF076,0x18,0x01}, +{0xF077,0x94,0x01}, +{0xF078,0x21,0x01}, +{0xF079,0x09,0x01}, +{0xF07A,0x2D,0x01}, +{0xF07B,0x68,0x01}, +{0xF07C,0x41,0x01}, +{0xF07D,0x11,0x01}, +{0xF07E,0xDA,0x01}, +{0xF07F,0x10,0x01}, +{0xF080,0x88,0x01}, +{0xF081,0x2A,0x01}, +{0xF082,0x04,0x01}, +{0xF083,0x00,0x01}, +{0xF084,0x00,0x01}, +{0xF085,0x00,0x01}, +{0xF086,0x00,0x01}, +{0xF087,0x00,0x01}, +{0xF088,0xBE,0x01}, +{0xF089,0x51,0x01}, +{0xF08A,0x4E,0x01}, +{0xF08B,0x6F,0x01}, +{0xF08C,0x6C,0x01}, +{0xF08D,0x43,0x01}, +{0xF08E,0x1B,0x01}, +{0xF08F,0xDA,0x01}, +{0xF090,0xEC,0x01}, +{0xF091,0x46,0x01}, +{0xF092,0x38,0x01}, +{0xF093,0xBB,0x01}, +{0xF094,0xC1,0x01}, +{0xF095,0xCD,0x01}, +{0xF096,0x69,0x01}, +{0xF097,0x26,0x01}, +{0xF098,0x93,0x01}, +{0xF099,0x98,0x01}, +{0xF09A,0xC1,0x01}, +{0xF09B,0x20,0x01}, +{0xF09C,0x26,0x01}, +{0xF09D,0x32,0x01}, +{0xF09E,0xA5,0x01}, +{0xF09F,0xB1,0x01}, +{0xF0A0,0x8D,0x01}, +{0xF0A1,0x67,0x01}, +{0xF0A2,0x0E,0x01}, +{0xF0A3,0x23,0x01}, +{0xF0A4,0x97,0x01}, +{0xF0A5,0xB0,0x01}, +{0xF0A6,0x6C,0x01}, +{0xF0A7,0x25,0x01}, +{0xF0A8,0x2C,0x01}, +{0xF0A9,0x71,0x01}, +{0xF0AA,0x41,0x01}, +{0xF0AB,0x0C,0x01}, +{0xF0AC,0x69,0x01}, +{0xF0AD,0x14,0x01}, +{0xF0AE,0xB3,0x01}, +{0xF0AF,0x96,0x01}, +{0xF0B0,0xA6,0x01}, +{0xF0B1,0xE8,0x01}, +{0xF0B2,0x64,0x01}, +{0xF0B3,0x26,0x01}, +{0xF0B4,0x3A,0x01}, +{0xF0B5,0x79,0x01}, +{0xF0B6,0x4A,0x01}, +{0xF0B7,0x5B,0x01}, +{0xF0B8,0x18,0x01}, +{0xF0B9,0xA3,0x01}, +{0xF0BA,0x97,0x01}, +{0xF0BB,0xA9,0x01}, +{0xF0BC,0xBC,0x01}, +{0xF0BD,0x24,0x01}, +{0xF0BE,0x23,0x01}, +{0xF0BF,0x13,0x01}, +{0xF0C0,0xE1,0x01}, +{0xF0C1,0xC8,0x01}, +{0xF0C2,0x4C,0x01}, +{0xF0C3,0xAA,0x01}, +{0xF0C4,0xA2,0x01}, +{0xF0C5,0x97,0x01}, +{0xF0C6,0xB6,0x01}, +{0xF0C7,0x14,0x01}, +{0xF0C8,0x05,0x01}, +{0xF0C9,0x24,0x01}, +{0xF0CA,0x06,0x01}, +{0xF0CB,0x09,0x01}, +{0xF0CC,0xC8,0x01}, +{0xF0CD,0x42,0x01}, +{0xF0CE,0x48,0x01}, +{0xF0CF,0x82,0x01}, +{0xF0D0,0x14,0x01}, +{0xF0D1,0xB8,0x01}, +{0xF0D2,0xC0,0x01}, +{0xF0D3,0xE5,0x01}, +{0xF0D4,0x28,0x01}, +{0xF0D5,0x21,0x01}, +{0xF0D6,0x39,0x01}, +{0xF0D7,0x08,0x01}, +{0xF0D8,0x40,0x01}, +{0xF0D9,0x14,0x01}, +{0xF0DA,0x62,0x01}, +{0xF0DB,0x92,0x01}, +{0xF0DC,0xA4,0x01}, +{0xF0DD,0xC4,0x01}, +{0xF0DE,0x05,0x01}, +{0xF0DF,0x30,0x01}, +{0xF0E0,0x58,0x01}, +{0xF0E1,0xA1,0x01}, +{0xF0E2,0x49,0x01}, +{0xF0E3,0x46,0x01}, +{0xF0E4,0x22,0x01}, +{0xF0E5,0xB2,0x01}, +{0xF0E6,0x91,0x01}, +{0xF0E7,0x9A,0x01}, +{0xF0E8,0x58,0x01}, +{0xF0E9,0xA5,0x01}, +{0xF0EA,0x2F,0x01}, +{0xF0EB,0x96,0x01}, +{0xF0EC,0x99,0x01}, +{0xF0ED,0x8B,0x01}, +{0xF0EE,0x54,0x01}, +{0xF0EF,0x74,0x01}, +{0xF0F0,0x32,0x01}, +{0xF0F1,0x13,0x01}, +{0xF0F2,0x9D,0x01}, +{0xF0F3,0x38,0x01}, +{0xF0F4,0xC5,0x01}, +{0xF0F5,0x2D,0x01}, +{0xF0F6,0x90,0x01}, +{0xF0F7,0x59,0x01}, +{0xF0F8,0x4D,0x01}, +{0xF0F9,0x64,0x01}, +{0xF0FA,0xEE,0x01}, +{0xF0FB,0x62,0x01}, +{0xF0FC,0x16,0x01}, +{0xF0FD,0xAE,0x01}, +{0xF0FE,0x84,0x01}, +{0xF0FF,0x25,0x01}, +{0xF100,0x2E,0x01}, +{0xF101,0x8B,0x01}, +{0xF102,0x31,0x01}, +{0xF103,0xCD,0x01}, +{0xF104,0x6F,0x01}, +{0xF105,0x60,0x01}, +{0xF106,0xC3,0x01}, +{0xF107,0x19,0x01}, +{0xF108,0xC7,0x01}, +{0xF109,0x14,0x01}, +{0xF10A,0x26,0x01}, +{0xF10B,0x31,0x01}, +{0xF10C,0x97,0x01}, +{0xF10D,0x41,0x01}, +{0xF10E,0x8D,0x01}, +{0xF10F,0x6D,0x01}, +{0xF110,0x86,0x01}, +{0xF111,0xE3,0x01}, +{0xF112,0x9C,0x01}, +{0xF113,0xE2,0x01}, +{0xF114,0xD8,0x01}, +{0xF115,0x06,0x01}, +{0xF116,0x36,0x01}, +{0xF117,0xB5,0x01}, +{0xF118,0xE9,0x01}, +{0xF119,0x4D,0x01}, +{0xF11A,0x70,0x01}, +{0xF11B,0x68,0x01}, +{0xF11C,0x03,0x01}, +{0xF11D,0x00,0x01}, +{0xF11E,0x00,0x01}, +{0xF11F,0x00,0x01}, +{0xF120,0x00,0x01}, +{0xF121,0x00,0x01}, + + +//SHD TH +{0x6C32,0x1964,0x02}, // SHD_INP_TH_HB_H_R2 +{0x6C34,0x18CE,0x02}, // SHD_INP_TH_HB_L_R2 +{0x6C36,0x10CC,0x02}, // SHD_INP_TH_LB_H_R2 +{0x6C38,0x1004,0x02}, // SHD_INP_TH_LB_L_R2 +{0x6C3C,0x10CC,0x02}, // SHD_INP_TH_HB_H_RB +{0x6C3E,0x1004,0x02}, // SHD_INP_TH_HB_L_RB +{0x6C40,0x0000,0x02}, // SHD_INP_TH_LB_H_RB +{0x6C42,0x0000,0x02}, // SHD_INP_TH_LB_L_RB + +//PreWB_offset (for SHD2) +{0x6828,0x0013,0x02}, // SHD_PRER_OFFSET_R2 : +//PreWB_offset (for SHD3) +{0x682C,0x000C,0x02}, // SHD_PRER_OFFSET_RB : +{0x6830,0xFFFF,0x02}, // SHD_PREB_OFFSET_RB : + +// CXC/SHD EN +{0x01BC,0x57,0x01}, // CXC ON SHD ON INP ON GAIN OFF +}; + +static const isx012_regset_t ISX012_Shading_0[] = +{ +{0x01BC,0x50,0x01}, // CXC OFF SHD OFF +{0xEB00,0x8282,0x02}, //valid_code +{0xEB02,0xFE,0x01}, +{0xEB03,0x84,0x01}, +{0xEB04,0x3F,0x01}, +{0xEB05,0x01,0x01}, +{0xEB06,0x50,0x01}, +{0xEB07,0x08,0x01}, +{0xEB08,0x14,0x01}, +{0xEB09,0xFF,0x01}, +{0xEB0A,0x45,0x01}, +{0xEB0B,0x80,0x01}, +{0xEB0C,0x01,0x01}, +{0xEB0D,0x68,0x01}, +{0xEB0E,0x04,0x01}, +{0xEB0F,0x1A,0x01}, +{0xEB10,0x81,0x01}, +{0xEB11,0x86,0x01}, +{0xEB12,0x3F,0x01}, +{0xEB13,0xE1,0x01}, +{0xEB14,0x4F,0x01}, +{0xEB15,0x00,0x01}, +{0xEB16,0x14,0x01}, +{0xEB17,0x02,0x01}, +{0xEB18,0xC5,0x01}, +{0xEB19,0x7F,0x01}, +{0xEB1A,0x11,0x01}, +{0xEB1B,0x60,0x01}, +{0xEB1C,0x00,0x01}, +{0xEB1D,0x1A,0x01}, +{0xEB1E,0x81,0x01}, +{0xEB1F,0x46,0x01}, +{0xEB20,0xA0,0x01}, +{0xEB21,0x01,0x01}, +{0xEB22,0x48,0x01}, +{0xEB23,0x00,0x01}, +{0xEB24,0x12,0x01}, +{0xEB25,0x81,0x01}, +{0xEB26,0x05,0x01}, +{0xEB27,0x20,0x01}, +{0xEB28,0xF1,0x01}, +{0xEB29,0x4F,0x01}, +{0xEB2A,0x00,0x01}, +{0xEB2B,0x14,0x01}, +{0xEB2C,0x82,0x01}, +{0xEB2D,0x85,0x01}, +{0xEB2E,0x80,0x01}, +{0xEB2F,0x21,0x01}, +{0xEB30,0x60,0x01}, +{0xEB31,0x04,0x01}, +{0xEB32,0x12,0x01}, +{0xEB33,0x81,0x01}, +{0xEB34,0x84,0x01}, +{0xEB35,0xE0,0x01}, +{0xEB36,0x00,0x01}, +{0xEB37,0x28,0x01}, +{0xEB38,0x04,0x01}, +{0xEB39,0x0C,0x01}, +{0xEB3A,0x82,0x01}, +{0xEB3B,0x43,0x01}, +{0xEB3C,0x20,0x01}, +{0xEB3D,0x11,0x01}, +{0xEB3E,0x68,0x01}, +{0xEB3F,0x04,0x01}, +{0xEB40,0x1A,0x01}, +{0xEB41,0x82,0x01}, +{0xEB42,0x83,0x01}, +{0xEB43,0xE0,0x01}, +{0xEB44,0x00,0x01}, +{0xEB45,0x20,0x01}, +{0xEB46,0x00,0x01}, +{0xEB47,0x06,0x01}, +{0xEB48,0xFF,0x01}, +{0xEB49,0x41,0x01}, +{0xEB4A,0x80,0x01}, +{0xEB4B,0x10,0x01}, +{0xEB4C,0x30,0x01}, +{0xEB4D,0x08,0x01}, +{0xEB4E,0x14,0x01}, +{0xEB4F,0x02,0x01}, +{0xEB50,0x45,0x01}, +{0xEB51,0xC0,0x01}, +{0xEB52,0x10,0x01}, +{0xEB53,0x30,0x01}, +{0xEB54,0x04,0x01}, +{0xEB55,0x04,0x01}, +{0xEB56,0x01,0x01}, +{0xEB57,0xC0,0x01}, +{0xEB58,0x3F,0x01}, +{0xEB59,0x10,0x01}, +{0xEB5A,0x10,0x01}, +{0xEB5B,0x04,0x01}, +{0xEB5C,0x0A,0x01}, +{0xEB5D,0x80,0x01}, +{0xEB5E,0x03,0x01}, +{0xEB5F,0xE0,0x01}, +{0xEB60,0x10,0x01}, +{0xEB61,0x28,0x01}, +{0xEB62,0x04,0x01}, +{0xEB63,0x0A,0x01}, +{0xEB64,0x81,0x01}, +{0xEB65,0x01,0x01}, +{0xEB66,0x00,0x01}, +{0xEB67,0x10,0x01}, +{0xEB68,0x00,0x01}, +{0xEB69,0x04,0x01}, +{0xEB6A,0x04,0x01}, +{0xEB6B,0x01,0x01}, +{0xEB6C,0x42,0x01}, +{0xEB6D,0xE0,0x01}, +{0xEB6E,0x10,0x01}, +{0xEB6F,0x38,0x01}, +{0xEB70,0xFC,0x01}, +{0xEB71,0x0D,0x01}, +{0xEB72,0x7F,0x01}, +{0xEB73,0x43,0x01}, +{0xEB74,0x60,0x01}, +{0xEB75,0x00,0x01}, +{0xEB76,0x08,0x01}, +{0xEB77,0x08,0x01}, +{0xEB78,0x02,0x01}, +{0xEB79,0x81,0x01}, +{0xEB7A,0x41,0x01}, +{0xEB7B,0x80,0x01}, +{0xEB7C,0x10,0x01}, +{0xEB7D,0x30,0x01}, +{0xEB7E,0x04,0x01}, +{0xEB7F,0x0C,0x01}, +{0xEB80,0x01,0x01}, +{0xEB81,0x43,0x01}, +{0xEB82,0xC0,0x01}, +{0xEB83,0x20,0x01}, +{0xEB84,0x28,0x01}, +{0xEB85,0x08,0x01}, +{0xEB86,0x06,0x01}, +{0xEB87,0x02,0x01}, +{0xEB88,0xC2,0x01}, +{0xEB89,0xA0,0x01}, +{0xEB8A,0x30,0x01}, +{0xEB8B,0x30,0x01}, +{0xEB8C,0x0C,0x01}, +{0xEB8D,0x12,0x01}, +{0xEB8E,0x83,0x01}, +{0xEB8F,0x84,0x01}, +{0xEB90,0x00,0x01}, +{0xEB91,0x21,0x01}, +{0xEB92,0x40,0x01}, +{0xEB93,0x0C,0x01}, +{0xEB94,0x0C,0x01}, +{0xEB95,0x82,0x01}, +{0xEB96,0x03,0x01}, +{0xEB97,0xC1,0x01}, +{0xEB98,0x40,0x01}, +{0xEB99,0x40,0x01}, +{0xEB9A,0x08,0x01}, +{0xEB9B,0x10,0x01}, +{0xEB9C,0x03,0x01}, +{0xEB9D,0xC4,0x01}, +{0xEB9E,0x00,0x01}, +{0xEB9F,0x21,0x01}, +{0xEBA0,0x38,0x01}, +{0xEBA1,0x08,0x01}, +{0xEBA2,0x0E,0x01}, +{0xEBA3,0x82,0x01}, +{0xEBA4,0xC3,0x01}, +{0xEBA5,0x20,0x01}, +{0xEBA6,0x41,0x01}, +{0xEBA7,0x48,0x01}, +{0xEBA8,0x00,0x01}, +{0xEBA9,0x14,0x01}, +{0xEBAA,0x83,0x01}, +{0xEBAB,0x44,0x01}, +{0xEBAC,0x20,0x01}, +{0xEBAD,0x11,0x01}, +{0xEBAE,0x48,0x01}, +{0xEBAF,0x08,0x01}, +{0xEBB0,0x0E,0x01}, +{0xEBB1,0x82,0x01}, +{0xEBB2,0x83,0x01}, +{0xEBB3,0xE0,0x01}, +{0xEBB4,0x30,0x01}, +{0xEBB5,0x48,0x01}, +{0xEBB6,0x10,0x01}, +{0xEBB7,0x12,0x01}, +{0xEBB8,0x00,0x01}, +{0xEBB9,0xC5,0x01}, +{0xEBBA,0x20,0x01}, +{0xEBBB,0x11,0x01}, +{0xEBBC,0x48,0x01}, +{0xEBBD,0x04,0x01}, +{0xEBBE,0x12,0x01}, +{0xEBBF,0x04,0x01}, +{0xEBC0,0x3B,0x01}, +{0xEBC1,0xC1,0x01}, +{0xEBC2,0x1E,0x01}, +{0xEBC3,0xC8,0x01}, +{0xEBC4,0x0F,0x01}, +{0xEBC5,0xF8,0x01}, +{0xEBC6,0x02,0x01}, +{0xEBC7,0xBB,0x01}, +{0xEBC8,0x60,0x01}, +{0xEBC9,0x0F,0x01}, +{0xEBCA,0xB8,0x01}, +{0xEBCB,0x0F,0x01}, +{0xEBCC,0xEA,0x01}, +{0xEBCD,0x83,0x01}, +{0xEBCE,0x3A,0x01}, +{0xEBCF,0xC1,0x01}, +{0xEBD0,0x4E,0x01}, +{0xEBD1,0xB0,0x01}, +{0xEBD2,0x07,0x01}, +{0xEBD3,0xF2,0x01}, +{0xEBD4,0x03,0x01}, +{0xEBD5,0xBE,0x01}, +{0xEBD6,0xC0,0x01}, +{0xEBD7,0x2E,0x01}, +{0xEBD8,0xD8,0x01}, +{0xEBD9,0x03,0x01}, +{0xEBDA,0xEE,0x01}, +{0xEBDB,0x83,0x01}, +{0xEBDC,0xFA,0x01}, +{0xEBDD,0xA0,0x01}, +{0xEBDE,0x2E,0x01}, +{0xEBDF,0xB0,0x01}, +{0xEBE0,0x0B,0x01}, +{0xEBE1,0xEC,0x01}, +{0xEBE2,0x05,0x01}, +{0xEBE3,0xBD,0x01}, +{0xEBE4,0x60,0x01}, +{0xEBE5,0x2F,0x01}, +{0xEBE6,0xD0,0x01}, +{0xEBE7,0x07,0x01}, +{0xEBE8,0xEC,0x01}, +{0xEBE9,0x02,0x01}, +{0xEBEA,0xBC,0x01}, +{0xEBEB,0x40,0x01}, +{0xEBEC,0x2F,0x01}, +{0xEBED,0xD0,0x01}, +{0xEBEE,0x13,0x01}, +{0xEBEF,0xEE,0x01}, +{0xEBF0,0x84,0x01}, +{0xEBF1,0xBB,0x01}, +{0xEBF2,0x00,0x01}, +{0xEBF3,0x1F,0x01}, +{0xEBF4,0xC8,0x01}, +{0xEBF5,0xFF,0x01}, +{0xEBF6,0xEF,0x01}, +{0xEBF7,0x00,0x01}, +{0xEBF8,0x7D,0x01}, +{0xEBF9,0x60,0x01}, +{0xEBFA,0x2F,0x01}, +{0xEBFB,0xD0,0x01}, +{0xEBFC,0x0B,0x01}, +{0xEBFD,0xF4,0x01}, +{0xEBFE,0x85,0x01}, +{0xEBFF,0x7D,0x01}, +{0xEC00,0x61,0x01}, +{0xEC01,0x0F,0x01}, +{0xEC02,0xC0,0x01}, +{0xEC03,0xFF,0x01}, +{0xEC04,0xF7,0x01}, +{0xEC05,0x7F,0x01}, +{0xEC06,0x3D,0x01}, +{0xEC07,0x40,0x01}, +{0xEC08,0xFF,0x01}, +{0xEC09,0xDF,0x01}, +{0xEC0A,0x07,0x01}, +{0xEC0B,0xFA,0x01}, +{0xEC0C,0x81,0x01}, +{0xEC0D,0x3E,0x01}, +{0xEC0E,0x61,0x01}, +{0xEC0F,0x4F,0x01}, +{0xEC10,0xD8,0x01}, +{0xEC11,0x0B,0x01}, +{0xEC12,0xFC,0x01}, +{0xEC13,0xFE,0x01}, +{0xEC14,0x3D,0x01}, +{0xEC15,0xC0,0x01}, +{0xEC16,0xFF,0x01}, +{0xEC17,0xFF,0x01}, +{0xEC18,0x03,0x01}, +{0xEC19,0xFC,0x01}, +{0xEC1A,0x82,0x01}, +{0xEC1B,0xBE,0x01}, +{0xEC1C,0xA0,0x01}, +{0xEC1D,0x6F,0x01}, +{0xEC1E,0xF8,0x01}, +{0xEC1F,0x1B,0x01}, +{0xEC20,0xFE,0x01}, +{0xEC21,0x83,0x01}, +{0xEC22,0xBF,0x01}, +{0xEC23,0xE0,0x01}, +{0xEC24,0x0F,0x01}, +{0xEC25,0x10,0x01}, +{0xEC26,0x00,0x01}, +{0xEC27,0x00,0x01}, +{0xEC28,0x82,0x01}, +{0xEC29,0xC0,0x01}, +{0xEC2A,0x60,0x01}, +{0xEC2B,0x30,0x01}, +{0xEC2C,0x18,0x01}, +{0xEC2D,0x20,0x01}, +{0xEC2E,0x04,0x01}, +{0xEC2F,0x08,0x01}, +{0xEC30,0x81,0x01}, +{0xEC31,0x21,0x01}, +{0xEC32,0x30,0x01}, +{0xEC33,0x08,0x01}, +{0xEC34,0x08,0x01}, +{0xEC35,0x08,0x01}, +{0xEC36,0x82,0x01}, +{0xEC37,0x01,0x01}, +{0xEC38,0x81,0x01}, +{0xEC39,0x50,0x01}, +{0xEC3A,0x08,0x01}, +{0xEC3B,0x14,0x01}, +{0xEC3C,0x02,0x01}, +{0xEC3D,0x09,0x01}, +{0xEC3E,0x41,0x01}, +{0xEC3F,0x42,0x01}, +{0xEC40,0x70,0x01}, +{0xEC41,0x20,0x01}, +{0xEC42,0x0C,0x01}, +{0xEC43,0x06,0x01}, +{0xEC44,0x84,0x01}, +{0xEC45,0x42,0x01}, +{0xEC46,0xE1,0x01}, +{0xEC47,0x40,0x01}, +{0xEC48,0x38,0x01}, +{0xEC49,0x1C,0x01}, +{0xEC4A,0x0C,0x01}, +{0xEC4B,0x07,0x01}, +{0xEC4C,0x03,0x01}, +{0xEC4D,0xA2,0x01}, +{0xEC4E,0x80,0x01}, +{0xEC4F,0x28,0x01}, +{0xEC50,0x18,0x01}, +{0xEC51,0x10,0x01}, +{0xEC52,0x87,0x01}, +{0xEC53,0x43,0x01}, +{0xEC54,0x61,0x01}, +{0xEC55,0x41,0x01}, +{0xEC56,0x48,0x01}, +{0xEC57,0x14,0x01}, +{0xEC58,0x10,0x01}, +{0xEC59,0x07,0x01}, +{0xEC5A,0xC2,0x01}, +{0xEC5B,0x81,0x01}, +{0xEC5C,0x80,0x01}, +{0xEC5D,0x30,0x01}, +{0xEC5E,0x20,0x01}, +{0xEC5F,0x0C,0x01}, +{0xEC60,0x87,0x01}, +{0xEC61,0x83,0x01}, +{0xEC62,0xC1,0x01}, +{0xEC63,0x40,0x01}, +{0xEC64,0x38,0x01}, +{0xEC65,0x14,0x01}, +{0xEC66,0x0A,0x01}, +{0xEC67,0x07,0x01}, +{0xEC68,0xC3,0x01}, +{0xEC69,0xC1,0x01}, +{0xEC6A,0x70,0x01}, +{0xEC6B,0x30,0x01}, +{0xEC6C,0x20,0x01}, +{0xEC6D,0x0C,0x01}, +{0xEC6E,0x08,0x01}, +{0xEC6F,0xC3,0x01}, +{0xEC70,0xE1,0x01}, +{0xEC71,0x60,0x01}, +{0xEC72,0x30,0x01}, +{0xEC73,0x10,0x01}, +{0xEC74,0x0E,0x01}, +{0xEC75,0x85,0x01}, +{0xEC76,0xC2,0x01}, +{0xEC77,0xC1,0x01}, +{0xEC78,0x70,0x01}, +{0xEC79,0x30,0x01}, +{0xEC7A,0x1C,0x01}, +{0xEC7B,0x0C,0x01}, + +//SHD1(from CO1) +{0xED02,0xE6,0x01}, +{0xED03,0x61,0x01}, +{0xED04,0x92,0x01}, +{0xED05,0x7C,0x01}, +{0xED06,0xBE,0x01}, +{0xED07,0xB4,0x01}, +{0xED08,0x9E,0x01}, +{0xED09,0x2C,0x01}, +{0xED0A,0x75,0x01}, +{0xED0B,0x47,0x01}, +{0xED0C,0x49,0x01}, +{0xED0D,0xD7,0x01}, +{0xED0E,0x61,0x01}, +{0xED0F,0x12,0x01}, +{0xED10,0x76,0x01}, +{0xED11,0xA8,0x01}, +{0xED12,0x34,0x01}, +{0xED13,0x1E,0x01}, +{0xED14,0x31,0x01}, +{0xED15,0xA1,0x01}, +{0xED16,0xC7,0x01}, +{0xED17,0x4C,0x01}, +{0xED18,0xDE,0x01}, +{0xED19,0xC1,0x01}, +{0xED1A,0xD2,0x01}, +{0xED1B,0x77,0x01}, +{0xED1C,0x76,0x01}, +{0xED1D,0x94,0x01}, +{0xED1E,0x9C,0x01}, +{0xED1F,0x10,0x01}, +{0xED20,0xC9,0x01}, +{0xED21,0xC6,0x01}, +{0xED22,0x40,0x01}, +{0xED23,0xA2,0x01}, +{0xED24,0x99,0x01}, +{0xED25,0x8F,0x01}, +{0xED26,0x66,0x01}, +{0xED27,0xDC,0x01}, +{0xED28,0xF3,0x01}, +{0xED29,0x19,0x01}, +{0xED2A,0xFC,0x01}, +{0xED2B,0xB0,0x01}, +{0xED2C,0xA6,0x01}, +{0xED2D,0x41,0x01}, +{0xED2E,0xC1,0x01}, +{0xED2F,0x49,0x01}, +{0xED30,0x91,0x01}, +{0xED31,0x75,0x01}, +{0xED32,0x8C,0x01}, +{0xED33,0x74,0x01}, +{0xED34,0x1C,0x01}, +{0xED35,0x0B,0x01}, +{0xED36,0x91,0x01}, +{0xED37,0x86,0x01}, +{0xED38,0x3D,0x01}, +{0xED39,0x87,0x01}, +{0xED3A,0x39,0x01}, +{0xED3B,0x4E,0x01}, +{0xED3C,0x5C,0x01}, +{0xED3D,0x50,0x01}, +{0xED3E,0x83,0x01}, +{0xED3F,0x16,0x01}, +{0xED40,0xCF,0x01}, +{0xED41,0xBC,0x01}, +{0xED42,0x45,0x01}, +{0xED43,0x35,0x01}, +{0xED44,0x83,0x01}, +{0xED45,0x41,0x01}, +{0xED46,0xCE,0x01}, +{0xED47,0x67,0x01}, +{0xED48,0xE8,0x01}, +{0xED49,0x33,0x01}, +{0xED4A,0x1C,0x01}, +{0xED4B,0x16,0x01}, +{0xED4C,0xC1,0x01}, +{0xED4D,0x86,0x01}, +{0xED4E,0x3E,0x01}, +{0xED4F,0x83,0x01}, +{0xED50,0xC1,0x01}, +{0xED51,0x0D,0x01}, +{0xED52,0x57,0x01}, +{0xED53,0x02,0x01}, +{0xED54,0x23,0x01}, +{0xED55,0x14,0x01}, +{0xED56,0xAE,0x01}, +{0xED57,0xE4,0x01}, +{0xED58,0x44,0x01}, +{0xED59,0x2A,0x01}, +{0xED5A,0x43,0x01}, +{0xED5B,0xF9,0x01}, +{0xED5C,0xCA,0x01}, +{0xED5D,0x56,0x01}, +{0xED5E,0x0C,0x01}, +{0xED5F,0x03,0x01}, +{0xED60,0x98,0x01}, +{0xED61,0xE2,0x01}, +{0xED62,0xA8,0x01}, +{0xED63,0x26,0x01}, +{0xED64,0x41,0x01}, +{0xED65,0x9E,0x01}, +{0xED66,0xC1,0x01}, +{0xED67,0xCE,0x01}, +{0xED68,0x59,0x01}, +{0xED69,0x1C,0x01}, +{0xED6A,0xB3,0x01}, +{0xED6B,0x93,0x01}, +{0xED6C,0xA7,0x01}, +{0xED6D,0x74,0x01}, +{0xED6E,0x04,0x01}, +{0xED6F,0x25,0x01}, +{0xED70,0x13,0x01}, +{0xED71,0xD9,0x01}, +{0xED72,0xC8,0x01}, +{0xED73,0x47,0x01}, +{0xED74,0x54,0x01}, +{0xED75,0xD2,0x01}, +{0xED76,0x93,0x01}, +{0xED77,0xAA,0x01}, +{0xED78,0x98,0x01}, +{0xED79,0xE5,0x01}, +{0xED7A,0x32,0x01}, +{0xED7B,0x9A,0x01}, +{0xED7C,0x29,0x01}, +{0xED7D,0xCF,0x01}, +{0xED7E,0x64,0x01}, +{0xED7F,0x8E,0x01}, +{0xED80,0x73,0x01}, +{0xED81,0x95,0x01}, +{0xED82,0xBB,0x01}, +{0xED83,0xA4,0x01}, +{0xED84,0xA4,0x01}, +{0xED85,0x26,0x01}, +{0xED86,0x0A,0x01}, +{0xED87,0x59,0x01}, +{0xED88,0x08,0x01}, +{0xED89,0x40,0x01}, +{0xED8A,0x00,0x01}, +{0xED8B,0xC2,0x01}, +{0xED8C,0x10,0x01}, +{0xED8D,0x88,0x01}, +{0xED8E,0xB0,0x01}, +{0xED8F,0x84,0x01}, +{0xED90,0x27,0x01}, +{0xED91,0x59,0x01}, +{0xED92,0xF1,0x01}, +{0xED93,0x0B,0x01}, +{0xED94,0x64,0x01}, +{0xED95,0xA2,0x01}, +{0xED96,0x43,0x01}, +{0xED97,0x99,0x01}, +{0xED98,0xE4,0x01}, +{0xED99,0x68,0x01}, +{0xED9A,0x25,0x01}, +{0xED9B,0x2F,0x01}, +{0xED9C,0x2B,0x01}, +{0xED9D,0xB1,0x01}, +{0xED9E,0xC9,0x01}, +{0xED9F,0x42,0x01}, +{0xEDA0,0x18,0x01}, +{0xEDA1,0x32,0x01}, +{0xEDA2,0x90,0x01}, +{0xEDA3,0x80,0x01}, +{0xEDA4,0x3C,0x01}, +{0xEDA5,0x24,0x01}, +{0xEDA6,0x22,0x01}, +{0xEDA7,0x2F,0x01}, +{0xEDA8,0xF1,0x01}, +{0xEDA9,0x09,0x01}, +{0xEDAA,0x57,0x01}, +{0xEDAB,0x00,0x01}, +{0xEDAC,0x53,0x01}, +{0xEDAD,0x99,0x01}, +{0xEDAE,0xEA,0x01}, +{0xEDAF,0x90,0x01}, +{0xEDB0,0xC6,0x01}, +{0xEDB1,0x3B,0x01}, +{0xEDB2,0x6D,0x01}, +{0xEDB3,0x99,0x01}, +{0xEDB4,0x4C,0x01}, +{0xEDB5,0x50,0x01}, +{0xEDB6,0xA4,0x01}, +{0xEDB7,0x32,0x01}, +{0xEDB8,0x12,0x01}, +{0xEDB9,0x94,0x01}, +{0xEDBA,0x64,0x01}, +{0xEDBB,0xA4,0x01}, +{0xEDBC,0x23,0x01}, +{0xEDBD,0x25,0x01}, +{0xEDBE,0x71,0x01}, +{0xEDBF,0x49,0x01}, +{0xEDC0,0x51,0x01}, +{0xEDC1,0xB2,0x01}, +{0xEDC2,0x02,0x01}, +{0xEDC3,0x17,0x01}, +{0xEDC4,0xCD,0x01}, +{0xEDC5,0x98,0x01}, +{0xEDC6,0x86,0x01}, +{0xEDC7,0x3D,0x01}, +{0xEDC8,0xBC,0x01}, +{0xEDC9,0x01,0x01}, +{0xEDCA,0x50,0x01}, +{0xEDCB,0x63,0x01}, +{0xEDCC,0x80,0x01}, +{0xEDCD,0x63,0x01}, +{0xEDCE,0x16,0x01}, +{0xEDCF,0xC3,0x01}, +{0xEDD0,0x2C,0x01}, +{0xEDD1,0x25,0x01}, +{0xEDD2,0x2C,0x01}, +{0xEDD3,0x43,0x01}, +{0xEDD4,0xB1,0x01}, +{0xEDD5,0x4A,0x01}, +{0xEDD6,0x53,0x01}, +{0xEDD7,0xCC,0x01}, +{0xEDD8,0x82,0x01}, +{0xEDD9,0x96,0x01}, +{0xEDDA,0xC7,0x01}, +{0xEDDB,0x40,0x01}, +{0xEDDC,0xA6,0x01}, +{0xEDDD,0x39,0x01}, +{0xEDDE,0xBE,0x01}, +{0xEDDF,0x91,0x01}, +{0xEDE0,0xD0,0x01}, +{0xEDE1,0x75,0x01}, +{0xEDE2,0x54,0x01}, +{0xEDE3,0x34,0x01}, +{0xEDE4,0x1B,0x01}, +{0xEDE5,0xFC,0x01}, +{0xEDE6,0x4C,0x01}, +{0xEDE7,0x46,0x01}, +{0xEDE8,0x39,0x01}, +{0xEDE9,0x7D,0x01}, +{0xEDEA,0x71,0x01}, +{0xEDEB,0x8D,0x01}, +{0xEDEC,0x5D,0x01}, +{0xEDED,0x46,0x01}, +{0xEDEE,0xE3,0x01}, +{0xEDEF,0x17,0x01}, +{0xEDF0,0xD9,0x01}, +{0xEDF1,0x50,0x01}, +{0xEDF2,0x86,0x01}, +{0xEDF3,0x3A,0x01}, +{0xEDF4,0xB3,0x01}, +{0xEDF5,0x09,0x01}, +{0xEDF6,0x50,0x01}, +{0xEDF7,0x76,0x01}, +{0xEDF8,0x6A,0x01}, +{0xEDF9,0xF4,0x01}, +{0xEDFA,0x1E,0x01}, +{0xEDFB,0x25,0x01}, +{0xEDFC,0x61,0x01}, +{0xEDFD,0x67,0x01}, +{0xEDFE,0x45,0x01}, +{0xEDFF,0xC0,0x01}, +{0xEE00,0x69,0x01}, +{0xEE01,0xD0,0x01}, +{0xEE02,0x6B,0x01}, +{0xEE03,0xF6,0x01}, +{0xEE04,0x93,0x01}, +{0xEE05,0x9A,0x01}, +{0xEE06,0xFA,0x01}, +{0xEE07,0xB8,0x01}, +{0xEE08,0x26,0x01}, +{0xEE09,0x40,0x01}, +{0xEE0A,0xC0,0x01}, +{0xEE0B,0xB9,0x01}, +{0xEE0C,0xD0,0x01}, +{0xEE0D,0x75,0x01}, +{0xEE0E,0x6E,0x01}, +{0xEE0F,0xE4,0x01}, +{0xEE10,0x9E,0x01}, +{0xEE11,0x2D,0x01}, +{0xEE12,0xE1,0x01}, +{0xEE13,0xA7,0x01}, +{0xEE14,0x49,0x01}, +{0xEE15,0xFD,0x01}, +{0xEE16,0xB9,0x01}, +{0xEE17,0x52,0x01}, +{0xEE18,0x7C,0x01}, +{0xEE19,0x98,0x01}, +{0xEE1A,0x64,0x01}, +{0xEE1B,0x1E,0x01}, +{0xEE1C,0x22,0x01}, +{0xEE1D,0x89,0x01}, +{0xEE1E,0xA7,0x01}, +{0xEE1F,0x48,0x01}, +{0xEE20,0xE4,0x01}, +{0xEE21,0x49,0x01}, +{0xEE22,0x12,0x01}, +{0xEE23,0x7D,0x01}, +{0xEE24,0xB4,0x01}, +{0xEE25,0xB4,0x01}, +{0xEE26,0x1F,0x01}, +{0xEE27,0x31,0x01}, +{0xEE28,0xC5,0x01}, +{0xEE29,0x47,0x01}, +{0xEE2A,0x4B,0x01}, +{0xEE2B,0xC2,0x01}, +{0xEE2C,0x19,0x01}, +{0xEE2D,0x0F,0x01}, +{0xEE2E,0x73,0x01}, +{0xEE2F,0xE2,0x01}, +{0xEE30,0x13,0x01}, +{0xEE31,0x1C,0x01}, +{0xEE32,0xF5,0x01}, +{0xEE33,0xE0,0x01}, +{0xEE34,0xC6,0x01}, +{0xEE35,0x3B,0x01}, +{0xEE36,0xB6,0x01}, +{0xEE37,0xB1,0x01}, +{0xEE38,0xCE,0x01}, +{0xEE39,0x6D,0x01}, +{0xEE3A,0xB8,0x01}, +{0xEE3B,0xF3,0x01}, +{0xEE3C,0x9B,0x01}, +{0xEE3D,0xF2,0x01}, +{0xEE3E,0x18,0x01}, +{0xEE3F,0x27,0x01}, +{0xEE40,0x3D,0x01}, +{0xEE41,0xBF,0x01}, +{0xEE42,0xE9,0x01}, +{0xEE43,0xCE,0x01}, +{0xEE44,0x6E,0x01}, +{0xEE45,0xBA,0x01}, +{0xEE46,0x83,0x01}, +{0xEE47,0x9A,0x01}, +{0xEE48,0xE4,0x01}, +{0xEE49,0x50,0x01}, +{0xEE4A,0x66,0x01}, +{0xEE4B,0x36,0x01}, +{0xEE4C,0x8A,0x01}, +{0xEE4D,0x29,0x01}, +{0xEE4E,0x4D,0x01}, +{0xEE4F,0x61,0x01}, +{0xEE50,0x3A,0x01}, +{0xEE51,0xA3,0x01}, +{0xEE52,0x18,0x01}, +{0xEE53,0xD2,0x01}, +{0xEE54,0x50,0x01}, +{0xEE55,0x26,0x01}, +{0xEE56,0x36,0x01}, +{0xEE57,0xA8,0x01}, +{0xEE58,0x21,0x01}, +{0xEE59,0xCE,0x01}, +{0xEE5A,0x6E,0x01}, +{0xEE5B,0xB2,0x01}, +{0xEE5C,0x03,0x01}, +{0xEE5D,0x9A,0x01}, +{0xEE5E,0xE0,0x01}, +{0xEE5F,0x1C,0x01}, +{0xEE60,0x46,0x01}, +{0xEE61,0x34,0x01}, +{0xEE62,0x72,0x01}, +{0xEE63,0x41,0x01}, +{0xEE64,0x8C,0x01}, +{0xEE65,0x58,0x01}, +{0xEE66,0xE8,0x01}, +{0xEE67,0xC2,0x01}, +{0xEE68,0x95,0x01}, +{0xEE69,0xB5,0x01}, +{0xEE6A,0x88,0x01}, +{0xEE6B,0x65,0x01}, +{0xEE6C,0x2E,0x01}, +{0xEE6D,0x72,0x01}, +{0xEE6E,0x39,0x01}, +{0xEE6F,0x8C,0x01}, +{0xEE70,0x62,0x01}, +{0xEE71,0x48,0x01}, +{0xEE72,0x83,0x01}, +{0xEE73,0x1A,0x01}, +{0xEE74,0xE4,0x01}, +{0xEE75,0x28,0x01}, +{0xEE76,0x06,0x01}, +{0xEE77,0x35,0x01}, +{0xEE78,0x6A,0x01}, +{0xEE79,0xF9,0x01}, +{0xEE7A,0x4B,0x01}, +{0xEE7B,0x53,0x01}, +{0xEE7C,0xB8,0x01}, +{0xEE7D,0x92,0x01}, +{0xEE7E,0x13,0x01}, +{0xEE7F,0xA2,0x01}, +{0xEE80,0xCC,0x01}, +{0xEE81,0x64,0x01}, +{0xEE82,0x27,0x01}, +{0xEE83,0x3B,0x01}, +{0xEE84,0x29,0x01}, +{0xEE85,0x0A,0x01}, +{0xEE86,0x54,0x01}, +{0xEE87,0xBC,0x01}, +{0xEE88,0xF2,0x01}, +{0xEE89,0x96,0x01}, +{0xEE8A,0xC1,0x01}, +{0xEE8B,0x40,0x01}, +{0xEE8C,0xA6,0x01}, +{0xEE8D,0x35,0x01}, +{0xEE8E,0x7A,0x01}, +{0xEE8F,0xB1,0x01}, +{0xEE90,0x8C,0x01}, +{0xEE91,0x54,0x01}, +{0xEE92,0xC8,0x01}, +{0xEE93,0xF2,0x01}, +{0xEE94,0x92,0x01}, +{0xEE95,0x9D,0x01}, +{0xEE96,0x64,0x01}, +{0xEE97,0xE4,0x01}, +{0xEE98,0x23,0x01}, +{0xEE99,0x13,0x01}, +{0xEE9A,0xA9,0x01}, +{0xEE9B,0x48,0x01}, +{0xEE9C,0x47,0x01}, +{0xEE9D,0x40,0x01}, +{0xEE9E,0x42,0x01}, +{0xEE9F,0x13,0x01}, +{0xEEA0,0x9F,0x01}, +{0xEEA1,0x58,0x01}, +{0xEEA2,0xE5,0x01}, +{0xEEA3,0x2C,0x01}, +{0xEEA4,0x7F,0x01}, +{0xEEA5,0xD9,0x01}, +{0xEEA6,0x8C,0x01}, +{0xEEA7,0x5B,0x01}, +{0xEEA8,0x12,0x01}, +{0xEEA9,0x43,0x01}, +{0xEEAA,0x14,0x01}, +{0xEEAB,0xAA,0x01}, +{0xEEAC,0x80,0x01}, +{0xEEAD,0x04,0x01}, +{0xEEAE,0x25,0x01}, +{0xEEAF,0x06,0x01}, +{0xEEB0,0x51,0x01}, +{0xEEB1,0x08,0x01}, +{0xEEB2,0x40,0x01}, +{0xEEB3,0x00,0x01}, +{0xEEB4,0xB2,0x01}, +{0xEEB5,0x10,0x01}, +{0xEEB6,0x86,0x01}, +{0xEEB7,0x98,0x01}, +{0xEEB8,0x64,0x01}, +{0xEEB9,0x25,0x01}, +{0xEEBA,0x4A,0x01}, +{0xEEBB,0xB9,0x01}, +{0xEEBC,0x0A,0x01}, +{0xEEBD,0x5D,0x01}, +{0xEEBE,0x1C,0x01}, +{0xEEBF,0x13,0x01}, +{0xEEC0,0x97,0x01}, +{0xEEC1,0xC4,0x01}, +{0xEEC2,0x18,0x01}, +{0xEEC3,0x85,0x01}, +{0xEEC4,0x2A,0x01}, +{0xEEC5,0x21,0x01}, +{0xEEC6,0x41,0x01}, +{0xEEC7,0xC9,0x01}, +{0xEEC8,0x41,0x01}, +{0xEEC9,0x12,0x01}, +{0xEECA,0x02,0x01}, +{0xEECB,0x10,0x01}, +{0xEECC,0x80,0x01}, +{0xEECD,0x2C,0x01}, +{0xEECE,0x64,0x01}, +{0xEECF,0x21,0x01}, +{0xEED0,0x27,0x01}, +{0xEED1,0x61,0x01}, +{0xEED2,0xC9,0x01}, +{0xEED3,0x52,0x01}, +{0xEED4,0xB0,0x01}, +{0xEED5,0x42,0x01}, +{0xEED6,0x17,0x01}, +{0xEED7,0xC8,0x01}, +{0xEED8,0x04,0x01}, +{0xEED9,0xE6,0x01}, +{0xEEDA,0x32,0x01}, +{0xEEDB,0x58,0x01}, +{0xEEDC,0x29,0x01}, +{0xEEDD,0xCB,0x01}, +{0xEEDE,0x4C,0x01}, +{0xEEDF,0x74,0x01}, +{0xEEE0,0x92,0x01}, +{0xEEE1,0x91,0x01}, +{0xEEE2,0x8E,0x01}, +{0xEEE3,0x48,0x01}, +{0xEEE4,0x84,0x01}, +{0xEEE5,0x22,0x01}, +{0xEEE6,0x1D,0x01}, +{0xEEE7,0x01,0x01}, +{0xEEE8,0xC9,0x01}, +{0xEEE9,0x4D,0x01}, +{0xEEEA,0x7E,0x01}, +{0xEEEB,0x82,0x01}, +{0xEEEC,0x15,0x01}, +{0xEEED,0xB5,0x01}, +{0xEEEE,0x04,0x01}, +{0xEEEF,0xE6,0x01}, +{0xEEF0,0x33,0x01}, +{0xEEF1,0x99,0x01}, +{0xEEF2,0x69,0x01}, +{0xEEF3,0x0D,0x01}, +{0xEEF4,0x5D,0x01}, +{0xEEF5,0x06,0x01}, +{0xEEF6,0x33,0x01}, +{0xEEF7,0x15,0x01}, +{0xEEF8,0xAF,0x01}, +{0xEEF9,0xEC,0x01}, +{0xEEFA,0xA4,0x01}, +{0xEEFB,0x28,0x01}, +{0xEEFC,0x35,0x01}, +{0xEEFD,0xE9,0x01}, +{0xEEFE,0x09,0x01}, +{0xEEFF,0x4F,0x01}, +{0xEF00,0x8E,0x01}, +{0xEF01,0x02,0x01}, +{0xEF02,0x95,0x01}, +{0xEF03,0xB1,0x01}, +{0xEF04,0xC4,0x01}, +{0xEF05,0x25,0x01}, +{0xEF06,0x31,0x01}, +{0xEF07,0x94,0x01}, +{0xEF08,0xB1,0x01}, +{0xEF09,0x4D,0x01}, +{0xEF0A,0x6C,0x01}, +{0xEF0B,0x94,0x01}, +{0xEF0C,0x43,0x01}, +{0xEF0D,0x99,0x01}, +{0xEF0E,0xD4,0x01}, +{0xEF0F,0xEC,0x01}, +{0xEF10,0xC5,0x01}, +{0xEF11,0x31,0x01}, +{0xEF12,0x69,0x01}, +{0xEF13,0xC9,0x01}, +{0xEF14,0x0B,0x01}, +{0xEF15,0x58,0x01}, +{0xEF16,0xE6,0x01}, +{0xEF17,0x52,0x01}, +{0xEF18,0x16,0x01}, +{0xEF19,0xBE,0x01}, +{0xEF1A,0xD4,0x01}, +{0xEF1B,0x45,0x01}, +{0xEF1C,0x32,0x01}, +{0xEF1D,0x8E,0x01}, +{0xEF1E,0x79,0x01}, +{0xEF1F,0x4D,0x01}, +{0xEF20,0x6A,0x01}, +{0xEF21,0xA4,0x01}, +{0xEF22,0x83,0x01}, +{0xEF23,0x1C,0x01}, +{0xEF24,0xF2,0x01}, +{0xEF25,0xDC,0x01}, +{0xEF26,0x26,0x01}, +{0xEF27,0x3A,0x01}, +{0xEF28,0xA3,0x01}, +{0xEF29,0xE1,0x01}, +{0xEF2A,0x4D,0x01}, +{0xEF2B,0x65,0x01}, +{0xEF2C,0x5C,0x01}, +{0xEF2D,0xC3,0x01}, +{0xEF2E,0x98,0x01}, +{0xEF2F,0xD4,0x01}, +{0xEF30,0x3C,0x01}, +{0xEF31,0xE6,0x01}, +{0xEF32,0x35,0x01}, +{0xEF33,0x9D,0x01}, +{0xEF34,0x09,0x01}, +{0xEF35,0x8E,0x01}, +{0xEF36,0x6B,0x01}, +{0xEF37,0xAC,0x01}, +{0xEF38,0xE3,0x01}, +{0xEF39,0x9B,0x01}, +{0xEF3A,0xF4,0x01}, +{0xEF3B,0x34,0x01}, +{0xEF3C,0x07,0x01}, +{0xEF3D,0x3E,0x01}, +{0xEF3E,0xDA,0x01}, +{0xEF3F,0xC1,0x01}, +{0xEF40,0x8F,0x01}, +{0xEF41,0x74,0x01}, +{0xEF42,0xEA,0x01}, +{0xEF43,0x13,0x01}, +{0xEF44,0x9C,0x01}, +{0xEF45,0xF4,0x01}, +{0xEF46,0xF0,0x01}, +{0xEF47,0xA6,0x01}, +{0xEF48,0x3C,0x01}, +{0xEF49,0xC0,0x01}, +{0xEF4A,0x49,0x01}, +{0xEF4B,0x0F,0x01}, +{0xEF4C,0x72,0x01}, +{0xEF4D,0xEA,0x01}, +{0xEF4E,0xD3,0x01}, +{0xEF4F,0x9C,0x01}, +{0xEF50,0xFE,0x01}, +{0xEF51,0x04,0x01}, +{0xEF52,0xA7,0x01}, +{0xEF53,0x3D,0x01}, + +//SHD2 CW+TL84 33:66 + +{0xED00,0x9191,0x02},// +{0xEF54,0x28,0x01}, +{0xEF55,0xC2,0x01}, +{0xEF56,0x11,0x01}, +{0xEF57,0x8C,0x01}, +{0xEF58,0x46,0x01}, +{0xEF59,0x34,0x01}, +{0xEF5A,0xA2,0x01}, +{0xEF5B,0x12,0x01}, +{0xEF5C,0xCD,0x01}, +{0xEF5D,0x08,0x01}, +{0xEF5E,0x47,0x01}, +{0xEF5F,0x27,0x01}, +{0xEF60,0xAA,0x01}, +{0xEF61,0x10,0x01}, +{0xEF62,0x7F,0x01}, +{0xEF63,0xC2,0x01}, +{0xEF64,0xF3,0x01}, +{0xEF65,0x1C,0x01}, +{0xEF66,0xE4,0x01}, +{0xEF67,0x40,0x01}, +{0xEF68,0x27,0x01}, +{0xEF69,0x3C,0x01}, +{0xEF6A,0xFB,0x01}, +{0xEF6B,0xA1,0x01}, +{0xEF6C,0x90,0x01}, +{0xEF6D,0x7C,0x01}, +{0xEF6E,0x92,0x01}, +{0xEF6F,0x63,0x01}, +{0xEF70,0x9A,0x01}, +{0xEF71,0xC5,0x01}, +{0xEF72,0x0C,0x01}, +{0xEF73,0x66,0x01}, +{0xEF74,0x31,0x01}, +{0xEF75,0xA4,0x01}, +{0xEF76,0x49,0x01}, +{0xEF77,0x0E,0x01}, +{0xEF78,0x7F,0x01}, +{0xEF79,0xA0,0x01}, +{0xEF7A,0xB3,0x01}, +{0xEF7B,0x19,0x01}, +{0xEF7C,0xB6,0x01}, +{0xEF7D,0x34,0x01}, +{0xEF7E,0x85,0x01}, +{0xEF7F,0x28,0x01}, +{0xEF80,0x4D,0x01}, +{0xEF81,0x61,0x01}, +{0xEF82,0x0B,0x01}, +{0xEF83,0x68,0x01}, +{0xEF84,0xB6,0x01}, +{0xEF85,0x73,0x01}, +{0xEF86,0x9B,0x01}, +{0xEF87,0xBB,0x01}, +{0xEF88,0x0C,0x01}, +{0xEF89,0x45,0x01}, +{0xEF8A,0x24,0x01}, +{0xEF8B,0x17,0x01}, +{0xEF8C,0x11,0x01}, +{0xEF8D,0x49,0x01}, +{0xEF8E,0x51,0x01}, +{0xEF8F,0xF4,0x01}, +{0xEF90,0xC2,0x01}, +{0xEF91,0x1B,0x01}, +{0xEF92,0xD4,0x01}, +{0xEF93,0x94,0x01}, +{0xEF94,0xC5,0x01}, +{0xEF95,0x25,0x01}, +{0xEF96,0x0B,0x01}, +{0xEF97,0x01,0x01}, +{0xEF98,0x48,0x01}, +{0xEF99,0x43,0x01}, +{0xEF9A,0x62,0x01}, +{0xEF9B,0x62,0x01}, +{0xEF9C,0x96,0x01}, +{0xEF9D,0xD5,0x01}, +{0xEF9E,0xA4,0x01}, +{0xEF9F,0xC6,0x01}, +{0xEFA0,0x2C,0x01}, +{0xEFA1,0x2F,0x01}, +{0xEFA2,0x51,0x01}, +{0xEFA3,0x48,0x01}, +{0xEFA4,0x40,0x01}, +{0xEFA5,0x1C,0x01}, +{0xEFA6,0x22,0x01}, +{0xEFA7,0x13,0x01}, +{0xEFA8,0xB4,0x01}, +{0xEFA9,0xC0,0x01}, +{0xEFAA,0x86,0x01}, +{0xEFAB,0x37,0x01}, +{0xEFAC,0x7B,0x01}, +{0xEFAD,0x29,0x01}, +{0xEFAE,0x8A,0x01}, +{0xEFAF,0x48,0x01}, +{0xEFB0,0x30,0x01}, +{0xEFB1,0x52,0x01}, +{0xEFB2,0x12,0x01}, +{0xEFB3,0xA4,0x01}, +{0xEFB4,0xF4,0x01}, +{0xEFB5,0x25,0x01}, +{0xEFB6,0x38,0x01}, +{0xEFB7,0xD9,0x01}, +{0xEFB8,0x01,0x01}, +{0xEFB9,0xCD,0x01}, +{0xEFBA,0x5B,0x01}, +{0xEFBB,0xA0,0x01}, +{0xEFBC,0x72,0x01}, +{0xEFBD,0x14,0x01}, +{0xEFBE,0xA9,0x01}, +{0xEFBF,0xCC,0x01}, +{0xEFC0,0xC5,0x01}, +{0xEFC1,0x34,0x01}, +{0xEFC2,0xE3,0x01}, +{0xEFC3,0xF1,0x01}, +{0xEFC4,0x0F,0x01}, +{0xEFC5,0x74,0x01}, +{0xEFC6,0x50,0x01}, +{0xEFC7,0xF3,0x01}, +{0xEFC8,0x98,0x01}, +{0xEFC9,0xC2,0x01}, +{0xEFCA,0x40,0x01}, +{0xEFCB,0x86,0x01}, +{0xEFCC,0x35,0x01}, +{0xEFCD,0xD4,0x01}, +{0xEFCE,0x29,0x01}, +{0xEFCF,0xD0,0x01}, +{0xEFD0,0x86,0x01}, +{0xEFD1,0xFE,0x01}, +{0xEFD2,0x23,0x01}, +{0xEFD3,0x9E,0x01}, +{0xEFD4,0xE8,0x01}, +{0xEFD5,0x28,0x01}, +{0xEFD6,0x87,0x01}, +{0xEFD7,0x3A,0x01}, +{0xEFD8,0xE7,0x01}, +{0xEFD9,0x21,0x01}, +{0xEFDA,0x10,0x01}, +{0xEFDB,0x89,0x01}, +{0xEFDC,0x3E,0x01}, +{0xEFDD,0x64,0x01}, +{0xEFDE,0xA2,0x01}, +{0xEFDF,0x0D,0x01}, +{0xEFE0,0x41,0x01}, +{0xEFE1,0xC8,0x01}, +{0xEFE2,0x41,0x01}, +{0xEFE3,0x14,0x01}, +{0xEFE4,0x02,0x01}, +{0xEFE5,0x11,0x01}, +{0xEFE6,0x8A,0x01}, +{0xEFE7,0x4C,0x01}, +{0xEFE8,0x04,0x01}, +{0xEFE9,0x00,0x01}, +{0xEFEA,0x00,0x01}, +{0xEFEB,0x00,0x01}, +{0xEFEC,0x00,0x01}, +{0xEFED,0x00,0x01}, + + +//SHD3 D65+TL84 C01// +{0xED00,0x9191,0x02},// +{0xEFEE,0x12,0x01}, +{0xEFEF,0x42,0x01}, +{0xEFF0,0x51,0x01}, +{0xEFF1,0x89,0x01}, +{0xEFF2,0x38,0x01}, +{0xEFF3,0xD4,0x01}, +{0xEFF4,0x21,0x01}, +{0xEFF5,0x10,0x01}, +{0xEFF6,0xAD,0x01}, +{0xEFF7,0xA8,0x01}, +{0xEFF8,0x45,0x01}, +{0xEFF9,0x18,0x01}, +{0xEFFA,0x4A,0x01}, +{0xEFFB,0x50,0x01}, +{0xEFFC,0x7D,0x01}, +{0xEFFD,0xBA,0x01}, +{0xEFFE,0xD3,0x01}, +{0xEFFF,0x1C,0x01}, +{0xF000,0xE4,0x01}, +{0xF001,0x40,0x01}, +{0xF002,0x27,0x01}, +{0xF003,0x3C,0x01}, +{0xF004,0xF8,0x01}, +{0xF005,0x69,0x01}, +{0xF006,0x10,0x01}, +{0xF007,0x7B,0x01}, +{0xF008,0x8E,0x01}, +{0xF009,0x63,0x01}, +{0xF00A,0x1A,0x01}, +{0xF00B,0xC6,0x01}, +{0xF00C,0x10,0x01}, +{0xF00D,0xA6,0x01}, +{0xF00E,0x31,0x01}, +{0xF00F,0xA6,0x01}, +{0xF010,0x59,0x01}, +{0xF011,0x8E,0x01}, +{0xF012,0x7E,0x01}, +{0xF013,0x9A,0x01}, +{0xF014,0xB3,0x01}, +{0xF015,0x19,0x01}, +{0xF016,0xB6,0x01}, +{0xF017,0x38,0x01}, +{0xF018,0xA5,0x01}, +{0xF019,0x28,0x01}, +{0xF01A,0x4F,0x01}, +{0xF01B,0x79,0x01}, +{0xF01C,0xCB,0x01}, +{0xF01D,0x68,0x01}, +{0xF01E,0xBA,0x01}, +{0xF01F,0x53,0x01}, +{0xF020,0x9B,0x01}, +{0xF021,0xBB,0x01}, +{0xF022,0x0C,0x01}, +{0xF023,0x65,0x01}, +{0xF024,0x24,0x01}, +{0xF025,0x17,0x01}, +{0xF026,0x21,0x01}, +{0xF027,0xC9,0x01}, +{0xF028,0x51,0x01}, +{0xF029,0xFC,0x01}, +{0xF02A,0xF2,0x01}, +{0xF02B,0x9B,0x01}, +{0xF02C,0xD3,0x01}, +{0xF02D,0x94,0x01}, +{0xF02E,0xC5,0x01}, +{0xF02F,0x25,0x01}, +{0xF030,0x0A,0x01}, +{0xF031,0x01,0x01}, +{0xF032,0x48,0x01}, +{0xF033,0x43,0x01}, +{0xF034,0x66,0x01}, +{0xF035,0x92,0x01}, +{0xF036,0x96,0x01}, +{0xF037,0xD7,0x01}, +{0xF038,0xA0,0x01}, +{0xF039,0xE6,0x01}, +{0xF03A,0x2C,0x01}, +{0xF03B,0x2F,0x01}, +{0xF03C,0x51,0x01}, +{0xF03D,0x48,0x01}, +{0xF03E,0x40,0x01}, +{0xF03F,0x1E,0x01}, +{0xF040,0x42,0x01}, +{0xF041,0x93,0x01}, +{0xF042,0xB5,0x01}, +{0xF043,0xCC,0x01}, +{0xF044,0x46,0x01}, +{0xF045,0x37,0x01}, +{0xF046,0x7C,0x01}, +{0xF047,0x29,0x01}, +{0xF048,0x8A,0x01}, +{0xF049,0x48,0x01}, +{0xF04A,0x32,0x01}, +{0xF04B,0x72,0x01}, +{0xF04C,0x12,0x01}, +{0xF04D,0xA5,0x01}, +{0xF04E,0x00,0x01}, +{0xF04F,0xA6,0x01}, +{0xF050,0x38,0x01}, +{0xF051,0xD7,0x01}, +{0xF052,0x01,0x01}, +{0xF053,0x0D,0x01}, +{0xF054,0x5C,0x01}, +{0xF055,0xA2,0x01}, +{0xF056,0x82,0x01}, +{0xF057,0x94,0x01}, +{0xF058,0xAA,0x01}, +{0xF059,0xD8,0x01}, +{0xF05A,0x45,0x01}, +{0xF05B,0x35,0x01}, +{0xF05C,0xE5,0x01}, +{0xF05D,0xC9,0x01}, +{0xF05E,0xCF,0x01}, +{0xF05F,0x73,0x01}, +{0xF060,0x50,0x01}, +{0xF061,0x03,0x01}, +{0xF062,0x99,0x01}, +{0xF063,0xC3,0x01}, +{0xF064,0x4C,0x01}, +{0xF065,0xE6,0x01}, +{0xF066,0x35,0x01}, +{0xF067,0xD7,0x01}, +{0xF068,0x21,0x01}, +{0xF069,0x10,0x01}, +{0xF06A,0x84,0x01}, +{0xF06B,0xF2,0x01}, +{0xF06C,0x03,0x01}, +{0xF06D,0x9E,0x01}, +{0xF06E,0xE8,0x01}, +{0xF06F,0x2C,0x01}, +{0xF070,0xA7,0x01}, +{0xF071,0x3A,0x01}, +{0xF072,0xE8,0x01}, +{0xF073,0x11,0x01}, +{0xF074,0x90,0x01}, +{0xF075,0x87,0x01}, +{0xF076,0x18,0x01}, +{0xF077,0x94,0x01}, +{0xF078,0x21,0x01}, +{0xF079,0x09,0x01}, +{0xF07A,0x2D,0x01}, +{0xF07B,0x68,0x01}, +{0xF07C,0x41,0x01}, +{0xF07D,0x11,0x01}, +{0xF07E,0xDA,0x01}, +{0xF07F,0x10,0x01}, +{0xF080,0x88,0x01}, +{0xF081,0x2A,0x01}, +{0xF082,0x04,0x01}, +{0xF083,0x00,0x01}, +{0xF084,0x00,0x01}, +{0xF085,0x00,0x01}, +{0xF086,0x00,0x01}, +{0xF087,0x00,0x01}, +{0xF088,0xBE,0x01}, +{0xF089,0x51,0x01}, +{0xF08A,0x4E,0x01}, +{0xF08B,0x6F,0x01}, +{0xF08C,0x6C,0x01}, +{0xF08D,0x43,0x01}, +{0xF08E,0x1B,0x01}, +{0xF08F,0xDA,0x01}, +{0xF090,0xEC,0x01}, +{0xF091,0x46,0x01}, +{0xF092,0x38,0x01}, +{0xF093,0xBB,0x01}, +{0xF094,0xC1,0x01}, +{0xF095,0xCD,0x01}, +{0xF096,0x69,0x01}, +{0xF097,0x26,0x01}, +{0xF098,0x93,0x01}, +{0xF099,0x98,0x01}, +{0xF09A,0xC1,0x01}, +{0xF09B,0x20,0x01}, +{0xF09C,0x26,0x01}, +{0xF09D,0x32,0x01}, +{0xF09E,0xA5,0x01}, +{0xF09F,0xB1,0x01}, +{0xF0A0,0x8D,0x01}, +{0xF0A1,0x67,0x01}, +{0xF0A2,0x0E,0x01}, +{0xF0A3,0x23,0x01}, +{0xF0A4,0x97,0x01}, +{0xF0A5,0xB0,0x01}, +{0xF0A6,0x6C,0x01}, +{0xF0A7,0x25,0x01}, +{0xF0A8,0x2C,0x01}, +{0xF0A9,0x71,0x01}, +{0xF0AA,0x41,0x01}, +{0xF0AB,0x0C,0x01}, +{0xF0AC,0x69,0x01}, +{0xF0AD,0x14,0x01}, +{0xF0AE,0xB3,0x01}, +{0xF0AF,0x96,0x01}, +{0xF0B0,0xA6,0x01}, +{0xF0B1,0xE8,0x01}, +{0xF0B2,0x64,0x01}, +{0xF0B3,0x26,0x01}, +{0xF0B4,0x3A,0x01}, +{0xF0B5,0x79,0x01}, +{0xF0B6,0x4A,0x01}, +{0xF0B7,0x5B,0x01}, +{0xF0B8,0x18,0x01}, +{0xF0B9,0xA3,0x01}, +{0xF0BA,0x97,0x01}, +{0xF0BB,0xA9,0x01}, +{0xF0BC,0xBC,0x01}, +{0xF0BD,0x24,0x01}, +{0xF0BE,0x23,0x01}, +{0xF0BF,0x13,0x01}, +{0xF0C0,0xE1,0x01}, +{0xF0C1,0xC8,0x01}, +{0xF0C2,0x4C,0x01}, +{0xF0C3,0xAA,0x01}, +{0xF0C4,0xA2,0x01}, +{0xF0C5,0x97,0x01}, +{0xF0C6,0xB6,0x01}, +{0xF0C7,0x14,0x01}, +{0xF0C8,0x05,0x01}, +{0xF0C9,0x24,0x01}, +{0xF0CA,0x06,0x01}, +{0xF0CB,0x09,0x01}, +{0xF0CC,0xC8,0x01}, +{0xF0CD,0x42,0x01}, +{0xF0CE,0x48,0x01}, +{0xF0CF,0x82,0x01}, +{0xF0D0,0x14,0x01}, +{0xF0D1,0xB8,0x01}, +{0xF0D2,0xC0,0x01}, +{0xF0D3,0xE5,0x01}, +{0xF0D4,0x28,0x01}, +{0xF0D5,0x21,0x01}, +{0xF0D6,0x39,0x01}, +{0xF0D7,0x08,0x01}, +{0xF0D8,0x40,0x01}, +{0xF0D9,0x14,0x01}, +{0xF0DA,0x62,0x01}, +{0xF0DB,0x92,0x01}, +{0xF0DC,0xA4,0x01}, +{0xF0DD,0xC4,0x01}, +{0xF0DE,0x05,0x01}, +{0xF0DF,0x30,0x01}, +{0xF0E0,0x58,0x01}, +{0xF0E1,0xA1,0x01}, +{0xF0E2,0x49,0x01}, +{0xF0E3,0x46,0x01}, +{0xF0E4,0x22,0x01}, +{0xF0E5,0xB2,0x01}, +{0xF0E6,0x91,0x01}, +{0xF0E7,0x9A,0x01}, +{0xF0E8,0x58,0x01}, +{0xF0E9,0xA5,0x01}, +{0xF0EA,0x2F,0x01}, +{0xF0EB,0x96,0x01}, +{0xF0EC,0x99,0x01}, +{0xF0ED,0x8B,0x01}, +{0xF0EE,0x54,0x01}, +{0xF0EF,0x74,0x01}, +{0xF0F0,0x32,0x01}, +{0xF0F1,0x13,0x01}, +{0xF0F2,0x9D,0x01}, +{0xF0F3,0x38,0x01}, +{0xF0F4,0xC5,0x01}, +{0xF0F5,0x2D,0x01}, +{0xF0F6,0x90,0x01}, +{0xF0F7,0x59,0x01}, +{0xF0F8,0x4D,0x01}, +{0xF0F9,0x64,0x01}, +{0xF0FA,0xEE,0x01}, +{0xF0FB,0x62,0x01}, +{0xF0FC,0x16,0x01}, +{0xF0FD,0xAE,0x01}, +{0xF0FE,0x84,0x01}, +{0xF0FF,0x25,0x01}, +{0xF100,0x2E,0x01}, +{0xF101,0x8B,0x01}, +{0xF102,0x31,0x01}, +{0xF103,0xCD,0x01}, +{0xF104,0x6F,0x01}, +{0xF105,0x60,0x01}, +{0xF106,0xC3,0x01}, +{0xF107,0x19,0x01}, +{0xF108,0xC7,0x01}, +{0xF109,0x14,0x01}, +{0xF10A,0x26,0x01}, +{0xF10B,0x31,0x01}, +{0xF10C,0x97,0x01}, +{0xF10D,0x41,0x01}, +{0xF10E,0x8D,0x01}, +{0xF10F,0x6D,0x01}, +{0xF110,0x86,0x01}, +{0xF111,0xE3,0x01}, +{0xF112,0x9C,0x01}, +{0xF113,0xE2,0x01}, +{0xF114,0xD8,0x01}, +{0xF115,0x06,0x01}, +{0xF116,0x36,0x01}, +{0xF117,0xB5,0x01}, +{0xF118,0xE9,0x01}, +{0xF119,0x4D,0x01}, +{0xF11A,0x70,0x01}, +{0xF11B,0x68,0x01}, +{0xF11C,0x03,0x01}, +{0xF11D,0x00,0x01}, +{0xF11E,0x00,0x01}, +{0xF11F,0x00,0x01}, +{0xF120,0x00,0x01}, +{0xF121,0x00,0x01}, + + +//SHD TH +{0x6C32,0x1964,0x02}, // SHD_INP_TH_HB_H_R2 +{0x6C34,0x18CE,0x02}, // SHD_INP_TH_HB_L_R2 +{0x6C36,0x10CC,0x02}, // SHD_INP_TH_LB_H_R2 +{0x6C38,0x1004,0x02}, // SHD_INP_TH_LB_L_R2 +{0x6C3C,0x10CC,0x02}, // SHD_INP_TH_HB_H_RB +{0x6C3E,0x1004,0x02}, // SHD_INP_TH_HB_L_RB +{0x6C40,0x0000,0x02}, // SHD_INP_TH_LB_H_RB +{0x6C42,0x0000,0x02}, // SHD_INP_TH_LB_L_RB + +//PreWB_offset (for SHD2) +{0x6828,0x0013,0x02}, // SHD_PRER_OFFSET_R2 : +//PreWB_offset (for SHD3) +{0x682C,0x000C,0x02}, // SHD_PRER_OFFSET_RB : +{0x6830,0xFFFF,0x02}, // SHD_PREB_OFFSET_RB : + +// CXC/SHD EN +{0x01BC,0x57,0x01}, // CXC ON SHD ON INP ON GAIN OFF +}; + +static const isx012_regset_t ISX012_Shading_1[] = +{ +{0x01BC,0x50,0x01}, // CXC OFF SHD OFF +{0xEB00,0x8282,0x02}, //valid_code +{0xEB02,0xFE,0x01}, +{0xEB03,0x84,0x01}, +{0xEB04,0x3F,0x01}, +{0xEB05,0x01,0x01}, +{0xEB06,0x50,0x01}, +{0xEB07,0x08,0x01}, +{0xEB08,0x14,0x01}, +{0xEB09,0xFF,0x01}, +{0xEB0A,0x45,0x01}, +{0xEB0B,0x80,0x01}, +{0xEB0C,0x01,0x01}, +{0xEB0D,0x68,0x01}, +{0xEB0E,0x04,0x01}, +{0xEB0F,0x1A,0x01}, +{0xEB10,0x81,0x01}, +{0xEB11,0x86,0x01}, +{0xEB12,0x3F,0x01}, +{0xEB13,0xE1,0x01}, +{0xEB14,0x4F,0x01}, +{0xEB15,0x00,0x01}, +{0xEB16,0x14,0x01}, +{0xEB17,0x02,0x01}, +{0xEB18,0xC5,0x01}, +{0xEB19,0x7F,0x01}, +{0xEB1A,0x11,0x01}, +{0xEB1B,0x60,0x01}, +{0xEB1C,0x00,0x01}, +{0xEB1D,0x1A,0x01}, +{0xEB1E,0x81,0x01}, +{0xEB1F,0x46,0x01}, +{0xEB20,0xA0,0x01}, +{0xEB21,0x01,0x01}, +{0xEB22,0x48,0x01}, +{0xEB23,0x00,0x01}, +{0xEB24,0x12,0x01}, +{0xEB25,0x81,0x01}, +{0xEB26,0x05,0x01}, +{0xEB27,0x20,0x01}, +{0xEB28,0xF1,0x01}, +{0xEB29,0x4F,0x01}, +{0xEB2A,0x00,0x01}, +{0xEB2B,0x14,0x01}, +{0xEB2C,0x82,0x01}, +{0xEB2D,0x85,0x01}, +{0xEB2E,0x80,0x01}, +{0xEB2F,0x21,0x01}, +{0xEB30,0x60,0x01}, +{0xEB31,0x04,0x01}, +{0xEB32,0x12,0x01}, +{0xEB33,0x81,0x01}, +{0xEB34,0x84,0x01}, +{0xEB35,0xE0,0x01}, +{0xEB36,0x00,0x01}, +{0xEB37,0x28,0x01}, +{0xEB38,0x04,0x01}, +{0xEB39,0x0C,0x01}, +{0xEB3A,0x82,0x01}, +{0xEB3B,0x43,0x01}, +{0xEB3C,0x20,0x01}, +{0xEB3D,0x11,0x01}, +{0xEB3E,0x68,0x01}, +{0xEB3F,0x04,0x01}, +{0xEB40,0x1A,0x01}, +{0xEB41,0x82,0x01}, +{0xEB42,0x83,0x01}, +{0xEB43,0xE0,0x01}, +{0xEB44,0x00,0x01}, +{0xEB45,0x20,0x01}, +{0xEB46,0x00,0x01}, +{0xEB47,0x06,0x01}, +{0xEB48,0xFF,0x01}, +{0xEB49,0x41,0x01}, +{0xEB4A,0x80,0x01}, +{0xEB4B,0x10,0x01}, +{0xEB4C,0x30,0x01}, +{0xEB4D,0x08,0x01}, +{0xEB4E,0x14,0x01}, +{0xEB4F,0x02,0x01}, +{0xEB50,0x45,0x01}, +{0xEB51,0xC0,0x01}, +{0xEB52,0x10,0x01}, +{0xEB53,0x30,0x01}, +{0xEB54,0x04,0x01}, +{0xEB55,0x04,0x01}, +{0xEB56,0x01,0x01}, +{0xEB57,0xC0,0x01}, +{0xEB58,0x3F,0x01}, +{0xEB59,0x10,0x01}, +{0xEB5A,0x10,0x01}, +{0xEB5B,0x04,0x01}, +{0xEB5C,0x0A,0x01}, +{0xEB5D,0x80,0x01}, +{0xEB5E,0x03,0x01}, +{0xEB5F,0xE0,0x01}, +{0xEB60,0x10,0x01}, +{0xEB61,0x28,0x01}, +{0xEB62,0x04,0x01}, +{0xEB63,0x0A,0x01}, +{0xEB64,0x81,0x01}, +{0xEB65,0x01,0x01}, +{0xEB66,0x00,0x01}, +{0xEB67,0x10,0x01}, +{0xEB68,0x00,0x01}, +{0xEB69,0x04,0x01}, +{0xEB6A,0x04,0x01}, +{0xEB6B,0x01,0x01}, +{0xEB6C,0x42,0x01}, +{0xEB6D,0xE0,0x01}, +{0xEB6E,0x10,0x01}, +{0xEB6F,0x38,0x01}, +{0xEB70,0xFC,0x01}, +{0xEB71,0x0D,0x01}, +{0xEB72,0x7F,0x01}, +{0xEB73,0x43,0x01}, +{0xEB74,0x60,0x01}, +{0xEB75,0x00,0x01}, +{0xEB76,0x08,0x01}, +{0xEB77,0x08,0x01}, +{0xEB78,0x02,0x01}, +{0xEB79,0x81,0x01}, +{0xEB7A,0x41,0x01}, +{0xEB7B,0x80,0x01}, +{0xEB7C,0x10,0x01}, +{0xEB7D,0x30,0x01}, +{0xEB7E,0x04,0x01}, +{0xEB7F,0x0C,0x01}, +{0xEB80,0x01,0x01}, +{0xEB81,0x43,0x01}, +{0xEB82,0xC0,0x01}, +{0xEB83,0x20,0x01}, +{0xEB84,0x28,0x01}, +{0xEB85,0x08,0x01}, +{0xEB86,0x06,0x01}, +{0xEB87,0x02,0x01}, +{0xEB88,0xC2,0x01}, +{0xEB89,0xA0,0x01}, +{0xEB8A,0x30,0x01}, +{0xEB8B,0x30,0x01}, +{0xEB8C,0x0C,0x01}, +{0xEB8D,0x12,0x01}, +{0xEB8E,0x83,0x01}, +{0xEB8F,0x84,0x01}, +{0xEB90,0x00,0x01}, +{0xEB91,0x21,0x01}, +{0xEB92,0x40,0x01}, +{0xEB93,0x0C,0x01}, +{0xEB94,0x0C,0x01}, +{0xEB95,0x82,0x01}, +{0xEB96,0x03,0x01}, +{0xEB97,0xC1,0x01}, +{0xEB98,0x40,0x01}, +{0xEB99,0x40,0x01}, +{0xEB9A,0x08,0x01}, +{0xEB9B,0x10,0x01}, +{0xEB9C,0x03,0x01}, +{0xEB9D,0xC4,0x01}, +{0xEB9E,0x00,0x01}, +{0xEB9F,0x21,0x01}, +{0xEBA0,0x38,0x01}, +{0xEBA1,0x08,0x01}, +{0xEBA2,0x0E,0x01}, +{0xEBA3,0x82,0x01}, +{0xEBA4,0xC3,0x01}, +{0xEBA5,0x20,0x01}, +{0xEBA6,0x41,0x01}, +{0xEBA7,0x48,0x01}, +{0xEBA8,0x00,0x01}, +{0xEBA9,0x14,0x01}, +{0xEBAA,0x83,0x01}, +{0xEBAB,0x44,0x01}, +{0xEBAC,0x20,0x01}, +{0xEBAD,0x11,0x01}, +{0xEBAE,0x48,0x01}, +{0xEBAF,0x08,0x01}, +{0xEBB0,0x0E,0x01}, +{0xEBB1,0x82,0x01}, +{0xEBB2,0x83,0x01}, +{0xEBB3,0xE0,0x01}, +{0xEBB4,0x30,0x01}, +{0xEBB5,0x48,0x01}, +{0xEBB6,0x10,0x01}, +{0xEBB7,0x12,0x01}, +{0xEBB8,0x00,0x01}, +{0xEBB9,0xC5,0x01}, +{0xEBBA,0x20,0x01}, +{0xEBBB,0x11,0x01}, +{0xEBBC,0x48,0x01}, +{0xEBBD,0x04,0x01}, +{0xEBBE,0x12,0x01}, +{0xEBBF,0x04,0x01}, +{0xEBC0,0x3B,0x01}, +{0xEBC1,0xC1,0x01}, +{0xEBC2,0x1E,0x01}, +{0xEBC3,0xC8,0x01}, +{0xEBC4,0x0F,0x01}, +{0xEBC5,0xF8,0x01}, +{0xEBC6,0x02,0x01}, +{0xEBC7,0xBB,0x01}, +{0xEBC8,0x60,0x01}, +{0xEBC9,0x0F,0x01}, +{0xEBCA,0xB8,0x01}, +{0xEBCB,0x0F,0x01}, +{0xEBCC,0xEA,0x01}, +{0xEBCD,0x83,0x01}, +{0xEBCE,0x3A,0x01}, +{0xEBCF,0xC1,0x01}, +{0xEBD0,0x4E,0x01}, +{0xEBD1,0xB0,0x01}, +{0xEBD2,0x07,0x01}, +{0xEBD3,0xF2,0x01}, +{0xEBD4,0x03,0x01}, +{0xEBD5,0xBE,0x01}, +{0xEBD6,0xC0,0x01}, +{0xEBD7,0x2E,0x01}, +{0xEBD8,0xD8,0x01}, +{0xEBD9,0x03,0x01}, +{0xEBDA,0xEE,0x01}, +{0xEBDB,0x83,0x01}, +{0xEBDC,0xFA,0x01}, +{0xEBDD,0xA0,0x01}, +{0xEBDE,0x2E,0x01}, +{0xEBDF,0xB0,0x01}, +{0xEBE0,0x0B,0x01}, +{0xEBE1,0xEC,0x01}, +{0xEBE2,0x05,0x01}, +{0xEBE3,0xBD,0x01}, +{0xEBE4,0x60,0x01}, +{0xEBE5,0x2F,0x01}, +{0xEBE6,0xD0,0x01}, +{0xEBE7,0x07,0x01}, +{0xEBE8,0xEC,0x01}, +{0xEBE9,0x02,0x01}, +{0xEBEA,0xBC,0x01}, +{0xEBEB,0x40,0x01}, +{0xEBEC,0x2F,0x01}, +{0xEBED,0xD0,0x01}, +{0xEBEE,0x13,0x01}, +{0xEBEF,0xEE,0x01}, +{0xEBF0,0x84,0x01}, +{0xEBF1,0xBB,0x01}, +{0xEBF2,0x00,0x01}, +{0xEBF3,0x1F,0x01}, +{0xEBF4,0xC8,0x01}, +{0xEBF5,0xFF,0x01}, +{0xEBF6,0xEF,0x01}, +{0xEBF7,0x00,0x01}, +{0xEBF8,0x7D,0x01}, +{0xEBF9,0x60,0x01}, +{0xEBFA,0x2F,0x01}, +{0xEBFB,0xD0,0x01}, +{0xEBFC,0x0B,0x01}, +{0xEBFD,0xF4,0x01}, +{0xEBFE,0x85,0x01}, +{0xEBFF,0x7D,0x01}, +{0xEC00,0x61,0x01}, +{0xEC01,0x0F,0x01}, +{0xEC02,0xC0,0x01}, +{0xEC03,0xFF,0x01}, +{0xEC04,0xF7,0x01}, +{0xEC05,0x7F,0x01}, +{0xEC06,0x3D,0x01}, +{0xEC07,0x40,0x01}, +{0xEC08,0xFF,0x01}, +{0xEC09,0xDF,0x01}, +{0xEC0A,0x07,0x01}, +{0xEC0B,0xFA,0x01}, +{0xEC0C,0x81,0x01}, +{0xEC0D,0x3E,0x01}, +{0xEC0E,0x61,0x01}, +{0xEC0F,0x4F,0x01}, +{0xEC10,0xD8,0x01}, +{0xEC11,0x0B,0x01}, +{0xEC12,0xFC,0x01}, +{0xEC13,0xFE,0x01}, +{0xEC14,0x3D,0x01}, +{0xEC15,0xC0,0x01}, +{0xEC16,0xFF,0x01}, +{0xEC17,0xFF,0x01}, +{0xEC18,0x03,0x01}, +{0xEC19,0xFC,0x01}, +{0xEC1A,0x82,0x01}, +{0xEC1B,0xBE,0x01}, +{0xEC1C,0xA0,0x01}, +{0xEC1D,0x6F,0x01}, +{0xEC1E,0xF8,0x01}, +{0xEC1F,0x1B,0x01}, +{0xEC20,0xFE,0x01}, +{0xEC21,0x83,0x01}, +{0xEC22,0xBF,0x01}, +{0xEC23,0xE0,0x01}, +{0xEC24,0x0F,0x01}, +{0xEC25,0x10,0x01}, +{0xEC26,0x00,0x01}, +{0xEC27,0x00,0x01}, +{0xEC28,0x82,0x01}, +{0xEC29,0xC0,0x01}, +{0xEC2A,0x60,0x01}, +{0xEC2B,0x30,0x01}, +{0xEC2C,0x18,0x01}, +{0xEC2D,0x20,0x01}, +{0xEC2E,0x04,0x01}, +{0xEC2F,0x08,0x01}, +{0xEC30,0x81,0x01}, +{0xEC31,0x21,0x01}, +{0xEC32,0x30,0x01}, +{0xEC33,0x08,0x01}, +{0xEC34,0x08,0x01}, +{0xEC35,0x08,0x01}, +{0xEC36,0x82,0x01}, +{0xEC37,0x01,0x01}, +{0xEC38,0x81,0x01}, +{0xEC39,0x50,0x01}, +{0xEC3A,0x08,0x01}, +{0xEC3B,0x14,0x01}, +{0xEC3C,0x02,0x01}, +{0xEC3D,0x09,0x01}, +{0xEC3E,0x41,0x01}, +{0xEC3F,0x42,0x01}, +{0xEC40,0x70,0x01}, +{0xEC41,0x20,0x01}, +{0xEC42,0x0C,0x01}, +{0xEC43,0x06,0x01}, +{0xEC44,0x84,0x01}, +{0xEC45,0x42,0x01}, +{0xEC46,0xE1,0x01}, +{0xEC47,0x40,0x01}, +{0xEC48,0x38,0x01}, +{0xEC49,0x1C,0x01}, +{0xEC4A,0x0C,0x01}, +{0xEC4B,0x07,0x01}, +{0xEC4C,0x03,0x01}, +{0xEC4D,0xA2,0x01}, +{0xEC4E,0x80,0x01}, +{0xEC4F,0x28,0x01}, +{0xEC50,0x18,0x01}, +{0xEC51,0x10,0x01}, +{0xEC52,0x87,0x01}, +{0xEC53,0x43,0x01}, +{0xEC54,0x61,0x01}, +{0xEC55,0x41,0x01}, +{0xEC56,0x48,0x01}, +{0xEC57,0x14,0x01}, +{0xEC58,0x10,0x01}, +{0xEC59,0x07,0x01}, +{0xEC5A,0xC2,0x01}, +{0xEC5B,0x81,0x01}, +{0xEC5C,0x80,0x01}, +{0xEC5D,0x30,0x01}, +{0xEC5E,0x20,0x01}, +{0xEC5F,0x0C,0x01}, +{0xEC60,0x87,0x01}, +{0xEC61,0x83,0x01}, +{0xEC62,0xC1,0x01}, +{0xEC63,0x40,0x01}, +{0xEC64,0x38,0x01}, +{0xEC65,0x14,0x01}, +{0xEC66,0x0A,0x01}, +{0xEC67,0x07,0x01}, +{0xEC68,0xC3,0x01}, +{0xEC69,0xC1,0x01}, +{0xEC6A,0x70,0x01}, +{0xEC6B,0x30,0x01}, +{0xEC6C,0x20,0x01}, +{0xEC6D,0x0C,0x01}, +{0xEC6E,0x08,0x01}, +{0xEC6F,0xC3,0x01}, +{0xEC70,0xE1,0x01}, +{0xEC71,0x60,0x01}, +{0xEC72,0x30,0x01}, +{0xEC73,0x10,0x01}, +{0xEC74,0x0E,0x01}, +{0xEC75,0x85,0x01}, +{0xEC76,0xC2,0x01}, +{0xEC77,0xC1,0x01}, +{0xEC78,0x70,0x01}, +{0xEC79,0x30,0x01}, +{0xEC7A,0x1C,0x01}, +{0xEC7B,0x0C,0x01}, + +//SHD1(from CO1) +{0xED02,0xE6,0x01}, +{0xED03,0x61,0x01}, +{0xED04,0x92,0x01}, +{0xED05,0x7C,0x01}, +{0xED06,0xBE,0x01}, +{0xED07,0xB4,0x01}, +{0xED08,0x9E,0x01}, +{0xED09,0x2C,0x01}, +{0xED0A,0x75,0x01}, +{0xED0B,0x47,0x01}, +{0xED0C,0x49,0x01}, +{0xED0D,0xD7,0x01}, +{0xED0E,0x61,0x01}, +{0xED0F,0x12,0x01}, +{0xED10,0x76,0x01}, +{0xED11,0xA8,0x01}, +{0xED12,0x34,0x01}, +{0xED13,0x1E,0x01}, +{0xED14,0x31,0x01}, +{0xED15,0xA1,0x01}, +{0xED16,0xC7,0x01}, +{0xED17,0x4C,0x01}, +{0xED18,0xDE,0x01}, +{0xED19,0xC1,0x01}, +{0xED1A,0xD2,0x01}, +{0xED1B,0x77,0x01}, +{0xED1C,0x76,0x01}, +{0xED1D,0x94,0x01}, +{0xED1E,0x9C,0x01}, +{0xED1F,0x10,0x01}, +{0xED20,0xC9,0x01}, +{0xED21,0xC6,0x01}, +{0xED22,0x40,0x01}, +{0xED23,0xA2,0x01}, +{0xED24,0x99,0x01}, +{0xED25,0x8F,0x01}, +{0xED26,0x66,0x01}, +{0xED27,0xDC,0x01}, +{0xED28,0xF3,0x01}, +{0xED29,0x19,0x01}, +{0xED2A,0xFC,0x01}, +{0xED2B,0xB0,0x01}, +{0xED2C,0xA6,0x01}, +{0xED2D,0x41,0x01}, +{0xED2E,0xC1,0x01}, +{0xED2F,0x49,0x01}, +{0xED30,0x91,0x01}, +{0xED31,0x75,0x01}, +{0xED32,0x8C,0x01}, +{0xED33,0x74,0x01}, +{0xED34,0x1C,0x01}, +{0xED35,0x0B,0x01}, +{0xED36,0x91,0x01}, +{0xED37,0x86,0x01}, +{0xED38,0x3D,0x01}, +{0xED39,0x87,0x01}, +{0xED3A,0x39,0x01}, +{0xED3B,0x4E,0x01}, +{0xED3C,0x5C,0x01}, +{0xED3D,0x50,0x01}, +{0xED3E,0x83,0x01}, +{0xED3F,0x16,0x01}, +{0xED40,0xCF,0x01}, +{0xED41,0xBC,0x01}, +{0xED42,0x45,0x01}, +{0xED43,0x35,0x01}, +{0xED44,0x83,0x01}, +{0xED45,0x41,0x01}, +{0xED46,0xCE,0x01}, +{0xED47,0x67,0x01}, +{0xED48,0xE8,0x01}, +{0xED49,0x33,0x01}, +{0xED4A,0x1C,0x01}, +{0xED4B,0x16,0x01}, +{0xED4C,0xC1,0x01}, +{0xED4D,0x86,0x01}, +{0xED4E,0x3E,0x01}, +{0xED4F,0x83,0x01}, +{0xED50,0xC1,0x01}, +{0xED51,0x0D,0x01}, +{0xED52,0x57,0x01}, +{0xED53,0x02,0x01}, +{0xED54,0x23,0x01}, +{0xED55,0x14,0x01}, +{0xED56,0xAE,0x01}, +{0xED57,0xE4,0x01}, +{0xED58,0x44,0x01}, +{0xED59,0x2A,0x01}, +{0xED5A,0x43,0x01}, +{0xED5B,0xF9,0x01}, +{0xED5C,0xCA,0x01}, +{0xED5D,0x56,0x01}, +{0xED5E,0x0C,0x01}, +{0xED5F,0x03,0x01}, +{0xED60,0x98,0x01}, +{0xED61,0xE2,0x01}, +{0xED62,0xA8,0x01}, +{0xED63,0x26,0x01}, +{0xED64,0x41,0x01}, +{0xED65,0x9E,0x01}, +{0xED66,0xC1,0x01}, +{0xED67,0xCE,0x01}, +{0xED68,0x59,0x01}, +{0xED69,0x1C,0x01}, +{0xED6A,0xB3,0x01}, +{0xED6B,0x93,0x01}, +{0xED6C,0xA7,0x01}, +{0xED6D,0x74,0x01}, +{0xED6E,0x04,0x01}, +{0xED6F,0x25,0x01}, +{0xED70,0x13,0x01}, +{0xED71,0xD9,0x01}, +{0xED72,0xC8,0x01}, +{0xED73,0x47,0x01}, +{0xED74,0x54,0x01}, +{0xED75,0xD2,0x01}, +{0xED76,0x93,0x01}, +{0xED77,0xAA,0x01}, +{0xED78,0x98,0x01}, +{0xED79,0xE5,0x01}, +{0xED7A,0x32,0x01}, +{0xED7B,0x9A,0x01}, +{0xED7C,0x29,0x01}, +{0xED7D,0xCF,0x01}, +{0xED7E,0x64,0x01}, +{0xED7F,0x8E,0x01}, +{0xED80,0x73,0x01}, +{0xED81,0x95,0x01}, +{0xED82,0xBB,0x01}, +{0xED83,0xA4,0x01}, +{0xED84,0xA4,0x01}, +{0xED85,0x26,0x01}, +{0xED86,0x0A,0x01}, +{0xED87,0x59,0x01}, +{0xED88,0x08,0x01}, +{0xED89,0x40,0x01}, +{0xED8A,0x00,0x01}, +{0xED8B,0xC2,0x01}, +{0xED8C,0x10,0x01}, +{0xED8D,0x88,0x01}, +{0xED8E,0xB0,0x01}, +{0xED8F,0x84,0x01}, +{0xED90,0x27,0x01}, +{0xED91,0x59,0x01}, +{0xED92,0xF1,0x01}, +{0xED93,0x0B,0x01}, +{0xED94,0x64,0x01}, +{0xED95,0xA2,0x01}, +{0xED96,0x43,0x01}, +{0xED97,0x99,0x01}, +{0xED98,0xE4,0x01}, +{0xED99,0x68,0x01}, +{0xED9A,0x25,0x01}, +{0xED9B,0x2F,0x01}, +{0xED9C,0x2B,0x01}, +{0xED9D,0xB1,0x01}, +{0xED9E,0xC9,0x01}, +{0xED9F,0x42,0x01}, +{0xEDA0,0x18,0x01}, +{0xEDA1,0x32,0x01}, +{0xEDA2,0x90,0x01}, +{0xEDA3,0x80,0x01}, +{0xEDA4,0x3C,0x01}, +{0xEDA5,0x24,0x01}, +{0xEDA6,0x22,0x01}, +{0xEDA7,0x2F,0x01}, +{0xEDA8,0xF1,0x01}, +{0xEDA9,0x09,0x01}, +{0xEDAA,0x57,0x01}, +{0xEDAB,0x00,0x01}, +{0xEDAC,0x53,0x01}, +{0xEDAD,0x99,0x01}, +{0xEDAE,0xEA,0x01}, +{0xEDAF,0x90,0x01}, +{0xEDB0,0xC6,0x01}, +{0xEDB1,0x3B,0x01}, +{0xEDB2,0x6D,0x01}, +{0xEDB3,0x99,0x01}, +{0xEDB4,0x4C,0x01}, +{0xEDB5,0x50,0x01}, +{0xEDB6,0xA4,0x01}, +{0xEDB7,0x32,0x01}, +{0xEDB8,0x12,0x01}, +{0xEDB9,0x94,0x01}, +{0xEDBA,0x64,0x01}, +{0xEDBB,0xA4,0x01}, +{0xEDBC,0x23,0x01}, +{0xEDBD,0x25,0x01}, +{0xEDBE,0x71,0x01}, +{0xEDBF,0x49,0x01}, +{0xEDC0,0x51,0x01}, +{0xEDC1,0xB2,0x01}, +{0xEDC2,0x02,0x01}, +{0xEDC3,0x17,0x01}, +{0xEDC4,0xCD,0x01}, +{0xEDC5,0x98,0x01}, +{0xEDC6,0x86,0x01}, +{0xEDC7,0x3D,0x01}, +{0xEDC8,0xBC,0x01}, +{0xEDC9,0x01,0x01}, +{0xEDCA,0x50,0x01}, +{0xEDCB,0x63,0x01}, +{0xEDCC,0x80,0x01}, +{0xEDCD,0x63,0x01}, +{0xEDCE,0x16,0x01}, +{0xEDCF,0xC3,0x01}, +{0xEDD0,0x2C,0x01}, +{0xEDD1,0x25,0x01}, +{0xEDD2,0x2C,0x01}, +{0xEDD3,0x43,0x01}, +{0xEDD4,0xB1,0x01}, +{0xEDD5,0x4A,0x01}, +{0xEDD6,0x53,0x01}, +{0xEDD7,0xCC,0x01}, +{0xEDD8,0x82,0x01}, +{0xEDD9,0x96,0x01}, +{0xEDDA,0xC7,0x01}, +{0xEDDB,0x40,0x01}, +{0xEDDC,0xA6,0x01}, +{0xEDDD,0x39,0x01}, +{0xEDDE,0xBE,0x01}, +{0xEDDF,0x91,0x01}, +{0xEDE0,0xD0,0x01}, +{0xEDE1,0x75,0x01}, +{0xEDE2,0x54,0x01}, +{0xEDE3,0x34,0x01}, +{0xEDE4,0x1B,0x01}, +{0xEDE5,0xFC,0x01}, +{0xEDE6,0x4C,0x01}, +{0xEDE7,0x46,0x01}, +{0xEDE8,0x39,0x01}, +{0xEDE9,0x7D,0x01}, +{0xEDEA,0x71,0x01}, +{0xEDEB,0x8D,0x01}, +{0xEDEC,0x5D,0x01}, +{0xEDED,0x46,0x01}, +{0xEDEE,0xE3,0x01}, +{0xEDEF,0x17,0x01}, +{0xEDF0,0xD9,0x01}, +{0xEDF1,0x50,0x01}, +{0xEDF2,0x86,0x01}, +{0xEDF3,0x3A,0x01}, +{0xEDF4,0xB3,0x01}, +{0xEDF5,0x09,0x01}, +{0xEDF6,0x50,0x01}, +{0xEDF7,0x76,0x01}, +{0xEDF8,0x6A,0x01}, +{0xEDF9,0xF4,0x01}, +{0xEDFA,0x1E,0x01}, +{0xEDFB,0x25,0x01}, +{0xEDFC,0x61,0x01}, +{0xEDFD,0x67,0x01}, +{0xEDFE,0x45,0x01}, +{0xEDFF,0xC0,0x01}, +{0xEE00,0x69,0x01}, +{0xEE01,0xD0,0x01}, +{0xEE02,0x6B,0x01}, +{0xEE03,0xF6,0x01}, +{0xEE04,0x93,0x01}, +{0xEE05,0x9A,0x01}, +{0xEE06,0xFA,0x01}, +{0xEE07,0xB8,0x01}, +{0xEE08,0x26,0x01}, +{0xEE09,0x40,0x01}, +{0xEE0A,0xC0,0x01}, +{0xEE0B,0xB9,0x01}, +{0xEE0C,0xD0,0x01}, +{0xEE0D,0x75,0x01}, +{0xEE0E,0x6E,0x01}, +{0xEE0F,0xE4,0x01}, +{0xEE10,0x9E,0x01}, +{0xEE11,0x2D,0x01}, +{0xEE12,0xE1,0x01}, +{0xEE13,0xA7,0x01}, +{0xEE14,0x49,0x01}, +{0xEE15,0xFD,0x01}, +{0xEE16,0xB9,0x01}, +{0xEE17,0x52,0x01}, +{0xEE18,0x7C,0x01}, +{0xEE19,0x98,0x01}, +{0xEE1A,0x64,0x01}, +{0xEE1B,0x1E,0x01}, +{0xEE1C,0x22,0x01}, +{0xEE1D,0x89,0x01}, +{0xEE1E,0xA7,0x01}, +{0xEE1F,0x48,0x01}, +{0xEE20,0xE4,0x01}, +{0xEE21,0x49,0x01}, +{0xEE22,0x12,0x01}, +{0xEE23,0x7D,0x01}, +{0xEE24,0xB4,0x01}, +{0xEE25,0xB4,0x01}, +{0xEE26,0x1F,0x01}, +{0xEE27,0x31,0x01}, +{0xEE28,0xC5,0x01}, +{0xEE29,0x47,0x01}, +{0xEE2A,0x4B,0x01}, +{0xEE2B,0xC2,0x01}, +{0xEE2C,0x19,0x01}, +{0xEE2D,0x0F,0x01}, +{0xEE2E,0x73,0x01}, +{0xEE2F,0xE2,0x01}, +{0xEE30,0x13,0x01}, +{0xEE31,0x1C,0x01}, +{0xEE32,0xF5,0x01}, +{0xEE33,0xE0,0x01}, +{0xEE34,0xC6,0x01}, +{0xEE35,0x3B,0x01}, +{0xEE36,0xB6,0x01}, +{0xEE37,0xB1,0x01}, +{0xEE38,0xCE,0x01}, +{0xEE39,0x6D,0x01}, +{0xEE3A,0xB8,0x01}, +{0xEE3B,0xF3,0x01}, +{0xEE3C,0x9B,0x01}, +{0xEE3D,0xF2,0x01}, +{0xEE3E,0x18,0x01}, +{0xEE3F,0x27,0x01}, +{0xEE40,0x3D,0x01}, +{0xEE41,0xBF,0x01}, +{0xEE42,0xE9,0x01}, +{0xEE43,0xCE,0x01}, +{0xEE44,0x6E,0x01}, +{0xEE45,0xBA,0x01}, +{0xEE46,0x83,0x01}, +{0xEE47,0x9A,0x01}, +{0xEE48,0xE4,0x01}, +{0xEE49,0x50,0x01}, +{0xEE4A,0x66,0x01}, +{0xEE4B,0x36,0x01}, +{0xEE4C,0x8A,0x01}, +{0xEE4D,0x29,0x01}, +{0xEE4E,0x4D,0x01}, +{0xEE4F,0x61,0x01}, +{0xEE50,0x3A,0x01}, +{0xEE51,0xA3,0x01}, +{0xEE52,0x18,0x01}, +{0xEE53,0xD2,0x01}, +{0xEE54,0x50,0x01}, +{0xEE55,0x26,0x01}, +{0xEE56,0x36,0x01}, +{0xEE57,0xA8,0x01}, +{0xEE58,0x21,0x01}, +{0xEE59,0xCE,0x01}, +{0xEE5A,0x6E,0x01}, +{0xEE5B,0xB2,0x01}, +{0xEE5C,0x03,0x01}, +{0xEE5D,0x9A,0x01}, +{0xEE5E,0xE0,0x01}, +{0xEE5F,0x1C,0x01}, +{0xEE60,0x46,0x01}, +{0xEE61,0x34,0x01}, +{0xEE62,0x72,0x01}, +{0xEE63,0x41,0x01}, +{0xEE64,0x8C,0x01}, +{0xEE65,0x58,0x01}, +{0xEE66,0xE8,0x01}, +{0xEE67,0xC2,0x01}, +{0xEE68,0x95,0x01}, +{0xEE69,0xB5,0x01}, +{0xEE6A,0x88,0x01}, +{0xEE6B,0x65,0x01}, +{0xEE6C,0x2E,0x01}, +{0xEE6D,0x72,0x01}, +{0xEE6E,0x39,0x01}, +{0xEE6F,0x8C,0x01}, +{0xEE70,0x62,0x01}, +{0xEE71,0x48,0x01}, +{0xEE72,0x83,0x01}, +{0xEE73,0x1A,0x01}, +{0xEE74,0xE4,0x01}, +{0xEE75,0x28,0x01}, +{0xEE76,0x06,0x01}, +{0xEE77,0x35,0x01}, +{0xEE78,0x6A,0x01}, +{0xEE79,0xF9,0x01}, +{0xEE7A,0x4B,0x01}, +{0xEE7B,0x53,0x01}, +{0xEE7C,0xB8,0x01}, +{0xEE7D,0x92,0x01}, +{0xEE7E,0x13,0x01}, +{0xEE7F,0xA2,0x01}, +{0xEE80,0xCC,0x01}, +{0xEE81,0x64,0x01}, +{0xEE82,0x27,0x01}, +{0xEE83,0x3B,0x01}, +{0xEE84,0x29,0x01}, +{0xEE85,0x0A,0x01}, +{0xEE86,0x54,0x01}, +{0xEE87,0xBC,0x01}, +{0xEE88,0xF2,0x01}, +{0xEE89,0x96,0x01}, +{0xEE8A,0xC1,0x01}, +{0xEE8B,0x40,0x01}, +{0xEE8C,0xA6,0x01}, +{0xEE8D,0x35,0x01}, +{0xEE8E,0x7A,0x01}, +{0xEE8F,0xB1,0x01}, +{0xEE90,0x8C,0x01}, +{0xEE91,0x54,0x01}, +{0xEE92,0xC8,0x01}, +{0xEE93,0xF2,0x01}, +{0xEE94,0x92,0x01}, +{0xEE95,0x9D,0x01}, +{0xEE96,0x64,0x01}, +{0xEE97,0xE4,0x01}, +{0xEE98,0x23,0x01}, +{0xEE99,0x13,0x01}, +{0xEE9A,0xA9,0x01}, +{0xEE9B,0x48,0x01}, +{0xEE9C,0x47,0x01}, +{0xEE9D,0x40,0x01}, +{0xEE9E,0x42,0x01}, +{0xEE9F,0x13,0x01}, +{0xEEA0,0x9F,0x01}, +{0xEEA1,0x58,0x01}, +{0xEEA2,0xE5,0x01}, +{0xEEA3,0x2C,0x01}, +{0xEEA4,0x7F,0x01}, +{0xEEA5,0xD9,0x01}, +{0xEEA6,0x8C,0x01}, +{0xEEA7,0x5B,0x01}, +{0xEEA8,0x12,0x01}, +{0xEEA9,0x43,0x01}, +{0xEEAA,0x14,0x01}, +{0xEEAB,0xAA,0x01}, +{0xEEAC,0x80,0x01}, +{0xEEAD,0x04,0x01}, +{0xEEAE,0x25,0x01}, +{0xEEAF,0x06,0x01}, +{0xEEB0,0x51,0x01}, +{0xEEB1,0x08,0x01}, +{0xEEB2,0x40,0x01}, +{0xEEB3,0x00,0x01}, +{0xEEB4,0xB2,0x01}, +{0xEEB5,0x10,0x01}, +{0xEEB6,0x86,0x01}, +{0xEEB7,0x98,0x01}, +{0xEEB8,0x64,0x01}, +{0xEEB9,0x25,0x01}, +{0xEEBA,0x4A,0x01}, +{0xEEBB,0xB9,0x01}, +{0xEEBC,0x0A,0x01}, +{0xEEBD,0x5D,0x01}, +{0xEEBE,0x1C,0x01}, +{0xEEBF,0x13,0x01}, +{0xEEC0,0x97,0x01}, +{0xEEC1,0xC4,0x01}, +{0xEEC2,0x18,0x01}, +{0xEEC3,0x85,0x01}, +{0xEEC4,0x2A,0x01}, +{0xEEC5,0x21,0x01}, +{0xEEC6,0x41,0x01}, +{0xEEC7,0xC9,0x01}, +{0xEEC8,0x41,0x01}, +{0xEEC9,0x12,0x01}, +{0xEECA,0x02,0x01}, +{0xEECB,0x10,0x01}, +{0xEECC,0x80,0x01}, +{0xEECD,0x2C,0x01}, +{0xEECE,0x64,0x01}, +{0xEECF,0x21,0x01}, +{0xEED0,0x27,0x01}, +{0xEED1,0x61,0x01}, +{0xEED2,0xC9,0x01}, +{0xEED3,0x52,0x01}, +{0xEED4,0xB0,0x01}, +{0xEED5,0x42,0x01}, +{0xEED6,0x17,0x01}, +{0xEED7,0xC8,0x01}, +{0xEED8,0x04,0x01}, +{0xEED9,0xE6,0x01}, +{0xEEDA,0x32,0x01}, +{0xEEDB,0x58,0x01}, +{0xEEDC,0x29,0x01}, +{0xEEDD,0xCB,0x01}, +{0xEEDE,0x4C,0x01}, +{0xEEDF,0x74,0x01}, +{0xEEE0,0x92,0x01}, +{0xEEE1,0x91,0x01}, +{0xEEE2,0x8E,0x01}, +{0xEEE3,0x48,0x01}, +{0xEEE4,0x84,0x01}, +{0xEEE5,0x22,0x01}, +{0xEEE6,0x1D,0x01}, +{0xEEE7,0x01,0x01}, +{0xEEE8,0xC9,0x01}, +{0xEEE9,0x4D,0x01}, +{0xEEEA,0x7E,0x01}, +{0xEEEB,0x82,0x01}, +{0xEEEC,0x15,0x01}, +{0xEEED,0xB5,0x01}, +{0xEEEE,0x04,0x01}, +{0xEEEF,0xE6,0x01}, +{0xEEF0,0x33,0x01}, +{0xEEF1,0x99,0x01}, +{0xEEF2,0x69,0x01}, +{0xEEF3,0x0D,0x01}, +{0xEEF4,0x5D,0x01}, +{0xEEF5,0x06,0x01}, +{0xEEF6,0x33,0x01}, +{0xEEF7,0x15,0x01}, +{0xEEF8,0xAF,0x01}, +{0xEEF9,0xEC,0x01}, +{0xEEFA,0xA4,0x01}, +{0xEEFB,0x28,0x01}, +{0xEEFC,0x35,0x01}, +{0xEEFD,0xE9,0x01}, +{0xEEFE,0x09,0x01}, +{0xEEFF,0x4F,0x01}, +{0xEF00,0x8E,0x01}, +{0xEF01,0x02,0x01}, +{0xEF02,0x95,0x01}, +{0xEF03,0xB1,0x01}, +{0xEF04,0xC4,0x01}, +{0xEF05,0x25,0x01}, +{0xEF06,0x31,0x01}, +{0xEF07,0x94,0x01}, +{0xEF08,0xB1,0x01}, +{0xEF09,0x4D,0x01}, +{0xEF0A,0x6C,0x01}, +{0xEF0B,0x94,0x01}, +{0xEF0C,0x43,0x01}, +{0xEF0D,0x99,0x01}, +{0xEF0E,0xD4,0x01}, +{0xEF0F,0xEC,0x01}, +{0xEF10,0xC5,0x01}, +{0xEF11,0x31,0x01}, +{0xEF12,0x69,0x01}, +{0xEF13,0xC9,0x01}, +{0xEF14,0x0B,0x01}, +{0xEF15,0x58,0x01}, +{0xEF16,0xE6,0x01}, +{0xEF17,0x52,0x01}, +{0xEF18,0x16,0x01}, +{0xEF19,0xBE,0x01}, +{0xEF1A,0xD4,0x01}, +{0xEF1B,0x45,0x01}, +{0xEF1C,0x32,0x01}, +{0xEF1D,0x8E,0x01}, +{0xEF1E,0x79,0x01}, +{0xEF1F,0x4D,0x01}, +{0xEF20,0x6A,0x01}, +{0xEF21,0xA4,0x01}, +{0xEF22,0x83,0x01}, +{0xEF23,0x1C,0x01}, +{0xEF24,0xF2,0x01}, +{0xEF25,0xDC,0x01}, +{0xEF26,0x26,0x01}, +{0xEF27,0x3A,0x01}, +{0xEF28,0xA3,0x01}, +{0xEF29,0xE1,0x01}, +{0xEF2A,0x4D,0x01}, +{0xEF2B,0x65,0x01}, +{0xEF2C,0x5C,0x01}, +{0xEF2D,0xC3,0x01}, +{0xEF2E,0x98,0x01}, +{0xEF2F,0xD4,0x01}, +{0xEF30,0x3C,0x01}, +{0xEF31,0xE6,0x01}, +{0xEF32,0x35,0x01}, +{0xEF33,0x9D,0x01}, +{0xEF34,0x09,0x01}, +{0xEF35,0x8E,0x01}, +{0xEF36,0x6B,0x01}, +{0xEF37,0xAC,0x01}, +{0xEF38,0xE3,0x01}, +{0xEF39,0x9B,0x01}, +{0xEF3A,0xF4,0x01}, +{0xEF3B,0x34,0x01}, +{0xEF3C,0x07,0x01}, +{0xEF3D,0x3E,0x01}, +{0xEF3E,0xDA,0x01}, +{0xEF3F,0xC1,0x01}, +{0xEF40,0x8F,0x01}, +{0xEF41,0x74,0x01}, +{0xEF42,0xEA,0x01}, +{0xEF43,0x13,0x01}, +{0xEF44,0x9C,0x01}, +{0xEF45,0xF4,0x01}, +{0xEF46,0xF0,0x01}, +{0xEF47,0xA6,0x01}, +{0xEF48,0x3C,0x01}, +{0xEF49,0xC0,0x01}, +{0xEF4A,0x49,0x01}, +{0xEF4B,0x0F,0x01}, +{0xEF4C,0x72,0x01}, +{0xEF4D,0xEA,0x01}, +{0xEF4E,0xD3,0x01}, +{0xEF4F,0x9C,0x01}, +{0xEF50,0xFE,0x01}, +{0xEF51,0x04,0x01}, +{0xEF52,0xA7,0x01}, +{0xEF53,0x3D,0x01}, + +//SHD2 CW+TL84 33:66 + +{0xED00,0x9191,0x02},// +{0xEF54,0x0B,0x01}, +{0xEF55,0xFA,0x01}, +{0xEF56,0x10,0x01}, +{0xEF57,0x87,0x01}, +{0xEF58,0x24,0x01}, +{0xEF59,0x24,0x01}, +{0xEF5A,0xA1,0x01}, +{0xEF5B,0x09,0x01}, +{0xEF5C,0x7D,0x01}, +{0xEF5D,0x08,0x01}, +{0xEF5E,0x44,0x01}, +{0xEF5F,0x0A,0x01}, +{0xEF60,0x0A,0x01}, +{0xEF61,0x50,0x01}, +{0xEF62,0x7B,0x01}, +{0xEF63,0xAA,0x01}, +{0xEF64,0x53,0x01}, +{0xEF65,0x9C,0x01}, +{0xEF66,0xDF,0x01}, +{0xEF67,0x18,0x01}, +{0xEF68,0xC7,0x01}, +{0xEF69,0x3A,0x01}, +{0xEF6A,0xEC,0x01}, +{0xEF6B,0xF9,0x01}, +{0xEF6C,0x0F,0x01}, +{0xEF6D,0x79,0x01}, +{0xEF6E,0x80,0x01}, +{0xEF6F,0x03,0x01}, +{0xEF70,0x9A,0x01}, +{0xEF71,0xC3,0x01}, +{0xEF72,0xF8,0x01}, +{0xEF73,0xE5,0x01}, +{0xEF74,0x30,0x01}, +{0xEF75,0x9D,0x01}, +{0xEF76,0x01,0x01}, +{0xEF77,0x4E,0x01}, +{0xEF78,0x7B,0x01}, +{0xEF79,0x8C,0x01}, +{0xEF7A,0x53,0x01}, +{0xEF7B,0x19,0x01}, +{0xEF7C,0xB4,0x01}, +{0xEF7D,0x2C,0x01}, +{0xEF7E,0x45,0x01}, +{0xEF7F,0x28,0x01}, +{0xEF80,0x4B,0x01}, +{0xEF81,0x49,0x01}, +{0xEF82,0x8B,0x01}, +{0xEF83,0x66,0x01}, +{0xEF84,0xA0,0x01}, +{0xEF85,0xF3,0x01}, +{0xEF86,0x9A,0x01}, +{0xEF87,0xB9,0x01}, +{0xEF88,0x04,0x01}, +{0xEF89,0x45,0x01}, +{0xEF8A,0x24,0x01}, +{0xEF8B,0x16,0x01}, +{0xEF8C,0x09,0x01}, +{0xEF8D,0xC9,0x01}, +{0xEF8E,0x50,0x01}, +{0xEF8F,0xEC,0x01}, +{0xEF90,0x42,0x01}, +{0xEF91,0x1B,0x01}, +{0xEF92,0xD1,0x01}, +{0xEF93,0x88,0x01}, +{0xEF94,0xA5,0x01}, +{0xEF95,0x25,0x01}, +{0xEF96,0x0A,0x01}, +{0xEF97,0x01,0x01}, +{0xEF98,0x48,0x01}, +{0xEF99,0x43,0x01}, +{0xEF9A,0x60,0x01}, +{0xEF9B,0x32,0x01}, +{0xEF9C,0x96,0x01}, +{0xEF9D,0xD2,0x01}, +{0xEF9E,0x88,0x01}, +{0xEF9F,0x66,0x01}, +{0xEFA0,0x2C,0x01}, +{0xEFA1,0x2E,0x01}, +{0xEFA2,0x51,0x01}, +{0xEFA3,0x48,0x01}, +{0xEFA4,0x40,0x01}, +{0xEFA5,0x1C,0x01}, +{0xEFA6,0x12,0x01}, +{0xEFA7,0x93,0x01}, +{0xEFA8,0xB2,0x01}, +{0xEFA9,0xA4,0x01}, +{0xEFAA,0x86,0x01}, +{0xEFAB,0x36,0x01}, +{0xEFAC,0x77,0x01}, +{0xEFAD,0x19,0x01}, +{0xEFAE,0x4A,0x01}, +{0xEFAF,0x48,0x01}, +{0xEFB0,0x30,0x01}, +{0xEFB1,0x52,0x01}, +{0xEFB2,0x12,0x01}, +{0xEFB3,0xA3,0x01}, +{0xEFB4,0xE4,0x01}, +{0xEFB5,0x25,0x01}, +{0xEFB6,0x37,0x01}, +{0xEFB7,0xCF,0x01}, +{0xEFB8,0xD1,0x01}, +{0xEFB9,0xCC,0x01}, +{0xEFBA,0x5A,0x01}, +{0xEFBB,0x9A,0x01}, +{0xEFBC,0x52,0x01}, +{0xEFBD,0x14,0x01}, +{0xEFBE,0xA8,0x01}, +{0xEFBF,0xC0,0x01}, +{0xEFC0,0x05,0x01}, +{0xEFC1,0x34,0x01}, +{0xEFC2,0xD8,0x01}, +{0xEFC3,0x79,0x01}, +{0xEFC4,0xCF,0x01}, +{0xEFC5,0x71,0x01}, +{0xEFC6,0x42,0x01}, +{0xEFC7,0xA3,0x01}, +{0xEFC8,0x98,0x01}, +{0xEFC9,0xC0,0x01}, +{0xEFCA,0x30,0x01}, +{0xEFCB,0xA6,0x01}, +{0xEFCC,0x34,0x01}, +{0xEFCD,0xCA,0x01}, +{0xEFCE,0xB1,0x01}, +{0xEFCF,0x8F,0x01}, +{0xEFD0,0x81,0x01}, +{0xEFD1,0xE0,0x01}, +{0xEFD2,0x73,0x01}, +{0xEFD3,0x9D,0x01}, +{0xEFD4,0xE3,0x01}, +{0xEFD5,0x04,0x01}, +{0xEFD6,0x47,0x01}, +{0xEFD7,0x39,0x01}, +{0xEFD8,0xDB,0x01}, +{0xEFD9,0xA9,0x01}, +{0xEFDA,0x8F,0x01}, +{0xEFDB,0x83,0x01}, +{0xEFDC,0x06,0x01}, +{0xEFDD,0xE4,0x01}, +{0xEFDE,0xA0,0x01}, +{0xEFDF,0x03,0x01}, +{0xEFE0,0xFD,0x01}, +{0xEFE1,0xA7,0x01}, +{0xEFE2,0x3F,0x01}, +{0xEFE3,0x03,0x01}, +{0xEFE4,0x62,0x01}, +{0xEFE5,0x10,0x01}, +{0xEFE6,0x84,0x01}, +{0xEFE7,0x12,0x01}, +{0xEFE8,0x04,0x01}, +{0xEFE9,0x00,0x01}, +{0xEFEA,0x00,0x01}, +{0xEFEB,0x00,0x01}, +{0xEFEC,0x00,0x01}, +{0xEFED,0x00,0x01}, + + + +//SHD3 D65+TL84 C01// +{0xED00,0x9191,0x02},// +{0xEFEE,0x0B,0x01}, +{0xEFEF,0x12,0x01}, +{0xEFF0,0x11,0x01}, +{0xEFF1,0x88,0x01}, +{0xEFF2,0x2E,0x01}, +{0xEFF3,0x94,0x01}, +{0xEFF4,0x21,0x01}, +{0xEFF5,0x0E,0x01}, +{0xEFF6,0x99,0x01}, +{0xEFF7,0xE8,0x01}, +{0xEFF8,0x44,0x01}, +{0xEFF9,0x10,0x01}, +{0xEFFA,0x22,0x01}, +{0xEFFB,0x50,0x01}, +{0xEFFC,0x7C,0x01}, +{0xEFFD,0xB6,0x01}, +{0xEFFE,0xB3,0x01}, +{0xEFFF,0x1C,0x01}, +{0xF000,0xE3,0x01}, +{0xF001,0x38,0x01}, +{0xF002,0xC7,0x01}, +{0xF003,0x3B,0x01}, +{0xF004,0xF4,0x01}, +{0xF005,0x39,0x01}, +{0xF006,0x10,0x01}, +{0xF007,0x7A,0x01}, +{0xF008,0x8A,0x01}, +{0xF009,0x53,0x01}, +{0xF00A,0x9A,0x01}, +{0xF00B,0xC5,0x01}, +{0xF00C,0x0C,0x01}, +{0xF00D,0x86,0x01}, +{0xF00E,0x31,0x01}, +{0xF00F,0xA5,0x01}, +{0xF010,0x49,0x01}, +{0xF011,0xCE,0x01}, +{0xF012,0x7D,0x01}, +{0xF013,0x94,0x01}, +{0xF014,0xA3,0x01}, +{0xF015,0x19,0x01}, +{0xF016,0xB6,0x01}, +{0xF017,0x38,0x01}, +{0xF018,0xA5,0x01}, +{0xF019,0x28,0x01}, +{0xF01A,0x4F,0x01}, +{0xF01B,0x79,0x01}, +{0xF01C,0x8B,0x01}, +{0xF01D,0x68,0x01}, +{0xF01E,0xB4,0x01}, +{0xF01F,0x43,0x01}, +{0xF020,0x1B,0x01}, +{0xF021,0xBB,0x01}, +{0xF022,0x0C,0x01}, +{0xF023,0x45,0x01}, +{0xF024,0x24,0x01}, +{0xF025,0x17,0x01}, +{0xF026,0x19,0x01}, +{0xF027,0xC9,0x01}, +{0xF028,0x51,0x01}, +{0xF029,0xFA,0x01}, +{0xF02A,0xD2,0x01}, +{0xF02B,0x1B,0x01}, +{0xF02C,0xD3,0x01}, +{0xF02D,0x94,0x01}, +{0xF02E,0xC5,0x01}, +{0xF02F,0x25,0x01}, +{0xF030,0x0A,0x01}, +{0xF031,0x01,0x01}, +{0xF032,0x48,0x01}, +{0xF033,0x43,0x01}, +{0xF034,0x66,0x01}, +{0xF035,0x82,0x01}, +{0xF036,0x96,0x01}, +{0xF037,0xD6,0x01}, +{0xF038,0x98,0x01}, +{0xF039,0xC6,0x01}, +{0xF03A,0x2C,0x01}, +{0xF03B,0x2F,0x01}, +{0xF03C,0x51,0x01}, +{0xF03D,0x48,0x01}, +{0xF03E,0x40,0x01}, +{0xF03F,0x1E,0x01}, +{0xF040,0x42,0x01}, +{0xF041,0x13,0x01}, +{0xF042,0xB5,0x01}, +{0xF043,0xC8,0x01}, +{0xF044,0x06,0x01}, +{0xF045,0x37,0x01}, +{0xF046,0x7B,0x01}, +{0xF047,0x29,0x01}, +{0xF048,0x8A,0x01}, +{0xF049,0x48,0x01}, +{0xF04A,0x32,0x01}, +{0xF04B,0x72,0x01}, +{0xF04C,0x12,0x01}, +{0xF04D,0xA5,0x01}, +{0xF04E,0xFC,0x01}, +{0xF04F,0x65,0x01}, +{0xF050,0x38,0x01}, +{0xF051,0xD4,0x01}, +{0xF052,0xF9,0x01}, +{0xF053,0xCC,0x01}, +{0xF054,0x5B,0x01}, +{0xF055,0xA0,0x01}, +{0xF056,0x82,0x01}, +{0xF057,0x14,0x01}, +{0xF058,0xAA,0x01}, +{0xF059,0xD4,0x01}, +{0xF05A,0x05,0x01}, +{0xF05B,0x35,0x01}, +{0xF05C,0xE2,0x01}, +{0xF05D,0xA9,0x01}, +{0xF05E,0x4F,0x01}, +{0xF05F,0x73,0x01}, +{0xF060,0x4E,0x01}, +{0xF061,0xF3,0x01}, +{0xF062,0x18,0x01}, +{0xF063,0xC3,0x01}, +{0xF064,0x48,0x01}, +{0xF065,0xC6,0x01}, +{0xF066,0x35,0x01}, +{0xF067,0xD4,0x01}, +{0xF068,0x01,0x01}, +{0xF069,0xD0,0x01}, +{0xF06A,0x82,0x01}, +{0xF06B,0xEA,0x01}, +{0xF06C,0xD3,0x01}, +{0xF06D,0x1D,0x01}, +{0xF06E,0xE7,0x01}, +{0xF06F,0x24,0x01}, +{0xF070,0x47,0x01}, +{0xF071,0x3A,0x01}, +{0xF072,0xE5,0x01}, +{0xF073,0xF1,0x01}, +{0xF074,0x0F,0x01}, +{0xF075,0x86,0x01}, +{0xF076,0x0A,0x01}, +{0xF077,0x34,0x01}, +{0xF078,0xA1,0x01}, +{0xF079,0x06,0x01}, +{0xF07A,0x19,0x01}, +{0xF07B,0xE8,0x01}, +{0xF07C,0x40,0x01}, +{0xF07D,0x0D,0x01}, +{0xF07E,0xB2,0x01}, +{0xF07F,0x90,0x01}, +{0xF080,0x86,0x01}, +{0xF081,0x1C,0x01}, +{0xF082,0x04,0x01}, +{0xF083,0x00,0x01}, +{0xF084,0x00,0x01}, +{0xF085,0x00,0x01}, +{0xF086,0x00,0x01}, +{0xF087,0x00,0x01}, +{0xF088,0xBE,0x01}, +{0xF089,0x51,0x01}, +{0xF08A,0x4E,0x01}, +{0xF08B,0x6F,0x01}, +{0xF08C,0x6C,0x01}, +{0xF08D,0x43,0x01}, +{0xF08E,0x1B,0x01}, +{0xF08F,0xDA,0x01}, +{0xF090,0xEC,0x01}, +{0xF091,0x46,0x01}, +{0xF092,0x38,0x01}, +{0xF093,0xBB,0x01}, +{0xF094,0xC1,0x01}, +{0xF095,0xCD,0x01}, +{0xF096,0x69,0x01}, +{0xF097,0x26,0x01}, +{0xF098,0x93,0x01}, +{0xF099,0x98,0x01}, +{0xF09A,0xC1,0x01}, +{0xF09B,0x20,0x01}, +{0xF09C,0x26,0x01}, +{0xF09D,0x32,0x01}, +{0xF09E,0xA5,0x01}, +{0xF09F,0xB1,0x01}, +{0xF0A0,0x8D,0x01}, +{0xF0A1,0x67,0x01}, +{0xF0A2,0x0E,0x01}, +{0xF0A3,0x23,0x01}, +{0xF0A4,0x97,0x01}, +{0xF0A5,0xB0,0x01}, +{0xF0A6,0x6C,0x01}, +{0xF0A7,0x25,0x01}, +{0xF0A8,0x2C,0x01}, +{0xF0A9,0x71,0x01}, +{0xF0AA,0x41,0x01}, +{0xF0AB,0x0C,0x01}, +{0xF0AC,0x69,0x01}, +{0xF0AD,0x14,0x01}, +{0xF0AE,0xB3,0x01}, +{0xF0AF,0x96,0x01}, +{0xF0B0,0xA6,0x01}, +{0xF0B1,0xE8,0x01}, +{0xF0B2,0x64,0x01}, +{0xF0B3,0x26,0x01}, +{0xF0B4,0x3A,0x01}, +{0xF0B5,0x79,0x01}, +{0xF0B6,0x4A,0x01}, +{0xF0B7,0x5B,0x01}, +{0xF0B8,0x18,0x01}, +{0xF0B9,0xA3,0x01}, +{0xF0BA,0x97,0x01}, +{0xF0BB,0xA9,0x01}, +{0xF0BC,0xBC,0x01}, +{0xF0BD,0x24,0x01}, +{0xF0BE,0x23,0x01}, +{0xF0BF,0x13,0x01}, +{0xF0C0,0xE1,0x01}, +{0xF0C1,0xC8,0x01}, +{0xF0C2,0x4C,0x01}, +{0xF0C3,0xAA,0x01}, +{0xF0C4,0xA2,0x01}, +{0xF0C5,0x97,0x01}, +{0xF0C6,0xB6,0x01}, +{0xF0C7,0x14,0x01}, +{0xF0C8,0x05,0x01}, +{0xF0C9,0x24,0x01}, +{0xF0CA,0x06,0x01}, +{0xF0CB,0x09,0x01}, +{0xF0CC,0xC8,0x01}, +{0xF0CD,0x42,0x01}, +{0xF0CE,0x48,0x01}, +{0xF0CF,0x82,0x01}, +{0xF0D0,0x14,0x01}, +{0xF0D1,0xB8,0x01}, +{0xF0D2,0xC0,0x01}, +{0xF0D3,0xE5,0x01}, +{0xF0D4,0x28,0x01}, +{0xF0D5,0x21,0x01}, +{0xF0D6,0x39,0x01}, +{0xF0D7,0x08,0x01}, +{0xF0D8,0x40,0x01}, +{0xF0D9,0x14,0x01}, +{0xF0DA,0x62,0x01}, +{0xF0DB,0x92,0x01}, +{0xF0DC,0xA4,0x01}, +{0xF0DD,0xC4,0x01}, +{0xF0DE,0x05,0x01}, +{0xF0DF,0x30,0x01}, +{0xF0E0,0x58,0x01}, +{0xF0E1,0xA1,0x01}, +{0xF0E2,0x49,0x01}, +{0xF0E3,0x46,0x01}, +{0xF0E4,0x22,0x01}, +{0xF0E5,0xB2,0x01}, +{0xF0E6,0x91,0x01}, +{0xF0E7,0x9A,0x01}, +{0xF0E8,0x58,0x01}, +{0xF0E9,0xA5,0x01}, +{0xF0EA,0x2F,0x01}, +{0xF0EB,0x96,0x01}, +{0xF0EC,0x99,0x01}, +{0xF0ED,0x8B,0x01}, +{0xF0EE,0x54,0x01}, +{0xF0EF,0x74,0x01}, +{0xF0F0,0x32,0x01}, +{0xF0F1,0x13,0x01}, +{0xF0F2,0x9D,0x01}, +{0xF0F3,0x38,0x01}, +{0xF0F4,0xC5,0x01}, +{0xF0F5,0x2D,0x01}, +{0xF0F6,0x90,0x01}, +{0xF0F7,0x59,0x01}, +{0xF0F8,0x4D,0x01}, +{0xF0F9,0x64,0x01}, +{0xF0FA,0xEE,0x01}, +{0xF0FB,0x62,0x01}, +{0xF0FC,0x16,0x01}, +{0xF0FD,0xAE,0x01}, +{0xF0FE,0x84,0x01}, +{0xF0FF,0x25,0x01}, +{0xF100,0x2E,0x01}, +{0xF101,0x8B,0x01}, +{0xF102,0x31,0x01}, +{0xF103,0xCD,0x01}, +{0xF104,0x6F,0x01}, +{0xF105,0x60,0x01}, +{0xF106,0xC3,0x01}, +{0xF107,0x19,0x01}, +{0xF108,0xC7,0x01}, +{0xF109,0x14,0x01}, +{0xF10A,0x26,0x01}, +{0xF10B,0x31,0x01}, +{0xF10C,0x97,0x01}, +{0xF10D,0x41,0x01}, +{0xF10E,0x8D,0x01}, +{0xF10F,0x6D,0x01}, +{0xF110,0x86,0x01}, +{0xF111,0xE3,0x01}, +{0xF112,0x9C,0x01}, +{0xF113,0xE2,0x01}, +{0xF114,0xD8,0x01}, +{0xF115,0x06,0x01}, +{0xF116,0x36,0x01}, +{0xF117,0xB5,0x01}, +{0xF118,0xE9,0x01}, +{0xF119,0x4D,0x01}, +{0xF11A,0x70,0x01}, +{0xF11B,0x68,0x01}, +{0xF11C,0x03,0x01}, +{0xF11D,0x00,0x01}, +{0xF11E,0x00,0x01}, +{0xF11F,0x00,0x01}, +{0xF120,0x00,0x01}, +{0xF121,0x00,0x01}, + + +//SHD TH +{0x6C32,0x1964,0x02}, // SHD_INP_TH_HB_H_R2 +{0x6C34,0x18CE,0x02}, // SHD_INP_TH_HB_L_R2 +{0x6C36,0x10CC,0x02}, // SHD_INP_TH_LB_H_R2 +{0x6C38,0x1004,0x02}, // SHD_INP_TH_LB_L_R2 +{0x6C3C,0x10CC,0x02}, // SHD_INP_TH_HB_H_RB +{0x6C3E,0x1004,0x02}, // SHD_INP_TH_HB_L_RB +{0x6C40,0x0000,0x02}, // SHD_INP_TH_LB_H_RB +{0x6C42,0x0000,0x02}, // SHD_INP_TH_LB_L_RB + +//PreWB_offset (for SHD2) +{0x6828,0x0013,0x02}, // SHD_PRER_OFFSET_R2 : +//PreWB_offset (for SHD3) +{0x682C,0x000D,0x02}, // SHD_PRER_OFFSET_RB : +{0x6830,0xFFFE,0x02}, // SHD_PREB_OFFSET_RB : + +// CXC/SHD EN +{0x01BC,0x57,0x01}, // CXC ON SHD ON INP ON GAIN OFF +}; + +static const isx012_regset_t ISX012_Shading_2[] = +{ +{0x01BC,0x50,0x01}, // CXC OFF SHD OFF +{0xEB00,0x8282,0x02}, //valid_code +{0xEB02,0xFE,0x01}, +{0xEB03,0x84,0x01}, +{0xEB04,0x3F,0x01}, +{0xEB05,0x01,0x01}, +{0xEB06,0x50,0x01}, +{0xEB07,0x08,0x01}, +{0xEB08,0x14,0x01}, +{0xEB09,0xFF,0x01}, +{0xEB0A,0x45,0x01}, +{0xEB0B,0x80,0x01}, +{0xEB0C,0x01,0x01}, +{0xEB0D,0x68,0x01}, +{0xEB0E,0x04,0x01}, +{0xEB0F,0x1A,0x01}, +{0xEB10,0x81,0x01}, +{0xEB11,0x86,0x01}, +{0xEB12,0x3F,0x01}, +{0xEB13,0xE1,0x01}, +{0xEB14,0x4F,0x01}, +{0xEB15,0x00,0x01}, +{0xEB16,0x14,0x01}, +{0xEB17,0x02,0x01}, +{0xEB18,0xC5,0x01}, +{0xEB19,0x7F,0x01}, +{0xEB1A,0x11,0x01}, +{0xEB1B,0x60,0x01}, +{0xEB1C,0x00,0x01}, +{0xEB1D,0x1A,0x01}, +{0xEB1E,0x81,0x01}, +{0xEB1F,0x46,0x01}, +{0xEB20,0xA0,0x01}, +{0xEB21,0x01,0x01}, +{0xEB22,0x48,0x01}, +{0xEB23,0x00,0x01}, +{0xEB24,0x12,0x01}, +{0xEB25,0x81,0x01}, +{0xEB26,0x05,0x01}, +{0xEB27,0x20,0x01}, +{0xEB28,0xF1,0x01}, +{0xEB29,0x4F,0x01}, +{0xEB2A,0x00,0x01}, +{0xEB2B,0x14,0x01}, +{0xEB2C,0x82,0x01}, +{0xEB2D,0x85,0x01}, +{0xEB2E,0x80,0x01}, +{0xEB2F,0x21,0x01}, +{0xEB30,0x60,0x01}, +{0xEB31,0x04,0x01}, +{0xEB32,0x12,0x01}, +{0xEB33,0x81,0x01}, +{0xEB34,0x84,0x01}, +{0xEB35,0xE0,0x01}, +{0xEB36,0x00,0x01}, +{0xEB37,0x28,0x01}, +{0xEB38,0x04,0x01}, +{0xEB39,0x0C,0x01}, +{0xEB3A,0x82,0x01}, +{0xEB3B,0x43,0x01}, +{0xEB3C,0x20,0x01}, +{0xEB3D,0x11,0x01}, +{0xEB3E,0x68,0x01}, +{0xEB3F,0x04,0x01}, +{0xEB40,0x1A,0x01}, +{0xEB41,0x82,0x01}, +{0xEB42,0x83,0x01}, +{0xEB43,0xE0,0x01}, +{0xEB44,0x00,0x01}, +{0xEB45,0x20,0x01}, +{0xEB46,0x00,0x01}, +{0xEB47,0x06,0x01}, +{0xEB48,0xFF,0x01}, +{0xEB49,0x41,0x01}, +{0xEB4A,0x80,0x01}, +{0xEB4B,0x10,0x01}, +{0xEB4C,0x30,0x01}, +{0xEB4D,0x08,0x01}, +{0xEB4E,0x14,0x01}, +{0xEB4F,0x02,0x01}, +{0xEB50,0x45,0x01}, +{0xEB51,0xC0,0x01}, +{0xEB52,0x10,0x01}, +{0xEB53,0x30,0x01}, +{0xEB54,0x04,0x01}, +{0xEB55,0x04,0x01}, +{0xEB56,0x01,0x01}, +{0xEB57,0xC0,0x01}, +{0xEB58,0x3F,0x01}, +{0xEB59,0x10,0x01}, +{0xEB5A,0x10,0x01}, +{0xEB5B,0x04,0x01}, +{0xEB5C,0x0A,0x01}, +{0xEB5D,0x80,0x01}, +{0xEB5E,0x03,0x01}, +{0xEB5F,0xE0,0x01}, +{0xEB60,0x10,0x01}, +{0xEB61,0x28,0x01}, +{0xEB62,0x04,0x01}, +{0xEB63,0x0A,0x01}, +{0xEB64,0x81,0x01}, +{0xEB65,0x01,0x01}, +{0xEB66,0x00,0x01}, +{0xEB67,0x10,0x01}, +{0xEB68,0x00,0x01}, +{0xEB69,0x04,0x01}, +{0xEB6A,0x04,0x01}, +{0xEB6B,0x01,0x01}, +{0xEB6C,0x42,0x01}, +{0xEB6D,0xE0,0x01}, +{0xEB6E,0x10,0x01}, +{0xEB6F,0x38,0x01}, +{0xEB70,0xFC,0x01}, +{0xEB71,0x0D,0x01}, +{0xEB72,0x7F,0x01}, +{0xEB73,0x43,0x01}, +{0xEB74,0x60,0x01}, +{0xEB75,0x00,0x01}, +{0xEB76,0x08,0x01}, +{0xEB77,0x08,0x01}, +{0xEB78,0x02,0x01}, +{0xEB79,0x81,0x01}, +{0xEB7A,0x41,0x01}, +{0xEB7B,0x80,0x01}, +{0xEB7C,0x10,0x01}, +{0xEB7D,0x30,0x01}, +{0xEB7E,0x04,0x01}, +{0xEB7F,0x0C,0x01}, +{0xEB80,0x01,0x01}, +{0xEB81,0x43,0x01}, +{0xEB82,0xC0,0x01}, +{0xEB83,0x20,0x01}, +{0xEB84,0x28,0x01}, +{0xEB85,0x08,0x01}, +{0xEB86,0x06,0x01}, +{0xEB87,0x02,0x01}, +{0xEB88,0xC2,0x01}, +{0xEB89,0xA0,0x01}, +{0xEB8A,0x30,0x01}, +{0xEB8B,0x30,0x01}, +{0xEB8C,0x0C,0x01}, +{0xEB8D,0x12,0x01}, +{0xEB8E,0x83,0x01}, +{0xEB8F,0x84,0x01}, +{0xEB90,0x00,0x01}, +{0xEB91,0x21,0x01}, +{0xEB92,0x40,0x01}, +{0xEB93,0x0C,0x01}, +{0xEB94,0x0C,0x01}, +{0xEB95,0x82,0x01}, +{0xEB96,0x03,0x01}, +{0xEB97,0xC1,0x01}, +{0xEB98,0x40,0x01}, +{0xEB99,0x40,0x01}, +{0xEB9A,0x08,0x01}, +{0xEB9B,0x10,0x01}, +{0xEB9C,0x03,0x01}, +{0xEB9D,0xC4,0x01}, +{0xEB9E,0x00,0x01}, +{0xEB9F,0x21,0x01}, +{0xEBA0,0x38,0x01}, +{0xEBA1,0x08,0x01}, +{0xEBA2,0x0E,0x01}, +{0xEBA3,0x82,0x01}, +{0xEBA4,0xC3,0x01}, +{0xEBA5,0x20,0x01}, +{0xEBA6,0x41,0x01}, +{0xEBA7,0x48,0x01}, +{0xEBA8,0x00,0x01}, +{0xEBA9,0x14,0x01}, +{0xEBAA,0x83,0x01}, +{0xEBAB,0x44,0x01}, +{0xEBAC,0x20,0x01}, +{0xEBAD,0x11,0x01}, +{0xEBAE,0x48,0x01}, +{0xEBAF,0x08,0x01}, +{0xEBB0,0x0E,0x01}, +{0xEBB1,0x82,0x01}, +{0xEBB2,0x83,0x01}, +{0xEBB3,0xE0,0x01}, +{0xEBB4,0x30,0x01}, +{0xEBB5,0x48,0x01}, +{0xEBB6,0x10,0x01}, +{0xEBB7,0x12,0x01}, +{0xEBB8,0x00,0x01}, +{0xEBB9,0xC5,0x01}, +{0xEBBA,0x20,0x01}, +{0xEBBB,0x11,0x01}, +{0xEBBC,0x48,0x01}, +{0xEBBD,0x04,0x01}, +{0xEBBE,0x12,0x01}, +{0xEBBF,0x04,0x01}, +{0xEBC0,0x3B,0x01}, +{0xEBC1,0xC1,0x01}, +{0xEBC2,0x1E,0x01}, +{0xEBC3,0xC8,0x01}, +{0xEBC4,0x0F,0x01}, +{0xEBC5,0xF8,0x01}, +{0xEBC6,0x02,0x01}, +{0xEBC7,0xBB,0x01}, +{0xEBC8,0x60,0x01}, +{0xEBC9,0x0F,0x01}, +{0xEBCA,0xB8,0x01}, +{0xEBCB,0x0F,0x01}, +{0xEBCC,0xEA,0x01}, +{0xEBCD,0x83,0x01}, +{0xEBCE,0x3A,0x01}, +{0xEBCF,0xC1,0x01}, +{0xEBD0,0x4E,0x01}, +{0xEBD1,0xB0,0x01}, +{0xEBD2,0x07,0x01}, +{0xEBD3,0xF2,0x01}, +{0xEBD4,0x03,0x01}, +{0xEBD5,0xBE,0x01}, +{0xEBD6,0xC0,0x01}, +{0xEBD7,0x2E,0x01}, +{0xEBD8,0xD8,0x01}, +{0xEBD9,0x03,0x01}, +{0xEBDA,0xEE,0x01}, +{0xEBDB,0x83,0x01}, +{0xEBDC,0xFA,0x01}, +{0xEBDD,0xA0,0x01}, +{0xEBDE,0x2E,0x01}, +{0xEBDF,0xB0,0x01}, +{0xEBE0,0x0B,0x01}, +{0xEBE1,0xEC,0x01}, +{0xEBE2,0x05,0x01}, +{0xEBE3,0xBD,0x01}, +{0xEBE4,0x60,0x01}, +{0xEBE5,0x2F,0x01}, +{0xEBE6,0xD0,0x01}, +{0xEBE7,0x07,0x01}, +{0xEBE8,0xEC,0x01}, +{0xEBE9,0x02,0x01}, +{0xEBEA,0xBC,0x01}, +{0xEBEB,0x40,0x01}, +{0xEBEC,0x2F,0x01}, +{0xEBED,0xD0,0x01}, +{0xEBEE,0x13,0x01}, +{0xEBEF,0xEE,0x01}, +{0xEBF0,0x84,0x01}, +{0xEBF1,0xBB,0x01}, +{0xEBF2,0x00,0x01}, +{0xEBF3,0x1F,0x01}, +{0xEBF4,0xC8,0x01}, +{0xEBF5,0xFF,0x01}, +{0xEBF6,0xEF,0x01}, +{0xEBF7,0x00,0x01}, +{0xEBF8,0x7D,0x01}, +{0xEBF9,0x60,0x01}, +{0xEBFA,0x2F,0x01}, +{0xEBFB,0xD0,0x01}, +{0xEBFC,0x0B,0x01}, +{0xEBFD,0xF4,0x01}, +{0xEBFE,0x85,0x01}, +{0xEBFF,0x7D,0x01}, +{0xEC00,0x61,0x01}, +{0xEC01,0x0F,0x01}, +{0xEC02,0xC0,0x01}, +{0xEC03,0xFF,0x01}, +{0xEC04,0xF7,0x01}, +{0xEC05,0x7F,0x01}, +{0xEC06,0x3D,0x01}, +{0xEC07,0x40,0x01}, +{0xEC08,0xFF,0x01}, +{0xEC09,0xDF,0x01}, +{0xEC0A,0x07,0x01}, +{0xEC0B,0xFA,0x01}, +{0xEC0C,0x81,0x01}, +{0xEC0D,0x3E,0x01}, +{0xEC0E,0x61,0x01}, +{0xEC0F,0x4F,0x01}, +{0xEC10,0xD8,0x01}, +{0xEC11,0x0B,0x01}, +{0xEC12,0xFC,0x01}, +{0xEC13,0xFE,0x01}, +{0xEC14,0x3D,0x01}, +{0xEC15,0xC0,0x01}, +{0xEC16,0xFF,0x01}, +{0xEC17,0xFF,0x01}, +{0xEC18,0x03,0x01}, +{0xEC19,0xFC,0x01}, +{0xEC1A,0x82,0x01}, +{0xEC1B,0xBE,0x01}, +{0xEC1C,0xA0,0x01}, +{0xEC1D,0x6F,0x01}, +{0xEC1E,0xF8,0x01}, +{0xEC1F,0x1B,0x01}, +{0xEC20,0xFE,0x01}, +{0xEC21,0x83,0x01}, +{0xEC22,0xBF,0x01}, +{0xEC23,0xE0,0x01}, +{0xEC24,0x0F,0x01}, +{0xEC25,0x10,0x01}, +{0xEC26,0x00,0x01}, +{0xEC27,0x00,0x01}, +{0xEC28,0x82,0x01}, +{0xEC29,0xC0,0x01}, +{0xEC2A,0x60,0x01}, +{0xEC2B,0x30,0x01}, +{0xEC2C,0x18,0x01}, +{0xEC2D,0x20,0x01}, +{0xEC2E,0x04,0x01}, +{0xEC2F,0x08,0x01}, +{0xEC30,0x81,0x01}, +{0xEC31,0x21,0x01}, +{0xEC32,0x30,0x01}, +{0xEC33,0x08,0x01}, +{0xEC34,0x08,0x01}, +{0xEC35,0x08,0x01}, +{0xEC36,0x82,0x01}, +{0xEC37,0x01,0x01}, +{0xEC38,0x81,0x01}, +{0xEC39,0x50,0x01}, +{0xEC3A,0x08,0x01}, +{0xEC3B,0x14,0x01}, +{0xEC3C,0x02,0x01}, +{0xEC3D,0x09,0x01}, +{0xEC3E,0x41,0x01}, +{0xEC3F,0x42,0x01}, +{0xEC40,0x70,0x01}, +{0xEC41,0x20,0x01}, +{0xEC42,0x0C,0x01}, +{0xEC43,0x06,0x01}, +{0xEC44,0x84,0x01}, +{0xEC45,0x42,0x01}, +{0xEC46,0xE1,0x01}, +{0xEC47,0x40,0x01}, +{0xEC48,0x38,0x01}, +{0xEC49,0x1C,0x01}, +{0xEC4A,0x0C,0x01}, +{0xEC4B,0x07,0x01}, +{0xEC4C,0x03,0x01}, +{0xEC4D,0xA2,0x01}, +{0xEC4E,0x80,0x01}, +{0xEC4F,0x28,0x01}, +{0xEC50,0x18,0x01}, +{0xEC51,0x10,0x01}, +{0xEC52,0x87,0x01}, +{0xEC53,0x43,0x01}, +{0xEC54,0x61,0x01}, +{0xEC55,0x41,0x01}, +{0xEC56,0x48,0x01}, +{0xEC57,0x14,0x01}, +{0xEC58,0x10,0x01}, +{0xEC59,0x07,0x01}, +{0xEC5A,0xC2,0x01}, +{0xEC5B,0x81,0x01}, +{0xEC5C,0x80,0x01}, +{0xEC5D,0x30,0x01}, +{0xEC5E,0x20,0x01}, +{0xEC5F,0x0C,0x01}, +{0xEC60,0x87,0x01}, +{0xEC61,0x83,0x01}, +{0xEC62,0xC1,0x01}, +{0xEC63,0x40,0x01}, +{0xEC64,0x38,0x01}, +{0xEC65,0x14,0x01}, +{0xEC66,0x0A,0x01}, +{0xEC67,0x07,0x01}, +{0xEC68,0xC3,0x01}, +{0xEC69,0xC1,0x01}, +{0xEC6A,0x70,0x01}, +{0xEC6B,0x30,0x01}, +{0xEC6C,0x20,0x01}, +{0xEC6D,0x0C,0x01}, +{0xEC6E,0x08,0x01}, +{0xEC6F,0xC3,0x01}, +{0xEC70,0xE1,0x01}, +{0xEC71,0x60,0x01}, +{0xEC72,0x30,0x01}, +{0xEC73,0x10,0x01}, +{0xEC74,0x0E,0x01}, +{0xEC75,0x85,0x01}, +{0xEC76,0xC2,0x01}, +{0xEC77,0xC1,0x01}, +{0xEC78,0x70,0x01}, +{0xEC79,0x30,0x01}, +{0xEC7A,0x1C,0x01}, +{0xEC7B,0x0C,0x01}, + +//SHD1(from CO1) +{0xED02,0xE6,0x01}, +{0xED03,0xD9,0x01}, +{0xED04,0x92,0x01}, +{0xED05,0x7C,0x01}, +{0xED06,0xD8,0x01}, +{0xED07,0xB4,0x01}, +{0xED08,0x1E,0x01}, +{0xED09,0x32,0x01}, +{0xED0A,0x75,0x01}, +{0xED0B,0x67,0x01}, +{0xED0C,0x4A,0x01}, +{0xED0D,0xD7,0x01}, +{0xED0E,0xA9,0x01}, +{0xED0F,0x12,0x01}, +{0xED10,0x76,0x01}, +{0xED11,0xBC,0x01}, +{0xED12,0x34,0x01}, +{0xED13,0x1E,0x01}, +{0xED14,0x37,0x01}, +{0xED15,0xA1,0x01}, +{0xED16,0x87,0x01}, +{0xED17,0x4E,0x01}, +{0xED18,0xDE,0x01}, +{0xED19,0x41,0x01}, +{0xED1A,0xD3,0x01}, +{0xED1B,0x77,0x01}, +{0xED1C,0x8C,0x01}, +{0xED1D,0x94,0x01}, +{0xED1E,0x9C,0x01}, +{0xED1F,0x14,0x01}, +{0xED20,0xC9,0x01}, +{0xED21,0xA6,0x01}, +{0xED22,0x41,0x01}, +{0xED23,0xA2,0x01}, +{0xED24,0xC1,0x01}, +{0xED25,0x8F,0x01}, +{0xED26,0x66,0x01}, +{0xED27,0xE6,0x01}, +{0xED28,0xF3,0x01}, +{0xED29,0x19,0x01}, +{0xED2A,0xFF,0x01}, +{0xED2B,0xB0,0x01}, +{0xED2C,0x66,0x01}, +{0xED2D,0x42,0x01}, +{0xED2E,0xC1,0x01}, +{0xED2F,0x91,0x01}, +{0xED30,0x91,0x01}, +{0xED31,0x75,0x01}, +{0xED32,0xA2,0x01}, +{0xED33,0x74,0x01}, +{0xED34,0x1C,0x01}, +{0xED35,0x0F,0x01}, +{0xED36,0x91,0x01}, +{0xED37,0x26,0x01}, +{0xED38,0x3E,0x01}, +{0xED39,0x87,0x01}, +{0xED3A,0x51,0x01}, +{0xED3B,0x4E,0x01}, +{0xED3C,0x5C,0x01}, +{0xED3D,0x54,0x01}, +{0xED3E,0x83,0x01}, +{0xED3F,0x96,0x01}, +{0xED40,0xD0,0x01}, +{0xED41,0xBC,0x01}, +{0xED42,0xA5,0x01}, +{0xED43,0x35,0x01}, +{0xED44,0x83,0x01}, +{0xED45,0x61,0x01}, +{0xED46,0xCE,0x01}, +{0xED47,0x67,0x01}, +{0xED48,0xF2,0x01}, +{0xED49,0x33,0x01}, +{0xED4A,0x1C,0x01}, +{0xED4B,0x1A,0x01}, +{0xED4C,0xC1,0x01}, +{0xED4D,0x46,0x01}, +{0xED4E,0x3F,0x01}, +{0xED4F,0x83,0x01}, +{0xED50,0xD9,0x01}, +{0xED51,0x0D,0x01}, +{0xED52,0x57,0x01}, +{0xED53,0x06,0x01}, +{0xED54,0x23,0x01}, +{0xED55,0x14,0x01}, +{0xED56,0xAF,0x01}, +{0xED57,0xE4,0x01}, +{0xED58,0x64,0x01}, +{0xED59,0x2A,0x01}, +{0xED5A,0x43,0x01}, +{0xED5B,0x01,0x01}, +{0xED5C,0xCB,0x01}, +{0xED5D,0x56,0x01}, +{0xED5E,0x10,0x01}, +{0xED5F,0x03,0x01}, +{0xED60,0x18,0x01}, +{0xED61,0xE4,0x01}, +{0xED62,0xA8,0x01}, +{0xED63,0xE6,0x01}, +{0xED64,0x41,0x01}, +{0xED65,0x9E,0x01}, +{0xED66,0xE1,0x01}, +{0xED67,0xCE,0x01}, +{0xED68,0x59,0x01}, +{0xED69,0x20,0x01}, +{0xED6A,0xB3,0x01}, +{0xED6B,0x13,0x01}, +{0xED6C,0xA8,0x01}, +{0xED6D,0x74,0x01}, +{0xED6E,0x04,0x01}, +{0xED6F,0x25,0x01}, +{0xED70,0x13,0x01}, +{0xED71,0xE1,0x01}, +{0xED72,0xC8,0x01}, +{0xED73,0x47,0x01}, +{0xED74,0x56,0x01}, +{0xED75,0xD2,0x01}, +{0xED76,0x13,0x01}, +{0xED77,0xAB,0x01}, +{0xED78,0x98,0x01}, +{0xED79,0x25,0x01}, +{0xED7A,0x33,0x01}, +{0xED7B,0x9A,0x01}, +{0xED7C,0x49,0x01}, +{0xED7D,0xCF,0x01}, +{0xED7E,0x64,0x01}, +{0xED7F,0x96,0x01}, +{0xED80,0x73,0x01}, +{0xED81,0x95,0x01}, +{0xED82,0xBC,0x01}, +{0xED83,0xA4,0x01}, +{0xED84,0xC4,0x01}, +{0xED85,0x26,0x01}, +{0xED86,0x0A,0x01}, +{0xED87,0x59,0x01}, +{0xED88,0x08,0x01}, +{0xED89,0x40,0x01}, +{0xED8A,0x00,0x01}, +{0xED8B,0xC2,0x01}, +{0xED8C,0x10,0x01}, +{0xED8D,0x88,0x01}, +{0xED8E,0xB0,0x01}, +{0xED8F,0xA4,0x01}, +{0xED90,0x27,0x01}, +{0xED91,0x59,0x01}, +{0xED92,0xF9,0x01}, +{0xED93,0x0B,0x01}, +{0xED94,0x64,0x01}, +{0xED95,0xA8,0x01}, +{0xED96,0x43,0x01}, +{0xED97,0x19,0x01}, +{0xED98,0xE6,0x01}, +{0xED99,0x68,0x01}, +{0xED9A,0x45,0x01}, +{0xED9B,0x2F,0x01}, +{0xED9C,0x2B,0x01}, +{0xED9D,0xB9,0x01}, +{0xED9E,0xC9,0x01}, +{0xED9F,0x42,0x01}, +{0xEDA0,0x18,0x01}, +{0xEDA1,0x32,0x01}, +{0xEDA2,0x90,0x01}, +{0xEDA3,0x80,0x01}, +{0xEDA4,0x3C,0x01}, +{0xEDA5,0x44,0x01}, +{0xEDA6,0x22,0x01}, +{0xEDA7,0x2F,0x01}, +{0xEDA8,0xF1,0x01}, +{0xEDA9,0x09,0x01}, +{0xEDAA,0x57,0x01}, +{0xEDAB,0x04,0x01}, +{0xEDAC,0x53,0x01}, +{0xEDAD,0x99,0x01}, +{0xEDAE,0xEC,0x01}, +{0xEDAF,0x90,0x01}, +{0xEDB0,0x66,0x01}, +{0xEDB1,0x3C,0x01}, +{0xEDB2,0x6D,0x01}, +{0xEDB3,0xA9,0x01}, +{0xEDB4,0x4C,0x01}, +{0xEDB5,0x50,0x01}, +{0xEDB6,0xA6,0x01}, +{0xEDB7,0x32,0x01}, +{0xEDB8,0x12,0x01}, +{0xEDB9,0x94,0x01}, +{0xEDBA,0x64,0x01}, +{0xEDBB,0xA4,0x01}, +{0xEDBC,0x23,0x01}, +{0xEDBD,0x25,0x01}, +{0xEDBE,0x71,0x01}, +{0xEDBF,0x49,0x01}, +{0xEDC0,0x51,0x01}, +{0xEDC1,0xB4,0x01}, +{0xEDC2,0x02,0x01}, +{0xEDC3,0x17,0x01}, +{0xEDC4,0xCE,0x01}, +{0xEDC5,0x98,0x01}, +{0xEDC6,0x06,0x01}, +{0xEDC7,0x3E,0x01}, +{0xEDC8,0xBC,0x01}, +{0xEDC9,0x31,0x01}, +{0xEDCA,0x50,0x01}, +{0xEDCB,0x63,0x01}, +{0xEDCC,0x86,0x01}, +{0xEDCD,0x63,0x01}, +{0xEDCE,0x16,0x01}, +{0xEDCF,0xC4,0x01}, +{0xEDD0,0x2C,0x01}, +{0xEDD1,0x45,0x01}, +{0xEDD2,0x2C,0x01}, +{0xEDD3,0x43,0x01}, +{0xEDD4,0xB9,0x01}, +{0xEDD5,0x4A,0x01}, +{0xEDD6,0x53,0x01}, +{0xEDD7,0xCE,0x01}, +{0xEDD8,0x82,0x01}, +{0xEDD9,0x96,0x01}, +{0xEDDA,0xC8,0x01}, +{0xEDDB,0x40,0x01}, +{0xEDDC,0x06,0x01}, +{0xEDDD,0x3A,0x01}, +{0xEDDE,0xBE,0x01}, +{0xEDDF,0xC1,0x01}, +{0xEDE0,0xD0,0x01}, +{0xEDE1,0x75,0x01}, +{0xEDE2,0x64,0x01}, +{0xEDE3,0x34,0x01}, +{0xEDE4,0x9B,0x01}, +{0xEDE5,0xFE,0x01}, +{0xEDE6,0x4C,0x01}, +{0xEDE7,0xA6,0x01}, +{0xEDE8,0x39,0x01}, +{0xEDE9,0x7D,0x01}, +{0xEDEA,0x89,0x01}, +{0xEDEB,0x8D,0x01}, +{0xEDEC,0x5D,0x01}, +{0xEDED,0x4A,0x01}, +{0xEDEE,0xE3,0x01}, +{0xEDEF,0x97,0x01}, +{0xEDF0,0xDA,0x01}, +{0xEDF1,0x50,0x01}, +{0xEDF2,0xE6,0x01}, +{0xEDF3,0x3A,0x01}, +{0xEDF4,0xB3,0x01}, +{0xEDF5,0x39,0x01}, +{0xEDF6,0x50,0x01}, +{0xEDF7,0x76,0x01}, +{0xEDF8,0x7A,0x01}, +{0xEDF9,0xF4,0x01}, +{0xEDFA,0x9E,0x01}, +{0xEDFB,0x2A,0x01}, +{0xEDFC,0x61,0x01}, +{0xEDFD,0x87,0x01}, +{0xEDFE,0x46,0x01}, +{0xEDFF,0xC0,0x01}, +{0xEE00,0x99,0x01}, +{0xEE01,0xD0,0x01}, +{0xEE02,0x6B,0x01}, +{0xEE03,0x02,0x01}, +{0xEE04,0x94,0x01}, +{0xEE05,0x1A,0x01}, +{0xEE06,0xFD,0x01}, +{0xEE07,0xB8,0x01}, +{0xEE08,0xE6,0x01}, +{0xEE09,0x40,0x01}, +{0xEE0A,0xC0,0x01}, +{0xEE0B,0xF1,0x01}, +{0xEE0C,0xD0,0x01}, +{0xEE0D,0x75,0x01}, +{0xEE0E,0x80,0x01}, +{0xEE0F,0xE4,0x01}, +{0xEE10,0x9E,0x01}, +{0xEE11,0x33,0x01}, +{0xEE12,0xE1,0x01}, +{0xEE13,0xA7,0x01}, +{0xEE14,0x4B,0x01}, +{0xEE15,0xFD,0x01}, +{0xEE16,0x21,0x01}, +{0xEE17,0x53,0x01}, +{0xEE18,0x7C,0x01}, +{0xEE19,0xAE,0x01}, +{0xEE1A,0x64,0x01}, +{0xEE1B,0x9E,0x01}, +{0xEE1C,0x26,0x01}, +{0xEE1D,0x89,0x01}, +{0xEE1E,0xC7,0x01}, +{0xEE1F,0x49,0x01}, +{0xEE20,0xE4,0x01}, +{0xEE21,0x99,0x01}, +{0xEE22,0x12,0x01}, +{0xEE23,0x7D,0x01}, +{0xEE24,0xCA,0x01}, +{0xEE25,0xB4,0x01}, +{0xEE26,0x9F,0x01}, +{0xEE27,0x37,0x01}, +{0xEE28,0xC5,0x01}, +{0xEE29,0x47,0x01}, +{0xEE2A,0x4D,0x01}, +{0xEE2B,0xC2,0x01}, +{0xEE2C,0x19,0x01}, +{0xEE2D,0x0F,0x01}, +{0xEE2E,0x73,0x01}, +{0xEE2F,0xE2,0x01}, +{0xEE30,0x13,0x01}, +{0xEE31,0x1C,0x01}, +{0xEE32,0xF5,0x01}, +{0xEE33,0xE0,0x01}, +{0xEE34,0xC6,0x01}, +{0xEE35,0x3B,0x01}, +{0xEE36,0xB6,0x01}, +{0xEE37,0xB1,0x01}, +{0xEE38,0xCE,0x01}, +{0xEE39,0x6D,0x01}, +{0xEE3A,0xB8,0x01}, +{0xEE3B,0xF3,0x01}, +{0xEE3C,0x9B,0x01}, +{0xEE3D,0xF2,0x01}, +{0xEE3E,0x18,0x01}, +{0xEE3F,0x27,0x01}, +{0xEE40,0x3D,0x01}, +{0xEE41,0xBF,0x01}, +{0xEE42,0xE9,0x01}, +{0xEE43,0xCE,0x01}, +{0xEE44,0x6E,0x01}, +{0xEE45,0xBA,0x01}, +{0xEE46,0x83,0x01}, +{0xEE47,0x9A,0x01}, +{0xEE48,0xE4,0x01}, +{0xEE49,0x50,0x01}, +{0xEE4A,0x66,0x01}, +{0xEE4B,0x36,0x01}, +{0xEE4C,0x8A,0x01}, +{0xEE4D,0x29,0x01}, +{0xEE4E,0x4D,0x01}, +{0xEE4F,0x61,0x01}, +{0xEE50,0x3A,0x01}, +{0xEE51,0xA3,0x01}, +{0xEE52,0x18,0x01}, +{0xEE53,0xD2,0x01}, +{0xEE54,0x50,0x01}, +{0xEE55,0x26,0x01}, +{0xEE56,0x36,0x01}, +{0xEE57,0xA8,0x01}, +{0xEE58,0x21,0x01}, +{0xEE59,0xCE,0x01}, +{0xEE5A,0x6E,0x01}, +{0xEE5B,0xB2,0x01}, +{0xEE5C,0x03,0x01}, +{0xEE5D,0x9A,0x01}, +{0xEE5E,0xE0,0x01}, +{0xEE5F,0x1C,0x01}, +{0xEE60,0x46,0x01}, +{0xEE61,0x34,0x01}, +{0xEE62,0x72,0x01}, +{0xEE63,0x41,0x01}, +{0xEE64,0x8C,0x01}, +{0xEE65,0x58,0x01}, +{0xEE66,0xE8,0x01}, +{0xEE67,0xC2,0x01}, +{0xEE68,0x95,0x01}, +{0xEE69,0xB5,0x01}, +{0xEE6A,0x88,0x01}, +{0xEE6B,0x65,0x01}, +{0xEE6C,0x2E,0x01}, +{0xEE6D,0x72,0x01}, +{0xEE6E,0x39,0x01}, +{0xEE6F,0x8C,0x01}, +{0xEE70,0x62,0x01}, +{0xEE71,0x48,0x01}, +{0xEE72,0x83,0x01}, +{0xEE73,0x1A,0x01}, +{0xEE74,0xE4,0x01}, +{0xEE75,0x28,0x01}, +{0xEE76,0x06,0x01}, +{0xEE77,0x35,0x01}, +{0xEE78,0x6A,0x01}, +{0xEE79,0xF9,0x01}, +{0xEE7A,0x4B,0x01}, +{0xEE7B,0x53,0x01}, +{0xEE7C,0xB8,0x01}, +{0xEE7D,0x92,0x01}, +{0xEE7E,0x13,0x01}, +{0xEE7F,0xA2,0x01}, +{0xEE80,0xCC,0x01}, +{0xEE81,0x64,0x01}, +{0xEE82,0x27,0x01}, +{0xEE83,0x3B,0x01}, +{0xEE84,0x29,0x01}, +{0xEE85,0x0A,0x01}, +{0xEE86,0x54,0x01}, +{0xEE87,0xBC,0x01}, +{0xEE88,0xF2,0x01}, +{0xEE89,0x96,0x01}, +{0xEE8A,0xC1,0x01}, +{0xEE8B,0x40,0x01}, +{0xEE8C,0xA6,0x01}, +{0xEE8D,0x35,0x01}, +{0xEE8E,0x7A,0x01}, +{0xEE8F,0xB1,0x01}, +{0xEE90,0x8C,0x01}, +{0xEE91,0x54,0x01}, +{0xEE92,0xC8,0x01}, +{0xEE93,0xF2,0x01}, +{0xEE94,0x92,0x01}, +{0xEE95,0x9D,0x01}, +{0xEE96,0x64,0x01}, +{0xEE97,0xE4,0x01}, +{0xEE98,0x23,0x01}, +{0xEE99,0x13,0x01}, +{0xEE9A,0xA9,0x01}, +{0xEE9B,0x48,0x01}, +{0xEE9C,0x47,0x01}, +{0xEE9D,0x40,0x01}, +{0xEE9E,0x42,0x01}, +{0xEE9F,0x13,0x01}, +{0xEEA0,0x9F,0x01}, +{0xEEA1,0x58,0x01}, +{0xEEA2,0xE5,0x01}, +{0xEEA3,0x2C,0x01}, +{0xEEA4,0x7F,0x01}, +{0xEEA5,0xD9,0x01}, +{0xEEA6,0x8C,0x01}, +{0xEEA7,0x5B,0x01}, +{0xEEA8,0x12,0x01}, +{0xEEA9,0x43,0x01}, +{0xEEAA,0x14,0x01}, +{0xEEAB,0xAA,0x01}, +{0xEEAC,0x80,0x01}, +{0xEEAD,0x04,0x01}, +{0xEEAE,0x25,0x01}, +{0xEEAF,0x06,0x01}, +{0xEEB0,0x51,0x01}, +{0xEEB1,0x08,0x01}, +{0xEEB2,0x40,0x01}, +{0xEEB3,0x00,0x01}, +{0xEEB4,0xB2,0x01}, +{0xEEB5,0x10,0x01}, +{0xEEB6,0x86,0x01}, +{0xEEB7,0x98,0x01}, +{0xEEB8,0x64,0x01}, +{0xEEB9,0x25,0x01}, +{0xEEBA,0x4A,0x01}, +{0xEEBB,0xB9,0x01}, +{0xEEBC,0x0A,0x01}, +{0xEEBD,0x5D,0x01}, +{0xEEBE,0x1C,0x01}, +{0xEEBF,0x13,0x01}, +{0xEEC0,0x97,0x01}, +{0xEEC1,0xC4,0x01}, +{0xEEC2,0x18,0x01}, +{0xEEC3,0x85,0x01}, +{0xEEC4,0x2A,0x01}, +{0xEEC5,0x21,0x01}, +{0xEEC6,0x41,0x01}, +{0xEEC7,0xC9,0x01}, +{0xEEC8,0x41,0x01}, +{0xEEC9,0x12,0x01}, +{0xEECA,0x02,0x01}, +{0xEECB,0x10,0x01}, +{0xEECC,0x80,0x01}, +{0xEECD,0x2C,0x01}, +{0xEECE,0x64,0x01}, +{0xEECF,0x21,0x01}, +{0xEED0,0x27,0x01}, +{0xEED1,0x61,0x01}, +{0xEED2,0xC9,0x01}, +{0xEED3,0x52,0x01}, +{0xEED4,0xB0,0x01}, +{0xEED5,0x42,0x01}, +{0xEED6,0x17,0x01}, +{0xEED7,0xC8,0x01}, +{0xEED8,0x04,0x01}, +{0xEED9,0xE6,0x01}, +{0xEEDA,0x32,0x01}, +{0xEEDB,0x58,0x01}, +{0xEEDC,0x29,0x01}, +{0xEEDD,0xCB,0x01}, +{0xEEDE,0x4C,0x01}, +{0xEEDF,0x74,0x01}, +{0xEEE0,0x92,0x01}, +{0xEEE1,0x91,0x01}, +{0xEEE2,0x8E,0x01}, +{0xEEE3,0x48,0x01}, +{0xEEE4,0x84,0x01}, +{0xEEE5,0x22,0x01}, +{0xEEE6,0x1D,0x01}, +{0xEEE7,0x01,0x01}, +{0xEEE8,0xC9,0x01}, +{0xEEE9,0x4D,0x01}, +{0xEEEA,0x7E,0x01}, +{0xEEEB,0x82,0x01}, +{0xEEEC,0x15,0x01}, +{0xEEED,0xB5,0x01}, +{0xEEEE,0x04,0x01}, +{0xEEEF,0xE6,0x01}, +{0xEEF0,0x33,0x01}, +{0xEEF1,0x99,0x01}, +{0xEEF2,0x69,0x01}, +{0xEEF3,0x0D,0x01}, +{0xEEF4,0x5D,0x01}, +{0xEEF5,0x06,0x01}, +{0xEEF6,0x33,0x01}, +{0xEEF7,0x15,0x01}, +{0xEEF8,0xAF,0x01}, +{0xEEF9,0xEC,0x01}, +{0xEEFA,0xA4,0x01}, +{0xEEFB,0x28,0x01}, +{0xEEFC,0x35,0x01}, +{0xEEFD,0xE9,0x01}, +{0xEEFE,0x09,0x01}, +{0xEEFF,0x4F,0x01}, +{0xEF00,0x8E,0x01}, +{0xEF01,0x02,0x01}, +{0xEF02,0x95,0x01}, +{0xEF03,0xB1,0x01}, +{0xEF04,0xC4,0x01}, +{0xEF05,0x25,0x01}, +{0xEF06,0x31,0x01}, +{0xEF07,0x94,0x01}, +{0xEF08,0xB1,0x01}, +{0xEF09,0x4D,0x01}, +{0xEF0A,0x6C,0x01}, +{0xEF0B,0x94,0x01}, +{0xEF0C,0x43,0x01}, +{0xEF0D,0x99,0x01}, +{0xEF0E,0xD4,0x01}, +{0xEF0F,0xEC,0x01}, +{0xEF10,0xC5,0x01}, +{0xEF11,0x31,0x01}, +{0xEF12,0x69,0x01}, +{0xEF13,0xC9,0x01}, +{0xEF14,0x0B,0x01}, +{0xEF15,0x58,0x01}, +{0xEF16,0xE6,0x01}, +{0xEF17,0x52,0x01}, +{0xEF18,0x16,0x01}, +{0xEF19,0xBE,0x01}, +{0xEF1A,0xD4,0x01}, +{0xEF1B,0x45,0x01}, +{0xEF1C,0x32,0x01}, +{0xEF1D,0x8E,0x01}, +{0xEF1E,0x79,0x01}, +{0xEF1F,0x4D,0x01}, +{0xEF20,0x6A,0x01}, +{0xEF21,0xA4,0x01}, +{0xEF22,0x83,0x01}, +{0xEF23,0x1C,0x01}, +{0xEF24,0xF2,0x01}, +{0xEF25,0xDC,0x01}, +{0xEF26,0x26,0x01}, +{0xEF27,0x3A,0x01}, +{0xEF28,0xA3,0x01}, +{0xEF29,0xE1,0x01}, +{0xEF2A,0x4D,0x01}, +{0xEF2B,0x65,0x01}, +{0xEF2C,0x5C,0x01}, +{0xEF2D,0xC3,0x01}, +{0xEF2E,0x98,0x01}, +{0xEF2F,0xD4,0x01}, +{0xEF30,0x3C,0x01}, +{0xEF31,0xE6,0x01}, +{0xEF32,0x35,0x01}, +{0xEF33,0x9D,0x01}, +{0xEF34,0x09,0x01}, +{0xEF35,0x8E,0x01}, +{0xEF36,0x6B,0x01}, +{0xEF37,0xAC,0x01}, +{0xEF38,0xE3,0x01}, +{0xEF39,0x9B,0x01}, +{0xEF3A,0xF4,0x01}, +{0xEF3B,0x34,0x01}, +{0xEF3C,0x07,0x01}, +{0xEF3D,0x3E,0x01}, +{0xEF3E,0xDA,0x01}, +{0xEF3F,0xC1,0x01}, +{0xEF40,0x8F,0x01}, +{0xEF41,0x74,0x01}, +{0xEF42,0xEA,0x01}, +{0xEF43,0x13,0x01}, +{0xEF44,0x9C,0x01}, +{0xEF45,0xF4,0x01}, +{0xEF46,0xF0,0x01}, +{0xEF47,0xA6,0x01}, +{0xEF48,0x3C,0x01}, +{0xEF49,0xC0,0x01}, +{0xEF4A,0x49,0x01}, +{0xEF4B,0x0F,0x01}, +{0xEF4C,0x72,0x01}, +{0xEF4D,0xEA,0x01}, +{0xEF4E,0xD3,0x01}, +{0xEF4F,0x9C,0x01}, +{0xEF50,0xFE,0x01}, +{0xEF51,0x04,0x01}, +{0xEF52,0xA7,0x01}, +{0xEF53,0x3D,0x01}, + +//SHD2 CW+TL84 33:66 + +{0xED00,0x9191,0x02},// +{0xEF54,0x2F,0x01}, +{0xEF55,0xF2,0x01}, +{0xEF56,0x51,0x01}, +{0xEF57,0x8D,0x01}, +{0xEF58,0x50,0x01}, +{0xEF59,0x74,0x01}, +{0xEF5A,0xA2,0x01}, +{0xEF5B,0x14,0x01}, +{0xEF5C,0xE1,0x01}, +{0xEF5D,0xC8,0x01}, +{0xEF5E,0x47,0x01}, +{0xEF5F,0x2E,0x01}, +{0xEF60,0xD2,0x01}, +{0xEF61,0x10,0x01}, +{0xEF62,0x80,0x01}, +{0xEF63,0xC8,0x01}, +{0xEF64,0x13,0x01}, +{0xEF65,0x9D,0x01}, +{0xEF66,0xE5,0x01}, +{0xEF67,0x48,0x01}, +{0xEF68,0x87,0x01}, +{0xEF69,0x3C,0x01}, +{0xEF6A,0xFE,0x01}, +{0xEF6B,0xC9,0x01}, +{0xEF6C,0x50,0x01}, +{0xEF6D,0x7D,0x01}, +{0xEF6E,0x96,0x01}, +{0xEF6F,0x83,0x01}, +{0xEF70,0x9A,0x01}, +{0xEF71,0xC6,0x01}, +{0xEF72,0x10,0x01}, +{0xEF73,0xA6,0x01}, +{0xEF74,0x31,0x01}, +{0xEF75,0xA5,0x01}, +{0xEF76,0x61,0x01}, +{0xEF77,0xCE,0x01}, +{0xEF78,0x7F,0x01}, +{0xEF79,0xA4,0x01}, +{0xEF7A,0xD3,0x01}, +{0xEF7B,0x19,0x01}, +{0xEF7C,0xB6,0x01}, +{0xEF7D,0x38,0x01}, +{0xEF7E,0xA5,0x01}, +{0xEF7F,0x28,0x01}, +{0xEF80,0x4E,0x01}, +{0xEF81,0x69,0x01}, +{0xEF82,0x4B,0x01}, +{0xEF83,0x68,0x01}, +{0xEF84,0xBA,0x01}, +{0xEF85,0x93,0x01}, +{0xEF86,0x1B,0x01}, +{0xEF87,0xBC,0x01}, +{0xEF88,0x0C,0x01}, +{0xEF89,0x65,0x01}, +{0xEF8A,0x24,0x01}, +{0xEF8B,0x17,0x01}, +{0xEF8C,0x19,0x01}, +{0xEF8D,0x49,0x01}, +{0xEF8E,0x51,0x01}, +{0xEF8F,0xF6,0x01}, +{0xEF90,0xE2,0x01}, +{0xEF91,0x1B,0x01}, +{0xEF92,0xD5,0x01}, +{0xEF93,0x98,0x01}, +{0xEF94,0xC5,0x01}, +{0xEF95,0x25,0x01}, +{0xEF96,0x0B,0x01}, +{0xEF97,0x01,0x01}, +{0xEF98,0x48,0x01}, +{0xEF99,0x43,0x01}, +{0xEF9A,0x64,0x01}, +{0xEF9B,0x72,0x01}, +{0xEF9C,0x96,0x01}, +{0xEF9D,0xD6,0x01}, +{0xEF9E,0xA8,0x01}, +{0xEF9F,0xE6,0x01}, +{0xEFA0,0x2C,0x01}, +{0xEFA1,0x30,0x01}, +{0xEFA2,0x51,0x01}, +{0xEFA3,0x48,0x01}, +{0xEFA4,0x40,0x01}, +{0xEFA5,0x1C,0x01}, +{0xEFA6,0x22,0x01}, +{0xEFA7,0x93,0x01}, +{0xEFA8,0xB4,0x01}, +{0xEFA9,0xC8,0x01}, +{0xEFAA,0xA6,0x01}, +{0xEFAB,0x37,0x01}, +{0xEFAC,0x7C,0x01}, +{0xEFAD,0x29,0x01}, +{0xEFAE,0x8A,0x01}, +{0xEFAF,0x48,0x01}, +{0xEFB0,0x30,0x01}, +{0xEFB1,0x62,0x01}, +{0xEFB2,0x12,0x01}, +{0xEFB3,0xA4,0x01}, +{0xEFB4,0xF8,0x01}, +{0xEFB5,0x65,0x01}, +{0xEFB6,0x38,0x01}, +{0xEFB7,0xDB,0x01}, +{0xEFB8,0x11,0x01}, +{0xEFB9,0x0D,0x01}, +{0xEFBA,0x5C,0x01}, +{0xEFBB,0xA0,0x01}, +{0xEFBC,0x72,0x01}, +{0xEFBD,0x94,0x01}, +{0xEFBE,0xA9,0x01}, +{0xEFBF,0xD0,0x01}, +{0xEFC0,0x05,0x01}, +{0xEFC1,0x35,0x01}, +{0xEFC2,0xE5,0x01}, +{0xEFC3,0x11,0x01}, +{0xEFC4,0xD0,0x01}, +{0xEFC5,0x74,0x01}, +{0xEFC6,0x52,0x01}, +{0xEFC7,0x03,0x01}, +{0xEFC8,0x19,0x01}, +{0xEFC9,0xC3,0x01}, +{0xEFCA,0x48,0x01}, +{0xEFCB,0xC6,0x01}, +{0xEFCC,0x35,0x01}, +{0xEFCD,0xD7,0x01}, +{0xEFCE,0x41,0x01}, +{0xEFCF,0x10,0x01}, +{0xEFD0,0x88,0x01}, +{0xEFD1,0x06,0x01}, +{0xEFD2,0x54,0x01}, +{0xEFD3,0x9E,0x01}, +{0xEFD4,0xE9,0x01}, +{0xEFD5,0x30,0x01}, +{0xEFD6,0xC7,0x01}, +{0xEFD7,0x3A,0x01}, +{0xEFD8,0xEA,0x01}, +{0xEFD9,0x41,0x01}, +{0xEFDA,0x50,0x01}, +{0xEFDB,0x8A,0x01}, +{0xEFDC,0x4E,0x01}, +{0xEFDD,0xB4,0x01}, +{0xEFDE,0x22,0x01}, +{0xEFDF,0x10,0x01}, +{0xEFE0,0x51,0x01}, +{0xEFE1,0x48,0x01}, +{0xEFE2,0x42,0x01}, +{0xEFE3,0x19,0x01}, +{0xEFE4,0x2A,0x01}, +{0xEFE5,0x91,0x01}, +{0xEFE6,0x8B,0x01}, +{0xEFE7,0x5A,0x01}, +{0xEFE8,0x04,0x01}, +{0xEFE9,0x00,0x01}, +{0xEFEA,0x00,0x01}, +{0xEFEB,0x00,0x01}, +{0xEFEC,0x00,0x01}, +{0xEFED,0x00,0x01}, + + + +//SHD3 D65+TL84 C01// +{0xED00,0x9191,0x02},// +{0xEFEE,0x21,0x01}, +{0xEFEF,0xAA,0x01}, +{0xEFF0,0xD1,0x01}, +{0xEFF1,0x8B,0x01}, +{0xEFF2,0x4A,0x01}, +{0xEFF3,0x64,0x01}, +{0xEFF4,0x22,0x01}, +{0xEFF5,0x15,0x01}, +{0xEFF6,0xD9,0x01}, +{0xEFF7,0x28,0x01}, +{0xEFF8,0x47,0x01}, +{0xEFF9,0x26,0x01}, +{0xEFFA,0xA2,0x01}, +{0xEFFB,0x50,0x01}, +{0xEFFC,0x7F,0x01}, +{0xEFFD,0xC6,0x01}, +{0xEFFE,0x23,0x01}, +{0xEFFF,0x9D,0x01}, +{0xF000,0xE6,0x01}, +{0xF001,0x54,0x01}, +{0xF002,0xE7,0x01}, +{0xF003,0x3C,0x01}, +{0xF004,0x00,0x01}, +{0xF005,0xBA,0x01}, +{0xF006,0xD0,0x01}, +{0xF007,0x7C,0x01}, +{0xF008,0x98,0x01}, +{0xF009,0xA3,0x01}, +{0xF00A,0x9A,0x01}, +{0xF00B,0xC7,0x01}, +{0xF00C,0x18,0x01}, +{0xF00D,0x06,0x01}, +{0xF00E,0x32,0x01}, +{0xF00F,0xAA,0x01}, +{0xF010,0x81,0x01}, +{0xF011,0x8E,0x01}, +{0xF012,0x80,0x01}, +{0xF013,0xA4,0x01}, +{0xF014,0xE3,0x01}, +{0xF015,0x19,0x01}, +{0xF016,0xB7,0x01}, +{0xF017,0x3C,0x01}, +{0xF018,0xC5,0x01}, +{0xF019,0x28,0x01}, +{0xF01A,0x51,0x01}, +{0xF01B,0x89,0x01}, +{0xF01C,0x8B,0x01}, +{0xF01D,0x69,0x01}, +{0xF01E,0xC4,0x01}, +{0xF01F,0x93,0x01}, +{0xF020,0x9B,0x01}, +{0xF021,0xBC,0x01}, +{0xF022,0x10,0x01}, +{0xF023,0x65,0x01}, +{0xF024,0x24,0x01}, +{0xF025,0x18,0x01}, +{0xF026,0x21,0x01}, +{0xF027,0x09,0x01}, +{0xF028,0x52,0x01}, +{0xF029,0x00,0x01}, +{0xF02A,0x33,0x01}, +{0xF02B,0x9C,0x01}, +{0xF02C,0xD5,0x01}, +{0xF02D,0x9C,0x01}, +{0xF02E,0xE5,0x01}, +{0xF02F,0x25,0x01}, +{0xF030,0x0A,0x01}, +{0xF031,0x01,0x01}, +{0xF032,0x88,0x01}, +{0xF033,0x43,0x01}, +{0xF034,0x68,0x01}, +{0xF035,0xA2,0x01}, +{0xF036,0x16,0x01}, +{0xF037,0xD9,0x01}, +{0xF038,0xAC,0x01}, +{0xF039,0x06,0x01}, +{0xF03A,0x2D,0x01}, +{0xF03B,0x30,0x01}, +{0xF03C,0x51,0x01}, +{0xF03D,0x48,0x01}, +{0xF03E,0x40,0x01}, +{0xF03F,0x1E,0x01}, +{0xF040,0x42,0x01}, +{0xF041,0x93,0x01}, +{0xF042,0xB6,0x01}, +{0xF043,0xDC,0x01}, +{0xF044,0xC6,0x01}, +{0xF045,0x37,0x01}, +{0xF046,0x7E,0x01}, +{0xF047,0x31,0x01}, +{0xF048,0xCA,0x01}, +{0xF049,0x48,0x01}, +{0xF04A,0x32,0x01}, +{0xF04B,0x72,0x01}, +{0xF04C,0x92,0x01}, +{0xF04D,0xA5,0x01}, +{0xF04E,0x08,0x01}, +{0xF04F,0x26,0x01}, +{0xF050,0x39,0x01}, +{0xF051,0xDC,0x01}, +{0xF052,0x19,0x01}, +{0xF053,0x8D,0x01}, +{0xF054,0x5C,0x01}, +{0xF055,0xA4,0x01}, +{0xF056,0x92,0x01}, +{0xF057,0x14,0x01}, +{0xF058,0xAB,0x01}, +{0xF059,0xE0,0x01}, +{0xF05A,0xA5,0x01}, +{0xF05B,0x35,0x01}, +{0xF05C,0xEA,0x01}, +{0xF05D,0x09,0x01}, +{0xF05E,0x10,0x01}, +{0xF05F,0x75,0x01}, +{0xF060,0x58,0x01}, +{0xF061,0x33,0x01}, +{0xF062,0x99,0x01}, +{0xF063,0xC4,0x01}, +{0xF064,0x58,0x01}, +{0xF065,0x66,0x01}, +{0xF066,0x36,0x01}, +{0xF067,0xDB,0x01}, +{0xF068,0x61,0x01}, +{0xF069,0xD0,0x01}, +{0xF06A,0x86,0x01}, +{0xF06B,0x02,0x01}, +{0xF06C,0x64,0x01}, +{0xF06D,0x1E,0x01}, +{0xF06E,0xEB,0x01}, +{0xF06F,0x40,0x01}, +{0xF070,0x47,0x01}, +{0xF071,0x3B,0x01}, +{0xF072,0xEE,0x01}, +{0xF073,0x51,0x01}, +{0xF074,0x10,0x01}, +{0xF075,0x8A,0x01}, +{0xF076,0x36,0x01}, +{0xF077,0x54,0x01}, +{0xF078,0x22,0x01}, +{0xF079,0x0E,0x01}, +{0xF07A,0x51,0x01}, +{0xF07B,0x88,0x01}, +{0xF07C,0x42,0x01}, +{0xF07D,0x1A,0x01}, +{0xF07E,0x2A,0x01}, +{0xF07F,0x11,0x01}, +{0xF080,0x8B,0x01}, +{0xF081,0x48,0x01}, +{0xF082,0x04,0x01}, +{0xF083,0x00,0x01}, +{0xF084,0x00,0x01}, +{0xF085,0x00,0x01}, +{0xF086,0x00,0x01}, +{0xF087,0x00,0x01}, +{0xF088,0xBE,0x01}, +{0xF089,0x51,0x01}, +{0xF08A,0x4E,0x01}, +{0xF08B,0x6F,0x01}, +{0xF08C,0x6C,0x01}, +{0xF08D,0x43,0x01}, +{0xF08E,0x1B,0x01}, +{0xF08F,0xDA,0x01}, +{0xF090,0xEC,0x01}, +{0xF091,0x46,0x01}, +{0xF092,0x38,0x01}, +{0xF093,0xBB,0x01}, +{0xF094,0xC1,0x01}, +{0xF095,0xCD,0x01}, +{0xF096,0x69,0x01}, +{0xF097,0x26,0x01}, +{0xF098,0x93,0x01}, +{0xF099,0x98,0x01}, +{0xF09A,0xC1,0x01}, +{0xF09B,0x20,0x01}, +{0xF09C,0x26,0x01}, +{0xF09D,0x32,0x01}, +{0xF09E,0xA5,0x01}, +{0xF09F,0xB1,0x01}, +{0xF0A0,0x8D,0x01}, +{0xF0A1,0x67,0x01}, +{0xF0A2,0x0E,0x01}, +{0xF0A3,0x23,0x01}, +{0xF0A4,0x97,0x01}, +{0xF0A5,0xB0,0x01}, +{0xF0A6,0x6C,0x01}, +{0xF0A7,0x25,0x01}, +{0xF0A8,0x2C,0x01}, +{0xF0A9,0x71,0x01}, +{0xF0AA,0x41,0x01}, +{0xF0AB,0x0C,0x01}, +{0xF0AC,0x69,0x01}, +{0xF0AD,0x14,0x01}, +{0xF0AE,0xB3,0x01}, +{0xF0AF,0x96,0x01}, +{0xF0B0,0xA6,0x01}, +{0xF0B1,0xE8,0x01}, +{0xF0B2,0x64,0x01}, +{0xF0B3,0x26,0x01}, +{0xF0B4,0x3A,0x01}, +{0xF0B5,0x79,0x01}, +{0xF0B6,0x4A,0x01}, +{0xF0B7,0x5B,0x01}, +{0xF0B8,0x18,0x01}, +{0xF0B9,0xA3,0x01}, +{0xF0BA,0x97,0x01}, +{0xF0BB,0xA9,0x01}, +{0xF0BC,0xBC,0x01}, +{0xF0BD,0x24,0x01}, +{0xF0BE,0x23,0x01}, +{0xF0BF,0x13,0x01}, +{0xF0C0,0xE1,0x01}, +{0xF0C1,0xC8,0x01}, +{0xF0C2,0x4C,0x01}, +{0xF0C3,0xAA,0x01}, +{0xF0C4,0xA2,0x01}, +{0xF0C5,0x97,0x01}, +{0xF0C6,0xB6,0x01}, +{0xF0C7,0x14,0x01}, +{0xF0C8,0x05,0x01}, +{0xF0C9,0x24,0x01}, +{0xF0CA,0x06,0x01}, +{0xF0CB,0x09,0x01}, +{0xF0CC,0xC8,0x01}, +{0xF0CD,0x42,0x01}, +{0xF0CE,0x48,0x01}, +{0xF0CF,0x82,0x01}, +{0xF0D0,0x14,0x01}, +{0xF0D1,0xB8,0x01}, +{0xF0D2,0xC0,0x01}, +{0xF0D3,0xE5,0x01}, +{0xF0D4,0x28,0x01}, +{0xF0D5,0x21,0x01}, +{0xF0D6,0x39,0x01}, +{0xF0D7,0x08,0x01}, +{0xF0D8,0x40,0x01}, +{0xF0D9,0x14,0x01}, +{0xF0DA,0x62,0x01}, +{0xF0DB,0x92,0x01}, +{0xF0DC,0xA4,0x01}, +{0xF0DD,0xC4,0x01}, +{0xF0DE,0x05,0x01}, +{0xF0DF,0x30,0x01}, +{0xF0E0,0x58,0x01}, +{0xF0E1,0xA1,0x01}, +{0xF0E2,0x49,0x01}, +{0xF0E3,0x46,0x01}, +{0xF0E4,0x22,0x01}, +{0xF0E5,0xB2,0x01}, +{0xF0E6,0x91,0x01}, +{0xF0E7,0x9A,0x01}, +{0xF0E8,0x58,0x01}, +{0xF0E9,0xA5,0x01}, +{0xF0EA,0x2F,0x01}, +{0xF0EB,0x96,0x01}, +{0xF0EC,0x99,0x01}, +{0xF0ED,0x8B,0x01}, +{0xF0EE,0x54,0x01}, +{0xF0EF,0x74,0x01}, +{0xF0F0,0x32,0x01}, +{0xF0F1,0x13,0x01}, +{0xF0F2,0x9D,0x01}, +{0xF0F3,0x38,0x01}, +{0xF0F4,0xC5,0x01}, +{0xF0F5,0x2D,0x01}, +{0xF0F6,0x90,0x01}, +{0xF0F7,0x59,0x01}, +{0xF0F8,0x4D,0x01}, +{0xF0F9,0x64,0x01}, +{0xF0FA,0xEE,0x01}, +{0xF0FB,0x62,0x01}, +{0xF0FC,0x16,0x01}, +{0xF0FD,0xAE,0x01}, +{0xF0FE,0x84,0x01}, +{0xF0FF,0x25,0x01}, +{0xF100,0x2E,0x01}, +{0xF101,0x8B,0x01}, +{0xF102,0x31,0x01}, +{0xF103,0xCD,0x01}, +{0xF104,0x6F,0x01}, +{0xF105,0x60,0x01}, +{0xF106,0xC3,0x01}, +{0xF107,0x19,0x01}, +{0xF108,0xC7,0x01}, +{0xF109,0x14,0x01}, +{0xF10A,0x26,0x01}, +{0xF10B,0x31,0x01}, +{0xF10C,0x97,0x01}, +{0xF10D,0x41,0x01}, +{0xF10E,0x8D,0x01}, +{0xF10F,0x6D,0x01}, +{0xF110,0x86,0x01}, +{0xF111,0xE3,0x01}, +{0xF112,0x9C,0x01}, +{0xF113,0xE2,0x01}, +{0xF114,0xD8,0x01}, +{0xF115,0x06,0x01}, +{0xF116,0x36,0x01}, +{0xF117,0xB5,0x01}, +{0xF118,0xE9,0x01}, +{0xF119,0x4D,0x01}, +{0xF11A,0x70,0x01}, +{0xF11B,0x68,0x01}, +{0xF11C,0x03,0x01}, +{0xF11D,0x00,0x01}, +{0xF11E,0x00,0x01}, +{0xF11F,0x00,0x01}, +{0xF120,0x00,0x01}, +{0xF121,0x00,0x01}, + + +//SHD TH +{0x6C32,0x1964,0x02}, // SHD_INP_TH_HB_H_R2 +{0x6C34,0x18CE,0x02}, // SHD_INP_TH_HB_L_R2 +{0x6C36,0x10CC,0x02}, // SHD_INP_TH_LB_H_R2 +{0x6C38,0x1004,0x02}, // SHD_INP_TH_LB_L_R2 +{0x6C3C,0x10CC,0x02}, // SHD_INP_TH_HB_H_RB +{0x6C3E,0x1004,0x02}, // SHD_INP_TH_HB_L_RB +{0x6C40,0x0000,0x02}, // SHD_INP_TH_LB_H_RB +{0x6C42,0x0000,0x02}, // SHD_INP_TH_LB_L_RB + +//PreWB_offset (for SHD2) +{0x6828,0x0013,0x02}, // SHD_PRER_OFFSET_R2 : +//PreWB_offset (for SHD3) +{0x682C,0x000B,0x02}, // SHD_PRER_OFFSET_RB : +{0x6830,0xFFFD,0x02}, // SHD_PREB_OFFSET_RB : + +// CXC/SHD EN +{0x01BC,0x57,0x01}, // CXC ON SHD ON INP ON GAIN OFF +}; + +static const isx012_regset_t ISX012_Flash_ON[] = +{ +//Flash_ON_SET +{0x00B7,0x15,0x01}, // LED_ON +{0x0016,0x10,0x01}, // GPIO_FUNCSEL +{0x0181,0x05,0x01}, // CAP_HALF_AE_CTRL +{0x01AE,0x01,0x01}, // HALF_AWB_CTRL +{0x6223,0x01,0x01}, // INIT_GAINS +{0x6226,0x01,0x01}, // ATW_GAINS_IN_NR +{0x6227,0x01,0x01}, // ATW_GAINS_IN +{0x6228,0x01,0x01}, // ATW_GAINS_OUT_NR +{0x6229,0x01,0x01}, // ATW_GAINS_OUT +{0x5E3D,0x0F,0x01}, // FASTMOVE_TIMEOUT +{0x5E32,0x0F,0x01}, // AESPEED_FAST +{0x5E2E,0x1A,0x01}, // AEIINDEADBAND +{0x500A,0x00,0x01}, // FAST_MODECHG_EN +{0x01AF,0x01,0x01}, // CAP_AWB_CTRL +{0x6224,0x01,0x01}, // ATW_DELAY +//AWB boundary set +{0x6400,0x00,0x01}, // INFRM_LEFT00 : +{0x6401,0x00,0x01}, // INFRM_LEFT01 : +{0x6402,0x00,0x01}, // INFRM_LEFT02 : +{0x6403,0x00,0x01}, // INFRM_LEFT03 : +{0x6404,0x00,0x01}, // INFRM_LEFT04 : +{0x6405,0x00,0x01}, // INFRM_LEFT05 : +{0x6406,0x00,0x01}, // INFRM_LEFT06 : +{0x6407,0x00,0x01}, // INFRM_LEFT07 : +{0x6408,0x00,0x01}, // INFRM_LEFT08 : +{0x6409,0x00,0x01}, // INFRM_LEFT09 : +{0x640A,0x00,0x01}, // INFRM_LEFT10 : +{0x640B,0x00,0x01}, // INFRM_LEFT11 : +{0x640C,0x00,0x01}, // INFRM_LEFT12 : +{0x640D,0x00,0x01}, // INFRM_LEFT13 : +{0x640E,0x00,0x01}, // INFRM_LEFT14 : +{0x640F,0x00,0x01}, // INFRM_LEFT15 : +{0x6410,0x00,0x01}, // INFRM_LEFT16 : +{0x6411,0x00,0x01}, // INFRM_LEFT17 : +{0x6412,0x00,0x01}, // INFRM_LEFT18 : +{0x6413,0x00,0x01}, // INFRM_LEFT19 : +{0x6414,0x00,0x01}, // INFRM_LEFT20 : +{0x6415,0x00,0x01}, // INFRM_LEFT21 : +{0x6416,0x00,0x01}, // INFRM_LEFT22 : +{0x6417,0x00,0x01}, // INFRM_LEFT23 : +{0x6418,0x00,0x01}, // INFRM_LEFT24 : +{0x6419,0x00,0x01}, // INFRM_LEFT25 : +{0x641A,0x00,0x01}, // INFRM_LEFT26 : +{0x641B,0x00,0x01}, // INFRM_LEFT27 : +{0x641C,0x00,0x01}, // INFRM_LEFT28 : +{0x641D,0x00,0x01}, // INFRM_LEFT29 : +{0x641E,0x00,0x01}, // INFRM_LEFT30 : +{0x641F,0x00,0x01}, // INFRM_LEFT31 : +{0x6420,0x00,0x01}, // INFRM_LEFT32 : +{0x6421,0x00,0x01}, // INFRM_LEFT33 : +{0x6422,0x00,0x01}, // INFRM_LEFT34 : +{0x6423,0x00,0x01}, // INFRM_LEFT35 : +{0x6424,0x00,0x01}, // INFRM_LEFT36 : +{0x6425,0x00,0x01}, // INFRM_LEFT37 : +{0x6426,0xFF,0x01}, // INFRM_RIGHT00 : +{0x6427,0xFF,0x01}, // INFRM_RIGHT01 : +{0x6428,0xFF,0x01}, // INFRM_RIGHT02 : +{0x6429,0xFF,0x01}, // INFRM_RIGHT03 : +{0x642A,0xFF,0x01}, // INFRM_RIGHT04 : +{0x642B,0xFF,0x01}, // INFRM_RIGHT05 : +{0x642C,0xFF,0x01}, // INFRM_RIGHT06 : +{0x642D,0xFF,0x01}, // INFRM_RIGHT07 : +{0x642E,0xFF,0x01}, // INFRM_RIGHT08 : +{0x642F,0xFF,0x01}, // INFRM_RIGHT09 : +{0x6430,0xFF,0x01}, // INFRM_RIGHT10 : +{0x6431,0xFF,0x01}, // INFRM_RIGHT11 : +{0x6432,0xFF,0x01}, // INFRM_RIGHT12 : +{0x6433,0xFF,0x01}, // INFRM_RIGHT13 : +{0x6434,0xFF,0x01}, // INFRM_RIGHT14 : +{0x6435,0xFF,0x01}, // INFRM_RIGHT15 : +{0x6436,0xFF,0x01}, // INFRM_RIGHT16 : +{0x6437,0xFF,0x01}, // INFRM_RIGHT17 : +{0x6438,0xFF,0x01}, // INFRM_RIGHT18 : +{0x6439,0xFF,0x01}, // INFRM_RIGHT19 : +{0x643A,0xFF,0x01}, // INFRM_RIGHT20 : +{0x643B,0xFF,0x01}, // INFRM_RIGHT21 : +{0x643C,0xFF,0x01}, // INFRM_RIGHT22 : +{0x643D,0xFF,0x01}, // INFRM_RIGHT23 : +{0x643E,0xFF,0x01}, // INFRM_RIGHT24 : +{0x643F,0xFF,0x01}, // INFRM_RIGHT25 : +{0x6440,0xFF,0x01}, // INFRM_RIGHT26 : +{0x6441,0xFF,0x01}, // INFRM_RIGHT27 : +{0x6442,0xFF,0x01}, // INFRM_RIGHT28 : +{0x6443,0xFF,0x01}, // INFRM_RIGHT29 : +{0x6444,0xFF,0x01}, // INFRM_RIGHT30 : +{0x6445,0xFF,0x01}, // INFRM_RIGHT31 : +{0x6446,0xFF,0x01}, // INFRM_RIGHT32 : +{0x6447,0xFF,0x01}, // INFRM_RIGHT33 : +{0x6448,0xFF,0x01}, // INFRM_RIGHT34 : +{0x6449,0xFF,0x01}, // INFRM_RIGHT35 : +{0x644A,0xFF,0x01}, // INFRM_RIGHT36 : +{0x644B,0xFF,0x01}, // INFRM_RIGHT37 : +{0x644C,0x25C2,0x02}, // INFRM_TOP : +{0x644E,0x0348,0x02}, // INFRM_BOTM : +{0x6450,0x1D,0x01}, // INFRM_FLTOP : +{0x6451,0x00,0x01}, // INFRM_FLBOTM : +//halfrelease_mode value +{0x0082,0x01,0x01}, // MONI_REFRESH +{0x00B1,0x01,0x01}, //AF_RESTART_F : +{0x00B2,0x03,0x01}, //AFMODE_MONI : AF OFF +{0x00B3,0x00,0x01}, //AFMODE_HREL : +{0xFFFF,0x42,0x01},//$wait, 66 +{0x0081,0x01,0x01}, //MODESEL +}; + +static const isx012_regset_t ISX012_Flash_OFF[] = +{ +//Flash_OFF_RESET +{0x00B7,0x00,0x01}, // LED_ON +{0x0016,0x10,0x01}, // GPIO_FUNCSEL +{0x0181,0x00,0x01}, // CAP_HALF_AE_CTRL +{0x01AE,0x00,0x01}, // HALF_AWB_CTRL +{0x6223,0x04,0x01}, // INIT_GAINS +{0x6226,0x08,0x01}, // ATW_GAINS_IN_NR +{0x6227,0x04,0x01}, // ATW_GAINS_IN +{0x6228,0x08,0x01}, // ATW_GAINS_OUT_NR +{0x6229,0x04,0x01}, // ATW_GAINS_OUT +{0x5E3D,0x0A,0x01}, // FASTMOVE_TIMEOUT +{0x5E32,0x0F,0x01}, // AESPEED_FAST +{0x5E2E,0x1A,0x01}, // AEIINDEADBAND +{0x500A,0x00,0x01}, // FAST_MODECHG_EN +{0x01AF,0x00,0x01}, // CAP_AWB_CTRL +{0x6224,0x04,0x01}, // ATW_DELAY +//AWB boundary reset +{0x6400,0xAA,0x01}, // INFRM_LEFT00 : +{0x6401,0xAA,0x01}, // INFRM_LEFT01 : +{0x6402,0xAA,0x01}, // INFRM_LEFT02 : +{0x6403,0xAA,0x01}, // INFRM_LEFT03 : +{0x6404,0xAA,0x01}, // INFRM_LEFT04 : +{0x6405,0xAA,0x01}, // INFRM_LEFT05 : +{0x6406,0xAA,0x01}, // INFRM_LEFT06 : +{0x6407,0xAA,0x01}, // INFRM_LEFT07 : +{0x6408,0xAA,0x01}, // INFRM_LEFT08 : +{0x6409,0xAE,0x01}, // INFRM_LEFT09 : +{0x640A,0xA0,0x01}, // INFRM_LEFT10 : +{0x640B,0x8C,0x01}, // INFRM_LEFT11 : +{0x640C,0x72,0x01}, // INFRM_LEFT12 : +{0x640D,0x64,0x01}, // INFRM_LEFT13 : +{0x640E,0x5A,0x01}, // INFRM_LEFT14 : +{0x640F,0x52,0x01}, // INFRM_LEFT15 : +{0x6410,0x48,0x01}, // INFRM_LEFT16 : +{0x6411,0x43,0x01}, // INFRM_LEFT17 : +{0x6412,0x3D,0x01}, // INFRM_LEFT18 : +{0x6413,0x37,0x01}, // INFRM_LEFT19 : +{0x6414,0x33,0x01}, // INFRM_LEFT20 : +{0x6415,0x30,0x01}, // INFRM_LEFT21 : +{0x6416,0x2E,0x01}, // INFRM_LEFT22 : +{0x6417,0x2B,0x01}, // INFRM_LEFT23 : +{0x6418,0x28,0x01}, // INFRM_LEFT24 : +{0x6419,0x26,0x01}, // INFRM_LEFT25 : +{0x641A,0x24,0x01}, // INFRM_LEFT26 : +{0x641B,0x23,0x01}, // INFRM_LEFT27 : +{0x641C,0x22,0x01}, // INFRM_LEFT28 : +{0x641D,0x22,0x01}, // INFRM_LEFT29 : +{0x641E,0x21,0x01}, // INFRM_LEFT30 : +{0x641F,0x20,0x01}, // INFRM_LEFT31 : +{0x6420,0x1D,0x01}, // INFRM_LEFT32 : +{0x6421,0x1A,0x01}, // INFRM_LEFT33 : +{0x6422,0x18,0x01}, // INFRM_LEFT34 : +{0x6423,0x17,0x01}, // INFRM_LEFT35 : +{0x6424,0x16,0x01}, // INFRM_LEFT36 : +{0x6425,0x17,0x01}, // INFRM_LEFT37 : +{0x6426,0xAF,0x01}, // INFRM_RIGHT00 : +{0x6427,0xAF,0x01}, // INFRM_RIGHT01 : +{0x6428,0xAF,0x01}, // INFRM_RIGHT02 : +{0x6429,0xAF,0x01}, // INFRM_RIGHT03 : +{0x642A,0xAF,0x01}, // INFRM_RIGHT04 : +{0x642B,0xAF,0x01}, // INFRM_RIGHT05 : +{0x642C,0xAF,0x01}, // INFRM_RIGHT06 : +{0x642D,0xAF,0x01}, // INFRM_RIGHT07 : +{0x642E,0xAF,0x01}, // INFRM_RIGHT08 : +{0x642F,0xAA,0x01}, // INFRM_RIGHT09 : +{0x6430,0xB2,0x01}, // INFRM_RIGHT10 : +{0x6431,0xB4,0x01}, // INFRM_RIGHT11 : +{0x6432,0xB6,0x01}, // INFRM_RIGHT12 : +{0x6433,0xB4,0x01}, // INFRM_RIGHT13 : +{0x6434,0x9B,0x01}, // INFRM_RIGHT14 : +{0x6435,0x8E,0x01}, // INFRM_RIGHT15 : +{0x6436,0x84,0x01}, // INFRM_RIGHT16 : +{0x6437,0x7A,0x01}, // INFRM_RIGHT17 : +{0x6438,0x72,0x01}, // INFRM_RIGHT18 : +{0x6439,0x6A,0x01}, // INFRM_RIGHT19 : +{0x643A,0x63,0x01}, // INFRM_RIGHT20 : +{0x643B,0x5E,0x01}, // INFRM_RIGHT21 : +{0x643C,0x58,0x01}, // INFRM_RIGHT22 : +{0x643D,0x53,0x01}, // INFRM_RIGHT23 : +{0x643E,0x4E,0x01}, // INFRM_RIGHT24 : +{0x643F,0x4A,0x01}, // INFRM_RIGHT25 : +{0x6440,0x46,0x01}, // INFRM_RIGHT26 : +{0x6441,0x42,0x01}, // INFRM_RIGHT27 : +{0x6442,0x3F,0x01}, // INFRM_RIGHT28 : +{0x6443,0x3C,0x01}, // INFRM_RIGHT29 : +{0x6444,0x3A,0x01}, // INFRM_RIGHT30 : +{0x6445,0x38,0x01}, // INFRM_RIGHT31 : +{0x6446,0x37,0x01}, // INFRM_RIGHT32 : +{0x6447,0x35,0x01}, // INFRM_RIGHT33 : +{0x6448,0x33,0x01}, // INFRM_RIGHT34 : +{0x6449,0x32,0x01}, // INFRM_RIGHT35 : +{0x644A,0x32,0x01}, // INFRM_RIGHT36 : +{0x644B,0x32,0x01}, // INFRM_RIGHT37 : +{0x644C,0x24FA,0x02}, // INFRM_TOP : +{0x644E,0x0940,0x02}, // INFRM_BOTM : +{0x6450,0x19,0x01}, // INFRM_FLTOP : +{0x6451,0x10,0x01}, // INFRM_FLBOTM : +////Flash_ON_RESET +{0x0308,0x11,0x01}, // AELINE_MONI_SN1_2 : +{0x0309,0x13,0x01}, // AELINE_MONI_SN3_4 : +{0x030B,0x41,0x01}, // AELINE_MONI_SN7_8 : +{0x030D,0x11,0x01}, // AELINE_MONI_SN11_12 : +{0x030E,0x11,0x01}, // AELINE_HALF_SN1_2 : +{0x030F,0x13,0x01}, // AELINE_HALF_SN3_4 : +{0x0311,0x41,0x01}, // AELINE_HALF_SN7_8 : +{0x0313,0x11,0x01}, // AELINE_HALF_SN11_12 : +{0x0314,0x11,0x01}, // AELINE_HALF_AFEND_SN1_2 : +{0x0315,0x13,0x01}, // AELINE_HALF_AFEND_SN3_4 : +{0x0317,0x41,0x01}, // AELINE_HALF_AFEND_SN7_8 : +{0x0319,0x11,0x01}, // AELINE_HALF_AFEND_SN11_12 : +{0x031A,0x00,0x01}, // AELINE_CAP_SN1_2 : +{0x031B,0x03,0x01}, // AELINE_CAP_SN3_4 : +{0x031D,0x50,0x01}, // AELINE_CAP_SN7_8 : +{0x031F,0x00,0x01}, // AELINE_CAP_SN11_12 : +{0x0294,0x00,0x01}, // AE_SN1 +{0x0297,0x00,0x01}, // AE_SN4 +{0x029A,0x00,0x01}, // AE_SN7 +{0x029E,0x00,0x01}, // AE_SN11 +}; + +static const isx012_regset_t ISX012_Flash_AELINE[] = +{ +//Flash_ON_SET +{0x0308,0x12,0x01}, // AELINE_MONI_SN1_2 : +{0x0309,0x23,0x01}, // AELINE_MONI_SN3_4 : +{0x030B,0x42,0x01}, // AELINE_MONI_SN7_8 : +{0x030D,0x12,0x01}, // AELINE_MONI_SN11_12 : +{0x030E,0x12,0x01}, // AELINE_HALF_SN1_2 : +{0x030F,0x23,0x01}, // AELINE_HALF_SN3_4 : +{0x0311,0x42,0x01}, // AELINE_HALF_SN7_8 : +{0x0313,0x12,0x01}, // AELINE_HALF_SN11_12 : +{0x0314,0x12,0x01}, // AELINE_HALF_AFEND_SN1_2 : +{0x0315,0x23,0x01}, // AELINE_HALF_AFEND_SN3_4 : +{0x0317,0x42,0x01}, // AELINE_HALF_AFEND_SN7_8 : +{0x0319,0x12,0x01}, // AELINE_HALF_AFEND_SN11_12 : +{0x031A,0x02,0x01}, // AELINE_CAP_SN1_2 : +{0x031B,0x23,0x01}, // AELINE_CAP_SN3_4 : +{0x031D,0x52,0x01}, // AELINE_CAP_SN7_8 : +{0x031F,0x02,0x01}, // AELINE_CAP_SN11_12 : +}; + +static const isx012_regset_t ISX012_ae_manual_mode[] = +{ +{0x0294,0x02,0x01}, /* AE_SN1 */ +{0x0297,0x02,0x01}, /* AE_SN4 */ +{0x029A,0x02,0x01}, /* AE_SN7 */ +{0x029E,0x02,0x01}, /* AE_SN11 */ +{0xFFFF,0x42,0x01}, /* $wait, 66 */ +}; + +static const isx012_regset_t ISX012_flash_fast_ae_awb[] = +{ +{0x5E32,0x0A,0x01}, +{0x5E3D,0x05,0x01}, /* Don't fix me. 0x05 */ + +{0x0181,0x01,0x01}, // CAP_HALF_AE_CTRL +{0x00B2,0x03,0x01}, //AFMODE_MONI : AF OFF +{0x00B3,0x03,0x01}, //AFMODE_HREL : AF OFF +{0x0081,0x01,0x01}, //MODESEL +}; + +static const isx012_regset_t ISX012_Lowlux_Night_Reset[] = +{ +{0x039D,0x00,0x01}, //UIHUE_TYPE3 : +{0x03A0,0x80,0x01}, //UISATURATION_TYPE3 : +{0x982A,0xFFEC,0x02}, // CS_CBLLEV_A : +{0x9830,0xFFEC,0x02}, // CS_CRLLEV_A : +{0x9805,0x0A,0x01}, // CS_SLP_C_A : +{0x6A9E,0x15C0,0x02}, //HMAX_1_1(0x6A9E)=0x15C0 +{0x00AC,0x00,0x01}, // +{0x660E,0x5A,0x01}, // AF_HBPF_PEAK_OPD_TH_MIN +{0x6610,0x5A,0x01}, // AF_HBPF_PEAK_OPD_TH_MAX +{0x664A,0x04,0x01}, // AF_DROPN_ON_PEAK_DETECT : +{0x6640,0x02,0x01}, // AF_DROPN_ON_PEAK_DETECT_SECOND : +{0x0289,0x20,0x01}, //AWB_SN8 +}; + +#endif /* __ISX012_REGS_H__ */ diff --git a/drivers/media/video/samsung/fimc/fimc_capture.c b/drivers/media/video/samsung/fimc/fimc_capture.c index 7d00c8b..75928ed 100644 --- a/drivers/media/video/samsung/fimc/fimc_capture.c +++ b/drivers/media/video/samsung/fimc/fimc_capture.c @@ -1435,7 +1435,7 @@ int fimc_s_fmt_vid_private(struct file *file, void *fh, struct v4l2_format *f) mbus_fmt = &ctrl->cap->mbus_fmt; mbus_fmt->width = pix->width; mbus_fmt->height = pix->height; -#ifdef CONFIG_MACH_P4NOTE +#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA) /* Unfortuntely, we have to use pix->field (not pix->priv) since * pix.field is already used in the below else condtion statement * (in case that sub-devices are not registered) @@ -1927,12 +1927,16 @@ int fimc_reqbufs_capture_mmap(void *fh, struct v4l2_requestbuffers *b) case V4L2_PIX_FMT_YVYU: /* fall through */ case V4L2_PIX_FMT_NV16: /* fall through */ case V4L2_PIX_FMT_NV61: /* fall through */ + fimc_err("%s : V4L2_PIX_FMT_YUYV - SBRISSEN\n", __func__); + fimc_err("%s : w %d h %d \n",__func__, + cap->fmt.width, cap->fmt.height); fimc_info1("%s : 1plane\n", __func__); ret = fimc_alloc_buffers(ctrl, 1, cap->fmt.width * cap->fmt.height, SZ_4K, bpp, cap->pktdata_enable, cap->pktdata_size); break; case V4L2_PIX_FMT_NV21: + fimc_err("%s : V4L2_PIX_FMT_NV12 - SBRISSEN\n", __func__); fimc_info1("%s : 2plane for NV21 w %d h %d\n", __func__, cap->fmt.width, cap->fmt.height); ret = fimc_alloc_buffers(ctrl, 2, @@ -1940,6 +1944,7 @@ int fimc_reqbufs_capture_mmap(void *fh, struct v4l2_requestbuffers *b) break; case V4L2_PIX_FMT_NV12: + fimc_info1("%s : 2plane for NV12\n", __func__); ret = fimc_alloc_buffers(ctrl, 2, cap->fmt.width * cap->fmt.height, SZ_64K, bpp, cap->pktdata_enable, cap->pktdata_size); @@ -1961,18 +1966,21 @@ int fimc_reqbufs_capture_mmap(void *fh, struct v4l2_requestbuffers *b) break; case V4L2_PIX_FMT_JPEG: + fimc_err("%s : V4L2_PIX_FMT_JPEG - SBRISSEN\n", __func__); fimc_info1("%s : JPEG 1plane\n", __func__); size = fimc_camera_get_jpeg_memsize(ctrl); fimc_info2("%s : JPEG 1plane size = %x\n", __func__, size); ret = fimc_alloc_buffers(ctrl, 1, size, 0, 8, cap->pktdata_enable, cap->pktdata_size); break; case V4L2_PIX_FMT_INTERLEAVED: + fimc_err("%s : V4L2_PIX_FMT_INTERLEAVED - SBRISSEN\n", __func__); fimc_info1("%s : Interleaved Format\n", __func__); size = fimc_camera_get_jpeg_memsize(ctrl); /*0xA00000*/ fimc_info2("%s : Interleaved size = %x\n", __func__, size); ret = fimc_alloc_buffers(ctrl, 1, size, 0, 8, cap->pktdata_enable, cap->pktdata_size); break; default: + fimc_err("%s : default - SBRISSEN\n", __func__); break; } @@ -1982,6 +1990,7 @@ int fimc_reqbufs_capture_mmap(void *fh, struct v4l2_requestbuffers *b) return -ENOMEM; } + fimc_err("%s : SBRISSEN - done\n", __func__); mutex_unlock(&ctrl->v4l2_lock); return 0; @@ -2248,7 +2257,7 @@ int fimc_s_ctrl_capture(void *fh, struct v4l2_control *c) clk_disable(ctrl->cam->clk); fimc->mclk_status = CAM_MCLK_OFF; ctrl->cam->initialized = 0; -#ifdef CONFIG_MACH_P4NOTE +#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA) /* 100ms: increase delay. * There are cases that sensor doesn't get revived * inspite of doing power reset.*/ @@ -2723,7 +2732,7 @@ int fimc_streamon_capture(void *fh) } } -#ifdef CONFIG_MACH_P4NOTE +#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA) #ifdef CONFIG_VIDEO_IMPROVE_STREAMOFF v4l2_subdev_call(cam->sd, video, s_stream, STREAM_MODE_WAIT_OFF); @@ -2753,7 +2762,7 @@ int fimc_streamon_capture(void *fh) cap->fmt.pixelformat); } } -#ifdef CONFIG_MACH_P4NOTE +#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA) if (1) { #else if (cap->fmt.priv != V4L2_PIX_FMT_MODE_CAPTURE) { diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c index 7fbea2a..8ff3d37 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c +++ b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c @@ -243,7 +243,15 @@ static void os_allocator_release(void * ctx, void * handle) static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) { - int allocation_order = 11; /* _MALI_OSK_CPU_PAGE_SIZE << 11 */ +#if defined(CONFIG_MACH_KONA) +#ifndef CONFIG_FORCE_MAX_ZONEORDER + int allocation_order = 10; +#else + int allocation_order = CONFIG_FORCE_MAX_ZONEORDER - 1; +#endif +#else + int allocation_order = 11; /* _MALI_OSK_CPU_PAGE_SIZE << 6 */ +#endif void *virt = NULL; u32 size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; os_allocator * info; diff --git a/drivers/media/video/sr130pc20.c b/drivers/media/video/sr130pc20.c new file mode 100644 index 0000000..ab2b8d5 --- /dev/null +++ b/drivers/media/video/sr130pc20.c @@ -0,0 +1,1999 @@ +/* drivers/media/video/sr130pc20.c + * + * Copyright (c) 2010, Samsung Electronics. All rights reserved + * Author: dongseong.lim + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * - change date: 2012.06.28 + */ +#include "sr130pc20.h" +#include + +#define i2c_read_nop() \ + (cam_err("error, not used read function, line %d\n", __LINE__)) +#define i2c_write_nop() \ + (cam_err("error, not used write function, line %d\n", __LINE__)) + +#define isx012_readb(sd, addr, data) i2c_read_nop() +#define isx012_writeb(sd, addr, data) i2c_write_nop() + +#define sr130pc20_readb(sd, addr, data) sr130pc20_i2c_read(sd, addr, data) +#define sr130pc20_readw(sd, addr, data) i2c_read_nop() +#define sr130pc20_readl(sd, addr, data) i2c_read_nop() +#define sr130pc20_writeb(sd, addr, data) sr130pc20_i2c_write(sd, addr, data) +#define sr130pc20_writew(sd, addr, data) i2c_write_nop() +#define sr130pc20_writel(sd, addr, data) i2c_write_nop() + +static int dbg_level; + +static const struct sr130pc20_fps sr130pc20_framerates[] = { + { I_FPS_0, FRAME_RATE_AUTO }, + { I_FPS_7, FRAME_RATE_7}, + { I_FPS_15, FRAME_RATE_15 }, + { I_FPS_25, FRAME_RATE_25 }, + { I_FPS_30, FRAME_RATE_30 }, +}; + +static const struct sr130pc20_framesize sr130pc20_preview_frmsizes[] = { + { PREVIEW_SZ_320x240, 320, 240 }, + { PREVIEW_SZ_CIF, 352, 288 }, + { PREVIEW_SZ_VGA, 640, 480 }, +}; + +static const struct sr130pc20_framesize sr130pc20_capture_frmsizes[] = { +/* { CAPTURE_SZ_VGA, 640, 480 },*/ + { CAPTURE_SZ_1MP, 1280, 960 }, +}; + +static struct sr130pc20_control sr130pc20_ctrls[] = { + SR130PC20_INIT_CONTROL(V4L2_CID_CAMERA_FLASH_MODE, \ + FLASH_MODE_OFF), + + SR130PC20_INIT_CONTROL(V4L2_CID_CAMERA_BRIGHTNESS, \ + EV_DEFAULT), + + SR130PC20_INIT_CONTROL(V4L2_CID_CAMERA_METERING, \ + METERING_MATRIX), + + SR130PC20_INIT_CONTROL(V4L2_CID_CAMERA_WHITE_BALANCE, \ + WHITE_BALANCE_AUTO), + + SR130PC20_INIT_CONTROL(V4L2_CID_CAMERA_EFFECT, \ + IMAGE_EFFECT_NONE), +}; + +static const struct sr130pc20_regs reg_datas = { + .ev = { + SR130PC20_REGSET(GET_EV_INDEX(EV_MINUS_4), + SR130PC20_ExpSetting_M4Step, 0), + SR130PC20_REGSET(GET_EV_INDEX(EV_MINUS_3), + SR130PC20_ExpSetting_M3Step, 0), + SR130PC20_REGSET(GET_EV_INDEX(EV_MINUS_2), + SR130PC20_ExpSetting_M2Step, 0), + SR130PC20_REGSET(GET_EV_INDEX(EV_MINUS_1), + SR130PC20_ExpSetting_M1Step, 0), + SR130PC20_REGSET(GET_EV_INDEX(EV_DEFAULT), + SR130PC20_ExpSetting_Default, 0), + SR130PC20_REGSET(GET_EV_INDEX(EV_PLUS_1), + SR130PC20_ExpSetting_P1Step, 0), + SR130PC20_REGSET(GET_EV_INDEX(EV_PLUS_2), + SR130PC20_ExpSetting_P2Step, 0), + SR130PC20_REGSET(GET_EV_INDEX(EV_PLUS_3), + SR130PC20_ExpSetting_P3Step, 0), + SR130PC20_REGSET(GET_EV_INDEX(EV_PLUS_4), + SR130PC20_ExpSetting_P4Step, 0), + }, + .metering = { + SR130PC20_REGSET(METERING_MATRIX, sr130pc20_Metering_Matrix, 0), + SR130PC20_REGSET(METERING_CENTER, sr130pc20_Metering_Center, 0), + SR130PC20_REGSET(METERING_SPOT, sr130pc20_Metering_Spot, 0), + }, + .iso = { + SR130PC20_REGSET(ISO_AUTO, sr130pc20_ISO_Auto, 0), + SR130PC20_REGSET(ISO_50, sr130pc20_ISO_50, 0), + SR130PC20_REGSET(ISO_100, sr130pc20_ISO_100, 0), + SR130PC20_REGSET(ISO_200, sr130pc20_ISO_200, 0), + SR130PC20_REGSET(ISO_400, sr130pc20_ISO_400, 0), + }, + .effect = { + SR130PC20_REGSET(IMAGE_EFFECT_NONE, sr130pc20_Effect_Normal, 0), + SR130PC20_REGSET(IMAGE_EFFECT_BNW, sr130pc20_Effect_Black_White, 0), + SR130PC20_REGSET(IMAGE_EFFECT_SEPIA, sr130pc20_Effect_Sepia, 0), + SR130PC20_REGSET(IMAGE_EFFECT_NEGATIVE, + SR130PC20_Effect_Negative, 0), + SR130PC20_REGSET(IMAGE_EFFECT_SOLARIZE, sr130pc20_Effect_Solar, 0), + SR130PC20_REGSET(IMAGE_EFFECT_SKETCH, sr130pc20_Effect_Sketch, 0), + SR130PC20_REGSET(IMAGE_EFFECT_POINT_COLOR_3, + sr130pc20_Effect_Pastel, 0), + }, + .white_balance = { + SR130PC20_REGSET(WHITE_BALANCE_AUTO, sr130pc20_WB_Auto, 0), + SR130PC20_REGSET(WHITE_BALANCE_SUNNY, sr130pc20_WB_Sunny, 0), + SR130PC20_REGSET(WHITE_BALANCE_CLOUDY, sr130pc20_WB_Cloudy, 0), + SR130PC20_REGSET(WHITE_BALANCE_TUNGSTEN, + sr130pc20_WB_Tungsten, 0), + SR130PC20_REGSET(WHITE_BALANCE_FLUORESCENT, + sr130pc20_WB_Fluorescent, 0), + }, + .scene_mode = { + SR130PC20_REGSET(SCENE_MODE_NONE, sr130pc20_Scene_Default, 0), + SR130PC20_REGSET(SCENE_MODE_PORTRAIT, sr130pc20_Scene_Portrait, 0), + SR130PC20_REGSET(SCENE_MODE_NIGHTSHOT, sr130pc20_Scene_Nightshot, 0), + SR130PC20_REGSET(SCENE_MODE_BACK_LIGHT, sr130pc20_Scene_Backlight, 0), + SR130PC20_REGSET(SCENE_MODE_LANDSCAPE, sr130pc20_Scene_Landscape, 0), + SR130PC20_REGSET(SCENE_MODE_SPORTS, sr130pc20_Scene_Sports, 0), + SR130PC20_REGSET(SCENE_MODE_PARTY_INDOOR, + sr130pc20_Scene_Party_Indoor, 0), + SR130PC20_REGSET(SCENE_MODE_BEACH_SNOW, + sr130pc20_Scene_Beach_Snow, 0), + SR130PC20_REGSET(SCENE_MODE_SUNSET, sr130pc20_Scene_Sunset, 0), + SR130PC20_REGSET(SCENE_MODE_DUSK_DAWN, sr130pc20_Scene_Duskdawn, 0), + SR130PC20_REGSET(SCENE_MODE_FALL_COLOR, + sr130pc20_Scene_Fall_Color, 0), + SR130PC20_REGSET(SCENE_MODE_FIREWORKS, sr130pc20_Scene_Fireworks, 0), + SR130PC20_REGSET(SCENE_MODE_TEXT, sr130pc20_Scene_Text, 0), + SR130PC20_REGSET(SCENE_MODE_CANDLE_LIGHT, + sr130pc20_Scene_Candle_Light, 0), + }, + .fps = { + SR130PC20_REGSET(I_FPS_0, sr130pc20_fps_auto, 0), + SR130PC20_REGSET(I_FPS_7, sr130pc20_fps_7fix, 0), + SR130PC20_REGSET(I_FPS_15, sr130pc20_fps_15fix, 0), + SR130PC20_REGSET(I_FPS_25, sr130pc20_fps_25fix, 0), + SR130PC20_REGSET(I_FPS_30, sr130pc20_fps_30fix, 0), + }, + .preview_size = { + SR130PC20_REGSET(PREVIEW_SZ_320x240, + sr130pc20_320_240_Preview, 0), + SR130PC20_REGSET(PREVIEW_SZ_CIF, sr130pc20_352_288_Preview, 0), + SR130PC20_REGSET(PREVIEW_SZ_VGA, sr130pc20_640_480_Preview, 0), + }, + .capture_size = { + /*SR130PC20_REGSET(CAPTURE_SZ_VGA, sr130pc20_VGA_Capture, 0),*/ + SR130PC20_REGSET(CAPTURE_SZ_1MP, sr130pc20_1280_960_Capture, 0), + }, + + .init_reg = SR130PC20_REGSET_TABLE(SR130PC20_Init_Reg, 0), + .VT_init_reg = SR130PC20_REGSET_TABLE(sr130pc20_VT_Init_Reg, 0), + .SS_init_reg = SR130PC20_REGSET_TABLE(sr130pc20_SmartStay_Init_Reg, 0), + /* Camera mode */ + .preview_mode = SR130PC20_REGSET_TABLE(SR130PC20_Preview_Mode, 0), + .capture_mode = SR130PC20_REGSET_TABLE(SR130PC20_Capture_Mode, 0), + .capture_mode_night = + SR130PC20_REGSET_TABLE(SR130PC20_Lowlux_Night_Capture_Mode, 0), + .stream_stop = SR130PC20_REGSET_TABLE(sr130pc20_stop_stream, 0), +}; + +static const struct v4l2_mbus_framefmt capture_fmts[] = { + { + .code = V4L2_MBUS_FMT_FIXED, + .colorspace = V4L2_COLORSPACE_JPEG, + }, +}; + +/** + * msleep_debug: wrapper function calling proper sleep() + * @msecs: time to be sleep (in milli-seconds unit) + * @dbg_on: whether enable log or not. + */ +static void msleep_debug(u32 msecs, bool dbg_on) +{ + u32 delta_halfrange; /* in us unit */ + + if (unlikely(!msecs)) + return; + + if (dbg_on) + cam_dbg("delay for %dms\n", msecs); + + if (msecs <= 7) + delta_halfrange = 100; + else + delta_halfrange = 300; + + if (msecs <= 20) + usleep_range((msecs * 1000 - delta_halfrange), + (msecs * 1000 + delta_halfrange)); + else + msleep(msecs); +} + +#ifdef CONFIG_LOAD_FILE +#define TABLE_MAX_NUM 500 +static char *sr130pc20_regs_table; +static int sr130pc20_regs_table_size; +static int gtable_buf[TABLE_MAX_NUM]; +static int sr130pc20_i2c_write(struct v4l2_subdev *sd, + u8 subaddr, u8 data); + +int sr130pc20_regs_table_init(void) +{ + struct file *filp; + char *dp; + long l; + loff_t pos; + int ret; + mm_segment_t fs = get_fs(); + + cam_info("%s %d\n", __func__, __LINE__); + + set_fs(get_ds()); + + filp = filp_open("/mnt/sdcard/sr130pc20_regs.h", O_RDONLY, 0); + + if (IS_ERR_OR_NULL(filp)) { + cam_err("file open error\n"); + return PTR_ERR(filp); + } + + l = filp->f_path.dentry->d_inode->i_size; + cam_trace("l = %ld\n", l); + //dp = kmalloc(l, GFP_KERNEL); + dp = vmalloc(l); + if (dp == NULL) { + cam_err("Out of Memory\n"); + filp_close(filp, current->files); + return -EINVAL; + } + + pos = 0; + memset(dp, 0, l); + ret = vfs_read(filp, (char __user *)dp, l, &pos); + + if (ret != l) { + cam_err("Failed to read file ret = %d\n", ret); + /*kfree(dp);*/ + vfree(dp); + filp_close(filp, current->files); + return -EINVAL; + } + + filp_close(filp, current->files); + + set_fs(fs); + + sr130pc20_regs_table = dp; + + sr130pc20_regs_table_size = l; + + *((sr130pc20_regs_table + sr130pc20_regs_table_size) - 1) = '\0'; + + printk("sr130pc20_reg_table_init end\n"); + return 0; +} + +void sr130pc20_regs_table_exit(void) +{ + printk(KERN_DEBUG "%s %d\n", __func__, __LINE__); + + if (sr130pc20_regs_table) { + vfree(sr130pc20_regs_table); + sr130pc20_regs_table = NULL; + } +} + +static int sr130pc20_is_hexnum(char *num) +{ + int i = 0; + for (i = 2; num[i] != '\0'; i++) { + if (!((num[i] >= '0' && num[5] <= '9') + || (num[5] >= 'a' && num[5] <= 'f') || (num[5] >= 'A' + && num[5] <= + 'F'))) { + return 0; + } + } + return 1; +} + +static int sr130pc20_write_regs_from_sd(struct v4l2_subdev *sd, + const char *name) +{ + char *start = NULL, *end = NULL, *reg = NULL, *temp = NULL; + unsigned char addr = 0, value = 0; + unsigned short data = 0; + char data_buf[7] = { 0 }; + int err = 0; + + cam_info("Enter!!\n"); + + addr = value = 0; + + *(data_buf + 6) = '\0'; + + start = strnstr(sr130pc20_regs_table, name, sr130pc20_regs_table_size); + if (start == NULL) { + cam_err("[%s : %d] start is NULL\n", __func__, __LINE__); + err = -EIO; + return err; + } + + end = strnstr(start, "};", sr130pc20_regs_table_size); + if (end == NULL) { + cam_err("[%s : %d] end is NULL\n", __func__, __LINE__); + err = -EIO; + return err; + } + + while (1) { + /* Find Address */ + reg = strnstr(start, "0x", sr130pc20_regs_table_size); + if (reg) + start = (reg + 6); + + if ((reg == NULL) || (reg > end)) { + cam_err("[%s : %d] write end of %s\n", + __func__, __LINE__, name); + break; + } + /* Write Value to Address */ + memcpy(data_buf, reg, 6); + + if (sr130pc20_is_hexnum(data_buf) == 0) { + cam_err("[%s : %d] it's not hex number %s\n", + __func__, __LINE__, data_buf); + continue; + } + + err = kstrtou16(data_buf, 16, &data); + if (err < 0) { + cam_err("[%s : %d] kstrtou16 failed\n", + __func__, __LINE__); + } + addr = (data >> 8); + value = (data & 0xff); + + if (addr == 0xff) { + msleep(value * 10); /*one step is 10ms */ + cam_trace("delay %d msec\n", value * 10); + } else { + if (sr130pc20_i2c_write(sd, addr, value) < 0) { + cam_err + ("[%s : %d] fail on sensor_write :" + "addr[0x%04x], value[0x%04x]\n", + __func__, __LINE__, addr, value); + err = -EIO; + return err; + } + cam_trace + ("success on sensor_write :" + "addr[0x%04x], value[0x%04x]\n", addr, value); + } + } + + cam_info("Exit!!\n"); + + return err; +} +#endif + +/** + * sr130pc20_read: read data from sensor with I2C + * Note the data-store way(Big or Little) + */ +static int sr130pc20_i2c_read(struct v4l2_subdev *sd, + u8 subaddr, u8 *data) +{ + int err = -EIO; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct i2c_msg msg[2]; + u8 buf[16] = {0,}; + int retry = 5; + + + CHECK_ERR_COND_MSG(!client->adapter, -ENODEV, + "can't search i2c client adapter\n"); + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = sizeof(subaddr); + msg[0].buf = &subaddr; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = 1; + msg[1].buf = buf; + + while (retry-- > 0) { + err = i2c_transfer(client->adapter, msg, 2); + if (likely(err == 2)) + break; + cam_err("i2c read: error, read register(0x%X). cnt %d\n", + subaddr, retry); + msleep_debug(POLL_TIME_MS, false); + } + + CHECK_ERR_COND_MSG(err != 2, -EIO, "I2C does not work\n"); + + *data = buf[0]; + + return 0; +} + +/** + * sr130pc20_write: write data with I2C + * Note the data-store way(Big or Little) + */ +static inline int sr130pc20_i2c_write(struct v4l2_subdev *sd, + u8 subaddr, u8 data) +{ + u8 buf[2]; + int err = 0, retry = 5; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .buf = buf, + .len = 2, + }; + + CHECK_ERR_COND_MSG(!client->adapter, -ENODEV, + "can't search i2c client adapter\n"); + + buf[0] = subaddr; + buf[1] = data; + + while (retry-- > 0) { + err = i2c_transfer(client->adapter, &msg, 1); + if (likely(err == 1)) + break; + cam_err("i2c write: error %d, write 0x%04X, retry %d\n", + err, ((subaddr << 8) | data), retry); + msleep_debug(POLL_TIME_MS, false); + } + + CHECK_ERR_COND_MSG(err != 1, -EIO, "I2C does not work\n"); + return 0; +} + +static int sr130pc20_i2c_burst_write_list(struct v4l2_subdev *sd, + const sr130pc20_regset_t regs[], int size, const char *name) +{ + + cam_err("burst write: not implemented\n"); + + return 0; +} + +static inline int sr130pc20_write_regs(struct v4l2_subdev *sd, + const sr130pc20_regset_t regs[], int size) +{ + int err = 0, i; + u8 subaddr, value; + + cam_trace("size %d\n", size); + + for (i = 0; i < size; i++) { + subaddr = (u8)(regs[i] >> 8); + value = (u8)(regs[i]); + if (unlikely(DELAY_SEQ == subaddr)) + msleep_debug(value * 10, true); + else { + err = sr130pc20_writeb(sd, subaddr, value); + CHECK_ERR_MSG(err, "register set failed\n") + } + } + + return 0; +} + +/* PX: */ +static int sr130pc20_set_from_table(struct v4l2_subdev *sd, + const char *setting_name, + const struct regset_table *table, + u32 table_size, s32 index) +{ + int err = 0; + + cam_trace("set %s index %d\n", setting_name, index); + + CHECK_ERR_COND_MSG(((index < 0) || (index >= table_size)), + -EINVAL, "index(%d) out of range[0:%d] for table for %s\n", + index, table_size, setting_name); + + table += index; + +#ifdef CONFIG_LOAD_FILE + cam_dbg("%s: \"%s\", reg_name=%s\n", __func__, + setting_name, table->name); + return sr130pc20_write_regs_from_sd(sd, table->name); + +#else /* !CONFIG_LOAD_FILE */ + CHECK_ERR_COND_MSG(!table->reg, -EFAULT, \ + "table=%s, index=%d, reg = NULL\n", setting_name, index); +# ifdef DEBUG_WRITE_REGS + cam_dbg("write_regtable: \"%s\", reg_name=%s\n", setting_name, + table->name); +# endif /* DEBUG_WRITE_REGS */ + + if (table->burst) { + err = sr130pc20_i2c_burst_write_list(sd, + table->reg, table->array_size, setting_name); + } else + err = sr130pc20_write_regs(sd, table->reg, table->array_size); + + CHECK_ERR_MSG(err, "write regs(%s), err=%d\n", setting_name, err); + + return 0; +#endif /* CONFIG_LOAD_FILE */ +} + +static inline int sr130pc20_transit_preview_mode(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + + if (state->exposure.ae_lock || state->wb.awb_lock) + cam_info("Restore user ae(awb)-lock...\n"); + + err = sr130pc20_set_from_table(sd, "preview_mode", + &state->regs->preview_mode, 1, 0); + + return err; +} + +static inline int sr130pc20_transit_capture_mode(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + int err = -EIO; + + if (state->capture.lowlux_night) { + cam_info("capture_mode: night lowlux\n"); + err = sr130pc20_set_from_table(sd, "capture_mode_night", + &state->regs->capture_mode_night, 1, 0); + } else + err = sr130pc20_set_from_table(sd, "capture_mode", + &state->regs->capture_mode, 1, 0); + + return err; +} + +/** + * sr130pc20_transit_movie_mode: switch camera mode if needed. + * Note that this fuction should be called from start_preview(). + */ +static inline int sr130pc20_transit_movie_mode(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + + /* we'll go from the below modes to RUNNING or RECORDING */ + switch (state->runmode) { + case RUNMODE_INIT: + /* case of entering camcorder firstly */ + break; + case RUNMODE_RUNNING_STOP: + /* case of switching from camera to camcorder */ + break; + case RUNMODE_RECORDING_STOP: + /* case of switching from camcorder to camera */ + break; + + default: + break; + } + + return 0; +} + +/** + * sr130pc20_is_hwflash_on - check whether flash device is on + * + * Refer to state->flash.on to check whether flash is in use in driver. + */ +static inline int sr130pc20_is_hwflash_on(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + +#ifdef SR130PC20_SUPPORT_FLASH + return state->pdata->is_flash_on(); +#else + return 0; +#endif +} + +/** + * sr130pc20_flash_en - contro Flash LED + * @mode: SR130PC20_FLASH_MODE_NORMAL or SR130PC20_FLASH_MODE_MOVIE + * @onoff: SR130PC20_FLASH_ON or SR130PC20_FLASH_OFF + */ +static int sr130pc20_flash_en(struct v4l2_subdev *sd, s32 mode, s32 onoff) +{ + struct sr130pc20_state *state = to_state(sd); + + if (unlikely(state->flash.ignore_flash)) { + cam_warn("WARNING, we ignore flash command.\n"); + return 0; + } + +#ifdef SR130PC20_SUPPORT_FLASH + return state->pdata->flash_en(mode, onoff); +#else + return 0; +#endif +} + +/** + * sr130pc20_flash_torch - turn flash on/off as torch for preflash, recording + * @onoff: SR130PC20_FLASH_ON or SR130PC20_FLASH_OFF + * + * This func set state->flash.on properly. + */ +static inline int sr130pc20_flash_torch(struct v4l2_subdev *sd, s32 onoff) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + + err = sr130pc20_flash_en(sd, SR130PC20_FLASH_MODE_MOVIE, onoff); + state->flash.on = (onoff == SR130PC20_FLASH_ON) ? 1 : 0; + + return err; +} + +/** + * sr130pc20_flash_oneshot - turn main flash on for capture + * @onoff: SR130PC20_FLASH_ON or SR130PC20_FLASH_OFF + * + * Main flash is turn off automatically in some milliseconds. + */ +static inline int sr130pc20_flash_oneshot(struct v4l2_subdev *sd, s32 onoff) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + + err = sr130pc20_flash_en(sd, SR130PC20_FLASH_MODE_NORMAL, onoff); + state->flash.on = (onoff == SR130PC20_FLASH_ON) ? 1 : 0; + + return err; +} + +static const struct sr130pc20_framesize *sr130pc20_get_framesize + (const struct sr130pc20_framesize *frmsizes, + u32 frmsize_count, u32 index) +{ + int i = 0; + + for (i = 0; i < frmsize_count; i++) { + if (frmsizes[i].index == index) + return &frmsizes[i]; + } + + return NULL; +} + +/* This function is called from the g_ctrl api + * + * This function should be called only after the s_fmt call, + * which sets the required width/height value. + * + * It checks a list of available frame sizes and sets the + * most appropriate frame size. + * + * The list is stored in an increasing order (as far as possible). + * Hence the first entry (searching from the beginning) where both the + * width and height is more than the required value is returned. + * In case of no perfect match, we set the last entry (which is supposed + * to be the largest resolution supported.) + */ +static void sr130pc20_set_framesize(struct v4l2_subdev *sd, + const struct sr130pc20_framesize *frmsizes, + u32 num_frmsize, bool preview) +{ + struct sr130pc20_state *state = to_state(sd); + const struct sr130pc20_framesize **found_frmsize = NULL; + u32 width = state->req_fmt.width; + u32 height = state->req_fmt.height; + int i = 0; + + cam_dbg("%s: Requested Res %dx%d\n", __func__, + width, height); + + found_frmsize = preview ? + &state->preview.frmsize : &state->capture.frmsize; + + for (i = 0; i < num_frmsize; i++) { + if ((frmsizes[i].width == width) && + (frmsizes[i].height == height)) { + *found_frmsize = &frmsizes[i]; + break; + } + } + + if (*found_frmsize == NULL) { + cam_err("%s: error, invalid frame size %dx%d\n", + __func__, width, height); + *found_frmsize = preview ? + sr130pc20_get_framesize(frmsizes, num_frmsize, + PREVIEW_SZ_VGA) : + sr130pc20_get_framesize(frmsizes, num_frmsize, + CAPTURE_SZ_1MP); + BUG_ON(!(*found_frmsize)); + } + + if (preview) + cam_info("Preview Res Set: %dx%d, index %d\n", + (*found_frmsize)->width, (*found_frmsize)->height, + (*found_frmsize)->index); + else + cam_info("Capture Res Set: %dx%d, index %d\n", + (*found_frmsize)->width, (*found_frmsize)->height, + (*found_frmsize)->index); +} + +/* PX: Set scene mode */ +static int sr130pc20_set_scene_mode(struct v4l2_subdev *sd, s32 val) +{ + struct sr130pc20_state *state = to_state(sd); + + cam_trace("E, value %d\n", val); + +retry: + switch (val) { + case SCENE_MODE_NONE: + case SCENE_MODE_PORTRAIT: + case SCENE_MODE_NIGHTSHOT: + case SCENE_MODE_BACK_LIGHT: + case SCENE_MODE_LANDSCAPE: + case SCENE_MODE_SPORTS: + case SCENE_MODE_PARTY_INDOOR: + case SCENE_MODE_BEACH_SNOW: + case SCENE_MODE_SUNSET: + case SCENE_MODE_DUSK_DAWN: + case SCENE_MODE_FALL_COLOR: + case SCENE_MODE_FIREWORKS: + case SCENE_MODE_TEXT: + case SCENE_MODE_CANDLE_LIGHT: + sr130pc20_set_from_table(sd, "scene_mode", + state->regs->scene_mode, + ARRAY_SIZE(state->regs->scene_mode), val); + break; + + default: + cam_err("set_scene: error, not supported (%d)\n", val); + val = SCENE_MODE_NONE; + goto retry; + } + + state->scene_mode = val; + + cam_trace("X\n"); + return 0; +} + +/* PX: Set brightness */ +static int sr130pc20_set_exposure(struct v4l2_subdev *sd, s32 val) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + + if ((val < EV_MINUS_4) || (val > EV_PLUS_4)) { + cam_err("%s: error, invalid value(%d)\n", __func__, val); + return -EINVAL; + } + + sr130pc20_set_from_table(sd, "brightness", state->regs->ev, + ARRAY_SIZE(state->regs->ev), GET_EV_INDEX(val)); + + state->exposure.val = val; + + return err; +} + +static int sr130pc20_set_vt_mode(struct v4l2_subdev *sd, s32 val) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + + if (val == PREVIEW_VIDEOCALL) { + err = sr130pc20_set_from_table(sd, "VT_init_reg", + &state->regs->VT_init_reg, 1, 0); + cam_info("VT Mode\n"); + } else if (val == PREVIEW_SMARTSTAY) { + err = sr130pc20_set_from_table(sd, "SS_init_reg", + &state->regs->SS_init_reg, 1, 0); + cam_info("SMART STAY Mode\n"); + } + + state->vt_mode = val; + + return err; +} + +/* PX(NEW) */ +static int sr130pc20_set_capture_size(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + u32 width, height; + + if (unlikely(!state->capture.frmsize)) { + cam_warn("warning, capture resolution not set\n"); + state->capture.frmsize = sr130pc20_get_framesize( + sr130pc20_capture_frmsizes, + ARRAY_SIZE(sr130pc20_capture_frmsizes), + CAPTURE_SZ_1MP); + } + + width = state->capture.frmsize->width; + height = state->capture.frmsize->height; + + state->preview.update_frmsize = 1; + + cam_dbg("set capture size(%dx%d)\n", width, height); + + return 0; +} + +/* PX: Set sensor mode */ +static int sr130pc20_set_sensor_mode(struct v4l2_subdev *sd, s32 val) +{ + struct sr130pc20_state *state = to_state(sd); + + cam_trace("mode=%d\n", val); + + switch (val) { + case SENSOR_MOVIE: + /* We does not support movie mode when in VT. */ + if (state->vt_mode) { + state->sensor_mode = SENSOR_CAMERA; + cam_err("%s: error, Not support movie\n", __func__); + break; + } + /* We do not break. */ + + case SENSOR_CAMERA: + state->sensor_mode = val; + break; + + default: + cam_err("%s: error, Not support.(%d)\n", __func__, val); + state->sensor_mode = SENSOR_CAMERA; + WARN_ON(1); + break; + } + + return 0; +} + +/* PX: Set framerate */ +static int sr130pc20_set_frame_rate(struct v4l2_subdev *sd, s32 fps) +{ + struct sr130pc20_state *state = to_state(sd); + int err = -EIO; + int i = 0, fps_index = -1; + + if (!state->initialized || (state->req_fps < 0)) + return 0; + + cam_info("set frame rate %d\n", fps); + + if (fps > 25) + fps = 25; /* sensor limitation */ + + for (i = 0; i < ARRAY_SIZE(sr130pc20_framerates); i++) { + if (fps == sr130pc20_framerates[i].fps) { + fps_index = sr130pc20_framerates[i].index; + state->fps = fps; + state->req_fps = -1; + break; + } + } + + if (unlikely(fps_index < 0)) { + cam_err("set_fps: warning, not supported fps %d\n", fps); + return 0; + } + + err = sr130pc20_set_from_table(sd, "fps", state->regs->fps, + ARRAY_SIZE(state->regs->fps), fps_index); + CHECK_ERR_MSG(err, "fail to set framerate\n"); + + /*sr130pc20_control_stream(sd, STREAM_STOP);*/ + + return 0; +} + +static int sr130pc20_control_stream(struct v4l2_subdev *sd, u32 cmd) +{ + struct sr130pc20_state *state = to_state(sd); + int err = -EINVAL; + + if (cmd == STREAM_STOP) { + if (!((state->runmode == RUNMODE_RUNNING) + && state->capture.pre_req)) { + cam_info("STREAM STOP!!\n"); + // [ W/A : Skip stream off sr130pc20 to prevent I2C behavior (P130301-0098) + // - DPM timeout (kernel Panic) happen by I2C behavior during system suspending + // ] + if (state->vt_mode != PREVIEW_SMARTSTAY) { + err = sr130pc20_set_from_table(sd, "stream_stop", + &state->regs->stream_stop, 1, 0); + CHECK_ERR_MSG(err, "failed to stop stream\n"); + } + state->preview.update_frmsize = 1; + } + } else { + cam_info("STREAM START\n"); + return 0; + } + + switch (state->runmode) { + case RUNMODE_CAPTURING: + cam_dbg("Capture Stop!\n"); + state->runmode = RUNMODE_CAPTURING_STOP; + state->capture.ready = 0; + state->capture.lowlux_night = 0; + break; + + case RUNMODE_RUNNING: + cam_dbg("Preview Stop!\n"); + state->runmode = RUNMODE_RUNNING_STOP; + if (state->capture.pre_req) { + sr130pc20_prepare_fast_capture(sd); + state->capture.pre_req = 0; + } + break; + + case RUNMODE_RECORDING: + state->runmode = RUNMODE_RECORDING_STOP; + break; + + default: + break; + } + + /*msleep_debug(state->pdata->streamoff_delay, true);*/ + + return 0; +} + +/* PX: Set flash mode */ +static int sr130pc20_set_flash_mode(struct v4l2_subdev *sd, s32 val) +{ + struct sr130pc20_state *state = to_state(sd); + + /* movie flash mode should be set when recording is started */ +/* if (state->sensor_mode == SENSOR_MOVIE && !state->recording) + return 0;*/ + + if (state->flash.mode == val) { + cam_dbg("the same flash mode=%d\n", val); + return 0; + } + + if (val == FLASH_MODE_TORCH) + sr130pc20_flash_torch(sd, SR130PC20_FLASH_ON); + + if ((state->flash.mode == FLASH_MODE_TORCH) + && (val == FLASH_MODE_OFF)) + sr130pc20_flash_torch(sd, SR130PC20_FLASH_OFF); + + state->flash.mode = val; + cam_dbg("Flash mode = %d\n", val); + return 0; +} + +static int sr130pc20_check_esd(struct v4l2_subdev *sd, s32 val) +{ + u32 data = 0, size_h = 0, size_v = 0; + +/* To do */ + return 0; + +esd_out: + cam_err("Check ESD(%d): ESD Shock detected! val=0x%X\n\n", data, val); + return -ERESTART; +} + +/* returns the real iso currently used by sensor due to lighting + * conditions, not the requested iso we sent using s_ctrl. + */ +static inline int sr130pc20_get_exif_iso(struct v4l2_subdev *sd, u16 *iso) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + u8 read_value = 0; + unsigned short gain_value = 0; + + err = sr130pc20_writeb(sd, 0x03, 0x20); + CHECK_ERR_COND(err < 0, -ENODEV); + sr130pc20_readb(sd, 0xb0, &read_value); + + gain_value = ((read_value * 100) / 32) + 50; + cam_dbg("gain_value=%d, read_value=%d\n", gain_value, read_value); + + if (gain_value < 114) + *iso = 50; + else if (gain_value < 214) + *iso = 100; + else if (gain_value < 264) + *iso = 200; + else if (gain_value < 825) + *iso = 400; + else + *iso = 800; + + cam_dbg("gain_value=%d, ISO=%d\n", gain_value, *iso); + return 0; +} + +/* PX: Set ISO */ +static int __used sr130pc20_set_iso(struct v4l2_subdev *sd, s32 val) +{ + struct sr130pc20_state *state = to_state(sd); + + sr130pc20_set_from_table(sd, "iso", state->regs->iso, + ARRAY_SIZE(state->regs->iso), val); + + state->iso = val; + + cam_trace("X\n"); + return 0; +} + +/* PX: Return exposure time (ms) */ +static inline int sr130pc20_get_exif_exptime(struct v4l2_subdev *sd, + u32 *exp_time) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + u8 read_value1 = 0; + u8 read_value2 = 0; + u8 read_value3 = 0; + + err = sr130pc20_writeb(sd, 0x03, 0x20); + CHECK_ERR_COND(err < 0, -ENODEV); + + sr130pc20_readb(sd, 0x80, &read_value1); + sr130pc20_readb(sd, 0x81, &read_value2); + sr130pc20_readb(sd, 0x82, &read_value3); + + cam_dbg("exposure time read_value %d, %d, %d\n", + read_value1, read_value2, read_value3); + *exp_time = (read_value1 << 19) + + (read_value2 << 11) + (read_value3 << 3); + + cam_dbg("exposure time %dus\n", *exp_time); + return 0; +} + +static inline void sr130pc20_get_exif_flash(struct v4l2_subdev *sd, + u16 *flash) +{ + struct sr130pc20_state *state = to_state(sd); + + *flash = 0; + + switch (state->flash.mode) { + case FLASH_MODE_OFF: + *flash |= EXIF_FLASH_MODE_SUPPRESSION; + break; + + case FLASH_MODE_AUTO: + *flash |= EXIF_FLASH_MODE_AUTO; + break; + + case FLASH_MODE_ON: + case FLASH_MODE_TORCH: + *flash |= EXIF_FLASH_MODE_FIRING; + break; + + default: + break; + } + + if (state->flash.on) + *flash |= EXIF_FLASH_FIRED; +} + +/* PX: */ +static int sr130pc20_get_exif(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + u32 exposure_time = 0; + u32 int_dec, integer; + int OPCLK = 24000000; + + /* exposure time */ + state->exif.exp_time_den = 0; + sr130pc20_get_exif_exptime(sd, &exposure_time); + if (exposure_time) { + state->exif.exp_time_den = OPCLK / exposure_time; + } else { + state->exif.exp_time_den = 0; + } + + /* iso */ + state->exif.iso = 0; + sr130pc20_get_exif_iso(sd, &state->exif.iso); + + /* flash */ + sr130pc20_get_exif_flash(sd, &state->exif.flash); + + cam_dbg("EXIF: ex_time_den=%d, iso=%d, flash=0x%02X\n", + state->exif.exp_time_den, state->exif.iso, state->exif.flash); + + return 0; +} + +static int sr130pc20_set_preview_size(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + u32 width, height; + int err = -EINVAL; + + if (!state->preview.update_frmsize) + return 0; + + if (unlikely(!state->preview.frmsize)) { + cam_warn("warning, preview resolution not set\n"); + state->preview.frmsize = sr130pc20_get_framesize( + sr130pc20_preview_frmsizes, + ARRAY_SIZE(sr130pc20_preview_frmsizes), + PREVIEW_SZ_VGA); + } + + width = state->preview.frmsize->width; + height = state->preview.frmsize->height; + + cam_dbg("set preview size(%dx%d)\n", width, height); + + err = sr130pc20_set_from_table(sd, "preview_size", + state->regs->preview_size, ARRAY_SIZE(state->regs->preview_size), + state->preview.frmsize->index); + CHECK_ERR_MSG(err, "fail to set preview size\n"); + + state->preview.update_frmsize = 0; + + return 0; +} + +static int sr130pc20_start_preview(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + int err = -EINVAL; + + cam_info("Camera Preview start, runmode = %d\n", state->runmode); + + if ((state->runmode == RUNMODE_NOTREADY) || + (state->runmode == RUNMODE_CAPTURING)) { + cam_err("%s: error - Invalid runmode\n", __func__); + return -EPERM; + } + + state->focus.status = AF_RESULT_SUCCESS; + + /* Transit preview mode */ + err = sr130pc20_transit_preview_mode(sd); + CHECK_ERR_MSG(err, "preview_mode(%d)\n", err); + + /* Set preview size */ + sr130pc20_set_preview_size(sd); + + sr130pc20_control_stream(sd, STREAM_START); + + state->runmode = (state->sensor_mode == SENSOR_CAMERA) ? + RUNMODE_RUNNING : RUNMODE_RECORDING; + return 0; +} + +static int sr130pc20_set_capture(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + + cam_info("set_capture\n"); + + /* Set capture size */ + sr130pc20_set_capture_size(sd); + + /* Transit to capture mode */ + err = sr130pc20_transit_capture_mode(sd); + CHECK_ERR_MSG(err, "fail to capture_mode (%d)\n", err); + return 0; +} + +static int sr130pc20_prepare_fast_capture(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + + cam_info("prepare_fast_capture\n"); + + state->req_fmt.width = (state->capture.pre_req >> 16); + state->req_fmt.height = (state->capture.pre_req & 0xFFFF); + sr130pc20_set_framesize(sd, sr130pc20_capture_frmsizes, + ARRAY_SIZE(sr130pc20_capture_frmsizes), false); + + err = sr130pc20_set_capture(sd); + CHECK_ERR(err); + + state->capture.ready = 1; + + return 0; +} + +static int sr130pc20_start_capture(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + int err = -ENODEV, count; + u32 val = 0; + u32 night_delay; + + cam_info("start_capture\n"); + + if (!state->capture.ready) { + err = sr130pc20_set_capture(sd); + CHECK_ERR(err); + + sr130pc20_control_stream(sd, STREAM_START); + night_delay = 500; + } else + night_delay = 700; /* for completely skipping 1 frame. */ + + state->runmode = RUNMODE_CAPTURING; + + if (state->capture.lowlux_night) + msleep_debug(night_delay, true); + + /* Get EXIF */ + sr130pc20_get_exif(sd); + + return 0; +} + +/** + * sr200pc20_init_regs: Indentify chip and get pointer to reg table + * @ + */ +static int sr130pc20_init_regs(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + int err = -ENODEV; + u8 read_value = 0; + + err = sr130pc20_writeb(sd, 0x03, 0x00); + CHECK_ERR_COND(err < 0, -ENODEV); + + sr130pc20_readb(sd, 0x04, &read_value); + if (SR130PC20_CHIP_ID == read_value) + cam_info("Sensor ChipID: 0x%02X\n", SR130PC20_CHIP_ID); + else + cam_info("Sensor ChipID: 0x%02X, unknown chipID\n", read_value); + + state->regs = ®_datas; + + return 0; +} + + +/* PX(NEW) */ +static int sr130pc20_s_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + struct sr130pc20_state *state = to_state(sd); + s32 previous_index = 0; + + cam_dbg("%s: pixelformat = 0x%x, colorspace = 0x%x, width = %d, height = %d\n", + __func__, fmt->code, fmt->colorspace, fmt->width, fmt->height); + + v4l2_fill_pix_format(&state->req_fmt, fmt); + if (fmt->field < IS_MODE_CAPTURE_STILL) + state->format_mode = V4L2_PIX_FMT_MODE_PREVIEW; + else + state->format_mode = V4L2_PIX_FMT_MODE_CAPTURE; + + if (state->format_mode != V4L2_PIX_FMT_MODE_CAPTURE) { + previous_index = state->preview.frmsize ? + state->preview.frmsize->index : -1; + sr130pc20_set_framesize(sd, sr130pc20_preview_frmsizes, + ARRAY_SIZE(sr130pc20_preview_frmsizes), true); + + if (previous_index != state->preview.frmsize->index) + state->preview.update_frmsize = 1; + } else { + /* + * In case of image capture mode, + * if the given image resolution is not supported, + * use the next higher image resolution. */ + sr130pc20_set_framesize(sd, sr130pc20_capture_frmsizes, + ARRAY_SIZE(sr130pc20_capture_frmsizes), false); + + /* for maket app. + * Samsung camera app does not use unmatched ratio.*/ + if (unlikely(NULL == state->preview.frmsize)) { + cam_warn("warning, capture without preview resolution\n"); + } else if (unlikely(FRM_RATIO(state->preview.frmsize) + != FRM_RATIO(state->capture.frmsize))) { + cam_warn("warning, capture ratio " \ + "is different with preview ratio\n"); + } + } + + return 0; +} + +static int sr130pc20_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + cam_dbg("%s: index = %d\n", __func__, index); + + if (index >= ARRAY_SIZE(capture_fmts)) + return -EINVAL; + + *code = capture_fmts[index].code; + + return 0; +} + +static int sr130pc20_try_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + int num_entries; + int i; + + num_entries = ARRAY_SIZE(capture_fmts); + + cam_dbg("%s: code = 0x%x , colorspace = 0x%x, num_entries = %d\n", + __func__, fmt->code, fmt->colorspace, num_entries); + + for (i = 0; i < num_entries; i++) { + if (capture_fmts[i].code == fmt->code && + capture_fmts[i].colorspace == fmt->colorspace) { + cam_info("%s: match found, returning 0\n", __func__); + return 0; + } + } + + cam_err("%s: no match found, returning -EINVAL\n", __func__); + return -EINVAL; +} + + +static int sr130pc20_enum_framesizes(struct v4l2_subdev *sd, + struct v4l2_frmsizeenum *fsize) +{ + struct sr130pc20_state *state = to_state(sd); + + /* + * The camera interface should read this value, this is the resolution + * at which the sensor would provide framedata to the camera i/f + * In case of image capture, + * this returns the default camera resolution (VGA) + */ + if (state->format_mode != V4L2_PIX_FMT_MODE_CAPTURE) { + if (unlikely(state->preview.frmsize == NULL)) { + cam_err("%s: error\n", __func__); + return -EFAULT; + } + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = state->preview.frmsize->width; + fsize->discrete.height = state->preview.frmsize->height; + } else { + if (unlikely(state->capture.frmsize == NULL)) { + cam_err("%s: error\n", __func__); + return -EFAULT; + } + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = state->capture.frmsize->width; + fsize->discrete.height = state->capture.frmsize->height; + } + + return 0; +} + +static int sr130pc20_g_parm(struct v4l2_subdev *sd, + struct v4l2_streamparm *param) +{ + return 0; +} + +static int sr130pc20_s_parm(struct v4l2_subdev *sd, + struct v4l2_streamparm *param) +{ + struct sr130pc20_state *state = to_state(sd); + + state->req_fps = param->parm.capture.timeperframe.denominator / + param->parm.capture.timeperframe.numerator; + + cam_dbg("s_parm state->fps=%d, state->req_fps=%d\n", + state->fps, state->req_fps); + + if ((state->req_fps < 0) || (state->req_fps > 30)) { + cam_err("%s: error, invalid frame rate %d. we'll set to 30\n", + __func__, state->req_fps); + state->req_fps = 0; + } + + return sr130pc20_set_frame_rate(sd, state->req_fps); +} + +static int sr130pc20_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + + if (!state->initialized) { + cam_err("%s: WARNING, camera not initialized\n", __func__); + return 0; + } + + mutex_lock(&state->ctrl_lock); + + switch (ctrl->id) { + case V4L2_CID_CAMERA_EXIF_EXPTIME: + if (state->sensor_mode == SENSOR_CAMERA) + ctrl->value = state->exif.exp_time_den; + else + ctrl->value = 24; + break; + + case V4L2_CID_CAMERA_EXIF_ISO: + if (state->sensor_mode == SENSOR_CAMERA) + ctrl->value = state->exif.iso; + else + ctrl->value = 100; + break; + + case V4L2_CID_CAMERA_EXIF_FLASH: + if (state->sensor_mode == SENSOR_CAMERA) + ctrl->value = state->exif.flash; + else + sr130pc20_get_exif_flash(sd, (u16 *)ctrl->value); + break; + +#if !defined(CONFIG_CAM_YUV_CAPTURE) + case V4L2_CID_CAM_JPEG_MAIN_SIZE: + ctrl->value = state->jpeg.main_size; + break; + + case V4L2_CID_CAM_JPEG_MAIN_OFFSET: + ctrl->value = state->jpeg.main_offset; + break; + + case V4L2_CID_CAM_JPEG_THUMB_SIZE: + ctrl->value = state->jpeg.thumb_size; + break; + + case V4L2_CID_CAM_JPEG_THUMB_OFFSET: + ctrl->value = state->jpeg.thumb_offset; + break; + + case V4L2_CID_CAM_JPEG_QUALITY: + ctrl->value = state->jpeg.quality; + break; + + case V4L2_CID_CAM_JPEG_MEMSIZE: + ctrl->value = SENSOR_JPEG_SNAPSHOT_MEMSIZE; + break; +#endif + + case V4L2_CID_CAMERA_AUTO_FOCUS_RESULT: + ctrl->value = state->focus.status; + break; + + case V4L2_CID_CAMERA_WHITE_BALANCE: + case V4L2_CID_CAMERA_EFFECT: + case V4L2_CID_CAMERA_CONTRAST: + case V4L2_CID_CAMERA_SATURATION: + case V4L2_CID_CAMERA_SHARPNESS: + case V4L2_CID_CAMERA_OBJ_TRACKING_STATUS: + case V4L2_CID_CAMERA_SMART_AUTO_STATUS: + default: + cam_err("%s: WARNING, unknown Ctrl-ID 0x%x\n", + __func__, ctrl->id); + err = 0; /* we return no error. */ + break; + } + + mutex_unlock(&state->ctrl_lock); + + return err; +} + +static int sr130pc20_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + + if (!state->initialized && ctrl->id != V4L2_CID_CAMERA_SENSOR_MODE + && ctrl->id != V4L2_CID_CAMERA_VT_MODE) { + cam_warn("%s: WARNING, camera not initialized. ID = %d(0x%X)\n", + __func__, ctrl->id - V4L2_CID_PRIVATE_BASE, + ctrl->id - V4L2_CID_PRIVATE_BASE); + return 0; + } + + cam_dbg("%s: ID =%d, val = %d\n", + __func__, ctrl->id - V4L2_CID_PRIVATE_BASE, ctrl->value); + + mutex_lock(&state->ctrl_lock); + + switch (ctrl->id) { + case V4L2_CID_CAMERA_SENSOR_MODE: + err = sr130pc20_set_sensor_mode(sd, ctrl->value); + break; + + case V4L2_CID_CAMERA_BRIGHTNESS: + err = sr130pc20_set_exposure(sd, ctrl->value); + break; + + case V4L2_CID_CAMERA_WHITE_BALANCE: + err = sr130pc20_set_from_table(sd, "white balance", + state->regs->white_balance, + ARRAY_SIZE(state->regs->white_balance), ctrl->value); + state->wb.mode = ctrl->value; + break; + + case V4L2_CID_CAMERA_EFFECT: + err = sr130pc20_set_from_table(sd, "effects", + state->regs->effect, + ARRAY_SIZE(state->regs->effect), ctrl->value); + break; + + case V4L2_CID_CAMERA_METERING: + err = sr130pc20_set_from_table(sd, "metering", + state->regs->metering, + ARRAY_SIZE(state->regs->metering), ctrl->value); + break; + + case V4L2_CID_CAMERA_SCENE_MODE: + err = sr130pc20_set_scene_mode(sd, ctrl->value); + break; + + case V4L2_CID_CAMERA_CHECK_ESD: + err = sr130pc20_check_esd(sd, ctrl->value); + break; + + case V4L2_CID_CAMERA_ISO: + err = sr130pc20_set_iso(sd, ctrl->value); + break; + + case V4L2_CID_CAMERA_CAPTURE_MODE: + if (RUNMODE_RUNNING == state->runmode) + state->capture.pre_req = ctrl->value; + break; + + case V4L2_CID_CAMERA_VT_MODE: + err = sr130pc20_set_vt_mode(sd, ctrl->value); + break; + + case V4L2_CID_CAMERA_ANTI_BANDING: + break; + + case V4L2_CID_CAMERA_OBJECT_POSITION_X: + case V4L2_CID_CAMERA_OBJECT_POSITION_Y: + case V4L2_CID_CAMERA_TOUCH_AF_START_STOP: + case V4L2_CID_CAMERA_FOCUS_MODE: + case V4L2_CID_CAMERA_SET_AUTO_FOCUS: + case V4L2_CID_CAMERA_FLASH_MODE: + case V4L2_CID_CAMERA_CONTRAST: + case V4L2_CID_CAMERA_SATURATION: + case V4L2_CID_CAMERA_SHARPNESS: + case V4L2_CID_CAMERA_FRAME_RATE: + case V4L2_CID_CAMERA_AE_LOCK_UNLOCK: + case V4L2_CID_CAMERA_AWB_LOCK_UNLOCK: + default: + cam_err("%s: WARNING, unknown Ctrl-ID 0x%x\n", + __func__, ctrl->id); + /* we return no error. */ + break; + } + + mutex_unlock(&state->ctrl_lock); + CHECK_ERR_MSG(err, "s_ctrl failed %d\n", err) + + return 0; +} + +static int sr130pc20_s_ext_ctrl(struct v4l2_subdev *sd, + struct v4l2_ext_control *ctrl) +{ + return 0; +} + +static int sr130pc20_s_ext_ctrls(struct v4l2_subdev *sd, + struct v4l2_ext_controls *ctrls) +{ + struct v4l2_ext_control *ctrl = ctrls->controls; + int ret; + int i; + + for (i = 0; i < ctrls->count; i++, ctrl++) { + ret = sr130pc20_s_ext_ctrl(sd, ctrl); + + if (ret) { + ctrls->error_idx = i; + break; + } + } + + return ret; +} + +static int sr130pc20_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct sr130pc20_state *state = to_state(sd); + int err = 0; + + cam_info("stream mode = %d\n", enable); + + BUG_ON(!state->initialized); + + switch (enable) { + case STREAM_MODE_CAM_OFF: + if (state->pdata->is_mipi) + err = sr130pc20_control_stream(sd, STREAM_STOP); + break; + + case STREAM_MODE_CAM_ON: + switch (state->sensor_mode) { + case SENSOR_CAMERA: + if (state->format_mode == V4L2_PIX_FMT_MODE_CAPTURE) + err = sr130pc20_start_capture(sd); + else + err = sr130pc20_start_preview(sd); + break; + + case SENSOR_MOVIE: + err = sr130pc20_start_preview(sd); + break; + + default: + break; + } + break; + + case STREAM_MODE_MOVIE_OFF: + cam_info("movie off"); + state->recording = 0; + break; + + case STREAM_MODE_MOVIE_ON: + cam_info("movie on"); + state->recording = 1; + break; + + default: + cam_err("%s: error - Invalid stream mode\n", __func__); + break; + } + + CHECK_ERR_MSG(err, "failed\n"); + + return 0; +} + +static inline int sr130pc20_check_i2c(struct v4l2_subdev *sd, u16 data) +{ + int err; + u32 val = 0; + + err = sr130pc20_readw(sd, 0x0000, &val); + if (unlikely(err)) + return err; + + cam_dbg("version: 0x%04X is 0x6017?\n", val); + return 0; +} + +static void sr130pc20_init_parameter(struct v4l2_subdev *sd) +{ + struct sr130pc20_state *state = to_state(sd); + + state->runmode = RUNMODE_INIT; + + /* Default state values */ + state->scene_mode = SCENE_MODE_NONE; + state->wb.mode = WHITE_BALANCE_AUTO; + state->light_level = LUX_LEVEL_MAX; + + /* Set update_frmsize to 1 for case of power reset */ + state->preview.update_frmsize = 1; + + /* Initialize focus field for case of init after power reset. */ + memset(&state->focus, 0, sizeof(state->focus)); + + state->lux_level_flash = LUX_LEVEL_FLASH_ON; + state->shutter_level_flash = 0x0; + +} + +static int sr130pc20_init(struct v4l2_subdev *sd, u32 val) +{ + struct sr130pc20_state *state = to_state(sd); + int err = -EINVAL; + + cam_info("init: start (%s)\n", __DATE__); + +#ifdef CONFIG_LOAD_FILE + err = sr130pc20_regs_table_init(); + CHECK_ERR_MSG(err, "loading setfile fail!\n"); +#endif + err = sr130pc20_init_regs(sd); + CHECK_ERR_MSG(err, "failed to indentify sensor chip\n"); + + err = sr130pc20_set_from_table(sd, "init_reg", + &state->regs->init_reg, 1, 0); + + CHECK_ERR_MSG(err, "failed to initialize camera device\n"); + sr130pc20_init_parameter(sd); + state->initialized = 1; + + return 0; +} + +/* + * s_config subdev ops + * With camera device, we need to re-initialize + * every single opening time therefor, + * it is not necessary to be initialized on probe time. + * except for version checking + * NOTE: version checking is optional + */ +static int sr130pc20_s_config(struct v4l2_subdev *sd, + int irq, void *platform_data) +{ + struct sr130pc20_state *state = to_state(sd); + int i; + + if (!platform_data) { + cam_err("%s: error, no platform data\n", __func__); + return -ENODEV; + } + state->pdata = platform_data; + state->dbg_level = &state->pdata->dbg_level; + + /* + * Assign default format and resolution + * Use configured default information in platform data + * or without them, use default information in driver + */ + state->req_fmt.width = state->pdata->default_width; + state->req_fmt.height = state->pdata->default_height; + + if (!state->pdata->pixelformat) + state->req_fmt.pixelformat = DEFAULT_PIX_FMT; + else + state->req_fmt.pixelformat = state->pdata->pixelformat; + + if (!state->pdata->freq) + state->freq = DEFAULT_MCLK; /* 24MHz default */ + else + state->freq = state->pdata->freq; + + state->preview.frmsize = state->capture.frmsize = NULL; + state->sensor_mode = SENSOR_CAMERA; + state->format_mode = V4L2_PIX_FMT_MODE_PREVIEW; + state->fps = 0; + state->req_fps = -1; + + /* Initialize the independant HW module like flash here */ + state->flash.mode = FLASH_MODE_OFF; + state->flash.on = 0; + + for (i = 0; i < ARRAY_SIZE(sr130pc20_ctrls); i++) + sr130pc20_ctrls[i].value = sr130pc20_ctrls[i].default_value; + +#ifdef SR130PC20_SUPPORT_FLASH + if (sr130pc20_is_hwflash_on(sd)) + state->flash.ignore_flash = 1; +#endif + + state->regs = ®_datas; + + return 0; +} + +static const struct v4l2_subdev_core_ops sr130pc20_core_ops = { + .init = sr130pc20_init, /* initializing API */ + .g_ctrl = sr130pc20_g_ctrl, + .s_ctrl = sr130pc20_s_ctrl, + .s_ext_ctrls = sr130pc20_s_ext_ctrls, + /*eset = sr130pc20_reset, */ +}; + +static const struct v4l2_subdev_video_ops sr130pc20_video_ops = { + .s_mbus_fmt = sr130pc20_s_mbus_fmt, + .enum_framesizes = sr130pc20_enum_framesizes, + .enum_mbus_fmt = sr130pc20_enum_mbus_fmt, + .try_mbus_fmt = sr130pc20_try_mbus_fmt, + .g_parm = sr130pc20_g_parm, + .s_parm = sr130pc20_s_parm, + .s_stream = sr130pc20_s_stream, +}; + +static const struct v4l2_subdev_ops sr130pc20_ops = { + .core = &sr130pc20_core_ops, + .video = &sr130pc20_video_ops, +}; + + +/* + * sr130pc20_probe + * Fetching platform data is being done with s_config subdev call. + * In probe routine, we just register subdev device + */ +static int sr130pc20_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct v4l2_subdev *sd; + struct sr130pc20_state *state; + int err = -EINVAL; + + state = kzalloc(sizeof(struct sr130pc20_state), GFP_KERNEL); + if (unlikely(!state)) { + dev_err(&client->dev, "probe, fail to get memory\n"); + return -ENOMEM; + } + + mutex_init(&state->ctrl_lock); + + state->runmode = RUNMODE_NOTREADY; + sd = &state->sd; + strcpy(sd->name, SR130PC20_DRIVER_NAME); + + /* Registering subdev */ + v4l2_i2c_subdev_init(sd, client, &sr130pc20_ops); + + state->workqueue = create_workqueue("cam_workqueue"); + if (unlikely(!state->workqueue)) { + dev_err(&client->dev, "probe, fail to create workqueue\n"); + goto err_out; + } + + err = sr130pc20_s_config(sd, 0, client->dev.platform_data); + CHECK_ERR_MSG(err, "fail to s_config\n"); + + printk(KERN_DEBUG "%s %s: driver probed!!\n", + dev_driver_string(&client->dev), dev_name(&client->dev)); + + return 0; + +err_out: + kfree(state); + return -ENOMEM; +} + +static int sr130pc20_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct sr130pc20_state *state = to_state(sd); + + destroy_workqueue(state->workqueue); + + /* Check whether flash is on when unlolading driver, + * to preventing Market App from controlling improperly flash. + * It isn't necessary in case that you power flash down + * in power routine to turn camera off.*/ + if (unlikely(state->flash.on && !state->flash.ignore_flash)) + sr130pc20_flash_torch(sd, SR130PC20_FLASH_OFF); + + v4l2_device_unregister_subdev(sd); + mutex_destroy(&state->ctrl_lock); + kfree(state); + + printk(KERN_DEBUG "%s %s: driver removed!!\n", + dev_driver_string(&client->dev), dev_name(&client->dev)); + return 0; +} + +static int is_sysdev(struct device *dev, void *str) +{ + return !strcmp(dev_name(dev), (char *)str) ? 1 : 0; +} + +static ssize_t cam_loglevel_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + char temp_buf[60] = {0,}; + + sprintf(buf, "Log Level: "); + if (dbg_level & CAMDBG_LEVEL_TRACE) { + sprintf(temp_buf, "trace "); + strcat(buf, temp_buf); + } + + if (dbg_level & CAMDBG_LEVEL_DEBUG) { + sprintf(temp_buf, "debug "); + strcat(buf, temp_buf); + } + + if (dbg_level & CAMDBG_LEVEL_INFO) { + sprintf(temp_buf, "info "); + strcat(buf, temp_buf); + } + + sprintf(temp_buf, "\n - warn and error level is always on\n\n"); + strcat(buf, temp_buf); + + return strlen(buf); +} + +static ssize_t cam_loglevel_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + printk(KERN_DEBUG "CAM buf=%s, count=%d\n", buf, count); + + if (strstr(buf, "trace")) + dbg_level |= CAMDBG_LEVEL_TRACE; + else + dbg_level &= ~CAMDBG_LEVEL_TRACE; + + if (strstr(buf, "debug")) + dbg_level |= CAMDBG_LEVEL_DEBUG; + else + dbg_level &= ~CAMDBG_LEVEL_DEBUG; + + if (strstr(buf, "info")) + dbg_level |= CAMDBG_LEVEL_INFO; + + return count; +} + +static DEVICE_ATTR(loglevel, 0664, cam_loglevel_show, cam_loglevel_store); + +static int sr130pc20_create_dbglogfile(struct class *cls) +{ + struct device *dev; + int err; + + dbg_level |= CAMDBG_LEVEL_DEFAULT; + + dev = class_find_device(cls, NULL, "front", is_sysdev); + if (unlikely(!dev)) { + pr_info("[SR130PC20] can not find front device\n"); + return 0; + } + + err = device_create_file(dev, &dev_attr_loglevel); + if (unlikely(err < 0)) { + pr_err("cam_init: failed to create device file, %s\n", + dev_attr_loglevel.attr.name); + } + + return 0; +} + +static const struct i2c_device_id sr130pc20_id[] = { + { SR130PC20_DRIVER_NAME, 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, sr130pc20_id); + +static struct i2c_driver v4l2_i2c_driver = { + .driver.name = SR130PC20_DRIVER_NAME, + .probe = sr130pc20_probe, + .remove = sr130pc20_remove, + .id_table = sr130pc20_id, +}; + +static int __init v4l2_i2c_drv_init(void) +{ + pr_info("%s: %s called\n", __func__, SR130PC20_DRIVER_NAME); /* dslim*/ + sr130pc20_create_file(camera_class); + sr130pc20_create_dbglogfile(camera_class); + return i2c_add_driver(&v4l2_i2c_driver); +} + +static void __exit v4l2_i2c_drv_cleanup(void) +{ + pr_info("%s: %s called\n", __func__, SR130PC20_DRIVER_NAME); /* dslim*/ + i2c_del_driver(&v4l2_i2c_driver); +} + +module_init(v4l2_i2c_drv_init); +module_exit(v4l2_i2c_drv_cleanup); + +MODULE_DESCRIPTION("SILICONFILE SR130PC20 1.3MP SOC camera driver"); +MODULE_AUTHOR("Dong-Seong Lim "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/sr130pc20.h b/drivers/media/video/sr130pc20.h new file mode 100755 index 0000000..a831007 --- /dev/null +++ b/drivers/media/video/sr130pc20.h @@ -0,0 +1,646 @@ +/* drivers/media/video/sr130pc20.h + * + * Driver for sr130pc20 (1.5MP Camera) from siliconfile + * + * Copyright (C) 2010, SAMSUNG ELECTRONICS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * - change date: 2012.06.28 + */ + +#ifndef __SR130PC20_H__ +#define __SR130PC20_H__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SR130PC20_DRIVER_NAME "SR130PC20" + +#define SR130PC20_DELAY 0xFFFF0000 + +/************************************ + * FEATURE DEFINITIONS + ************************************/ +#define CONFIG_CAM_YUV_CAPTURE +#define CONFIG_CAM_I2C_LITTLE_ENDIAN +/* #define CONFIG_LOAD_FILE *//* for tuning */ +/* #define CONFIG_DEBUG_NO_FRAME */ + +/** Debuging Feature **/ +// #define CONFIG_CAM_DEBUG */ +// #define CONFIG_CAM_TRACE *//* Enable it with CONFIG_CAM_DEBUG */ +// #define CONFIG_CAM_AF_DEBUG *//* Enable it with CONFIG_CAM_DEBUG */ +#define DEBUG_WRITE_REGS +/***********************************/ + +#ifdef CONFIG_VIDEO_SR130PC20_DEBUG +enum { + SR130PC20_DEBUG_I2C = 1U << 0, + SR130PC20_DEBUG_I2C_BURSTS = 1U << 1, +}; +static uint32_t sr130pc20_debug_mask = SR130PC20_DEBUG_I2C_BURSTS; +module_param_named(debug_mask, sr130pc20_debug_mask, uint, S_IWUSR | S_IRUGO); + +#define sr130pc20_debug(mask, x...) \ + do { \ + if (sr130pc20_debug_mask & mask) \ + pr_info(x); \ + } while (0) +#else +#define sr130pc20_debug(mask, x...) +#endif + +#define TAG_NAME "["SR130PC20_DRIVER_NAME"]"" " + +/* Define debug level */ +#define CAMDBG_LEVEL_ERR (1 << 0) +#define CAMDBG_LEVEL_WARN (1 << 1) +#define CAMDBG_LEVEL_INFO (1 << 2) +#define CAMDBG_LEVEL_DEBUG (1 << 3) +#define CAMDBG_LEVEL_TRACE (1 << 4) +#define CAMDBG_LEVEL_DEFAULT \ + (CAMDBG_LEVEL_ERR | CAMDBG_LEVEL_WARN | CAMDBG_LEVEL_INFO) + +#define cam_err(fmt, ...) \ + printk(KERN_ERR TAG_NAME fmt, ##__VA_ARGS__) +#define cam_warn(fmt, ...) \ + printk(KERN_WARNING TAG_NAME fmt, ##__VA_ARGS__) +#define cam_info(fmt, ...) \ + printk(KERN_INFO TAG_NAME fmt, ##__VA_ARGS__) + +#if defined(CONFIG_CAM_DEBUG) +#define cam_dbg(fmt, ...) \ + printk(KERN_DEBUG TAG_NAME fmt, ##__VA_ARGS__) +#else +#define cam_dbg(fmt, ...) \ + do { \ + if (dbg_level & CAMDBG_LEVEL_DEBUG) \ + printk(KERN_DEBUG TAG_NAME fmt, ##__VA_ARGS__); \ + } while (0) +#endif + +#if defined(CONFIG_CAM_DEBUG) && defined(CONFIG_CAM_TRACE) +#define cam_trace(fmt, ...) cam_dbg("%s: " fmt, __func__, ##__VA_ARGS__); +#else +#define cam_trace(fmt, ...) \ + do { \ + if (dbg_level & CAMDBG_LEVEL_TRACE) \ + printk(KERN_DEBUG TAG_NAME "%s: " fmt, \ + __func__, ##__VA_ARGS__); \ + } while (0) +#endif + +#if defined(CONFIG_CAM_DEBUG) && defined(CONFIG_CAM_AF_DEBUG) +#define af_dbg(fmt, ...) cam_dbg(fmt, ##__VA_ARGS__); +#else +#define af_dbg(fmt, ...) +#endif +#if defined(CONFIG_CAM_DEBUG) && defined(CONFIG_CAM_BOOT_DEBUG) +#define boot_dbg(fmt, ...) cam_dbg(fmt, ##__VA_ARGS__); +#else +#define boot_dbg(fmt, ...) +#endif + +#if 0 +#define cam_bug_on(arg...) \ + do { cam_err(arg); BUG_ON(1); } while (0) +#else +#define cam_bug_on(arg...) +#endif + +#define CHECK_ERR_COND(condition, ret) \ + do { if (unlikely(condition)) return ret; } while (0) +#define CHECK_ERR_COND_MSG(condition, ret, fmt, ...) \ + if (unlikely(condition)) { \ + cam_err("%s: error, " fmt, __func__, ##__VA_ARGS__); \ + return ret; \ + } + +#define CHECK_ERR(x) CHECK_ERR_COND(((x) < 0), (x)) +#define CHECK_ERR_MSG(x, fmt, ...) \ + CHECK_ERR_COND_MSG(((x) < 0), (x), fmt, ##__VA_ARGS__) + +/* result values returned to HAL */ +enum af_result_status { + AF_RESULT_NONE = 0x00, + AF_RESULT_FAILED = 0x01, + AF_RESULT_SUCCESS = 0x02, + AF_RESULT_CANCELLED = 0x04, + AF_RESULT_DOING = 0x08 +}; + +enum af_operation_status { + AF_NONE = 0, + AF_START, + AF_CANCEL, +}; + +enum preflash_status { + PREFLASH_NONE = 0, + PREFLASH_OFF, + PREFLASH_ON, +}; + +enum sr130pc20_oprmode { + SR130PC20_OPRMODE_VIDEO = 0, + SR130PC20_OPRMODE_IMAGE = 1, +}; + +enum stream_cmd { + STREAM_STOP, + STREAM_START, +}; + +enum wide_req_cmd { + WIDE_REQ_NONE, + WIDE_REQ_CHANGE, + WIDE_REQ_RESTORE, +}; + +/* Preview Size List: refer to the belows. */ +enum sr130pc20_preview_frame_size { + PREVIEW_SZ_QCIF = 0, /* 176x144 */ + PREVIEW_SZ_320x240, /* 320x240 */ + PREVIEW_SZ_CIF, /* 352x288 */ + PREVIEW_SZ_528x432, /* 528x432 */ + PREVIEW_SZ_VGA, /* 640x480 */ + PREVIEW_SZ_D1, /* 720x480 */ + PREVIEW_SZ_880x720, /* 880x720 */ + PREVIEW_SZ_SVGA, /* 800x600 */ + PREVIEW_SZ_1024x576, /* 1024x576, 16:9 */ + PREVIEW_SZ_1024x616, /* 1024x616, ? */ + PREVIEW_SZ_XGA, /* 1024x768 */ + PREVIEW_SZ_PVGA, /* 1280x720 */ + PREVIEW_SZ_SXGA, /* 1280x1024 */ + PREVIEW_SZ_MAX, +}; + +/* Capture Size List: Capture size is defined as below. + * + * CAPTURE_SZ_VGA: 640x480 + * CAPTURE_SZ_WVGA: 800x480 + * CAPTURE_SZ_SVGA: 800x600 + * CAPTURE_SZ_WSVGA: 1024x600 + * CAPTURE_SZ_1MP: 1280x960 + * CAPTURE_SZ_W1MP: 1600x960 + * CAPTURE_SZ_2MP: UXGA - 1600x1200 + * CAPTURE_SZ_W2MP: 35mm Academy Offset Standard 1.66 + * 2048x1232, 2.4MP + * CAPTURE_SZ_3MP: QXGA - 2048x1536 + * CAPTURE_SZ_W4MP: WQXGA - 2560x1536 + * CAPTURE_SZ_5MP: 2560x1920 + */ + +enum sr130pc20_capture_frame_size { + /*CAPTURE_SZ_VGA = 0,*/ /* 640x480 */ + /*CAPTURE_SZ_960_720,*/ + CAPTURE_SZ_1MP,/* 1280x960 */ + CAPTURE_SZ_MAX, +}; + +#define PREVIEW_WIDE_SIZE PREVIEW_SZ_1024x576 +#define CAPTURE_WIDE_SIZE CAPTURE_SZ_W2MP + +enum frame_ratio { + FRMRATIO_QCIF = 12, /* 11 : 9 */ + FRMRATIO_VGA = 13, /* 4 : 3 */ + FRMRATIO_D1 = 15, /* 3 : 2 */ + FRMRATIO_WVGA = 16, /* 5 : 3 */ + FRMRATIO_HD = 17, /* 16 : 9 */ +}; + +enum sr130pc20_fps_index { + I_FPS_0, + I_FPS_7, + I_FPS_10, + I_FPS_12, + I_FPS_15, + I_FPS_25, + I_FPS_30, + I_FPS_MAX, +}; + +enum ae_awb_lock { + AEAWB_UNLOCK = 0, + AEAWB_LOCK, + AEAWB_LOCK_MAX, +}; + +enum runmode { + RUNMODE_NOTREADY, + RUNMODE_INIT, + /*RUNMODE_IDLE,*/ + RUNMODE_RUNNING, /* previewing */ + RUNMODE_RUNNING_STOP, + RUNMODE_CAPTURING, + RUNMODE_CAPTURING_STOP, + RUNMODE_RECORDING, /* camcorder mode */ + RUNMODE_RECORDING_STOP, +}; + +enum sr130pc20_stby_type { + SR130PC20_STBY_HW, + SR130PC20_STBY_SW, +}; + +enum sr130_pc20_preview_mode { + PREVIEW_CAMERA = 1, + PREVIEW_VIDEOCALL, + PREVIEW_SMARTSTAY, +}; + +struct sr130pc20_control { + u32 id; + s32 value; + s32 default_value; +}; + +#define SR130PC20_INIT_CONTROL(ctrl_id, default_val) \ + { \ + .id = ctrl_id, \ + .value = default_val, \ + .default_value = default_val, \ + } + +struct sr130pc20_framesize { + s32 index; + u32 width; + u32 height; +}; + +#define FRM_RATIO(framesize) \ + (((framesize)->width) * 10 / ((framesize)->height)) + +struct sr130pc20_fps { + u32 index; + u32 fps; +}; + +struct sr130pc20_version { + u32 major; + u32 minor; +}; + +struct sr130pc20_date_info { + u32 year; + u32 month; + u32 date; +}; + +struct sr130pc20_firmware { + u32 addr; + u32 size; +}; + +struct sr130pc20_jpeg_param { + u32 enable; + u32 quality; + u32 main_size; /* Main JPEG file size */ + u32 thumb_size; /* Thumbnail file size */ + u32 main_offset; + u32 thumb_offset; + /* u32 postview_offset; */ +}; + +struct sr130pc20_position { + s32 x; + s32 y; +}; + +struct sr130pc20_rect { + s32 x; + s32 y; + u32 width; + u32 height; +}; + +struct gps_info_common { + u32 direction; + u32 dgree; + u32 minute; + u32 second; +}; + +struct sr130pc20_gps_info { + u8 gps_buf[8]; + u8 altitude_buf[4]; + s32 gps_timeStamp; +}; + +struct sr130pc20_preview { + const struct sr130pc20_framesize *frmsize; + u32 update_frmsize:1; + u32 fast_ae:1; +}; + +struct sr130pc20_capture { + const struct sr130pc20_framesize *frmsize; + u32 pre_req; /* for fast capture */ + u32 ae_manual_mode:1; + u32 lowlux_night:1; + u32 ready:1; /* for fast capture */ +}; + +/* Focus struct */ +struct sr130pc20_focus { + enum v4l2_focusmode mode; + enum af_result_status status; + + u32 pos_x; + u32 pos_y; + + u32 start:1; /* enum v4l2_auto_focus*/ + u32 touch:1; + u32 lock:1; /* set if single AF is done */ +}; + +/* struct for sensor specific data */ +struct sr130pc20_ae_gain_offset { + u32 ae_auto; + u32 ae_now; + u32 ersc_auto; + u32 ersc_now; + + u32 ae_ofsetval; + u32 ae_maxdiff; +}; + +/* Flash struct */ +struct sr130pc20_flash { + struct sr130pc20_ae_gain_offset ae_offset; + enum v4l2_flash_mode mode; + enum preflash_status preflash; + u32 awb_delay; + u32 ae_scl; /* for back-up */ + u32 on:1; /* flash on/off */ + u32 ignore_flash:1; + u32 ae_flash_lock:1; +}; + +/* Exposure struct */ +struct sr130pc20_exposure { + s32 val; /* exposure value */ + u32 ae_lock:1; +}; + +/* White Balance struct */ +struct sr130pc20_whitebalance { + enum v4l2_wb_mode mode; /* wb mode */ + u32 awb_lock:1; +}; + +struct sr130pc20_exif { + u16 exp_time_den; + u16 iso; + u16 flash; + + /*int bv;*/ /* brightness */ + /*int ebv;*/ /* exposure bias */ +}; + +/* EXIF - flash filed */ +#define EXIF_FLASH_FIRED (0x01) +#define EXIF_FLASH_MODE_FIRING (0x01 << 3) +#define EXIF_FLASH_MODE_SUPPRESSION (0x02 << 3) +#define EXIF_FLASH_MODE_AUTO (0x03 << 3) + +struct sr130pc20_stream_time { + struct timeval curr_time; + struct timeval before_time; +}; + +#define GET_ELAPSED_TIME(cur, before) \ + (((cur).tv_sec - (before).tv_sec) * USEC_PER_SEC \ + + ((cur).tv_usec - (before).tv_usec)) + +typedef u16 sr130pc20_regset_t; + +typedef struct isx012_regset { + u16 subaddr; + u32 value; + u32 len; +} isx012_regset_t; + +#ifdef CONFIG_LOAD_FILE +#define DEBUG_WRITE_REGS +struct regset_table { + const char *const name; +}; + +#define SR130PC20_REGSET(x, y, z) \ + [(x)] = { \ + .name = #y, \ + } + +#define SR130PC20_REGSET_TABLE(y, z) \ + { \ + .name = #y, \ + } + +#else /* !CONFIG_LOAD_FILE */ + +struct regset_table { + const sr130pc20_regset_t * const reg; + const u32 array_size; +#ifdef DEBUG_WRITE_REGS + const char * const name; +#endif + const u32 burst; /* on/off */ +}; + +#ifdef DEBUG_WRITE_REGS +#define SR130PC20_REGSET(x, y, z) \ + [(x)] = { \ + .reg = (y), \ + .array_size = ARRAY_SIZE((y)), \ + .name = #y, \ + .burst = z, \ + } +#define SR130PC20_REGSET_TABLE(y, z) \ + { \ + .reg = (y), \ + .array_size = ARRAY_SIZE((y)), \ + .name = #y, \ + .burst = z, \ + } +#else /* !DEBUG_WRITE_REGS */ +#define SR130PC20_REGSET(x, y, z) \ + [(x)] = { \ + .reg = (y), \ + .array_size = ARRAY_SIZE((y)), \ + .burst = z, \ + } +#define SR130PC20_REGSET_TABLE(y, z) \ + { \ + .reg = (y), \ + .array_size = ARRAY_SIZE((y)), \ + .burst = z, \ + } +#endif /* DEBUG_WRITE_REGS */ + +#endif /* CONFIG_LOAD_FILE */ + +#define EV_MIN_VLAUE EV_MINUS_4 +#define GET_EV_INDEX(EV) ((EV) - (EV_MIN_VLAUE)) + +struct sr130pc20_regs { + struct regset_table ev[GET_EV_INDEX(EV_MAX_V4L2)]; + struct regset_table metering[METERING_MAX]; + struct regset_table iso[ISO_MAX]; + struct regset_table effect[IMAGE_EFFECT_MAX]; + struct regset_table white_balance[WHITE_BALANCE_MAX]; + struct regset_table preview_size[PREVIEW_SZ_MAX]; + struct regset_table capture_size[CAPTURE_SZ_MAX]; + struct regset_table scene_mode[SCENE_MODE_MAX]; + struct regset_table fps[I_FPS_MAX]; + /* camera mode */ + struct regset_table preview_mode; + struct regset_table capture_mode; + struct regset_table capture_mode_night; + struct regset_table stream_stop; + struct regset_table init_reg; + struct regset_table VT_init_reg; + struct regset_table SS_init_reg; +}; + +struct sr130pc20_state { + struct sr130pc20_platform_data *pdata; + struct v4l2_subdev sd; + struct v4l2_pix_format req_fmt; + struct sr130pc20_preview preview; + struct sr130pc20_capture capture; + struct sr130pc20_focus focus; + struct sr130pc20_flash flash; + struct sr130pc20_exposure exposure; + struct sr130pc20_whitebalance wb; + struct sr130pc20_exif exif; +#if !defined(CONFIG_CAM_YUV_CAPTURE) + struct sr130pc20_jpeg_param jpeg; +#endif + struct sr130pc20_stream_time stream_time; + const struct sr130pc20_regs *regs; + struct mutex ctrl_lock; + struct mutex af_lock; + struct workqueue_struct *workqueue; + struct work_struct af_work; + struct work_struct af_win_work; +#ifdef CONFIG_DEBUG_NO_FRAME + struct work_struct frame_work; +#endif + enum runmode runmode; + enum v4l2_sensor_mode sensor_mode; + enum v4l2_pix_format_mode format_mode; + enum v4l2_scene_mode scene_mode; + enum v4l2_iso_mode iso; + + s32 vt_mode; + s32 req_fps; + s32 fps; + s32 freq; /* MCLK in Hz */ + u32 one_frame_delay_ms; + u32 light_level; /* light level */ + u32 lux_level_flash; + u32 shutter_level_flash; + u8 *dbg_level; +#ifdef CONFIG_DEBUG_NO_FRAME + bool frame_check; +#endif + u32 recording:1; + u32 hd_videomode:1; + u32 need_wait_streamoff:1; + u32 initialized:1; +}; + +static inline struct sr130pc20_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct sr130pc20_state, sd); +} + +static inline int sr130pc20_restore_sensor_flash(struct v4l2_subdev *sd); +static int sr130pc20_set_capture(struct v4l2_subdev *sd); +static int sr130pc20_prepare_fast_capture(struct v4l2_subdev *sd); +static int sr130pc20_control_stream(struct v4l2_subdev *sd, u32 cmd); + +extern struct class *camera_class; +extern int sr130pc20_create_file(struct class *cls); + +#if !defined(CONFIG_CAM_YUV_CAPTURE) +/* JPEG MEMORY SIZE */ +#define SENSOR_JPEG_OUTPUT_MAXSIZE 0x29999A /*2726298bytes, 2.6M */ +#define EXTRA_MEMSIZE (0 * SZ_1K) +#define SENSOR_JPEG_SNAPSHOT_MEMSIZE \ + (((SENSOR_JPEG_OUTPUT_MAXSIZE + EXTRA_MEMSIZE + SZ_16K-1) / SZ_16K) * SZ_16K) +#endif + +/*********** Sensor specific ************/ +#define DELAY_SEQ 0xFF +#define SR130PC20_CHIP_ID 0xC1 + +#define SR130PC20_INTSRC_VINT (0x01 << 5) + +#define POLL_TIME_MS 10 +#define CAPTURE_POLL_TIME_MS 1000 + +/* maximum time for one frame in norma light */ +#define ONE_FRAME_DELAY_MS_NORMAL 66 +/* maximum time for one frame in low light: minimum 10fps. */ +#define ONE_FRAME_DELAY_MS_LOW 100 +/* maximum time for one frame in night mode: 6fps */ +#define ONE_FRAME_DELAY_MS_NIGHTMODE 166 + +/* level at or below which we need to enable flash when in auto mode */ +#define LUX_LEVEL_MAX 0x00 /* the brightest */ +#define LUX_LEVEL_LOW 0x3D /* low light */ +#define LUX_LEVEL_FLASH_ON 0x2B + +/* Count for loop */ +#define SR130PC20_CNT_CAPTURE_FRM 330 +#define SR130PC20_CNT_CLEAR_VINT 20 +#define SR130PC20_CNT_AE_STABLE 100 /* for checking MODESEL_FIX */ +#define SR130PC20_CNT_CAPTURE_AWB 3 /* 8 -> 3 */ +#define SR130PC20_CNT_OM_CHECK 30 +#define SR130PC20_CNT_CM_CHECK 280 /* 160 -> 180 */ +#define SR130PC20_CNT_STREAMOFF 300 + +#define AF_SEARCH_COUNT 550 /* about 6s */ +#define AE_STABLE_SEARCH_COUNT 7 + +/* Sensor AF first,second window size. + * we use constant values intead of reading sensor register */ +#define DEFAULT_WINDOW_WIDTH 80 +#define DEFAULT_WINDOW_HEIGHT 80 +#define AF_PRECISION 100 + +/* diff value fior fast AE in preview */ +#define AESCL_DIFF_FASTAE 1000 + + +/* + * Register Address Definition + */ + +/* The Path of Setfile */ +#ifdef CONFIG_LOAD_FILE +#include +#include +#include +#include +#include + +#define TUNING_FILE_PATH "/mnt/sdcard/sr130pc20_regs.h" +#endif /* CONFIG_LOAD_FILE*/ + +#include "sr130pc20_regs.h" + +#endif /* __SR130PC20_H__ */ diff --git a/drivers/media/video/sr130pc20_regs.h b/drivers/media/video/sr130pc20_regs.h new file mode 100644 index 0000000..ebc578b --- /dev/null +++ b/drivers/media/video/sr130pc20_regs.h @@ -0,0 +1,4229 @@ +/* sr130pc20_regs.h + * + * Driver for s5k5ccgx (5MP Camera) from siliconfile + * + * Copyright (C) 2010, SAMSUNG ELECTRONICS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Change Date: 2012.06.28 + */ + +#ifndef __SR130PC20_REGS_H__ +#define __SR130PC20_REGS_H__ + +/* PV 1st */ + +static const sr130pc20_regset_t SR130PC20_Init_Reg[] = { + +/*0 Page*/ +0x0300, +0x0101, /*sleep*/ +0x0103, /*s/w reset*/ +0x0101, /*sleep*/ + +0x0800,/*Don't touch*/ +0x0937,/*Don't touch*/ +0x0a33,/*Don't touch*/ + +/*PLL Setting*/ +0xd005, +0xd130, +0xd201, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x1011, +0x1190, /*xy flip*/ +0x1200, +0x1488, + +0x0300, +0x2000, +0x2104, +0x2200, +0x2304, +0x2403, +0x25C0, +0x2605, +0x2700, + +0x4001, /*Hblank_280*/ +0x4118, +0x4200, /*Vblank 100*/ +0x4364, + +/*--------------- BLC*/ +0x8008, /*Don't touch */ +0x8197, /*Don't touch */ +0x8290, /*Don't touch */ +0x8330, /*Don't touch */ +0x84cc, /*Don't touch*/ +0x8500, /*Don't touch*/ +0x86d4, /*Don' t touch*/ +0x870f, /*Don't touch*/ +0x8834, /*Don't touch*/ + +0x900c, /*BLC_TIME_TH_ON*/ +0x910c, /*BLC_TIME_TH_OFF */ +0x92f0, /*BLC_AG_TH_ON*/ +0x93e8, /*BLC_AG_TH_OFF*/ + +0x9495, /*091202*/ +0x9590, /*091202 */ +0x9838, /*Don't touch*/ + +/*Dark BLC*/ +0xa001, /* 20100309*/ +0xa201, /* 20100309*/ +0xa401, /* 20100309*/ +0xa601, /* 20100309*/ + +/*Normal BLC*/ +0xa800, +0xaa00, +0xac00, +0xae00, + +/*Out BLC*/ +0x9900, +0x9a00, +0x9b00, +0x9c00, + +/*2 Page*/ +0x0302, +0x1200, /*Don't touch*/ +0x1400, /*Don't touch*/ +0x1500, /*Don't touch*/ +0x184C, /*Don't touch*/ +0x1900, /*Don't touch*/ +0x1A39, /*Don't touch*/ +0x1B00,/*Don't touch*/ +0x1C1a, /*Don't touch*/ +0x1D14, /*Don't touch*/ +0x1E30,/*Don't touch*/ +0x1F10,/*Don't touch*/ + +0x2077, +0x21de, +0x22a7, +0x2330, +0x2477, +0x2510, +0x2610, +0x273c, +0x2b80, +0x2c02, +0x2da0, +0x2e00, +0x2fa7, + +0x3000, +0x3199, +0x3200, +0x3300, +0x3422, +0x3601, +0x3701, +0x3888, +0x3988, +0x3d03, +0x3e0d, +0x3f02, + +0x49d1, +0x4a14, + +0x5021, +0x5201, +0x5381, +0x5410, +0x551c, +0x5611, +0x5818, +0x5916, +0x5da2, +0x5e5a, + +0x6093, /* 20120517 modify*/ +0x61a4, /* 20120517 modify*/ +0x6294, /* 20120517 modify*/ +0x63a3, /* 20120517 modify*/ +0x6494, /* 20120517 modify*/ +0x65a3, /* 20120517 modify*/ +0x670c, +0x680c, +0x690c, +0x6ab4, +0x6bc4, +0x6cb5, +0x6dc2, +0x6eb5, +0x6fc0, + +0x70b6, +0x71b8, +0x7295, /* 20120517 modify*/ +0x73a2, /* 20120517 modify*/ +0x7495, /* 20120517 modify*/ +0x75a2, /* 20120517 modify*/ +0x7695, /* 20120517 modify*/ +0x77a2, /* 20120517 modify*/ +0x7C92, /* 20120517 modify*/ +0x7Dff, /* 20120517 modify*/ + +0x8001, /* 20120517 modify*/ +0x818a, /* 20120517 modify*/ +0x821e, /* 20120517 modify*/ +0x8336, /* 20120517 modify*/ +0x8489, /* 20120517 modify*/ +0x858b, /* 20120517 modify*/ +0x8689, /* 20120517 modify*/ +0x878b, /* 20120517 modify*/ +0x88ab, +0x89bc, +0x8aac, +0x8bba, +0x8cad, +0x8db8, +0x8eae, +0x8fb2, + +0x90b3, +0x91b7, +0x9252, /* 20120517 modify*/ +0x936a, /* 20120517 modify*/ +0x9489, /* 20120517 modify*/ +0x958b, /* 20120517 modify*/ +0x9689, /* 20120517 modify*/ +0x978b, /* 20120517 modify*/ + +0xA002, +0xA186, /* 20120517 modify*/ +0xA202, +0xA386, /* 20120517 modify*/ +0xA486, /* 20120517 modify*/ +0xA502, +0xA686, /* 20120517 modify*/ +0xA702, +0xA892, /* 20120517 modify*/ +0xA994, /* 20120517 modify*/ +0xAA92, /* 20120517 modify*/ +0xAB94, /* 20120517 modify*/ +0xAC1c, +0xAD22, +0xAE1c, +0xAF22, + +0xB0a4, /* 20120517 modify*/ +0xB1ae, /* 20120517 modify*/ +0xB2a4, /* 20120517 modify*/ +0xB3ae, /* 20120517 modify*/ +0xB4a6, /* 20120517 modify*/ +0xB5ac, /* 20120517 modify*/ +0xB6a6, /* 20120517 modify*/ +0xB7ac, /* 20120517 modify*/ +0xB8a6, /* 20120517 modify*/ +0xB9ab, /* 20120517 modify*/ +0xBAa6, /* 20120517 modify*/ +0xBBab, /* 20120517 modify*/ +0xBCa6, /* 20120517 modify*/ +0xBDab, /* 20120517 modify*/ +0xBEa6, /* 20120517 modify*/ +0xBFab, /* 20120517 modify*/ + +0xc437, +0xc552, +0xc66b, +0xc786, +0xc838, /* 20120517 modify*/ +0xc950, /* 20120517 modify*/ +0xca38, /* 20120517 modify*/ +0xcb50, /* 20120517 modify*/ +0xcc6c, /* 20120517 modify*/ +0xcd84, /* 20120517 modify*/ +0xce6c, /* 20120517 modify*/ +0xcf84, /* 20120517 modify*/ + +/*0xd4a6,*/ +/*0xd5ac,*/ +/*0xd6a6,*/ +/*0xd7ac,*/ +/*add 20120517*/ +0xdc00, /* Added*/ +0xddaf, /* Added*/ +0xde00, /* Added*/ +0xdf90, /* Added*/ + +0xd010, +0xd114, +0xd220, +0xd300, +/*DCDC */ +0xd40c, /*DCDC_TIME_TH_ON*/ +0xd50c, /*DCDC_TIME_TH_OFF */ +0xd6f0, /*DCDC_AG_TH_ON*/ +0xd7e8, /*DCDC_AG_TH_OFF*/ + +0xea8a, + +0xF001, /* clock inversion*/ +0xF101, +0xF201, +0xF301, +0xF401, +0xF500, + +/*----------------------------------------------*/ +0x0310, /*page 10*/ +0x1001, /*Ycbcr422_bit Order: YUYV*/ +0x1103, +0x1230, /*y offset[4], dif_offset[5]*/ +0x1302, /*contrast effet enable : 0x02*/ +0x3400, /*hidden 10->00 100209*/ +0x3701, /*yc2d power save */ +0x3f04, /*100825*/ +0x4080, /*Y offset */ +0x4880, +0x5300, /*dif_offset option */ +0x5530, /*dif_offset option diff_offset max */ + +0x604f, /*out color sat en[7] | auto color decrement en[1] / + | manual color sat en[0]*/ + +0x6183, /*blue saturation_C0*/ +0x6280, /*red saturation_B0*/ + +0x63ff, /*auto decresment on AG th*/ +0x64c0, /*auto decresment on DG th*/ +0x66e4, /*Outdoor saturation step 137fps apply out th */ +0x6703, /*Outdoor saturation B/R*/ +0x7601, /* ADD 20121031 */ +0x7904, /* ADD 20121031 */ + +/* Hi 163 */ +/* PAGE 10 START*/ +0x0310, +0x8000, /* dsshin --> color enhance*/ +0xf500, /* dsshin --> h blank option*/ + +0x0311, /*page 11 D_LPF */ +0x103f, /*B[6]:Blue En Dlpf on[4:0] Sky over off : 0x7f->3f*/ +0x1120, /* Uniform Full GbGr/OV-Nr*/ + +0x1280, /*Blue MaxOpt blue sky max filter optoin rate : 0 0xc0->80*/ +0x13b8, /*dark2[7] | ratio[6:4] | dark3[3] | dark3 maxfilter ratio[2:0] */ + +0x30ba, /*Outdoor2 H th*/ +0x3110, /*Outdoor2 L th*/ +0x3250, /*Outdoor2 gain ratio*/ +0x331d, /*Outdoor2 H lum*/ +0x3420, /*Outdoor2 M lum*/ +0x351f, /*Outdoor2 L lum*/ + +0x36b0, /*Outdoor1 H th*/ +0x3718, /*Outdoor1 L th*/ +0x3850, /*Outdoor1 gain ratio 0x80->40*/ +0x391d, /*Outdoor1 H lum 0x28->1e*/ +0x3a20, /*Outdoor1 M lum 0x10->15*/ +0x3b1f, /*Outdoor1 L lum 0x08->20*/ + +0x3c3f, /*indoor H th*/ +0x3d16, /*indoor L th*/ +0x3e30, /*indoor gain ratio 0x44 6a */ +0x3f1a, /*indoor H lum 0x12 18 */ +0x4060, /*indoor M lum 0x18 1c*/ +0x411a, /*indoor L lum 0x18 3e*/ + +0x4298, /*dark1 H th*/ +0x4328, /*dark1 L th*/ +0x4465, /*dark1 gain ratio*/ +0x4516, /*dark1 H lum 0x38->0x28 */ +0x4630, /*dark1 M lum 0x27->0x17*/ +0x4734, /*dark1 L lum 0x20->0x1a */ + +0x4890, /*dark2 H th*/ +0x492a, /*dark2 L th*/ +0x4a65, /*dark2 gain ratio*/ +0x4b18, /*dark2 H lum */ +0x4c31, /*dark2 M lum*/ +0x4d36, /*dark2 L lum */ + +0x4e80, /*dark3 H th*/ +0x4f30, /*dark3 L th*/ +0x5065, /*dark3 gain ratio*/ +0x5119, /*dark3 H lum */ +0x5231, /*dark3 M lum */ +0x5336, /*dark3 L lum */ + +0x5a3f, /*blue sky mode out1/2 enable 0x27->3f */ +0x5b00, /*Impulse pixel enable dark123,in,out123 :: must be 0x07*/ +0x5c9f, /*Indoor maxfilter rate[7:5] | Uncertain onoff[4:0] 0x1f ->0x9f*/ + +0x603f, /*GbGr all enable*/ +0x620f, /*GbGr offset*/ + +0x650c, /*Outdoor GbGr rate H 100% M 25% L 100%*/ +0x660c, /*Indoor GbGr rate H 100% M 25% L 100%*/ +0x6700, /*dark GbGr rate H/M/L 100%*/ + +0x700c, /* Abberation On/Off B[1]: Outdoor B[0]: Indoor 07>>c*/ +0x75a0, /* Outdoor2 Abberation Luminance lvl */ +0x7db4, /* Indoor Abberation Luminance lvl*/ + +0x9608, /*indoor/Dark1 edgeoffset1*/ +0x9714, /*indoor/Dark1 center G value*/ +0x98f5, /*slope indoor :: left/right graph polarity, slope*/ +0x992a, /*indoor uncertain ratio control*/ +0x9a20, /*Edgeoffset_dark*/ + +/*DPC_CTRL*/ +0x0312, /*Preview DPC off[0x5c] on[0x5d]*/ +0x200f, +0x210f, + +0x2500, /* 0x30*/ + +0x2a01, +0x2e00, /*2010.8.25*/ + +0x3035, /*Texture region(most detail)*/ +0x31a0, /*STD uniform1 most blur region*/ +0x32b0, /*STD uniform2 2nd blur*/ +0x33c0, /*STD uniform3 3rd blur*/ +0x34d0, /*STD normal noise1 4th blur */ +0x35e0, /*STD normal noise2 5th blur*/ +0x36ff, /*STD normal noise3 6th blur*/ + +0x4083, /*Outdoor2 H th*/ +0x4120, /*Outdoor2 L th */ +0x4208, /*Outdoor2 H luminance */ +0x4310, /*Outdoor2 M luminance */ +0x4410, /*Outdoor2 l luminance */ +0x4550, /*Outdoor2 ratio*/ + +0x4683, /*Outdoor1 H th*/ +0x4720, /*Outdoor1 L th */ +0x4808, /*Outdoor1 H luminance*/ +0x4910, /*Outdoor1 M luminance*/ +0x4a10, /*Outdoor1 L luminance*/ +0x4b50, /*Outdoor1 ratio*/ + +0x4c80, /*Indoor H th*/ +0x4d48, /*Indoor L th*/ +0x4e30, /*indoor H lum*/ +0x4f30, /*indoor M lum*/ +0x5012, /*indoor L lum */ +0x5170, /*indoor ratio 0x10 -> 0x45*/ + +0x52a8, /*dark1 H th*/ +0x5330, /*dark1 L th */ +0x5428, /*dark1 H lum */ +0x553e, /*dark1 M lum*/ +0x5667, /*dark1 L lum*/ +0x576a, /*dark1 ratio*/ + +0x58a0, /*dark2 H th*/ +0x5940, /*dark2 L th*/ +0x5a28, /*dark2 H lum*/ +0x5b3f, /*dark2 M lum*/ +0x5c68, /*dark2 L lum*/ +0x5d70, /*dark2 ratio*/ + +0x5ea0, /*dark3 H th*/ +0x5f40, /*dark3 L th*/ +0x6029, /*dark3 H lum*/ +0x613f, /*dark3 M lum*/ +0x6269, /*dark3 L lum*/ +0x636a, /*dark3 ratio*/ + +/*C-filter(Out2&Out1)*/ +0x7010, +0x710a, + +/*C-filter(Indoor&Dark3)*/ +0x7210, +0x730a, + +/*C-filter(Dark2&Dark1)*/ +0x7418, +0x7512, + +0x8020, +0x8140, +0x8265, +0x851a, +0x8800, +0x8900, +0x905d, /*Preview DPC off[0x5c] on[0x5d]*/ + +/*DPC-Dark1,2,3*/ +0xad07, /*10825*/ +0xae07, /*10825*/ +0xaf07, /*10825*/ + +/*Blue Det..*/ +0xc558, /*BlueRange 2010.8.25 0x40->23 */ +0xc620, /*GreenRange 2010.8.25 0x3b->20 */ + +0xd088, /*2010.8.25*/ +0xd180, +0xd217,/*preview 17, full 67*/ +0xd300, +0xd400, +0xd50f,/*preview 0f, full 02*/ +0xd6ff, +0xd7ff,/*preview ff, full 18*/ +0xd800, +0xd904, + +/*interpolated with average*/ +0xdb38, /*resolution issue 0x00->0x18->0x38 */ +0xd904, /*strong_edge detect ratio*/ +0xe001, /*strong_edge detect ratio*/ + +0x0313, /*page 13 sharpness 1D*/ +0x10c5, +0x117b, +0x120e, +0x1400, + +0x1511, /*added option 1.3M*/ +0x1830, /*added option 1.3M*/ + +0x2015, +0x2113, +0x2233, +0x2308, /*hi_clip th1*/ +0x241a, /*hi_clip th2*/ +0x2506, /*low clip th*/ + +0x2618, +0x2730, +0x2910, /*time th*/ +0x2a30, /*pga th*/ + +0x2b03, /*lpf out2*/ +0x2c03, /*lpf out1*/ +0x2d0c, +0x2e12, +0x2f12, + +/*1D Edge*/ +0x500a, /*out2 hi nega*/ +0x5307, /* hi pos*/ +0x510c, /* mi nega*/ +0x5407, /* mi pos*/ +0x520b, /* lo nega*/ +0x5508, /* lo pos*/ + +0x560a, /*out1 hi nega*/ +0x5907, /* hi pos */ +0x570c, /* mi nega*/ +0x5a07, /* mi pos */ +0x580b, /* lo nega*/ +0x5b08, /* lo pos */ + +/*Indoor Edge*/ +0x5c08, /*indoor hi nega*/ +0x5f07, /* hi pos*/ +0x5d14, +0x6012, +0x5e0a, +0x6108, /* low pos*/ + +0x6208, /*dark1 hi nega*/ +0x6506, /* hi pos */ +0x6308, /* mid nega */ +0x6606, /* mid pos */ +0x6408, /* low nega */ +0x6706, /* low pos */ + +0x6807, /*dark2 hi nega*/ +0x6b05, /* hi pos */ +0x6907, /* mid nega */ +0x6c05, /* mid pos */ +0x6a07, /* low nega */ +0x6d05, /* low pos */ + +0x6e0a, /*dark3 hi nega*/ +0x7109, /* hi pos */ +0x6f0a, /* mid nega */ +0x7209, /* mid pos */ +0x700a, /* low nega */ +0x7309, /* low pos */ + + /* 2DY*/ +0x80c1, +0x811f, +0x82e1, +0x8333, + +0x9005, +0x9105, +0x9233, +0x9330, +0x9403, +0x9514, +0x9730, +0x9930, + +0xa002, /*2d lclp out2 nega*/ +0xa103, /*2d lclp out2 pos*/ +0xa202, /*2d lclp out1 nega*/ +0xa303, /*2d lclp out1 pos*/ +0xa403, /*2d lclp in nega*/ +0xa504, /*2d lclp in pos*/ +0xa607, /*2d lclp dark1 nega*/ +0xa708, /*2d lclp dark1 pos*/ +0xa807, /*2d lclp dark2 nega*/ +0xa908, /*2d lclp dark2 pos*/ +0xaa07, /*2d lclp dark3 nega*/ +0xab08, /*2d lclp dark3 pos*/ + +0xb010, /*out2 H Ne*/ +0xb310, /* H Po*/ +0xb11e, /* M Ne*/ +0xb41e, /* M Po*/ +0xb21f, /* L Ne*/ +0xb51e, /* L Po*/ + +0xb610, /*out1 H Ne */ +0xb910, /* H Po */ +0xb71e, /* M Ne */ +0xba1e, /* M Po */ +0xb81f, /* L Ne */ +0xbb1e, /* L Po */ + +0xbc20, /*indoor H Ne*/ +0xbf1e, /* H Po*/ +0xbd25, /* M Ne*/ +0xc023, /* M Po*/ +0xbe24, /* L Ne*/ +0xc122, /* L Po*/ + +0xc223, /*dark1 H Ne*/ +0xc523, /* H Po*/ +0xc329, /* M Ne*/ +0xc629, /* M Po*/ +0xc425, /* L Ne*/ +0xc725, /* L Po*/ + +0xc81c, /*dark2 H Ne*/ +0xcb1c, /* H Po*/ +0xc925, /* M Ne*/ +0xcc25, /* M Po*/ +0xca23, /* L Ne*/ +0xcd23, /* L Po*/ + +0xce1c, /*dark3 H Ne*/ +0xd11c, /* H Po*/ +0xcf25, /* M Ne*/ +0xd225, /* M Po*/ +0xd023, /* L Ne*/ +0xd323, /* L Po*/ + +/* PAGE 14 START*/ +0x0314, +0x1031, + +0x1480, /* GX*/ +0x1580, /* GY*/ +0x1680, /* RX*/ +0x1780, /* RY*/ +0x1880, /* BX*/ +0x1980, /* BY*/ + +0x2060, /* X Center*/ +0x2180, /* Y Center*/ + +0x2280, +0x2380, +0x2480, + +0x30c8, +0x312b, +0x3200, +0x3300, +0x3490, + +0x4056, /*R min's set 4e*/ +0x413a, /*Gr*/ +0x4237, /*B*/ +0x433a, /*Gb*/ + +0x0315, +0x1021, +0x1444, /*49*/ +0x1534, /*38*/ +0x1626, /*2b*/ +0x172f, + +0x30dd, +0x3162, +0x3205, +0x3326, +0x34bd, +0x3517, +0x3618, +0x3738, +0x38d0, + +0x40b0, +0x4130, +0x4200, +0x4300, +0x4400, +0x4500, +0x4699, +0x4719, +0x4800, + +0x5016, +0x51b2, +0x521c, +0x5306, +0x5420, +0x55a6, +0x560e, +0x57b2, +0x5824, + +0x0316, +0x1031, /*GMA_CTL*/ +0x187e, /*AG_ON*/ +0x197d, /*AG_OFF*/ +0x1a0e, /*TIME_ON*/ +0x1b01, /*TIME_OFF*/ +0x1Cdc, /*OUT_ON*/ +0x1Dfe, /*OUT_OFF*/ + +/*GMA Indoor*/ +0x3000, +0x3107, +0x321a, +0x3335, +0x345a, +0x357c, +0x3696, +0x37a9, +0x38b7, +0x39c6, +0x3ad2, +0x3bdc, +0x3ce4, +0x3deb, +0x3ef1, +0x3ff5, +0x40f9, +0x41fd, +0x42ff, + +/*RGMA Outdoor*/ +0x5000, +0x5103, +0x5213, +0x532e, +0x5459, +0x5579, +0x5690, +0x57a3, +0x58b4, +0x59c2, +0x5acd, +0x5bd7, +0x5ce0, +0x5de5, +0x5ee9, +0x5fee, +0x60f1, +0x61f3, +0x62f6, + +/*BGMA Dark*/ +0x7003, +0x7111, +0x721f, +0x7337, +0x7452, +0x756c, +0x7685, +0x779a, +0x78ad, +0x79bd, +0x7acb, +0x7bd6, +0x7ce0, +0x7de8, +0x7eef, +0x7ff4, +0x80f8, +0x81fb, +0x82fe, + +0x0324, /*Resol control */ +0x60c5, /*edge even frame | 16bit resol | white edge cnt | scene resol enable*/ +0x6104, /*even frame update */ +0x6408, +0x6500, +0x6626, /*edge th2 H */ +0x6700, /*edge th2 L */ + +0x0313, +0x1831, /*flat center Gb/Gr*/ +0x7402, /*det slope en | gausian filter*/ +0x750d, /*1D negative gain det 09 */ +0x760d, /*1D postive gain det 08*/ +0x7710, /*1D hclp2 det*/ +0x7808, /*outdoor flat threshold*/ +0x7910, /*indoor flat threshold*/ + +0x81df, /*det gain controler*/ +0x8690, /*2D negative gain det */ +0x8790, /*2D postive gain det */ +0x962a, /*2D hclp2 det*/ + +0x0312, /*0x12 page*/ +0xd088, +0xd9e4, + +/* PAGE 18 START*/ +0x0318, +0x1400, + +/* PAGE 20 START*/ +0x0320, +0x111c, +0x1830, +0x1a08, +0x2045,/*weight*/ +0x2130, +0x2210, +0x2300, +0x2400, + +0x28e7, /* add 20120223*/ +0x290d, /* 20100305 ad -> 0d*/ +0x2afd, +0x2bf8, + +0x2cc3, +0x2d5f, /* add 20120223*/ +0x2e33, +0x30f8, +0x3203, +0x332e, +0x3430, +0x35d4, +0x36ff, /*fe*/ +0x3732, +0x3804, +0x3922, +0x3ade, +0x3b22, +0x3cde, +0x3de1, + +0x5045, +0x5188, + +0x561a, +0x5780, +0x580e, +0x596a, +0x5a04, + +0x5e9d, /*AE_AWB_start*/ +0x5f76, /*AE_AWB_start*/ + +0x7033, /* 6c*/ +0x7182, /* 82(+8)*/ + +0x7621, +0x7771, +0x7822, /* 24*/ +0x7923, /* Y Target 70 => 25, 72 => 26*/ +0x7a23, /* 23*/ +0x7b22, /* 22*/ +0x7d23, + +0x8301, /*EXP Normal 33.33 fps */ +0x845f, +0x8590, +0x8601, /*EXPMin 7500.00 fps*/ +0x8790, +0x8805, /*EXP Max(120Hz) 8.00 fps */ +0x89b8, +0x8ad8, +0xa505, /*EXP Max(100Hz) 8.33 fps */ +0xa67e, +0xa740, +0x8B75, /*EXP100 */ +0x8C30, +0x8D61, /*EXP120 */ +0x8Ea8, +0x9c09, /*EXP Limit 1250.00 fps */ +0x9d60, +0x9e01, /*EXP Unit */ +0x9f90, +0x989d, + +0xb016, +0xb114, +0xb2f8, +0xb314, +0xb41b, +0xb546, +0xb631, +0xb729, +0xb826, +0xb924, +0xba22, +0xbb42, +0xbc41, +0xbd40, + +0xc010, +0xc138, +0xc238, +0xc338, +0xc407, + +0xc880, +0xc980, +0x109c, /* ae enable*/ +/* PAGE 20 END*/ + +/*AE_Weight*/ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2412, +0x2522, +0x2622, +0x2721, +0x2812, +0x2922, +0x2a22, +0x2b21, +0x2c12, +0x2d23, +0x2e32, +0x2f21, +0x3012, +0x3123, +0x3232, +0x3321, +0x3412, +0x3522, +0x3622, +0x3721, +0x3812, +0x3922, +0x3a22, +0x3b21, +0x3c11, +0x3d11, +0x3e11, +0x3f11, + +/* PAGE 22 START*/ +0x0322, +0x10fd, +0x112e, +0x1901, /* Low On*/ +0x2030, /* for wb speed*/ +0x2140, +0x2401, +0x257e, /* for tracking 20120314 */ + +0x3080, /* 20120224 test*/ +0x3180, +0x3811, +0x3934, + +0x40e8, +0x4143, /* 33*/ +0x4222, /* 22*/ + +0x43f3, /* f6*/ +0x4454, /* 44*/ +0x4522, /* 33*/ + +0x4600, +0x480a, +0x50b2, +0x5181, +0x5298, + +0x8038, +0x8120, +0x8238, /* 3a*/ + +0x8356, /* R Max*/ +0x8420, /* R Min*/ +0x8552, /* B Max*/ +0x8620, /* B Min*/ + +0x8745, +0x883a, +0x8933, +0x8a2c, + +0x8b42, +0x8c3d, +0x8d30, +0x8e2c, + +0x8f5a, +0x9059, +0x9155, +0x924e, +0x9344, +0x943a, +0x9534, +0x962c, +0x9723, +0x9820, +0x991f, +0x9a1f, + +0x9b77, +0x9c77, +0x9d48, +0x9e38, +0x9f30, + +0xa040, +0xa121, +0xa26f, +0xa3ff, + +0xa414, /* 1500fps*/ +0xa544, /* 700fps*/ +0xa6cf, + +0xad40, +0xae4a, + +0xaf2a, /* low temp Rgain*/ +0xb028, /* low temp Rgain*/ + +0xb100, /* 0x20 -> 0x00 0405 modify*/ +0xb4bf, /* for tracking 20120314*/ +0xb8a1, /* a2: b-2, R+2 b4 B-3, R+4 lowtemp b0 a1 Spec AWB A modify*/ +0xb900, +/* PAGE 22 END*/ + +/* PAGE 48 (MiPi 1600x1200)*/ +0x0300, + +/* PLL Setting */ +0xd005, +0xd130, +0xd205, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x0348, +/* MIPI TX Setting */ +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +0x1d0e, +0x1e07, +0x1f08, + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2b40,*/ + +0x3005, +0x3100, + +0x3207, +0x3309, +0x3401, +0x3501, + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_VT_Init_Reg[] = { +/*0 Page*/ +0x0300, +0x0101, /*sleep*/ +0x0103, /*s/w reset*/ +0x0101, /*sleep*/ + +0x0800,/*Don't touch*/ +0x0937,/*Don't touch*/ +0x0a33,/*Don't touch*/ + +/*PLL Setting*/ +0xd005, +0xd130, +0xd201, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x1011, +0x1194, /*xy flip*/ +0x1200, /*Sync type default:0x00 PCLK[2] 0 falling, 1 rising*/ +0x1488, + +/*--------------- windowing */ +0x0300, +0x2000, +0x2104, +0x2200, +0x2304, +0x2403, +0x25C0, +0x2605, +0x2700, + +0x4001, /*Hblank 280*/ +0x4118, +0x4200, /*Vblank 20*/ +0x4314, + +/*--------------- BLC*/ +0x8008, /*Don't touch */ +0x8197, /*Don't touch */ +0x8290, /*Don't touch */ +0x8330, /*Don't touch */ +0x84cc, /*Don't touch*/ +0x8500, /*Don't touch*/ +0x86d4, /*Don' t touch*/ +0x870f, /*Don't touch*/ +0x8834, /*Don't touch*/ + +0x9009, /*BLC_TIME_TH_ON*/ +0x9109, /*BLC_TIME_TH_OFF */ +0x92f0, /*BLC_AG_TH_ON*/ +0x93e8, /*BLC_AG_TH_OFF*/ + +0x9495, /*091202*/ +0x9590, /*091202 */ +0x9838, /*Don't touch*/ + +/*Dark BLC*/ +0xa001, /* 20100309*/ +0xa201, /* 20100309*/ +0xa401, /* 20100309*/ +0xa601, /* 20100309*/ + +/*Normal BLC*/ +0xa800, +0xaa00, +0xac00, +0xae00, + +/*Out BLC*/ +0x9900, +0x9a00, +0x9b00, +0x9c00, + +/*2 Page*/ +0x0302, +0x1200, /*Don't touch*/ +0x1400, /*Don't touch*/ +0x1500, /*Don't touch*/ +0x184C, /*Don't touch*/ +0x1900, /*Don't touch*/ +0x1A39, /*Don't touch*/ +0x1B00,/*Don't touch*/ +0x1C1a, /*Don't touch*/ +0x1D14, /*Don't touch*/ +0x1E30,/*Don't touch*/ +0x1F10,/*Don't touch*/ + +0x2077, +0x21de, +0x22a7, +0x2330, +0x2477, +0x2510, +0x2610, +0x273c, +0x2b80, +0x2c02, +0x2da0, +0x2e00, +0x2fa7, + +0x3000, +0x3199, +0x3200, +0x3300, +0x3422, +0x3601, +0x3701, +0x3888, +0x3988, +0x3d03, +0x3e0d, +0x3f02, + +0x49d1, +0x4a14, + +0x5021, +0x5201, +0x5381, +0x5410, +0x551c, +0x5611, +0x5818, +0x5916, +0x5da2, +0x5e5a, + +0x6093, /* 20120517 modify*/ +0x61a4, /* 20120517 modify*/ +0x6294, /* 20120517 modify*/ +0x63a3, /* 20120517 modify*/ +0x6494, /* 20120517 modify*/ +0x65a3, /* 20120517 modify*/ +0x670c, +0x680c, +0x690c, +0x6ab4, +0x6bc4, +0x6cb5, +0x6dc2, +0x6eb5, +0x6fc0, + +0x70b6, +0x71b8, +0x7295, /* 20120517 modify*/ +0x73a2, /* 20120517 modify*/ +0x7495, /* 20120517 modify*/ +0x75a2, /* 20120517 modify*/ +0x7695, /* 20120517 modify*/ +0x77a2, /* 20120517 modify*/ +0x7C92, /* 20120517 modify*/ +0x7Dff, /* 20120517 modify*/ + +0x8001, /* 20120517 modify*/ +0x818a, /* 20120517 modify*/ +0x821e, /* 20120517 modify*/ +0x8336, /* 20120517 modify*/ +0x8489, /* 20120517 modify*/ +0x858b, /* 20120517 modify*/ +0x8689, /* 20120517 modify*/ +0x878b, /* 20120517 modify*/ +0x88ab, +0x89bc, +0x8aac, +0x8bba, +0x8cad, +0x8db8, +0x8eae, +0x8fb2, + +0x90b3, +0x91b7, +0x9252, /* 20120517 modify*/ +0x936a, /* 20120517 modify*/ +0x9489, /* 20120517 modify*/ +0x958b, /* 20120517 modify*/ +0x9689, /* 20120517 modify*/ +0x978b, /* 20120517 modify*/ + +0xA002, +0xA186, /* 20120517 modify*/ +0xA202, +0xA386, /* 20120517 modify*/ +0xA486, /* 20120517 modify*/ +0xA502, +0xA686, /* 20120517 modify*/ +0xA702, +0xA892, /* 20120517 modify*/ +0xA994, /* 20120517 modify*/ +0xAA92, /* 20120517 modify*/ +0xAB94, /* 20120517 modify*/ +0xAC1c, +0xAD22, +0xAE1c, +0xAF22, + +0xB0a4, /* 20120517 modify*/ +0xB1ae, /* 20120517 modify*/ +0xB2a4, /* 20120517 modify*/ +0xB3ae, /* 20120517 modify*/ +0xB4a6, /* 20120517 modify*/ +0xB5ac, /* 20120517 modify*/ +0xB6a6, /* 20120517 modify*/ +0xB7ac, /* 20120517 modify*/ +0xB8a6, /* 20120517 modify*/ +0xB9ab, /* 20120517 modify*/ +0xBAa6, /* 20120517 modify*/ +0xBBab, /* 20120517 modify*/ +0xBCa6, /* 20120517 modify*/ +0xBDab, /* 20120517 modify*/ +0xBEa6, /* 20120517 modify*/ +0xBFab, /* 20120517 modify*/ + +0xc437, +0xc552, +0xc66b, +0xc786, +0xc838, /* 20120517 modify*/ +0xc950, /* 20120517 modify*/ +0xca38, /* 20120517 modify*/ +0xcb50, /* 20120517 modify*/ +0xcc6c, /* 20120517 modify*/ +0xcd84, /* 20120517 modify*/ +0xce6c, /* 20120517 modify*/ +0xcf84, /* 20120517 modify*/ + +/*0xd4a6,*/ +/*0xd5ac,*/ +/*0xd6a6,*/ +/*0xd7ac,*/ +/*add 20120517*/ +0xdc00, /* Added*/ +0xddaf, /* Added*/ +0xde00, /* Added*/ +0xdf90, /* Added*/ + +0xd010, +0xd114, +0xd220, +0xd300, +/*DCDC */ +0xd409, /*DCDC_TIME_TH_ON*/ +0xd509, /*DCDC_TIME_TH_OFF */ +0xd6f0, /*DCDC_AG_TH_ON*/ +0xd7e8, /*DCDC_AG_TH_OFF*/ + +0xea8a, + +0xF001, /* clock inversion*/ +0xF101, +0xF201, +0xF301, +0xF401, +0xF500, + +/*----------------------------------------------*/ +0x0310, /*page 10*/ +0x1001, /*Ycbcr422_bit Order: YUYV*/ +0x1230, /*y offset[4], dif_offset[5]*/ +0x1302, /*contrast effet enable : 0x02*/ +0x3400, /*hidden 10->00 100209*/ +0x3701, /*yc2d power save */ +0x3f04, /*100825*/ +0x4080, /*Y offset */ +0x4138, +0x4880, /*Contrast (Y = constrast * (Y - 128) + 128)*//*86 */ +0x50f0, +0x5300, /*dif_offset option */ +0x5530, /*dif_offset option diff_offset max */ + +0x6003, /*out color sat en[7] | auto color decrement en[1] / + | manual color sat en[0]*/ + + +0x6183, /*blue saturation_C0*/ +0x6280, /*red saturation_B0*/ + +0x63ff, /*auto decresment on AG th*/ +0x64ff, /*auto decresment on DG th*/ +0x66e4, /*Outdoor saturation step 137fps apply out th */ +0x6700, /*Outdoor saturation B/R*/ +0x7601, /* ADD 20121031 */ +0x7904, /* ADD 20121031 */ + +/* Hi 163 */ +/* PAGE 10 START*/ +0x0310, +0x8000, /* dsshin --> color enhance*/ +0xf500, /* dsshin --> h blank option*/ + +0x0311, /*page 11 D_LPF */ +0x103f, /*B[6]:Blue En Dlpf on[4:0] Sky over off : 0x7f->3f*/ +0x1120, /* Uniform Full GbGr/OV-Nr*/ + +0x1280, /*Blue MaxOpt blue sky max filter optoin rate : 0 0xc0->80*/ +0x13b8, /*dark2[7] | dark2 maxfilter ratio[6:4] + | dark3[3] | dark3 maxfilter ratio[2:0] */ + +0x30ba, /*Outdoor2 H th*/ +0x3110, /*Outdoor2 L th*/ +0x3250, /*Outdoor2 gain ratio*/ +0x331d, /*Outdoor2 H lum*/ +0x3420, /*Outdoor2 M lum*/ +0x351f, /*Outdoor2 L lum*/ + +0x36b0, /*Outdoor1 H th*/ +0x3718, /*Outdoor1 L th*/ +0x3850, /*Outdoor1 gain ratio 0x80->40*/ +0x391d, /*Outdoor1 H lum 0x28->1e*/ +0x3a20, /*Outdoor1 M lum 0x10->15*/ +0x3b1f, /*Outdoor1 L lum 0x08->20*/ + +0x3c3f, /*indoor H th*/ +0x3d16, /*indoor L th*/ +0x3e30, /*indoor gain ratio 0x44 6a */ +0x3f1a, /*indoor H lum 0x12 18 */ +0x4060, /*indoor M lum 0x18 1c*/ +0x411a, /*indoor L lum 0x18 3e*/ + +0x4298, /*dark1 H th*/ +0x4328, /*dark1 L th*/ +0x4465, /*dark1 gain ratio*/ +0x4516, /*dark1 H lum 0x38->0x28 */ +0x4630, /*dark1 M lum 0x27->0x17*/ +0x4734, /*dark1 L lum 0x20->0x1a */ + +0x4890, /*dark2 H th*/ +0x492a, /*dark2 L th*/ +0x4a65, /*dark2 gain ratio*/ +0x4b18, /*dark2 H lum */ +0x4c31, /*dark2 M lum*/ +0x4d36, /*dark2 L lum */ + +0x4e80, /*dark3 H th*/ +0x4f30, /*dark3 L th*/ +0x5065, /*dark3 gain ratio*/ +0x5119, /*dark3 H lum */ +0x5231, /*dark3 M lum */ +0x5336, /*dark3 L lum */ + +0x5a3f, /*blue sky mode out1/2 enable 0x27->3f */ +0x5b00, /*Impulse pixel enable dark123,in,out123 + :: must be 0x07 fix setting use!*/ +0x5c9f, /*Indoor maxfilter rate[7:5] | Uncertain onoff[4:0] 0x1f ->0x9f*/ + +0x603f, /*GbGr all enable*/ +0x620f, /*GbGr offset*/ +/*0x6325,*/ /*GbGr max_20120605_off*/ +/*0x6410,*/ /*GbGr min_20120605_off*/ + +0x650c, /*Outdoor GbGr rate H 100% M 25% L 100%*/ +0x660c, /*Indoor GbGr rate H 100% M 25% L 100%*/ +0x6700, /*dark GbGr rate H/M/L 100%*/ + +0x700c, /* Abberation On/Off B[1]: Outdoor B[0]: Indoor 07>>c*/ +0x75a0, /* Outdoor2 Abberation Luminance lvl */ +0x7db4, /* Indoor Abberation Luminance lvl*/ + +0x9608, /*indoor/Dark1 edgeoffset1*/ +0x9714, /*indoor/Dark1 center G value*/ +0x98f5, /*slope indoor :: left/right graph polarity, slope*/ +0x992a, /*indoor uncertain ratio control*/ +0x9a20, /*Edgeoffset_dark*/ + +/*DPC_CTRL*/ +0x0312, /*Preview DPC off[0x5c] on[0x5d]*/ +0x200e, +0x210e, + +0x2500, /* 0x30*/ + +0x2a01, +0x2e00, /*2010.8.25*/ + +0x3035, /*Texture region(most detail)*/ +0x31a0, /*STD uniform1 most blur region*/ +0x32b0, /*STD uniform2 2nd blur*/ +0x33c0, /*STD uniform3 3rd blur*/ +0x34d0, /*STD normal noise1 4th blur */ +0x35e0, /*STD normal noise2 5th blur*/ +0x36ff, /*STD normal noise3 6th blur*/ + +0x4083, /*Outdoor2 H th*/ +0x4120, /*Outdoor2 L th */ +0x4208, /*Outdoor2 H luminance */ +0x4310, /*Outdoor2 M luminance */ +0x4410, /*Outdoor2 l luminance */ +0x4550, /*Outdoor2 ratio*/ + +0x4683, /*Outdoor1 H th*/ +0x4720, /*Outdoor1 L th */ +0x4808, /*Outdoor1 H luminance*/ +0x4910, /*Outdoor1 M luminance*/ +0x4a10, /*Outdoor1 L luminance*/ +0x4b50, /*Outdoor1 ratio*/ + +0x4c80, /*Indoor H th*/ +0x4d48, /*Indoor L th*/ +0x4e30, /*indoor H lum*/ +0x4f30, /*indoor M lum*/ +0x5012, /*indoor L lum */ +0x5170, /*indoor ratio 0x10 -> 0x45*/ + +0x52a8, /*dark1 H th*/ +0x5330, /*dark1 L th */ +0x5428, /*dark1 H lum */ +0x553e, /*dark1 M lum*/ +0x5667, /*dark1 L lum*/ +0x576a, /*dark1 ratio*/ + +0x58a0, /*dark2 H th*/ +0x5940, /*dark2 L th*/ +0x5a28, /*dark2 H lum*/ +0x5b3f, /*dark2 M lum*/ +0x5c68, /*dark2 L lum*/ +0x5d70, /*dark2 ratio*/ + +0x5ea0, /*dark3 H th*/ +0x5f40, /*dark3 L th*/ +0x6029, /*dark3 H lum*/ +0x613f, /*dark3 M lum*/ +0x6269, /*dark3 L lum*/ +0x636a, /*dark3 ratio*/ + +/*C-filter(Out2&Out1)*/ +0x7010, +0x710a, + +/*C-filter(Indoor&Dark3)*/ +0x7210, +0x730a, + +/*C-filter(Dark2&Dark1)*/ +0x7418, +0x7512, + +0x8020, +0x8140, +0x8265, +0x851a, +0x8800, +0x8900, +0x905d, /*Preview DPC off[0x5c] on[0x5d]*/ + +/*DPC-Dark1,2,3*/ +0xad07, /*10825*/ +0xae07, /*10825*/ +0xaf07, /*10825*/ + +/*Blue Det..*/ +0xc558, /*BlueRange 2010.8.25 0x40->23 */ +0xc620, /*GreenRange 2010.8.25 0x3b->20 */ + +0xd088, /*2010.8.25*/ +0xd180, +0xd217,/*preview 17, full 67*/ +0xd300, +0xd400, +0xd50f,/*preview 0f, full 02*/ +0xd6ff, +0xd7ff,/*preview ff, full 18*/ +0xd800, +0xd904, + +/*interpolated with average*/ +0xdb38, /*resolution issue 0x00->0x18->0x38 */ +0xd904, /*strong_edge detect ratio*/ +0xe001, /*strong_edge detect ratio*/ + +0x0313, /*page 13 sharpness 1D*/ +0x10c5, +0x117b, +0x120e, +0x1400, + +0x1511, /*added option 1.3M*/ +0x1830, /*added option 1.3M*/ + +0x2015, +0x2113, +0x2233, +0x2308, /*hi_clip th1*/ +0x241a, /*hi_clip th2*/ +0x2506, /*low clip th*/ + +0x2618, +0x2730, +0x2910, /*time th*/ +0x2a30, /*pga th*/ + +0x2b03, /*lpf out2*/ +0x2c03, /*lpf out1*/ +0x2d0c, +0x2e12, +0x2f12, + +/*1D Edge*/ +0x500a, /*out2 hi nega*/ +0x5307, /* hi pos*/ +0x510c, /* mi nega*/ +0x5407, /* mi pos*/ +0x520b, /* lo nega*/ +0x5508, /* lo pos*/ + +0x560a, /*out1 hi nega*/ +0x5907, /* hi pos */ +0x570c, /* mi nega*/ +0x5a07, /* mi pos */ +0x580b, /* lo nega*/ +0x5b08, /* lo pos */ + +/*Indoor Edge*/ +0x5c08, /*indoor hi nega*/ +0x5f07, /* hi pos*/ +0x5d14, /* mid nega ,11*/ +0x6012, /* mid pos ,0*/ +0x5e0a, /* low nega */ +0x6108, /* low pos*/ + +0x6208, /*dark1 hi nega*/ +0x6506, /* hi pos */ +0x6308, /* mid nega */ +0x6606, /* mid pos */ +0x6408, /* low nega */ +0x6706, /* low pos */ + +0x6807, /*dark2 hi nega*/ +0x6b05, /* hi pos */ +0x6907, /* mid nega */ +0x6c05, /* mid pos */ +0x6a07, /* low nega */ +0x6d05, /* low pos */ + +0x6e0a, /*dark3 hi nega*/ +0x7109, /* hi pos */ +0x6f0a, /* mid nega */ +0x7209, /* mid pos */ +0x700a, /* low nega */ +0x7309, /* low pos */ + + /* 2DY*/ +0x80c1, +0x811f, +0x82e1, +0x8333, + +0x9005, +0x9105, +0x9233, +0x9330, +0x9403, +0x9514, +0x9730, +0x9930, + +0xa002, /*2d lclp out2 nega*/ +0xa103, /*2d lclp out2 pos*/ +0xa202, /*2d lclp out1 nega*/ +0xa303, /*2d lclp out1 pos*/ +0xa403, /*2d lclp in nega*/ +0xa504, /*2d lclp in pos*/ +0xa607, /*2d lclp dark1 nega*/ +0xa708, /*2d lclp dark1 pos*/ +0xa807, /*2d lclp dark2 nega*/ +0xa908, /*2d lclp dark2 pos*/ +0xaa07, /*2d lclp dark3 nega*/ +0xab08, /*2d lclp dark3 pos*/ + +0xb010, /*out2 H Ne*/ +0xb310, /* H Po*/ +0xb11e, /* M Ne*/ +0xb41e, /* M Po*/ +0xb21f, /* L Ne*/ +0xb51e, /* L Po*/ + +0xb610, /*out1 H Ne */ +0xb910, /* H Po */ +0xb71e, /* M Ne */ +0xba1e, /* M Po */ +0xb81f, /* L Ne */ +0xbb1e, /* L Po */ + +0xbc20, /*indoor H Ne*/ +0xbf1e, /* H Po*/ +0xbd25, /* M Ne*/ +0xc023, /* M Po*/ +0xbe24, /* L Ne*/ +0xc122, /* L Po*/ + +0xc223, /*dark1 H Ne*/ +0xc523, /* H Po*/ +0xc329, /* M Ne*/ +0xc629, /* M Po*/ +0xc425, /* L Ne*/ +0xc725, /* L Po*/ + +0xc81c, /*dark2 H Ne*/ +0xcb1c, /* H Po*/ +0xc925, /* M Ne*/ +0xcc25, /* M Po*/ +0xca23, /* L Ne*/ +0xcd23, /* L Po*/ + +0xce1c, /*dark3 H Ne*/ +0xd11c, /* H Po*/ +0xcf25, /* M Ne*/ +0xd225, /* M Po*/ +0xd023, /* L Ne*/ +0xd323, /* L Po*/ + +/* PAGE 14 START*/ +0x0314, +0x1031, + +0x1480, /* GX*/ +0x1580, /* GY*/ +0x1680, /* RX*/ +0x1780, /* RY*/ +0x1880, /* BX*/ +0x1980, /* BY*/ + +0x2060, /* X Center*/ +0x2180, /* Y Center*/ + +0x2280, +0x2380, +0x2480, + +0x30c8, +0x312b, +0x3200, +0x3300, +0x3490, + +0x4056, /*R min's set 4e*/ +0x413a, /*Gr*/ +0x4237, /*B*/ +0x433a, /*Gb*/ + +0x0315, +0x1021, +0x1444, /*49*/ +0x1534, /*38*/ +0x1626, /*2b*/ +0x172f, + +0x30dd, +0x3162, +0x3205, +0x3326, +0x34bd, +0x3517, +0x3618, +0x3738, +0x38d0, + +0x40b0, +0x4130, +0x4200, +0x4300, +0x4400, +0x4500, +0x4699, +0x4719, +0x4800, + +0x5016, +0x51b2, +0x521c, +0x5306, +0x5420, +0x55a6, +0x560e, +0x57b2, +0x5824, + +0x0316, +0x1031, /*GMA_CTL*/ +0x187e, /*AG_ON*/ +0x197d, /*AG_OFF*/ +0x1a0e, /*TIME_ON*/ +0x1b01, /*TIME_OFF*/ +0x1Cdc, /*OUT_ON*/ +0x1Dfe, /*OUT_OFF*/ + +/*GMA, Indoor*/ +0x3000, +0x3107, +0x321a, +0x3335, +0x345a, +0x357c, +0x3696, +0x37a9, +0x38b7, +0x39c6, +0x3ad2, +0x3bdc, +0x3ce4, +0x3deb, +0x3ef1, +0x3ff5, +0x40f9, +0x41fd, +0x42ff, + +/*RGMA, Outdoor*/ +0x5000, +0x5103, +0x5213, +0x532e, +0x5459, +0x5579, +0x5690, +0x57a3, +0x58b4, +0x59c2, +0x5acd, +0x5bd7, +0x5ce0, +0x5de5, +0x5ee9, +0x5fee, +0x60f1, +0x61f3, +0x62f6, + +/*BGMA Dark*/ +0x7000, +0x7107, +0x721a, +0x7335, +0x745a, +0x757c, +0x7696, +0x77a9, +0x78b7, +0x79c6, +0x7ad2, +0x7bdc, +0x7ce4, +0x7deb, +0x7ef1, +0x7ff5, +0x80f9, +0x81fd, +0x82ff, + +0x0324, /*Resol control */ +0x60c5, /*edge even frame | 16bit resol | white edge cnt | scene resol enable*/ +0x6104, /*even frame update */ +0x6408, /* 0x6435, edge th1 H*/ +0x6500, /*edge th1 L*/ +0x6626, /*edge th2 H */ +0x6700, /*edge th2 L */ + +0x0313, +0x1831, /*flat center Gb/Gr*/ +0x7402, /*det slope en | gausian filter*/ +0x750d, /*1D negative gain det 09 */ +0x760d, /*1D postive gain det 08*/ +0x7710, /*1D hclp2 det*/ +0x7808, /*outdoor flat threshold*/ +0x7910, /*indoor flat threshold*/ + +0x81df, /*det gain controler*/ +0x8690, /*2D negative gain det */ +0x8790, /*2D postive gain det */ +0x962a, /*2D hclp2 det*/ + +0x0312, /*0x12 page*/ +0xd088, +0xd9e4, + +/* PAGE 20 START*/ +0x0320, +0x111c, +0x1830, +0x1a08, +0x2045,/*weight*/ +0x2130, +0x2210, +0x2300, +0x2400, + +0x28e7, /* add 20120223*/ +0x290d, /* 20100305 ad -> 0d*/ +0x2afd, +0x2bf8, + +0x2cc3, +0x2d5f, /* add 20120223*/ +0x2e33, +0x30f8, +0x3203, +0x332e, +0x3430, +0x35d4, +0x36fe, +0x3732, +0x3804, +0x3922, +0x3ade, +0x3b22, +0x3cde, +0x3de1, + +0x5045, +0x5188, + +0x561a, +0x5780, +0x580e, +0x596a, +0x5a04, + +0x5e9d, /*AE_AWB_start*/ +0x5f76, /*AE_AWB_start*/ + +0x7040, /* 6c*/ +0x7182, /* 82(+8)*/ + +0x7621, +0x7791, +0x7822, /* 24*/ +0x792b, /* Y Target 70 => 25, 72 => 26*/ +0x7a23, /* 23*/ +0x7b22, /* 22*/ +0x7d23, + +0x8301, /*EXP Normal 33.33 fps */ +0x845f, +0x8590, + +0x8601, /*EXPMin 7500.00 fps*/ +0x8790, + +0x8803, /*EXP Max(120Hz) 12.00 fps*/ +0x89d0, +0x8a90, + +0xa504, /*EXP Max(100Hz) 11.11 fps*/ +0xa61e, +0xa7b0, + +0x8B75, /*EXP100 */ +0x8C30, +0x8D61, /*EXP120 */ +0x8Ea8, + +0x9104, /*EXP Fix 10.00 fps*/ +0x9293, +0x93e0, + +0x9c0a, /*EXP Limit 1071.43 fps*/ +0x9df0, +0x9e01, /*EXP Unit */ +0x9f90, +0x989d, + +0xb016, +0xb114, +0xb2f8, +0xb314, +0xb41b, +0xb546, +0xb631, +0xb729, +0xb826, +0xb924, +0xba22, +0xbb42, +0xbc41, +0xbd40, + +0xc010, +0xc138, +0xc238, +0xc338, +0xc407, + +0xc880, +0xc980, +0x109c, /* ae enable*/ +/* PAGE 20 END*/ + +/*AE_Weight*/ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2412, +0x2522, +0x2622, +0x2721, +0x2812, +0x2922, +0x2a22, +0x2b21, +0x2c12, +0x2d23, +0x2e32, +0x2f21, +0x3012, +0x3123, +0x3232, +0x3321, +0x3412, +0x3522, +0x3622, +0x3721, +0x3812, +0x3922, +0x3a22, +0x3b21, +0x3c11, +0x3d11, +0x3e11, +0x3f11, + +/* PAGE 22 START*/ +0x0322, +0x10fd, +0x112e, +0x1901, /* Low On*/ +0x2030, /* for wb speed*/ +0x2140, +0x2401, +0x257e, /* for tracking 20120314 */ + +0x3080, /* 20120224 test*/ +0x3180, +0x3811, +0x3934, + +0x40e8, +0x4143, /* 33*/ +0x4222, /* 22*/ + +0x43f3, /* f6*/ +0x4454, /* 44*/ +0x4522, /* 33*/ + +0x4600, +0x480a, +0x50b2, +0x5181, +0x5298, + +0x8038, +0x8120, +0x8238, /* 3a*/ + +0x8356, /* R Max*/ +0x8420, /* R Min*/ +0x8554, /* B Max*/ +0x8620, /* B Min*/ + +0x8746, +0x8836, +0x893a, +0x8a2f, + +0x8b3d, +0x8c37, +0x8d35, +0x8e32, + +0x8f5a, +0x9059, +0x9155, +0x924e, +0x9344, +0x943a, +0x9534, +0x962c, +0x9723, +0x9820, +0x991f, +0x9a1f, + +0x9b77, +0x9c77, +0x9d48, +0x9e38, +0x9f30, + +0xa040, +0xa121, +0xa26f, +0xa3ff, + +0xa414, /* 1500fps*/ +0xa544, /* 700fps*/ +0xa6cf, + +0xad40, +0xae4a, + +0xaf2a, /* low temp Rgain*/ +0xb028, /* low temp Rgain*/ + +0xb100, /* 0x20 -> 0x00 0405 modify*/ +0xb4bf, /* for tracking 20120314*/ +0xb8a1, /* a2: b-2, R+2 b4 B-3, R+4 lowtemp b0 a1 Spec AWB A modify*/ +0xb900, +/* PAGE 22 END*/ + +/* PAGE 48 (MiPi 1600x1200)*/ +0x0300, + +/* PLL Setting */ +0xd005, +0xd130, +0xd205, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +/* MIPI TX Setting */ +0x0348, +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +0x1d0e, +0x1e07, +0x1f08, +/*0x2000,*/ + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2a06,*/ +/*0x2b40,*/ +/*0x2c04,*/ +/*0x2db0,*/ + +0x3005, +0x3100, + +0x3207, +0x3309, +0x3401, +0x3501, +/*0x3601,*/ +/*0x3707,*/ +/*0x3802,*/ +/*0x3902,*/ + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_SmartStay_Init_Reg[] = { +/*0 Page*/ +0x0300, +0x0101, /*sleep*/ +0x0103, /*s/w reset*/ +0x0101, /*sleep*/ + +0x0800,/*Don't touch*/ +0x0937,/*Don't touch*/ +0x0a33,/*Don't touch*/ + +/*PLL Setting*/ +0xd005, +0xd130, +0xd201, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x1011, +0x1190, /*xy flip*/ +0x1200, +0x1488, + +0x0300, +0x2000, +0x2104, +0x2200, +0x2304, +0x2403, +0x25C0, +0x2605, +0x2700, + +0x4001, /*Hblank_280*/ +0x4118, +0x4201, /*Vblank 400*/ +0x4390, + +/*--------------- BLC*/ +0x8008, /*Don't touch */ +0x8197, /*Don't touch */ +0x8290, /*Don't touch */ +0x8330, /*Don't touch */ +0x84cc, /*Don't touch*/ +0x8500, /*Don't touch*/ +0x86d4, /*Don' t touch*/ +0x870f, /*Don't touch*/ +0x8834, /*Don't touch*/ + +0x900c, /*BLC_TIME_TH_ON*/ +0x910c, /*BLC_TIME_TH_OFF */ +0x92f7, /*BLC_AG_TH_ON*/ +0x93ef, /*BLC_AG_TH_OFF*/ + +0x9495, /*091202*/ +0x9590, /*091202 */ +0x9838, /*Don't touch*/ + +/*Dark BLC*/ +0xa000, /* 20100309*/ +0xa200, /* 20100309*/ +0xa400, /* 20100309*/ +0xa600, /* 20100309*/ + +/*Normal BLC*/ +0xa800, +0xaa00, +0xac00, +0xae00, + +/*Out BLC*/ +0x9900, +0x9a00, +0x9b00, +0x9c00, + +/*2 Page*/ +0x0302, +0x1200, /*Don't touch*/ +0x1400, /*Don't touch*/ +0x1500, /*Don't touch*/ +0x184C, /*Don't touch*/ +0x1900, /*Don't touch*/ +0x1A39, /*Don't touch*/ +0x1B00,/*Don't touch*/ +0x1C1a, /*Don't touch*/ +0x1D14, /*Don't touch*/ +0x1E30,/*Don't touch*/ +0x1F10,/*Don't touch*/ + +0x2077, +0x21de, +0x22a7, +0x2330, +0x2477, +0x2510, +0x2610, +0x273c, +0x2b80, +0x2c02, +0x2da0, +0x2e00, +0x2fa7, + +0x3000, +0x3199, +0x3200, +0x3300, +0x3422, +0x3601, +0x3701, +0x3888, +0x3988, +0x3d03, +0x3e0d, +0x3f02, + +0x49d1, +0x4a14, + +0x5021, +0x5201, +0x5381, +0x5410, +0x551c, +0x5611, +0x5818, +0x5916, +0x5da2, +0x5e5a, + +0x6093, /* 20120517 modify*/ +0x61a4, /* 20120517 modify*/ +0x6294, /* 20120517 modify*/ +0x63a3, /* 20120517 modify*/ +0x6494, /* 20120517 modify*/ +0x65a3, /* 20120517 modify*/ +0x670c, +0x680c, +0x690c, +0x6ab4, +0x6bc4, +0x6cb5, +0x6dc2, +0x6eb5, +0x6fc0, + +0x70b6, +0x71b8, +0x7295, /* 20120517 modify*/ +0x73a2, /* 20120517 modify*/ +0x7495, /* 20120517 modify*/ +0x75a2, /* 20120517 modify*/ +0x7695, /* 20120517 modify*/ +0x77a2, /* 20120517 modify*/ +0x7C92, /* 20120517 modify*/ +0x7Dff, /* 20120517 modify*/ + +0x8001, /* 20120517 modify*/ +0x818a, /* 20120517 modify*/ +0x821e, /* 20120517 modify*/ +0x8336, /* 20120517 modify*/ +0x8489, /* 20120517 modify*/ +0x858b, /* 20120517 modify*/ +0x8689, /* 20120517 modify*/ +0x878b, /* 20120517 modify*/ +0x88ab, +0x89bc, +0x8aac, +0x8bba, +0x8cad, +0x8db8, +0x8eae, +0x8fb2, + +0x90b3, +0x91b7, +0x9252, /* 20120517 modify*/ +0x936a, /* 20120517 modify*/ +0x9489, /* 20120517 modify*/ +0x958b, /* 20120517 modify*/ +0x9689, /* 20120517 modify*/ +0x978b, /* 20120517 modify*/ + +0xA002, +0xA186, /* 20120517 modify*/ +0xA202, +0xA386, /* 20120517 modify*/ +0xA486, /* 20120517 modify*/ +0xA502, +0xA686, /* 20120517 modify*/ +0xA702, +0xA892, /* 20120517 modify*/ +0xA994, /* 20120517 modify*/ +0xAA92, /* 20120517 modify*/ +0xAB94, /* 20120517 modify*/ +0xAC1c, +0xAD22, +0xAE1c, +0xAF22, + +0xB0a4, /* 20120517 modify*/ +0xB1ae, /* 20120517 modify*/ +0xB2a4, /* 20120517 modify*/ +0xB3ae, /* 20120517 modify*/ +0xB4a6, /* 20120517 modify*/ +0xB5ac, /* 20120517 modify*/ +0xB6a6, /* 20120517 modify*/ +0xB7ac, /* 20120517 modify*/ +0xB8a6, /* 20120517 modify*/ +0xB9ab, /* 20120517 modify*/ +0xBAa6, /* 20120517 modify*/ +0xBBab, /* 20120517 modify*/ +0xBCa6, /* 20120517 modify*/ +0xBDab, /* 20120517 modify*/ +0xBEa6, /* 20120517 modify*/ +0xBFab, /* 20120517 modify*/ + +0xc437, +0xc552, +0xc66b, +0xc786, +0xc838, /* 20120517 modify*/ +0xc950, /* 20120517 modify*/ +0xca38, /* 20120517 modify*/ +0xcb50, /* 20120517 modify*/ +0xcc6c, /* 20120517 modify*/ +0xcd84, /* 20120517 modify*/ +0xce6c, /* 20120517 modify*/ +0xcf84, /* 20120517 modify*/ + +/*0xd4a6,*/ +/*0xd5ac,*/ +/*0xd6a6,*/ +/*0xd7ac,*/ +/*add 20120517*/ +0xdc00, /* Added*/ +0xddaf, /* Added*/ +0xde00, /* Added*/ +0xdf90, /* Added*/ + +0xd010, +0xd114, +0xd220, +0xd300, +/*DCDC */ +0xd40c, /*DCDC_TIME_TH_ON*/ +0xd50c, /*DCDC_TIME_TH_OFF */ +0xd6f7, /*DCDC_AG_TH_ON*/ +0xd7ef, /*DCDC_AG_TH_OFF*/ + +0xea8a, + +0xF001, /* clock inversion*/ +0xF101, +0xF201, +0xF301, +0xF401, +0xF500, + +/*----------------------------------------------*/ +0x0310, /*page 10*/ +0x1001, /*Ycbcr422_bit Order: YUYV*/ +0x1103, +0x1230, /*y offset[4], dif_offset[5]*/ +0x1302, /*contrast effet enable : 0x02*/ +0x3400, /*hidden 10->00 100209*/ +0x3701, /*yc2d power save */ +0x3f04, /*100825*/ +0x4080, /*Y offset */ +0x4128, +0x4880, +0x5300, /*dif_offset option */ +0x5530, /*dif_offset option diff_offset max */ + +0x606b, /*out color sat en[7] | auto color decrement en[1] / + | manual color sat en[0]*/ + +0x6183, /*blue saturation_C0*/ +0x6280, /*red saturation_B0*/ + +0x63b0, /*auto decresment on AG th*/ +0x64ff, /*auto decresment on DG th*/ +0x66e4, /*Outdoor saturation step 137fps apply out th */ +0x6700, /*Outdoor saturation B/R*/ +0x7601, /* ADD 20121031 */ +0x7904, /* ADD 20121031 */ + +/* Hi 163 */ +/* PAGE 10 START*/ +0x0310, +0x8000, /* dsshin --> color enhance*/ +0xf500, /* dsshin --> h blank option*/ + +0x0311, /*page 11 D_LPF */ +0x103f, /*B[6]:Blue En Dlpf on[4:0] Sky over off : 0x7f->3f*/ +0x1120, /* Uniform Full GbGr/OV-Nr*/ + +0x1280, /*Blue MaxOpt blue sky max filter optoin rate : 0 0xc0->80*/ +0x13b8, /*dark2[7] | ratio[6:4] | dark3[3] | dark3 maxfilter ratio[2:0] */ + +0x30ba, /*Outdoor2 H th*/ +0x3110, /*Outdoor2 L th*/ +0x3250, /*Outdoor2 gain ratio*/ +0x331d, /*Outdoor2 H lum*/ +0x3420, /*Outdoor2 M lum*/ +0x351f, /*Outdoor2 L lum*/ + +0x36b0, /*Outdoor1 H th*/ +0x3718, /*Outdoor1 L th*/ +0x3850, /*Outdoor1 gain ratio 0x80->40*/ +0x391d, /*Outdoor1 H lum 0x28->1e*/ +0x3a20, /*Outdoor1 M lum 0x10->15*/ +0x3b1f, /*Outdoor1 L lum 0x08->20*/ + +0x3c3f, /*indoor H th*/ +0x3d16, /*indoor L th*/ +0x3e30, /*indoor gain ratio 0x44 6a */ +0x3f1a, /*indoor H lum 0x12 18 */ +0x4060, /*indoor M lum 0x18 1c*/ +0x411a, /*indoor L lum 0x18 3e*/ + +0x4280, /*dark1 H th*/ +0x4318, /*dark1 L th*/ +0x4480, /*dark1 gain ratio*/ +0x450f, /*dark1 H lum 0x38->0x28 */ +0x460c, /*dark1 M lum 0x27->0x17*/ +0x470b, /*dark1 L lum 0x20->0x1a */ + +0x4880, /*dark2 H th*/ +0x4918, /*dark2 L th*/ +0x4a80, /*dark2 gain ratio*/ +0x4b0f, /*dark2 H lum */ +0x4c0c, /*dark2 M lum*/ +0x4d0b, /*dark2 L lum */ + +0x4e80, /*dark3 H th*/ +0x4f23, /*dark3 L th*/ +0x5080, /*dark3 gain ratio*/ +0x511d, /*dark3 H lum */ +0x521f, /*dark3 M lum */ +0x531f, /*dark3 L lum */ + +0x5a3f, /*blue sky mode out1/2 enable 0x27->3f */ +0x5b00, /*Impulse pixel enable dark123,in,out123 :: must be 0x07*/ +0x5c9f, /*Indoor maxfilter rate[7:5] | Uncertain onoff[4:0] 0x1f ->0x9f*/ + +0x603f, /*GbGr all enable*/ +0x620f, /*GbGr offset*/ + +0x650c, /*Outdoor GbGr rate H 100% M 25% L 100%*/ +0x660c, /*Indoor GbGr rate H 100% M 25% L 100%*/ +0x6700, /*dark GbGr rate H/M/L 100%*/ + +0x700c, /* Abberation On/Off B[1]: Outdoor B[0]: Indoor 07>>c*/ +0x75a0, /* Outdoor2 Abberation Luminance lvl */ +0x7db4, /* Indoor Abberation Luminance lvl*/ + +0x9608, /*indoor/Dark1 edgeoffset1*/ +0x9714, /*indoor/Dark1 center G value*/ +0x98f5, /*slope indoor :: left/right graph polarity, slope*/ +0x992a, /*indoor uncertain ratio control*/ +0x9a20, /*Edgeoffset_dark*/ + +/*DPC_CTRL*/ +0x0312, /*Preview DPC off[0x5c] on[0x5d]*/ +0x200f, +0x210f, + +0x2500, /* 0x30*/ + +0x2a01, +0x2e00, /*2010.8.25*/ + +0x3035, /*Texture region(most detail)*/ +0x31a0, /*STD uniform1 most blur region*/ +0x32b0, /*STD uniform2 2nd blur*/ +0x33c0, /*STD uniform3 3rd blur*/ +0x34d0, /*STD normal noise1 4th blur */ +0x35e0, /*STD normal noise2 5th blur*/ +0x36ff, /*STD normal noise3 6th blur*/ + +0x4083, /*Outdoor2 H th*/ +0x4120, /*Outdoor2 L th */ +0x4208, /*Outdoor2 H luminance */ +0x4310, /*Outdoor2 M luminance */ +0x4410, /*Outdoor2 l luminance */ +0x4550, /*Outdoor2 ratio*/ + +0x4683, /*Outdoor1 H th*/ +0x4720, /*Outdoor1 L th */ +0x4808, /*Outdoor1 H luminance*/ +0x4910, /*Outdoor1 M luminance*/ +0x4a10, /*Outdoor1 L luminance*/ +0x4b50, /*Outdoor1 ratio*/ + +0x4c80, /*Indoor H th*/ +0x4d48, /*Indoor L th*/ +0x4e30, /*indoor H lum*/ +0x4f30, /*indoor M lum*/ +0x5012, /*indoor L lum */ +0x5170, /*indoor ratio 0x10 -> 0x45*/ + +0x52a8, /*dark1 H th*/ +0x5330, /*dark1 L th */ +0x5428, /*dark1 H lum */ +0x553e, /*dark1 M lum*/ +0x5667, /*dark1 L lum*/ +0x576a, /*dark1 ratio*/ + +0x58a0, /*dark2 H th*/ +0x5940, /*dark2 L th*/ +0x5a28, /*dark2 H lum*/ +0x5b3f, /*dark2 M lum*/ +0x5c68, /*dark2 L lum*/ +0x5d70, /*dark2 ratio*/ + +0x5ea0, /*dark3 H th*/ +0x5f1c, /*dark3 L th*/ +0x6029, /*dark3 H lum*/ +0x614a, /*dark3 M lum*/ +0x62ff, /*dark3 L lum*/ +0x63ff, /*dark3 ratio*/ + +/*C-filter(Out2&Out1)*/ +0x7010, +0x710a, + +/*C-filter(Indoor&Dark3)*/ +0x7210, +0x730a, + +/*C-filter(Dark2&Dark1)*/ +0x7418, +0x7512, + +0x8020, +0x8140, +0x8265, +0x851a, +0x8800, +0x8900, +0x905d, /*Preview DPC off[0x5c] on[0x5d]*/ + +/*DPC-Dark1,2,3*/ +0xad07, /*10825*/ +0xae07, /*10825*/ +0xaf07, /*10825*/ + +/*Blue Det..*/ +0xc558, /*BlueRange 2010.8.25 0x40->23 */ +0xc620, /*GreenRange 2010.8.25 0x3b->20 */ + +0xd088, /*2010.8.25*/ +0xd180, +0xd217,/*preview 17, full 67*/ +0xd300, +0xd400, +0xd50f,/*preview 0f, full 02*/ +0xd6ff, +0xd7ff,/*preview ff, full 18*/ +0xd800, +0xd904, + +/*interpolated with average*/ +0xdb38, /*resolution issue 0x00->0x18->0x38 */ +0xd904, /*strong_edge detect ratio*/ +0xe001, /*strong_edge detect ratio*/ + +0x0313, /*page 13 sharpness 1D*/ +0x10c5, +0x117b, +0x120e, +0x1400, + +0x1511, /*added option 1.3M*/ +0x1830, /*added option 1.3M*/ + +0x2015, +0x2113, +0x2233, +0x2308, /*hi_clip th1*/ +0x241a, /*hi_clip th2*/ +0x2506, /*low clip th*/ + +0x2618, +0x2730, +0x2910, /*time th*/ +0x2a30, /*pga th*/ + +0x2b03, /*lpf out2*/ +0x2c03, /*lpf out1*/ +0x2d0c, +0x2e12, +0x2f12, + +/*1D Edge*/ +0x500a, /*out2 hi nega*/ +0x5307, /* hi pos*/ +0x510c, /* mi nega*/ +0x5407, /* mi pos*/ +0x520b, /* lo nega*/ +0x5508, /* lo pos*/ + +0x560a, /*out1 hi nega*/ +0x5907, /* hi pos */ +0x570c, /* mi nega*/ +0x5a07, /* mi pos */ +0x580b, /* lo nega*/ +0x5b08, /* lo pos */ + +/*Indoor Edge*/ +0x5c08, /*indoor hi nega*/ +0x5f07, /* hi pos*/ +0x5d14, +0x6012, +0x5e0a, +0x6108, /* low pos*/ + +0x6208, /*dark1 hi nega*/ +0x6506, /* hi pos */ +0x6308, /* mid nega */ +0x6606, /* mid pos */ +0x6408, /* low nega */ +0x6706, /* low pos */ + +0x6807, /*dark2 hi nega*/ +0x6b05, /* hi pos */ +0x6907, /* mid nega */ +0x6c05, /* mid pos */ +0x6a07, /* low nega */ +0x6d05, /* low pos */ + +0x6e0a, /*dark3 hi nega*/ +0x7109, /* hi pos */ +0x6f0d, /* mid nega */ +0x720c, /* mid pos */ +0x700d, /* low nega */ +0x730c, /* low pos */ + + /* 2DY*/ +0x80c1, +0x811f, +0x82e1, +0x8333, + +0x9005, +0x9105, +0x9233, +0x9330, +0x9403, +0x9514, +0x9730, +0x9930, + +0xa002, /*2d lclp out2 nega*/ +0xa103, /*2d lclp out2 pos*/ +0xa202, /*2d lclp out1 nega*/ +0xa303, /*2d lclp out1 pos*/ +0xa403, /*2d lclp in nega*/ +0xa504, /*2d lclp in pos*/ +0xa607, /*2d lclp dark1 nega*/ +0xa708, /*2d lclp dark1 pos*/ +0xa807, /*2d lclp dark2 nega*/ +0xa908, /*2d lclp dark2 pos*/ +0xaa07, /*2d lclp dark3 nega*/ +0xab08, /*2d lclp dark3 pos*/ + +0xb010, /*out2 H Ne*/ +0xb310, /* H Po*/ +0xb11e, /* M Ne*/ +0xb41e, /* M Po*/ +0xb21f, /* L Ne*/ +0xb51e, /* L Po*/ + +0xb610, /*out1 H Ne */ +0xb910, /* H Po */ +0xb71e, /* M Ne */ +0xba1e, /* M Po */ +0xb81f, /* L Ne */ +0xbb1e, /* L Po */ + +0xbc20, /*indoor H Ne*/ +0xbf1e, /* H Po*/ +0xbd25, /* M Ne*/ +0xc023, /* M Po*/ +0xbe24, /* L Ne*/ +0xc122, /* L Po*/ + +0xc223, /*dark1 H Ne*/ +0xc523, /* H Po*/ +0xc329, /* M Ne*/ +0xc629, /* M Po*/ +0xc425, /* L Ne*/ +0xc725, /* L Po*/ + +0xc81c, /*dark2 H Ne*/ +0xcb1c, /* H Po*/ +0xc925, /* M Ne*/ +0xcc25, /* M Po*/ +0xca23, /* L Ne*/ +0xcd23, /* L Po*/ + +0xce1c, /*dark3 H Ne*/ +0xd11c, /* H Po*/ +0xcf29, /* M Ne*/ +0xd229, /* M Po*/ +0xd027, /* L Ne*/ +0xd327, /* L Po*/ + +/* PAGE 14 START*/ +0x0314, +0x1031, + +0x1480, /* GX*/ +0x1580, /* GY*/ +0x1680, /* RX*/ +0x1780, /* RY*/ +0x1880, /* BX*/ +0x1980, /* BY*/ + +0x2060, /* X Center*/ +0x2180, /* Y Center*/ + +0x2280, +0x2380, +0x2480, + +0x30c8, +0x312b, +0x3200, +0x3300, +0x3490, + +0x4056, /*R min's set 4e*/ +0x413a, /*Gr*/ +0x4237, /*B*/ +0x433a, /*Gb*/ + +0x0315, +0x1021, +0x1444, /*49*/ +0x1534, /*38*/ +0x1626, /*2b*/ +0x172f, + +0x30dd, +0x3162, +0x3205, +0x3326, +0x34bd, +0x3517, +0x3618, +0x3738, +0x38d0, + +0x40b0, +0x4130, +0x4200, +0x4300, +0x4400, +0x4500, +0x4699, +0x4719, +0x4800, + +0x5016, +0x51b2, +0x521c, +0x5306, +0x5420, +0x55a6, +0x560e, +0x57b2, +0x5824, + +0x0316, +0x1031, /*GMA_CTL*/ +0x187e, /*AG_ON*/ +0x197d, /*AG_OFF*/ +0x1a0e, /*TIME_ON*/ +0x1b01, /*TIME_OFF*/ +0x1Cdc, /*OUT_ON*/ +0x1Dfe, /*OUT_OFF*/ + +/*GMA Indoor*/ +0x3000, +0x3126, +0x3238, +0x3355, +0x347e, +0x3597, +0x36a9, +0x37ba, +0x38c7, +0x39d2, +0x3adb, +0x3be3, +0x3cea, +0x3dee, +0x3ef5, +0x3ff9, +0x40fc, +0x41fe, +0x42ff, + +/*RGMA Outdoor*/ +0x5000, +0x5126, +0x5238, +0x5355, +0x547e, +0x5597, +0x56a9, +0x57ba, +0x58c7, +0x59d2, +0x5adb, +0x5be3, +0x5cea, +0x5dee, +0x5ef5, +0x5ff9, +0x60fc, +0x61fe, +0x62ff, + +/*BGMA Dark*/ +0x7002, +0x712a, +0x723b, +0x7359, +0x7481, +0x759b, +0x76ac, +0x77be, +0x78ca, +0x79d4, +0x7adb, +0x7be4, +0x7ceb, +0x7def, +0x7ef6, +0x7ffa, +0x80fc, +0x81fe, +0x82ff, + +0x0324, /*Resol control */ +0x60c5, /*edge even frame | 16bit resol | white edge cnt | scene resol enable*/ +0x6104, /*even frame update */ +0x6408, +0x6500, +0x6626, /*edge th2 H */ +0x6700, /*edge th2 L */ + +0x0313, +0x1831, /*flat center Gb/Gr*/ +0x7402, /*det slope en | gausian filter*/ +0x750d, /*1D negative gain det 09 */ +0x760d, /*1D postive gain det 08*/ +0x7710, /*1D hclp2 det*/ +0x7808, /*outdoor flat threshold*/ +0x7910, /*indoor flat threshold*/ + +0x81df, /*det gain controler*/ +0x8690, /*2D negative gain det */ +0x8790, /*2D postive gain det */ +0x962a, /*2D hclp2 det*/ + +0x0312, /*0x12 page*/ +0xd088, +0xd9e4, + +/* PAGE 18 START*/ +0x0318, +0x1400, + +/* PAGE 20 START*/ +0x0320, +0x111c, +0x1830, +0x1a08, +0x2045,/*weight*/ +0x2130, +0x2210, +0x2300, +0x2400, + +0x28e7, /* add 20120223*/ +0x290d, /* 20100305 ad -> 0d*/ +0x2afd, +0x2bf8, + +0x2cc3, +0x2d5f, /* add 20120223*/ +0x2e33, +0x30f8, +0x3203, +0x332e, +0x3430, +0x35d4, +0x36ff, /*fe*/ +0x3732, +0x3804, +0x3922, +0x3ade, +0x3b22, +0x3cde, +0x3de1, + +0x5045, +0x5188, + +0x561a, +0x5780, +0x580e, +0x596a, +0x5a04, + +0x5e9d, /*AE_AWB_start*/ +0x5f76, /*AE_AWB_start*/ + +0x703f, /* 6c*/ +0x7180, /* 82(+8)*/ + +0x7621, +0x7781, +0x7822, /* 24*/ +0x7925, /* Y Target 70 => 25, 72 => 26*/ +0x7a23, /* 23*/ +0x7b22, /* 22*/ +0x7d23, + +0x8301, /*EXP Normal 30.00 fps */ +0x845f, +0x8590, +0x8601, /*EXPMin 7500.00 fps*/ +0x8790, +0x8805, /*EXP Max(120Hz) 8.00 fps */ +0x89b8, +0x8ad8, +0xa505, /*EXP Max(100Hz) 8.33 fps */ +0xa67e, +0xa740, +0x8B75, /*EXP100 */ +0x8C30, +0x8D61, /*EXP120 */ +0x8Ea8, +0x9c09, /*EXP Limit 1250.00 fps */ +0x9d60, +0x9e01, /*EXP Unit */ +0x9f90, +0x989d, + +0xb016, +0xb114, +0xb2f0, +0xb314, +0xb41b, +0xb546, +0xb631, +0xb729, +0xb826, +0xb924, +0xba22, +0xbb42, +0xbc41, +0xbd40, + +0xc010, +0xc138, +0xc238, +0xc338, +0xc407, + +0xc880, +0xc980, +0x109c, /* ae enable*/ +/* PAGE 20 END*/ + +/*AE_Weight*/ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2422, +0x2522, +0x2622, +0x2721, +0x2823, +0x2933, +0x2a32, +0x2b21, +0x2c23, +0x2d44, +0x2e32, +0x2f21, +0x3023, +0x3144, +0x3232, +0x3311, +0x3423, +0x3533, +0x3632, +0x3721, +0x3822, +0x3922, +0x3a22, +0x3b21, +0x3c11, +0x3d11, +0x3e11, +0x3f11, + +/* PAGE 22 START*/ +0x0322, +0x10fd, +0x112e, +0x1901, /* Low On*/ +0x2030, /* for wb speed*/ +0x2140, +0x2401, +0x257e, /* for tracking 20120314 */ + +0x3080, /* 20120224 test*/ +0x3180, +0x3811, +0x3934, + +0x40e8, +0x4143, /* 33*/ +0x4222, /* 22*/ + +0x43f3, /* f6*/ +0x4454, /* 44*/ +0x4522, /* 33*/ + +0x4600, +0x480a, +0x50b2, +0x5181, +0x5298, + +0x8038, +0x8120, +0x8238, /* 3a*/ + +0x8356, /* R Max*/ +0x8420, /* R Min*/ +0x8552, /* B Max*/ +0x8620, /* B Min*/ + +0x8746, +0x8836, +0x8939, +0x8a2d, + +0x8b3c, +0x8c36, +0x8d34, +0x8e31, + +0x8f5a, +0x9059, +0x9154, +0x924d, +0x9342, +0x943a, +0x9534, +0x962c, +0x9723, +0x9820, +0x991f, +0x9a1f, + +0x9b77, +0x9c77, +0x9d48, +0x9e38, +0x9f30, + +0xa040, +0xa122, +0xa26f, +0xa3ff, + +0xa414, /* 1500fps*/ +0xa544, /* 700fps*/ +0xa6cf, + +0xad40, +0xae4a, + +0xaf2a, /* low temp Rgain*/ +0xb028, /* low temp Rgain*/ + +0xb100, /* 0x20 -> 0x00 0405 modify*/ +0xb4bf, /* for tracking 20120314*/ +0xb8a1, /* a2: b-2, R+2 b4 B-3, R+4 lowtemp b0 a1 Spec AWB A modify*/ +0xb900, +/* PAGE 22 END*/ + +/* PAGE 48 (MiPi 1600x1200)*/ +0x0300, + +/* PLL Setting */ +0xd005, +0xd130, +0xd205, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x0348, +/* MIPI TX Setting */ +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +0x1d0e, +0x1e07, +0x1f08, + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2b40,*/ + +0x3005, +0x3100, + +0x3207, +0x3309, +0x3401, +0x3501, + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_stop_stream[] = { +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t SR130PC20_Preview_Mode[] = +{ +0x0300, +0x0101,/*sleep*/ + +0xd005,/*Pll Off*/ + +0x0320, +0x101c,/*AE off (0x0c:60Hz 0x1c:50Hz)*/ +0x0322, +0x107d,/*AWB off*/ + +0x0300, +0x1011, +/* 0x1190, *//*0x91 : mirror mode*/ + +/* page 11 yc_lpf */ +0x0311, +0x5b00,/*don't touch*/ + +/* PAGE 12 YC_LPF */ +0x0312, +0x200f, +0x210f, + +/*preview DPC*/ +0xd217, +0xd50f, +0xd7ff, + + +/* PAGE13 Sharpness 1D/2D */ +0x0313, +0x10c4, +0x80c0, + +/* PAGE 18 START*/ +0x0318, +0x1443, /*83*/ + +0x0320, +0x109c, /*AE ON (0x8c:60Hz 0x9c:50Hz)*/ +0x0322, +0x10fd, /*AWB ON*/ + +0x0300, /*Page 0 PLL on*/ +0xd005, +0xd130, +0xd205, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +/* MIPI TX Setting */ +0x0348, +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +/*0x1d09,*/ +0x1d0e, +0x1e07, +0x1f08, +/*0x2000,*/ + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2a06,*/ +/*0x2b40,*/ +/*0x2c04,*/ +/*0x2db0,*/ + +0x3005, +0x3100, + +0x3207, +0x3309, +0x3401, +0x3501, +/*0x3601,*/ +/*0x3707,*/ +/*0x3802,*/ +/*0x3902,*/ + +0x0300, +0x0100, + +}; + +static const sr130pc20_regset_t SR130PC20_Capture_Mode[] = +{ +0x0300, +0x0101,/*sleep*/ + +0xd005,/*Pll off*/ + +0x0322, +0x107d,/*AWB off*/ + +0x0300, +0x1000, +/* 0x1190, */ + +0x0302, +0x2faa, + +0x0311, +0x5b00,/*don't touch*/ + +0x0312, +0x200f, +0x210f, + +/*preview DPC*/ +0xd267, +0xd502, +0xd718, + +0x0313, +0x10c5, +0x80c1,/*Sharpness 2D On[0xc1] Off[0xc0]*/ + +/* PAGE 18 START*/ +0x0318, +0x1400, + +0x0300, +0xd005,/*pll on*/ +0xd130, +0xd201, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x0348, +/* MIPI TX Setting */ +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +0x1d0d, /* 0c:90ns , 0b:110ns */ +0x1e0f, +0x1f0a, +/*0x2000,*/ + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2a06,*/ +/*0x2b40,*/ +/*0x2c04,*/ +/*0x2db0,*/ + +0x300a, +0x3100, + +0x320d, +0x330b, +0x3402, +0x3504, +0x3601, +0x3709, +/*0x3802,*/ +/*0x3902,*/ + +0x0300, +0x0100,/*sleep off*/ + +}; + +static const sr130pc20_regset_t SR130PC20_Lowlux_Night_Capture_Mode[] = +{ +0x0300, +0x0101,/*sleep*/ + +0xd005,/*Pll off*/ + +0x0322, +0x107d,/*AWB off*/ + +0x0300, +0x1000, +/* 0x1190, */ + +0x0302, +0x2faa, + +0x0311, +0x5b00,/*don't touch*/ + +0x0312, +0x200f, +0x210f, + +/*preview DPC*/ +0xd267, +0xd502, +0xd718, + +0x0313, +0x10c5, +0x80c1,/*Sharpness 2D On[0xc1] Off[0xc0]*/ + +/* PAGE 18 START*/ +0x0318, +0x1400, + +0x0300, +0xd005,/*pll on*/ +0xd130, +0xd201, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x0348, +/* MIPI TX Setting */ +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +0x1d0d, /* 0c:90ns , 0b:110ns */ +0x1e0f, +0x1f0a, +/*0x2000,*/ + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2a06,*/ +/*0x2b40,*/ +/*0x2c04,*/ +/*0x2db0,*/ + +0x300a, +0x3100, + +0x320d, +0x330b, +0x3402, +0x3504, +0x3601, +0x3709, +/*0x3802,*/ +/*0x3902,*/ + +0x0300, +0x0100,/*sleep off*/ + +0xff03, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Sketch[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Pastel[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Black_White[] = +{ +0x0310, +0x1103, +0x1233, +0x1302, +0x4080, +0x4480, +0x4580, +}; + +static const sr130pc20_regset_t SR130PC20_Effect_Negative[] = +{ +0x0310, +0x1103, +0x1238, +0x1302, +0x4080, +0x4480, +0x4580, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Solar[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Normal[] = +{ +0x0310, +0x1103, +0x1230, +0x1302, +0x4080, +0x4480, +0x4580, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Sepia[] = +{ +0x0310, +0x1103, +0x1233, +0x1302, +0x4080, +0x4470, +0x4598, +}; + +static const sr130pc20_regset_t sr130pc20_Metering_Center[] = +{ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2412, +0x2522, +0x2622, +0x2721, +0x2812, +0x2922, +0x2a22, +0x2b21, +0x2c12, +0x2d23, +0x2e32, +0x2f21, +0x3012, +0x3123, +0x3232, +0x3321, +0x3412, +0x3522, +0x3622, +0x3721, +0x3812, +0x3922, +0x3a22, +0x3b21, +0x3c11, +0x3d11, +0x3e11, +0x3f11, +}; + +static const sr130pc20_regset_t sr130pc20_Metering_Matrix[] = +{ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2411, +0x2511, +0x2611, +0x2711, +0x2811, +0x2911, +0x2a11, +0x2b11, +0x2c11, +0x2d11, +0x2e11, +0x2f11, +0x3011, +0x3111, +0x3211, +0x3311, +0x3411, +0x3511, +0x3611, +0x3711, +0x3811, +0x3911, +0x3a11, +0x3b11, +0x3c11, +0x3d11, +0x3e11, +0x3f11, +}; + +static const sr130pc20_regset_t sr130pc20_Metering_Spot[] = +{ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2411, +0x2511, +0x2611, +0x2711, +0x2811, +0x2911, +0x2a11, +0x2b11, +0x2c11, +0x2d13, +0x2e31, +0x2f11, +0x3011, +0x3113, +0x3231, +0x3311, +0x3411, +0x3511, +0x3611, +0x3711, +0x3811, +0x3911, +0x3a11, +0x3b11, +0x3c11, +0x3d11, +0x3e11, +0x3f11, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_Default[] = +{ +0x0310, +0x4080, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_M1Step[] = +{ +0x0310, +0x4090, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_M2Step[] = +{ +0x0310, +0x40A0, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_M3Step[] = +{ +0x0310, +0x40B0, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_M4Step[] = +{ +0x0310, +0x40d0, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_P1Step[] = +{ +0x0310, +0x4010, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_P2Step[] = +{ +0x0310, +0x4020, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_P3Step[] = +{ +0x0310, +0x4030, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_P4Step[] = +{ +0x0310, +0x4050, +}; + +static const sr130pc20_regset_t sr130pc20_ISO_50[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_ISO_100[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_ISO_200[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_ISO_400[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_ISO_Auto[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Default[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Landscape[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Sports[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Party_Indoor[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Beach_Snow[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Sunset[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Duskdawn[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Candle_Light[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Fall_Color[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Portrait[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Nightshot[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Fireworks[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Text[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Backlight[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Sharpness_Default[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_WB_Auto[] = +{ +0x0322, +0x106b, +0x112e, +0x8038, +0x8120, +0x8238, +0x8356, +0x8420, +0x8552, +0x8620, +0x10eb, +}; + +static const sr130pc20_regset_t sr130pc20_WB_Cloudy[] = +{ +0x0322, +0x106b, +0x112c, +0x8050, +0x8120, +0x8228, +0x8352, +0x844c, +0x852c, +0x8622, +0x10eb, +}; + +static const sr130pc20_regset_t sr130pc20_WB_Sunny[] = +{ +0x0322, +0x106b, +0x112c, +0x8038, +0x8120, +0x8235, +0x833b, +0x8434, +0x8538, +0x8631, +0x10eb, +}; + +static const sr130pc20_regset_t sr130pc20_WB_Fluorescent[] = +{ +0x0322, +0x106b, +0x112c, +0x8037, +0x8120, +0x8248, +0x8339, +0x8434, +0x854a, +0x8645, +0x10eb, +}; + +static const sr130pc20_regset_t sr130pc20_WB_Tungsten[] = +{ +0x0322, +0x106b, +0x112c, +0x8021, +0x8120, +0x824f, +0x8327, +0x841b, +0x8559, +0x8650, +0x10eb, +}; + +static const sr130pc20_regset_t sr130pc20_640_480_Preview[] = { +0x0300, +0x0101, + +0x0300, +0x1011, + +0x0318, +0x1000, + +0x0348, +0x3005, +0x3100, + +0x0300, +0x0100, + +0xff0a, +}; + +static const sr130pc20_regset_t sr130pc20_352_288_Preview[] = { +0x0300, +0x0101, +0x0300, +0x1011, + +0x0318, +0x1007, +0x1200, +0x2003, +0x2100, +0x2201, +0x2320, +0x2400, +0x2520, +0x2600, +0x2700, +0x2802, +0x29e0, +0x2a01, +0x2b20, +0x2c0d, +0x2d55, +0x2e0d, +0x2f55, +0x3051, + +0x0348, +0x3002, +0x31c0, + +0x0300, +0x0100, + +0xff28, +}; + +static const sr130pc20_regset_t sr130pc20_320_240_Preview[] = { +0x0300, +0x0101, + +0x0300, +0x1023, + +0x0318, +0x1000, + +0x0348, +0x3002, +0x3180, + +0x0300, +0x0100, + +0xff28, +}; + +static const sr130pc20_regset_t sr130pc20_176_144_Preview[] = { +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_1280_960_Capture[] = { +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_960_720_Capture[] = { +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_VGA_Capture[] = { +0xff00 +}; + +static const sr130pc20_regset_t sr130pc20_fps_auto[] = { +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_fps_7fix[] = { +0x0300, +0x0101, + +0x1190, + +0x4200, +0x4314, + +0x0320, +0x101C, + +0x0322, +0x107d, + +0x0320, +0x2af3, +0x2bf5, + +0x8301, /*EXP Normal 33.33 fps */ +0x845f, +0x8590, + +0x8806, /*EXP Max(120Hz) 7.50 fps */ +0x8968, +0x8aa0, + +0xa506, /*EXP Max(100Hz) 7.14 fps */ +0xa668, +0xa7a0, + +0x9106, /*EXP Fix 7.00 fps*/ +0x9289, +0x9370, + +0x0320, +0x109C, + +0x0322, +0x10fd, + +0x0300, +0x1194, + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_fps_15fix[] = { +0x0300, +0x0101, + +0x1190, + +0x4200, +0x4314, + +0x0320, +0x101C, + +0x0322, +0x107d, + +0x0310, /*page 10*/ +0x6007, +0x6380, /*auto decresment on AG th*/ + +0x0316, +0x7007, +0x711a, +0x722d, +0x7346, +0x746a, +0x7586, +0x769c, +0x77ad, +0x78bc, +0x79c9, +0x7ad4, +0x7bde, +0x7ce4, +0x7deb, +0x7ef1, +0x7ff5, +0x80f9, +0x81fd, +0x82ff, + +0x0322, +0x8f5d, +0x905a, +0x9156, +0x9250, +0x9348, +0x943f, + +0x0320, +0x2afd, +0x2bf8, + +0x8301, /*EXP Normal 33.33 fps */ +0x845f, +0x8590, + +0x8802, /*EXP Max(120Hz) 17.14 fps */ +0x89bf, +0x8a20, + +0xa502, /*EXP Max(100Hz) 16.67 fps */ +0xa6bf, +0xa720, + +0x9103, /*EXP Fix 15.00 fps*/ +0x920d, +0x9340, + +0x0320, +0x109C, + +0x0322, +0x10fd, + +0x0300, +0x1194, + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_fps_25fix[] = { +0x0300, +0x0101, + +0x1190, + +0x4200, +0x4362, + +0x0320, +0x101C, + +0x0322, +0x107d, + +0x0310, /*page 10*/ + +0x410a, +0x6007, +0x6380, /*auto decresment on AG th*/ + +0x0316, +0x7007, +0x711a, +0x722d, +0x7346, +0x746a, +0x7586, +0x769c, +0x77ad, +0x78bc, +0x79c9, +0x7ad4, +0x7bde, +0x7ce4, +0x7deb, +0x7ef1, +0x7ff5, +0x80f9, +0x81fd, +0x82ff, + +0x0322, +0x8f5d, +0x905a, +0x9156, +0x9250, +0x9348, +0x943f, + +0x0320, +0x2afd, +0x2bf8, + +0x8301, /*EXP Normal 33.33 fps */ +0x845d, +0x8538, + +0x8801, /*EXP Max(120Hz) 40.00 fps */ +0x895f, +0x8a90, + +0xa501, /*EXP Max(100Hz) 25.xx fps */ +0xa6d1, +0xa7a0, + +0x8b74, /*EXP100 */ +0x8c68, +0x8d60, /*EXP120 */ +0x8ee0, + +0x9101, /*EXP Fix 25.00 fps*/ +0x92d4, +0x93c0, + +0x0320, +0x109C, + +0x0322, +0x10fd, + +0x0300, +0x1194, + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_fps_30fix[] = +{ +/* sensor limitation, use 25fps */ +0xff00, +}; + +#endif /* __SR130PC20_REGS_H__ */ diff --git a/drivers/misc/max77693-muic.c b/drivers/misc/max77693-muic.c index 9a78d76..082777d 100644 --- a/drivers/misc/max77693-muic.c +++ b/drivers/misc/max77693-muic.c @@ -473,7 +473,7 @@ static ssize_t max77693_muic_show_manualsw(struct device *dev, struct max77693_muic_info *info = dev_get_drvdata(dev); #if !defined(CONFIG_MACH_T0) && !defined(CONFIG_MACH_M3) \ - && !defined(CONFIG_MACH_SLP_T0_LTE) + && !defined(CONFIG_MACH_SLP_T0_LTE) && !defined(CONFIG_MACH_KONA) dev_info(info->dev, "func:%s ap(0),cp(1),vps(2)sw_path:%d(%d)\n", __func__, info->muic_data->sw_path, gpio_get_value(GPIO_USB_SEL));/*For debuging*/ @@ -716,7 +716,7 @@ static ssize_t max77693_muic_set_uart_sel(struct device *dev, if (info->max77693->pmic_rev < MAX77693_REV_PASS2) { #if !defined(CONFIG_MACH_T0) && !defined(CONFIG_MACH_M3) \ - && !defined(CONFIG_MACH_SLP_T0_LTE) + && !defined(CONFIG_MACH_SLP_T0_LTE) && !defined(CONFIG_MACH_KONA) if (!strncasecmp(buf, "AP", 2)) { info->muic_data->uart_path = UART_PATH_AP; if (gpio_is_valid(GPIO_UART_SEL)) { @@ -845,7 +845,7 @@ static ssize_t max77693_muic_show_uart_sel(struct device *dev, struct max77693_muic_info *info = dev_get_drvdata(dev); if (info->max77693->pmic_rev < MAX77693_REV_PASS2) { #if !defined(CONFIG_MACH_T0) && !defined(CONFIG_MACH_M3) \ - && !defined(CONFIG_MACH_SLP_T0_LTE) + && !defined(CONFIG_MACH_SLP_T0_LTE) && !defined(CONFIG_MACH_KONA) switch (info->muic_data->uart_path) { case UART_PATH_AP: if (gpio_get_value(GPIO_UART_SEL) == GPIO_LEVEL_HIGH) @@ -3112,7 +3112,7 @@ static int uart_switch_init(struct max77693_muic_info *info) int ret, val; #if !defined(CONFIG_MACH_T0) && !defined(CONFIG_MACH_M3) \ - && !defined(CONFIG_MACH_SLP_T0_LTE) + && !defined(CONFIG_MACH_SLP_T0_LTE) && !defined(CONFIG_MACH_KONA) if (info->max77693->pmic_rev < MAX77693_REV_PASS2) { ret = gpio_request(GPIO_UART_SEL, "UART_SEL"); if (ret < 0) { diff --git a/drivers/net/wireless/bcmdhd/dhd_sec_feature.h b/drivers/net/wireless/bcmdhd/dhd_sec_feature.h index 933a78a..98a41a0 100755 --- a/drivers/net/wireless/bcmdhd/dhd_sec_feature.h +++ b/drivers/net/wireless/bcmdhd/dhd_sec_feature.h @@ -49,7 +49,8 @@ #define READ_MACADDR #endif /* CONFIG_ARCH_MSM7X30 */ -#if defined(CONFIG_MACH_GC1) || defined(CONFIG_MACH_U1_NA_SPR) || defined(CONFIG_MACH_V1) +#if defined(CONFIG_MACH_GC1) || defined(CONFIG_MACH_U1_NA_SPR) || defined(CONFIG_MACH_V1)\ + || defined(CONFIG_MACH_KONA) #undef USE_CID_CHECK #define READ_MACADDR #endif /* CONFIG_MACH_GC1 || CONFIG_MACH_U1_NA_SPR || CONFIG_MACH_V1 */ diff --git a/drivers/power/sec_battery_px.c b/drivers/power/sec_battery_px.c index 0a31772..f039c17 100644 --- a/drivers/power/sec_battery_px.c +++ b/drivers/power/sec_battery_px.c @@ -60,7 +60,7 @@ enum { #define P2_CHARGING_FEATURE_02 /* SMB136 + MAX17042, Cable detect by TA_nCon */ #endif -#if defined(CONFIG_MACH_P4NOTE) +#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA) #define P4_CHARGING_FEATURE_01 /* SMB347 + MAX17042, use TA_nCON */ #endif diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index f7888b9..36464eb 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -112,6 +112,17 @@ config SENSORS_AL3201 Say N here if you do not use AL3201. +config SENSORS_K2DH + tristate "K2DH acceleration sensor support" + depends on I2C + default n + help + Say Y here if you use K2DH. + This option enables accelerometer sensors using + STM K2DH in K2DH device driver. + + Say N here if you do not use K2DH. + config SENSORS_K3DH tristate "K3DH acceleration sensor support" depends on I2C @@ -119,6 +130,17 @@ config SENSORS_K3DH help Driver for STMicroelectronic K3DH accelerometer. +config SENSOR_K3DH_INPUTDEV + bool "K3DH acceleration sensor input dev support" + depends on SENSORS_K3DH + default n + help + Say Y here if you use K3DH. + This option enables accelerometer sensor using + K3DH device driver. + + Say N here if you do not use K3DH. + config SENSORS_K3G tristate "K3G driver for s5pc210" depends on I2C @@ -139,4 +161,36 @@ config SENSORS_LPS331 depends on I2C help Driver for STMicro LPS331 + +config SENSORS_YAS532 + depends on I2C + tristate "yas532 Sensor Support" + default n + help + Say Y to enable YAS532 Magnetic Sensor support. + This allows control of supported Magnetic Sensor. + +config SENSORS_YAS_ORI + depends on I2C + tristate "yas orientation Sensor Support" + default n + help + Say Y to enable YAS532 Magnetic Sensor support. + This allows control of supported Magnetic Sensor. + +config INPUT_YAS_MAGNETOMETER_POSITION + int "YAS Geomagnetic Sensor Mounting Position on Board" + depends on I2C + default "0" + help + Chip mounting position (pin 1). + 0: top, upper-left + 1: top, upper-right + 2: top, lower-right + 3: top, lower-left + 4: bottom, upper-left + 5: bottom, upper-right + 6: bottom, lower-right + 7: bottom, lower-left + endif diff --git a/drivers/sensor/Makefile b/drivers/sensor/Makefile index 44adf31..195f0f9 100644 --- a/drivers/sensor/Makefile +++ b/drivers/sensor/Makefile @@ -6,7 +6,11 @@ obj-$(CONFIG_SENSORS_CORE) += sensors_core.o # accelerometer_sensor +ifeq ($(CONFIG_MACH_KONA_SENSOR),y) +obj-$(CONFIG_SENSORS_K3DH) += k3dh_kona.o +else obj-$(CONFIG_SENSORS_K3DH) += k3dh.o +endif obj-$(CONFIG_SENSORS_BMA254) += bma254_driver.o # gyro_sensor obj-$(CONFIG_SENSORS_K3G) += k3g.o @@ -15,6 +19,8 @@ obj-$(CONFIG_SENSORS_LSM330DLC) += lsm330dlc_accel.o lsm330dlc_gyro.o # magnetic_sensor obj-$(CONFIG_SENSORS_AK8975C) += ak8975.o obj-$(CONFIG_SENSORS_AK8963C) += ak8963.o +obj-$(CONFIG_SENSORS_YAS532) += yas_mag_kernel_driver.o +obj-$(CONFIG_SENSORS_YAS_ORI) += yas_ori_kernel_driver.o # optical_sensor obj-$(CONFIG_SENSORS_CM3663) += cm3663.o obj-$(CONFIG_SENSORS_TAOS) += taos.o diff --git a/drivers/sensor/al3201.c b/drivers/sensor/al3201.c index a225b1a..df21515 100644 --- a/drivers/sensor/al3201.c +++ b/drivers/sensor/al3201.c @@ -304,10 +304,35 @@ static ssize_t get_chip_name(struct device *dev, { return sprintf(buf, "%s\n", CHIP_NAME); } +#if defined(CONFIG_MACH_KONA) +static ssize_t al3201_lux_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int result; + struct input_dev *input = to_input_dev(dev); + struct al3201_data *data = input_get_drvdata(input); + + /* No LUX data if not operational */ + if (data->state == OFF) { + al3201_set_power_state(data->client, ON); + msleep(180); + } + + result = al3201_get_adc_value(data->client); + + if (data->state == OFF) + al3201_set_power_state(data->client, OFF); + + return sprintf(buf, "%d\n", result); +} +#endif static DEVICE_ATTR(raw_data, 0644, al3201_raw_data_show, NULL); static DEVICE_ATTR(vendor, 0644, get_vendor_name, NULL); static DEVICE_ATTR(name, 0644, get_chip_name, NULL); +#if defined(CONFIG_MACH_KONA) +static DEVICE_ATTR(lux, 0644, al3201_lux_show, NULL); +#endif /* factory test*/ #ifdef LSC_DBG @@ -582,26 +607,38 @@ static int __devinit al3201_probe(struct i2c_client *client, dev_attr_name.attr.name); goto err_light_device_create_file3; } + +#if defined(CONFIG_MACH_KONA) + if (device_create_file(data->light_dev, &dev_attr_lux) < 0) { + pr_err("%s: could not create device file(%s)!\n", __func__, + dev_attr_lux.attr.name); + goto err_light_device_create_file4; + } +#endif dev_set_drvdata(data->light_dev, data); pr_info("%s: success!\n", __func__); goto done; - err_light_device_create_file3: +#if defined(CONFIG_MACH_KONA) +err_light_device_create_file4: + device_remove_file(data->light_dev, &dev_attr_lux); +#endif +err_light_device_create_file3: device_remove_file(data->light_dev, &dev_attr_vendor); err_light_device_create_file2: device_remove_file(data->light_dev, &dev_attr_raw_data); err_light_device_create_file1: sensors_classdev_unregister(data->light_dev); - err_light_device_create: +err_light_device_create: sysfs_remove_group(&data->input->dev.kobj, &al3201_attribute_group); - err_sysfs_create_group_light: +err_sysfs_create_group_light: input_unregister_device(data->input); - err_input_register_device_light: - err_input_allocate_device_light: +err_input_register_device_light: +err_input_allocate_device_light: destroy_workqueue(data->wq); - err_create_workqueue: - err_initializ_chip: +err_create_workqueue: +err_initializ_chip: mutex_destroy(&data->lock); kfree(data); done: diff --git a/drivers/sensor/k3dh_kona.c b/drivers/sensor/k3dh_kona.c new file mode 100644 index 0000000..04e1f8b --- /dev/null +++ b/drivers/sensor/k3dh_kona.c @@ -0,0 +1,1080 @@ +/* + * STMicroelectronics k3dh acceleration sensor driver + * + * Copyright (C) 2010 Samsung Electronics Co.Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "k3dh_reg.h" +#ifdef CONFIG_SENSOR_K3DH_INPUTDEV +#include +#endif + +/* For Debugging */ +#if 1 +#define k3dh_dbgmsg(str, args...) pr_debug("%s: " str, __func__, ##args) +#endif +#define k3dh_infomsg(str, args...) pr_info("%s: " str, __func__, ##args) + +#define VENDOR "STM" +#define CHIP_ID "K3DH" + +/* The default settings when sensor is on is for all 3 axis to be enabled + * and output data rate set to 400Hz. Output is via a ioctl read call. + */ +#define DEFAULT_POWER_ON_SETTING (ODR400 | ENABLE_ALL_AXES) +#define ACC_DEV_MAJOR 241 + +#define CALIBRATION_FILE_PATH "/efs/calibration_data" +#define CAL_DATA_AMOUNT 20 + +#ifdef CONFIG_SENSOR_K3DH_INPUTDEV +/* ABS axes parameter range [um/s^2] (for input event) */ +#define GRAVITY_EARTH 9806550 +#define ABSMAX_2G (GRAVITY_EARTH * 2) +#define ABSMIN_2G (-GRAVITY_EARTH * 2) +#define MIN_DELAY 5 +#define MAX_DELAY 200 +#endif + +static const struct odr_delay { + u8 odr; /* odr reg setting */ + s64 delay_ns; /* odr in ns */ +} odr_delay_table[] = { + { ODR1344, 744047LL }, /* 1344Hz */ + { ODR400, 2500000LL }, /* 400Hz */ + { ODR200, 5000000LL }, /* 200Hz */ + { ODR100, 10000000LL }, /* 100Hz */ + { ODR50, 20000000LL }, /* 50Hz */ + { ODR25, 40000000LL }, /* 25Hz */ + { ODR10, 100000000LL }, /* 10Hz */ + { ODR1, 1000000000LL }, /* 1Hz */ +}; + +/* K3DH acceleration data */ +struct k3dh_acc { + s16 x; + s16 y; + s16 z; +}; + +struct k3dh_data { + struct i2c_client *client; + struct miscdevice k3dh_device; + struct mutex read_lock; + struct mutex write_lock; + struct completion data_ready; +#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_TRATS) + struct class *acc_class; +#else + struct device *dev; +#endif + struct k3dh_acc cal_data; + struct k3dh_acc acc_xyz; + u8 ctrl_reg1_shadow; + atomic_t opened; /* opened implies enabled */ +#ifdef CONFIG_SENSOR_K3DH_INPUTDEV + struct input_dev *input; + struct delayed_work work; + atomic_t delay; + atomic_t enable; +#endif + bool axis_adjust; + int position; +}; + +static struct k3dh_data *g_k3dh; + + +static void k3dh_xyz_position_adjust(struct k3dh_acc *acc, + int position) +{ + const int position_map[][3][3] = { + {{ 0, 1, 0}, {-1, 0, 0}, { 0, 0, 1} }, /* 0 top/upper-left */ + {{-1, 0, 0}, { 0, -1, 0}, { 0, 0, 1} }, /* 1 top/upper-right */ + {{ 0, -1, 0}, { 1, 0, 0}, { 0, 0, 1} }, /* 2 top/lower-right */ + {{ 1, 0, 0}, { 0, 1, 0}, { 0, 0, 1} }, /* 3 top/lower-left */ + {{ 0, -1, 0}, {-1, 0, 0}, { 0, 0, -1} }, /* 4 bottom/upper-left */ + {{ 1, 0, 0}, { 0, -1, 0}, { 0, 0, -1} }, /* 5 bottom/upper-right */ + {{ 0, 1, 0}, { 1, 0, 0}, { 0, 0, -1} }, /* 6 bottom/lower-right */ + {{-1, 0, 0}, { 0, 1, 0}, { 0, 0, -1} }, /* 7 bottom/lower-left*/ + }; + + struct k3dh_acc xyz_adjusted = {0,}; + s16 raw[3] = {0,}; + int j; + raw[0] = acc->x; + raw[1] = acc->y; + raw[2] = acc->z; + for (j = 0; j < 3; j++) { + xyz_adjusted.x += + (position_map[position][0][j] * raw[j]); + xyz_adjusted.y += + (position_map[position][1][j] * raw[j]); + xyz_adjusted.z += + (position_map[position][2][j] * raw[j]); + } + acc->x = xyz_adjusted.x; + acc->y = xyz_adjusted.y; + acc->z = xyz_adjusted.z; +} + +/* Read X,Y and Z-axis acceleration raw data */ +static int k3dh_read_accel_raw_xyz(struct k3dh_data *data, + struct k3dh_acc *acc) +{ + int err; + s8 reg = OUT_X_L | AC; /* read from OUT_X_L to OUT_Z_H by auto-inc */ + u8 acc_data[6]; + + err = i2c_smbus_read_i2c_block_data(data->client, reg, + sizeof(acc_data), acc_data); + if (err != sizeof(acc_data)) { + pr_err("%s : failed to read 6 bytes for getting x/y/z\n", + __func__); + return -EIO; + } + + acc->x = (acc_data[1] << 8) | acc_data[0]; + acc->y = (acc_data[3] << 8) | acc_data[2]; + acc->z = (acc_data[5] << 8) | acc_data[4]; + + acc->x = acc->x >> 4; + acc->y = acc->y >> 4; + +#if defined(CONFIG_MACH_U1_NA_SPR_REV05) \ + || defined(CONFIG_MACH_U1_NA_SPR_EPIC2_REV00) \ + || defined(CONFIG_MACH_U1_NA_USCC_REV05) \ + || defined(CONFIG_MACH_Q1_BD) \ + || defined(CONFIG_MACH_U1_NA_USCC) \ + || defined(CONFIG_MACH_U1_NA_SPR) + acc->z = -acc->z >> 4; +#else + acc->z = acc->z >> 4; +#endif + + if (data->axis_adjust) + k3dh_xyz_position_adjust(acc, data->position); + return 0; +} + +static int k3dh_read_accel_xyz(struct k3dh_data *data, + struct k3dh_acc *acc) +{ + int err = 0; + + mutex_lock(&data->read_lock); + err = k3dh_read_accel_raw_xyz(data, acc); + mutex_unlock(&data->read_lock); + if (err < 0) { + pr_err("%s: k3dh_read_accel_raw_xyz() failed\n", __func__); + return err; + } + + acc->x -= data->cal_data.x; + acc->y -= data->cal_data.y; + acc->z -= data->cal_data.z; + + return err; +} + +static int k3dh_open_calibration(struct k3dh_data *data) +{ + struct file *cal_filp = NULL; + int err = 0; + mm_segment_t old_fs; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + cal_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY, 0666); + if (IS_ERR(cal_filp)) { + err = PTR_ERR(cal_filp); + if (err != -ENOENT) + pr_err("%s: Can't open calibration file\n", __func__); + set_fs(old_fs); + return err; + } + + err = cal_filp->f_op->read(cal_filp, + (char *)&data->cal_data, 3 * sizeof(s16), &cal_filp->f_pos); + if (err != 3 * sizeof(s16)) { + pr_err("%s: Can't read the cal data from file\n", __func__); + err = -EIO; + } + + k3dh_dbgmsg("%s: (%u,%u,%u)\n", __func__, + data->cal_data.x, data->cal_data.y, data->cal_data.z); + + filp_close(cal_filp, current->files); + set_fs(old_fs); + + return err; +} + +static int k3dh_do_calibrate(struct device *dev, bool do_calib) +{ + struct k3dh_data *acc_data = dev_get_drvdata(dev); + struct k3dh_acc data = { 0, }; + struct file *cal_filp = NULL; + int sum[3] = { 0, }; + int err = 0; + int i; + mm_segment_t old_fs; + + if (do_calib) { + for (i = 0; i < CAL_DATA_AMOUNT; i++) { + mutex_lock(&acc_data->read_lock); + err = k3dh_read_accel_raw_xyz(acc_data, &data); + mutex_unlock(&acc_data->read_lock); + if (err < 0) { + pr_err("%s: k3dh_read_accel_raw_xyz() " + "failed in the %dth loop\n", + __func__, i); + return err; + } + + sum[0] += data.x; + sum[1] += data.y; + sum[2] += data.z; + } + + acc_data->cal_data.x = sum[0] / CAL_DATA_AMOUNT; + acc_data->cal_data.y = sum[1] / CAL_DATA_AMOUNT; + if (sum[2] >= 0) + acc_data->cal_data.z = (sum[2] / CAL_DATA_AMOUNT)-1024; + else + acc_data->cal_data.z = (sum[2] / CAL_DATA_AMOUNT)+1024; + } else { + acc_data->cal_data.x = 0; + acc_data->cal_data.y = 0; + acc_data->cal_data.z = 0; + } + + printk(KERN_INFO "%s: cal data (%d,%d,%d)\n", __func__, + acc_data->cal_data.x, acc_data->cal_data.y, acc_data->cal_data.z); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + cal_filp = filp_open(CALIBRATION_FILE_PATH, + O_CREAT | O_TRUNC | O_WRONLY, 0666); + if (IS_ERR(cal_filp)) { + pr_err("%s: Can't open calibration file\n", __func__); + set_fs(old_fs); + err = PTR_ERR(cal_filp); + return err; + } + + err = cal_filp->f_op->write(cal_filp, + (char *)&acc_data->cal_data, 3 * sizeof(s16), &cal_filp->f_pos); + if (err != 3 * sizeof(s16)) { + pr_err("%s: Can't write the cal data to file\n", __func__); + err = -EIO; + } + + filp_close(cal_filp, current->files); + set_fs(old_fs); + + return err; +} + +static int k3dh_accel_enable(struct k3dh_data *data) +{ + int err = 0; + + if (atomic_read(&data->opened) == 0) { + err = k3dh_open_calibration(data); + if (err < 0 && err != -ENOENT) + pr_err("%s: k3dh_open_calibration() failed\n", + __func__); + data->ctrl_reg1_shadow = DEFAULT_POWER_ON_SETTING; + err = i2c_smbus_write_byte_data(data->client, CTRL_REG1, + DEFAULT_POWER_ON_SETTING); + if (err) + pr_err("%s: i2c write ctrl_reg1 failed\n", __func__); + +#if defined(CONFIG_SENSORS_K2DH) + err = i2c_smbus_write_byte_data(data->client, CTRL_REG4, + CTRL_REG4_HR | CTRL_REG4_BDU); +#else + err = i2c_smbus_write_byte_data(data->client, CTRL_REG4, + CTRL_REG4_HR); +#endif + if (err) + pr_err("%s: i2c write ctrl_reg4 failed\n", __func__); + } + + atomic_add(1, &data->opened); + + return err; +} + +static int k3dh_accel_disable(struct k3dh_data *data) +{ + int err = 0; + + atomic_sub(1, &data->opened); + if (atomic_read(&data->opened) == 0) { + err = i2c_smbus_write_byte_data(data->client, CTRL_REG1, + PM_OFF); + data->ctrl_reg1_shadow = PM_OFF; + } + + return err; +} + +/* open command for K3DH device file */ +static int k3dh_open(struct inode *inode, struct file *file) +{ + k3dh_infomsg("is called.\n"); + return 0; +} + +/* release command for K3DH device file */ +static int k3dh_close(struct inode *inode, struct file *file) +{ + k3dh_infomsg("is called.\n"); + return 0; +} + +static s64 k3dh_get_delay(struct k3dh_data *data) +{ + int i; + u8 odr; + s64 delay = -1; + + odr = data->ctrl_reg1_shadow & ODR_MASK; + for (i = 0; i < ARRAY_SIZE(odr_delay_table); i++) { + if (odr == odr_delay_table[i].odr) { + delay = odr_delay_table[i].delay_ns; + break; + } + } + return delay; +} + +static int k3dh_set_delay(struct k3dh_data *data, s64 delay_ns) +{ + int odr_value = ODR1; + int res = 0; + int i; + + /* round to the nearest delay that is less than + * the requested value (next highest freq) + */ + for (i = 0; i < ARRAY_SIZE(odr_delay_table); i++) { + if (delay_ns < odr_delay_table[i].delay_ns) + break; + } + if (i > 0) + i--; + odr_value = odr_delay_table[i].odr; + delay_ns = odr_delay_table[i].delay_ns; + + k3dh_infomsg("old=%lldns, new=%lldns, odr=0x%x/0x%x\n", + k3dh_get_delay(data), delay_ns, odr_value, + data->ctrl_reg1_shadow); + mutex_lock(&data->write_lock); + if (odr_value != (data->ctrl_reg1_shadow & ODR_MASK)) { + u8 ctrl = (data->ctrl_reg1_shadow & ~ODR_MASK); + ctrl |= odr_value; + data->ctrl_reg1_shadow = ctrl; + res = i2c_smbus_write_byte_data(data->client, CTRL_REG1, ctrl); + } + mutex_unlock(&data->write_lock); + return res; +} + +/* ioctl command for K3DH device file */ +static long k3dh_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + int err = 0; + struct k3dh_data *data = container_of(file->private_data, + struct k3dh_data, k3dh_device); + s64 delay_ns; + int enable = 0; + + /* cmd mapping */ + switch (cmd) { + case K3DH_IOCTL_SET_ENABLE: + if (copy_from_user(&enable, (void __user *)arg, + sizeof(enable))) + return -EFAULT; + k3dh_infomsg("opened = %d, enable = %d\n", + atomic_read(&data->opened), enable); + if (enable) + err = k3dh_accel_enable(data); + else + err = k3dh_accel_disable(data); + break; + case K3DH_IOCTL_SET_DELAY: + if (copy_from_user(&delay_ns, (void __user *)arg, + sizeof(delay_ns))) + return -EFAULT; + err = k3dh_set_delay(data, delay_ns); + break; + case K3DH_IOCTL_GET_DELAY: + delay_ns = k3dh_get_delay(data); + if (put_user(delay_ns, (s64 __user *)arg)) + return -EFAULT; + break; + case K3DH_IOCTL_READ_ACCEL_XYZ: + err = k3dh_read_accel_xyz(data, &data->acc_xyz); + if (err) + break; + if (copy_to_user((void __user *)arg, + &data->acc_xyz, sizeof(data->acc_xyz))) + return -EFAULT; + break; + default: + err = -EINVAL; + break; + } + + return err; +} + +static int k3dh_suspend(struct device *dev) +{ + int res = 0; + struct k3dh_data *data = dev_get_drvdata(dev); +#ifdef CONFIG_SENSOR_K3DH_INPUTDEV + if (atomic_read(&data->enable)) + cancel_delayed_work_sync(&data->work); +#endif + if (atomic_read(&data->opened) > 0) + res = i2c_smbus_write_byte_data(data->client, + CTRL_REG1, PM_OFF); + + return res; +} + +static int k3dh_resume(struct device *dev) +{ + int res = 0; + struct k3dh_data *data = dev_get_drvdata(dev); + + if (atomic_read(&data->opened) > 0) + res = i2c_smbus_write_byte_data(data->client, CTRL_REG1, + data->ctrl_reg1_shadow); +#ifdef CONFIG_SENSOR_K3DH_INPUTDEV + if (atomic_read(&data->enable)) + schedule_delayed_work(&data->work, + msecs_to_jiffies(5)); +#endif + return res; +} + +static const struct dev_pm_ops k3dh_pm_ops = { + .suspend = k3dh_suspend, + .resume = k3dh_resume, +}; + +static const struct file_operations k3dh_fops = { + .owner = THIS_MODULE, + .open = k3dh_open, + .release = k3dh_close, + .unlocked_ioctl = k3dh_ioctl, +}; + +#ifdef CONFIG_SENSOR_K3DH_INPUTDEV +static ssize_t k3dh_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input = to_input_dev(dev); + struct k3dh_data *data = input_get_drvdata(input); + + return sprintf(buf, "%d\n", atomic_read(&data->enable)); +} + +static ssize_t k3dh_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input = to_input_dev(dev); + struct k3dh_data *data = input_get_drvdata(input); + unsigned long enable = 0; + int err; + + if (strict_strtoul(buf, 10, &enable)) + return -EINVAL; + k3dh_open_calibration(data); + + if (enable) { + err = k3dh_accel_enable(data); + if (err < 0) + goto done; + schedule_delayed_work(&data->work, + msecs_to_jiffies(5)); + } else { + cancel_delayed_work_sync(&data->work); + err = k3dh_accel_disable(data); + if (err < 0) + goto done; + } + atomic_set(&data->enable, enable); + pr_info("%s, enable = %ld\n", __func__, enable); +done: + return count; +} +static DEVICE_ATTR(enable, + S_IRUGO | S_IWUSR | S_IWGRP, + k3dh_enable_show, k3dh_enable_store); + +static ssize_t k3dh_delay_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input = to_input_dev(dev); + struct k3dh_data *data = input_get_drvdata(input); + + return sprintf(buf, "%d\n", atomic_read(&data->delay)); +} + +static ssize_t k3dh_delay_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input = to_input_dev(dev); + struct k3dh_data *data = input_get_drvdata(input); + unsigned long delay = 0; + if (strict_strtoul(buf, 10, &delay)) + return -EINVAL; + + if (delay > MAX_DELAY) + delay = MAX_DELAY; + if (delay < MIN_DELAY) + delay = MIN_DELAY; + atomic_set(&data->delay, delay); + k3dh_set_delay(data, delay * 1000000); + pr_info("%s, delay = %ld\n", __func__, delay); + return count; +} +static DEVICE_ATTR(poll_delay, + S_IRUGO | S_IWUSR | S_IWGRP, + k3dh_delay_show, k3dh_delay_store); + +static struct attribute *k3dh_attributes[] = { + &dev_attr_enable.attr, + &dev_attr_poll_delay.attr, + NULL +}; + +static struct attribute_group k3dh_attribute_group = { + .attrs = k3dh_attributes +}; +#endif + +static ssize_t k3dh_fs_read(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct k3dh_data *data = dev_get_drvdata(dev); + +#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_TRATS) + int err = 0; + int on; + + mutex_lock(&data->write_lock); + on = atomic_read(&data->opened); + if (on == 0) { + err = i2c_smbus_write_byte_data(data->client, CTRL_REG1, + DEFAULT_POWER_ON_SETTING); + } + mutex_unlock(&data->write_lock); + + if (err < 0) { + pr_err("%s: i2c write ctrl_reg1 failed\n", __func__); + return err; + } + + err = k3dh_read_accel_xyz(data, &data->acc_xyz); + if (err < 0) { + pr_err("%s: k3dh_read_accel_xyz failed\n", __func__); + return err; + } + + if (on == 0) { + mutex_lock(&data->write_lock); + err = i2c_smbus_write_byte_data(data->client, CTRL_REG1, + PM_OFF); + mutex_unlock(&data->write_lock); + if (err) + pr_err("%s: i2c write ctrl_reg1 failed\n", __func__); + } +#endif + return sprintf(buf, "%d,%d,%d\n", + data->acc_xyz.x, data->acc_xyz.y, data->acc_xyz.z); +} + +static ssize_t k3dh_calibration_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int err; + struct k3dh_data *data = dev_get_drvdata(dev); + + err = k3dh_open_calibration(data); + if (err < 0) + pr_err("%s: k3dh_open_calibration() failed\n", __func__); + + if (!data->cal_data.x && !data->cal_data.y && !data->cal_data.z) + err = -1; + + return sprintf(buf, "%d %d %d %d\n", + err, data->cal_data.x, data->cal_data.y, data->cal_data.z); +} + +static ssize_t k3dh_calibration_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct k3dh_data *data = dev_get_drvdata(dev); + bool do_calib; + int err; + + if (sysfs_streq(buf, "1")) + do_calib = true; + else if (sysfs_streq(buf, "0")) + do_calib = false; + else { + pr_debug("%s: invalid value %d\n", __func__, *buf); + return -EINVAL; + } + + if (atomic_read(&data->opened) == 0) { + /* if off, turn on the device.*/ + err = i2c_smbus_write_byte_data(data->client, CTRL_REG1, + DEFAULT_POWER_ON_SETTING); + if (err) { + pr_err("%s: i2c write ctrl_reg1 failed(err=%d)\n", + __func__, err); + } + } + + err = k3dh_do_calibrate(dev, do_calib); + if (err < 0) { + pr_err("%s: k3dh_do_calibrate() failed\n", __func__); + return err; + } + + if (atomic_read(&data->opened) == 0) { + /* if off, turn on the device.*/ + err = i2c_smbus_write_byte_data(data->client, CTRL_REG1, + PM_OFF); + if (err) { + pr_err("%s: i2c write ctrl_reg1 failed(err=%d)\n", + __func__, err); + } + } + + return count; +} + +#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_TRATS) +static DEVICE_ATTR(acc_file, 0664, k3dh_fs_read, NULL); +#else +static ssize_t +k3dh_accel_position_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct k3dh_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", data->position); +} + +static ssize_t +k3dh_accel_position_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct k3dh_data *data = dev_get_drvdata(dev); + int err = 0; + + err = kstrtoint(buf, 10, &data->position); + if (err < 0) + pr_err("%s, kstrtoint failed.", __func__); + + return count; +} + +static ssize_t k3dh_accel_vendor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%s\n", VENDOR); +} + +static ssize_t k3dh_accel_name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%s\n", CHIP_ID); +} + +static DEVICE_ATTR(name, 0664, k3dh_accel_name_show, NULL); +static DEVICE_ATTR(vendor, 0664, k3dh_accel_vendor_show, NULL); +static DEVICE_ATTR(raw_data, 0664, k3dh_fs_read, NULL); +static DEVICE_ATTR(position, 0664, + k3dh_accel_position_show, k3dh_accel_position_store); +#endif +static DEVICE_ATTR(calibration, 0664, + k3dh_calibration_show, k3dh_calibration_store); + +void k3dh_shutdown(struct i2c_client *client) +{ + int res = 0; + struct k3dh_data *data = i2c_get_clientdata(client); + + k3dh_infomsg("is called.\n"); + +#ifdef CONFIG_SENSOR_K3DH_INPUTDEV + if (atomic_read(&data->enable)) + cancel_delayed_work_sync(&data->work); +#endif + res = i2c_smbus_write_byte_data(data->client, + CTRL_REG1, PM_OFF); + if (res < 0) + pr_err("%s: pm_off failed %d\n", __func__, res); +} + +#ifdef CONFIG_SENSOR_K3DH_INPUTDEV +static void k3dh_work_func(struct work_struct *work) +{ + k3dh_read_accel_xyz(g_k3dh, &g_k3dh->acc_xyz); + pr_debug("%s: x: %d, y: %d, z: %d\n", __func__, + g_k3dh->acc_xyz.x, g_k3dh->acc_xyz.y, g_k3dh->acc_xyz.z); + input_report_abs(g_k3dh->input, ABS_X, g_k3dh->acc_xyz.x); + input_report_abs(g_k3dh->input, ABS_Y, g_k3dh->acc_xyz.y); + input_report_abs(g_k3dh->input, ABS_Z, g_k3dh->acc_xyz.z); + input_sync(g_k3dh->input); + schedule_delayed_work(&g_k3dh->work, msecs_to_jiffies( + atomic_read(&g_k3dh->delay))); +} + +/* ----------------- * + Input device interface + * ------------------ */ +static int k3dh_input_init(struct k3dh_data *data) +{ + struct input_dev *dev; + int err = 0; + + dev = input_allocate_device(); + if (!dev) + return -ENOMEM; + dev->name = "accelerometer"; + dev->id.bustype = BUS_I2C; + + input_set_capability(dev, EV_ABS, ABS_MISC); + input_set_abs_params(dev, ABS_X, ABSMIN_2G, ABSMAX_2G, 0, 0); + input_set_abs_params(dev, ABS_Y, ABSMIN_2G, ABSMAX_2G, 0, 0); + input_set_abs_params(dev, ABS_Z, ABSMIN_2G, ABSMAX_2G, 0, 0); + input_set_drvdata(dev, data); + + err = input_register_device(dev); + if (err < 0) + goto done; + data->input = dev; +done: + return 0; +} +#endif +static int k3dh_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct k3dh_data *data; +#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_TRATS) + struct device *dev_t, *dev_cal; +#endif + struct accel_platform_data *pdata; + int err; + + k3dh_infomsg("is started.\n"); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA | + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + pr_err("%s: i2c functionality check failed!\n", __func__); + err = -ENODEV; + goto exit; + } + + data = kzalloc(sizeof(struct k3dh_data), GFP_KERNEL); + if (data == NULL) { + dev_err(&client->dev, + "failed to allocate memory for module data\n"); + err = -ENOMEM; + goto exit; + } + + /* Checking device */ + err = i2c_smbus_write_byte_data(client, CTRL_REG1, + PM_OFF); + if (err) { + pr_err("%s: there is no such device, err = %d\n", + __func__, err); + goto err_read_reg; + } + + data->client = client; + g_k3dh = data; + i2c_set_clientdata(client, data); + + init_completion(&data->data_ready); + mutex_init(&data->read_lock); + mutex_init(&data->write_lock); + atomic_set(&data->opened, 0); + + /* sensor HAL expects to find /dev/accelerometer */ + data->k3dh_device.minor = MISC_DYNAMIC_MINOR; + data->k3dh_device.name = ACC_DEV_NAME; + data->k3dh_device.fops = &k3dh_fops; + + err = misc_register(&data->k3dh_device); + if (err) { + pr_err("%s: misc_register failed\n", __FILE__); + goto err_misc_register; + } + + pdata = client->dev.platform_data; + if (!pdata) { + /*Set by default position 3, it doesn't adjust raw value*/ + data->position = 3; + data->axis_adjust = false; + pr_err("using defualt position = %d\n", data->position); + } else { + if (pdata->accel_get_position) + data->position = pdata->accel_get_position(); + data->axis_adjust = pdata->axis_adjust; + pr_info("successful, position = %d\n", data->position); + } +#ifdef CONFIG_SENSOR_K3DH_INPUTDEV + atomic_set(&data->enable, 0); + atomic_set(&data->delay, 200); + k3dh_input_init(data); + + /* Setup sysfs */ + err = + sysfs_create_group(&data->input->dev.kobj, + &k3dh_attribute_group); + if (err < 0) + goto err_sysfs_create_group; + + /* Setup driver interface */ + INIT_DELAYED_WORK(&data->work, k3dh_work_func); +#endif +#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_TRATS) + /* creating class/device for test */ + data->acc_class = class_create(THIS_MODULE, "accelerometer"); + if (IS_ERR(data->acc_class)) { + pr_err("%s: class create failed(accelerometer)\n", __func__); + err = PTR_ERR(data->acc_class); + goto err_class_create; + } + + dev_t = device_create(data->acc_class, NULL, + MKDEV(ACC_DEV_MAJOR, 0), "%s", "accelerometer"); + if (IS_ERR(dev_t)) { + pr_err("%s: class create failed(accelerometer)\n", __func__); + err = PTR_ERR(dev_t); + goto err_acc_device_create; + } + + err = device_create_file(dev_t, &dev_attr_acc_file); + if (err < 0) { + pr_err("%s: Failed to create device file(%s)\n", + __func__, dev_attr_acc_file.attr.name); + goto err_acc_device_create_file; + } + dev_set_drvdata(dev_t, data); + + /* creating device for calibration */ + dev_cal = device_create(sec_class, NULL, 0, NULL, "gsensorcal"); + if (IS_ERR(dev_cal)) { + pr_err("%s: class create failed(gsensorcal)\n", __func__); + err = PTR_ERR(dev_cal); + goto err_cal_device_create; + } + + err = device_create_file(dev_cal, &dev_attr_calibration); + if (err < 0) { + pr_err("%s: Failed to create device file(%s)\n", + __func__, dev_attr_calibration.attr.name); + goto err_cal_device_create_file; + } + dev_set_drvdata(dev_cal, data); +#else + /* creating device for test & calibration */ + data->dev = sensors_classdev_register("accelerometer_sensor"); + if (IS_ERR(data->dev)) { + pr_err("%s: class create failed(accelerometer_sensor)\n", + __func__); + err = PTR_ERR(data->dev); + goto err_acc_device_create; + } + + err = device_create_file(data->dev, &dev_attr_position); + if (err < 0) { + pr_err("%s: Failed to create device file(%s)\n", + __func__, dev_attr_position.attr.name); + goto err_position_device_create_file; + } + + err = device_create_file(data->dev, &dev_attr_raw_data); + if (err < 0) { + pr_err("%s: Failed to create device file(%s)\n", + __func__, dev_attr_raw_data.attr.name); + goto err_acc_device_create_file; + } + + err = device_create_file(data->dev, &dev_attr_calibration); + if (err < 0) { + pr_err("%s: Failed to create device file(%s)\n", + __func__, dev_attr_calibration.attr.name); + goto err_cal_device_create_file; + } + + err = device_create_file(data->dev, &dev_attr_vendor); + if (err < 0) { + pr_err("%s: Failed to create device file(%s)\n", + __func__, dev_attr_vendor.attr.name); + goto err_vendor_device_create_file; + } + + err = device_create_file(data->dev, &dev_attr_name); + if (err < 0) { + pr_err("%s: Failed to create device file(%s)\n", + __func__, dev_attr_name.attr.name); + goto err_name_device_create_file; + } + + dev_set_drvdata(data->dev, data); +#endif + + k3dh_infomsg("is successful.\n"); + + return 0; + +#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_TRATS) +err_cal_device_create_file: + device_destroy(sec_class, 0); +err_cal_device_create: + device_remove_file(dev_t, &dev_attr_acc_file); +err_acc_device_create_file: + device_destroy(data->acc_class, MKDEV(ACC_DEV_MAJOR, 0)); +err_acc_device_create: + class_destroy(data->acc_class); +err_class_create: +#else +err_name_device_create_file: + device_remove_file(data->dev, &dev_attr_vendor); +err_vendor_device_create_file: + device_remove_file(data->dev, &dev_attr_calibration); +err_cal_device_create_file: + device_remove_file(data->dev, &dev_attr_raw_data); +err_acc_device_create_file: + device_remove_file(data->dev, &dev_attr_position); +err_position_device_create_file: + sensors_classdev_unregister(data->dev); + +err_acc_device_create: +#endif +#ifdef CONFIG_SENSOR_K3DH_INPUTDEV + input_free_device(data->input); +err_sysfs_create_group: +#endif +misc_deregister(&data->k3dh_device); +err_misc_register: + mutex_destroy(&data->read_lock); + mutex_destroy(&data->write_lock); +err_read_reg: + kfree(data); +exit: + return err; +} + +static int k3dh_remove(struct i2c_client *client) +{ + struct k3dh_data *data = i2c_get_clientdata(client); + int err = 0; + + if (atomic_read(&data->opened) > 0) { + err = i2c_smbus_write_byte_data(data->client, + CTRL_REG1, PM_OFF); + if (err < 0) + pr_err("%s: pm_off failed %d\n", __func__, err); + } + +#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_TRATS) + device_destroy(sec_class, 0); + device_destroy(data->acc_class, MKDEV(ACC_DEV_MAJOR, 0)); + class_destroy(data->acc_class); +#else + device_remove_file(data->dev, &dev_attr_name); + device_remove_file(data->dev, &dev_attr_vendor); + device_remove_file(data->dev, &dev_attr_calibration); + device_remove_file(data->dev, &dev_attr_raw_data); + device_remove_file(data->dev, &dev_attr_position); + sensors_classdev_unregister(data->dev); +#endif + misc_deregister(&data->k3dh_device); + mutex_destroy(&data->read_lock); + mutex_destroy(&data->write_lock); + kfree(data); + + return 0; +} + +static const struct i2c_device_id k3dh_id[] = { + { "k3dh", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, k3dh_id); + +static struct i2c_driver k3dh_driver = { + .probe = k3dh_probe, + .shutdown = k3dh_shutdown, + .remove = __devexit_p(k3dh_remove), + .id_table = k3dh_id, + .driver = { + .pm = &k3dh_pm_ops, + .owner = THIS_MODULE, + .name = "k3dh", + }, +}; + +static int __init k3dh_init(void) +{ + return i2c_add_driver(&k3dh_driver); +} + +static void __exit k3dh_exit(void) +{ + i2c_del_driver(&k3dh_driver); +} + +module_init(k3dh_init); +module_exit(k3dh_exit); + +MODULE_DESCRIPTION("k3dh accelerometer driver"); +MODULE_AUTHOR("Samsung Electronics"); +MODULE_LICENSE("GPL"); diff --git a/drivers/sensor/k3dh_reg.h b/drivers/sensor/k3dh_reg.h index 846d0d7..e6c9fa4 100644 --- a/drivers/sensor/k3dh_reg.h +++ b/drivers/sensor/k3dh_reg.h @@ -102,6 +102,7 @@ #define I1_OVERRUN (1 << 1) /* CTRL_REG4 */ +#define CTRL_REG4_BDU (1 << 7) #define CTRL_REG4_BLE (1 << 6) #define CTRL_REG4_FS1 (1 << 5) #define CTRL_REG4_FS0 (1 << 4) diff --git a/drivers/sensor/yas_mag_driver-yas532.c b/drivers/sensor/yas_mag_driver-yas532.c new file mode 100644 index 0000000..14259b8 --- /dev/null +++ b/drivers/sensor/yas_mag_driver-yas532.c @@ -0,0 +1,2909 @@ +/* + * Copyright (c) 2010-2011 Yamaha Corporation + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#include + +struct utimeval { + int32_t tv_sec; + int32_t tv_msec; +}; + +struct utimer { + struct utimeval prev_time; + struct utimeval total_time; + struct utimeval delay_ms; +}; + +static int utimeval_init(struct utimeval *val); +static int utimeval_is_initial(struct utimeval *val); +static int utimeval_is_overflow(struct utimeval *val); +static struct utimeval utimeval_plus(struct utimeval *first, + struct utimeval *second); +static struct utimeval utimeval_minus(struct utimeval *first, + struct utimeval *second); +static int utimeval_greater_than(struct utimeval *first, + struct utimeval *second); +static int utimeval_greater_or_equal(struct utimeval *first, + struct utimeval *second); +static int utimeval_greater_than_zero(struct utimeval *val); +static int utimeval_less_than_zero(struct utimeval *val); +static struct utimeval *msec_to_utimeval(struct utimeval *result, + uint32_t msec); +static uint32_t utimeval_to_msec(struct utimeval *val); + +static struct utimeval utimer_calc_next_time(struct utimer *ut, + struct utimeval *cur); +static struct utimeval utimer_current_time(void); +static int utimer_is_timeout(struct utimer *ut); +static int utimer_clear_timeout(struct utimer *ut); +static uint32_t utimer_get_total_time(struct utimer *ut); +static uint32_t utimer_get_delay(struct utimer *ut); +static int utimer_set_delay(struct utimer *ut, uint32_t delay_ms); +static int utimer_update(struct utimer *ut); +static int utimer_update_with_curtime(struct utimer *ut, struct utimeval *cur); +static uint32_t utimer_sleep_time(struct utimer *ut); +static uint32_t utimer_sleep_time_with_curtime(struct utimer *ut, + struct utimeval *cur); +static int utimer_init(struct utimer *ut, uint32_t delay_ms); +static int utimer_clear(struct utimer *ut); +static void utimer_lib_init(void (*func) (int *sec, int *msec)); + +#define YAS_REGADDR_DEVICE_ID (0x80) +#define YAS_REGADDR_ACTUATE_INIT_COIL (0x81) +#define YAS_REGADDR_MEASURE_COMMAND (0x82) +#define YAS_REGADDR_CONFIG (0x83) +#define YAS_REGADDR_MEASURE_INTERVAL (0x84) +#define YAS_REGADDR_OFFSET_X (0x85) +#define YAS_REGADDR_OFFSET_Y1 (0x86) +#define YAS_REGADDR_OFFSET_Y2 (0x87) +#define YAS_REGADDR_TEST1 (0x88) +#define YAS_REGADDR_TEST2 (0x89) +#define YAS_REGADDR_CAL (0x90) +#define YAS_REGADDR_MEASURE_DATA (0xb0) +#define YAS_YAS530_DEVICE_ID (0x01) /* YAS530 (MS-3E) */ +#define YAS_YAS530_VERSION_A (0) /* YAS530 (MS-3E Aver) */ +#define YAS_YAS530_VERSION_B (1) /* YAS530B (MS-3E Bver) */ +#define YAS_YAS530_VERSION_A_COEF (380) +#define YAS_YAS530_VERSION_B_COEF (550) +#define YAS_YAS530_DATA_CENTER (2048) +#define YAS_YAS530_DATA_OVERFLOW (4095) + +#define YAS_YAS532_DEVICE_ID (0x02) /* YAS532 (MS-3R) */ +#define YAS_YAS532_VERSION_AB (0) /* YAS532AB (MS-3R ABver) */ +#define YAS_YAS532_VERSION_AC (1) /* YAS532AC (MS-3R ACver) */ +#define YAS_YAS532_VERSION_AB_COEF (1800) +#define YAS_YAS532_VERSION_AC_COEF (900) +#define YAS_YAS532_DATA_CENTER (4096) +#define YAS_YAS532_DATA_OVERFLOW (8190) + +#undef YAS_YAS530_CAL_SINGLE_READ + +struct yas_machdep_func { + int (*device_open) (void); + int (*device_close) (void); + int (*device_write) (uint8_t addr, const uint8_t *buf, int len); + int (*device_read) (uint8_t addr, uint8_t *buf, int len); + void (*msleep) (int msec); +}; + +static int yas_cdrv_actuate_initcoil(void); +static int yas_cdrv_set_offset(const int8_t *offset); +static int yas_cdrv_recalc_calib_offset(int32_t *prev_calib_offset, + int32_t *new_calib_offset, + int8_t *prev_offset, + int8_t *new_offset); +static int yas_cdrv_set_transformatiom_matrix(const int8_t *transform); +static int yas_cdrv_measure_and_set_offset(int8_t *offset); +static int yas_cdrv_measure(int32_t *msens, int32_t *raw, int16_t *t); +static int yas_cdrv_init(const int8_t *transform, + struct yas_machdep_func *func); +static int yas_cdrv_term(void); + +static void (*current_time) (int *sec, int *msec) = { +0}; + +static int utimeval_init(struct utimeval *val) +{ + if (unlikely(!val)) + return -1; + val->tv_sec = val->tv_msec = 0; + return 0; +} + +static int utimeval_is_initial(struct utimeval *val) +{ + if (unlikely(!val)) + return 0; + return val->tv_sec == 0 && val->tv_msec == 0; +} + +static int utimeval_is_overflow(struct utimeval *val) +{ + int32_t max; + + if (unlikely(!val)) + return 0; + + max = (int32_t) (0xffffffff / 1000); + if (val->tv_sec > max) { + return 1; /* overflow */ + } else if (val->tv_sec == max) { + if (val->tv_msec > + (int32_t) (0xffffffff % 1000)) { + return 1; /* overflow */ + } + } + + return 0; +} + +static struct utimeval +utimeval_plus(struct utimeval *first, struct utimeval *second) +{ + struct utimeval result = { 0, 0 }; + int32_t tmp; + + if (unlikely(!first || !second)) + return result; + + tmp = first->tv_sec + second->tv_sec; + if (first->tv_sec >= 0 && second->tv_sec >= 0 && tmp < 0) + goto overflow; + if (first->tv_sec < 0 && second->tv_sec < 0 && tmp >= 0) + goto underflow; + + result.tv_sec = tmp; + result.tv_msec = first->tv_msec + second->tv_msec; + if (1000 <= result.tv_msec) { + tmp = result.tv_sec + result.tv_msec / 1000; + if (result.tv_sec >= 0 && result.tv_msec >= 0 && tmp < 0) + goto overflow; + result.tv_sec = tmp; + result.tv_msec = result.tv_msec % 1000; + } + if (result.tv_msec < 0) { + tmp = result.tv_sec + result.tv_msec / 1000 - 1; + if (result.tv_sec < 0 && result.tv_msec < 0 && tmp >= 0) + goto underflow; + result.tv_sec = tmp; + result.tv_msec = result.tv_msec % 1000 + 1000; + } + + return result; + +overflow: + result.tv_sec = 0x7fffffff; + result.tv_msec = 999; + return result; + +underflow: + result.tv_sec = 0x80000000; + result.tv_msec = 0; + return result; +} + +static struct utimeval +utimeval_minus(struct utimeval *first, struct utimeval *second) +{ + struct utimeval result = { 0, 0 }, tmp; + + if (first == NULL || second == NULL + || second->tv_sec == (int)0x80000000) + return result; + + tmp.tv_sec = -second->tv_sec; + tmp.tv_msec = -second->tv_msec; + return utimeval_plus(first, &tmp); +} + +static int utimeval_less_than(struct utimeval *first, struct utimeval *second) +{ + if (unlikely(!first || !second)) + return 0; + + if (first->tv_sec > second->tv_sec) + return 1; + else if (first->tv_sec < second->tv_sec) + return 0; + else + if (first->tv_msec > second->tv_msec) + return 1; + else + return 0; +} + +static int +utimeval_greater_than(struct utimeval *first, struct utimeval *second) +{ + if (unlikely(!first || !second)) + return 0; + + if (first->tv_sec < second->tv_sec) + return 1; + else if (first->tv_sec > second->tv_sec) + return 0; + else + if (first->tv_msec < second->tv_msec) + return 1; + else + return 0; +} + +static int +utimeval_greater_or_equal(struct utimeval *first, struct utimeval *second) +{ + return !utimeval_less_than(first, second); +} + +static int utimeval_greater_than_zero(struct utimeval *val) +{ + struct utimeval zero = { 0, 0 }; + return utimeval_greater_than(&zero, val); +} + +static int utimeval_less_than_zero(struct utimeval *val) +{ + struct utimeval zero = { 0, 0 }; + return utimeval_less_than(&zero, val); +} + +static struct utimeval *msec_to_utimeval(struct utimeval *result, uint32_t msec) +{ + if (unlikely(!result)) + return result; + result->tv_sec = msec / 1000; + result->tv_msec = msec % 1000; + + return result; +} + +static uint32_t utimeval_to_msec(struct utimeval *val) +{ + if (unlikely(!val)) + return 0; + if (utimeval_less_than_zero(val)) + return 0; + + if (utimeval_is_overflow(val)) + return 0xffffffff; + + return val->tv_sec * 1000 + val->tv_msec; +} + +static struct utimeval +utimer_calc_next_time(struct utimer *ut, struct utimeval *cur) +{ + struct utimeval result = { 0, 0 }, delay; + + if (ut == NULL || cur == NULL) + return result; + utimer_update_with_curtime(ut, cur); + if (utimer_is_timeout(ut)) { + result = *cur; + } else { + delay = utimeval_minus(&ut->delay_ms, &ut->total_time); + result = utimeval_plus(cur, &delay); + } + + return result; +} + +static struct utimeval utimer_current_time(void) +{ + struct utimeval tv; + int sec, msec; + + if (current_time != NULL) + current_time(&sec, &msec); + else + sec = 0, msec = 0; + tv.tv_sec = sec; + tv.tv_msec = msec; + + return tv; +} + +static int utimer_clear(struct utimer *ut) +{ + if (unlikely(!ut)) + return -1; + utimeval_init(&ut->prev_time); + utimeval_init(&ut->total_time); + + return 0; +} + +static int utimer_update_with_curtime(struct utimer *ut, struct utimeval *cur) +{ + struct utimeval tmp; + + if (unlikely(!ut || !cur)) + return -1; + if (utimeval_is_initial(&ut->prev_time)) + ut->prev_time = *cur; + if (utimeval_greater_than_zero(&ut->delay_ms)) { + tmp = utimeval_minus(cur, &ut->prev_time); + if (utimeval_less_than_zero(&tmp)) + utimeval_init(&ut->total_time); + else { + ut->total_time = utimeval_plus(&tmp, &ut->total_time); + if (utimeval_is_overflow(&ut->total_time)) + utimeval_init(&ut->total_time); + } + ut->prev_time = *cur; + } + + return 0; +} + +static int utimer_update(struct utimer *ut) +{ + struct utimeval cur; + + if (unlikely(!ut)) + return -1; + + cur = utimer_current_time(); + utimer_update_with_curtime(ut, &cur); + return 0; +} + +static int utimer_is_timeout(struct utimer *ut) +{ + if (unlikely(!ut)) + return 0; + + if (utimeval_greater_than_zero(&ut->delay_ms)) + return utimeval_greater_or_equal(&ut->delay_ms, + &ut->total_time); + else + return 1; +} + +static int utimer_clear_timeout(struct utimer *ut) +{ + uint32_t delay, total; + + if (unlikely(!ut)) + return -1; + + delay = utimeval_to_msec(&ut->delay_ms); + if (delay == 0 || utimeval_is_overflow(&ut->total_time)) + total = 0; + else + if (utimeval_is_overflow(&ut->total_time)) + total = 0; + else { + total = utimeval_to_msec(&ut->total_time); + total = total % delay; + } + msec_to_utimeval(&ut->total_time, total); + + return 0; +} + +static uint32_t +utimer_sleep_time_with_curtime(struct utimer *ut, struct utimeval *cur) +{ + struct utimeval tv; + + if (unlikely(!ut || !cur)) + return 0; + + tv = utimer_calc_next_time(ut, cur); + tv = utimeval_minus(&tv, cur); + if (utimeval_less_than_zero(&tv)) + return 0; + + return utimeval_to_msec(&tv); +} + +static uint32_t utimer_sleep_time(struct utimer *ut) +{ + struct utimeval cur; + + if (unlikely(!ut)) + return 0; + + cur = utimer_current_time(); + return utimer_sleep_time_with_curtime(ut, &cur); +} + +static int utimer_init(struct utimer *ut, uint32_t delay_ms) +{ + if (unlikely(!ut)) + return -1; + utimer_clear(ut); + msec_to_utimeval(&ut->delay_ms, delay_ms); + + return 0; +} + +static uint32_t utimer_get_total_time(struct utimer *ut) +{ + return utimeval_to_msec(&ut->total_time); +} + +static uint32_t utimer_get_delay(struct utimer *ut) +{ + if (unlikely(!ut)) + return -1; + return utimeval_to_msec(&ut->delay_ms); +} + +static int utimer_set_delay(struct utimer *ut, uint32_t delay_ms) +{ + return utimer_init(ut, delay_ms); +} + +static void utimer_lib_init(void (*func) (int *sec, int *msec)) +{ + current_time = func; +} + +struct yas_cal_data { + uint8_t dx, dy1, dy2; + uint8_t d2, d3, d4, d5, d6, d7, d8, d9, d0; + uint8_t dck; + uint8_t ver; +}; +struct yas_correction_data { + int32_t Cx, Cy1, Cy2; + int32_t a2, a3, a4, a5, a6, a7, a8, a9, k; +}; +struct yas_cdriver { + struct yas_cal_data cal; + struct yas_correction_data correct; + struct yas_machdep_func func; + int8_t transform[9]; + int16_t temperature; + uint8_t dev_id; + int32_t coef; + int16_t center; + int16_t overflow; +}; +static struct yas_cdriver cdriver; + +static int device_open(void) +{ + if (cdriver.func.device_open == NULL) + return -1; + return cdriver.func.device_open(); +} + +static int device_close(void) +{ + if (cdriver.func.device_close == NULL) + return -1; + return cdriver.func.device_close(); +} + +static int device_write(uint8_t addr, const uint8_t *buf, int len) +{ + if (cdriver.func.device_write == NULL) + return -1; + return cdriver.func.device_write(addr, buf, len); +} + +static int device_read(uint8_t addr, uint8_t *buf, int len) +{ + if (cdriver.func.device_read == NULL) + return -1; + return cdriver.func.device_read(addr, buf, len); +} + +static void sleep(int millisec) +{ + if (cdriver.func.msleep == NULL) + return; + cdriver.func.msleep(millisec); +} + +static int init_test_register(void) +{ + uint8_t data; + + data = 0x00; + if (device_write(YAS_REGADDR_TEST1, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + data = 0x00; + if (device_write(YAS_REGADDR_TEST2, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + return YAS_NO_ERROR; +} + +static int get_device_id(uint8_t *id) +{ + uint8_t data = 0; + + if (device_read(YAS_REGADDR_DEVICE_ID, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + *id = data; + + return YAS_NO_ERROR; +} + +static int get_cal_data_yas530(struct yas_cal_data *cal) +{ + uint8_t data[16]; +#ifdef YAS_YAS530_CAL_SINGLE_READ + int i; + + for (i = 0; i < 16; i++) { /* dummy read */ + if (device_read(YAS_REGADDR_CAL + i, &data[i], 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + } + for (i = 0; i < 16; i++) { + if (device_read(YAS_REGADDR_CAL + i, &data[i], 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + } +#else + if (device_read(YAS_REGADDR_CAL, data, 16) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + if (device_read(YAS_REGADDR_CAL, data, 16) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; +#endif + + cal->dx = data[0]; + cal->dy1 = data[1]; + cal->dy2 = data[2]; + cal->d2 = (data[3] >> 2) & 0x03f; + cal->d3 = ((data[3] << 2) & 0x0c) | ((data[4] >> 6) & 0x03); + cal->d4 = data[4] & 0x3f; + cal->d5 = (data[5] >> 2) & 0x3f; + cal->d6 = ((data[5] << 4) & 0x30) | ((data[6] >> 4) & 0x0f); + cal->d7 = ((data[6] << 3) & 0x78) | ((data[7] >> 5) & 0x07); + cal->d8 = ((data[7] << 1) & 0x3e) | ((data[8] >> 7) & 0x01); + cal->d9 = ((data[8] << 1) & 0xfe) | ((data[9] >> 7) & 0x01); + cal->d0 = (data[9] >> 2) & 0x1f; + cal->dck = ((data[9] << 1) & 0x06) | ((data[10] >> 7) & 0x01); + cal->ver = (data[15]) & 0x03; + + return YAS_NO_ERROR; +} + +static void +get_correction_value_yas530(struct yas_cal_data *cal, + struct yas_correction_data *correct) +{ + correct->Cx = cal->dx * 6 - 768; + correct->Cy1 = cal->dy1 * 6 - 768; + correct->Cy2 = cal->dy2 * 6 - 768; + correct->a2 = cal->d2 - 32; + correct->a3 = cal->d3 - 8; + correct->a4 = cal->d4 - 32; + correct->a5 = cal->d5 + 38; + correct->a6 = cal->d6 - 32; + correct->a7 = cal->d7 - 64; + correct->a8 = cal->d8 - 32; + correct->a9 = cal->d9; + correct->k = cal->d0 + 10; +} + +static int get_cal_data_yas532(struct yas_cal_data *cal) +{ + uint8_t data[14]; +#ifdef YAS_YAS530_CAL_SINGLE_READ + int i; + + for (i = 0; i < 14; i++) { /* dummy read */ + if (device_read(YAS_REGADDR_CAL + i, &data[i], 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + } + for (i = 0; i < 14; i++) { + if (device_read(YAS_REGADDR_CAL + i, &data[i], 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + } +#else + if (device_read(YAS_REGADDR_CAL, data, 14) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + if (device_read(YAS_REGADDR_CAL, data, 14) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; +#endif + + cal->dx = data[0]; + cal->dy1 = data[1]; + cal->dy2 = data[2]; + cal->d2 = (data[3] >> 2) & 0x03f; + cal->d3 = ((data[3] << 2) & 0x0c) | ((data[4] >> 6) & 0x03); + cal->d4 = data[4] & 0x3f; + cal->d5 = (data[5] >> 2) & 0x3f; + cal->d6 = ((data[5] << 4) & 0x30) | ((data[6] >> 4) & 0x0f); + cal->d7 = ((data[6] << 3) & 0x78) | ((data[7] >> 5) & 0x07); + cal->d8 = ((data[7] << 1) & 0x3e) | ((data[8] >> 7) & 0x01); + cal->d9 = ((data[8] << 1) & 0xfe) | ((data[9] >> 7) & 0x01); + cal->d0 = (data[9] >> 2) & 0x1f; + cal->dck = ((data[9] << 1) & 0x06) | ((data[10] >> 7) & 0x01); + cal->ver = (data[13]) & 0x01; + + return YAS_NO_ERROR; +} + +static void +get_correction_value_yas532(struct yas_cal_data *cal, + struct yas_correction_data *correct) +{ + correct->Cx = cal->dx * 10 - 1280; + correct->Cy1 = cal->dy1 * 10 - 1280; + correct->Cy2 = cal->dy2 * 10 - 1280; + correct->a2 = cal->d2 - 32; + correct->a3 = cal->d3 - 8; + correct->a4 = cal->d4 - 32; + correct->a5 = cal->d5 + 38; + correct->a6 = cal->d6 - 32; + correct->a7 = cal->d7 - 64; + correct->a8 = cal->d8 - 32; + correct->a9 = cal->d9; + correct->k = cal->d0; +} + +static int set_configuration(int inton, int inthact, int cck) +{ + uint8_t data = 0; + + data |= (!!inton) & 0x01; + data |= ((!!inthact) << 1) & 0x02; + data |= (cck << 2) & 0x1c; + + if (device_write(YAS_REGADDR_CONFIG, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + return YAS_NO_ERROR; +} + +static int get_measure_interval(int32_t *msec) +{ + uint8_t data; + int mult = 7; + + if (device_read(YAS_REGADDR_MEASURE_INTERVAL, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + switch (cdriver.dev_id) { + case YAS_YAS532_DEVICE_ID: + mult = 4; + break; + case YAS_YAS530_DEVICE_ID: + default: + mult = 7; + break; + } + + *msec = data * mult; + + return YAS_NO_ERROR; +} + +static int set_measure_interval(int32_t msec) +{ + uint8_t data = 0; + int mult = 7; + + switch (cdriver.dev_id) { + case YAS_YAS532_DEVICE_ID: + mult = 4; + break; + case YAS_YAS530_DEVICE_ID: + default: + mult = 7; + break; + } + + if (msec > mult*0xff) + data = 0xff; + else + if (msec % mult == 0) + data = (uint8_t)(msec / mult); + else + data = (uint8_t)(msec / mult + 1); + if (device_write(YAS_REGADDR_MEASURE_INTERVAL, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + return YAS_NO_ERROR; +} + +static int set_measure_command(int ldtc, int fors, int dlymes) +{ + uint8_t data = 0; + + data |= 0x01; /* bit 0 must be 1 */ + data |= ((!(!ldtc)) << 1) & 0x02; + data |= ((!(!fors)) << 2) & 0x04; + data |= ((!(!dlymes)) << 4) & 0x10; + + if (device_write(YAS_REGADDR_MEASURE_COMMAND, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + return YAS_NO_ERROR; +} + +static int +measure_normal_yas530(int *busy, int16_t *t, int16_t *x, int16_t *y1, + int16_t *y2) +{ + uint8_t data[8]; + + if (set_measure_command(0, 0, 0) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + sleep(2); + + if (device_read(YAS_REGADDR_MEASURE_DATA, data, 8) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + *busy = (data[0] >> 7) & 0x01; + *t = (((int32_t) data[0] << 2) & 0x1fc) | ((data[1] >> 6) & 0x03); + *x = (((int32_t) data[2] << 5) & 0xfe0) | ((data[3] >> 3) & 0x1f); + *y1 = (((int32_t) data[4] << 5) & 0xfe0) | ((data[5] >> 3) & 0x1f); + *y2 = (((int32_t) data[6] << 5) & 0xfe0) | ((data[7] >> 3) & 0x1f); + /*YLOGD(("f[%d] t[%d] x[%d] y1[%d] y2[%d]\n", + *busy, *t, *x, *y1, *y2)); */ + + return YAS_NO_ERROR; +} + +static int +measure_normal_yas532(int *busy, int16_t *t, int16_t *x, int16_t *y1, + int16_t *y2) +{ + uint8_t data[8]; + + if (set_measure_command(0, 0, 0) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + sleep(2); + + if (device_read(YAS_REGADDR_MEASURE_DATA, data, 8) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + *busy = (data[0] >> 7) & 0x01; + *t = (((int32_t) data[0] << 3) & 0x3f8) | ((data[1] >> 5) & 0x07); + *x = (((int32_t) data[2] << 6) & 0x1fc0) | ((data[3] >> 2) & 0x3f); + *y1 = (((int32_t) data[4] << 6) & 0x1fc0) | ((data[5] >> 2) & 0x3f); + *y2 = (((int32_t) data[6] << 6) & 0x1fc0) | ((data[7] >> 2) & 0x3f); + /*YLOGD(("f[%d] t[%d] x[%d] y1[%d] y2[%d]\n", + *busy, *t, *x, *y1, *y2)); */ + + return YAS_NO_ERROR; +} + +static int +measure_normal(int *busy, int16_t *t, int16_t *x, int16_t *y1, int16_t *y2) +{ + int result; + + switch (cdriver.dev_id) { + case YAS_YAS532_DEVICE_ID: + result = measure_normal_yas532(busy, t, x, y1, y2); + break; + case YAS_YAS530_DEVICE_ID: + default: + result = measure_normal_yas530(busy, t, x, y1, y2); + break; + } + + return result; +} + +static int +coordinate_conversion(int32_t x, int32_t y1, int32_t y2, int16_t t, + int32_t *xo, int32_t *yo, int32_t *zo, + struct yas_correction_data *c) +{ + int32_t sx, sy1, sy2, sy, sz; + int32_t hx, hy, hz; + + sx = x - (c->Cx * t) / 100; + sy1 = y1 - (c->Cy1 * t) / 100; + sy2 = y2 - (c->Cy2 * t) / 100; + + sy = sy1 - sy2; + sz = -sy1 - sy2; + + hx = c->k * ((100 * sx + c->a2 * sy + c->a3 * sz) / 10); + hy = c->k * ((c->a4 * sx + c->a5 * sy + c->a6 * sz) / 10); + hz = c->k * ((c->a7 * sx + c->a8 * sy + c->a9 * sz) / 10); + + *xo = cdriver.transform[0] * hx + + cdriver.transform[1] * hy + cdriver.transform[2] * hz; + *yo = cdriver.transform[3] * hx + + cdriver.transform[4] * hy + cdriver.transform[5] * hz; + *zo = cdriver.transform[6] * hx + + cdriver.transform[7] * hy + cdriver.transform[8] * hz; + + return YAS_NO_ERROR; +} + +static int +set_hardware_offset(int8_t offset_x, int8_t offset_y1, int8_t offset_y2) +{ + uint8_t data; + + data = offset_x & 0x3f; + if (device_write(YAS_REGADDR_OFFSET_X, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + data = offset_y1 & 0x3f; + if (device_write(YAS_REGADDR_OFFSET_Y1, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + data = offset_y2 & 0x3f; + if (device_write(YAS_REGADDR_OFFSET_Y2, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + return YAS_NO_ERROR; +} + +static int yas_cdrv_actuate_initcoil(void) +{ + uint8_t data = 0; + + if (device_write(YAS_REGADDR_ACTUATE_INIT_COIL, &data, 1) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + return YAS_NO_ERROR; +} + +static int +check_offset(int8_t offset_x, int8_t offset_y1, int8_t offset_y2, + int *flag_x, int *flag_y1, int *flag_y2) +{ + int busy; + int16_t t, x, y1, y2; + + if (set_hardware_offset(offset_x, offset_y1, offset_y2) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + if (measure_normal(&busy, &t, &x, &y1, &y2) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + *flag_x = *flag_y1 = *flag_y2 = 0; + if (x > cdriver.center) + *flag_x = 1; + if (y1 > cdriver.center) + *flag_y1 = 1; + if (y2 > cdriver.center) + *flag_y2 = 1; + if (x < cdriver.center) + *flag_x = -1; + if (y1 < cdriver.center) + *flag_y1 = -1; + if (y2 < cdriver.center) + *flag_y2 = -1; + + return YAS_NO_ERROR; +} + +static int yas_cdrv_measure_and_set_offset(int8_t *offset) +{ + int i; + int8_t offset_x = 0, offset_y1 = 0, offset_y2 = 0; + int flag_x = 0, flag_y1 = 0, flag_y2 = 0; + static const int correct[5] = { 16, 8, 4, 2, 1 }; + + for (i = 0; i < 5; i++) { + if (check_offset(offset_x, offset_y1, offset_y2, + &flag_x, &flag_y1, &flag_y2) < 0) { + return YAS_ERROR_DEVICE_COMMUNICATION; + } + YLOGD(("offset[%d][%d][%d] flag[%d][%d][%d]\n", + offset_x, offset_y1, offset_y2, + flag_x, flag_y1, flag_y2)); + if (flag_x) + offset_x += flag_x * correct[i]; + if (flag_y1) + offset_y1 += flag_y1 * correct[i]; + if (flag_y2) + offset_y2 += flag_y2 * correct[i]; + } + if (set_hardware_offset(offset_x, offset_y1, offset_y2) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + offset[0] = offset_x; + offset[1] = offset_y1; + offset[2] = offset_y2; + + return YAS_NO_ERROR; +} + +static int yas_cdrv_set_offset(const int8_t *offset) +{ + if (set_hardware_offset(offset[0], offset[1], offset[2]) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + return YAS_NO_ERROR; +} + +static int +yas_cdrv_measure(int32_t *data, int32_t *raw, int16_t *temperature) +{ + int busy; + int16_t x, y1, y2, t; + int32_t xx, yy1, yy2; + int result = 0; + + if (measure_normal(&busy, &t, &x, &y1, &y2) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + if (x == 0) + result |= 0x01; + if (x == cdriver.overflow) + result |= 0x02; + if (y1 == 0) + result |= 0x04; + if (y1 == cdriver.overflow) + result |= 0x08; + if (y2 == 0) + result |= 0x10; + if (y2 == cdriver.overflow) + result |= 0x20; + + xx = x; + yy1 = y1; + yy2 = y2; + + if (coordinate_conversion(xx, yy1, yy2, t, &data[0], &data[1], + &data[2], &cdriver.correct) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + cdriver.temperature = t; + + if (raw != NULL) + raw[0] = xx, raw[1] = yy1, raw[2] = yy2; + if (temperature != NULL) + *temperature = t; + + return result; +} + +static int +yas_cdrv_recalc_calib_offset(int32_t *prev_calib_offset, + int32_t *new_calib_offset, + int8_t *prev_offset, int8_t *new_offset) +{ + int32_t tmp[3], resolution[9], base[3]; + int32_t raw[3]; + int32_t diff, i; + + if (prev_calib_offset == NULL || new_calib_offset == NULL + || prev_offset == NULL || new_offset == NULL) + return YAS_ERROR_ARG; + + raw[0] = raw[1] = raw[2] = 0; + if (coordinate_conversion(raw[0], raw[1], raw[2], cdriver.temperature, + &base[0], &base[1], &base[2], + &cdriver.correct) < 0) + return YAS_ERROR_ERROR; + for (i = 0; i < 3; i++) { + raw[0] = raw[1] = raw[2] = 0; + raw[i] = cdriver.coef; + if (coordinate_conversion(raw[0], raw[1], raw[2], + cdriver.temperature, + &resolution[i * 3 + 0], + &resolution[i * 3 + 1], + &resolution[i * 3 + 2], + &cdriver.correct) < 0) + return YAS_ERROR_ERROR; + resolution[i * 3 + 0] -= base[0]; + resolution[i * 3 + 1] -= base[1]; + resolution[i * 3 + 2] -= base[2]; + } + + for (i = 0; i < 3; i++) + tmp[i] = prev_calib_offset[i]; + + for (i = 0; i < 3; i++) { + diff = (int32_t) new_offset[i] - (int32_t) prev_offset[i]; + while (diff > 0) { + tmp[0] -= resolution[i * 3 + 0]; + tmp[1] -= resolution[i * 3 + 1]; + tmp[2] -= resolution[i * 3 + 2]; + diff--; + } + while (diff < 0) { + tmp[0] += resolution[i * 3 + 0]; + tmp[1] += resolution[i * 3 + 1]; + tmp[2] += resolution[i * 3 + 2]; + diff++; + } + } + for (i = 0; i < 3; i++) + new_calib_offset[i] = tmp[i]; + + return YAS_NO_ERROR; +} + +static int yas_cdrv_set_transformatiom_matrix(const int8_t *transform) +{ + int i; + + if (transform == NULL) + return YAS_ERROR_ARG; + for (i = 0; i < 9; i++) + cdriver.transform[i] = transform[i]; + + return YAS_NO_ERROR; +} + +static int +yas_cdrv_init(const int8_t *transform, struct yas_machdep_func *func) +{ + int interval, i; + uint8_t id; + + if (transform == NULL || func == NULL) + return YAS_ERROR_ARG; + + for (i = 0; i < 9; i++) + cdriver.transform[i] = transform[i]; + + cdriver.func = *func; + + if (device_open() < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + if (init_test_register() < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + if (get_device_id(&id) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + YLOGD(("device id:%02x\n", id)); + + switch (id) { + case YAS_YAS530_DEVICE_ID: + if (get_cal_data_yas530(&cdriver.cal) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + + get_correction_value_yas530(&cdriver.cal, &cdriver.correct); + cdriver.center = YAS_YAS530_DATA_CENTER; + cdriver.overflow = YAS_YAS530_DATA_OVERFLOW; + switch (cdriver.cal.ver) { + case YAS_YAS530_VERSION_B: + cdriver.coef = YAS_YAS530_VERSION_B_COEF; + break; + case YAS_YAS530_VERSION_A: + default: + cdriver.coef = YAS_YAS530_VERSION_A_COEF; + break; + } + break; + + case YAS_YAS532_DEVICE_ID: + if (get_cal_data_yas532(&cdriver.cal) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + get_correction_value_yas532(&cdriver.cal, &cdriver.correct); + cdriver.center = YAS_YAS532_DATA_CENTER; + cdriver.overflow = YAS_YAS532_DATA_OVERFLOW; + switch (cdriver.cal.ver) { + case YAS_YAS532_VERSION_AC: + cdriver.coef = YAS_YAS532_VERSION_AC_COEF; + break; + case YAS_YAS532_VERSION_AB: + default: + cdriver.coef = YAS_YAS532_VERSION_AB_COEF; + break; + } + break; + + default: + return YAS_ERROR_DEVICE_COMMUNICATION; + } + cdriver.dev_id = id; + + if (set_configuration(0, 0, cdriver.cal.dck) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + if (set_measure_interval(0) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + if (get_measure_interval(&interval) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + YLOGD(("interval[%d]\n", interval)); + + return YAS_NO_ERROR; +} + +static int yas_cdrv_term(void) +{ + device_close(); + return YAS_NO_ERROR; +} + +#define YAS_DEFAULT_CALIB_INTERVAL (50) /* 50 msecs */ +#define YAS_DEFAULT_DATA_INTERVAL (200) /* 200 msecs */ +#define YAS_INITCOIL_INTERVAL (200) /* 200 msec */ +#define YAS_INITCOIL_GIVEUP_INTERVAL (180000) /* 180 seconds */ +#define YAS_DETECT_OVERFLOW_INTERVAL (0) /* 0 second */ + +#define YAS_MAG_ERROR_DELAY (200) +#define YAS_MAG_STATE_NORMAL (0) +#define YAS_MAG_STATE_INIT_COIL (1) +#define YAS_MAG_STATE_MEASURE_OFFSET (2) + +static const int8_t YAS_TRANSFORMATION[][9] = { + {0, 1, 0, -1, 0, 0, 0, 0, 1}, + {-1, 0, 0, 0, -1, 0, 0, 0, 1}, + {0, -1, 0, 1, 0, 0, 0, 0, 1}, + {1, 0, 0, 0, 1, 0, 0, 0, 1}, + {0, -1, 0, -1, 0, 0, 0, 0, -1}, + {1, 0, 0, 0, -1, 0, 0, 0, -1}, + {0, 1, 0, 1, 0, 0, 0, 0, -1}, + {-1, 0, 0, 0, 1, 0, 0, 0, -1}, +}; + +static const int supported_data_interval[] = { 10, 20, 50, 60, 100, 200, 1000 }; +static const int supported_calib_interval[] = { 60, 60, 50, 60, 50, 50, 50 }; +static const int32_t INVALID_CALIB_OFFSET[] = { 0x7fffffff, + 0x7fffffff, 0x7fffffff }; +static const int8_t INVALID_OFFSET[] = { 0x7f, 0x7f, 0x7f }; + +struct yas_adaptive_filter { + int num; + int index; + int filter_len; + int filter_noise; + int32_t sequence[YAS_MAG_MAX_FILTER_LEN]; +}; + +struct yas_thresh_filter { + int32_t threshold; + int32_t last; +}; + +struct yas_driver { + int initialized; + struct yas_mag_driver_callback callback; + struct utimer data_timer; + struct utimer initcoil_timer; + struct utimer initcoil_giveup_timer; + struct utimer detect_overflow_timer; + int32_t prev_mag[3]; + int32_t prev_xy1y2[3]; + int32_t prev_mag_w_offset[3]; + int16_t prev_temperature; + int measure_state; + int active; + int overflow; + int initcoil_gaveup; + int position; + int delay_timer_use_data; + int delay_timer_interval; + int delay_timer_counter; + int filter_enable; + int filter_len; + int filter_thresh; + int filter_noise[3]; + struct yas_adaptive_filter adap_filter[3]; + struct yas_thresh_filter thresh_filter[3]; + struct yas_mag_offset offset; +#ifdef YAS_MAG_MANUAL_OFFSET + struct yas_vector manual_offset; +#endif + struct yas_matrix static_matrix; + struct yas_matrix dynamic_matrix; +}; + +static struct yas_driver this_driver; + +static int lock(void) +{ + if (this_driver.callback.lock != NULL) { + if (this_driver.callback.lock() < 0) + return YAS_ERROR_RESTARTSYS; + } + return 0; +} + +static int unlock(void) +{ + if (this_driver.callback.unlock != NULL) { + if (this_driver.callback.unlock() < 0) + return YAS_ERROR_RESTARTSYS; + } + return 0; +} + +static int32_t square(int32_t data) +{ + return data * data; +} + +static void +adaptive_filter_init(struct yas_adaptive_filter *adap_filter, int len, + int noise) +{ + int i; + + adap_filter->num = 0; + adap_filter->index = 0; + adap_filter->filter_noise = noise; + adap_filter->filter_len = len; + + for (i = 0; i < adap_filter->filter_len; ++i) + adap_filter->sequence[i] = 0; +} + +static int32_t +adaptive_filter_filter(struct yas_adaptive_filter *adap_filter, int32_t in) +{ + int32_t avg, sum; + int i; + + if (adap_filter->filter_len == 0) + return in; + + if (adap_filter->num < adap_filter->filter_len) { + adap_filter->sequence[adap_filter->index++] = in / 100; + adap_filter->num++; + return in; + } + if (adap_filter->filter_len <= adap_filter->index) + adap_filter->index = 0; + + adap_filter->sequence[adap_filter->index++] = in / 100; + + avg = 0; + for (i = 0; i < adap_filter->filter_len; i++) + avg += adap_filter->sequence[i]; + + avg /= adap_filter->filter_len; + + sum = 0; + for (i = 0; i < adap_filter->filter_len; i++) + sum += square(avg - adap_filter->sequence[i]); + + sum /= adap_filter->filter_len; + + if (sum <= adap_filter->filter_noise) + return avg * 100; + + return ((in / 100 - avg) * (sum - adap_filter->filter_noise) / sum + + avg) * 100; +} + +static void +thresh_filter_init(struct yas_thresh_filter *thresh_filter, int threshold) +{ + thresh_filter->threshold = threshold; + thresh_filter->last = 0; +} + +static int32_t +thresh_filter_filter(struct yas_thresh_filter *thresh_filter, int32_t in) +{ + if (in < thresh_filter->last - thresh_filter->threshold + || thresh_filter->last + thresh_filter->threshold < in) { + thresh_filter->last = in; + return in; + } else + return thresh_filter->last; +} + +static void filter_init(struct yas_driver *d) +{ + int i; + + for (i = 0; i < 3; i++) { + adaptive_filter_init(&d->adap_filter[i], d->filter_len, + d->filter_noise[i]); + thresh_filter_init(&d->thresh_filter[i], d->filter_thresh); + } +} + +static void +filter_filter(struct yas_driver *d, int32_t *orig, int32_t *filtered) +{ + int i; + + for (i = 0; i < 3; i++) { + filtered[i] = + adaptive_filter_filter(&d->adap_filter[i], orig[i]); + filtered[i] = + thresh_filter_filter(&d->thresh_filter[i], filtered[i]); + } +} + +static int is_valid_offset(const int8_t *p) +{ + return (p != NULL && (p[0] <= 31) && (p[1] <= 31) && (p[2] <= 31) + && (-31 <= p[0]) && (-31 <= p[1]) && (-31 <= p[2])); +} + +static int is_valid_calib_offset(const int32_t *p) +{ + int i; + for (i = 0; i < 3; i++) { + if (p[i] != INVALID_CALIB_OFFSET[i]) + return 1; + } + return 0; +} + +static int is_offset_differ(const int8_t *p0, const int8_t *p1) +{ + if (p0[0] != p1[0] || p0[1] != p1[1] || p0[2] != p1[2]) + return 1; + else + return 0; +} + +static int is_calib_offset_differ(const int32_t *p0, const int32_t *p1) +{ + if (p0[0] != p1[0] || p0[1] != p1[1] || p0[2] != p1[2]) + return 1; + else + return 0; +} + +static int get_overflow(struct yas_driver *d) +{ + return d->overflow; +} + +static void set_overflow(struct yas_driver *d, const int overflow) +{ + if (d->overflow != overflow) + d->overflow = overflow; +} + +static int get_initcoil_gaveup(struct yas_driver *d) +{ + return d->initcoil_gaveup; +} + +static void set_initcoil_gaveup(struct yas_driver *d, const int initcoil_gaveup) +{ + d->initcoil_gaveup = initcoil_gaveup; +} + +static int32_t *get_calib_offset(struct yas_driver *d) +{ + return d->offset.calib_offset.v; +} + +static void set_calib_offset(struct yas_driver *d, const int32_t *offset) +{ + int i; + + if (is_calib_offset_differ(d->offset.calib_offset.v, offset)) { + for (i = 0; i < 3; i++) + d->offset.calib_offset.v[i] = offset[i]; + } +} + +#ifdef YAS_MAG_MANUAL_OFFSET +static int32_t *get_manual_offset(struct yas_driver *d) +{ + return d->manual_offset.v; +} + +static void set_manual_offset(struct yas_driver *d, const int32_t *offset) +{ + int i; + + for (i = 0; i < 3; i++) + d->manual_offset.v[i] = offset[i]; +} +#endif + +static int32_t *get_static_matrix(struct yas_driver *d) +{ + return d->static_matrix.matrix; +} + +static void set_static_matrix(struct yas_driver *d, const int32_t *matrix) +{ + int i; + + for (i = 0; i < 9; i++) + d->static_matrix.matrix[i] = matrix[i]; +} + +static int32_t *get_dynamic_matrix(struct yas_driver *d) +{ + return d->dynamic_matrix.matrix; +} + +static void set_dynamic_matrix(struct yas_driver *d, const int32_t *matrix) +{ + int i; + + for (i = 0; i < 9; i++) + d->dynamic_matrix.matrix[i] = matrix[i]; +} + +static int8_t *get_offset(struct yas_driver *d) +{ + return d->offset.hard_offset; +} + +static void set_offset(struct yas_driver *d, const int8_t *offset) +{ + int i; + + if (is_offset_differ(d->offset.hard_offset, offset)) { + for (i = 0; i < 3; i++) + d->offset.hard_offset[i] = offset[i]; + } +} + +static int get_active(struct yas_driver *d) +{ + return d->active; +} + +static void set_active(struct yas_driver *d, const int active) +{ + d->active = active; +} + +static int get_position(struct yas_driver *d) +{ + return d->position; +} + +static void set_position(struct yas_driver *d, const int position) +{ + d->position = position; +} + +static int get_measure_state(struct yas_driver *d) +{ + return d->measure_state; +} + +static void set_measure_state(struct yas_driver *d, const int state) +{ + d->measure_state = state; +} + +static struct utimer *get_data_timer(struct yas_driver *d) +{ + return &d->data_timer; +} + +static struct utimer *get_initcoil_timer(struct yas_driver *d) +{ + return &d->initcoil_timer; +} + +static struct utimer *get_initcoil_giveup_timer(struct yas_driver *d) +{ + return &d->initcoil_giveup_timer; +} + +static struct utimer *get_detect_overflow_timer(struct yas_driver *d) +{ + return &d->detect_overflow_timer; +} + +static int get_delay_timer_use_data(struct yas_driver *d) +{ + return d->delay_timer_use_data; +} + +static void set_delay_timer_use_data(struct yas_driver *d, int flag) +{ + d->delay_timer_use_data = !(!flag); +} + +static int get_delay_timer_interval(struct yas_driver *d) +{ + return d->delay_timer_interval; +} + +static void set_delay_timer_interval(struct yas_driver *d, int interval) +{ + d->delay_timer_interval = interval; +} + +static int get_delay_timer_counter(struct yas_driver *d) +{ + return d->delay_timer_counter; +} + +static void set_delay_timer_counter(struct yas_driver *d, int counter) +{ + d->delay_timer_counter = counter; +} + +static int get_filter_enable(struct yas_driver *d) +{ + return d->filter_enable; +} + +static void set_filter_enable(struct yas_driver *d, int enable) +{ + if (enable) + filter_init(d); + + d->filter_enable = !(!enable); +} + +static int get_filter_len(struct yas_driver *d) +{ + return d->filter_len; +} + +static void set_filter_len(struct yas_driver *d, int len) +{ + if (len < 0) + return; + + if (len > YAS_MAG_MAX_FILTER_LEN) + return; + + d->filter_len = len; + filter_init(d); +} + +static int get_filter_noise(struct yas_driver *d, int *noise) +{ + int i; + + for (i = 0; i < 3; i++) + noise[i] = d->filter_noise[i]; + + return 0; +} + +static void set_filter_noise(struct yas_driver *d, int *noise) +{ + int i; + + if (noise == NULL) + return; + + for (i = 0; i < 3; i++) { + if (noise[i] < 0) + noise[i] = 0; + + d->filter_noise[i] = noise[i]; + } + filter_init(d); +} + +static int get_filter_thresh(struct yas_driver *d) +{ + return d->filter_thresh; +} + +static void set_filter_thresh(struct yas_driver *d, int threshold) +{ + if (threshold < 0) + return; + + d->filter_thresh = threshold; + filter_init(d); +} + +static int32_t *get_previous_mag(struct yas_driver *d) +{ + return d->prev_mag; +} + +static void set_previous_mag(struct yas_driver *d, int32_t *data) +{ + int i; + for (i = 0; i < 3; i++) + d->prev_mag[i] = data[i]; +} + +static int32_t *get_previous_xy1y2(struct yas_driver *d) +{ + return d->prev_xy1y2; +} + +static void set_previous_xy1y2(struct yas_driver *d, int32_t *data) +{ + int i; + for (i = 0; i < 3; i++) + d->prev_xy1y2[i] = data[i]; +} + +static int32_t *get_previous_mag_w_offset(struct yas_driver *d) +{ + return d->prev_mag_w_offset; +} + +static void set_previous_mag_w_offset(struct yas_driver *d, int32_t *data) +{ + int i; + for (i = 0; i < 3; i++) + d->prev_mag_w_offset[i] = data[i]; +} + +static int16_t get_previous_temperature(struct yas_driver *d) +{ + return d->prev_temperature; +} + +static void set_previous_temperature(struct yas_driver *d, int16_t temperature) +{ + d->prev_temperature = temperature; +} + +static int init_coil(struct yas_driver *d) +{ + int rt; + + YLOGD(("init_coil IN\n")); + + utimer_update(get_initcoil_timer(d)); + if (!get_initcoil_gaveup(d)) { + utimer_update(get_initcoil_giveup_timer(d)); + if (utimer_is_timeout(get_initcoil_giveup_timer(d))) { + utimer_clear_timeout(get_initcoil_giveup_timer(d)); + set_initcoil_gaveup(d, TRUE); + } + } + if (utimer_is_timeout(get_initcoil_timer(d)) && + !get_initcoil_gaveup(d)) { + utimer_clear_timeout(get_initcoil_timer(d)); + YLOGI(("init_coil!\n")); + rt = yas_cdrv_actuate_initcoil(); + if (rt < 0) { + YLOGE(("yas_cdrv_actuate_initcoil failed[%d]\n", rt)); + return rt; + } + if (get_overflow(d) || !is_valid_offset(get_offset(d))) + set_measure_state(d, YAS_MAG_STATE_MEASURE_OFFSET); + else + set_measure_state(d, YAS_MAG_STATE_NORMAL); + } + + YLOGD(("init_coil OUT\n")); + + return 0; +} + +static int measure_offset(struct yas_driver *d) +{ + int8_t offset[3]; + int32_t moffset[3]; + int rt, result = 0, i; + + YLOGI(("measure_offset IN\n")); + rt = yas_cdrv_measure_and_set_offset(offset); + if (rt < 0) { + YLOGE(("yas_cdrv_measure_offset failed[%d]\n", rt)); + return rt; + } + + YLOGI(("offset[%d][%d][%d]\n", offset[0], offset[1], offset[2])); + + for (i = 0; i < 3; i++) + moffset[i] = get_calib_offset(d)[i]; + + if (is_offset_differ(get_offset(d), offset)) { + if (is_valid_offset(get_offset(d)) + && is_valid_calib_offset(get_calib_offset(d))) { + yas_cdrv_recalc_calib_offset(get_calib_offset(d), + moffset, + get_offset(d), offset); + result |= YAS_REPORT_CALIB_OFFSET_CHANGED; + } + } + result |= YAS_REPORT_HARD_OFFSET_CHANGED; + + set_offset(d, offset); + if (is_valid_calib_offset(moffset)) + set_calib_offset(d, moffset); + + set_measure_state(d, YAS_MAG_STATE_NORMAL); + + YLOGI(("measure_offset OUT\n")); + + return result; +} + +static int +measure_msensor_normal(struct yas_driver *d, int32_t *magnetic, + int32_t *mag_w_offset, int32_t * xy1y2, + int16_t *temperature) +{ + int rt = 0, result, i; + int32_t tmp[3]; + + YLOGD(("measure_msensor_normal IN\n")); + + result = 0; + rt = yas_cdrv_measure(mag_w_offset, tmp, temperature); + if (rt < 0) { + YLOGE(("yas_cdrv_measure failed[%d]\n", rt)); + return rt; + } + for (i = 0; i < 3; i++) + xy1y2[i] = tmp[i]; + +#ifdef YAS_MAG_MANUAL_OFFSET + for (i = 0; i < 3; i++) + mag_w_offset[i] -= get_manual_offset(d)[i]; +#endif + if (rt > 0) { + utimer_update(get_detect_overflow_timer(d)); + set_overflow(d, TRUE); + if (utimer_is_timeout(get_detect_overflow_timer(d))) { + utimer_clear_timeout(get_detect_overflow_timer(d)); + result |= YAS_REPORT_OVERFLOW_OCCURED; + } + if (get_measure_state(d) == YAS_MAG_STATE_NORMAL) + set_measure_state(d, YAS_MAG_STATE_INIT_COIL); + + } else { + utimer_clear(get_detect_overflow_timer(d)); + set_overflow(d, FALSE); + if (get_measure_state(d) == YAS_MAG_STATE_NORMAL) { + utimer_clear(get_initcoil_timer(d)); + utimer_clear(get_initcoil_giveup_timer(d)); + } + } + + for (i = 0; i < 3; i++) { + tmp[i] + = (get_static_matrix(d)[i * 3 + 0] / 10 * + (mag_w_offset[0] / 10)) / 100 + + (get_static_matrix(d)[i * 3 + 1] / 10 * + (mag_w_offset[1] / 10)) / 100 + + (get_static_matrix(d)[i * 3 + 2] / 10 * + (mag_w_offset[2] / 10)) / 100; + } + for (i = 0; i < 3; i++) + magnetic[i] = mag_w_offset[i] = tmp[i]; + if (is_valid_calib_offset(get_calib_offset(d))) { + for (i = 0; i < 3; i++) + magnetic[i] -= get_calib_offset(d)[i]; + } + for (i = 0; i < 3; i++) { + tmp[i] + = (get_dynamic_matrix(d)[i * 3 + 0] / 10 * + (magnetic[0] / 10)) / 100 + + (get_dynamic_matrix(d)[i * 3 + 1] / 10 * + (magnetic[1] / 10)) / 100 + (get_dynamic_matrix(d)[i * 3 + + 2] / + 10 * (magnetic[2] / 10)) / + 100; + } + for (i = 0; i < 3; i++) + magnetic[i] = tmp[i]; + + if (get_filter_enable(d)) + filter_filter(d, magnetic, magnetic); + + YLOGD(("measure_msensor_normal OUT\n")); + + return result; +} + +static int +measure_msensor(struct yas_driver *d, int32_t *magnetic, + int32_t *mag_w_offset, int32_t *xy1y2, int16_t *temperature) +{ + int result, i; + + YLOGD(("measure_msensor IN\n")); + + for (i = 0; i < 3; i++) { + magnetic[i] = get_previous_mag(d)[i]; + mag_w_offset[i] = get_previous_mag_w_offset(d)[i]; + xy1y2[i] = get_previous_xy1y2(d)[i]; + *temperature = get_previous_temperature(d); + } + + result = 0; + switch (get_measure_state(d)) { + case YAS_MAG_STATE_INIT_COIL: + result = init_coil(d); + break; + case YAS_MAG_STATE_MEASURE_OFFSET: + result = measure_offset(d); + break; + case YAS_MAG_STATE_NORMAL: + result = 0; + break; + default: + result = -1; + break; + } + + if (result < 0) + return result; + + if (!(result & YAS_REPORT_OVERFLOW_OCCURED)) + result |= + measure_msensor_normal(d, magnetic, mag_w_offset, xy1y2, + temperature); + set_previous_mag(d, magnetic); + set_previous_xy1y2(d, xy1y2); + set_previous_mag_w_offset(d, mag_w_offset); + set_previous_temperature(d, *temperature); + + YLOGD(("measure_msensor OUT\n")); + + return result; +} + +static int +measure(struct yas_driver *d, int32_t *magnetic, int32_t *mag_w_offset, + int32_t *xy1y2, int16_t *temperature, uint32_t *time_delay) +{ + int result; + int counter; + uint32_t total = 0; + + YLOGD(("measure IN\n")); + + utimer_update(get_data_timer(d)); + result = measure_msensor(d, magnetic, mag_w_offset, xy1y2, + temperature); + if (result < 0) + return result; + + counter = get_delay_timer_counter(d); + total = utimer_get_total_time(get_data_timer(d)); + if (utimer_get_delay(get_data_timer(d)) > 0) + counter -= total / utimer_get_delay(get_data_timer(d)); + else + counter = 0; + + if (utimer_is_timeout(get_data_timer(d))) { + utimer_clear_timeout(get_data_timer(d)); + + if (get_delay_timer_use_data(d)) { + result |= YAS_REPORT_DATA; + if (counter <= 0) + result |= YAS_REPORT_CALIB; + } else { + result |= YAS_REPORT_CALIB; + if (counter <= 0) + result |= YAS_REPORT_DATA; + } + } + + if (counter <= 0) + set_delay_timer_counter(d, get_delay_timer_interval(d)); + else + set_delay_timer_counter(d, counter); + + *time_delay = utimer_sleep_time(get_data_timer(d)); + + YLOGD(("measure OUT [%d]\n", result)); + + return result; +} + +static int resume(struct yas_driver *d) +{ + int32_t zero[] = { 0, 0, 0 }; + struct yas_machdep_func func; + int rt; + + YLOGI(("resume IN\n")); + + func.device_open = d->callback.device_open; + func.device_close = d->callback.device_close; + func.device_write = d->callback.device_write; + func.device_read = d->callback.device_read; + func.msleep = d->callback.msleep; + + rt = + yas_cdrv_init(YAS_TRANSFORMATION[get_position(d)], &func); + + if (rt < 0) { + YLOGE(("yas_cdrv_init failed[%d]\n", rt)); + return rt; + } + + utimer_clear(get_data_timer(d)); + utimer_clear(get_initcoil_giveup_timer(d)); + utimer_clear(get_initcoil_timer(d)); + utimer_clear(get_detect_overflow_timer(d)); + + set_previous_mag(d, zero); + set_previous_xy1y2(d, zero); + set_previous_mag_w_offset(d, zero); + set_previous_temperature(d, 0); + set_overflow(d, FALSE); + set_initcoil_gaveup(d, FALSE); + + filter_init(d); + + if (is_valid_offset(d->offset.hard_offset)) { + yas_cdrv_set_offset(d->offset.hard_offset); + rt = yas_cdrv_actuate_initcoil(); + if (rt < 0) { + YLOGE(("yas_cdrv_actuate_initcoil failed[%d]\n", rt)); + set_measure_state(d, YAS_MAG_STATE_INIT_COIL); + } else + set_measure_state(d, YAS_MAG_STATE_NORMAL); + } else { + rt = yas_cdrv_actuate_initcoil(); + if (rt < 0) { + YLOGE(("yas_cdrv_actuate_initcoil failed[%d]\n", rt)); + set_measure_state(d, YAS_MAG_STATE_INIT_COIL); + } else + set_measure_state(d, YAS_MAG_STATE_MEASURE_OFFSET); + } + + YLOGI(("resume OUT\n")); + return 0; +} + +static int suspend(struct yas_driver *d) +{ + YLOGI(("suspend IN\n")); + + (void)d; + yas_cdrv_term(); + + YLOGI(("suspend OUT\n")); + return 0; +} + +static int check_interval(int ms) +{ + int index = -1; + + if (ms <= supported_data_interval[0]) + ms = supported_data_interval[0]; + for (index = 0; index < NELEMS(supported_data_interval); index++) { + if (ms == supported_data_interval[index]) + goto done; + else if (ms < supported_data_interval[index]) { + if (index != 0) + index -= 1; + goto done; + } + } +done: + return index; +} + +static int yas_get_delay_nolock(struct yas_driver *d, int *ms) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + if (get_delay_timer_use_data(d)) + *ms = utimer_get_delay(get_data_timer(d)); + else { + *ms = + utimer_get_delay(get_data_timer(d)) * + get_delay_timer_interval(d); + } + return YAS_NO_ERROR; +} + +static int yas_set_delay_nolock(struct yas_driver *d, int ms) +{ + int index; + uint32_t delay_data, delay_calib; + + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + index = check_interval(ms); + if (index < 0) + return YAS_ERROR_ARG; + delay_data = supported_data_interval[index]; + delay_calib = supported_calib_interval[index]; + set_delay_timer_use_data(d, delay_data < delay_calib); + if (delay_data < delay_calib) { + set_delay_timer_interval(d, delay_calib / delay_data); + set_delay_timer_counter(d, delay_calib / delay_data); + utimer_set_delay(get_data_timer(d), + supported_data_interval[index]); + } else { + set_delay_timer_interval(d, delay_data / delay_calib); + set_delay_timer_counter(d, delay_data / delay_calib); + utimer_set_delay(get_data_timer(d), + supported_calib_interval[index]); + } + + return YAS_NO_ERROR; +} + +static int +yas_get_offset_nolock(struct yas_driver *d, struct yas_mag_offset *offset) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + *offset = d->offset; + return YAS_NO_ERROR; +} + +static int +yas_set_offset_nolock(struct yas_driver *d, struct yas_mag_offset *offset) +{ + int32_t zero[] = { 0, 0, 0 }; + int rt; + + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + if (!get_active(d)) { + d->offset = *offset; + return YAS_NO_ERROR; + } + + if (!is_valid_offset(offset->hard_offset) + || is_offset_differ(offset->hard_offset, d->offset.hard_offset)) { + filter_init(d); + + utimer_clear(get_data_timer(d)); + utimer_clear(get_initcoil_giveup_timer(d)); + utimer_clear(get_initcoil_timer(d)); + utimer_clear(get_detect_overflow_timer(d)); + + set_previous_mag(d, zero); + set_previous_xy1y2(d, zero); + set_previous_mag_w_offset(d, zero); + set_previous_temperature(d, 0); + set_overflow(d, FALSE); + set_initcoil_gaveup(d, FALSE); + } + d->offset = *offset; + + if (is_valid_offset(d->offset.hard_offset)) + yas_cdrv_set_offset(d->offset.hard_offset); + else { + rt = yas_cdrv_actuate_initcoil(); + if (rt < 0) { + YLOGE(("yas_cdrv_actuate_initcoil failed[%d]\n", rt)); + set_measure_state(d, YAS_MAG_STATE_INIT_COIL); + } else + set_measure_state(d, YAS_MAG_STATE_MEASURE_OFFSET); + } + + return YAS_NO_ERROR; +} + +#ifdef YAS_MAG_MANUAL_OFFSET + +static int +yas_get_manual_offset_nolock(struct yas_driver *d, struct yas_vector *offset) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + + *offset = d->manual_offset; + + return YAS_NO_ERROR; +} + +static int +yas_set_manual_offset_nolock(struct yas_driver *d, struct yas_vector *offset) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + + set_manual_offset(d, offset->v); + + return YAS_NO_ERROR; +} + +#endif + +static int +yas_get_static_matrix_nolock(struct yas_driver *d, struct yas_matrix *matrix) +{ + int i; + + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + + for (i = 0; i < 9; i++) + matrix->matrix[i] = get_static_matrix(d)[i]; + + return YAS_NO_ERROR; +} + +static int +yas_set_static_matrix_nolock(struct yas_driver *d, struct yas_matrix *matrix) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + + set_static_matrix(d, matrix->matrix); + + return YAS_NO_ERROR; +} + +static int +yas_get_dynamic_matrix_nolock(struct yas_driver *d, struct yas_matrix *matrix) +{ + int i; + + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + + for (i = 0; i < 9; i++) + matrix->matrix[i] = get_dynamic_matrix(d)[i]; + + return YAS_NO_ERROR; +} + +static int +yas_set_dynamic_matrix_nolock(struct yas_driver *d, struct yas_matrix *matrix) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + + set_dynamic_matrix(d, matrix->matrix); + + return YAS_NO_ERROR; +} + +static int yas_get_enable_nolock(struct yas_driver *d) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + return get_active(d); +} + +static int yas_set_enable_nolock(struct yas_driver *d, int active) +{ + int rt; + + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + + if (active) { + if (get_active(d)) + return YAS_NO_ERROR; + rt = resume(d); + if (rt < 0) + return rt; + set_active(d, TRUE); + } else { + if (!get_active(d)) + return YAS_NO_ERROR; + rt = suspend(d); + if (rt < 0) + return rt; + set_active(d, FALSE); + } + return YAS_NO_ERROR; +} + +static int +yas_get_filter_nolock(struct yas_driver *d, struct yas_mag_filter *filter) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + filter->len = get_filter_len(d); + get_filter_noise(d, filter->noise); + filter->threshold = get_filter_thresh(d); + return YAS_NO_ERROR; +} + +static int +yas_set_filter_nolock(struct yas_driver *d, struct yas_mag_filter *filter) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + set_filter_len(d, filter->len); + set_filter_noise(d, filter->noise); + set_filter_thresh(d, filter->threshold); + return YAS_NO_ERROR; +} + +static int yas_get_filter_enable_nolock(struct yas_driver *d) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + return get_filter_enable(d); +} + +static int yas_set_filter_enable_nolock(struct yas_driver *d, int enable) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + set_filter_enable(d, enable); + return YAS_NO_ERROR; +} + +static int yas_get_position_nolock(struct yas_driver *d, int *position) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + *position = get_position(d); + return YAS_NO_ERROR; +} + +static int yas_set_position_nolock(struct yas_driver *d, int position) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + if (get_active(d)) + yas_cdrv_set_transformatiom_matrix(YAS_TRANSFORMATION + [position]); + set_position(d, position); + filter_init(d); + return YAS_NO_ERROR; +} + +static int +yas_read_reg_nolock(struct yas_driver *d, uint8_t addr, uint8_t * buf, int len) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + if (!get_active(d)) { + if (d->callback.device_open() < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + } + if (d->callback.device_read(addr, buf, len) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + if (!get_active(d)) { + if (d->callback.device_close() < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + } + + return YAS_NO_ERROR; +} + +static int +yas_write_reg_nolock(struct yas_driver *d, uint8_t addr, const uint8_t * buf, + int len) +{ + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + if (!get_active(d)) { + if (d->callback.device_open() < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + } + if (d->callback.device_write(addr, buf, len) < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + if (!get_active(d)) { + if (d->callback.device_close() < 0) + return YAS_ERROR_DEVICE_COMMUNICATION; + } + + return YAS_NO_ERROR; +} + +static int +yas_measure_nolock(struct yas_driver *d, struct yas_mag_data *data, + int *time_delay_ms) +{ + uint32_t time_delay = YAS_MAG_ERROR_DELAY; + int rt, i; + + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + *time_delay_ms = YAS_MAG_ERROR_DELAY; + + if (!get_active(d)) { + for (i = 0; i < 3; i++) { + data->xyz.v[i] = get_previous_mag(d)[i]; + data->raw.v[i] = get_previous_mag_w_offset(d)[i]; + data->xy1y2.v[i] = get_previous_xy1y2(d)[i]; + } + data->temperature = get_previous_temperature(d); + return YAS_NO_ERROR; + } + + rt = measure(d, data->xyz.v, data->raw.v, data->xy1y2.v, + &data->temperature, &time_delay); + if (rt >= 0) { + *time_delay_ms = time_delay; + if (*time_delay_ms > 0) + *time_delay_ms += 1; + } + + return rt; +} + +static int yas_init_nolock(struct yas_driver *d) +{ +#ifdef YAS_MAG_MANUAL_OFFSET + int32_t zero[] = { 0, 0, 0 }; +#endif + int32_t notransform[] = { 10000, 0, 0, 0, 10000, 0, 0, 0, 10000 }; + int noise[] = { + YAS_MAG_DEFAULT_FILTER_NOISE_X, + YAS_MAG_DEFAULT_FILTER_NOISE_Y, + YAS_MAG_DEFAULT_FILTER_NOISE_Z + }; + + YLOGI(("yas_init_nolock IN\n")); + + utimer_lib_init(this_driver.callback.current_time); + utimer_init(get_data_timer(d), 50); + utimer_init(get_initcoil_timer(d), YAS_INITCOIL_INTERVAL); + utimer_init(get_initcoil_giveup_timer(d), YAS_INITCOIL_GIVEUP_INTERVAL); + utimer_init(get_detect_overflow_timer(d), YAS_DETECT_OVERFLOW_INTERVAL); + + set_delay_timer_use_data(d, 0); + set_delay_timer_interval(d, + YAS_DEFAULT_DATA_INTERVAL / + YAS_DEFAULT_CALIB_INTERVAL); + set_delay_timer_counter(d, + YAS_DEFAULT_DATA_INTERVAL / + YAS_DEFAULT_CALIB_INTERVAL); + + set_filter_enable(d, FALSE); + set_filter_len(d, YAS_MAG_DEFAULT_FILTER_LEN); + set_filter_thresh(d, YAS_MAG_DEFAULT_FILTER_THRESH); + set_filter_noise(d, noise); + filter_init(d); + set_calib_offset(d, INVALID_CALIB_OFFSET); +#ifdef YAS_MAG_MANUAL_OFFSET + set_manual_offset(d, zero); +#endif + set_static_matrix(d, notransform); + set_dynamic_matrix(d, notransform); + set_offset(d, INVALID_OFFSET); + set_active(d, FALSE); + set_position(d, 0); + + d->initialized = 1; + + YLOGI(("yas_init_nolock OUT\n")); + + return YAS_NO_ERROR; +} + +static int yas_term_nolock(struct yas_driver *d) +{ + YLOGI(("yas_term_nolock\n")); + + if (unlikely(!d->initialized)) + return YAS_ERROR_NOT_INITIALIZED; + + if (get_active(d)) + suspend(d); + d->initialized = 0; + + YLOGI(("yas_term_nolock out\n")); + return YAS_NO_ERROR; +} + +static int yas_get_delay(void) +{ + int ms = 0, rt; + + YLOGI(("yas_get_delay\n")); + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_get_delay_nolock(&this_driver, &ms); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_get_delay[%d] OUT\n", ms)); + + return (rt < 0 ? rt : ms); +} + +static int yas_set_delay(int delay) +{ + int rt; + + YLOGI(("yas_set_delay\n")); + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_set_delay_nolock(&this_driver, delay); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_set_delay OUT\n")); + + return rt; +} + +static int yas_get_offset(struct yas_mag_offset *offset) +{ + int rt; + + YLOGI(("yas_get_offset\n")); + + if (offset == NULL) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_get_offset_nolock(&this_driver, offset); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_get_offset[%d] OUT\n", rt)); + + return rt; +} + +static int yas_set_offset(struct yas_mag_offset *offset) +{ + int rt; + + YLOGI(("yas_set_offset IN\n")); + + if (offset == NULL) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_set_offset_nolock(&this_driver, offset); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_set_offset OUT\n")); + + return rt; +} + +#ifdef YAS_MAG_MANUAL_OFFSET + +static int yas_get_manual_offset(struct yas_vector *offset) +{ + int rt; + + YLOGI(("yas_get_manual_offset\n")); + + if (offset == NULL) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_get_manual_offset_nolock(&this_driver, offset); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_get_manual_offset[%d] OUT\n", rt)); + + return rt; +} + +static int yas_set_manual_offset(struct yas_vector *offset) +{ + int rt; + + YLOGI(("yas_set_manual_offset IN\n")); + + if (offset == NULL) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_set_manual_offset_nolock(&this_driver, offset); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_set_manual_offset OUT\n")); + + return rt; +} + +#endif + +static int yas_get_static_matrix(struct yas_matrix *matrix) +{ + int rt; + + YLOGI(("yas_get_static_matrix\n")); + + if (matrix == NULL) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_get_static_matrix_nolock(&this_driver, matrix); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_get_static_matrix[%d] OUT\n", rt)); + + return rt; +} + +static int yas_set_static_matrix(struct yas_matrix *matrix) +{ + int rt; + + YLOGI(("yas_set_static_matrix IN\n")); + + if (matrix == NULL) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_set_static_matrix_nolock(&this_driver, matrix); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_set_static_matrix OUT\n")); + + return rt; +} + +static int yas_get_dynamic_matrix(struct yas_matrix *matrix) +{ + int rt; + + YLOGI(("yas_get_dynamic_matrix\n")); + + if (matrix == NULL) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_get_dynamic_matrix_nolock(&this_driver, matrix); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_get_dynamic_matrix[%d] OUT\n", rt)); + + return rt; +} + +static int yas_set_dynamic_matrix(struct yas_matrix *matrix) +{ + int rt; + + YLOGI(("yas_set_dynamic_matrix IN\n")); + + if (matrix == NULL) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_set_dynamic_matrix_nolock(&this_driver, matrix); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_set_dynamic_matrix OUT\n")); + + return rt; +} + +static int yas_get_enable(void) +{ + int rt; + + YLOGI(("yas_get_enable\n")); + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_get_enable_nolock(&this_driver); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_get_enable OUT[%d]\n", rt)); + + return rt; +} + +static int yas_set_enable(int enable) +{ + int rt; + + YLOGI(("yas_set_enable IN\n")); + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_set_enable_nolock(&this_driver, enable); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_set_enable OUT\n")); + + return rt; +} + +static int yas_get_filter(struct yas_mag_filter *filter) +{ + int rt; + + YLOGI(("yas_get_filter\n")); + + if (filter == NULL) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_get_filter_nolock(&this_driver, filter); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_get_filter[%d] OUT\n", rt)); + + return rt; +} + +static int yas_set_filter(struct yas_mag_filter *filter) +{ + int rt, i; + + YLOGI(("yas_set_filter IN\n")); + + if (filter == NULL + || filter->len < 0 + || YAS_MAG_MAX_FILTER_LEN < filter->len || filter->threshold < 0) { + return YAS_ERROR_ARG; + } + for (i = 0; i < 3; i++) { + if (filter->noise[i] < 0) + return YAS_ERROR_ARG; + } + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_set_filter_nolock(&this_driver, filter); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_set_filter OUT\n")); + + return rt; +} + +static int yas_get_filter_enable(void) +{ + int rt; + + YLOGI(("yas_get_filter_enable\n")); + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_get_filter_enable_nolock(&this_driver); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_get_filter_enable OUT[%d]\n", rt)); + + return rt; +} + +static int yas_set_filter_enable(int enable) +{ + int rt; + + YLOGI(("yas_set_filter_enable IN\n")); + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_set_filter_enable_nolock(&this_driver, enable); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_set_filter_enable OUT\n")); + + return rt; +} + +static int yas_get_position(void) +{ + int position = 0; + int rt; + + YLOGI(("yas_get_position\n")); + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_get_position_nolock(&this_driver, &position); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_get_position[%d] OUT\n", position)); + + return (rt < 0 ? rt : position); +} + +static int yas_set_position(int position) +{ + int rt; + + YLOGI(("yas_set_position\n")); + + if (position < 0 || 7 < position) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_set_position_nolock(&this_driver, position); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_set_position[%d] OUT\n", position)); + + return rt; +} + +static int yas_read_reg(uint8_t addr, uint8_t *buf, int len) +{ + int rt; + + YLOGI(("yas_read_reg\n")); + + if (buf == NULL || len <= 0) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_read_reg_nolock(&this_driver, addr, buf, len); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_read_reg[%d] OUT\n", rt)); + + return rt; +} + +static int yas_write_reg(uint8_t addr, const uint8_t *buf, int len) +{ + int rt; + + YLOGI(("yas_write_reg\n")); + + if (buf == NULL || len <= 0) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_write_reg_nolock(&this_driver, addr, buf, len); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGI(("yas_write_reg[%d] OUT\n", rt)); + + return rt; +} + +static int yas_measure(struct yas_mag_data *data, int *time_delay_ms) +{ + int rt; + + YLOGD(("yas_measure IN\n")); + + if (data == NULL || time_delay_ms == NULL) + return YAS_ERROR_ARG; + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_measure_nolock(&this_driver, data, time_delay_ms); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + YLOGD(("yas_measure OUT[%d]\n", rt)); + + return rt; +} + +static int yas_init(void) +{ + int rt; + + YLOGI(("yas_init\n")); + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_init_nolock(&this_driver); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + return rt; +} + +static int yas_term(void) +{ + int rt; + YLOGI(("yas_term\n")); + + if (lock() < 0) + return YAS_ERROR_RESTARTSYS; + + rt = yas_term_nolock(&this_driver); + + if (unlock() < 0) + return YAS_ERROR_RESTARTSYS; + + return rt; +} + +int yas_mag_driver_init(struct yas_mag_driver *f) +{ + if (f == NULL) + return YAS_ERROR_ARG; + if (f->callback.device_open == NULL + || f->callback.device_close == NULL + || f->callback.device_read == NULL + || f->callback.device_write == NULL + || f->callback.msleep == NULL || f->callback.current_time == NULL) + return YAS_ERROR_ARG; + + f->init = yas_init; + f->term = yas_term; + f->get_delay = yas_get_delay; + f->set_delay = yas_set_delay; + f->get_offset = yas_get_offset; + f->set_offset = yas_set_offset; +#ifdef YAS_MAG_MANUAL_OFFSET + f->get_manual_offset = yas_get_manual_offset; + f->set_manual_offset = yas_set_manual_offset; +#endif + f->get_static_matrix = yas_get_static_matrix; + f->set_static_matrix = yas_set_static_matrix; + f->get_dynamic_matrix = yas_get_dynamic_matrix; + f->set_dynamic_matrix = yas_set_dynamic_matrix; + f->get_enable = yas_get_enable; + f->set_enable = yas_set_enable; + f->get_filter = yas_get_filter; + f->set_filter = yas_set_filter; + f->get_filter_enable = yas_get_filter_enable; + f->set_filter_enable = yas_set_filter_enable; + f->get_position = yas_get_position; + f->set_position = yas_set_position; + f->read_reg = yas_read_reg; + f->write_reg = yas_write_reg; + f->measure = yas_measure; + + if ((f->callback.lock == NULL && f->callback.unlock != NULL) + || (f->callback.lock != NULL && f->callback.unlock == NULL)) { + this_driver.callback.lock = NULL; + this_driver.callback.unlock = NULL; + } else { + this_driver.callback.lock = f->callback.lock; + this_driver.callback.unlock = f->callback.unlock; + } + this_driver.callback.device_open = f->callback.device_open; + this_driver.callback.device_close = f->callback.device_close; + this_driver.callback.device_write = f->callback.device_write; + this_driver.callback.device_read = f->callback.device_read; + this_driver.callback.msleep = f->callback.msleep; + this_driver.callback.current_time = f->callback.current_time; + yas_term(); + + return YAS_NO_ERROR; +} diff --git a/drivers/sensor/yas_mag_driver.c b/drivers/sensor/yas_mag_driver.c new file mode 100644 index 0000000..805ec32 --- /dev/null +++ b/drivers/sensor/yas_mag_driver.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010 Yamaha Corporation + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#include + +#if CONFIG_SENSORS_YAS532 +#include "yas_mag_driver-yas532.c" +#else +#include "yas_mag_driver-none.c" +#endif diff --git a/drivers/sensor/yas_mag_kernel_driver.c b/drivers/sensor/yas_mag_kernel_driver.c new file mode 100644 index 0000000..0106958 --- /dev/null +++ b/drivers/sensor/yas_mag_kernel_driver.c @@ -0,0 +1,2192 @@ +/* + * Copyright (c) 2010-2011 Yamaha Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __LINUX_KERNEL_DRIVER__ +#include +#include +#include "yas_mag_driver.c" + +#define SYSFS_PCBTEST +#ifdef SYSFS_PCBTEST +#include "yas_pcb_test.h" +#include "yas_pcb_test.c" +#endif + +#define GEOMAGNETIC_I2C_DEVICE_NAME "yas532" +#define GEOMAGNETIC_INPUT_NAME "geomagnetic" +#define GEOMAGNETIC_INPUT_RAW_NAME "geomagnetic_raw" +#undef GEOMAGNETIC_PLATFORM_API + +#define ABS_STATUS (ABS_BRAKE) +#define ABS_WAKE (ABS_MISC) + +#define ABS_RAW_DISTORTION (ABS_THROTTLE) +#define ABS_RAW_THRESHOLD (ABS_RUDDER) +#define ABS_RAW_SHAPE (ABS_WHEEL) +#define ABS_RAW_MODE (ABS_HAT0X) +#define ABS_RAW_REPORT (ABS_GAS) + +struct geomagnetic_data { + struct input_dev *input_data; + struct input_dev *input_raw; + struct delayed_work work; + struct semaphore driver_lock; + struct semaphore multi_lock; + atomic_t last_data[3]; + atomic_t last_status; + atomic_t enable; + int filter_enable; + int filter_len; + int32_t filter_noise[3]; + int32_t filter_threshold; + int delay; + int32_t threshold; + int32_t distortion[3]; + int32_t shape; + int32_t ellipsoid_mode; + struct yas_mag_offset driver_offset; +#if DEBUG + int suspend; +#endif +#ifdef YAS_MAG_MANUAL_OFFSET + struct yas_vector manual_offset; +#endif + struct yas_matrix static_matrix; + struct yas_matrix dynamic_matrix; +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct list_head devfile_list; + struct list_head raw_devfile_list; +#endif + struct device *magnetic_sensor_device; + struct mag_platform_data *mag_pdata; + uint8_t dev_id; + int noise_test_init; +}; + +static struct i2c_client *this_client; + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + +#include +#define MAX_COUNT (64) +#define SENSOR_NAME "geomagnetic" +#define SENSOR_RAW_NAME "geomagnetic_raw" + +struct sensor_device { + struct list_head list; + struct mutex lock; + wait_queue_head_t waitq; + struct input_event events[MAX_COUNT]; + int head, num_event; +}; + +static void get_time_stamp(struct timeval *tv) +{ + struct timespec ts; + ktime_get_ts(&ts); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; +} + +static void make_event(struct input_event *ev, int type, int code, int value) +{ + struct timeval tv; + get_time_stamp(&tv); + ev->type = type; + ev->code = code; + ev->value = value; + ev->time = tv; +} + +static void +make_event_w_time(struct input_event *ev, int type, int code, int value, + struct timeval *tv) +{ + ev->type = type; + ev->code = code; + ev->value = value; + ev->time = *tv; +} + +static void sensor_enq(struct sensor_device *kdev, struct input_event *ev) +{ + int idx; + + idx = kdev->head + kdev->num_event; + if (MAX_COUNT <= idx) + idx -= MAX_COUNT; + kdev->events[idx] = *ev; + kdev->num_event++; + if (MAX_COUNT < kdev->num_event) { + kdev->num_event = MAX_COUNT; + kdev->head++; + if (MAX_COUNT <= kdev->head) + kdev->head -= MAX_COUNT; + } +} + +static int sensor_deq(struct sensor_device *kdev, struct input_event *ev) +{ + if (kdev->num_event == 0) + return 0; + + *ev = kdev->events[kdev->head]; + kdev->num_event--; + kdev->head++; + if (MAX_COUNT <= kdev->head) + kdev->head -= MAX_COUNT; + return 1; +} + +static void +sensor_event(struct list_head *devlist, struct input_event *ev, int num) +{ + struct sensor_device *kdev; + int i; + + list_for_each_entry(kdev, devlist, list) { + mutex_lock(&kdev->lock); + for (i = 0; i < num; i++) + sensor_enq(kdev, &ev[i]); + mutex_unlock(&kdev->lock); + wake_up_interruptible(&kdev->waitq); + } +} + +static ssize_t +sensor_write(struct file *f, const char __user *buf, size_t count, + loff_t *pos) +{ + struct geomagnetic_data *data = i2c_get_clientdata(this_client); + struct sensor_device *kdev; + struct input_event ev[MAX_COUNT]; + int num, i; + + if (count < sizeof(struct input_event)) + return -EINVAL; + num = count / sizeof(struct input_event); + if (MAX_COUNT < num) + num = MAX_COUNT; + + if (copy_from_user(ev, buf, num * sizeof(struct input_event))) + return -EFAULT; + + list_for_each_entry(kdev, &data->devfile_list, list) { + mutex_lock(&kdev->lock); + for (i = 0; i < num; i++) + sensor_enq(kdev, &ev[i]); + mutex_unlock(&kdev->lock); + wake_up_interruptible(&kdev->waitq); + } + + return count; +} + +static ssize_t +sensor_read(struct file *f, char __user *buf, size_t count, loff_t *pos) +{ + struct sensor_device *kdev = f->private_data; + int rt, num; + struct input_event ev[MAX_COUNT]; + + if (count < sizeof(struct input_event)) + return -EINVAL; + + rt = wait_event_interruptible(kdev->waitq, kdev->num_event != 0); + if (rt) + return rt; + + mutex_lock(&kdev->lock); + for (num = 0; num < count / sizeof(struct input_event); num++) { + if (!sensor_deq(kdev, &ev[num])) + break; + } + mutex_unlock(&kdev->lock); + + if (copy_to_user(buf, ev, num * sizeof(struct input_event))) + return -EFAULT; + + return num * sizeof(struct input_event); +} + +static unsigned int sensor_poll(struct file *f, struct poll_table_struct *wait) +{ + struct sensor_device *kdev = f->private_data; + + poll_wait(f, &kdev->waitq, wait); + if (kdev->num_event != 0) + return POLLIN | POLLRDNORM; + + return 0; +} + +static int sensor_open(struct inode *inode, struct file *f) +{ + struct geomagnetic_data *data = i2c_get_clientdata(this_client); + struct sensor_device *kdev; + + kdev = kzalloc(sizeof(struct sensor_device), GFP_KERNEL); + if (!kdev) + return -ENOMEM; + + mutex_init(&kdev->lock); + init_waitqueue_head(&kdev->waitq); + f->private_data = kdev; + kdev->head = 0; + kdev->num_event = 0; + list_add(&kdev->list, &data->devfile_list); + + return 0; +} + +static int sensor_release(struct inode *inode, struct file *f) +{ + struct sensor_device *kdev = f->private_data; + + list_del(&kdev->list); + kfree(kdev); + + return 0; +} + +static int sensor_raw_open(struct inode *inode, struct file *f) +{ + struct geomagnetic_data *data = i2c_get_clientdata(this_client); + struct sensor_device *kdev; + + kdev = kzalloc(sizeof(struct sensor_device), GFP_KERNEL); + if (!kdev) + return -ENOMEM; + + mutex_init(&kdev->lock); + init_waitqueue_head(&kdev->waitq); + f->private_data = kdev; + kdev->head = 0; + kdev->num_event = 0; + list_add(&kdev->list, &data->raw_devfile_list); + + return 0; +} + +const struct file_operations sensor_fops = { + .owner = THIS_MODULE, + .open = sensor_open, + .release = sensor_release, + .write = sensor_write, + .read = sensor_read, + .poll = sensor_poll, +}; + +static struct miscdevice sensor_devfile = { + .name = SENSOR_NAME, + .fops = &sensor_fops, + .minor = MISC_DYNAMIC_MINOR, +}; + +const struct file_operations sensor_raw_fops = { + .owner = THIS_MODULE, + .open = sensor_raw_open, + .release = sensor_release, + .write = sensor_write, + .read = sensor_read, + .poll = sensor_poll, +}; + +static struct miscdevice sensor_raw_devfile = { + .name = SENSOR_RAW_NAME, + .fops = &sensor_raw_fops, + .minor = MISC_DYNAMIC_MINOR, +}; + +#endif + +static int geomagnetic_i2c_open(void) +{ + return 0; +} + +static int geomagnetic_i2c_close(void) +{ + return 0; +} + +#if YAS_MAG_DRIVER == YAS_MAG_DRIVER_YAS529 +static int geomagnetic_i2c_write(const uint8_t *buf, int len) +{ + if (i2c_master_send(this_client, buf, len) < 0) + return -1; +#if DEBUG + YLOGD(("[W] [%02x]\n", buf[0])); +#endif + + return 0; +} + +static int geomagnetic_i2c_read(uint8_t *buf, int len) +{ + if (i2c_master_recv(this_client, buf, len) < 0) + return -1; + return 0; +} + +#else + +static int geomagnetic_i2c_write(uint8_t addr, const uint8_t *buf, int len) +{ + uint8_t tmp[16]; + + if (sizeof(tmp) - 1 < len) + return -1; + + tmp[0] = addr; + memcpy(&tmp[1], buf, len); + + if (i2c_master_send(this_client, tmp, len + 1) < 0) + return -1; +#if DEBUG + YLOGD(("[W] addr[%02x] [%02x]\n", addr, buf[0])); +#endif + + return 0; +} + +static int geomagnetic_i2c_read(uint8_t addr, uint8_t *buf, int len) +{ + struct i2c_msg msg[2]; + int err; + + msg[0].addr = this_client->addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = &addr; + msg[1].addr = this_client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = len; + msg[1].buf = buf; + + err = i2c_transfer(this_client->adapter, msg, 2); + if (err != 2) { + dev_err(&this_client->dev, + "i2c_transfer() read error: slave_addr=%02x, reg_addr=%02x, err=%d\n", + this_client->addr, addr, err); + return err; + } + + return 0; +} + +#endif + +static int geomagnetic_lock(void) +{ + struct geomagnetic_data *data = NULL; + int rt; + + if (this_client == NULL) + return -1; + + data = i2c_get_clientdata(this_client); + rt = down_interruptible(&data->driver_lock); + if (rt < 0) + up(&data->driver_lock); + return rt; +} + +static int geomagnetic_unlock(void) +{ + struct geomagnetic_data *data = NULL; + + if (this_client == NULL) + return -1; + + data = i2c_get_clientdata(this_client); + up(&data->driver_lock); + return 0; +} + +static void geomagnetic_msleep(int ms) +{ + usleep_range(ms * 999, ms * 1000); +} + +static void geomagnetic_current_time(int32_t *sec, int32_t *msec) +{ + struct timeval tv; + + do_gettimeofday(&tv); + + *sec = tv.tv_sec; + *msec = tv.tv_usec / 1000; +} + +static struct yas_mag_driver hwdep_driver = { + .callback = { + .lock = geomagnetic_lock, + .unlock = geomagnetic_unlock, + .device_open = geomagnetic_i2c_open, + .device_close = geomagnetic_i2c_close, + .device_read = geomagnetic_i2c_read, + .device_write = geomagnetic_i2c_write, + .msleep = geomagnetic_msleep, + .current_time = geomagnetic_current_time, + }, +}; + +static int geomagnetic_multi_lock(void) +{ + struct geomagnetic_data *data = NULL; + int rt; + + if (this_client == NULL) + return -1; + + data = i2c_get_clientdata(this_client); + rt = down_interruptible(&data->multi_lock); + if (rt < 0) + up(&data->multi_lock); + return rt; +} + +static int geomagnetic_multi_unlock(void) +{ + struct geomagnetic_data *data = NULL; + + if (this_client == NULL) + return -1; + + data = i2c_get_clientdata(this_client); + up(&data->multi_lock); + return 0; +} + +static int geomagnetic_enable(struct geomagnetic_data *data) +{ + if (!atomic_cmpxchg(&data->enable, 0, 1)) + schedule_delayed_work(&data->work, 0); + + return 0; +} + +static int geomagnetic_disable(struct geomagnetic_data *data) +{ + if (atomic_cmpxchg(&data->enable, 1, 0)) + cancel_delayed_work_sync(&data->work); + + return 0; +} + +/* Sysfs interface */ +static ssize_t +geomagnetic_delay_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + int delay; + + geomagnetic_multi_lock(); + + delay = data->delay; + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d\n", delay); +} + +static ssize_t +geomagnetic_delay_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + unsigned long value; + int error; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + + if (hwdep_driver.set_delay == NULL) + return -ENOTTY; + + geomagnetic_multi_lock(); + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + if (hwdep_driver.set_delay(value) == 0) + data->delay = value; + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + + return sprintf(buf, "%d\n", atomic_read(&data->enable)); +} + +static ssize_t +geomagnetic_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + unsigned long value; + int error; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + value = !(!value); + + if (hwdep_driver.set_enable == NULL) + return -ENOTTY; + + if (geomagnetic_multi_lock() < 0) + return count; + + if (hwdep_driver.set_enable(value) == 0) { + if (value) + geomagnetic_enable(data); + else + geomagnetic_disable(data); + } + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_filter_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + int filter_enable; + + geomagnetic_multi_lock(); + + filter_enable = data->filter_enable; + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d\n", filter_enable); +} + +static ssize_t +geomagnetic_filter_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + unsigned long value; + int error; + + if (hwdep_driver.set_filter_enable == NULL) + return -ENOTTY; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + + if (geomagnetic_multi_lock() < 0) + return count; + + if (hwdep_driver.set_filter_enable(value) == 0) + data->filter_enable = !!value; + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_filter_len_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + int filter_len; + + geomagnetic_multi_lock(); + + filter_len = data->filter_len; + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d\n", filter_len); +} + +static ssize_t +geomagnetic_filter_len_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + struct yas_mag_filter filter; + unsigned long value; + int error; + + if (hwdep_driver.get_filter == NULL || hwdep_driver.set_filter == NULL) + return -ENOTTY; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + + if (geomagnetic_multi_lock() < 0) + return count; + + hwdep_driver.get_filter(&filter); + filter.len = value; + if (hwdep_driver.set_filter(&filter) == 0) + data->filter_len = value; + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_filter_noise_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + int rt; + + geomagnetic_multi_lock(); + + rt = sprintf(buf, "%d %d %d\n", + data->filter_noise[0], + data->filter_noise[1], data->filter_noise[2]); + + geomagnetic_multi_unlock(); + + return rt; +} + +static ssize_t +geomagnetic_filter_noise_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct yas_mag_filter filter; + struct geomagnetic_data *data = input_get_drvdata(input_raw); + int32_t filter_noise[3]; + + geomagnetic_multi_lock(); + + sscanf(buf, "%d %d %d", + &filter_noise[0], &filter_noise[1], &filter_noise[2]); + hwdep_driver.get_filter(&filter); + memcpy(filter.noise, filter_noise, sizeof(filter.noise)); + if (hwdep_driver.set_filter(&filter) == 0) + memcpy(data->filter_noise, filter_noise, + sizeof(data->filter_noise)); + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_filter_threshold_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + int32_t filter_threshold; + + geomagnetic_multi_lock(); + + filter_threshold = data->filter_threshold; + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d\n", filter_threshold); +} + +static ssize_t +geomagnetic_filter_threshold_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + struct yas_mag_filter filter; + unsigned long value; + int error; + + if (hwdep_driver.get_filter == NULL || hwdep_driver.set_filter == NULL) + return -ENOTTY; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + + if (geomagnetic_multi_lock() < 0) + return count; + + hwdep_driver.get_filter(&filter); + filter.threshold = value; + if (hwdep_driver.set_filter(&filter) == 0) + data->filter_threshold = value; + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_position_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (hwdep_driver.get_position == NULL) + return -ENOTTY; + return sprintf(buf, "%d\n", hwdep_driver.get_position()); +} + +static ssize_t +geomagnetic_position_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long value; + int error; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + + if (hwdep_driver.set_position == NULL) + return -ENOTTY; + hwdep_driver.set_position(value); + + return count; +} + +static ssize_t +geomagnetic_data_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + int rt; + + rt = sprintf(buf, "%d %d %d\n", + atomic_read(&data->last_data[0]), + atomic_read(&data->last_data[1]), + atomic_read(&data->last_data[2])); + + return rt; +} + +static ssize_t +geomagnetic_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + int rt; + + rt = sprintf(buf, "%d\n", atomic_read(&data->last_status)); + + return rt; +} + +static ssize_t +geomagnetic_status_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + static int16_t cnt = 1; +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev; +#endif + int accuracy = 0; + int code = 0; + int value = 0; + + geomagnetic_multi_lock(); + + sscanf(buf, "%d", &accuracy); + if (0 <= accuracy && accuracy <= 3) + atomic_set(&data->last_status, accuracy); + code |= YAS_REPORT_CALIB_OFFSET_CHANGED; + value = (cnt++ << 16) | (code); + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + mkev(&ev, EV_ABS, ABS_RAW_REPORT, value); + sensor_event(&data->raw_devfile_list, &ev, 1); +#else + input_report_abs(data->input_raw, ABS_RAW_REPORT, value); + input_sync(data->input_raw); +#endif + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_wake_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_data = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_data); + static int16_t cnt = 1; +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev[1]; + make_event(ev, EV_ABS, ABS_WAKE, cnt++); + sensor_event(&data->devfile_list, ev, 1); +#else + input_report_abs(data->input_data, ABS_WAKE, cnt++); + input_sync(data->input_data); +#endif + + return count; +} + +#if DEBUG + +static int geomagnetic_suspend(struct i2c_client *client, pm_message_t mesg); +static int geomagnetic_resume(struct i2c_client *client); + +static ssize_t +geomagnetic_debug_suspend_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input); + + return sprintf(buf, "%d\n", data->suspend); +} + +static ssize_t +geomagnetic_debug_suspend_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long suspend; + int error; + + error = strict_strtoul(buf, 10, &suspend); + if (unlikely(error)) + return error; + + if (suspend) { + pm_message_t msg; + memset(&msg, 0, sizeof(msg)); + geomagnetic_suspend(this_client, msg); + } else + geomagnetic_resume(this_client); + + return count; +} + +#endif /* DEBUG */ + +static DEVICE_ATTR(delay, S_IRUGO | S_IWUSR | S_IWGRP, + geomagnetic_delay_show, geomagnetic_delay_store); +static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP, + geomagnetic_enable_show, geomagnetic_enable_store); +static DEVICE_ATTR(filter_enable, S_IRUGO | S_IWUSR | S_IWGRP, + geomagnetic_filter_enable_show, + geomagnetic_filter_enable_store); +static DEVICE_ATTR(filter_len, S_IRUGO | S_IWUSR | S_IWGRP, + geomagnetic_filter_len_show, geomagnetic_filter_len_store); +static DEVICE_ATTR(filter_threshold, S_IRUGO | S_IWUSR | S_IWGRP, + geomagnetic_filter_threshold_show, + geomagnetic_filter_threshold_store); +static DEVICE_ATTR(filter_noise, S_IRUGO | S_IWUSR | S_IWGRP, + geomagnetic_filter_noise_show, + geomagnetic_filter_noise_store); +static DEVICE_ATTR(data, S_IRUGO, geomagnetic_data_show, NULL); +static DEVICE_ATTR(status, S_IRUGO|S_IWUSR|S_IWGRP, geomagnetic_status_show, + geomagnetic_status_store); +static DEVICE_ATTR(wake, S_IWUSR | S_IWGRP, NULL, geomagnetic_wake_store); +static DEVICE_ATTR(position, S_IRUGO | S_IWUSR, + geomagnetic_position_show, geomagnetic_position_store); +#if DEBUG +static DEVICE_ATTR(debug_suspend, S_IRUGO | S_IWUSR, + geomagnetic_debug_suspend_show, + geomagnetic_debug_suspend_store); +#endif /* DEBUG */ + +static struct attribute *geomagnetic_attributes[] = { + &dev_attr_delay.attr, + &dev_attr_enable.attr, + &dev_attr_filter_enable.attr, + &dev_attr_filter_len.attr, + &dev_attr_filter_threshold.attr, + &dev_attr_filter_noise.attr, + &dev_attr_data.attr, + &dev_attr_status.attr, + &dev_attr_wake.attr, + &dev_attr_position.attr, +#if DEBUG + &dev_attr_debug_suspend.attr, +#endif /* DEBUG */ + NULL +}; + +static struct attribute_group geomagnetic_attribute_group = { + .attrs = geomagnetic_attributes +}; + +static ssize_t +geomagnetic_raw_threshold_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + int threshold; + + geomagnetic_multi_lock(); + + threshold = data->threshold; + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d\n", threshold); +} + +static ssize_t +geomagnetic_raw_threshold_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + unsigned long value; + int error; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + + geomagnetic_multi_lock(); + + if (0 <= value && value <= 2) { +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev[1]; + make_event(ev, EV_ABS, ABS_RAW_THRESHOLD, value); + sensor_event(&data->raw_devfile_list, ev, 1); +#endif + data->threshold = value; +#ifndef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + input_report_abs(data->input_raw, ABS_RAW_THRESHOLD, value); + input_sync(data->input_raw); +#endif + } + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_raw_distortion_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + int rt; + + geomagnetic_multi_lock(); + + rt = sprintf(buf, "%d %d %d\n", + data->distortion[0], + data->distortion[1], data->distortion[2]); + + geomagnetic_multi_unlock(); + + return rt; +} + +static ssize_t +geomagnetic_raw_distortion_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + int32_t distortion[3]; + static int32_t val = 1; + int i; + + geomagnetic_multi_lock(); + + sscanf(buf, "%d %d %d", &distortion[0], &distortion[1], &distortion[2]); + if (distortion[0] > 0 && distortion[1] > 0 && distortion[2] > 0) { +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev[1]; + make_event(ev, EV_ABS, ABS_RAW_DISTORTION, val++); + sensor_event(&data->raw_devfile_list, ev, 1); +#endif + for (i = 0; i < 3; i++) + data->distortion[i] = distortion[i]; +#ifndef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + input_report_abs(data->input_raw, ABS_RAW_DISTORTION, val++); + input_sync(data->input_raw); +#endif + } + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_raw_shape_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + int shape; + + geomagnetic_multi_lock(); + + shape = data->shape; + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d\n", shape); +} + +static ssize_t +geomagnetic_raw_shape_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + unsigned long value; + int error; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + + geomagnetic_multi_lock(); + + if (0 == value || value == 1) { +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev[1]; + make_event(ev, EV_ABS, ABS_RAW_SHAPE, value); + sensor_event(&data->raw_devfile_list, ev, 1); +#endif + data->shape = value; +#ifndef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + input_report_abs(data->input_raw, ABS_RAW_SHAPE, value); + input_sync(data->input_raw); +#endif + } + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_raw_offsets_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + struct yas_mag_offset offset; + int accuracy; + + geomagnetic_multi_lock(); + + offset = data->driver_offset; + accuracy = atomic_read(&data->last_status); + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d %d %d %d %d %d %d\n", + offset.hard_offset[0], + offset.hard_offset[1], + offset.hard_offset[2], + offset.calib_offset.v[0], + offset.calib_offset.v[1], + offset.calib_offset.v[2], accuracy); +} + +static ssize_t +geomagnetic_raw_offsets_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + struct yas_mag_offset offset; + int32_t hard_offset[3]; + int i, accuracy; + + geomagnetic_multi_lock(); + + sscanf(buf, "%d %d %d %d %d %d %d", + &hard_offset[0], + &hard_offset[1], + &hard_offset[2], + &offset.calib_offset.v[0], + &offset.calib_offset.v[1], &offset.calib_offset.v[2], &accuracy); + if (0 <= accuracy && accuracy <= 3) { + for (i = 0; i < 3; i++) + offset.hard_offset[i] = (int8_t) hard_offset[i]; + + if (hwdep_driver.set_offset(&offset) == 0) { + atomic_set(&data->last_status, accuracy); + data->driver_offset = offset; + } + } + + geomagnetic_multi_unlock(); + + return count; +} + +#ifdef YAS_MAG_MANUAL_OFFSET +static ssize_t +geomagnetic_raw_manual_offsets_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + struct yas_vector offset; + + geomagnetic_multi_lock(); + + offset = data->manual_offset; + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d %d %d\n", offset.v[0], offset.v[1], + offset.v[2]); +} + +static ssize_t +geomagnetic_raw_manual_offsets_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + struct yas_vector offset; + + geomagnetic_multi_lock(); + + sscanf(buf, "%d %d %d", &offset.v[0], &offset.v[1], &offset.v[2]); + if (hwdep_driver.set_manual_offset(&offset) == 0) + data->manual_offset = offset; + + geomagnetic_multi_unlock(); + + return count; +} +#endif + +static ssize_t +geomagnetic_raw_static_matrix_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + struct yas_matrix matrix; + + geomagnetic_multi_lock(); + + matrix = data->static_matrix; + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d %d %d %d %d %d %d %d %d\n", + matrix.matrix[0], matrix.matrix[1], matrix.matrix[2], + matrix.matrix[3], matrix.matrix[4], matrix.matrix[5], + matrix.matrix[6], matrix.matrix[7], matrix.matrix[8]); +} + +static ssize_t +geomagnetic_raw_static_matrix_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + struct yas_matrix matrix; + + geomagnetic_multi_lock(); + + sscanf(buf, "%d %d %d %d %d %d %d %d %d", + &matrix.matrix[0], &matrix.matrix[1], &matrix.matrix[2], + &matrix.matrix[3], &matrix.matrix[4], &matrix.matrix[5], + &matrix.matrix[6], &matrix.matrix[7], &matrix.matrix[8]); + if (hwdep_driver.set_static_matrix(&matrix) == 0) + data->static_matrix = matrix; + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_raw_dynamic_matrix_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + struct yas_matrix matrix; + + geomagnetic_multi_lock(); + + matrix = data->dynamic_matrix; + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d %d %d %d %d %d %d %d %d\n", + matrix.matrix[0], matrix.matrix[1], matrix.matrix[2], + matrix.matrix[3], matrix.matrix[4], matrix.matrix[5], + matrix.matrix[6], matrix.matrix[7], matrix.matrix[8]); +} + +static ssize_t +geomagnetic_raw_dynamic_matrix_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + struct yas_matrix matrix; + + geomagnetic_multi_lock(); + + sscanf(buf, "%d %d %d %d %d %d %d %d %d", + &matrix.matrix[0], &matrix.matrix[1], &matrix.matrix[2], + &matrix.matrix[3], &matrix.matrix[4], &matrix.matrix[5], + &matrix.matrix[6], &matrix.matrix[7], &matrix.matrix[8]); + if (hwdep_driver.set_dynamic_matrix(&matrix) == 0) + data->dynamic_matrix = matrix; + + geomagnetic_multi_unlock(); + + return count; +} + +static ssize_t +geomagnetic_raw_ellipsoid_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + int ellipsoid_mode; + + geomagnetic_multi_lock(); + + ellipsoid_mode = data->ellipsoid_mode; + + geomagnetic_multi_unlock(); + + return sprintf(buf, "%d\n", ellipsoid_mode); +} + +static ssize_t +geomagnetic_raw_ellipsoid_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_raw = to_input_dev(dev); + struct geomagnetic_data *data = input_get_drvdata(input_raw); + unsigned long value; + int error; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + value = !(!value); +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev[1]; +#endif + + geomagnetic_multi_lock(); + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + make_event(ev, EV_ABS, ABS_RAW_MODE, value); + sensor_event(&data->raw_devfile_list, ev, 1); +#endif + data->ellipsoid_mode = value; +#ifndef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + input_report_abs(data->input_raw, ABS_RAW_MODE, value); + input_sync(data->input_raw); +#endif + + geomagnetic_multi_unlock(); + + return count; +} + +#ifdef SYSFS_PCBTEST + +static int +pcbtest_i2c_write(uint8_t slave, uint8_t addr, const uint8_t *buf, int len) +{ + return geomagnetic_i2c_write(addr, buf, len); +} + +static int +pcbtest_i2c_read(uint8_t slave, uint8_t addr, uint8_t *buf, int len) +{ + return geomagnetic_i2c_read(addr, buf, len); +} + +static struct yas_pcb_test pcbtest = { + .callback = { + .power_on = NULL, + .power_off = NULL, + .i2c_open = geomagnetic_i2c_open, + .i2c_close = geomagnetic_i2c_close, + .i2c_read = pcbtest_i2c_read, + .i2c_write = pcbtest_i2c_write, + .msleep = geomagnetic_msleep, + .read_intpin = NULL, + }, +}; + + +static ssize_t +geomagnetic_raw_self_test_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct geomagnetic_data *data = i2c_get_clientdata(this_client); + int id, x, y1, y2, dir, sx, sy, ohx, ohy, ohz; + int err1, err2, err3, err4, err5, err6, err7; + + if (data->noise_test_init) + pcbtest.power_off(); + err1 = pcbtest.power_on_and_device_check(&id); + err3 = pcbtest.initialization(); + err4 = + pcbtest.offset_control_measurement_and_set_offset_register( + &x, &y1, &y2); + err5 = pcbtest.direction_measurement(&dir); + err6 = + pcbtest.sensitivity_measurement_of_magnetic_sensor_by_test_coil( + &sx, &sy); + err7 = pcbtest.magnetic_field_level_check(&ohx, &ohy, &ohz); + err2 = pcbtest.power_off(); + data->noise_test_init = 0; + if (unlikely(id != 0x2)) + err1 = -1; + if (unlikely(x < -30 || x > 30)) + err4 = -1; + if (unlikely(y1 < -30 || y1 > 30)) + err4 = -1; + if (unlikely(y2 < -30 || y2 > 30)) + err4 = -1; + if (unlikely(sx < 17 || sy < 22)) + err6 = -1; + if (unlikely(ohx < -600 || ohx > 600)) + err7 = -1; + if (unlikely(ohy < -600 || ohy > 600)) + err7 = -1; + if (unlikely(ohz < -600 || ohz > 600)) + err7 = -1; + + pr_info("%s\n" + "Test1 - err = %d, id = %d\n" + "Test3 - err = %d\n" + "Test4 - err = %d, offset = %d,%d,%d\n" + "Test5 - err = %d, direction = %d\n" + "Test6 - err = %d, sensitivity = %d,%d\n" + "Test7 - err = %d, offset = %d,%d,%d\n" + "Test2 - err = %d\n", __func__, + err1, id, err3, err4, x, y1, y2, err5, dir, err6, sx, sy, + err7, ohx, ohy, ohz, err2); + + return sprintf(buf, + "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + err1, id, err3, err4, x, y1, y2, err5, dir, err6, sx, + sy, err7, ohx, ohy, ohz, err2); +} + +static ssize_t +geomagnetic_raw_self_test_noise_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct geomagnetic_data *data = i2c_get_clientdata(this_client); + int id, x, y1, y2, dir, hx0, hy0, hz0; + int err8; +#if CONFIG_MACH_KONA_SENSOR + pcbtest.power_on_and_device_check(&id); + pcbtest.initialization(); + pcbtest.offset_control_measurement_and_set_offset_register( + &x, &y1, &y2); +#else + if (!data->noise_test_init) { + pcbtest.power_on_and_device_check(&id); + pcbtest.initialization(); + pcbtest.offset_control_measurement_and_set_offset_register( + &x, &y1, &y2); + } +#endif + pcbtest.direction_measurement(&dir); + err8 = pcbtest.noise_level_check(&hx0, &hy0, &hz0); + if (err8 < 0) { + pr_err("%s: err8=%d\n", __func__, err8); + hx0 = 0; + hy0 = 0; + hz0 = 0; + } + usleep_range(3000, 3100); + data->noise_test_init = 1; + pr_debug("%s: %d, %d, %d\n", __func__, hx0, hy0, hz0); + return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n", hx0, hy0, hz0); +} + +static DEVICE_ATTR(self_test, S_IRUSR, geomagnetic_raw_self_test_show, NULL); +static DEVICE_ATTR(self_test_noise, S_IRUSR, + geomagnetic_raw_self_test_noise_show, NULL); + +#endif + + +static DEVICE_ATTR(threshold, S_IRUGO | S_IWUSR, + geomagnetic_raw_threshold_show, + geomagnetic_raw_threshold_store); +static DEVICE_ATTR(distortion, S_IRUGO | S_IWUSR, + geomagnetic_raw_distortion_show, + geomagnetic_raw_distortion_store); +static DEVICE_ATTR(shape, S_IRUGO | S_IWUSR, geomagnetic_raw_shape_show, + geomagnetic_raw_shape_store); +static DEVICE_ATTR(offsets, S_IRUGO | S_IWUSR, geomagnetic_raw_offsets_show, + geomagnetic_raw_offsets_store); +#ifdef YAS_MAG_MANUAL_OFFSET +static DEVICE_ATTR(manual_offsets, S_IRUGO | S_IWUSR, + geomagnetic_raw_manual_offsets_show, + geomagnetic_raw_manual_offsets_store); +#endif +static DEVICE_ATTR(static_matrix, S_IRUGO | S_IWUSR, + geomagnetic_raw_static_matrix_show, + geomagnetic_raw_static_matrix_store); +static DEVICE_ATTR(dynamic_matrix, S_IRUGO | S_IWUSR, + geomagnetic_raw_dynamic_matrix_show, + geomagnetic_raw_dynamic_matrix_store); +static DEVICE_ATTR(ellipsoid_mode, S_IRUGO | S_IWUSR, + geomagnetic_raw_ellipsoid_mode_show, + geomagnetic_raw_ellipsoid_mode_store); +static struct attribute *geomagnetic_raw_attributes[] = { +#ifdef SYSFS_PCBTEST + &dev_attr_self_test.attr, + &dev_attr_self_test_noise.attr, +#endif + &dev_attr_threshold.attr, + &dev_attr_distortion.attr, + &dev_attr_shape.attr, + &dev_attr_offsets.attr, +#ifdef YAS_MAG_MANUAL_OFFSET + &dev_attr_manual_offsets.attr, +#endif + &dev_attr_static_matrix.attr, + &dev_attr_dynamic_matrix.attr, + &dev_attr_ellipsoid_mode.attr, + NULL +}; + +static struct attribute_group geomagnetic_raw_attribute_group = { + .attrs = geomagnetic_raw_attributes +}; +static struct device_attribute dev_attr_magnetic_sensor_selftest = + __ATTR(selftest, S_IRUSR | S_IRGRP, + geomagnetic_raw_self_test_show, NULL); + +static struct device_attribute dev_attr_magnetic_sensor_raw_data = + __ATTR(raw_data, S_IRUSR | S_IRGRP, + geomagnetic_raw_self_test_noise_show, NULL); + +static ssize_t magnetic_vendor_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%s\n", "YAMAHA"); +} +static struct device_attribute dev_attr_magnetic_sensor_vendor = + __ATTR(vendor, S_IRUSR | S_IRGRP, magnetic_vendor_show, NULL); + +static ssize_t magnetic_name_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct geomagnetic_data *data = i2c_get_clientdata(this_client); + int ret; + if (data->dev_id == YAS_YAS532_DEVICE_ID) + ret = sprintf(buf, "%s\n", "YAS532"); + else + ret = sprintf(buf, "%s\n", "YAS530C"); + return ret; +} +static struct device_attribute dev_attr_magnetic_sensor_name = + __ATTR(name, S_IRUSR | S_IRGRP, magnetic_name_show, NULL); + +static struct device_attribute *magnetic_sensor_attrs[] = { + &dev_attr_magnetic_sensor_selftest, + &dev_attr_magnetic_sensor_raw_data, + &dev_attr_magnetic_sensor_vendor, + &dev_attr_magnetic_sensor_name, + NULL, +}; + + +/* Interface Functions for Lower Layer */ +#ifdef YAS_MAG_MANUAL_OFFSET +void geomagnetic_manual_offset(void) +{ + struct geomagnetic_data *data = i2c_get_clientdata(this_client); + struct yas_vector offset; + if (data->mag_pdata->chg_status == CABLE_TYPE_NONE) { + offset = data->mag_pdata->full_offset; + if (hwdep_driver.set_manual_offset(&offset) == 0) + data->manual_offset = offset; + } else if (data->mag_pdata->chg_status == CABLE_TYPE_USB) { + offset = data->mag_pdata->usb_offset; + if (hwdep_driver.set_manual_offset(&offset) == 0) + data->manual_offset = offset; + } else if (data->mag_pdata->chg_status == CABLE_TYPE_AC) { + offset = data->mag_pdata->ta_offset; + if (hwdep_driver.set_manual_offset(&offset) == 0) + data->manual_offset = offset; + } else { + offset = data->mag_pdata->full_offset; + if (hwdep_driver.set_manual_offset(&offset) == 0) + data->manual_offset = offset; + } + data->mag_pdata->offset_enable = 0; +} +#endif + +static int geomagnetic_work(struct yas_mag_data *magdata) +{ + struct geomagnetic_data *data = i2c_get_clientdata(this_client); + uint32_t time_delay_ms = 100; + static int cnt; + int rt, i, accuracy; +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev[5]; + struct timeval tv; +#endif + +#ifdef YAS_MAG_MANUAL_OFFSET + if (data->mag_pdata) { + if (data->mag_pdata->offset_enable) + geomagnetic_manual_offset(); + } +#endif + + if (hwdep_driver.measure == NULL || hwdep_driver.get_offset == NULL) + return time_delay_ms; + + rt = hwdep_driver.measure(magdata, &time_delay_ms); + if (rt < 0) + YLOGE(("measure failed[%d]\n", rt)); + YLOGD(("xy1y2 [%d][%d][%d] raw[%d][%d][%d]\n", + magdata->xy1y2.v[0], magdata->xy1y2.v[1], magdata->xy1y2.v[2], + magdata->xyz.v[0], magdata->xyz.v[1], magdata->xyz.v[2])); + + if (rt >= 0) { + accuracy = atomic_read(&data->last_status); + + if ((rt & YAS_REPORT_OVERFLOW_OCCURED) + || (rt & YAS_REPORT_HARD_OFFSET_CHANGED) + || (rt & YAS_REPORT_CALIB_OFFSET_CHANGED)) { + static uint16_t count = 1; + int code = 0; + int value = 0; + + hwdep_driver.get_offset(&data->driver_offset); + if (rt & YAS_REPORT_OVERFLOW_OCCURED) { + atomic_set(&data->last_status, 0); + accuracy = 0; + } + + /* report event */ + code |= (rt & YAS_REPORT_OVERFLOW_OCCURED); + code |= (rt & YAS_REPORT_HARD_OFFSET_CHANGED); + code |= (rt & YAS_REPORT_CALIB_OFFSET_CHANGED); + value = (count++ << 16) | (code); +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + make_event(ev, EV_ABS, ABS_RAW_REPORT, value); + sensor_event(&data->raw_devfile_list, ev, 1); +#else + input_report_abs(data->input_raw, ABS_RAW_REPORT, + value); + input_sync(data->input_raw); +#endif + } + + if (rt & YAS_REPORT_DATA) { +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + get_time_stamp(&tv); + make_event_w_time(&ev[0], EV_ABS, ABS_X, + magdata->xyz.v[0], &tv); + make_event_w_time(&ev[1], EV_ABS, ABS_Y, + magdata->xyz.v[1], &tv); + make_event_w_time(&ev[2], EV_ABS, ABS_Z, + magdata->xyz.v[2], &tv); + make_event_w_time(&ev[3], EV_ABS, ABS_STATUS, accuracy, + &tv); + make_event_w_time(&ev[4], EV_SYN, 0, 0, &tv); + sensor_event(&data->devfile_list, ev, 5); +#else + /* report magnetic data in [nT] */ + input_report_abs(data->input_data, ABS_X, + magdata->xyz.v[0]); + input_report_abs(data->input_data, ABS_Y, + magdata->xyz.v[1]); + input_report_abs(data->input_data, ABS_Z, + magdata->xyz.v[2]); + if (atomic_read(&data->last_data[0]) == + magdata->xyz.v[0] + && atomic_read(&data->last_data[1]) == + magdata->xyz.v[1] + && atomic_read(&data->last_data[2]) == + magdata->xyz.v[2]) { + input_report_abs(data->input_data, ABS_RUDDER, + cnt++); + } + input_report_abs(data->input_data, ABS_STATUS, + accuracy); + input_sync(data->input_data); +#endif + + for (i = 0; i < 3; i++) + atomic_set(&data->last_data[i], + magdata->xyz.v[i]); + } + + if (rt & YAS_REPORT_CALIB) { +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + get_time_stamp(&tv); + make_event_w_time(&ev[0], EV_ABS, ABS_X, + magdata->raw.v[0], &tv); + make_event_w_time(&ev[1], EV_ABS, ABS_Y, + magdata->raw.v[1], &tv); + make_event_w_time(&ev[2], EV_ABS, ABS_Z, + magdata->raw.v[2], &tv); + make_event_w_time(&ev[3], EV_SYN, 0, 0, &tv); + sensor_event(&data->raw_devfile_list, ev, 4); +#else + /* report raw magnetic data */ + input_report_abs(data->input_raw, ABS_X, + magdata->raw.v[0]); + input_report_abs(data->input_raw, ABS_Y, + magdata->raw.v[1]); + input_report_abs(data->input_raw, ABS_Z, + magdata->raw.v[2]); + input_sync(data->input_raw); +#endif + } + } else { + time_delay_ms = 100; + } + + return time_delay_ms; + +} + +static void geomagnetic_input_work_func(struct work_struct *work) +{ + struct geomagnetic_data *data = + container_of((struct delayed_work *)work, + struct geomagnetic_data, work); + uint32_t time_delay_ms; + struct yas_mag_data magdata; + + time_delay_ms = geomagnetic_work(&magdata); + + if (time_delay_ms > 60) + schedule_delayed_work(&data->work, + msecs_to_jiffies(time_delay_ms)); + else { + if (time_delay_ms > 0) + usleep_range(time_delay_ms * 1000, + time_delay_ms * 1100); + schedule_delayed_work(&data->work, 0); + } +} + +static int geomagnetic_suspend(struct i2c_client *client, pm_message_t mesg) +{ + struct geomagnetic_data *data = i2c_get_clientdata(client); + + if (atomic_read(&data->enable)) + cancel_delayed_work_sync(&data->work); +#if DEBUG + data->suspend = 1; +#endif + + return 0; +} + +static int geomagnetic_resume(struct i2c_client *client) +{ + struct geomagnetic_data *data = i2c_get_clientdata(client); + + if (atomic_read(&data->enable)) + schedule_delayed_work(&data->work, 0); +#if DEBUG + data->suspend = 0; +#endif + + return 0; +} + +static int +geomagnetic_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct geomagnetic_data *data = NULL; + struct input_dev *input_data = NULL, *input_raw = NULL; + int rt, sysfs_created = 0, sysfs_raw_created = 0; + int data_registered = 0, raw_registered = 0, i; + struct yas_mag_filter filter; + struct mag_platform_data *pdata; + + pr_err("%s, is called\n", __func__); + + i2c_set_clientdata(client, NULL); + data = kzalloc(sizeof(struct geomagnetic_data), GFP_KERNEL); + if (data == NULL) { + rt = -ENOMEM; + goto err; + } + + pdata = (struct mag_platform_data *) client->dev.platform_data; + data->mag_pdata = pdata; + + if (pdata) { + if (pdata->power_on) + pdata->power_on(true); + } + data->threshold = YAS_DEFAULT_MAGCALIB_THRESHOLD; + for (i = 0; i < 3; i++) + data->distortion[i] = YAS_DEFAULT_MAGCALIB_DISTORTION; + data->shape = 0; + atomic_set(&data->enable, 0); + for (i = 0; i < 3; i++) + atomic_set(&data->last_data[i], 0); + atomic_set(&data->last_status, 0); + INIT_DELAYED_WORK(&data->work, geomagnetic_input_work_func); + sema_init(&data->driver_lock, 1); + sema_init(&data->multi_lock, 1); + + input_data = input_allocate_device(); + if (input_data == NULL) { + rt = -ENOMEM; + YLOGE(("mag Failed to allocate input_data device\n")); + goto err; + } + + input_data->name = GEOMAGNETIC_INPUT_NAME; + input_data->id.bustype = BUS_I2C; + set_bit(EV_ABS, input_data->evbit); + input_set_abs_params(input_data, ABS_X, 0x80000000, 0x7fffffff, 0, 0); + input_set_abs_params(input_data, ABS_Y, 0x80000000, 0x7fffffff, 0, 0); + input_set_abs_params(input_data, ABS_Z, 0x80000000, 0x7fffffff, 0, 0); + input_set_abs_params(input_data, ABS_RUDDER, 0x80000000, 0x7fffffff, 0, + 0); + input_set_abs_params(input_data, ABS_STATUS, 0, 3, 0, 0); + input_set_abs_params(input_data, ABS_WAKE, 0x80000000, 0x7fffffff, 0, + 0); + input_data->dev.parent = &client->dev; + + rt = input_register_device(input_data); + if (rt) { + YLOGE(("mag: Unable to reg input_data %s\n", input_data->name)); + goto err; + } + data_registered = 1; + + rt = sysfs_create_group(&input_data->dev.kobj, + &geomagnetic_attribute_group); + if (rt) { + YLOGE(("mag sysfs_create failed[%s]\n", input_data->name)); + goto err; + } + sysfs_created = 1; + + input_raw = input_allocate_device(); + if (input_raw == NULL) { + rt = -ENOMEM; + YLOGE(("mag Failed to alloc input_raw dev\n")); + goto err; + } + + input_raw->name = GEOMAGNETIC_INPUT_RAW_NAME; + input_raw->id.bustype = BUS_I2C; + set_bit(EV_ABS, input_raw->evbit); + input_set_abs_params(input_raw, ABS_X, 0x80000000, 0x7fffffff, 0, 0); + input_set_abs_params(input_raw, ABS_Y, 0x80000000, 0x7fffffff, 0, 0); + input_set_abs_params(input_raw, ABS_Z, 0x80000000, 0x7fffffff, 0, 0); + input_set_abs_params(input_raw, ABS_RAW_DISTORTION, 0, 0x7fffffff, 0, + 0); + input_set_abs_params(input_raw, ABS_RAW_THRESHOLD, 0, 2, 0, 0); + input_set_abs_params(input_raw, ABS_RAW_SHAPE, 0, 1, 0, 0); + input_set_abs_params(input_raw, ABS_RAW_MODE, 0, 1, 0, 0); + input_set_abs_params(input_raw, ABS_RAW_REPORT, 0x80000000, 0x7fffffff, + 0, 0); + input_raw->dev.parent = &client->dev; + + rt = input_register_device(input_raw); + if (rt) { + YLOGE(("mag: Unable to reg input_raw dev\n")); + goto err; + } + raw_registered = 1; + + rt = sysfs_create_group(&input_raw->dev.kobj, + &geomagnetic_raw_attribute_group); + if (rt) { + YLOGE(("geomagnetic_probe: sysfs_create_group failed[%s]\n", + input_data->name)); + goto err; + } + sysfs_raw_created = 1; + + this_client = client; + data->input_raw = input_raw; + data->input_data = input_data; + input_set_drvdata(input_data, data); + input_set_drvdata(input_raw, data); + i2c_set_clientdata(client, data); + rt = yas_mag_driver_init(&hwdep_driver); + if (rt < 0) { + YLOGE(("yas_mag_driver_init failed[%d]\n", rt)); + goto err; + } + if (hwdep_driver.init != NULL) { + rt = hwdep_driver.init(); + if (rt < 0) { + YLOGE(("hwdep_driver.init() failed[%d]\n", rt)); + goto err; + } + } + if (hwdep_driver.set_position != NULL) { + if (pdata) { + if (pdata->orientation) { + pr_info("%s: set from board file.\n", __func__); + if (hwdep_driver. + set_position(pdata->orientation + - YAS532_POSITION_OFFSET) < 0) { + pr_err("set_position failed %d\n", rt); + goto err; + } + } else { + pr_info("%s: set from defconfig.\n", __func__); + if (hwdep_driver. + set_position( + CONFIG_INPUT_YAS_MAGNETOMETER_POSITION) + < 0) { + pr_err("set_position failed %d\n", rt); + goto err; + } + } + } else { + if (hwdep_driver. + set_position( + CONFIG_INPUT_YAS_MAGNETOMETER_POSITION) + < 0) { + pr_err("set_position() failed[%d]\n", rt); + goto err; + } + } + pr_info("%s: yas magnetic position is %d\n", __func__, + hwdep_driver.get_position()); + } + if (hwdep_driver.get_offset != NULL) { + if (hwdep_driver.get_offset(&data->driver_offset) < 0) { + YLOGE(("hwdep_driver get_driver_state failed\n")); + goto err; + } + } + if (hwdep_driver.get_delay != NULL) + data->delay = hwdep_driver.get_delay(); + + if (hwdep_driver.set_filter_enable != NULL) { + /* default to enable */ + if (hwdep_driver.set_filter_enable(1) == 0) + data->filter_enable = 1; + } + if (hwdep_driver.get_filter != NULL) { + if (hwdep_driver.get_filter(&filter) < 0) { + YLOGE(("hwdep_driver get_filter failed\n")); + goto err; + } + data->filter_len = filter.len; + for (i = 0; i < 3; i++) + data->filter_noise[i] = filter.noise[i]; + data->filter_threshold = filter.threshold; + } + if (hwdep_driver.get_static_matrix != NULL) + hwdep_driver.get_static_matrix(&data->static_matrix); + if (hwdep_driver.get_dynamic_matrix != NULL) + hwdep_driver.get_dynamic_matrix(&data->dynamic_matrix); +#ifdef SYSFS_PCBTEST + rt = yas_pcb_test_init(&pcbtest); + if (rt < 0) { + YLOGE(("yas_pcb_test_init failed[%d]\n", rt)); + goto err; + } +#endif +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + INIT_LIST_HEAD(&data->devfile_list); + INIT_LIST_HEAD(&data->raw_devfile_list); + if (misc_register(&sensor_devfile) < 0) + goto err; + if (misc_register(&sensor_raw_devfile) < 0) { + misc_deregister(&sensor_devfile); + goto err; + } +#endif + + rt = + geomagnetic_i2c_read(YAS_REGADDR_DEVICE_ID, &data->dev_id, 1); + if (rt) { + pr_err("%s: cound not read device id(%d).\n", + __func__, rt); + goto err; + } else + pr_info("%s: yamaha magnetic sensor id = %x\n", + __func__, data->dev_id); + + rt = sensors_register(data->magnetic_sensor_device, + NULL, magnetic_sensor_attrs, + "magnetic_sensor"); + if (rt) { + pr_err("%s: cound not register magnetic sensor device(%d).\n", + __func__, rt); + goto out_sensor_register_failed; + } + + return 0; + +out_sensor_register_failed: +err: + if (data != NULL) { + if (input_raw != NULL) { + if (sysfs_raw_created) + sysfs_remove_group(&input_raw->dev.kobj, + &geomagnetic_raw_attribute_group); + + if (raw_registered) + input_unregister_device(input_raw); + else + input_free_device(input_raw); + } + if (input_data != NULL) { + if (sysfs_created) + sysfs_remove_group(&input_data->dev.kobj, + &geomagnetic_attribute_group); + if (data_registered) + input_unregister_device(input_data); + else + input_free_device(input_data); + } + if (pdata) { + if (pdata->power_on) + pdata->power_on(false); + } + kfree(data); + } + + return rt; +} + +static int geomagnetic_remove(struct i2c_client *client) +{ + struct geomagnetic_data *data = i2c_get_clientdata(client); + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + misc_deregister(&sensor_devfile); + misc_deregister(&sensor_raw_devfile); +#endif + if (data != NULL) { + geomagnetic_disable(data); + if (hwdep_driver.term != NULL) + hwdep_driver.term(); + + input_unregister_device(data->input_raw); + sysfs_remove_group(&data->input_data->dev.kobj, + &geomagnetic_attribute_group); + sysfs_remove_group(&data->input_raw->dev.kobj, + &geomagnetic_raw_attribute_group); + input_unregister_device(data->input_data); + kfree(data); + } + + return 0; +} + +static void geomagnetic_shutdown(struct i2c_client *client) +{ + struct geomagnetic_data *data = i2c_get_clientdata(client); + + if (data != NULL) { + geomagnetic_disable(data); + if (data->mag_pdata) { + if (data->mag_pdata->power_on) + data->mag_pdata->power_on(false); + } + } +} + +/* I2C Device Driver */ +static struct i2c_device_id geomagnetic_idtable[] = { + {GEOMAGNETIC_I2C_DEVICE_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, geomagnetic_idtable); + +static struct i2c_driver geomagnetic_i2c_driver = { + .driver = { + .name = GEOMAGNETIC_I2C_DEVICE_NAME, + .owner = THIS_MODULE, + }, + + .id_table = geomagnetic_idtable, + .probe = geomagnetic_probe, + .remove = geomagnetic_remove, + .suspend = geomagnetic_suspend, + .resume = geomagnetic_resume, + .shutdown = geomagnetic_shutdown, +}; + +static int __init geomagnetic_init(void) +{ + return i2c_add_driver(&geomagnetic_i2c_driver); +} + +static void __exit geomagnetic_term(void) +{ + i2c_del_driver(&geomagnetic_i2c_driver); +} + +#ifdef GEOMAGNETIC_PLATFORM_API +static int geomagnetic_api_enable(int enable) +{ + struct geomagnetic_data *data = i2c_get_clientdata(this_client); + int rt; + + if (geomagnetic_multi_lock() < 0) + return -1; + enable = !!enable; + rt = hwdep_driver.set_enable(enable); + if (rt == 0) { + atomic_set(&data->enable, enable); + if (enable) + rt = hwdep_driver.set_delay(20); + } + + geomagnetic_multi_unlock(); + + return rt; +} + +int geomagnetic_api_resume(void) +{ + return geomagnetic_api_enable(1); +} +EXPORT_SYMBOL(geomagnetic_api_resume); + +int geomagnetic_api_suspend(void) +{ + return geomagnetic_api_enable(0); +} +EXPORT_SYMBOL(geomagnetic_api_suspend); + +int geomagnetic_api_read(int *xyz, int *raw, int *xy1y2, int *accuracy) +{ + struct geomagnetic_data *data = i2c_get_clientdata(this_client); + struct yas_mag_data magdata; + int i; + + geomagnetic_work(&magdata); + if (xyz != NULL) { + for (i = 0; i < 3; i++) + xyz[i] = magdata.xyz.v[i]; + } + if (raw != NULL) { + for (i = 0; i < 3; i++) + raw[i] = magdata.raw.v[i]; + } + if (xy1y2 != NULL) { + for (i = 0; i < 3; i++) + xy1y2[i] = magdata.xy1y2.v[i]; + } + if (accuracy != NULL) + *accuracy = atomic_read(&data->last_status); + + return 0; +} +EXPORT_SYMBOL(geomagnetic_api_read); +#endif + +module_init(geomagnetic_init); +module_exit(geomagnetic_term); + +MODULE_AUTHOR("Yamaha Corporation"); +#if YAS_MAG_DRIVER == YAS_MAG_DRIVER_YAS529 +MODULE_DESCRIPTION("YAS529 Geomagnetic Sensor Driver"); +#elif YAS_MAG_DRIVER == YAS_MAG_DRIVER_YAS530 +MODULE_DESCRIPTION("YAS530 Geomagnetic Sensor Driver"); +#elif CONFIG_SENSORS_YAS532 +MODULE_DESCRIPTION("YAS532 Geomagnetic Sensor Driver"); +#endif +MODULE_LICENSE("GPL"); +MODULE_VERSION("4.4.702a"); diff --git a/drivers/sensor/yas_ori_kernel_driver.c b/drivers/sensor/yas_ori_kernel_driver.c new file mode 100644 index 0000000..20003aa --- /dev/null +++ b/drivers/sensor/yas_ori_kernel_driver.c @@ -0,0 +1,695 @@ +/* + * Copyright (c) 2010-2011 Yamaha Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __LINUX_KERNEL_DRIVER__ +#include + +#define SENSOR_NAME "orientation" +#define SENSOR_DEFAULT_DELAY (200) /* 200 ms */ +#define SENSOR_MAX_DELAY (2000) /* 2000 ms */ +#define ABS_STATUS (ABS_BRAKE) +#define ABS_WAKE (ABS_MISC) +#define ABS_CONTROL_REPORT (ABS_THROTTLE) + +static int suspend(void); +static int resume(void); + +struct sensor_data { + struct mutex mutex; + int enabled; + int delay; +#if DEBUG + int suspend; +#endif +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct list_head devfile_list; +#endif +}; + +static struct platform_device *sensor_pdev; +static struct input_dev *this_data; + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE +#include +#define MAX_COUNT (64) + +struct sensor_device { + struct list_head list; + struct mutex lock; + wait_queue_head_t waitq; + struct input_event events[MAX_COUNT]; + int head, num_event; +}; + +static void get_time_stamp(struct timeval *tv) +{ + struct timespec ts; + ktime_get_ts(&ts); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; +} + +static void make_event(struct input_event *ev, int type, int code, int value) +{ + struct timeval tv; + get_time_stamp(&tv); + ev->type = type; + ev->code = code; + ev->value = value; + ev->time = tv; +} + +static void +make_event_w_time(struct input_event *ev, int type, int code, int value, + struct timeval *tv) +{ + ev->type = type; + ev->code = code; + ev->value = value; + ev->time = *tv; +} + +static void sensor_enq(struct sensor_device *kdev, struct input_event *ev) +{ + int idx; + + idx = kdev->head + kdev->num_event; + if (MAX_COUNT <= idx) + idx -= MAX_COUNT; + kdev->events[idx] = *ev; + kdev->num_event++; + if (MAX_COUNT < kdev->num_event) { + kdev->num_event = MAX_COUNT; + kdev->head++; + if (MAX_COUNT <= kdev->head) + kdev->head -= MAX_COUNT; + } +} + +static int sensor_deq(struct sensor_device *kdev, struct input_event *ev) +{ + if (kdev->num_event == 0) + return 0; + + *ev = kdev->events[kdev->head]; + kdev->num_event--; + kdev->head++; + if (MAX_COUNT <= kdev->head) + kdev->head -= MAX_COUNT; + return 1; +} + +static void +sensor_event(struct list_head *devlist, struct input_event *ev, int num) +{ + struct sensor_device *kdev; + int i; + + list_for_each_entry(kdev, devlist, list) { + mutex_lock(&kdev->lock); + for (i = 0; i < num; i++) + sensor_enq(kdev, &ev[i]); + + mutex_unlock(&kdev->lock); + wake_up_interruptible(&kdev->waitq); + } +} + +static ssize_t +sensor_write(struct file *f, const char __user *buf, size_t count, + loff_t *pos) +{ + struct sensor_data *data = input_get_drvdata(this_data); + struct sensor_device *kdev; + struct input_event ev[MAX_COUNT]; + int num, i; + + if (count < sizeof(struct input_event)) + return -EINVAL; + + num = count / sizeof(struct input_event); + if (MAX_COUNT < num) + num = MAX_COUNT; + + if (copy_from_user(ev, buf, num * sizeof(struct input_event))) + return -EFAULT; + + list_for_each_entry(kdev, &data->devfile_list, list) { + mutex_lock(&kdev->lock); + for (i = 0; i < num; i++) + sensor_enq(kdev, &ev[i]); + mutex_unlock(&kdev->lock); + wake_up_interruptible(&kdev->waitq); + } + + return count; +} + +static ssize_t +sensor_read(struct file *f, char __user *buf, size_t count, loff_t *pos) +{ + struct sensor_device *kdev = f->private_data; + int rt, num; + struct input_event ev[MAX_COUNT]; + + if (count < sizeof(struct input_event)) + return -EINVAL; + + rt = wait_event_interruptible(kdev->waitq, kdev->num_event != 0); + if (rt) + return rt; + + mutex_lock(&kdev->lock); + for (num = 0; num < count / sizeof(struct input_event); num++) { + if (!sensor_deq(kdev, &ev[num])) + break; + } + mutex_unlock(&kdev->lock); + + if (copy_to_user(buf, ev, num * sizeof(struct input_event))) + return -EFAULT; + + return num * sizeof(struct input_event); +} + +static unsigned int sensor_poll(struct file *f, struct poll_table_struct *wait) +{ + struct sensor_device *kdev = f->private_data; + + poll_wait(f, &kdev->waitq, wait); + if (kdev->num_event != 0) + return POLLIN | POLLRDNORM; + + return 0; +} + +static int sensor_open(struct inode *inode, struct file *f) +{ + struct sensor_data *data = input_get_drvdata(this_data); + struct sensor_device *kdev; + + kdev = kzalloc(sizeof(struct sensor_device), GFP_KERNEL); + if (!kdev) + return -ENOMEM; + + mutex_init(&kdev->lock); + init_waitqueue_head(&kdev->waitq); + f->private_data = kdev; + kdev->head = 0; + kdev->num_event = 0; + list_add(&kdev->list, &data->devfile_list); + + return 0; +} + +static int sensor_release(struct inode *inode, struct file *f) +{ + struct sensor_device *kdev = f->private_data; + + list_del(&kdev->list); + kfree(kdev); + + return 0; +} + +const struct file_operations sensor_fops = { + .owner = THIS_MODULE, + .open = sensor_open, + .release = sensor_release, + .write = sensor_write, + .read = sensor_read, + .poll = sensor_poll, +}; + +static struct miscdevice sensor_devfile = { + .name = SENSOR_NAME, + .fops = &sensor_fops, + .minor = MISC_DYNAMIC_MINOR, +}; + +#endif + +static int suspend(void) +{ + /* implement suspend of the sensor */ + YLOGD(("%s: suspend\n", SENSOR_NAME)); + + return 0; +} + +static int resume(void) +{ + /* implement resume of the sensor */ + YLOGD(("%s: resume\n", SENSOR_NAME)); + + return 0; +} + +/* Sysfs interface */ +static ssize_t +sensor_delay_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + struct sensor_data *data = input_get_drvdata(input_data); + int delay; + + mutex_lock(&data->mutex); + + delay = data->delay; + + mutex_unlock(&data->mutex); + + return sprintf(buf, "%d\n", delay); +} + +static ssize_t +sensor_delay_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct input_dev *input_data = to_input_dev(dev); + struct sensor_data *data = input_get_drvdata(input_data); + long value; + int error; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev[1]; +#endif + + if (value < 0) + return count; + + if (SENSOR_MAX_DELAY < value) + value = SENSOR_MAX_DELAY; + + mutex_lock(&data->mutex); + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + make_event(ev, EV_ABS, ABS_CONTROL_REPORT, + (data->enabled << 16) | value); + sensor_event(&data->devfile_list, ev, 1); +#endif + data->delay = value; +#ifndef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + input_report_abs(input_data, ABS_CONTROL_REPORT, + (data->enabled << 16) | value); +#endif + + mutex_unlock(&data->mutex); + + return count; +} + +static ssize_t +sensor_enable_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + struct sensor_data *data = input_get_drvdata(input_data); + int enabled; + + mutex_lock(&data->mutex); + + enabled = data->enabled; + + mutex_unlock(&data->mutex); + + return sprintf(buf, "%d\n", enabled); +} + +static ssize_t +sensor_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input_data = to_input_dev(dev); + struct sensor_data *data = input_get_drvdata(input_data); + unsigned long value; + int error; + + error = strict_strtoul(buf, 10, &value); + if (unlikely(error)) + return error; + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev[1]; +#endif + + value = !(!value); + + mutex_lock(&data->mutex); + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + make_event(ev, EV_ABS, ABS_CONTROL_REPORT, (value << 16) | data->delay); + sensor_event(&data->devfile_list, ev, 1); +#else + input_report_abs(input_data, ABS_CONTROL_REPORT, + (value << 16) | data->delay); + input_sync(input_data); +#endif + + if (data->enabled && !value) + suspend(); + if (!data->enabled && value) + resume(); + data->enabled = value; + + mutex_unlock(&data->mutex); + + return count; +} + +static ssize_t +sensor_wake_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct input_dev *input_data = to_input_dev(dev); + static int cnt = 1; +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct sensor_data *data = input_get_drvdata(input_data); + struct input_event ev[2]; + struct timeval tv; + get_time_stamp(&tv); + make_event_w_time(&ev[0], EV_ABS, ABS_WAKE, cnt++, &tv); + make_event_w_time(&ev[1], EV_SYN, 0, 0, &tv); + sensor_event(&data->devfile_list, ev, 2); +#else + input_report_abs(input_data, ABS_WAKE, cnt++); + input_sync(input_data); +#endif + + return count; +} + +#if DEBUG + +static int sensor_suspend(struct platform_device *pdev, pm_message_t state); +static int sensor_resume(struct platform_device *pdev); + +static ssize_t +sensor_debug_suspend_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input = to_input_dev(dev); + struct sensor_data *data = input_get_drvdata(input); + + return sprintf(buf, "%d\n", data->suspend); +} + +static ssize_t +sensor_debug_suspend_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long suspend; + int error; + + error = strict_strtoul(buf, 10, &suspend); + if (unlikely(error)) + return error; + + + if (suspend) { + pm_message_t msg; + memset(&msg, 0, sizeof(msg)); + sensor_suspend(sensor_pdev, msg); + } else + sensor_resume(sensor_pdev); + + return count; +} + +#endif /* DEBUG */ + +static ssize_t +sensor_data_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + int x, y, z; + + x = input_abs_get_val(input_data, ABS_X); + y = input_abs_get_val(input_data, ABS_Y); + z = input_abs_get_val(input_data, ABS_Z); + + return sprintf(buf, "%d %d %d\n", x, y, z); +} + +static ssize_t +sensor_status_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct input_dev *input_data = to_input_dev(dev); + int status; + + status = input_abs_get_val(input_data, ABS_STATUS); + + return sprintf(buf, "%d\n", status); +} + +static DEVICE_ATTR(delay, S_IRUGO | S_IWUSR | S_IWGRP, + sensor_delay_show, sensor_delay_store); +static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP, + sensor_enable_show, sensor_enable_store); +static DEVICE_ATTR(wake, S_IWUSR | S_IWGRP, NULL, sensor_wake_store); +static DEVICE_ATTR(data, S_IRUGO, sensor_data_show, NULL); +static DEVICE_ATTR(status, S_IRUGO, sensor_status_show, NULL); + +#if DEBUG +static DEVICE_ATTR(debug_suspend, S_IRUGO | S_IWUSR, + sensor_debug_suspend_show, sensor_debug_suspend_store); +#endif /* DEBUG */ + +static struct attribute *sensor_attributes[] = { + &dev_attr_delay.attr, + &dev_attr_enable.attr, + &dev_attr_wake.attr, + &dev_attr_data.attr, + &dev_attr_status.attr, +#if DEBUG + &dev_attr_debug_suspend.attr, +#endif /* DEBUG */ + NULL +}; + +static struct attribute_group sensor_attribute_group = { + .attrs = sensor_attributes +}; + +static int sensor_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct sensor_data *data = input_get_drvdata(this_data); + int rt = 0; + + mutex_lock(&data->mutex); + + if (data->enabled) { +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev[1]; + make_event(ev, EV_ABS, ABS_CONTROL_REPORT, + (0 << 16) | data->delay); + sensor_event(&data->devfile_list, ev, 1); +#else + input_report_abs(this_data, ABS_CONTROL_REPORT, + (0 << 16) | data->delay); +#endif + rt = suspend(); + } + + mutex_unlock(&data->mutex); + + return rt; +} + +static int sensor_resume(struct platform_device *pdev) +{ + struct sensor_data *data = input_get_drvdata(this_data); + int rt = 0; + + mutex_lock(&data->mutex); + + if (data->enabled) { +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + struct input_event ev[1]; + make_event(ev, EV_ABS, ABS_CONTROL_REPORT, + (1 << 16) | data->delay); + sensor_event(&data->devfile_list, ev, 1); +#endif + rt = resume(); +#ifndef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + input_report_abs(this_data, ABS_CONTROL_REPORT, + (1 << 16) | data->delay); +#endif + } + + mutex_unlock(&data->mutex); + + return rt; +} + +static int sensor_probe(struct platform_device *pdev) +{ + struct sensor_data *data = NULL; + struct input_dev *input_data = NULL; + int input_registered = 0, sysfs_created = 0; + int rt; + + data = kzalloc(sizeof(struct sensor_data), GFP_KERNEL); + if (!data) { + rt = -ENOMEM; + goto err; + } + data->enabled = 0; + data->delay = SENSOR_DEFAULT_DELAY; + + input_data = input_allocate_device(); + if (!input_data) { + rt = -ENOMEM; + YLOGE(("sensor_probe: Failed to allocate input_data device\n")); + goto err; + } + + set_bit(EV_ABS, input_data->evbit); + input_set_abs_params(input_data, ABS_X, 0x80000000, 0x7fffffff, 0, 0); + input_set_abs_params(input_data, ABS_Y, 0x80000000, 0x7fffffff, 0, 0); + input_set_abs_params(input_data, ABS_Z, 0x80000000, 0x7fffffff, 0, 0); + input_set_abs_params(input_data, ABS_RUDDER, 0x80000000, 0x7fffffff, 0, + 0); + input_set_abs_params(input_data, ABS_STATUS, 0, 3, 0, 0); + input_set_abs_params(input_data, ABS_WAKE, 0x80000000, 0x7fffffff, 0, + 0); + input_set_abs_params(input_data, ABS_CONTROL_REPORT, 0x80000000, + 0x7fffffff, 0, 0); + input_data->name = SENSOR_NAME; + + rt = input_register_device(input_data); + if (rt) { + YLOGE(("ori Unable to reg input_data %s\n", input_data->name)); + goto err; + } + input_set_drvdata(input_data, data); + input_registered = 1; + + rt = sysfs_create_group(&input_data->dev.kobj, &sensor_attribute_group); + if (rt) { + YLOGE(("sensor_probe: sysfs_create_group failed[%s]\n", + input_data->name)); + goto err; + } + sysfs_created = 1; + mutex_init(&data->mutex); + this_data = input_data; + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + INIT_LIST_HEAD(&data->devfile_list); + if (misc_register(&sensor_devfile) < 0) + goto err; +#endif + + return 0; + +err: + if (data != NULL) { + if (input_data != NULL) { + if (sysfs_created) + sysfs_remove_group(&input_data->dev.kobj, + &sensor_attribute_group); + if (input_registered) + input_unregister_device(input_data); + else + input_free_device(input_data); + input_data = NULL; + } + kfree(data); + } + + return rt; +} + +static int sensor_remove(struct platform_device *pdev) +{ + struct sensor_data *data; + +#ifdef YAS_SENSOR_KERNEL_DEVFILE_INTERFACE + misc_deregister(&sensor_devfile); +#endif + if (this_data != NULL) { + data = input_get_drvdata(this_data); + sysfs_remove_group(&this_data->dev.kobj, + &sensor_attribute_group); + input_unregister_device(this_data); + if (data != NULL) + kfree(data); + } + + return 0; +} + +/* + * Module init and exit + */ +static struct platform_driver sensor_driver = { + .probe = sensor_probe, + .remove = sensor_remove, + .suspend = sensor_suspend, + .resume = sensor_resume, + .driver = { + .name = SENSOR_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init sensor_init(void) +{ + sensor_pdev = platform_device_register_simple(SENSOR_NAME, 0, NULL, 0); + if (IS_ERR(sensor_pdev)) + return -1; + return platform_driver_register(&sensor_driver); +} + +module_init(sensor_init); + +static void __exit sensor_exit(void) +{ + platform_driver_unregister(&sensor_driver); + platform_device_unregister(sensor_pdev); +} + +module_exit(sensor_exit); + +MODULE_AUTHOR("Yamaha Corporation"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("4.4.702a"); diff --git a/drivers/sensor/yas_pcb_test.c b/drivers/sensor/yas_pcb_test.c new file mode 100644 index 0000000..686c8c6 --- /dev/null +++ b/drivers/sensor/yas_pcb_test.c @@ -0,0 +1,1282 @@ +/* + * Copyright (c) 2010-2011 Yamaha Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +/* + * File yas_pcb_test.c + * Brief pcb test program for yas530/yas532 + * Date 2013/1/22 + * Revision 1.4.3 + */ +#include "yas_pcb_test.h" + +/* define */ +/* reg num */ +#define YAS530_CAL_REG_NUM (16) +#define YAS532_CAL_REG_NUM (14) +#define YAS_PCB_MEASURE_DATA_REG_NUM (8) + +/* default value */ +#define YAS_PCB_TEST1_DEFAULT (0x00) +#define YAS_PCB_TEST2_DEFAULT (0x00) +#define YAS_PCB_INTERVAL_DEFAULT (0x00) +#define YAS_PCB_CONFIG_DEFAULT (0x01) /* INTON = 1 */ +#define YAS_PCB_COIL_DEFAULT (0x00) + +/* measure command */ +#define YAS_PCB_MEASURE_COMMAND_START (0x01) +#define YAS_PCB_MEASURE_COMMAND_LDTC (0x02) +#define YAS_PCB_MEASURE_COMMAND_FORS (0x04) + +#define YAS_PCB_MEASURE_BUSY (0x80) + +#define YAS_PCB_MEASURE_WAIT_TIME (2) /* ms */ +#define YAS_PCB_HARD_OFFSET_CORRECT (16) +#define YAS_PCB_COIL_INIT_CALC_NUM (5) + +#define YAS_PCB_HARD_OFFSET_MASK (0x3F) + +#define YAS_PCB_INT_CHECK (1) +#define YAS_PCB_INT_NOTCHECK (0) +#define YAS_PCB_INT_HIGH (1) +#define YAS_PCB_INT_LOW (0) + +#define YAS_PCB_ACC_Z (9806550L) /* m/s2 */ + +#define YAS530_DEVICE_ID (0x01) /* MS-3E */ +#define YAS532_DEVICE_ID (0x02) /* MS-3R */ + +#define YAS530_VERSION_A (0) /* MS-3E Aver */ +#define YAS530_VERSION_B (1) /* MS-3E Bver */ +/*#define YAS530_VERSION_AB (0)*/ /* MS-3R ABver */ +#define YAS532_VERSION_AC (1) /* MS-3R ACver */ + +#define YAS530_COEF_VERSION_A (380) +#define YAS530_COEF_VERSION_B (550) +/*#define YAS532_COEF_VERSION_AB (1800)*/ +/*#define YAS532_COEF_VERSION_AC (900)*/ +#define YAS532_COEFX_VERSION_AC (850) +#define YAS532_COEFY1_VERSION_AC (750) +#define YAS532_COEFY2_VERSION_AC (750) + +#define YAS530_RAWDATA_CENTER (2048) +#define YAS530_RAWDATA_OVERFLOW (4095) +#define YAS532_RAWDATA_CENTER (4096) +#define YAS532_RAWDATA_OVERFLOW (8190) + +#define YAS_PCB_DIR_DIVIDER (400) + +#define YAS_PCB_TEST1 (0) +#define YAS_PCB_TEST3 (1) +#define YAS_PCB_TEST4 (2) +#define YAS_PCB_TEST5 (3) +#define YAS_PCB_TEST6 (4) +#define YAS_PCB_TEST7 (5) +#define YAS_PCB_TEST8 (6) +#define YAS_PCB_TEST2 (7) +#define YAS_PCB_TEST_NUM (8) + +/* typedef */ +struct yas_pcb_vector { + int32_t v[3]; +}; + +struct yas_pcb_correction { + int32_t s32Cx, s32Cy1, s32Cy2; + int32_t s32A2, s32A3, s32A4, s32A5, s32A6, s32A7, s32A8, s32A9, s32K; + int32_t s32ZFlag; + int32_t s32Rx, s32Ry1, s32Ry2; + int32_t s32Fx, s32Fy1, s32Fy2; + int32_t s32Ver; +}; + +struct yas_pcb_sensitivity { + int32_t s32Sx, s32Sy, s32Sz; +}; + +/* values */ +static uint16_t gu16State; +static struct yas_pcb_test_callback g_callback; +static struct yas_pcb_vector gstXy1y2; +static int8_t gs08HardOffset[3]; +static struct yas_pcb_correction gstCorrect; +static uint8_t gu08DevId; +static int32_t gs32Center; +static int32_t gs32Overflow; +#ifdef YAS_PCBTEST_EXTRA +static uint8_t gu08Recalc; +static int32_t gs32RecalcWait; +#endif + +/* functions */ +static int Ms3AxesLibAtan8(int, int, short *); +static int Ms3AxesLibDir8(int, int, unsigned short *); +static int yas_pcb_check_state(int); +static void yas_pcb_update_state(int); +static int yas_pcb_power_on(void); +static int yas_pcb_power_off(void); +static int yas_pcb_reset_coil(void); +static int yas530_read_cal(uint8_t *); +static int yas532_read_cal(uint8_t *); +static void yas530_calc_correction(const uint8_t *); +static void yas532_calc_correction(const uint8_t *); +static int yas_pcb_set_offset(const int8_t *); +static int yas_pcb_measure(struct yas_pcb_vector *, int *, uint8_t, uint8_t); +static int yas_pcb_is_flow_occued(struct yas_pcb_vector *, int32_t, int32_t); +static void yas_pcb_calc_sensitivity(struct yas_pcb_vector *, + int, struct yas_pcb_sensitivity *); +static void yas_pcb_calc_position(struct yas_pcb_vector *, + struct yas_pcb_vector *, int); +static int yas_pcb_calc_magnetic_field(struct yas_pcb_vector *, + struct yas_pcb_vector *); +static int yas_pcb_test1(int *); +static int yas_pcb_test2(void); +static int yas_pcb_test3(void); +static int yas_pcb_test4(int *, int *, int *); +static int yas_pcb_test5(int *); +static int yas_pcb_test6(int *, int *); +#ifdef YAS_PCBTEST_EXTRA +static int yas_pcb_test7(int *, int *, int *); +#endif + +static int Ms3AxesLibAtan8(int ss, int cc, short *ans) +{ + static const unsigned char AtanTable[] = { + 0, 1, 3, 5, 6, 8, 11, 13, + 15, 18, 21, 24, 27, 31, 34, 39, + 43, 48, 53, 58, 63, 69, 75, 82, + 89, 96, 103, 110, 118, 126, 134, 143, + 152 + }; + + unsigned char idx; + unsigned short idx_mul64; + signed char sign = 1; + unsigned int ucc; + unsigned int uss; + unsigned short ans_mul8; + unsigned char idx_mod64; + unsigned short ans_diff8; + + if (cc < 0) { + sign = -sign; + ucc = -cc; + } else { + ucc = cc; + } + + if (ss < 0) { + sign = -sign; + uss = -ss; + } else { + uss = ss; + } + + while (ucc >= 0x400) { + ucc >>= 1; + uss >>= 1; + } + + if (ucc == 0) + return -1; + + idx_mul64 = (uss << 11) / ucc; + + idx = idx_mul64 >> 6; + ans_mul8 = (idx << 4) - AtanTable[idx]; + + idx_mod64 = (unsigned char)idx_mul64 & 0x3f; + + if (idx < 32) { + idx++; + ans_diff8 = (idx << 4) - AtanTable[idx] - ans_mul8; + ans_mul8 += (ans_diff8 * idx_mod64) >> 6; + } + + *ans = (sign == 1) ? ans_mul8 : (-ans_mul8); + + return 0; +} + +static int Ms3AxesLibDir8(int ss, int cc, unsigned short *ans) +{ + short temp_ans = 0; + int ucc = cc; + int uss = ss; + int ret = 0; + + if (cc < -2147483647) + cc++; + if (ss < -2147483647) + ss++; + + if (cc < 0) + ucc = -cc; + + if (ss < 0) + uss = -ss; + + if (uss <= ucc) { + ret = Ms3AxesLibAtan8(ss, cc, &temp_ans); + if (ret < 0) + return 1; + + if (cc > 0) { + if (temp_ans < 0) + temp_ans += 2880; + } else + temp_ans += 1440; + } else { + ret = Ms3AxesLibAtan8(cc, ss, &temp_ans); + if (ret < 0) + return 1; + + if (ss > 0) + temp_ans = 720 - temp_ans; + else + temp_ans = 2160 - temp_ans; + } + + *ans = temp_ans; + + return 0; +} + +static int yas_pcb_check_state(int id) +{ + int result = YAS_PCB_ERROR_TEST_ORDER; + uint16_t u16Mask; + const uint16_t u16TestTable[] = { + 0x0000, /* 1 */ + 0x0000, /* 3 */ + (1 << YAS_PCB_TEST1) | (1 << YAS_PCB_TEST3), /* 4 */ + (1 << YAS_PCB_TEST1) | (1 << YAS_PCB_TEST3) + | (1 << YAS_PCB_TEST4), /* 5 */ + (1 << YAS_PCB_TEST1) | (1 << YAS_PCB_TEST3) + | (1 << YAS_PCB_TEST4), /* 6 */ + (1 << YAS_PCB_TEST1) | (1 << YAS_PCB_TEST3) + | (1 << YAS_PCB_TEST4) /* 7 */ + | (1 << YAS_PCB_TEST5), + (1 << YAS_PCB_TEST1) | (1 << YAS_PCB_TEST3) + | (1 << YAS_PCB_TEST4), /* 8 */ + (1 << YAS_PCB_TEST1), /* 2 */ + }; + + if ((YAS_PCB_TEST1 <= id) && (id < YAS_PCB_TEST_NUM)) { + u16Mask = u16TestTable[id]; + if (u16Mask == 0) { + switch (id) { + case YAS_PCB_TEST1: + if ((gu16State == 0) + || (gu16State == (1 << YAS_PCB_TEST1))) + result = YAS_PCB_NO_ERROR; + break; + + case YAS_PCB_TEST3: + if ((gu16State == (1 << YAS_PCB_TEST1)) + || (gu16State == + ((1 << YAS_PCB_TEST1) + | (1 << YAS_PCB_TEST3)))) + result = YAS_PCB_NO_ERROR; + break; + + default: + break; + } + } else { + if ((gu16State & u16Mask) == u16Mask) + result = YAS_PCB_NO_ERROR; + } + } + + return result; +} + +static void yas_pcb_update_state(int id) +{ + if ((YAS_PCB_TEST1 <= id) && (id < YAS_PCB_TEST2)) + gu16State |= (uint16_t)(1 << id); + else + gu16State = 0; +} + +static int yas_pcb_power_on(void) +{ + int result = YAS_PCB_NO_ERROR; + int ret; + + if (NULL != g_callback.power_on) { + ret = g_callback.power_on(); + if (0 != ret) + result = YAS_PCB_ERROR_POWER; + } + + return result; +} + +static int yas_pcb_power_off(void) +{ + int result = YAS_PCB_NO_ERROR; + int ret; + + if (NULL != g_callback.power_off) { + ret = g_callback.power_off(); + if (0 != ret) + result = YAS_PCB_ERROR_POWER; + } + + return result; +} + +static int yas_pcb_reset_coil(void) +{ + int ret; + uint8_t u08Data; + u08Data = YAS_PCB_COIL_DEFAULT; + ret = g_callback.i2c_write(YAS_PCB_ADDR_SLAVE, YAS_PCB_ADDR_COIL, + &u08Data, 1); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + return YAS_PCB_NO_ERROR; +} +static int yas530_read_cal(uint8_t *pu08Buf) +{ + int i; + int ret; + int size = YAS530_CAL_REG_NUM; + + /* Dummy read */ + ret = g_callback.i2c_read(YAS_PCB_ADDR_SLAVE, YAS_PCB_ADDR_CAL, + pu08Buf, size); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + ret = g_callback.i2c_read(YAS_PCB_ADDR_SLAVE, YAS_PCB_ADDR_CAL, + pu08Buf, size); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + /* cal register is all 0 */ + for (i = 0; i < size; i++) { + if (pu08Buf[i] != 0x00) + return YAS_PCB_NO_ERROR; + } + + return YAS_PCB_ERROR_CALREG; +} + + +static int yas532_read_cal(uint8_t *pu08Buf) +{ + int i; + int ret; + int size = YAS532_CAL_REG_NUM; + int len = size - 1; + + /* Dummy read */ + ret = g_callback.i2c_read(YAS_PCB_ADDR_SLAVE, YAS_PCB_ADDR_CAL, + pu08Buf, size); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + ret = g_callback.i2c_read(YAS_PCB_ADDR_SLAVE, YAS_PCB_ADDR_CAL, + pu08Buf, size); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + /* cal register is all 0 */ + for (i = 0; i < len; i++) { + if (pu08Buf[i] != 0x00) + return YAS_PCB_NO_ERROR; + } + + /* MSB is not 0 */ + if (pu08Buf[len] & 0x80) + return YAS_PCB_NO_ERROR; + + return YAS_PCB_ERROR_CALREG; +} + +static void yas530_calc_correction(const uint8_t *pu08Data) +{ + uint8_t u08Dx = pu08Data[0]; + uint8_t u08Dy1 = pu08Data[1]; + uint8_t u08Dy2 = pu08Data[2]; + uint8_t u08D2 = (uint8_t)((pu08Data[3] >> 2) & 0x3F); + uint8_t u08D3 = (uint8_t)(((pu08Data[3] << 2) & 0x0C) + | ((pu08Data[4] >> 6) & 0x03)); + uint8_t u08D4 = (uint8_t)(pu08Data[4] & 0x3F); + uint8_t u08D5 = (uint8_t)((pu08Data[5] >> 2) & 0x3f); + uint8_t u08D6 = (uint8_t)(((pu08Data[5] << 4) & 0x30) + | ((pu08Data[6] >> 4) & 0x0F)); + uint8_t u08D7 = (uint8_t)(((pu08Data[6] << 3) & 0x78) + | ((pu08Data[7] >> 5) & 0x07)); + uint8_t u08D8 = (uint8_t)(((pu08Data[7] << 1) & 0x3E) + | ((pu08Data[8] >> 7) & 0x01)); + uint8_t u08D9 = (uint8_t)(((pu08Data[8] << 1) & 0xFE) + | ((pu08Data[9] >> 7) & 0x01)); + uint8_t u08D0 = (uint8_t)((pu08Data[9] >> 2) & 0x1F); + uint8_t u08ZFlag = (uint8_t)((pu08Data[11] >> 5) & 0x01); + uint8_t u08Rx = (uint8_t)(((pu08Data[11] << 1) & 0x3E) + | ((pu08Data[12] >> 7) & 0x01)); + uint8_t u08Fx = (uint8_t)((pu08Data[12] >> 5) & 0x03); + uint8_t u08Ry1 = (uint8_t)(((pu08Data[12] << 1) & 0x3E) + | ((pu08Data[13] >> 7) & 0x01)); + uint8_t u08Fy1 = (uint8_t)((pu08Data[13] >> 5) & 0x03); + uint8_t u08Ry2 = (uint8_t)(((pu08Data[13] << 1) & 0x3E) + | ((pu08Data[14] >> 7) & 0x01)); + uint8_t u08Fy2 = (uint8_t)((pu08Data[14] >> 5) & 0x03); + uint8_t u08Ver = pu08Data[15] & 0x07; + + gstCorrect.s32Cx = (int32_t)((u08Dx * 6) - 768); + gstCorrect.s32Cy1 = (int32_t)((u08Dy1 * 6) - 768); + gstCorrect.s32Cy2 = (int32_t)((u08Dy2 * 6) - 768); + gstCorrect.s32A2 = (int32_t)(u08D2 - 32); + gstCorrect.s32A3 = (int32_t)(u08D3 - 8); + gstCorrect.s32A4 = (int32_t)(u08D4 - 32); + gstCorrect.s32A5 = (int32_t)(u08D5 + 38); + gstCorrect.s32A6 = (int32_t)(u08D6 - 32); + gstCorrect.s32A7 = (int32_t)(u08D7 - 64); + gstCorrect.s32A8 = (int32_t)(u08D8 - 32); + gstCorrect.s32A9 = (int32_t)u08D9; + gstCorrect.s32K = (int32_t)(u08D0) + 10; + gstCorrect.s32ZFlag = (int32_t)u08ZFlag; + gstCorrect.s32Rx = (int32_t)((int8_t)(u08Rx << 2) >> 2); + gstCorrect.s32Fx = (int32_t)u08Fx; + gstCorrect.s32Ry1 = (int32_t)((int8_t)(u08Ry1 << 2) >> 2); + gstCorrect.s32Fy1 = (int32_t)u08Fy1; + gstCorrect.s32Ry2 = (int32_t)((int8_t)(u08Ry2 << 2) >> 2); + gstCorrect.s32Fy2 = (int32_t)u08Fy2; + gstCorrect.s32Ver = (int32_t)u08Ver; +} + +static void yas532_calc_correction(const uint8_t *pu08Data) +{ + uint8_t u08Dx = pu08Data[0]; + uint8_t u08Dy1 = pu08Data[1]; + uint8_t u08Dy2 = pu08Data[2]; + uint8_t u08D2 = (uint8_t)((pu08Data[3] >> 2) & 0x3F); + uint8_t u08D3 = (uint8_t)(((pu08Data[3] << 2) & 0x0C) + | ((pu08Data[4] >> 6) & 0x03)); + uint8_t u08D4 = (uint8_t)(pu08Data[4] & 0x3F); + uint8_t u08D5 = (uint8_t)((pu08Data[5] >> 2) & 0x3f); + uint8_t u08D6 = (uint8_t)(((pu08Data[5] << 4) & 0x30) + | ((pu08Data[6] >> 4) & 0x0F)); + uint8_t u08D7 = (uint8_t)(((pu08Data[6] << 3) & 0x78) + | ((pu08Data[7] >> 5) & 0x07)); + uint8_t u08D8 = (uint8_t)(((pu08Data[7] << 1) & 0x3E) + | ((pu08Data[8] >> 7) & 0x01)); + uint8_t u08D9 = (uint8_t)(((pu08Data[8] << 1) & 0xFE) + | ((pu08Data[9] >> 7) & 0x01)); + uint8_t u08D0 = (uint8_t)((pu08Data[9] >> 2) & 0x1F); + uint8_t u08Rx = (uint8_t)((pu08Data[10] >> 1) & 0x3F); + uint8_t u08Fx = (uint8_t)(((pu08Data[10] & 0x01) << 1) + | ((pu08Data[11] >> 7) & 0x01)); + uint8_t u08Ry1 = (uint8_t)((pu08Data[11] >> 1) & 0x3F); + uint8_t u08Fy1 = (uint8_t)(((pu08Data[11] & 0x01) << 1) + | ((pu08Data[12] >> 7) & 0x01)); + uint8_t u08Ry2 = (uint8_t)((pu08Data[12] >> 1) & 0x3F); + uint8_t u08Fy2 = (uint8_t)(((pu08Data[12] & 0x01) << 1) + | ((pu08Data[13] >> 7) & 0x01)); + uint8_t u08Ver = pu08Data[13] & 0x01; + + gstCorrect.s32Cx = (int32_t)((u08Dx * 10) - 1280); + gstCorrect.s32Cy1 = (int32_t)((u08Dy1 * 10) - 1280); + gstCorrect.s32Cy2 = (int32_t)((u08Dy2 * 10) - 1280); + gstCorrect.s32A2 = (int32_t)(u08D2 - 32); + gstCorrect.s32A3 = (int32_t)(u08D3 - 8); + gstCorrect.s32A4 = (int32_t)(u08D4 - 32); + gstCorrect.s32A5 = (int32_t)(u08D5 + 38); + gstCorrect.s32A6 = (int32_t)(u08D6 - 32); + gstCorrect.s32A7 = (int32_t)(u08D7 - 64); + gstCorrect.s32A8 = (int32_t)(u08D8 - 32); + gstCorrect.s32A9 = (int32_t)u08D9; + gstCorrect.s32K = (int32_t)u08D0; + gstCorrect.s32ZFlag = (int32_t)1; + gstCorrect.s32Rx = (int32_t)((int8_t)(u08Rx << 2) >> 2); + gstCorrect.s32Fx = (int32_t)u08Fx; + gstCorrect.s32Ry1 = (int32_t)((int8_t)(u08Ry1 << 2) >> 2); + gstCorrect.s32Fy1 = (int32_t)u08Fy1; + gstCorrect.s32Ry2 = (int32_t)((int8_t)(u08Ry2 << 2) >> 2); + gstCorrect.s32Fy2 = (int32_t)u08Fy2; + gstCorrect.s32Ver = (int32_t)u08Ver; +} + +static int yas_pcb_set_offset(const int8_t *ps08Offset) +{ + int result = YAS_PCB_NO_ERROR; + int ret; + uint8_t u08Addr; + uint8_t u08Data; + uint8_t i; + + for (i = 0; i < 3; i++) { + u08Addr = (uint8_t)(YAS_PCB_ADDR_OFFSET + i); + u08Data = (uint8_t)ps08Offset[i] & YAS_PCB_HARD_OFFSET_MASK; + ret = g_callback.i2c_write(YAS_PCB_ADDR_SLAVE, + u08Addr, &u08Data, 1); + if (0 != ret) { + result = YAS_PCB_ERROR_I2C; + break; + } + } + + return result; +} + +static int yas_pcb_measure(struct yas_pcb_vector *pstXy1y2, int *temperature, + uint8_t u08Command, uint8_t u08CheckIni) +{ + int ret; + uint8_t u08Buf[YAS_PCB_MEASURE_DATA_REG_NUM]; + int low_or_high; + + if ((YAS_PCB_INT_CHECK == u08CheckIni) + && (NULL != g_callback.read_intpin)) { + ret = g_callback.read_intpin(&low_or_high); + if ((0 != ret) || (YAS_PCB_INT_HIGH != low_or_high)) + return YAS_PCB_ERROR_INTERRUPT; + } + + ret = g_callback.i2c_write(YAS_PCB_ADDR_SLAVE, + YAS_PCB_ADDR_MEASURE_COMMAND, + &u08Command, 1); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + g_callback.msleep(YAS_PCB_MEASURE_WAIT_TIME); + + if ((YAS_PCB_INT_CHECK == u08CheckIni) + && (NULL != g_callback.read_intpin)) { + ret = g_callback.read_intpin(&low_or_high); + if ((0 != ret) || (YAS_PCB_INT_LOW != low_or_high)) + return YAS_PCB_ERROR_INTERRUPT; + } + + ret = g_callback.i2c_read(YAS_PCB_ADDR_SLAVE, YAS_PCB_ADDR_MEASURE_DATA, + u08Buf, YAS_PCB_MEASURE_DATA_REG_NUM); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + /* calc measure data */ + if (YAS532_DEVICE_ID == gu08DevId) { + *temperature = (((int32_t)(u08Buf[0] & 0x7F) << 3) + | ((u08Buf[1] >> 5) & 0x07)); + pstXy1y2->v[0] = (int32_t)(((int32_t)(u08Buf[2] & 0x7F) << 6) + | ((u08Buf[3] >> 2) & 0x3F)); + pstXy1y2->v[1] = (int32_t)(((int32_t)(u08Buf[4] & 0x7F) << 6) + | ((u08Buf[5] >> 2) & 0x3F)); + pstXy1y2->v[2] = (int32_t)(((int32_t)(u08Buf[6] & 0x7F) << 6) + | ((u08Buf[7] >> 2) & 0x3F)); + } else { + *temperature = (((int32_t)(u08Buf[0] & 0x7F) << 2) + | ((u08Buf[1] >> 6) & 0x03)); + pstXy1y2->v[0] = (int32_t)(((int32_t)(u08Buf[2] & 0x7F) << 5) + | ((u08Buf[3] >> 3) & 0x1F)); + pstXy1y2->v[1] = (int32_t)(((int32_t)(u08Buf[4] & 0x7F) << 5) + | ((u08Buf[5] >> 3) & 0x1F)); + pstXy1y2->v[2] = (int32_t)(((int32_t)(u08Buf[6] & 0x7F) << 5) + | ((u08Buf[7] >> 3) & 0x1F)); + } + + if (YAS_PCB_MEASURE_BUSY == (u08Buf[0] & YAS_PCB_MEASURE_BUSY)) + return YAS_PCB_ERROR_BUSY; + + return YAS_PCB_NO_ERROR; +} + +static int yas_pcb_is_flow_occued(struct yas_pcb_vector *pstXy1y2, + int32_t underflow, int32_t overflow) +{ + int result = YAS_PCB_NO_ERROR; + int32_t s32Tmp; + uint8_t i; + + for (i = 0; i < 3; i++) { + s32Tmp = pstXy1y2->v[i]; + if (s32Tmp <= underflow) + result = YAS_PCB_ERROR_UNDERFLOW; + else + if (overflow <= s32Tmp) + result = YAS_PCB_ERROR_OVERFLOW; + } + + return result; +} + +static void yas_pcb_calc_sensitivity(struct yas_pcb_vector *pstXy1y2, + int temperature, struct yas_pcb_sensitivity *pstYasSensitivity) +{ + /* calc XYZ data from xy1y2 data */ + int32_t s32Sx = pstXy1y2->v[0] + - ((gstCorrect.s32Cx * temperature) / 100); + int32_t s32Sy1 = pstXy1y2->v[1] + - ((gstCorrect.s32Cy1 * temperature) / 100); + int32_t s32Sy2 = pstXy1y2->v[2] + - ((gstCorrect.s32Cy2 * temperature) / 100); + int32_t s32Sy = s32Sy1 - s32Sy2; + int32_t s32Sz = -s32Sy1 - s32Sy2; + + pstYasSensitivity->s32Sx = s32Sx; + pstYasSensitivity->s32Sy = s32Sy; + pstYasSensitivity->s32Sz = s32Sz; +} + +static void yas_pcb_calc_position(struct yas_pcb_vector *pstXy1y2, + struct yas_pcb_vector *pstXyz, int temperature) +{ + struct yas_pcb_sensitivity stSensitivity; + struct yas_pcb_sensitivity *pst; + + yas_pcb_calc_sensitivity(pstXy1y2, temperature, &stSensitivity); + + pst = &stSensitivity; + pstXyz->v[0] = (gstCorrect.s32K + * ((100 * pst->s32Sx) + (gstCorrect.s32A2 * pst->s32Sy) + + (gstCorrect.s32A3 * pst->s32Sz))) / 10; + pstXyz->v[1] = (gstCorrect.s32K * ((gstCorrect.s32A4 * pst->s32Sx) + + (gstCorrect.s32A5 * pst->s32Sy) + + (gstCorrect.s32A6 * pst->s32Sz))) / 10; + pstXyz->v[2] = (gstCorrect.s32K * ((gstCorrect.s32A7 * pst->s32Sx) + + (gstCorrect.s32A8 * pst->s32Sy) + + (gstCorrect.s32A9 * pst->s32Sz))) / 10; +} + +static void yas530_calc_magnetic_field(struct yas_pcb_vector *pstXy1y2, + struct yas_pcb_vector *pstXyz, int32_t s32Coef) +{ + int32_t s32Oy; + int32_t s32Oz; + static const int32_t s32HTbl[] = { + 1748, 1948, 2148, 2348 + }; + + pstXy1y2->v[0] = gstXy1y2.v[0] - s32HTbl[gstCorrect.s32Fx] + + (gs08HardOffset[0] - gstCorrect.s32Rx) * s32Coef; + pstXy1y2->v[1] = gstXy1y2.v[1] - s32HTbl[gstCorrect.s32Fy1] + + (gs08HardOffset[1] - gstCorrect.s32Ry1) * s32Coef; + pstXy1y2->v[2] = gstXy1y2.v[2] - s32HTbl[gstCorrect.s32Fy2] + + (gs08HardOffset[2] - gstCorrect.s32Ry2) * s32Coef; + s32Oy = pstXy1y2->v[1] - pstXy1y2->v[2]; + s32Oz = -pstXy1y2->v[1] - pstXy1y2->v[2]; + + pstXyz->v[0] = (gstCorrect.s32K + * ((100 * pstXy1y2->v[0]) + + (gstCorrect.s32A2 * s32Oy) + + (gstCorrect.s32A3 * s32Oz))) / 10; + pstXyz->v[1] = (gstCorrect.s32K + * ((gstCorrect.s32A4 * pstXy1y2->v[0]) + + (gstCorrect.s32A5 * s32Oy) + + (gstCorrect.s32A6 * s32Oz))) / 10; + pstXyz->v[2] = (gstCorrect.s32K + * ((gstCorrect.s32A7 * pstXy1y2->v[0]) + + (gstCorrect.s32A8 * s32Oy) + + (gstCorrect.s32A9 * s32Oz))) / 10; +} + +static void yas532_calc_magnetic_field(struct yas_pcb_vector *pstXy1y2, + struct yas_pcb_vector *pstXyz, + int32_t s32CoefX, int32_t s32CoefY1, int32_t s32CoefY2) +{ + int32_t s32Oy; + int32_t s32Oz; + static const int32_t s32HTbl[] = { + 3721, 3971, 4221, 4471 + }; + + pstXy1y2->v[0] = gstXy1y2.v[0] - s32HTbl[gstCorrect.s32Fx] + + (gs08HardOffset[0] - gstCorrect.s32Rx) * s32CoefX; + pstXy1y2->v[1] = gstXy1y2.v[1] - s32HTbl[gstCorrect.s32Fy1] + + (gs08HardOffset[1] - gstCorrect.s32Ry1) * s32CoefY1; + pstXy1y2->v[2] = gstXy1y2.v[2] - s32HTbl[gstCorrect.s32Fy2] + + (gs08HardOffset[2] - gstCorrect.s32Ry2) * s32CoefY2; + s32Oy = pstXy1y2->v[1] - pstXy1y2->v[2]; + s32Oz = -pstXy1y2->v[1] - pstXy1y2->v[2]; + + pstXyz->v[0] = (gstCorrect.s32K + * ((100 * pstXy1y2->v[0]) + + (gstCorrect.s32A2 * s32Oy) + + (gstCorrect.s32A3 * s32Oz))) / 10; + pstXyz->v[1] = (gstCorrect.s32K + * ((gstCorrect.s32A4 * pstXy1y2->v[0]) + + (gstCorrect.s32A5 * s32Oy) + + (gstCorrect.s32A6 * s32Oz))) / 10; + pstXyz->v[2] = (gstCorrect.s32K + * ((gstCorrect.s32A7 * pstXy1y2->v[0]) + + (gstCorrect.s32A8 * s32Oy) + + (gstCorrect.s32A9 * s32Oz))) / 10; +} + +static int yas_pcb_calc_magnetic_field(struct yas_pcb_vector *pstXy1y2, + struct yas_pcb_vector *pstXyz) +{ + int32_t s32Coef; + + if (YAS532_DEVICE_ID == gu08DevId) { + switch (gstCorrect.s32Ver) { + case YAS532_VERSION_AC: + break; + + default: + return YAS_PCB_ERROR_I2C; + /* break; */ + } + + /* calculate Ohx/y/z[nT] */ + yas532_calc_magnetic_field(pstXy1y2, pstXyz, + YAS532_COEFX_VERSION_AC, + YAS532_COEFY1_VERSION_AC, + YAS532_COEFY2_VERSION_AC); + } else { + switch (gstCorrect.s32Ver) { + case YAS530_VERSION_A: + s32Coef = YAS530_COEF_VERSION_A; + break; + + case YAS530_VERSION_B: + s32Coef = YAS530_COEF_VERSION_B; + break; + + default: + return YAS_PCB_ERROR_I2C; + /* break; */ + } + + /* calculate Ohx/y/z[nT] */ + yas530_calc_magnetic_field(pstXy1y2, pstXyz, s32Coef); + } + + return YAS_PCB_NO_ERROR; +} + +static int yas_pcb_test1(int *id) +{ + int result; + int ret; + + result = yas_pcb_power_on(); + if (YAS_PCB_NO_ERROR == result) { + result = YAS_PCB_ERROR_I2C; + ret = g_callback.i2c_read(YAS_PCB_ADDR_SLAVE, + YAS_PCB_ADDR_ID, &gu08DevId, 1); + if (0 == ret) { + *id = (int)gu08DevId; + result = YAS_PCB_NO_ERROR; + } + } + + return result; +} + +static int yas_pcb_test2(void) +{ + return yas_pcb_power_off(); +} + +static int yas_pcb_test3(void) +{ + int result; + int ret; + uint8_t u08Data; + uint8_t pu08Buf[YAS530_CAL_REG_NUM]; + + u08Data = YAS_PCB_TEST1_DEFAULT; + ret = g_callback.i2c_write(YAS_PCB_ADDR_SLAVE, YAS_PCB_ADDR_TEST1, + &u08Data, 1); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + u08Data = YAS_PCB_TEST2_DEFAULT; + ret = g_callback.i2c_write(YAS_PCB_ADDR_SLAVE, YAS_PCB_ADDR_TEST2, + &u08Data, 1); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + u08Data = YAS_PCB_INTERVAL_DEFAULT; + ret = g_callback.i2c_write(YAS_PCB_ADDR_SLAVE, + YAS_PCB_ADDR_MEASURE_INTERVAL, &u08Data, 1); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + if (YAS532_DEVICE_ID == gu08DevId) { + gs32Center = YAS532_RAWDATA_CENTER; + gs32Overflow = YAS532_RAWDATA_OVERFLOW; + result = yas532_read_cal(pu08Buf); + if (YAS_PCB_NO_ERROR == result) + yas532_calc_correction(pu08Buf); + } else { + gs32Center = YAS530_RAWDATA_CENTER; + gs32Overflow = YAS530_RAWDATA_OVERFLOW; + result = yas530_read_cal(pu08Buf); + if (YAS_PCB_NO_ERROR == result) + yas530_calc_correction(pu08Buf); + } + + if (YAS_PCB_NO_ERROR != result) + return result; + + u08Data = (uint8_t)(YAS_PCB_CONFIG_DEFAULT + | (uint8_t)((pu08Buf[9] & 0x03) << 3) + | (uint8_t)((pu08Buf[10] & 0x80) >> 5)); + ret = g_callback.i2c_write(YAS_PCB_ADDR_SLAVE, + YAS_PCB_ADDR_CONFIG, &u08Data, 1); + if (0 != ret) + return YAS_PCB_ERROR_I2C; + + ret = yas_pcb_reset_coil(); + if (YAS_PCB_NO_ERROR != ret) + return ret; + return YAS_PCB_NO_ERROR; +} + +static int yas_pcb_test4(int *x, int *y1, int *y2) +{ + int result; + struct yas_pcb_vector stXy1y2; + int temperature; + int32_t s32Tmp; + int8_t s08Correct = YAS_PCB_HARD_OFFSET_CORRECT; + uint8_t i; + uint8_t k; + + gs08HardOffset[0] = 0; + gs08HardOffset[1] = 0; + gs08HardOffset[2] = 0; + result = yas_pcb_set_offset(&gs08HardOffset[0]); + if (YAS_PCB_NO_ERROR == result) { + /* calc hard offset */ + for (i = 0; i < YAS_PCB_COIL_INIT_CALC_NUM; i++) { + result = yas_pcb_measure(&stXy1y2, &temperature, + YAS_PCB_MEASURE_COMMAND_START, + YAS_PCB_INT_NOTCHECK); + if (YAS_PCB_NO_ERROR != result) + break; + + for (k = 0; k < 3; k++) { + s32Tmp = stXy1y2.v[k]; + if (gs32Center < s32Tmp) + gs08HardOffset[k] += s08Correct; + else { + if (s32Tmp < gs32Center) + gs08HardOffset[k] -= s08Correct; + } + } + + result = yas_pcb_set_offset(&gs08HardOffset[0]); + if (YAS_PCB_NO_ERROR != result) + break; + + s08Correct = (int8_t)((uint8_t)s08Correct >> 1); + } + + if (YAS_PCB_NO_ERROR == result) { + *x = (int)gs08HardOffset[0]; + *y1 = (int)gs08HardOffset[1]; + *y2 = (int)gs08HardOffset[2]; + result = yas_pcb_is_flow_occued(&stXy1y2, + 0, gs32Overflow); + } + } + + return result; +} + +static int yas_pcb_test5(int *direction) +{ + uint16_t dir; + int result; + int ret; + int x; + int y; + int nTemp; + struct yas_pcb_vector stXyz; + + result = yas_pcb_measure(&gstXy1y2, &nTemp, + YAS_PCB_MEASURE_COMMAND_START, YAS_PCB_INT_NOTCHECK); + if (YAS_PCB_NO_ERROR == result) { + result = YAS_PCB_ERROR_DIRCALC; + yas_pcb_calc_position(&gstXy1y2, &stXyz, nTemp); + + x = -stXyz.v[0] / YAS_PCB_DIR_DIVIDER; + y = stXyz.v[1] / YAS_PCB_DIR_DIVIDER; + ret = Ms3AxesLibDir8(x, y, &dir); + if (0 == ret) { + *direction = (int)(dir / 8); + result = yas_pcb_is_flow_occued(&gstXy1y2, + 0, gs32Overflow); + } + } + + return result; +} + +static int yas_pcb_test6(int *sx, int *sy) +{ + int result; + struct yas_pcb_vector stXy1y2P; + struct yas_pcb_vector stXy1y2N; + int temperature; + uint8_t u08Command; + struct yas_pcb_vector *pP = &stXy1y2P; + struct yas_pcb_vector *pN = &stXy1y2N; + struct yas_pcb_correction *pC = &gstCorrect; + + u08Command = YAS_PCB_MEASURE_COMMAND_START + | YAS_PCB_MEASURE_COMMAND_LDTC; + result = yas_pcb_measure(pP, &temperature, + u08Command, YAS_PCB_INT_CHECK); + + if (YAS_PCB_NO_ERROR == result) { + u08Command = YAS_PCB_MEASURE_COMMAND_START + | YAS_PCB_MEASURE_COMMAND_LDTC + | YAS_PCB_MEASURE_COMMAND_FORS; + result = yas_pcb_measure(pN, &temperature, u08Command, + YAS_PCB_INT_NOTCHECK); + + if (YAS_PCB_NO_ERROR == result) { + if (YAS532_DEVICE_ID == gu08DevId) { + *sx = (int)(pC->s32K * 100 + * (pP->v[0] - pN->v[0])); + *sx /= 1000; + *sx /= YAS_VCORE; + *sy = (int)(pC->s32K * pC->s32A5 + * ((pP->v[1] - pN->v[1]) + - (pP->v[2] - pN->v[2]))); + *sy /= 1000; + *sy /= YAS_VCORE; + } else { + *sx = (int)(pN->v[0] - pP->v[0]); + *sy = (int)((pN->v[1] - pP->v[1]) + - (pN->v[2] - pP->v[2])); + } + + result = yas_pcb_is_flow_occued(pP, 0, gs32Overflow); + if (YAS_PCB_NO_ERROR == result) + result = yas_pcb_is_flow_occued(pN, + 0, gs32Overflow); + } + } + + return result; +} + +#ifdef YAS_PCBTEST_EXTRA +static int yas_pcb_test7(int *ohx, int *ohy, int *ohz) +{ + int nRet = YAS_PCB_ERROR_NOT_SUPPORTED; + struct yas_pcb_vector stOhxy1y2, stOhxyz; + + if (0 != gstCorrect.s32ZFlag) { + nRet = yas_pcb_calc_magnetic_field(&stOhxy1y2, &stOhxyz); + if (YAS_PCB_NO_ERROR == nRet) { + /* [nT]->[uT] */ + *ohx = stOhxyz.v[0] / 1000; + *ohy = stOhxyz.v[1] / 1000; + *ohz = stOhxyz.v[2] / 1000; + } + } + + return nRet; +} + +static int yas_pcb_test8(int *hx0, int *hy0, int *hz0) +{ + int nRet; + int nTemp; + int nX, nY1, nY2; + int32_t s32Underflow = 0; + int32_t s32Overflow = gs32Overflow; + struct yas_pcb_vector stOhxy1y2, stOhxyz; + + if (YAS532_DEVICE_ID == gu08DevId) { + s32Underflow = YAS_PCB_NOISE_UNDERFLOW; + s32Overflow = YAS_PCB_NOISE_OVERFLOW; + } + + if (gu08Recalc != 0) { + gs32RecalcWait++; + if (YAS_PCB_NOISE_INTERVAL <= gs32RecalcWait) { + nRet = yas_pcb_reset_coil(); + if (YAS_PCB_NO_ERROR == nRet) + nRet = yas_pcb_test4(&nX, &nY1, &nY2); + + if (YAS_PCB_NO_ERROR == nRet) + gu08Recalc = 0; + + gs32RecalcWait = 0; + } + } + + if (0 != gstCorrect.s32ZFlag) { + nRet = yas_pcb_measure(&gstXy1y2, &nTemp, + YAS_PCB_MEASURE_COMMAND_START, + YAS_PCB_INT_NOTCHECK); + if (YAS_PCB_NO_ERROR == nRet) { + nRet = yas_pcb_calc_magnetic_field(&stOhxy1y2, + &stOhxyz); + if (YAS_PCB_NO_ERROR == nRet) { + *hx0 = stOhxy1y2.v[0]; + *hy0 = stOhxy1y2.v[1] - stOhxy1y2.v[2]; + *hz0 = -stOhxy1y2.v[1] - stOhxy1y2.v[2]; + nRet = yas_pcb_is_flow_occued(&gstXy1y2, + s32Underflow, s32Overflow); + if (YAS_PCB_NO_ERROR != nRet) { + if (gu08Recalc == 0) { + gu08Recalc++; + gs32RecalcWait = 0; + } + } + } + } + } else + nRet = YAS_PCB_ERROR_NOT_SUPPORTED; + + return nRet; +} + +#endif + +/* test 1 */ +static int power_on_and_device_check(int *id) +{ + int ret; + int result = yas_pcb_check_state(YAS_PCB_TEST1); + + if (YAS_PCB_NO_ERROR == result) { + if (id != NULL) { + result = YAS_PCB_ERROR_I2C; + ret = g_callback.i2c_open(); + if (0 == ret) { + result = yas_pcb_test1(id); + ret = g_callback.i2c_close(); + if (0 != ret) + result = YAS_PCB_ERROR_I2C; + } + if (YAS_PCB_NO_ERROR == result) + yas_pcb_update_state(YAS_PCB_TEST1); + } else + result = YAS_PCB_ERROR_ARG; + } + + return result; +} + +/* test 2 */ +static int power_off(void) +{ + int result = yas_pcb_check_state(YAS_PCB_TEST2); + + if (YAS_PCB_NO_ERROR == result) { + result = yas_pcb_test2(); + + if (YAS_PCB_NO_ERROR == result) + yas_pcb_update_state(YAS_PCB_TEST2); + } + + return result; +} + +/* test 3 */ +static int initialization(void) +{ + int ret; + int result = yas_pcb_check_state(YAS_PCB_TEST3); + + if (YAS_PCB_NO_ERROR == result) { + result = YAS_PCB_ERROR_I2C; + ret = g_callback.i2c_open(); + if (0 == ret) { + result = yas_pcb_test3(); + ret = g_callback.i2c_close(); + if (0 != ret) + result = YAS_PCB_ERROR_I2C; + } + + if (YAS_PCB_NO_ERROR == result) + yas_pcb_update_state(YAS_PCB_TEST3); + } + + return result; +} + +/* test 4 */ +static int offset_control_measurement_and_set_offset_register(int *x, + int *y1, int *y2) +{ + int ret; + int result = yas_pcb_check_state(YAS_PCB_TEST4); + + if (YAS_PCB_NO_ERROR == result) { + if ((x != NULL) && (y1 != NULL) && (y2 != NULL)) { + result = YAS_PCB_ERROR_I2C; + ret = g_callback.i2c_open(); + if (0 == ret) { + result = yas_pcb_test4(x, y1, y2); + ret = g_callback.i2c_close(); + if (0 != ret) + result = YAS_PCB_ERROR_I2C; + } + if (YAS_PCB_NO_ERROR == result) + yas_pcb_update_state(YAS_PCB_TEST4); + } else + result = YAS_PCB_ERROR_ARG; + } + + return result; +} + +/* test 5 */ +static int direction_measurement(int *direction) +{ + int ret; + int result = yas_pcb_check_state(YAS_PCB_TEST5); + + if (YAS_PCB_NO_ERROR == result) { + if (direction != NULL) { + result = YAS_PCB_ERROR_I2C; + ret = g_callback.i2c_open(); + if (0 == ret) { + result = yas_pcb_test5(direction); + ret = g_callback.i2c_close(); + if (0 != ret) + result = YAS_PCB_ERROR_I2C; + } + if (YAS_PCB_NO_ERROR == result) + yas_pcb_update_state(YAS_PCB_TEST5); + } else + result = YAS_PCB_ERROR_ARG; + } + + return result; +} + +/* test 6 */ +static int sensitivity_measurement_of_magnetic_sensor_by_test_coil( + int *sx, int *sy) +{ + int ret; + int result = yas_pcb_check_state(YAS_PCB_TEST6); + + if (YAS_PCB_NO_ERROR == result) { + if ((sx != NULL) && (sy != NULL)) { + result = YAS_PCB_ERROR_I2C; + ret = g_callback.i2c_open(); + if (0 == ret) { + result = yas_pcb_test6(sx, sy); + ret = g_callback.i2c_close(); + if (0 != ret) + result = YAS_PCB_ERROR_I2C; + } + if (YAS_PCB_NO_ERROR == result) + yas_pcb_update_state(YAS_PCB_TEST6); + } else + result = YAS_PCB_ERROR_ARG; + } + + return result; +} + +/* test 7 */ +static int magnetic_field_level_check(int *ohx, int *ohy, int *ohz) +{ +#ifdef YAS_PCBTEST_EXTRA + int result = yas_pcb_check_state(YAS_PCB_TEST7); + + if (YAS_PCB_NO_ERROR == result) { + if ((ohx != NULL) && (ohy != NULL) && (ohz != NULL)) { + result = yas_pcb_test7(ohx, ohy, ohz); + if (YAS_PCB_NO_ERROR == result) + yas_pcb_update_state(YAS_PCB_TEST7); + } else + result = YAS_PCB_ERROR_ARG; + } + + return result; +#else + return YAS_PCB_ERROR_NOT_SUPPORTED; +#endif +} + +/* test 8 */ +static int noise_level_check(int *hx0, int *hy0, int *hz0) +{ +#ifdef YAS_PCBTEST_EXTRA + int ret; + int result = yas_pcb_check_state(YAS_PCB_TEST8); + + if (YAS_PCB_NO_ERROR == result) { + if ((hx0 != NULL) && (hy0 != NULL) && (hz0 != NULL)) { + result = YAS_PCB_ERROR_I2C; + ret = g_callback.i2c_open(); + if (0 == ret) { + result = yas_pcb_test8(hx0, hy0, hz0); + ret = g_callback.i2c_close(); + if (0 != ret) + result = YAS_PCB_ERROR_I2C; + } + if (YAS_PCB_NO_ERROR == result) + yas_pcb_update_state(YAS_PCB_TEST8); + } else + result = YAS_PCB_ERROR_ARG; + } + + return result; +#else + return YAS_PCB_ERROR_NOT_SUPPORTED; +#endif +} + +/* pcb test module initialize */ +int yas_pcb_test_init(struct yas_pcb_test *func) +{ + int result = YAS_PCB_ERROR_ARG; + + if ((NULL != func) + && (NULL != func->callback.i2c_open) + && (NULL != func->callback.i2c_close) + && (NULL != func->callback.i2c_write) + && (NULL != func->callback.i2c_read) + && (NULL != func->callback.msleep)) { + func->power_on_and_device_check = power_on_and_device_check; + func->initialization = initialization; + func->offset_control_measurement_and_set_offset_register + = offset_control_measurement_and_set_offset_register; + func->direction_measurement = direction_measurement; + func->sensitivity_measurement_of_magnetic_sensor_by_test_coil + = sensitivity_measurement_of_magnetic_sensor_by_test_coil; + func->magnetic_field_level_check = magnetic_field_level_check; + func->noise_level_check = noise_level_check; + func->power_off = power_off; + + g_callback = func->callback; + + if (0 != gu16State) { + gu16State = 0; + yas_pcb_power_off(); + } +#ifdef YAS_PCBTEST_EXTRA + gu08Recalc = 0; + gs32RecalcWait = 0; +#endif + result = YAS_PCB_NO_ERROR; + } + + return result; +} +/* end of file */ diff --git a/drivers/sensor/yas_pcb_test.h b/drivers/sensor/yas_pcb_test.h new file mode 100644 index 0000000..40d9dbd --- /dev/null +++ b/drivers/sensor/yas_pcb_test.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2010-2011 Yamaha Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +/* + * File yas_pcb_test.h + * Date 2013/1/22 + * Revision 1.4.3 + */ + +#ifndef __YAS_PCB_TEST_H__ +#define __YAS_PCB_TEST_H__ + +#include "yas_types.h" + +/* extra */ +#define YAS_PCBTEST_EXTRA + +/* error code */ +#define YAS_PCB_NO_ERROR (0) +#define YAS_PCB_ERROR_I2C (-1) +#define YAS_PCB_ERROR_POWER (-2) +#define YAS_PCB_ERROR_TEST_ORDER (-3) +#define YAS_PCB_ERROR_INTERRUPT (-4) +#define YAS_PCB_ERROR_BUSY (-5) +#define YAS_PCB_ERROR_OVERFLOW (-6) +#define YAS_PCB_ERROR_UNDERFLOW (-7) +#define YAS_PCB_ERROR_DIRCALC (-8) +#define YAS_PCB_ERROR_NOT_SUPPORTED (-9) +#define YAS_PCB_ERROR_CALREG (-10) +#define YAS_PCB_ERROR_ARG (-128) + +/* addr */ +#define YAS_PCB_ADDR_SLAVE (0x2E) + +#define YAS_PCB_ADDR_ID (0x80) +#define YAS_PCB_ADDR_COIL (0x81) +#define YAS_PCB_ADDR_MEASURE_COMMAND (0x82) +#define YAS_PCB_ADDR_CONFIG (0x83) +#define YAS_PCB_ADDR_MEASURE_INTERVAL (0x84) +#define YAS_PCB_ADDR_OFFSET (0x85) +#define YAS_PCB_ADDR_TEST1 (0x88) +#define YAS_PCB_ADDR_TEST2 (0x89) +#define YAS_PCB_ADDR_CAL (0x90) +#define YAS_PCB_ADDR_MEASURE_DATA (0xB0) + +/* V Core */ +#define YAS_VCORE (18) +#define YAS_PCB_NOISE_OVERFLOW (6000) +#define YAS_PCB_NOISE_UNDERFLOW (2000) +#define YAS_PCB_NOISE_INTERVAL (50) + +struct yas_pcb_test_callback { + int (*power_on)(void); + int (*power_off)(void); + int (*i2c_open)(void); + int (*i2c_close)(void); + int (*i2c_write)(uint8_t, uint8_t, const uint8_t *, int); + int (*i2c_read)(uint8_t, uint8_t, uint8_t *, int); + void (*msleep)(int); + int (*read_intpin)(int *); +}; + +struct yas_pcb_test { + int (*power_on_and_device_check)(int *); + int (*initialization)(void); + int (*offset_control_measurement_and_set_offset_register) + (int *, int *, int *); + int (*direction_measurement)(int *); + int (*sensitivity_measurement_of_magnetic_sensor_by_test_coil) + (int *, int *); + int (*magnetic_field_level_check)(int *, int *, int *); + int (*noise_level_check)(int *, int *, int *); + int (*power_off)(void); + struct yas_pcb_test_callback callback; +}; + +/* prototype functions */ +#ifdef __cplusplus +extern "C" { +#endif + +int yas_pcb_test_init(struct yas_pcb_test *); + +#ifdef __cplusplus +} +#endif + +#endif /* ! __YAS_PCB_TEST_H__ */ + +/* end of file */ diff --git a/drivers/sensor/yas_types.h b/drivers/sensor/yas_types.h new file mode 100644 index 0000000..97aa3f3 --- /dev/null +++ b/drivers/sensor/yas_types.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010-2011 Yamaha Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +/* + * File yas_types.h + * Date 2012/10/05 + * Revision 1.4.1 + */ + +#ifndef __YAS_TYPES_H__ +#define __YAS_TYPES_H__ + +/* macro */ +#ifndef NULL +#define NULL ((void *)0) +#endif + +#if defined(__KERNEL__) +#include +#else +#include +/*typedef signed char int8_t;*/ +/*typedef unsigned char uint8_t;*/ +/*typedef signed short int16_t;*/ +/*typedef unsigned short uint16_t;*/ +/*typedef signed int int32_t;*/ +/*typedef unsigned int uint32_t;*/ +#endif + +#endif /* __YASTYPES_H__ */ + +/* end of file */ diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 8cf2cee..8a37cbd 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1543,7 +1543,7 @@ static void binder_transaction(struct binder_proc *proc, t->from = thread; else t->from = NULL; -#ifdef CONFIG_MACH_P4NOTE +#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA) /* workaround code for invalid binder proc */ if (!proc->tsk) { binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 29c581f..d82a55b 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -424,6 +424,13 @@ config BACKLIGHT_SMART_DIMMING help Say Y to enable the Smart Dimming Feature. +config BACKLIGHT_LP855X + tristate "Backlight driver for TI LP855X" + depends on BACKLIGHT_CLASS_DEVICE && I2C + help + This supports TI LP8550, LP8551, LP8552, LP8553 and LP8556 + backlight driver. + endif # BACKLIGHT_CLASS_DEVICE endif # BACKLIGHT_LCD_SUPPORT diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 9d8d82f..658e9a1 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o +obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c new file mode 100644 index 0000000..bbedab5 --- /dev/null +++ b/drivers/video/backlight/lp855x_bl.c @@ -0,0 +1,466 @@ +/* + * TI LP855x Backlight Driver + * + * Copyright (C) 2011 Texas Instruments + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif + +/* Registers */ +#define BRIGHTNESS_CTRL 0x00 +#define DEVICE_CTRL 0x01 +#define EEPROM_START 0xA0 +#define EEPROM_END 0xA7 +#define EPROM_START 0xA0 +#define EPROM_END 0xAF + +#if defined(CONFIG_MACH_KONA) +#define EEPROM_CFG3 0xA3 +#define EEPROM_CFG5 0xA5 +#endif + +#define BUF_SIZE 20 +#define DEFAULT_BL_NAME "lcd-backlight" +#define MAX_BRIGHTNESS 255 + +struct lp855x { + const char *chipname; + enum lp855x_chip_id chip_id; + struct i2c_client *client; + struct backlight_device *bl; + struct device *dev; + struct mutex xfer_lock; + struct lp855x_platform_data *pdata; + int enabled; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif +}; + +static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data) +{ + int ret; + + mutex_lock(&lp->xfer_lock); + ret = i2c_smbus_read_byte_data(lp->client, reg); + if (ret < 0) { + mutex_unlock(&lp->xfer_lock); + dev_err(lp->dev, "failed to read 0x%.2x\n", reg); + return ret; + } + mutex_unlock(&lp->xfer_lock); + + *data = (u8)ret; + return 0; +} + +static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data) +{ + int ret; + + mutex_lock(&lp->xfer_lock); + ret = i2c_smbus_write_byte_data(lp->client, reg, data); + mutex_unlock(&lp->xfer_lock); + + return ret; +} + +static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr) +{ + u8 start, end; + + switch (lp->chip_id) { + case LP8550: + case LP8551: + case LP8552: + case LP8553: + start = EEPROM_START; + end = EEPROM_END; + break; + case LP8556: + start = EPROM_START; + end = EPROM_END; + break; + default: + return false; + } + + return (addr >= start && addr <= end); +} + +static int lp855x_init_registers(struct lp855x *lp) +{ + u8 val, addr, mask; + int i, ret; + struct lp855x_platform_data *pd = lp->pdata; + + val = pd->initial_brightness; + ret = lp855x_write_byte(lp, BRIGHTNESS_CTRL, val); + if (ret) + return ret; + + val = pd->device_control; + ret = lp855x_write_byte(lp, DEVICE_CTRL, val); + if (ret) + return ret; + + if (pd->load_new_rom_data && pd->size_program) { + for (i = 0; i < pd->size_program; i++) { + addr = pd->rom_data[i].addr; + val = pd->rom_data[i].val; + mask = pd->rom_data[i].mask; + if (!lp855x_is_valid_rom_area(lp, addr)) + continue; + + if (mask) { + u8 reg_val; + + ret = lp855x_read_byte(lp, addr, ®_val); + if (ret) + return ret; + val = (val & ~mask) | (reg_val & mask); + } + + ret = lp855x_write_byte(lp, addr, val); + if (ret) + return ret; + } + } + + return ret; +} + +static int lp855x_bl_update_status(struct backlight_device *bl) +{ + struct lp855x *lp = bl_get_data(bl); + enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode; + int ret; + + if (bl->props.state & BL_CORE_SUSPENDED) + bl->props.brightness = 0; + + if (mode == PWM_BASED) { + struct lp855x_pwm_data *pd = &lp->pdata->pwm_data; + int br = bl->props.brightness; + int max_br = bl->props.max_brightness; + + if (pd->pwm_set_intensity) + pd->pwm_set_intensity(br, max_br); + + } else if (mode == REGISTER_BASED) { + u8 val = bl->props.brightness; + ret = lp855x_write_byte(lp, BRIGHTNESS_CTRL, val); + if (ret) + return ret; + } + + return 0; +} + +static int lp855x_bl_get_brightness(struct backlight_device *bl) +{ + struct lp855x *lp = bl_get_data(bl); + enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode; + + if (mode == PWM_BASED) { + struct lp855x_pwm_data *pd = &lp->pdata->pwm_data; + int max_br = bl->props.max_brightness; + + if (pd->pwm_get_intensity) + bl->props.brightness = pd->pwm_get_intensity(max_br); + + } else if (mode == REGISTER_BASED) { + u8 val = 0; + + lp855x_read_byte(lp, BRIGHTNESS_CTRL, &val); + bl->props.brightness = val; + } + + return bl->props.brightness; +} + +static const struct backlight_ops lp855x_bl_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = lp855x_bl_update_status, + .get_brightness = lp855x_bl_get_brightness, +}; + +static int lp855x_backlight_register(struct lp855x *lp) +{ + struct backlight_device *bl; + struct backlight_properties props; + struct lp855x_platform_data *pdata = lp->pdata; + char *name = pdata->name ? : DEFAULT_BL_NAME; + + props.type = BACKLIGHT_PLATFORM; + props.max_brightness = MAX_BRIGHTNESS; + + if (pdata->initial_brightness > props.max_brightness) + pdata->initial_brightness = props.max_brightness; + + props.brightness = pdata->initial_brightness; + + bl = backlight_device_register(name, lp->dev, lp, + &lp855x_bl_ops, &props); + if (IS_ERR(bl)) + return PTR_ERR(bl); + + lp->bl = bl; + + return 0; +} + +static void lp855x_backlight_unregister(struct lp855x *lp) +{ + if (lp->bl) + backlight_device_unregister(lp->bl); +} + +static ssize_t lp855x_get_chip_id(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lp855x *lp = dev_get_drvdata(dev); + return scnprintf(buf, BUF_SIZE, "%s\n", lp->chipname); +} + +static ssize_t lp855x_get_bl_ctl_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lp855x *lp = dev_get_drvdata(dev); + enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode; + char *strmode = NULL; + + if (mode == PWM_BASED) + strmode = "pwm based"; + else if (mode == REGISTER_BASED) + strmode = "register based"; + + return scnprintf(buf, BUF_SIZE, "%s\n", strmode); +} + +static DEVICE_ATTR(chip_id, S_IRUGO, lp855x_get_chip_id, NULL); +static DEVICE_ATTR(bl_ctl_mode, S_IRUGO, lp855x_get_bl_ctl_mode, NULL); + +static struct attribute *lp855x_attributes[] = { + &dev_attr_chip_id.attr, + &dev_attr_bl_ctl_mode.attr, + NULL, +}; + +static const struct attribute_group lp855x_attr_group = { + .attrs = lp855x_attributes, +}; + +static int lp855x_set_power(struct lp855x *lp, int on) +{ + unsigned long on_udelay = lp->pdata->power_on_udelay; + + pr_info("%s : %d\n", __func__, on); + + if (on) { + int ret = 0; + + gpio_set_value(lp->pdata->gpio_en, GPIO_LEVEL_HIGH); + usleep_range(on_udelay, on_udelay); + + ret = lp855x_init_registers(lp); + if (ret) + return ret; + } else { + gpio_set_value(lp->pdata->gpio_en, GPIO_LEVEL_LOW); + } + + lp->enabled = on; + + return 0; +} + +#if defined(CONFIG_MACH_KONA) +static int lp855x_config(struct lp855x *lp) +{ + u8 val; + int ret; + + /* DEVICE CONTROL: No FAST bit to prevent LP8556 register reset */ + ret = lp855x_write_byte(lp, DEVICE_CTRL, 0x81); + if (ret) + return ret; + + /* CFG3: SCURVE_EN is linear transitions, SLOPE = 200ms, + * FILTER = heavy smoothing, + * PWM_INPUT_HYSTERESIS = 1-bit hysteresis with 12-bit resolution + */ + ret = lp855x_write_byte(lp, EEPROM_CFG3, 0x5E); + if (ret) + return ret; + + /* CFG5: No PWM_DIRECT, PS_MODE from platform data, PWM_FREQ = 9616Hz */ + val = 0x2 << 4 | 0x04; + ret = lp855x_write_byte(lp, EEPROM_CFG5, val); + + if (ret) + return ret; + + return 0; + +} +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void lp855x_early_suspend(struct early_suspend *h) +{ + struct lp855x *lp = + container_of(h, struct lp855x, early_suspend); + + lp855x_set_power(lp, 0); +} + +static void lp855x_late_resume(struct early_suspend *h) +{ + struct lp855x *lp = + container_of(h, struct lp855x, early_suspend); + + lp855x_set_power(lp, 1); + backlight_update_status(lp->bl); +#if defined(CONFIG_MACH_KONA) + lp855x_config(lp); +#endif + +} +#endif + +static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) +{ + struct lp855x *lp; + struct lp855x_platform_data *pdata = cl->dev.platform_data; + enum lp855x_brightness_ctrl_mode mode; + int ret; + + if (!pdata) { + dev_err(&cl->dev, "no platform data supplied\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) + return -EIO; + + lp = devm_kzalloc(&cl->dev, sizeof(struct lp855x), GFP_KERNEL); + if (!lp) + return -ENOMEM; + + mode = pdata->mode; + lp->client = cl; + lp->dev = &cl->dev; + lp->pdata = pdata; + lp->chipname = id->name; + lp->chip_id = id->driver_data; + i2c_set_clientdata(cl, lp); + + mutex_init(&lp->xfer_lock); + + ret = lp855x_init_registers(lp); + if (ret) { + dev_err(lp->dev, "i2c communication err: %d", ret); + if (mode == REGISTER_BASED) + goto err_dev; + } + + lp->enabled = 1; +#ifdef CONFIG_HAS_EARLYSUSPEND + if (lp->pdata->use_gpio_en) { + lp->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2; + lp->early_suspend.suspend = lp855x_early_suspend; + lp->early_suspend.resume = lp855x_late_resume; + register_early_suspend(&lp->early_suspend); + } +#endif + + ret = lp855x_backlight_register(lp); + if (ret) { + dev_err(lp->dev, + "failed to register backlight. err: %d\n", ret); + goto err_dev; + } + + ret = sysfs_create_group(&lp->dev->kobj, &lp855x_attr_group); + if (ret) { + dev_err(lp->dev, "failed to register sysfs. err: %d\n", ret); + goto err_sysfs; + } + + backlight_update_status(lp->bl); + +#if defined(CONFIG_MACH_KONA) + lp855x_config(lp); +#endif + + return 0; + +err_sysfs: + lp855x_backlight_unregister(lp); +err_dev: + return ret; +} + +static int __devexit lp855x_remove(struct i2c_client *cl) +{ + struct lp855x *lp = i2c_get_clientdata(cl); + + lp->bl->props.brightness = 0; + backlight_update_status(lp->bl); + sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group); + lp855x_backlight_unregister(lp); + + return 0; +} + +static const struct i2c_device_id lp855x_ids[] = { + {"lp8550", LP8550}, + {"lp8551", LP8551}, + {"lp8552", LP8552}, + {"lp8553", LP8553}, + {"lp8556", LP8556}, + { } +}; +MODULE_DEVICE_TABLE(i2c, lp855x_ids); + +static struct i2c_driver lp855x_driver = { + .driver = { + .name = "lp855x", + }, + .probe = lp855x_probe, + .remove = __devexit_p(lp855x_remove), + .id_table = lp855x_ids, +}; + +static int __init lp855x_init(void) +{ + return i2c_add_driver(&lp855x_driver); +} + +static void __exit lp855x_exit(void) +{ + i2c_del_driver(&lp855x_driver); +} + +module_init(lp855x_init); +module_exit(lp855x_exit); + +MODULE_DESCRIPTION("Texas Instruments LP855x Backlight driver"); +MODULE_AUTHOR("Milo Kim "); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/Kconfig b/drivers/video/samsung/Kconfig index 0234465..80f6a0a 100644 --- a/drivers/video/samsung/Kconfig +++ b/drivers/video/samsung/Kconfig @@ -273,6 +273,12 @@ config FB_S5P_S6E63M0 ---help--- This enables support for Samsung S6E63M0 MIPI LCD +config FB_S5P_NT71391 + bool "NT71391 MIPI LCD" + depends on FB_S5P_MIPI_DSIM + ---help--- + This enables support for Novatek NT71391 MIPI LCD + endchoice choice diff --git a/drivers/video/samsung/Makefile b/drivers/video/samsung/Makefile index 75995be..8934e35 100644 --- a/drivers/video/samsung/Makefile +++ b/drivers/video/samsung/Makefile @@ -15,11 +15,16 @@ obj-$(CONFIG_FB_S5P_WA101S) += s3cfb_wa101s.o obj-$(CONFIG_FB_S5P_AMS369FG06) += s3cfb_ams369fg06.o obj-$(CONFIG_FB_S5P_LD9040) += ld9040.o smart_dimming_ld9042.o obj-$(CONFIG_FB_S5P_NT35560) += nt35560.o +ifeq ($(CONFIG_MACH_KONA),y) +obj-$(CONFIG_FB_S5P_MDNIE) += s3cfb_mdnie_kona.o s3cfb_ielcd_kona.o mdnie_kona.o mdnie_tuning_kona.o +else obj-$(CONFIG_FB_S5P_MDNIE) += s3cfb_mdnie.o s3cfb_ielcd.o mdnie.o mdnie_tunning.o +endif obj-$(CONFIG_FB_S5P_LMS501KF03) += s3cfb_lms501kf03.o obj-$(CONFIG_FB_S5P_LMS501XX) += s3cfb_lms501xx.o obj-$(CONFIG_FB_S5P_DUMMY_MIPI_LCD) += s3cfb_dummymipilcd.o obj-$(CONFIG_FB_S5P_S6E8AA0) += s3cfb_s6e8aa0.o smart_dimming.o +obj-$(CONFIG_FB_S5P_NT71391) += s3cfb_nt71391.o obj-$(CONFIG_FB_S5P_EA8061) += s3cfb_ea8061.o smart_dimming_ea8061.o obj-$(CONFIG_FB_S5P_S6EVR02) += s3cfb_s6evr02.o smart_dimming_s6evr02.o s3cfb_ea8061.o smart_dimming_ea8061.o obj-$(CONFIG_FB_S5P_S6E8AB0) += s3cfb_s6e8ab0.o smart_dimming_s6e8ab0.o diff --git a/drivers/video/samsung/mdnie_color_tone_4412.h b/drivers/video/samsung/mdnie_color_tone_4412.h new file mode 100644 index 0000000..7a34444 --- /dev/null +++ b/drivers/video/samsung/mdnie_color_tone_4412.h @@ -0,0 +1,239 @@ +#ifndef __MDNIE_COLOR_TONE_H__ +#define __MDNIE_COLOR_TONE_H__ + +#include "mdnie_kona.h" + +static const unsigned short tune_scr_setting[9][3] = { + {0xff, 0xf9, 0xf9}, + {0xff, 0xf9, 0xfe}, + {0xfc, 0xfa, 0xff}, + {0xff, 0xfc, 0xf8}, + {0xff, 0xff, 0xff}, + {0xfb, 0xfb, 0xff}, + {0xfb, 0xff, 0xf5}, + {0xfa, 0xff, 0xf9}, + {0xf8, 0xff, 0xfc}, +}; + +static unsigned short tune_color_tone_1[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0020, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0xaf00, /*SCR RrCr*/ + 0x00e2, 0x00b7, /*SCR RgCg*/ + 0x00e3, 0x00bc, /*SCR RbCb*/ + 0x00e4, 0x00af, /*SCR GrMr*/ + 0x00e5, 0xb700, /*SCR GgMg*/ + 0x00e6, 0x00bc, /*SCR GbMb*/ + 0x00e7, 0x00af, /*SCR BrYr*/ + 0x00e8, 0x00b7, /*SCR BgYg*/ + 0x00e9, 0xbc00, /*SCR BbYb*/ + 0x00ea, 0x00af, /*SCR KrWr*/ + 0x00eb, 0x00b7, /*SCR KgWg*/ + 0x00ec, 0x00bc, /*SCR KbWb*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, + +}; + +static unsigned short tune_color_tone_2[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0020, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0xa000, /*SCR RrCr*/ + 0x00e2, 0x00a8, /*SCR RgCg*/ + 0x00e3, 0x00b2, /*SCR RbCb*/ + 0x00e4, 0x00a0, /*SCR GrMr*/ + 0x00e5, 0xa800, /*SCR GgMg*/ + 0x00e6, 0x00b2, /*SCR GbMb*/ + 0x00e7, 0x00a0, /*SCR BrYr*/ + 0x00e8, 0x00a8, /*SCR BgYg*/ + 0x00e9, 0xb200, /*SCR BbYb*/ + 0x00ea, 0x00a0, /*SCR KrWr*/ + 0x00eb, 0x00a8, /*SCR KgWg*/ + 0x00ec, 0x00b2, /*SCR KbWb*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_color_tone_3[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0020, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0x9100, /*SCR RrCr*/ + 0x00e2, 0x0099, /*SCR RgCg*/ + 0x00e3, 0x00a3, /*SCR RbCb*/ + 0x00e4, 0x0091, /*SCR GrMr*/ + 0x00e5, 0x9900, /*SCR GgMg*/ + 0x00e6, 0x00a3, /*SCR GbMb*/ + 0x00e7, 0x0091, /*SCR BrYr*/ + 0x00e8, 0x0099, /*SCR BgYg*/ + 0x00e9, 0xa300, /*SCR BbYb*/ + 0x00ea, 0x0091, /*SCR KrWr*/ + 0x00eb, 0x0099, /*SCR KgWg*/ + 0x00ec, 0x00a3, /*SCR KbWb*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +#if defined(CONFIG_FB_MDNIE_PWM) +static unsigned short tune_negative[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0020, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0x00ff, /*SCR RrCr*/ + 0x00e2, 0xff00, /*SCR RgCg*/ + 0x00e3, 0xff00, /*SCR RbCb*/ + 0x00e4, 0xff00, /*SCR GrMr*/ + 0x00e5, 0x00ff, /*SCR GgMg*/ + 0x00e6, 0xff00, /*SCR GbMb*/ + 0x00e7, 0xff00, /*SCR BrYr*/ + 0x00e8, 0xff00, /*SCR BgYg*/ + 0x00e9, 0x00ff, /*SCR BbYb*/ + 0x00ea, 0xff00, /*SCR KrWr*/ + 0x00eb, 0xff00, /*SCR KgWg*/ + 0x00ec, 0xff00, /*SCR KbWb*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_negative_cabc[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0220, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0x00ff, /*SCR RrCr*/ + 0x00e2, 0xff00, /*SCR RgCg*/ + 0x00e3, 0xff00, /*SCR RbCb*/ + 0x00e4, 0xff00, /*SCR GrMr*/ + 0x00e5, 0x00ff, /*SCR GgMg*/ + 0x00e6, 0xff00, /*SCR GbMb*/ + 0x00e7, 0xff00, /*SCR BrYr*/ + 0x00e8, 0xff00, /*SCR BgYg*/ + 0x00e9, 0x00ff, /*SCR BbYb*/ + 0x00ea, 0xff00, /*SCR KrWrv*/ + 0x00eb, 0xff00, /*SCR KgWg*/ + 0x00ec, 0xff00, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0075, 0x0000, /*CABC dgain*/ + 0x0076, 0x0000, + 0x0077, 0x0000, + 0x0078, 0x0000, + 0x007f, 0x0002, /*dynamic lcd*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_color_blind[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0020, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0x00ff, /*SCR RrCr*/ + 0x00e2, 0xff00, /*SCR RgCg*/ + 0x00e3, 0xff00, /*SCR RbCb*/ + 0x00e4, 0xff00, /*SCR GrMr*/ + 0x00e5, 0x00ff, /*SCR GgMg*/ + 0x00e6, 0xff00, /*SCR GbMb*/ + 0x00e7, 0xff00, /*SCR BrYr*/ + 0x00e8, 0xff00, /*SCR BgYg*/ + 0x00e9, 0x00ff, /*SCR BbYb*/ + 0x00ea, 0xff00, /*SCR KrWr*/ + 0x00eb, 0xff00, /*SCR KgWg*/ + 0x00ec, 0xff00, /*SCR KbWb*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_color_blind_cabc[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0220, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0x00ff, /*SCR RrCr*/ + 0x00e2, 0xff00, /*SCR RgCg*/ + 0x00e3, 0xff00, /*SCR RbCb*/ + 0x00e4, 0xff00, /*SCR GrMr*/ + 0x00e5, 0x00ff, /*SCR GgMg*/ + 0x00e6, 0xff00, /*SCR GbMb*/ + 0x00e7, 0xff00, /*SCR BrYr*/ + 0x00e8, 0xff00, /*SCR BgYg*/ + 0x00e9, 0x00ff, /*SCR BbYb*/ + 0x00ea, 0xff00, /*SCR KrWrv*/ + 0x00eb, 0xff00, /*SCR KgWg*/ + 0x00ec, 0xff00, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0075, 0x0000, /*CABC dgain*/ + 0x0076, 0x0000, + 0x0077, 0x0000, + 0x0078, 0x0000, + 0x007f, 0x0002, /*dynamic lcd*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; +#else +static unsigned short tune_negative[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0020, /*SCR*/ + 0x00e1, 0x00ff, /*SCR RrCr*/ + 0x00e2, 0xff00, /*SCR RgCg*/ + 0x00e3, 0xff00, /*SCR RbCb*/ + 0x00e4, 0xff00, /*SCR GrMr*/ + 0x00e5, 0x00ff, /*SCR GgMg*/ + 0x00e6, 0xff00, /*SCR GbMb*/ + 0x00e7, 0xff00, /*SCR BrYr*/ + 0x00e8, 0xff00, /*SCR BgYg*/ + 0x00e9, 0x00ff, /*SCR BbYb*/ + 0x00ea, 0xff00, /*SCR KrWr*/ + 0x00eb, 0xff00, /*SCR KgWg*/ + 0x00ec, 0xff00, /*SCR KbWb*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_color_blind[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0020, /*SCR*/ + 0x00e1, 0x00ff, /*SCR RrCr*/ + 0x00e2, 0xff00, /*SCR RgCg*/ + 0x00e3, 0xff00, /*SCR RbCb*/ + 0x00e4, 0xff00, /*SCR GrMr*/ + 0x00e5, 0x00ff, /*SCR GgMg*/ + 0x00e6, 0xff00, /*SCR GbMb*/ + 0x00e7, 0xff00, /*SCR BrYr*/ + 0x00e8, 0xff00, /*SCR BgYg*/ + 0x00e9, 0x00ff, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00ff, /*SCR KgWg*/ + 0x00ec, 0x00ff, /*SCR KbWb*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; +#endif + +struct mdnie_tuning_info negative_table[CABC_MAX] = { + {"negative", tune_negative}, +#if defined(CONFIG_FB_MDNIE_PWM) + {"negative_cabc", tune_negative_cabc}, +#endif +}; + +struct mdnie_tuning_info accessibility_table[CABC_MAX][ACCESSIBILITY_MAX] = { + { + {NULL, NULL}, + {"negative", tune_negative}, + {"color_blind", tune_color_blind}, + }, +#if defined(CONFIG_FB_MDNIE_PWM) + { + {NULL, NULL}, + {"negative_cabc", tune_negative_cabc}, + {"color_blind_cabc", tune_color_blind_cabc}, + } +#endif +}; + +struct mdnie_tuning_info color_tone_table[COLOR_TONE_MAX - COLOR_TONE_1] = { + {"color_tone_1", tune_color_tone_1}, + {"color_tone_2", tune_color_tone_2}, + {"color_tone_3", tune_color_tone_3}, +}; + +#endif /* __MDNIE_COLOR_TONE_H__ */ diff --git a/drivers/video/samsung/mdnie_kona.c b/drivers/video/samsung/mdnie_kona.c new file mode 100644 index 0000000..d44aa0e --- /dev/null +++ b/drivers/video/samsung/mdnie_kona.c @@ -0,0 +1,1171 @@ +/* linux/drivers/video/samsung/mdnie.c + * + * Register interface file for Samsung mDNIe driver + * + * Copyright (c) 2009 Samsung Electronics + * http://www.samsungsemi.com/ + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif +#include +#include + +#include "s3cfb.h" +#include "s3cfb_mdnie_kona.h" + +#if defined(CONFIG_FB_S5P_NT71391) +#include "mdnie_table_kona.h" +#endif +#include "mdnie_color_tone_4412.h" + +#if defined(CONFIG_FB_EBOOK_PANEL_SCENARIO) +#include "mdnie_table_ebook.h" +#endif + +#if defined(CONFIG_FB_MDNIE_PWM) +#define MIN_BRIGHTNESS 0 +#define DEFAULT_BRIGHTNESS 150 +#if defined(CONFIG_FB_S5P_S6F1202A) +#define CABC_CUTOFF_BACKLIGHT_VALUE 40 /* 2.5% */ +#elif defined(CONFIG_FB_S5P_S6C1372) +#define CABC_CUTOFF_BACKLIGHT_VALUE 34 +#elif defined(CONFIG_FB_S5P_NT71391) +#define CABC_CUTOFF_BACKLIGHT_VALUE 31 +#endif +#define MAX_BRIGHTNESS_LEVEL 255 +#define MID_BRIGHTNESS_LEVEL 150 +#define LOW_BRIGHTNESS_LEVEL 30 +#define DIM_BRIGHTNESS_LEVEL 20 +#endif + +#define MDNIE_SYSFS_PREFIX "/sdcard/mdnie/" +#define PANEL_COLOR_OFFSET_PATH "/sys/class/lcd/panel/color_offset" + +#if defined(CONFIG_TDMB) || defined(CONFIG_TARGET_LOCALE_NTT) +#define SCENARIO_IS_DMB(scenario) ((scenario >= DMB_NORMAL_MODE) && (scenario < DMB_MODE_MAX)) +#else +#define SCENARIO_IS_DMB(scenario) NULL +#endif + +#define SCENARIO_IS_COLOR(scenario) ((scenario >= COLOR_TONE_1) && (scenario < COLOR_TONE_MAX)) +#define SCENARIO_IS_VIDEO(scenario) ((scenario >= VIDEO_MODE) && (scenario <= VIDEO_COLD_MODE)) +#define SCENARIO_IS_VALID(scenario) (SCENARIO_IS_COLOR(scenario) || SCENARIO_IS_DMB(scenario) || scenario < SCENARIO_MAX) + +#define ACCESSIBILITY_IS_VALID(accessibility) (accessibility && (accessibility < ACCESSIBILITY_MAX)) + +#define ADDRESS_IS_SCR_BLACK(address) (address >= MDNIE_REG_BLACK_R && address <= MDNIE_REG_BLACK_B) +#define ADDRESS_IS_SCR_RGB(address) (address >= MDNIE_REG_RED_R && address <= MDNIE_REG_GREEN_B) + +#define SCR_BLACK_MASK(value) (value % MDNIE_REG_BLACK_R) +#define SCR_RGB_MASK(value) (value % MDNIE_REG_RED_R) + +struct class *mdnie_class; +struct mdnie_info *g_mdnie; + +static int mdnie_send_sequence(struct mdnie_info *mdnie, const unsigned short *seq) +{ + int ret = 0, i = 0; + const unsigned short *wbuf = NULL; + + if (IS_ERR_OR_NULL(seq)) { + dev_err(mdnie->dev, "mdnie sequence is null\n"); + return -EPERM; + } + + mutex_lock(&mdnie->dev_lock); + + wbuf = seq; + + mdnie_mask(); + + while (wbuf[i] != END_SEQ) { + ret += mdnie_write(wbuf[i], wbuf[i+1]); + i += 2; + } + + mdnie_unmask(); + + mutex_unlock(&mdnie->dev_lock); + + return ret; +} + +static struct mdnie_tuning_info *mdnie_request_table(struct mdnie_info *mdnie) +{ + struct mdnie_tuning_info *table = NULL; + + mutex_lock(&mdnie->lock); + +#if defined(CONFIG_FB_EBOOK_PANEL_SCENARIO) + if (mdnie->ebook == EBOOK_ON) { + table = &ebook_table[mdnie->cabc]; + goto exit; + } +#endif + + /* it will be removed next year */ + if (mdnie->negative == NEGATIVE_ON) { + table = &negative_table[mdnie->cabc]; + goto exit; + } + + if (ACCESSIBILITY_IS_VALID(mdnie->accessibility)) { + table = &accessibility_table[mdnie->cabc][mdnie->accessibility]; + goto exit; + } else if (SCENARIO_IS_DMB(mdnie->scenario)) { +#if defined(CONFIG_TDMB) || defined(CONFIG_TARGET_LOCALE_NTT) + table = &tune_dmb[mdnie->mode]; +#endif + goto exit; + } else if (SCENARIO_IS_COLOR(mdnie->scenario)) { + table = &color_tone_table[mdnie->scenario % COLOR_TONE_1]; + goto exit; + } else if (mdnie->scenario == CAMERA_MODE) { + table = &camera_table[mdnie->outdoor]; + goto exit; + } else if (mdnie->scenario < SCENARIO_MAX) { + table = &tuning_table[mdnie->cabc][mdnie->mode][mdnie->scenario]; + goto exit; + } + +exit: + mutex_unlock(&mdnie->lock); + + return table; +} + +static struct mdnie_tuning_info *mdnie_request_etc_table(struct mdnie_info *mdnie) +{ + struct mdnie_tuning_info *table = NULL; + + mutex_lock(&mdnie->lock); + + if (SCENARIO_IS_VIDEO(mdnie->scenario)) + mdnie->tone = mdnie->scenario - VIDEO_MODE; + else if (SCENARIO_IS_DMB(mdnie->scenario)) + mdnie->tone = mdnie->scenario % DMB_NORMAL_MODE; + + table = &etc_table[mdnie->cabc][mdnie->outdoor][mdnie->tone]; + + mutex_unlock(&mdnie->lock); + + return table; +} + +static void mdnie_update_sequence(struct mdnie_info *mdnie, struct mdnie_tuning_info *table) +{ + unsigned short *wbuf = NULL; + int ret; + + if (unlikely(mdnie->tuning)) { + ret = mdnie_request_firmware(mdnie->path, &wbuf, table->name); + if (ret < 0 && IS_ERR_OR_NULL(wbuf)) + goto exit; + mdnie_send_sequence(mdnie, wbuf); + kfree(wbuf); + } else + mdnie_send_sequence(mdnie, table->sequence); + +exit: + return; +} + +static void mdnie_update(struct mdnie_info *mdnie) +{ + struct mdnie_tuning_info *table = NULL; + + if (!mdnie->enable) { + dev_err(mdnie->dev, "mdnie state is off\n"); + return; + } + + table = mdnie_request_table(mdnie); + if (!IS_ERR_OR_NULL(table) && !IS_ERR_OR_NULL(table->sequence)) { + mdnie_update_sequence(mdnie, table); + dev_info(mdnie->dev, "%s\n", table->name); + } + + if (!(SCENARIO_IS_VIDEO(mdnie->scenario) || SCENARIO_IS_DMB(mdnie->scenario))) + goto exit; + + table = mdnie_request_etc_table(mdnie); + if (!IS_ERR_OR_NULL(table) && !IS_ERR_OR_NULL(table->sequence)) { + mdnie_update_sequence(mdnie, table); + dev_info(mdnie->dev, "%s\n", table->name); + } + +exit: + return; +} + +#if defined(CONFIG_FB_MDNIE_PWM) +static int get_backlight_level_from_brightness(struct mdnie_info *mdnie, unsigned int brightness) +{ + unsigned int value; + struct mdnie_backlight_value *pwm = mdnie->backlight; + + /* brightness tuning*/ + if (brightness >= MID_BRIGHTNESS_LEVEL) { + value = (brightness - MID_BRIGHTNESS_LEVEL) * + (pwm->max - pwm->mid) / (MAX_BRIGHTNESS_LEVEL-MID_BRIGHTNESS_LEVEL) + pwm->mid; + } else if (brightness >= LOW_BRIGHTNESS_LEVEL) { + value = (brightness - LOW_BRIGHTNESS_LEVEL) * + (pwm->mid - pwm->low) / (MID_BRIGHTNESS_LEVEL-LOW_BRIGHTNESS_LEVEL) + pwm->low; + } else if (brightness >= DIM_BRIGHTNESS_LEVEL) { + value = (brightness - DIM_BRIGHTNESS_LEVEL) * + (pwm->low - pwm->dim) / (LOW_BRIGHTNESS_LEVEL-DIM_BRIGHTNESS_LEVEL) + pwm->dim; + } else if (brightness > 0) + value = pwm->dim; + else + return 0; + + if (value > 1600) + value = 1600; + + if (value < 16) + value = 1; + else + value = value >> 4; + + return value; +} + +static void mdnie_pwm_control(struct mdnie_info *mdnie, int value) +{ + mutex_lock(&mdnie->dev_lock); + mdnie_write(MDNIE_REG_BANK_SEL, MDNIE_PWM_BANK); + mdnie_write(MDNIE_REG_PWM_CONTROL, 0xC000 | value); + mdnie_write(MDNIE_REG_MASK, 0); + mutex_unlock(&mdnie->dev_lock); +} + +static void mdnie_pwm_control_cabc(struct mdnie_info *mdnie, int value) +{ + int reg; + const unsigned char *p_plut; + u16 min_duty; + unsigned idx; + + mutex_lock(&mdnie->dev_lock); + + idx = SCENARIO_IS_VIDEO(mdnie->scenario) ? LUT_VIDEO : LUT_DEFAULT; + p_plut = power_lut[mdnie->power_lut_idx][idx]; + min_duty = p_plut[7] * value / 100; + + mdnie_write(MDNIE_REG_BANK_SEL, MDNIE_PWM_BANK); + + if (min_duty < 4) + reg = 0xC000 | (max(1, (value * p_plut[3] / 100))); + else { + /*PowerLUT*/ + mdnie_write(MDNIE_REG_POWER_LUT0, (p_plut[0] * value / 100) << 8 | (p_plut[1] * value / 100)); + mdnie_write(MDNIE_REG_POWER_LUT2, (p_plut[2] * value / 100) << 8 | (p_plut[3] * value / 100)); + mdnie_write(MDNIE_REG_POWER_LUT4, (p_plut[4] * value / 100) << 8 | (p_plut[5] * value / 100)); + mdnie_write(MDNIE_REG_POWER_LUT6, (p_plut[6] * value / 100) << 8 | (p_plut[7] * value / 100)); + mdnie_write(MDNIE_REG_POWER_LUT8, (p_plut[8] * value / 100) << 8); + + reg = 0x5000 | (value << 4); + } + + mdnie_write(MDNIE_REG_PWM_CONTROL, reg); + mdnie_write(MDNIE_REG_MASK, 0); + + mutex_unlock(&mdnie->dev_lock); +} + +void set_mdnie_pwm_value(struct mdnie_info *mdnie, int value) +{ + mdnie_pwm_control(mdnie, value); +} + +static int update_brightness(struct mdnie_info *mdnie) +{ + unsigned int value; + unsigned int brightness = mdnie->bd->props.brightness; + + value = get_backlight_level_from_brightness(mdnie, brightness); + + if (!mdnie->enable) { + dev_err(mdnie->dev, "mdnie states is off\n"); + return 0; + } + + if (brightness <= CABC_CUTOFF_BACKLIGHT_VALUE) { + mdnie_pwm_control(mdnie, value); + } else { + if ((mdnie->cabc) && (mdnie->scenario != CAMERA_MODE) && !(mdnie->tuning)) + mdnie_pwm_control_cabc(mdnie, value); + else + mdnie_pwm_control(mdnie, value); + } + return 0; +} + +static int mdnie_set_brightness(struct backlight_device *bd) +{ + struct mdnie_info *mdnie = bl_get_data(bd); + int ret = 0; + unsigned int brightness = bd->props.brightness; + + if (brightness < MIN_BRIGHTNESS || + brightness > bd->props.max_brightness) { + dev_err(&bd->dev, "lcd brightness should be %d to %d. now %d\n", + MIN_BRIGHTNESS, bd->props.max_brightness, brightness); + brightness = bd->props.max_brightness; + } + + if ((mdnie->enable) && (mdnie->bd_enable)) { + ret = update_brightness(mdnie); + dev_info(&bd->dev, "brightness=%d\n", bd->props.brightness); + if (ret < 0) + return -EINVAL; + } + + return ret; +} + +static int mdnie_get_brightness(struct backlight_device *bd) +{ + return bd->props.brightness; +} + +static const struct backlight_ops mdnie_backlight_ops = { + .get_brightness = mdnie_get_brightness, + .update_status = mdnie_set_brightness, +}; +#endif + +static void update_color_position(struct mdnie_info *mdnie, u16 idx) +{ + u8 cabc, mode, scenario, outdoor, i; + unsigned short *wbuf; + + dev_info(mdnie->dev, "%s: idx=%d\n", __func__, idx); + + mutex_lock(&mdnie->lock); + + for (cabc = 0; cabc < CABC_MAX; cabc++) { + for (mode = 0; mode <= STANDARD; mode++) { + for (scenario = 0; scenario < SCENARIO_MAX; scenario++) { + wbuf = tuning_table[cabc][mode][scenario].sequence; + if (IS_ERR_OR_NULL(wbuf)) + continue; + i = 0; + while (wbuf[i] != END_SEQ) { + if (ADDRESS_IS_SCR_BLACK(wbuf[i])) + wbuf[i+1] = tune_scr_setting[idx][SCR_BLACK_MASK(wbuf[i])]; + i += 2; + } + } + } + } + + for (outdoor = 0; outdoor < OUTDOOR_MAX; outdoor++) { + wbuf = camera_table[outdoor].sequence; + if (IS_ERR_OR_NULL(wbuf)) + continue; + i = 0; + while (wbuf[i] != END_SEQ) { + if (ADDRESS_IS_SCR_BLACK(wbuf[i])) + wbuf[i+1] = tune_scr_setting[idx][SCR_BLACK_MASK(wbuf[i])]; + i += 2; + } + } + + mutex_unlock(&mdnie->lock); +} + +static int get_panel_color_position(struct mdnie_info *mdnie, int *result) +{ + int ret = 0; + char *fp = NULL; + unsigned int offset[2] = {0,}; + + if (likely(mdnie->color_correction)) + goto skip_color_correction; + + ret = mdnie_open_file(PANEL_COLOR_OFFSET_PATH, &fp); + if (IS_ERR_OR_NULL(fp) || ret <= 0) { + dev_info(mdnie->dev, "%s: open fail: %s, %d\n", __func__, PANEL_COLOR_OFFSET_PATH, ret); + ret = -EINVAL; + goto skip_color_correction; + } + + ret = sscanf(fp, "0x%x, 0x%x", &offset[0], &offset[1]); + if (!(offset[0] + offset[1]) || ret != 2) { + dev_info(mdnie->dev, "%s: 0x%x, 0x%x\n", __func__, offset[0], offset[1]); + ret = -EINVAL; + goto skip_color_correction; + } + + ret = mdnie_calibration(offset[0], offset[1], result); + dev_info(mdnie->dev, "%s: %x, %x, idx=%d\n", __func__, offset[0], offset[1], ret - 1); + +skip_color_correction: + mdnie->color_correction = 1; + if (!IS_ERR_OR_NULL(fp)) + kfree(fp); + + return ret; +} + +static ssize_t mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", mdnie->mode); +} + +static ssize_t mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + unsigned int value = 0; + int result[5] = {0,}; + int ret; + + ret = kstrtoul(buf, 0, (unsigned long *)&value); + if (ret) + return -EINVAL; + + dev_info(dev, "%s :: value=%d\n", __func__, value); + + if (value >= MODE_MAX) { + value = STANDARD; + return -EINVAL; + } + + mutex_lock(&mdnie->lock); + mdnie->mode = value; + mutex_unlock(&mdnie->lock); + + if (!mdnie->color_correction) { + ret = get_panel_color_position(mdnie, result); + if (ret > 0) + update_color_position(mdnie, ret - 1); + } + + mdnie_update(mdnie); +#if defined(CONFIG_FB_MDNIE_PWM) + if ((mdnie->enable) && (mdnie->bd_enable)) + update_brightness(mdnie); +#endif + + return count; +} + + +static ssize_t scenario_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", mdnie->scenario); +} + +static ssize_t scenario_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + unsigned int value; + int ret; + + ret = kstrtoul(buf, 0, (unsigned long *)&value); + + dev_info(dev, "%s :: value=%d\n", __func__, value); + + if (!SCENARIO_IS_VALID(value)) + value = UI_MODE; + +#if defined(CONFIG_FB_MDNIE_PWM) + if (value >= SCENARIO_MAX) + value = UI_MODE; +#endif + + mutex_lock(&mdnie->lock); + mdnie->scenario = value; + mutex_unlock(&mdnie->lock); + + mdnie_update(mdnie); +#if defined(CONFIG_FB_MDNIE_PWM) + if ((mdnie->enable) && (mdnie->bd_enable)) + update_brightness(mdnie); +#endif + + return count; +} + + +static ssize_t outdoor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", mdnie->outdoor); +} + +static ssize_t outdoor_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + unsigned int value; + int ret; + + ret = kstrtoul(buf, 0, (unsigned long *)&value); + + dev_info(dev, "%s :: value=%d\n", __func__, value); + + if (value >= OUTDOOR_MAX) + value = OUTDOOR_OFF; + + value = (value) ? OUTDOOR_ON : OUTDOOR_OFF; + + mutex_lock(&mdnie->lock); + mdnie->outdoor = value; + mutex_unlock(&mdnie->lock); + + mdnie_update(mdnie); + + return count; +} + + +#if defined(CONFIG_FB_MDNIE_PWM) +static ssize_t cabc_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", mdnie->cabc); +} + +static ssize_t cabc_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + unsigned int value; + int ret; + +#if defined(CONFIG_FB_S5P_S6C1372) + if (mdnie->auto_brightness) + return -EINVAL; +#endif + + ret = strict_strtoul(buf, 0, (unsigned long *)&value); + + dev_info(dev, "%s :: value=%d\n", __func__, value); + + if (value >= CABC_MAX) + value = CABC_OFF; + + value = (value) ? CABC_ON : CABC_OFF; + + mutex_lock(&mdnie->lock); + mdnie->cabc = value; + mutex_unlock(&mdnie->lock); + + mdnie_update(mdnie); + if ((mdnie->enable) && (mdnie->bd_enable)) + update_brightness(mdnie); + + return count; +} + +static ssize_t auto_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + char *pos = buf; + int i; + + pos += sprintf(pos, "%d, %d, ", mdnie->auto_brightness, mdnie->power_lut_idx); + for (i = 0; i < 5; i++) + pos += sprintf(pos, "0x%02x, ", power_lut[mdnie->power_lut_idx][0][i]); + pos += sprintf(pos, "\n"); + + return pos - buf; +} + +static ssize_t auto_brightness_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (mdnie->auto_brightness != value) { + dev_info(dev, "%s - %d -> %d\n", __func__, mdnie->auto_brightness, value); + mutex_lock(&mdnie->dev_lock); + mdnie->auto_brightness = value; +#if defined(CONFIG_FB_S5P_S6C1372) + mutex_lock(&mdnie->lock); + mdnie->cabc = (value) ? CABC_ON : CABC_OFF; + mutex_unlock(&mdnie->lock); +#endif + if (mdnie->auto_brightness >= 5) + mdnie->power_lut_idx = LUT_LEVEL_OUTDOOR_2; + else if (mdnie->auto_brightness == 4) + mdnie->power_lut_idx = LUT_LEVEL_OUTDOOR_1; + else + mdnie->power_lut_idx = LUT_LEVEL_MANUAL_AND_INDOOR; + mutex_unlock(&mdnie->dev_lock); + mdnie_update(mdnie); + if (mdnie->bd_enable) + update_brightness(mdnie); + } + } + return size; +} + +static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_store); +#endif + +static ssize_t tuning_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + char *pos = buf; + struct mdnie_tuning_info *table; + int ret, i; + unsigned short *wbuf; + + pos += sprintf(pos, "++ %s: %s\n", __func__, mdnie->path); + + if (!mdnie->tuning) { + pos += sprintf(pos, "tunning mode is off\n"); + goto exit; + } + + if (strncmp(mdnie->path, MDNIE_SYSFS_PREFIX, sizeof(MDNIE_SYSFS_PREFIX) - 1)) { + pos += sprintf(pos, "file path is invalid, %s\n", mdnie->path); + goto exit; + } + + table = mdnie_request_table(mdnie); + if (!IS_ERR_OR_NULL(table)) { + ret = mdnie_request_firmware(mdnie->path, &wbuf, table->name); + i = 0; + while (wbuf[i] != END_SEQ) { + pos += sprintf(pos, "0x%04x, 0x%04x\n", wbuf[i], wbuf[i+1]); + i += 2; + } + if (!IS_ERR_OR_NULL(wbuf)) + kfree(wbuf); + pos += sprintf(pos, "%s\n", table->name); + } + + if (!(SCENARIO_IS_VIDEO(mdnie->scenario) || SCENARIO_IS_DMB(mdnie->scenario))) + goto exit; + + table = mdnie_request_etc_table(mdnie); + if (!IS_ERR_OR_NULL(table)) { + ret = mdnie_request_firmware(mdnie->path, &wbuf, table->name); + i = 0; + while (wbuf[i] != END_SEQ) { + pos += sprintf(pos, "0x%04x, 0x%04x\n", wbuf[i], wbuf[i+1]); + i += 2; + } + if (!IS_ERR_OR_NULL(wbuf)) + kfree(wbuf); + pos += sprintf(pos, "%s\n", table->name); + } + +exit: + pos += sprintf(pos, "-- %s\n", __func__); + + return pos - buf; +} + +static ssize_t tuning_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + int ret; + + if (sysfs_streq(buf, "0") || sysfs_streq(buf, "1")) { + ret = kstrtoul(buf, 0, (unsigned long *)&mdnie->tuning); + if (!mdnie->tuning) + memset(mdnie->path, 0, sizeof(mdnie->path)); + dev_info(dev, "%s :: %s\n", __func__, mdnie->tuning ? "enable" : "disable"); + } else { + if (!mdnie->tuning) + return count; + + if (count > (sizeof(mdnie->path) - sizeof(MDNIE_SYSFS_PREFIX))) { + dev_err(dev, "file name %s is too long\n", mdnie->path); + return -ENOMEM; + } + + memset(mdnie->path, 0, sizeof(mdnie->path)); + snprintf(mdnie->path, sizeof(MDNIE_SYSFS_PREFIX) + count-1, "%s%s", MDNIE_SYSFS_PREFIX, buf); + dev_info(dev, "%s :: %s\n", __func__, mdnie->path); + + mdnie_update(mdnie); + } + + return count; +} + +static ssize_t negative_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", mdnie->negative); +} + +static ssize_t negative_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + unsigned int value; + int ret; + + ret = kstrtoul(buf, 0, (unsigned long *)&value); + + dev_info(dev, "%s :: value=%d\n", __func__, value); + + if (ret < 0) + return ret; + else { + if (mdnie->negative == value) + return count; + + if (value >= NEGATIVE_MAX) + value = NEGATIVE_OFF; + + value = (value) ? NEGATIVE_ON : NEGATIVE_OFF; + + mutex_lock(&mdnie->lock); + mdnie->negative = value; + mutex_unlock(&mdnie->lock); + + mdnie_update(mdnie); + } + return count; +} + +static ssize_t accessibility_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + char *pos = buf; + unsigned short *wbuf; + int i = 0; + + pos += sprintf(pos, "%d, ", mdnie->accessibility); + if (mdnie->accessibility == COLOR_BLIND) { + if (!IS_ERR_OR_NULL(accessibility_table[mdnie->cabc][COLOR_BLIND].sequence)) { + wbuf = accessibility_table[mdnie->cabc][COLOR_BLIND].sequence; + while (wbuf[i] != END_SEQ) { + if (ADDRESS_IS_SCR_RGB(wbuf[i])) + pos += sprintf(pos, "0x%04x, ", wbuf[i+1]); + i += 2; + } + } + } + pos += sprintf(pos, "\n"); + + return pos - buf; +} + +static ssize_t accessibility_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + unsigned int value, s[9], cabc, i, len = 0; + int ret; + unsigned short *wbuf; + char str[100] = {0,}; + + ret = sscanf(buf, "%d %x %x %x %x %x %x %x %x %x", + &value, &s[0], &s[1], &s[2], &s[3], + &s[4], &s[5], &s[6], &s[7], &s[8]); + + dev_info(dev, "%s :: value=%d\n", __func__, value); + + if (ret < 0) + return ret; + else { + if (value >= ACCESSIBILITY_MAX) + value = ACCESSIBILITY_OFF; + + mutex_lock(&mdnie->lock); + mdnie->accessibility = value; + if (value == COLOR_BLIND) { + if (ret != 10) { + mutex_unlock(&mdnie->lock); + return -EINVAL; + } + + for (cabc = 0; cabc < CABC_MAX; cabc++) { + wbuf = accessibility_table[cabc][COLOR_BLIND].sequence; + if (IS_ERR_OR_NULL(wbuf)) + continue; + i = 0; + while (wbuf[i] != END_SEQ) { + if (ADDRESS_IS_SCR_RGB(wbuf[i])) + wbuf[i+1] = s[SCR_RGB_MASK(wbuf[i])]; + i += 2; + } + } + + i = 0; + len = sprintf(str + len, "%s :: ", __func__); + while (len < sizeof(str) && i < ARRAY_SIZE(s)) { + len += sprintf(str + len, "0x%04x, ", s[i]); + i++; + } + dev_info(dev, "%s\n", str); + } + mutex_unlock(&mdnie->lock); + + mdnie_update(mdnie); + } + return count; +} + +static ssize_t color_correct_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + char *pos = buf; + int i; + int result[5] = {0,}; + + if (!mdnie->color_correction) + return -EINVAL; + + for (i = 1; i < ARRAY_SIZE(result); i++) + pos += sprintf(pos, "F%d= %d, ", i, result[i]); + pos += sprintf(pos, "idx=%d\n", get_panel_color_position(mdnie, result)); + + return pos - buf; +} + +#if defined(CONFIG_FB_EBOOK_PANEL_SCENARIO) +static ssize_t ebook_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", mdnie->ebook); +} + +static ssize_t ebook_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mdnie_info *mdnie = dev_get_drvdata(dev); + unsigned int value; + int ret; + + ret = strict_strtoul(buf, 0, (unsigned long *)&value); + + dev_info(dev, "%s :: value=%d\n", __func__, value); + + if (ret < 0) + return ret; + else { + if (mdnie->ebook == value) + return count; + + if (value >= EBOOK_MAX) + value = EBOOK_OFF; + + value = (value) ? EBOOK_ON : EBOOK_OFF; + + mutex_lock(&mdnie->lock); + mdnie->ebook = value; + mutex_unlock(&mdnie->lock); + + mdnie_update(mdnie); + } + return count; +} +#endif + +static struct device_attribute mdnie_attributes[] = { + __ATTR(mode, 0664, mode_show, mode_store), + __ATTR(scenario, 0664, scenario_show, scenario_store), + __ATTR(outdoor, 0664, outdoor_show, outdoor_store), +#if defined(CONFIG_FB_MDNIE_PWM) + __ATTR(cabc, 0664, cabc_show, cabc_store), +#endif + __ATTR(tuning, 0664, tuning_show, tuning_store), + __ATTR(negative, 0664, negative_show, negative_store), + __ATTR(accessibility, 0664, accessibility_show, accessibility_store), + __ATTR(color_correct, 0444, color_correct_show, NULL), +#if defined(CONFIG_FB_EBOOK_PANEL_SCENARIO) + __ATTR(ebook, 0664, ebook_show, ebook_store), +#endif + __ATTR_NULL, +}; + +#ifdef CONFIG_PM +#if defined(CONFIG_HAS_EARLYSUSPEND) +#if defined(CONFIG_FB_MDNIE_PWM) +static void mdnie_early_suspend(struct early_suspend *h) +{ + struct mdnie_info *mdnie = container_of(h, struct mdnie_info, early_suspend); + struct lcd_platform_data *pd = mdnie->lcd_pd; + + dev_info(mdnie->dev, "+%s\n", __func__); + + mdnie->bd_enable = FALSE; + + if (mdnie->enable) + mdnie_pwm_control(mdnie, 0); + + if (pd && pd->power_on) + pd->power_on(NULL, 0); + + dev_info(mdnie->dev, "-%s\n", __func__); + + return; +} +#endif + +static void mdnie_late_resume(struct early_suspend *h) +{ + struct mdnie_info *mdnie = container_of(h, struct mdnie_info, early_suspend); +#if defined(CONFIG_FB_MDNIE_PWM) + struct lcd_platform_data *pd = mdnie->lcd_pd; +#endif + + dev_info(mdnie->dev, "+%s\n", __func__); + +#if defined(CONFIG_FB_MDNIE_PWM) + if (mdnie->enable) + mdnie_pwm_control(mdnie, 0); + + if (pd && pd->power_on) + pd->power_on(NULL, 1); + + if (mdnie->enable) { + dev_info(&mdnie->bd->dev, "brightness=%d\n", mdnie->bd->props.brightness); + update_brightness(mdnie); + } + + mdnie->bd_enable = TRUE; +#endif + + mdnie_update(mdnie); + + dev_info(mdnie->dev, "-%s\n", __func__); + + return; +} +#endif +#endif + +static int mdnie_probe(struct platform_device *pdev) +{ +#if defined(CONFIG_FB_MDNIE_PWM) + struct platform_mdnie_data *pdata = pdev->dev.platform_data; +#endif + struct mdnie_info *mdnie; + int ret = 0; + + mdnie_class = class_create(THIS_MODULE, dev_name(&pdev->dev)); + if (IS_ERR_OR_NULL(mdnie_class)) { + pr_err("failed to create mdnie class\n"); + ret = -EINVAL; + goto error0; + } + + mdnie_class->dev_attrs = mdnie_attributes; + + mdnie = kzalloc(sizeof(struct mdnie_info), GFP_KERNEL); + if (!mdnie) { + pr_err("failed to allocate mdnie\n"); + ret = -ENOMEM; + goto error1; + } + + mdnie->dev = device_create(mdnie_class, &pdev->dev, 0, &mdnie, "mdnie"); + if (IS_ERR_OR_NULL(mdnie->dev)) { + pr_err("failed to create mdnie device\n"); + ret = -EINVAL; + goto error2; + } + +#if defined(CONFIG_FB_MDNIE_PWM) + if (!pdata) { + pr_err("no platform data specified\n"); + ret = -EINVAL; + goto error2; + } + + mdnie->bd = backlight_device_register("panel", mdnie->dev, + mdnie, &mdnie_backlight_ops, NULL); + mdnie->bd->props.max_brightness = MAX_BRIGHTNESS_LEVEL; + mdnie->bd->props.brightness = DEFAULT_BRIGHTNESS; + mdnie->bd_enable = TRUE; + mdnie->lcd_pd = pdata->lcd_pd; + + ret = device_create_file(&mdnie->bd->dev, &dev_attr_auto_brightness); + if (ret < 0) + dev_err(&mdnie->bd->dev, "failed to add sysfs entries, %d\n", __LINE__); +#endif + + mdnie->scenario = UI_MODE; + mdnie->mode = STANDARD; + mdnie->tone = TONE_NORMAL; + mdnie->outdoor = OUTDOOR_OFF; + mdnie->enable = TRUE; + mdnie->tuning = FALSE; + mdnie->negative = NEGATIVE_OFF; + mdnie->accessibility = ACCESSIBILITY_OFF; + mdnie->cabc = CABC_OFF; + +#if defined(CONFIG_FB_MDNIE_PWM) +#if defined(CONFIG_FB_S5P_S6F1202A) + mdnie->cabc = CABC_ON; +#endif + mdnie->power_lut_idx = LUT_LEVEL_MANUAL_AND_INDOOR; + mdnie->auto_brightness = 0; +#endif + +#if defined(CONFIG_FB_EBOOK_PANEL_SCENARIO) + mdnie->ebook = EBOOK_OFF; +#endif + + mutex_init(&mdnie->lock); + mutex_init(&mdnie->dev_lock); + + platform_set_drvdata(pdev, mdnie); + dev_set_drvdata(mdnie->dev, mdnie); + +#ifdef CONFIG_HAS_EARLYSUSPEND +#if defined(CONFIG_FB_MDNIE_PWM) + mdnie->early_suspend.suspend = mdnie_early_suspend; +#endif + mdnie->early_suspend.resume = mdnie_late_resume; + mdnie->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1; + register_early_suspend(&mdnie->early_suspend); +#endif + + +#if defined(CONFIG_FB_MDNIE_PWM) + dev_info(mdnie->dev, "lcdtype = %d\n", pdata->display_type); + if (pdata->display_type > ARRAY_SIZE(backlight_table)) + pdata->display_type = 0; + mdnie->backlight = &backlight_table[pdata->display_type]; +#endif + +#if defined(CONFIG_FB_S5P_S6F1202A) + if (pdata->display_type == 0) { + memcpy(tuning_table, tuning_table_hydis, sizeof(tuning_table)); + memcpy(etc_table, etc_table_hydis, sizeof(etc_table)); + memcpy(camera_table, camera_table_hydis, sizeof(camera_table)); + } else if (pdata->display_type == 1) { + memcpy(tuning_table, tuning_table_sec, sizeof(tuning_table)); + memcpy(etc_table, etc_table_sec, sizeof(etc_table)); + memcpy(camera_table, camera_table_sec, sizeof(camera_table)); + } else if (pdata->display_type == 2) { + memcpy(tuning_table, tuning_table_boe, sizeof(tuning_table)); + memcpy(etc_table, etc_table_boe, sizeof(etc_table)); + memcpy(camera_table, camera_table_boe, sizeof(camera_table)); + } +#endif + + g_mdnie = mdnie; + + mdnie_update(mdnie); + + dev_info(mdnie->dev, "registered successfully\n"); + + return 0; + +error2: + kfree(mdnie); +error1: + class_destroy(mdnie_class); +error0: + return ret; +} + +static int mdnie_remove(struct platform_device *pdev) +{ + struct mdnie_info *mdnie = dev_get_drvdata(&pdev->dev); + +#if defined(CONFIG_FB_MDNIE_PWM) + backlight_device_unregister(mdnie->bd); +#endif + class_destroy(mdnie_class); + kfree(mdnie); + + return 0; +} + +static void mdnie_shutdown(struct platform_device *pdev) +{ +#if defined(CONFIG_FB_MDNIE_PWM) + struct mdnie_info *mdnie = dev_get_drvdata(&pdev->dev); + struct lcd_platform_data *pd = NULL; + pd = mdnie->lcd_pd; + + dev_info(mdnie->dev, "+%s\n", __func__); + + mdnie->bd_enable = FALSE; + + if (mdnie->enable) + mdnie_pwm_control(mdnie, 0); + + if (pd && pd->power_on) + pd->power_on(NULL, 0); + + dev_info(mdnie->dev, "-%s\n", __func__); +#endif +} + + +static struct platform_driver mdnie_driver = { + .driver = { + .name = "mdnie", + .owner = THIS_MODULE, + }, + .probe = mdnie_probe, + .remove = mdnie_remove, +#ifndef CONFIG_HAS_EARLYSUSPEND + .suspend = mdnie_suspend, + .resume = mdnie_resume, +#endif + .shutdown = mdnie_shutdown, +}; + +static int __init mdnie_init(void) +{ + return platform_driver_register(&mdnie_driver); +} +module_init(mdnie_init); + +static void __exit mdnie_exit(void) +{ + platform_driver_unregister(&mdnie_driver); +} +module_exit(mdnie_exit); + +MODULE_DESCRIPTION("mDNIe Driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/samsung/mdnie_kona.h b/drivers/video/samsung/mdnie_kona.h new file mode 100644 index 0000000..b5c95ab --- /dev/null +++ b/drivers/video/samsung/mdnie_kona.h @@ -0,0 +1,148 @@ +#ifndef __MDNIE_H__ +#define __MDNIE_H__ + +#define END_SEQ 0xffff + +enum MODE { + DYNAMIC, + STANDARD, +#if !defined(CONFIG_FB_MDNIE_PWM) + NATURAL, +#endif + MOVIE, + MODE_MAX, +}; + +enum SCENARIO { + CYANOGENMOD_MODE, + UI_MODE, + VIDEO_MODE, + VIDEO_WARM_MODE, + VIDEO_COLD_MODE, + CAMERA_MODE, + NAVI_MODE, + GALLERY_MODE, + VT_MODE, + SCENARIO_MAX, + COLOR_TONE_1 = 40, + COLOR_TONE_2, + COLOR_TONE_3, + COLOR_TONE_MAX, +}; + +enum SCENARIO_DMB { + DMB_NORMAL_MODE = 20, + DMB_WARM_MODE, + DMB_COLD_MODE, + DMB_MODE_MAX, +}; + +enum OUTDOOR { + OUTDOOR_OFF, + OUTDOOR_ON, + OUTDOOR_MAX, +}; + +enum TONE { + TONE_NORMAL, + TONE_WARM, + TONE_COLD, + TONE_MAX, +}; + +enum CABC { + CABC_OFF, +#if defined(CONFIG_FB_MDNIE_PWM) + CABC_ON, +#endif + CABC_MAX, +}; + +enum POWER_LUT { + LUT_DEFAULT, + LUT_VIDEO, + LUT_MAX, +}; + +enum POWER_LUT_LEVEL { + LUT_LEVEL_MANUAL_AND_INDOOR, + LUT_LEVEL_OUTDOOR_1, + LUT_LEVEL_OUTDOOR_2, + LUT_LEVEL_MAX, +}; + +enum NEGATIVE { + NEGATIVE_OFF, + NEGATIVE_ON, + NEGATIVE_MAX, +}; + +enum ACCESSIBILITY { + ACCESSIBILITY_OFF, + NEGATIVE, + COLOR_BLIND, + ACCESSIBILITY_MAX, +}; + +#if defined(CONFIG_FB_EBOOK_PANEL_SCENARIO) +enum EBOOK { + EBOOK_OFF, + EBOOK_ON, + EBOOK_MAX, +}; +#endif + +struct mdnie_tuning_info { + char *name; + unsigned short * const sequence; +}; + +struct mdnie_backlight_value { + const unsigned int max; + const unsigned int mid; + const unsigned char low; + const unsigned char dim; +}; + +struct mdnie_info { + struct device *dev; +#if defined(CONFIG_FB_MDNIE_PWM) + struct lcd_platform_data *lcd_pd; + struct backlight_device *bd; + unsigned int bd_enable; + unsigned int auto_brightness; + unsigned int power_lut_idx; + struct mdnie_backlight_value *backlight; +#endif + struct mutex lock; + struct mutex dev_lock; + + unsigned int enable; + enum SCENARIO scenario; + enum MODE mode; + enum TONE tone; + enum OUTDOOR outdoor; + enum CABC cabc; + unsigned int tuning; + unsigned int negative; + unsigned int accessibility; + unsigned int color_correction; + char path[50]; +#if defined(CONFIG_FB_EBOOK_PANEL_SCENARIO) + unsigned int ebook; +#endif +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif +}; + +extern struct mdnie_info *g_mdnie; + +#if defined(CONFIG_FB_MDNIE_PWM) +extern void set_mdnie_pwm_value(struct mdnie_info *mdnie, int value); +#endif +extern int mdnie_calibration(unsigned short x, unsigned short y, int *r); +extern int mdnie_request_firmware(const char *path, u16 **buf, char *name); +extern int mdnie_open_file(const char *path, char **fp); + +#endif /* __MDNIE_H__ */ diff --git a/drivers/video/samsung/mdnie_table_4412_kona.h b/drivers/video/samsung/mdnie_table_4412_kona.h new file mode 100644 index 0000000..40e7c07 --- /dev/null +++ b/drivers/video/samsung/mdnie_table_4412_kona.h @@ -0,0 +1,319 @@ +#ifndef __MDNIE_TABLE_H__ +#define __MDNIE_TABLE_H__ + +#include "mdnie_kona.h" + + +static unsigned short tune_dynamic_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_natural_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_natural_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_natural_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_natural_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_camera[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ +}; + +static unsigned short tune_camera_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ +}; + +static unsigned short tune_cold[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_cold_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_normal_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_warm[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_warm_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +#if defined(CONFIG_FB_MDNIE_PWM) +struct mdnie_tuning_info etc_table[CABC_MAX][OUTDOOR_MAX][TONE_MAX] = { + { + { + {"normal", NULL}, + {"warm", tune_warm}, + {"cold", tune_cold}, + }, + { + {"normal_outdoor", tune_normal_outdoor}, + {"warm_outdoor", tune_warm_outdoor}, + {"cold_outdoor", tune_cold_outdoor}, + }, + }, + { + { + {"normal_cabc", NULL}, + {"warm_cabc", tune_warm}, + {"cold_cabc", tune_cold}, + }, + { + {"normal_outdoor_cabc", tune_normal_outdoor}, + {"warm_outdoor_cabc", tune_warm_outdoor}, + {"cold_outdoor_cabc", tune_cold_outdoor}, + }, + }, +}; + +struct mdnie_tuning_info tuning_table[CABC_MAX][MODE_MAX][SCENARIO_MAX] = { + { + { + {"dynamic_ui", tune_dynamic_ui}, + {"dynamic_video", tune_dynamic_video}, + {"dynamic_video", tune_dynamic_video}, + {"dynamic_video", tune_dynamic_video}, + {"camera", NULL}, + {"dynamic_ui", tune_dynamic_ui}, + {"dynamic_gallery", tune_dynamic_gallery}, + {"dynamic_vt", tune_dynamic_vt}, + }, { + {"standard_ui", tune_standard_ui}, + {"standard_video", tune_standard_video}, + {"standard_video", tune_standard_video}, + {"standard_video", tune_standard_video}, + {"camera", NULL}, + {"standard_ui", tune_standard_ui}, + {"standard_gallery", tune_standard_gallery}, + {"standard_vt", tune_standard_vt}, + }, { + {"movie_ui", tune_movie_ui}, + {"movie_video", tune_movie_video}, + {"movie_video", tune_movie_video}, + {"movie_video", tune_movie_video}, + {"camera", NULL}, + {"movie_ui", tune_movie_ui}, + {"movie_gallery", tune_movie_gallery}, + {"movie_vt", tune_movie_vt}, + }, + }, { + { + {"dynamic_ui_cabc", tune_dynamic_ui}, + {"dynamic_video_cabc", tune_dynamic_video}, + {"dynamic_video_cabc", tune_dynamic_video}, + {"dynamic_video_cabc", tune_dynamic_video}, + {"camera", NULL}, + {"dynamic_ui_cabc", tune_dynamic_ui}, + {"dynamic_gallery_cabc", tune_dynamic_gallery}, + {"dynamic_vt_cabc", tune_dynamic_vt}, + }, { + {"standard_ui_cabc", tune_standard_ui}, + {"standard_video_cabc", tune_standard_video}, + {"standard_video_cabc", tune_standard_video}, + {"standard_video_cabc", tune_standard_video}, + {"camera", NULL}, + {"standard_ui_cabc", tune_standard_ui}, + {"standard_gallery_cabc", tune_standard_gallery}, + {"standard_vt_cabc", tune_standard_vt}, + }, { + {"movie_ui_cabc", tune_movie_ui}, + {"movie_video_cabc", tune_movie_video}, + {"movie_video_cabc", tune_movie_video}, + {"movie_video_cabc", tune_movie_video}, + {"camera", NULL}, + {"movie_ui_cabc", tune_movie_ui}, + {"movie_gallery_cabc", tune_movie_gallery}, + {"movie_vt_cabc", tune_movie_vt}, + }, + }, +}; +#else +struct mdnie_tuning_info etc_table[CABC_MAX][OUTDOOR_MAX][TONE_MAX] = { + { + { + {"normal", NULL}, + {"warm", tune_warm}, + {"cold", tune_cold}, + }, + { + {"normal_outdoor", tune_normal_outdoor}, + {"warm_outdoor", tune_warm_outdoor}, + {"cold_outdoor", tune_cold_outdoor}, + }, + } +}; + +struct mdnie_tuning_info tuning_table[CABC_MAX][MODE_MAX][SCENARIO_MAX] = { + { + { + {"dynamic_ui", tune_dynamic_ui}, + {"dynamic_video", tune_dynamic_video}, + {"dynamic_video", tune_dynamic_video}, + {"dynamic_video", tune_dynamic_video}, + {"camera", NULL/*tune_camera*/}, + {"dynamic_ui", tune_dynamic_ui}, + {"dynamic_gallery", tune_dynamic_gallery}, + {"dynamic_vt", tune_dynamic_vt}, + }, { + {"standard_ui", tune_standard_ui}, + {"standard_video", tune_standard_video}, + {"standard_video", tune_standard_video}, + {"standard_video", tune_standard_video}, + {"camera", NULL/*tune_camera*/}, + {"standard_ui", tune_standard_ui}, + {"standard_gallery", tune_standard_gallery}, + {"standard_vt", tune_standard_vt}, + }, { + {"natural_ui", tune_natural_ui}, + {"natural_video", tune_natural_video}, + {"natural_video", tune_natural_video}, + {"natural_video", tune_natural_video}, + {"camera", NULL/*tune_camera*/}, + {"natural_ui", tune_natural_ui}, + {"natural_gallery", tune_natural_gallery}, + {"natural_vt", tune_natural_vt}, + }, { + {"movie_ui", tune_movie_ui}, + {"movie_video", tune_movie_video}, + {"movie_video", tune_movie_video}, + {"movie_video", tune_movie_video}, + {"camera", NULL/*tune_camera*/}, + {"movie_ui", tune_movie_ui}, + {"movie_gallery", tune_movie_gallery}, + {"movie_vt", tune_movie_vt}, + }, + } +}; +#endif + +struct mdnie_tuning_info camera_table[OUTDOOR_MAX] = { + {"camera", tune_camera}, + {"camera_outdoor", tune_camera_outdoor}, +}; + +#endif /* __MDNIE_TABLE_H__ */ diff --git a/drivers/video/samsung/mdnie_table_ebook.h b/drivers/video/samsung/mdnie_table_ebook.h new file mode 100644 index 0000000..2f75fa4 --- /dev/null +++ b/drivers/video/samsung/mdnie_table_ebook.h @@ -0,0 +1,153 @@ +#ifndef __MDNIE_TABLE_EBOOK_H__ +#define __MDNIE_TABLE_EBOOK_H__ + +#include "mdnie_kona.h" + +#if defined(CONFIG_FB_MDNIE_PWM) +static unsigned short tune_ebook[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x00a0, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0030, /*DE pe*/ + 0x0093,0x0030, /*DE pf*/ + 0x0094,0x0030, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0030, /*DE nf*/ + 0x0097,0x0030, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00ff, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ef, /*SCR KgWg*/ + 0x00ec,0x00e4, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x1090, /*CC lut r 16 144*/ + 0x0022,0x20a0, /*CC lut r 32 160*/ + 0x0023,0x30b0, /*CC lut r 48 176*/ + 0x0024,0x40c0, /*CC lut r 64 192*/ + 0x0025,0x50d0, /*CC lut r 80 208*/ + 0x0026,0x60e0, /*CC lut r 96 224*/ + 0x0027,0x70f0, /*CC lut r 112 240*/ + 0x0028,0x80ff, /*CC lut r 128 255*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_ebook_cabc[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x02a0, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0030, /*DE pe*/ + 0x0093,0x0030, /*DE pf*/ + 0x0094,0x0030, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0030, /*DE nf*/ + 0x0097,0x0030, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00ff, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ef, /*SCR KgWg*/ + 0x00ec,0x00e4, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x1090, /*CC lut r 16 144*/ + 0x0022,0x20a0, /*CC lut r 32 160*/ + 0x0023,0x30b0, /*CC lut r 48 176*/ + 0x0024,0x40c0, /*CC lut r 64 192*/ + 0x0025,0x50d0, /*CC lut r 80 208*/ + 0x0026,0x60e0, /*CC lut r 96 224*/ + 0x0027,0x70f0, /*CC lut r 112 240*/ + 0x0028,0x80ff, /*CC lut r 128 255*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; +#else +static unsigned short tune_ebook[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x00a0, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0030, /*DE pe*/ + 0x0093,0x0030, /*DE pf*/ + 0x0094,0x0030, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0030, /*DE nf*/ + 0x0097,0x0030, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00ff, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ef, /*SCR KgWg*/ + 0x00ec,0x00e4, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x1090, /*CC lut r 16 144*/ + 0x0022,0x20a0, /*CC lut r 32 160*/ + 0x0023,0x30b0, /*CC lut r 48 176*/ + 0x0024,0x40c0, /*CC lut r 64 192*/ + 0x0025,0x50d0, /*CC lut r 80 208*/ + 0x0026,0x60e0, /*CC lut r 96 224*/ + 0x0027,0x70f0, /*CC lut r 112 240*/ + 0x0028,0x80ff, /*CC lut r 128 255*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; +#endif + +struct mdnie_tuning_info ebook_table[CABC_MAX] = { +#if defined(CONFIG_FB_MDNIE_PWM) + {"EBOOK", tune_ebook}, + {"EBOOK_CABC", tune_ebook_cabc}, +#else + {"EBOOK", tune_ebook}, +#endif +}; +#endif /* __MDNIE_TABLE_EBOOK_H__ */ diff --git a/drivers/video/samsung/mdnie_table_kona.h b/drivers/video/samsung/mdnie_table_kona.h new file mode 100644 index 0000000..8b3b283 --- /dev/null +++ b/drivers/video/samsung/mdnie_table_kona.h @@ -0,0 +1,1304 @@ +#ifndef __MDNIE_TABLE_H__ +#define __MDNIE_TABLE_H__ + +#include "mdnie_kona.h" + + +static struct mdnie_backlight_value backlight_table[4] = { + { + .max = 977, /*3G/WIFI BOE LCD SYS REV <= 0x03*/ + .mid = 531, /*LTE BOE LCD SYS REV <= 0x02*/ + .low = 16, + .dim = 16, + }, { + .max = 1280, /*3G/WIFI BOE LCD SYS REV >= 0x04*/ + .mid = 700, /*LTE BOE LCD SYS REV >= 0x03*/ + .low = 16, + .dim = 16, + }, { + .max = 1056, /*3G/WIFI SDC LCD SYS REV <= 0x03*/ + .mid = 574, /*LTE SDC LCD SYS REV <= 0x02*/ + .low = 16, + .dim = 16, + }, { + .max = 1435, /* 3G/WIFI SDC LCD SYS REV >= 0x04*/ + .mid = 780, /* LTE SDC LCD SYS REV >= 0x03*/ + .low = 17, + .dim = 17, + } +}; + +static const unsigned char power_lut[LUT_LEVEL_MAX][LUT_MAX][9] = { + /* Indoor power look up table */ + { + {0x42, 0x3d, 0x3E, 0x48, 0x42, 0x3F, 0x3A, 0x37, 0x3F}, + {0x38, 0x3d, 0x34, 0x48, 0x38, 0x35, 0x30, 0x2d, 0x35}, + }, + /* Outdoor power look up table for outdoor 1 (1k~15k) */ + { + {0x42, 0x47, 0x3E, 0x52, 0x42, 0x3F, 0x3A, 0x37, 0x3F}, + {0x38, 0x3d, 0x34, 0x48, 0x38, 0x35, 0x30, 0x2d, 0x35}, + }, + /* Outdoor power look up table (15k ~) */ + { + {100, 100, 100, 100, 100, 100, 100, 100, 100}, + {100, 100, 100, 100, 100, 100, 100, 100, 100}, + }, +}; + +static unsigned short tune_camera[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x002c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092,0x0000, /*DE pe*/ + 0x0093,0x0030, /*DE pf*/ + 0x0094,0x0030, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0030, /*DE nf*/ + 0x0097,0x0030, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_camera_outdoor[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x042c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092,0x0000, /*DE pe*/ + 0x0093,0x0030, /*DE pf*/ + 0x0094,0x0030, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0030, /*DE nf*/ + 0x0097,0x0030, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x00d0,0x01a0, /*UC y*/ + 0x00d1,0x01ff, /*UC cs*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_ui[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x00a8, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1a04, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0b94, /*CC lut r 16 144*/ + 0x0022,0x18a6, /*CC lut r 32 160*/ + 0x0023,0x28b8, /*CC lut r 48 176*/ + 0x0024,0x3ac9, /*CC lut r 64 192*/ + 0x0025,0x4cd9, /*CC lut r 80 208*/ + 0x0026,0x5ee7, /*CC lut r 96 224*/ + 0x0027,0x70f4, /*CC lut r 112 240*/ + 0x0028,0x82ff, /*CC lut r 128 255*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_video[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x00ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0030, /*DE pe*/ + 0x0093,0x0080, /*DE pf*/ + 0x0094,0x0080, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0080, /*DE nf*/ + 0x0097,0x0080, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1a04, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0b94, /*CC lut r 16 144*/ + 0x0022,0x18a6, /*CC lut r 32 160*/ + 0x0023,0x28b8, /*CC lut r 48 176*/ + 0x0024,0x3ac9, /*CC lut r 64 192*/ + 0x0025,0x4cd9, /*CC lut r 80 208*/ + 0x0026,0x5ee7, /*CC lut r 96 224*/ + 0x0027,0x70f4, /*CC lut r 112 240*/ + 0x0028,0x82ff, /*CC lut r 128 255*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_gallery[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x00ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0030, /*DE pe*/ + 0x0093,0x0050, /*DE pf*/ + 0x0094,0x0050, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0050, /*DE nf*/ + 0x0097,0x0050, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1a04, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0b94, /*CC lut r 16 144*/ + 0x0022,0x18a6, /*CC lut r 32 160*/ + 0x0023,0x28b8, /*CC lut r 48 176*/ + 0x0024,0x3ac9, /*CC lut r 64 192*/ + 0x0025,0x4cd9, /*CC lut r 80 208*/ + 0x0026,0x5ee7, /*CC lut r 96 224*/ + 0x0027,0x70f4, /*CC lut r 112 240*/ + 0x0028,0x82ff, /*CC lut r 128 255*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_vt[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x00ae, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0005, /*FA cs1 de8 hdr2 fa1*/ + 0x0039,0x0080, /*FA dnrWeight*/ + 0x0080,0x0fff, /*DNR dirTh*/ + 0x0081,0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082,0xff16, /*DNR decon5Th maskTh*/ + 0x0083,0x0000, /*DNR blTh*/ + 0x0092,0x00e0, /*DE pe*/ + 0x0093,0x00e0, /*DE pf*/ + 0x0094,0x00e0, /*DE pb*/ + 0x0095,0x00e0, /*DE ne*/ + 0x0096,0x00e0, /*DE nf*/ + 0x0097,0x00e0, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1a04, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0b94, /*CC lut r 16 144*/ + 0x0022,0x18a6, /*CC lut r 32 160*/ + 0x0023,0x28b8, /*CC lut r 48 176*/ + 0x0024,0x3ac9, /*CC lut r 64 192*/ + 0x0025,0x4cd9, /*CC lut r 80 208*/ + 0x0026,0x5ee7, /*CC lut r 96 224*/ + 0x0027,0x70f4, /*CC lut r 112 240*/ + 0x0028,0x82ff, /*CC lut r 128 255*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_ui[] = { + /*start KONA standard ui cabcoff*/ + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x00a8, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0a82, /*CC lut r 16 144*/ + 0x0022,0x1693, /*CC lut r 32 160*/ + 0x0023,0x23a4, /*CC lut r 48 176*/ + 0x0024,0x32b6, /*CC lut r 64 192*/ + 0x0025,0x41c8, /*CC lut r 80 208*/ + 0x0026,0x50da, /*CC lut r 96 224*/ + 0x0027,0x60ed, /*CC lut r 112 240*/ + 0x0028,0x71ff, /*CC lut r 128 255*/ + 0x00ff,0x0000, /*Mask Release*/ + /*end*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_video[] = { + /*start KONA standard video cabcoff*/ + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x00ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0030, /*DE pe*/ + 0x0093,0x0060, /*DE pf*/ + 0x0094,0x0060, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0060, /*DE nf*/ + 0x0097,0x0060, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0a82, /*CC lut r 16 144*/ + 0x0022,0x1693, /*CC lut r 32 160*/ + 0x0023,0x23a4, /*CC lut r 48 176*/ + 0x0024,0x32b6, /*CC lut r 64 192*/ + 0x0025,0x41c8, /*CC lut r 80 208*/ + 0x0026,0x50da, /*CC lut r 96 224*/ + 0x0027,0x60ed, /*CC lut r 112 240*/ + 0x0028,0x71ff, /*CC lut r 128 255*/ + 0x00ff,0x0000, /*Mask Release*/ + /*end*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_gallery[] = { + /*start KONA standard gallery cabcoff*/ + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x00ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0000, /*DE pe*/ + 0x0093,0x0030, /*DE pf*/ + 0x0094,0x0030, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0030, /*DE nf*/ + 0x0097,0x0030, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0a82, /*CC lut r 16 144*/ + 0x0022,0x1693, /*CC lut r 32 160*/ + 0x0023,0x23a4, /*CC lut r 48 176*/ + 0x0024,0x32b6, /*CC lut r 64 192*/ + 0x0025,0x41c8, /*CC lut r 80 208*/ + 0x0026,0x50da, /*CC lut r 96 224*/ + 0x0027,0x60ed, /*CC lut r 112 240*/ + 0x0028,0x71ff, /*CC lut r 128 255*/ + 0x00ff,0x0000, /*Mask Release*/ + /*end*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_vt[] = { + /*start KONA standard vtcall cabcoff*/ + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x00ae, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0005, /*FA cs1 de8 hdr2 fa1*/ + 0x0039,0x0080, /*FA dnrWeight*/ + 0x0080,0x0fff, /*DNR dirTh*/ + 0x0081,0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082,0xff16, /*DNR decon5Th maskTh*/ + 0x0083,0x0000, /*DNR blTh*/ + 0x0092,0x00c0, /*DE pe*/ + 0x0093,0x00c0, /*DE pf*/ + 0x0094,0x00c0, /*DE pb*/ + 0x0095,0x00c0, /*DE ne*/ + 0x0096,0x00c0, /*DE nf*/ + 0x0097,0x00c0, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0a82, /*CC lut r 16 144*/ + 0x0022,0x1693, /*CC lut r 32 160*/ + 0x0023,0x23a4, /*CC lut r 48 176*/ + 0x0024,0x32b6, /*CC lut r 64 192*/ + 0x0025,0x41c8, /*CC lut r 80 208*/ + 0x0026,0x50da, /*CC lut r 96 224*/ + 0x0027,0x60ed, /*CC lut r 112 240*/ + 0x0028,0x71ff, /*CC lut r 128 255*/ + 0x00ff,0x0000, /*Mask Release*/ + /*end*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_ui[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x0020, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00f6, /*SCR KgWg*/ + 0x00ec,0x00f2, /*SCR KbWb*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_video[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x0020, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092,0x0000, /*DE pe*/ + 0x0093,0x0000, /*DE pf*/ + 0x0094,0x0000, /*DE pb*/ + 0x0095,0x0000, /*DE ne*/ + 0x0096,0x0000, /*DE nf*/ + 0x0097,0x0000, /*DE nb*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1004, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00f6, /*SCR KgWg*/ + 0x00ec,0x00f2, /*SCR KbWb*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_gallery[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x0020, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00f6, /*SCR KgWg*/ + 0x00ec,0x00f2, /*SCR KbWb*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_vt[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x002e, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0005, /*FA cs1 de8 hdr2 fa1*/ + 0x0039,0x0080, /*FA dnrWeight*/ + 0x0080,0x0fff, /*DNR dirTh*/ + 0x0081,0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082,0xff16, /*DNR decon5Th maskTh*/ + 0x0083,0x0000, /*DNR blTh*/ + 0x0092,0x0040, /*DE pe*/ + 0x0093,0x0040, /*DE pf*/ + 0x0094,0x0040, /*DE pb*/ + 0x0095,0x0040, /*DE ne*/ + 0x0096,0x0040, /*DE nf*/ + 0x0097,0x0040, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1204, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00f6, /*SCR KgWg*/ + 0x00ec,0x00f2, /*SCR KbWb*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_ui_cabc[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x02a8, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1a04, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0b94, /*CC lut r 16 144*/ + 0x0022,0x18a6, /*CC lut r 32 160*/ + 0x0023,0x28b8, /*CC lut r 48 176*/ + 0x0024,0x3ac9, /*CC lut r 64 192*/ + 0x0025,0x4cd9, /*CC lut r 80 208*/ + 0x0026,0x5ee7, /*CC lut r 96 224*/ + 0x0027,0x70f4, /*CC lut r 112 240*/ + 0x0028,0x82ff, /*CC lut r 128 255*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_video_cabc[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x02ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0030, /*DE pe*/ + 0x0093,0x0080, /*DE pf*/ + 0x0094,0x0080, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0080, /*DE nf*/ + 0x0097,0x0080, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1a04, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0b94, /*CC lut r 16 144*/ + 0x0022,0x18a6, /*CC lut r 32 160*/ + 0x0023,0x28b8, /*CC lut r 48 176*/ + 0x0024,0x3ac9, /*CC lut r 64 192*/ + 0x0025,0x4cd9, /*CC lut r 80 208*/ + 0x0026,0x5ee7, /*CC lut r 96 224*/ + 0x0027,0x70f4, /*CC lut r 112 240*/ + 0x0028,0x82ff, /*CC lut r 128 255*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_gallery_cabc[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x02ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0030, /*DE pe*/ + 0x0093,0x0050, /*DE pf*/ + 0x0094,0x0050, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0050, /*DE nf*/ + 0x0097,0x0050, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1a04, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0b94, /*CC lut r 16 144*/ + 0x0022,0x18a6, /*CC lut r 32 160*/ + 0x0023,0x28b8, /*CC lut r 48 176*/ + 0x0024,0x3ac9, /*CC lut r 64 192*/ + 0x0025,0x4cd9, /*CC lut r 80 208*/ + 0x0026,0x5ee7, /*CC lut r 96 224*/ + 0x0027,0x70f4, /*CC lut r 112 240*/ + 0x0028,0x82ff, /*CC lut r 128 255*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_dynamic_vt_cabc[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x02ae, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0005, /*FA cs1 de8 hdr2 fa1*/ + 0x0039,0x0080, /*FA dnrWeight*/ + 0x0080,0x0fff, /*DNR dirTh*/ + 0x0081,0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082,0xff16, /*DNR decon5Th maskTh*/ + 0x0083,0x0000, /*DNR blTh*/ + 0x0092,0x00e0, /*DE pe*/ + 0x0093,0x00e0, /*DE pf*/ + 0x0094,0x00e0, /*DE pb*/ + 0x0095,0x00e0, /*DE ne*/ + 0x0096,0x00e0, /*DE nf*/ + 0x0097,0x00e0, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1a04, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0b94, /*CC lut r 16 144*/ + 0x0022,0x18a6, /*CC lut r 32 160*/ + 0x0023,0x28b8, /*CC lut r 48 176*/ + 0x0024,0x3ac9, /*CC lut r 64 192*/ + 0x0025,0x4cd9, /*CC lut r 80 208*/ + 0x0026,0x5ee7, /*CC lut r 96 224*/ + 0x0027,0x70f4, /*CC lut r 112 240*/ + 0x0028,0x82ff, /*CC lut r 128 255*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_ui_cabc[] = { + /*start KONA standard ui cabcon*/ + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x02a8, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0a82, /*CC lut r 16 144*/ + 0x0022,0x1693, /*CC lut r 32 160*/ + 0x0023,0x23a4, /*CC lut r 48 176*/ + 0x0024,0x32b6, /*CC lut r 64 192*/ + 0x0025,0x41c8, /*CC lut r 80 208*/ + 0x0026,0x50da, /*CC lut r 96 224*/ + 0x0027,0x60ed, /*CC lut r 112 240*/ + 0x0028,0x71ff, /*CC lut r 128 255*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + /*end*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_video_cabc[] = { + /*start KONA standard video cabcon*/ + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x02ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0030, /*DE pe*/ + 0x0093,0x0060, /*DE pf*/ + 0x0094,0x0060, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0060, /*DE nf*/ + 0x0097,0x0060, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0a82, /*CC lut r 16 144*/ + 0x0022,0x1693, /*CC lut r 32 160*/ + 0x0023,0x23a4, /*CC lut r 48 176*/ + 0x0024,0x32b6, /*CC lut r 64 192*/ + 0x0025,0x41c8, /*CC lut r 80 208*/ + 0x0026,0x50da, /*CC lut r 96 224*/ + 0x0027,0x60ed, /*CC lut r 112 240*/ + 0x0028,0x71ff, /*CC lut r 128 255*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + /*end*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_gallery_cabc[] = { + /*start KONA standard gallery cabcon*/ + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x02ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090,0x0080, /*DE egth*/ + 0x0092,0x0000, /*DE pe*/ + 0x0093,0x0030, /*DE pf*/ + 0x0094,0x0030, /*DE pb*/ + 0x0095,0x0030, /*DE ne*/ + 0x0096,0x0030, /*DE nf*/ + 0x0097,0x0030, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0a82, /*CC lut r 16 144*/ + 0x0022,0x1693, /*CC lut r 32 160*/ + 0x0023,0x23a4, /*CC lut r 48 176*/ + 0x0024,0x32b6, /*CC lut r 64 192*/ + 0x0025,0x41c8, /*CC lut r 80 208*/ + 0x0026,0x50da, /*CC lut r 96 224*/ + 0x0027,0x60ed, /*CC lut r 112 240*/ + 0x0028,0x71ff, /*CC lut r 128 255*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + /*end*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_standard_vt_cabc[] = { + /*start KONA standard vtcall cabcon*/ + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x02ae, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0005, /*FA cs1 de8 hdr2 fa1*/ + 0x0039,0x0080, /*FA dnrWeight*/ + 0x0080,0x0fff, /*DNR dirTh*/ + 0x0081,0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082,0xff16, /*DNR decon5Th maskTh*/ + 0x0083,0x0000, /*DNR blTh*/ + 0x0092,0x00c0, /*DE pe*/ + 0x0093,0x00c0, /*DE pf*/ + 0x0094,0x00c0, /*DE pb*/ + 0x0095,0x00c0, /*DE ne*/ + 0x0096,0x00c0, /*DE nf*/ + 0x0097,0x00c0, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1804, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00ff, /*SCR KgWg*/ + 0x00ec,0x00ff, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x001f,0x0080, /*CC chsel strength*/ + 0x0020,0x0000, /*CC lut r 0*/ + 0x0021,0x0a82, /*CC lut r 16 144*/ + 0x0022,0x1693, /*CC lut r 32 160*/ + 0x0023,0x23a4, /*CC lut r 48 176*/ + 0x0024,0x32b6, /*CC lut r 64 192*/ + 0x0025,0x41c8, /*CC lut r 80 208*/ + 0x0026,0x50da, /*CC lut r 96 224*/ + 0x0027,0x60ed, /*CC lut r 112 240*/ + 0x0028,0x71ff, /*CC lut r 128 255*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + /*end*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_ui_cabc[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x0220, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00f6, /*SCR KgWg*/ + 0x00ec,0x00f2, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_video_cabc[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x0220, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092,0x0000, /*DE pe*/ + 0x0093,0x0000, /*DE pf*/ + 0x0094,0x0000, /*DE pb*/ + 0x0095,0x0000, /*DE ne*/ + 0x0096,0x0000, /*DE nf*/ + 0x0097,0x0000, /*DE nb*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1004, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00f6, /*SCR KgWg*/ + 0x00ec,0x00f2, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_gallery_cabc[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x0220, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00f6, /*SCR KgWg*/ + 0x00ec,0x00f2, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_movie_vt_cabc[] = { + 0x0000,0x0000, /*BANK 0*/ + 0x0008,0x022e, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030,0x0005, /*FA cs1 de8 hdr2 fa1*/ + 0x0039,0x0080, /*FA dnrWeight*/ + 0x0080,0x0fff, /*DNR dirTh*/ + 0x0081,0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082,0xff16, /*DNR decon5Th maskTh*/ + 0x0083,0x0000, /*DNR blTh*/ + 0x0092,0x0040, /*DE pe*/ + 0x0093,0x0040, /*DE pf*/ + 0x0094,0x0040, /*DE pb*/ + 0x0095,0x0040, /*DE ne*/ + 0x0096,0x0040, /*DE nf*/ + 0x0097,0x0040, /*DE nb*/ + 0x0098,0x1000, /*DE max ratio*/ + 0x0099,0x0100, /*DE min ratio*/ + 0x00b0,0x1010, /*CS hg ry*/ + 0x00b1,0x1010, /*CS hg gc*/ + 0x00b2,0x1010, /*CS hg bm*/ + 0x00b3,0x1204, /*CS weight grayTH*/ + 0x00e1,0xff00, /*SCR RrCr*/ + 0x00e2,0x00ff, /*SCR RgCg*/ + 0x00e3,0x00ff, /*SCR RbCb*/ + 0x00e4,0x00ff, /*SCR GrMr*/ + 0x00e5,0xff00, /*SCR GgMg*/ + 0x00e6,0x00ff, /*SCR GbMb*/ + 0x00e7,0x00ff, /*SCR BrYr*/ + 0x00e8,0x00f0, /*SCR BgYg*/ + 0x00e9,0xff00, /*SCR BbYb*/ + 0x00ea,0x00ff, /*SCR KrWr*/ + 0x00eb,0x00f6, /*SCR KgWg*/ + 0x00ec,0x00f2, /*SCR KbWb*/ + 0x0000,0x0001, /*BANK 1*/ + 0x0075,0x0000, /*CABC dgain*/ + 0x0076,0x0000, + 0x0077,0x0000, + 0x0078,0x0000, + 0x007f,0x0002, /*dynamic lcd*/ + 0x00ff,0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_warm[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0028, /*MCM 4000K*/ + 0x0007, 0x7575, /*MCM 1cb 2cb W*/ + 0x0009, 0xa08e, /*MCM 5cb 1cr W*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_cold[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0064, /*MCM 10000K*/ + 0x0009, 0xa08e, /*MCM 5cb 1cr W*/ + 0x000b, 0x7979, /*MCM 4cr 5cr W*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_normal_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x04ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x00d0, 0x01a0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_warm_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x04ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0028, /*MCM 4000K*/ + 0x0007, 0x7575, /*MCM 1cb 2cb W*/ + 0x0009, 0xa08e, /*MCM 5cb 1cr W*/ + 0x00d0, 0x01c0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_cold_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x04ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0064, /*MCM 10000K*/ + 0x0009, 0xa08e, /*MCM 5cb 1cr W*/ + 0x000b, 0x7979, /*MCM 4cr 5cr W*/ + 0x00d0, 0x01a0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_warm_cabc[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x02ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0028, /*MCM 4000K*/ + 0x0007, 0x7575, /*MCM 1cb 2cb W*/ + 0x0009, 0xa08e, /*MCM 5cb 1cr W*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_cold_cabc[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x02ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0064, /*MCM 10000K*/ + 0x0009, 0xa08e, /*MCM 5cb 1cr W*/ + 0x000b, 0x7979, /*MCM 4cr 5cr W*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_normal_outdoor_cabc[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x06ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x00d0, 0x01a0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_warm_outdoor_cabc[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x06ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0028, /*MCM 4000K*/ + 0x0007, 0x7575, /*MCM 1cb 2cb W*/ + 0x0009, 0xa08e, /*MCM 5cb 1cr W*/ + 0x00d0, 0x01c0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static unsigned short tune_cold_outdoor_cabc[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x06ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0064, /*MCM 10000K*/ + 0x0009, 0xa08e, /*MCM 5cb 1cr W*/ + 0x000b, 0x7979, /*MCM 4cr 5cr W*/ + 0x00d0, 0x01a0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +struct mdnie_tuning_info etc_table[CABC_MAX][OUTDOOR_MAX][TONE_MAX] = { + { + { + {"normal", NULL}, + {"warm", tune_warm}, + {"cold", tune_cold}, + }, + { + {"normal_outdoor", tune_normal_outdoor}, + {"warm_outdoor", tune_warm_outdoor}, + {"cold_outdoor", tune_cold_outdoor}, + }, + }, + { + { + {"normal_cabc", NULL}, + {"warm_cabc", tune_warm_cabc}, + {"cold_cabc", tune_cold_cabc}, + }, + { + {"normal_outdoor_cabc", tune_normal_outdoor_cabc}, + {"warm_outdoor_cabc", tune_warm_outdoor_cabc}, + {"cold_outdoor_cabc", tune_cold_outdoor_cabc}, + }, + }, +}; + +struct mdnie_tuning_info tuning_table[CABC_MAX][MODE_MAX][SCENARIO_MAX] = { + { + { + {"dynamic_ui", tune_dynamic_ui}, + {"dynamic_video", tune_dynamic_video}, + {"dynamic_video", tune_dynamic_video}, + {"dynamic_video", tune_dynamic_video}, + {"camera", NULL}, + {"dynamic_ui", tune_dynamic_ui}, + {"dynamic_gallery", tune_dynamic_gallery}, + {"dynamic_vt", tune_dynamic_vt}, + }, { + {"standard_ui", tune_standard_ui}, + {"standard_video", tune_standard_video}, + {"standard_video", tune_standard_video}, + {"standard_video", tune_standard_video}, + {"camera", NULL}, + {"standard_ui", tune_standard_ui}, + {"standard_gallery", tune_standard_gallery}, + {"standard_vt", tune_standard_vt}, + }, { + {"movie_ui", tune_movie_ui}, + {"movie_video", tune_movie_video}, + {"movie_video", tune_movie_video}, + {"movie_video", tune_movie_video}, + {"camera", NULL}, + {"movie_ui", tune_movie_ui}, + {"movie_gallery", tune_movie_gallery}, + {"movie_vt", tune_movie_vt}, + }, + }, { + { + {"dynamic_ui_cabc", tune_dynamic_ui_cabc}, + {"dynamic_video_cabc", tune_dynamic_video_cabc}, + {"dynamic_video_cabc", tune_dynamic_video_cabc}, + {"dynamic_video_cabc", tune_dynamic_video_cabc}, + {"camera", NULL}, + {"dynamic_ui_cabc", tune_dynamic_ui_cabc}, + {"dynamic_gallery_cabc", tune_dynamic_gallery_cabc}, + {"dynamic_vt_cabc", tune_dynamic_vt_cabc}, + }, { + {"standard_ui_cabc", tune_standard_ui_cabc}, + {"standard_video_cabc", tune_standard_video_cabc}, + {"standard_video_cabc", tune_standard_video_cabc}, + {"standard_video_cabc", tune_standard_video_cabc}, + {"camera", NULL}, + {"standard_ui_cabc", tune_standard_ui_cabc}, + {"standard_gallery_cabc", tune_standard_gallery_cabc}, + {"standard_vt_cabc", tune_standard_vt_cabc}, + }, { + {"movie_ui_cabc", tune_movie_ui_cabc}, + {"movie_video_cabc", tune_movie_video_cabc}, + {"movie_video_cabc", tune_movie_video_cabc}, + {"movie_video_cabc", tune_movie_video_cabc}, + {"camera", NULL}, + {"movie_ui_cabc", tune_movie_ui_cabc}, + {"movie_gallery_cabc", tune_movie_gallery_cabc}, + {"movie_vt_cabc", tune_movie_vt_cabc}, + }, + }, +}; + +struct mdnie_tuning_info camera_table[OUTDOOR_MAX] = { + {"camera", tune_camera}, + {"camera_outdoor", tune_camera_outdoor}, +}; + +#endif /* __MDNIE_TABLE_H__ */ diff --git a/drivers/video/samsung/mdnie_tuning_kona.c b/drivers/video/samsung/mdnie_tuning_kona.c new file mode 100644 index 0000000..e198a85 --- /dev/null +++ b/drivers/video/samsung/mdnie_tuning_kona.c @@ -0,0 +1,294 @@ +/* linux/drivers/video/samsung/mdnie_tuning.c + * + * Register interface file for Samsung mDNIe driver + * + * Copyright (c) 2011 Samsung Electronics + * + * 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 +#include +#include +#include +#include + +#include "s3cfb.h" +#include "mdnie_kona.h" + +#define KFREE(ptr) do { if (ptr) kfree(ptr); (ptr) = NULL; } while (0) +#define CONSTANT_F1 ((23<<10)/21) +#define CONSTANT_F2 ((19<<10)/18) +#define CONSTANT_F3 (5<<10) +#define CONSTANT_F4 ((21<<10)/8) + +int mdnie_calibration(unsigned short x, unsigned short y, int *result) +{ + u8 ret = 0; + + result[1] = ((y << 10) - (CONSTANT_F1 * x) + (12 << 10)) >> 10; + result[2] = ((y << 10) - (CONSTANT_F2 * x) + (44 << 10)) >> 10; + result[3] = ((y << 10) + (CONSTANT_F3 * x) - (18365 << 10)) >> 10; + result[4] = ((y << 10) + (CONSTANT_F4 * x) - (10814 << 10)) >> 10; + + pr_info("%d, %d, %d, %d\n", result[1], result[2], result[3], result[4]); + + if (result[1] > 0) { + if (result[3] > 0) + ret = 3; + else + ret = (result[4] < 0) ? 1 : 2; + } else { + if (result[2] < 0) { + if (result[3] > 0) + ret = 9; + else + ret = (result[4] < 0) ? 7 : 8; + } else { + if (result[3] > 0) + ret = 6; + else + ret = (result[4] < 0) ? 4 : 5; + } + } + + ret = (ret > 0) ? ret : 1; + ret = (ret > 9) ? 1 : ret; + + return ret; +} + +static int parse_text(char *src, int len, u16 *buf, char *name) +{ + int i, count, ret; + int index = 0; + char *str_line[100]; + char *sstart; + char *c; + unsigned int data1, data2; + + c = src; + count = 0; + sstart = c; + + for (i = 0; i < len; i++, c++) { + char a = *c; + if (a == '\r' || a == '\n') { + if (c > sstart) { + str_line[count] = sstart; + count++; + } + *c = '\0'; + sstart = c+1; + } + } + + if (c > sstart) { + str_line[count] = sstart; + count++; + } + + /* printk(KERN_INFO "----------------------------- Total number of lines:%d\n", count); */ + + for (i = 0; i < count; i++) { + /* printk(KERN_INFO "line:%d, [start]%s[end]\n", i, str_line[i]); */ + ret = sscanf(str_line[i], "0x%x, 0x%x\n", &data1, &data2); + /* printk(KERN_INFO "Result => [0x%2x 0x%4x] %s\n", data1, data2, (ret == 2) ? "Ok" : "Not available"); */ + if (ret == 2) { + buf[index++] = (unsigned short)data1; + buf[index++] = (unsigned short)data2; + } + } + + buf[index] = END_SEQ; + + return index; +} + +int mdnie_txtbuf_to_parsing(char *path, u16 size, u16 *buf, char *name) +{ + struct file *filp; + char *dp; + long l; + loff_t pos; + int ret, num; + mm_segment_t fs; + + fs = get_fs(); + set_fs(get_ds()); + + if (!path) { + pr_err("%s: invalid filepath\n", __func__); + goto parse_err; + } + + filp = filp_open(path, O_RDONLY, 0); + + if (IS_ERR(filp)) { + pr_err("file open error: %s\n", path); + goto parse_err; + } + + l = filp->f_path.dentry->d_inode->i_size; + dp = kmalloc(l, GFP_KERNEL); + if (dp == NULL) { + pr_err("Out of Memory!\n"); + filp_close(filp, current->files); + goto parse_err; + } + pos = 0; + memset(dp, 0, l); + ret = vfs_read(filp, (char __user *)dp, l, &pos); + + if (ret != l) { + pr_info("read size = %d, l = %ld, size=%d\n", ret, l, size); + l = (l > ret) ? ret : l; + if (size < l) { + KFREE(dp); + filp_close(filp, current->files); + goto parse_err; + } + } + + filp_close(filp, current->files); + set_fs(fs); + + num = parse_text(dp, l, buf, name); + + if (!num) { + pr_err("Nothing to parse!\n"); + KFREE(dp); + goto parse_err; + } + + KFREE(dp); + + return num; + +parse_err: + return -EPERM; +} + +int mdnie_open_file(const char *path, char **fp) +{ + struct file *filp; + char *dp; + long length; + int ret; + struct super_block *sb; + loff_t pos = 0; + + if (!path) { + pr_err("%s: path is invalid\n", __func__); + return -EPERM; + } + + filp = filp_open(path, O_RDONLY, 0); + if (IS_ERR(filp)) { + pr_err("%s: file open err: %s\n", __func__, path); + return -EPERM; + } + + length = i_size_read(filp->f_path.dentry->d_inode); + if (length <= 0) { + pr_err("%s: file size %ld error\n", __func__, length); + return -EPERM; + } + + dp = kzalloc(length, GFP_KERNEL); + if (dp == NULL) { + pr_err("%s: Out of Memory\n", __func__); + filp_close(filp, current->files); + return -EPERM; + } + + ret = kernel_read(filp, pos, dp, length); + if (ret != length) { + /* check node is sysfs, bus this way is not safe */ + sb = filp->f_path.dentry->d_inode->i_sb; + if ((sb->s_magic != SYSFS_MAGIC) && (length != sb->s_blocksize)) { + pr_err("%s: read size= %d, length= %ld\n", __func__, ret, length); + KFREE(dp); + filp_close(filp, current->files); + return -EPERM; + } + } + + filp_close(filp, current->files); + + *fp = dp; + + return ret; +} + +int mdnie_check_firmware(const char *path, char *name) +{ + char *ptr = NULL; + int ret = 0, size; + + size = mdnie_open_file(path, &ptr); + if (IS_ERR_OR_NULL(ptr) || size <= 0) { + pr_err("%s: file open fail %s\n", __func__, path); + KFREE(ptr); + return 0; + } + + ret = (strstr(ptr, name) != NULL) ? 1 : 0; + + KFREE(ptr); + + return ret; +} + +int mdnie_request_firmware(const char *path, u16 **buf, char *name) +{ + char *token, *ptr = NULL; + unsigned short *dp; + int ret = 0, size, i = 0; + unsigned int data1, data2; + + size = mdnie_open_file(path, &ptr); + if (IS_ERR_OR_NULL(ptr) || size <= 0) { + pr_err("%s: file open fail %s\n", __func__, path); + KFREE(ptr); + return ret; + } + + dp = kzalloc(size, GFP_KERNEL); + if (dp == NULL) { + pr_err("%s: Out of Memory\n", __func__); + KFREE(ptr); + return -ENOMEM; + } + + if (name) { + if (strstr(ptr, name) != NULL) { + pr_info("found %s in %s\n", name, path); + ptr = strstr(ptr, name); + } + } + + while ((token = strsep(&ptr, "\r\n")) != NULL) { + if ((name) && (!strncmp(token, "};", 2))) { + pr_info("found %s end in local, stop searching\n", name); + break; + } + ret = sscanf(token, "%x, %x", &data1, &data2); + if (ret == 2) { + dp[i] = (u16)data1; + dp[i+1] = (u16)data2; + i += 2; + } + } + + dp[i] = END_SEQ; + + *buf = dp; + + KFREE(ptr); + + return i; +} + diff --git a/drivers/video/samsung/s3cfb_ielcd_kona.c b/drivers/video/samsung/s3cfb_ielcd_kona.c new file mode 100644 index 0000000..7eadd5f --- /dev/null +++ b/drivers/video/samsung/s3cfb_ielcd_kona.c @@ -0,0 +1,136 @@ +/* linux/drivers/video/samsung/s3cfb_mdnie.c + * + * Register interface file for Samsung IELCD driver + * + * Copyright (c) 2009 Samsung Electronics + * http://www.samsungsemi.com/ + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "s3cfb.h" +#include "s3cfb_mdnie_kona.h" +#include "s3cfb_ielcd_kona.h" + +static struct resource *s3c_ielcd_mem; +static void __iomem *s3c_ielcd_base; + +#define s3c_ielcd_readl(addr) __raw_readl(s3c_ielcd_base + addr) +#define s3c_ielcd_writel(addr, val) writel(val, s3c_ielcd_base + addr) + +static struct s3cfb_global ielcd_fb; +static struct s3cfb_global *ielcd_fbdev; + +int ielcd_hw_init(void) +{ + s3c_ielcd_mem = request_mem_region(S3C_IELCD_PHY_BASE, S3C_IELCD_MAP_SIZE, "ielcd"); + if (IS_ERR_OR_NULL(s3c_ielcd_mem)) { + pr_err("%s: fail to request_mem_region\n", __func__); + return -ENOENT; + } + + s3c_ielcd_base = ioremap(S3C_IELCD_PHY_BASE, S3C_IELCD_MAP_SIZE); + if (IS_ERR_OR_NULL(s3c_ielcd_base)) { + pr_err("%s: fail to ioremap\n", __func__); + return -ENOENT; + } + + ielcd_fbdev = &ielcd_fb; + + return 0; +} + +int ielcd_display_on(void) +{ + unsigned int cfg; + + cfg = s3c_ielcd_readl(S3C_VIDCON0); + cfg |= (S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE); + s3c_ielcd_writel(S3C_VIDCON0, cfg); + + return 0; +} + +int ielcd_display_off(void) +{ + unsigned int cfg, ielcd_count = 0; + + cfg = s3c_ielcd_readl(S3C_VIDCON0); + cfg |= S3C_VIDCON0_ENVID_ENABLE; + cfg &= ~(S3C_VIDCON0_ENVID_F_ENABLE); + + s3c_ielcd_writel(S3C_VIDCON0, cfg); + + do { + if (++ielcd_count > 2000000) { + printk(KERN_ERR "ielcd off fail\n"); + return 1; + } + + if (!(s3c_ielcd_readl(S3C_VIDCON1) & 0xffff0000)) + return 0; + } while (1); +} + +void ielcd_init_global(struct s3cfb_global *ctrl) +{ + unsigned int cfg; + + *ielcd_fbdev = *ctrl; + ctrl->ielcd_regs = ielcd_fbdev->regs = s3c_ielcd_base; + + s3c_ielcd_writel(S3C_IELCD_GPOUTCON0, S3C_IELCD_MAGIC_KEY); + + s3cfb_set_polarity_only(ielcd_fbdev); + s3cfb_set_timing(ielcd_fbdev); + s3cfb_set_lcd_size(ielcd_fbdev); + + /* vclock divider setting , same as FIMD */ + cfg = readl(ctrl->regs + S3C_VIDCON0); + cfg &= ~(S3C_VIDCON0_VIDOUT_MASK | S3C_VIDCON0_VCLKEN_MASK); + cfg |= S3C_VIDCON0_VIDOUT_RGB; + cfg |= S3C_VIDCON0_VCLKEN_NORMAL; + s3c_ielcd_writel(S3C_VIDCON0, cfg); + + /* window0 position setting , fixed */ + s3c_ielcd_writel(S3C_VIDOSD0A, 0); + + /* window0 position setting */ + cfg = S3C_VIDOSD_RIGHT_X(ctrl->lcd->width - 1); + cfg |= S3C_VIDOSD_BOTTOM_Y(ctrl->lcd->height - 1); + s3c_ielcd_writel(S3C_VIDOSD0B, cfg); + + /* window0 osd size setting */ + s3c_ielcd_writel(S3C_VIDOSD0C, ctrl->lcd->width * ctrl->lcd->height); + + /* window0 setting , fixed */ + cfg = S3C_WINCON_DATAPATH_LOCAL | S3C_WINCON_BPPMODE_32BPP | S3C_WINCON_INRGB_RGB; + s3c_ielcd_writel(S3C_WINCON0, cfg); + + s3cfb_window_on(ielcd_fbdev, 0); +} + diff --git a/drivers/video/samsung/s3cfb_ielcd_kona.h b/drivers/video/samsung/s3cfb_ielcd_kona.h new file mode 100644 index 0000000..4c89643 --- /dev/null +++ b/drivers/video/samsung/s3cfb_ielcd_kona.h @@ -0,0 +1,28 @@ +/* linux/drivers/video/samsung/s3cfb_ielcd.h + * + * Header file for Samsung (IELCD) driver + * + * Copyright (c) 2009 Samsung Electronics + * http://www.samsungsemi.com/ + * + * 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 __S3CFB_IELCD_H__ +#define __S3CFB_IELCD_H__ + +#define S3C_IELCD_MAGIC_KEY 0x2ff47 + +#define S3C_IELCD_PHY_BASE 0x11C40000 +#define S3C_IELCD_MAP_SIZE 0x00008000 + +#define S3C_IELCD_GPOUTCON0 0x0278 + +int ielcd_hw_init(void); +int ielcd_display_on(void); +int ielcd_display_off(void); +void ielcd_init_global(struct s3cfb_global *ctrl); + +#endif diff --git a/drivers/video/samsung/s3cfb_main.c b/drivers/video/samsung/s3cfb_main.c index fadea40..191c68e 100644 --- a/drivers/video/samsung/s3cfb_main.c +++ b/drivers/video/samsung/s3cfb_main.c @@ -41,9 +41,14 @@ #endif #ifdef CONFIG_FB_S5P_MDNIE +#ifdef CONFIG_MACH_KONA +#include "s3cfb_mdnie_kona.h" +#include "mdnie_kona.h" +#else #include "s3cfb_mdnie.h" #include "mdnie.h" #endif +#endif #ifdef CONFIG_HAS_WAKELOCK #include #include @@ -604,8 +609,12 @@ static int s3cfb_probe(struct platform_device *pdev) #ifdef CONFIG_FB_S5P_MDNIE /* only FIMD0 is supported */ if (i == 0) +#ifdef CONFIG_MACH_KONA + mdnie_setup(); +#else s3c_mdnie_setup(); #endif +#endif /* hw setting */ s3cfb_init_global(fbdev[i]); @@ -636,8 +645,12 @@ static int s3cfb_probe(struct platform_device *pdev) pdata->set_display_path(); s3cfb_set_dualrgb(fbdev[i], S3C_DUALRGB_MDNIE); +#ifdef CONFIG_MACH_KONA + mdnie_display_on(fbdev[i]); +#else s3c_mdnie_init_global(fbdev[i]); s3c_mdnie_display_on(fbdev[i]); +#endif } #endif s3cfb_enable_window(fbdev[0], pdata->default_win); @@ -916,8 +929,12 @@ void s3cfb_early_suspend(struct early_suspend *h) ret = s3cfb_display_off(fbdev[i]); #ifdef CONFIG_FB_S5P_MDNIE +#ifdef CONFIG_MACH_KONA + ret += mdnie_display_off(); +#else ret += s3c_mdnie_display_off(); #endif +#endif if (ret > 0) s3cfb_lcd0_pmu_off(); @@ -1023,10 +1040,14 @@ void s3cfb_late_resume(struct early_suspend *h) #if defined(CONFIG_FB_S5P_S6C1372) || defined(CONFIG_FB_S5P_S6F1202A) s5c1372_ldi_enable(); #endif +#ifdef CONFIG_MACH_KONA + mdnie_display_on(fbdev[i]); +#else s3c_mdnie_init_global(fbdev[i]); set_mdnie_value(g_mdnie, 1); s3c_mdnie_display_on(fbdev[i]); #endif +#endif s3cfb_display_on(fbdev[i]); /* Set alpha value width to 8-bit */ diff --git a/drivers/video/samsung/s3cfb_mdnie_kona.c b/drivers/video/samsung/s3cfb_mdnie_kona.c new file mode 100644 index 0000000..1fc7fcd --- /dev/null +++ b/drivers/video/samsung/s3cfb_mdnie_kona.c @@ -0,0 +1,120 @@ +/* linux/drivers/video/samsung/s3cfb_mdnie.c + * + * Register interface file for Samsung mDNIe driver + * + * Copyright (c) 2009 Samsung Electronics + * http://www.samsungsemi.com/ + * + * 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 "s3cfb.h" +#include "s3cfb_ielcd_kona.h" +#include "s3cfb_mdnie_kona.h" +#include "mdnie_kona.h" + + +#define s3c_mdnie_read(addr) __raw_readl(s3c_mdnie_base + addr*4) +#define s3c_mdnie_write(addr, val) __raw_writel(val, s3c_mdnie_base + addr*4) + + +static struct resource *s3c_mdnie_mem; +static void __iomem *s3c_mdnie_base; + + +int mdnie_write(unsigned int addr, unsigned int val) +{ + return s3c_mdnie_write(addr, val); +} + +int mdnie_mask(void) +{ + return s3c_mdnie_write(MDNIE_REG_MASK, 0x9FFF); +} + +int mdnie_unmask(void) +{ + return s3c_mdnie_write(MDNIE_REG_MASK, 0); +} + +int mdnie_set_size(unsigned int hsize, unsigned int vsize) +{ + unsigned int reg; + + /* Bank0 Select : DO NOT REMOVE THIS LINE */ + s3c_mdnie_write(MDNIE_REG_BANK_SEL, 0); + +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) + /* Input Data Unmask */ + reg = s3c_mdnie_read(S3C_MDNIE_rR1); + reg &= ~S3C_MDNIE_INPUT_DATA_ENABLE; + s3c_mdnie_write(S3C_MDNIE_rR1, reg); +#endif + + /* LCD width */ + reg = s3c_mdnie_read(MDNIE_REG_WIDTH); + reg &= ~S3C_MDNIE_SIZE_MASK; + reg |= S3C_MDNIE_HSIZE(hsize); + s3c_mdnie_write(MDNIE_REG_WIDTH, reg); + + /* LCD height */ + reg = s3c_mdnie_read(MDNIE_REG_HEIGHT); + reg &= ~S3C_MDNIE_SIZE_MASK; + reg |= S3C_MDNIE_VSIZE(vsize); + s3c_mdnie_write(MDNIE_REG_HEIGHT, reg); + + mdnie_unmask(); + + return 0; +} + +int mdnie_display_on(struct s3cfb_global *ctrl) +{ + mdnie_set_size(ctrl->lcd->width, ctrl->lcd->height); + + ielcd_init_global(ctrl); + + ielcd_display_on(); + + if (!IS_ERR_OR_NULL(g_mdnie)) + g_mdnie->enable = TRUE; + + return 0; +} + +int mdnie_display_off(void) +{ + if (!IS_ERR_OR_NULL(g_mdnie)) + g_mdnie->enable = FALSE; + + return ielcd_display_off(); +} + +static int mdnie_hw_init(void) +{ + s3c_mdnie_mem = request_mem_region(S3C_MDNIE_PHY_BASE, S3C_MDNIE_MAP_SIZE, "mdnie"); + if (IS_ERR_OR_NULL(s3c_mdnie_mem)) { + pr_err("%s: fail to request_mem_region\n", __func__); + return -ENOENT; + } + + s3c_mdnie_base = ioremap(S3C_MDNIE_PHY_BASE, S3C_MDNIE_MAP_SIZE); + if (IS_ERR_OR_NULL(s3c_mdnie_base)) { + pr_err("%s: fail to ioremap\n", __func__); + return -ENOENT; + } + + return 0; +} + +void mdnie_setup(void) +{ + mdnie_hw_init(); + ielcd_hw_init(); +} + +MODULE_DESCRIPTION("EXYNOS mDNIe Device Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/s3cfb_mdnie_kona.h b/drivers/video/samsung/s3cfb_mdnie_kona.h new file mode 100644 index 0000000..4a91691 --- /dev/null +++ b/drivers/video/samsung/s3cfb_mdnie_kona.h @@ -0,0 +1,88 @@ + +/* linux/drivers/video/samsung/s3cfb_mdnie.h + * + * Header file for Samsung (MDNIE) driver + * + * Copyright (c) 2009 Samsung Electronics + * http://www.samsungsemi.com/ + * + * 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 __S3CFB_MDNIE_H__ +#define __S3CFB_MDNIE_H__ + +#define S3C_MDNIE_PHY_BASE 0x11CA0000 +#define S3C_MDNIE_MAP_SIZE 0x00001000 + +/* Register Address */ +#if defined(CONFIG_CPU_EXYNOS4210) +#define MDNIE_REG_BANK_SEL 0x0000 +#define MDNIE_REG_WIDTH 0x0022 +#define MDNIE_REG_HEIGHT 0x0023 +#define MDNIE_REG_MASK 0x0028 + +#define MDNIE_REG_PWM_CONTROL 0x00B4 +#define MDNIE_REG_POWER_LUT0 0x0076 +#define MDNIE_REG_POWER_LUT2 0x0077 +#define MDNIE_REG_POWER_LUT4 0x0078 +#define MDNIE_REG_POWER_LUT6 0x0079 +#define MDNIE_REG_POWER_LUT8 0x007A + +#elif defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +#define MDNIE_REG_BANK_SEL 0x0000 +#define MDNIE_REG_WIDTH 0x0003 +#define MDNIE_REG_HEIGHT 0x0004 +#define MDNIE_REG_MASK 0x00FF + +#define S3C_MDNIE_rR1 0x0001 + +#define MDNIE_REG_PWM_CONTROL 0x00B6 +#define MDNIE_REG_POWER_LUT0 0x0079 +#define MDNIE_REG_POWER_LUT2 0x007A +#define MDNIE_REG_POWER_LUT4 0x007B +#define MDNIE_REG_POWER_LUT6 0x007C +#define MDNIE_REG_POWER_LUT8 0x007D +#endif + +#define MDNIE_REG_RED_R 0x00E1 /*SCR RrCr*/ +#define MDNIE_REG_RED_G 0x00E2 /*SCR RgCg*/ +#define MDNIE_REG_RED_B 0x00E3 /*SCR RbCb*/ +#define MDNIE_REG_BLUE_R 0x00E4 /*SCR GrMr*/ +#define MDNIE_REG_BLUE_G 0x00E5 /*SCR GgMg*/ +#define MDNIE_REG_BLUE_B 0x00E6 /*SCR GbMb*/ +#define MDNIE_REG_GREEN_R 0x00E7 /*SCR BrYr*/ +#define MDNIE_REG_GREEN_G 0x00E8 /*SCR BgYg*/ +#define MDNIE_REG_GREEN_B 0x00E9 /*SCR BbYb*/ +#define MDNIE_REG_BLACK_R 0x00EA /*SCR KrWr*/ +#define MDNIE_REG_BLACK_G 0x00EB /*SCR KgWg*/ +#define MDNIE_REG_BLACK_B 0x00EC /*SCR KbWb*/ + +/* Register Value */ +#if defined(CONFIG_CPU_EXYNOS4210) +#define MDNIE_PWM_BANK 0x0000 +#elif defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +#define MDNIE_PWM_BANK 0x0001 /* CMC624's PWM CTL is in BANK1 */ +#endif + +#define S3C_MDNIE_INPUT_DATA_ENABLE (1 << 10) + +#define S3C_MDNIE_SIZE_MASK 0x7FF +#define S3C_MDNIE_HSIZE(n) (n & S3C_MDNIE_SIZE_MASK) +#define S3C_MDNIE_VSIZE(n) (n & S3C_MDNIE_SIZE_MASK) + + +#define TRUE 1 +#define FALSE 0 + +void mdnie_setup(void); +int mdnie_display_on(struct s3cfb_global *ctrl); +int mdnie_display_off(void); + +int mdnie_write(unsigned int addr, unsigned int val); +int mdnie_mask(void); +int mdnie_unmask(void); + +#endif diff --git a/drivers/video/samsung/s3cfb_nt71391.c b/drivers/video/samsung/s3cfb_nt71391.c new file mode 100644 index 0000000..921544a --- /dev/null +++ b/drivers/video/samsung/s3cfb_nt71391.c @@ -0,0 +1,415 @@ +/* linux/drivers/video/samsung/s3cfb_nt71391.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * NT71391 : 8" WXGA Landscape LCD module 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif + +#include "s3cfb.h" +#include "s5p-dsim.h" + +#define NT71391_CHANGE_MINI_LVDS_FREQ_MIPI 1 + +#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) + +struct lcd_info { + struct device *dev; + unsigned int ldi_enable; + unsigned int power; + unsigned int connected; + struct mutex lock; + struct lcd_device *ld; + struct lcd_platform_data *lcd_pd; + struct dsim_global *dsim; +}; + +#ifdef NT71391_CHANGE_MINI_LVDS_FREQ_MIPI + +#define NT71391_TCON_REG_ADD 0xAC +#define NT71391_TCON_REG_CHECKSUM 0xFF +#define NT71931_N_16 0x18 +#define NT71931_N_17 0x19 +#define NT71931_N_18 0x1A +#define NT71931_N_19 0x1B +#define NT71931_N_20 0x1C +#define NT71931_N_21 0x1D +#define NT71931_N_22 0x1E +#define NT71931_N_23 0x1F +#define NT71931_N_24 0x10 +#define NT71931_N_25 0x11 + + +enum NT71391_COMMAND_TYPE { + NT71391_LOCK_CMD2 = 0x03, + NT71391_READ = 0x14, + NT71391_WRITE = 0x23, +}; + + +static const unsigned char NT71391_UNLOCK_PAGE0[] = { + 0xF3,0xA0 +}; + +static const unsigned char NT71391_UNLOCK_PAGE1[] = { + 0xF3,0xA1 +}; + +static const unsigned char NT71391_FREQ_SETTING[] = { + NT71391_TCON_REG_ADD,NT71931_N_16 +}; + +static const unsigned char TESTA[] = { + 0x2B,0xC0 +}; + +static int _nt71391_write(struct lcd_info *lcd, const unsigned char *seq, enum NT71391_COMMAND_TYPE cmd_type) +{ + const unsigned char *wbuf; + int ret = 0; + + if (!lcd->connected) + return 0; + + mutex_lock(&lcd->lock); + + wbuf = seq; + + switch (cmd_type) { + case NT71391_LOCK_CMD2: + ret = lcd->dsim->ops->cmd_write(lcd->dsim, NT71391_LOCK_CMD2,0x0,0x0); + break; + case NT71391_READ: + ret = lcd->dsim->ops->cmd_write(lcd->dsim, NT71391_READ,wbuf[0],0x0); + break; + case NT71391_WRITE: + ret = lcd->dsim->ops->cmd_write(lcd->dsim, NT71391_WRITE, wbuf[0], wbuf[1]); + break; + default: + dev_dbg(&lcd->ld->dev, "%s :: Invalid cmd type \n", __func__); + break; + } + + mutex_unlock(&lcd->lock); + + return ret; +} + +static int nt71391_write(struct lcd_info *lcd, const unsigned char *seq, enum NT71391_COMMAND_TYPE cmd_type) +{ + int ret = 0; + int retry_cnt = 1; + +retry: + ret = _nt71391_write(lcd, seq, cmd_type); + if (!ret) { + if (retry_cnt) { + dev_dbg(&lcd->ld->dev, "%s :: retry: %d\n", __func__, retry_cnt); + retry_cnt--; + goto retry; + } else + dev_dbg(&lcd->ld->dev, "%s :: 0x%02x\n", __func__, seq[0]); + } + + return ret; +} + +static int _nt71391_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) +{ + int ret = 0; + + if (!lcd->connected) + return ret; + + mutex_lock(&lcd->lock); + + if (lcd->dsim->ops->cmd_read) + ret = lcd->dsim->ops->cmd_dcs_read(lcd->dsim, addr, count, buf); + + mutex_unlock(&lcd->lock); + + return ret; +} + +static int nt71391_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) +{ + int ret = 0; + +read_retry: + ret = _nt71391_read(lcd, addr, count, buf); + if (!ret) { + if (retry_cnt) { + printk(KERN_WARNING "[WARN:LCD] %s : retry cnt : %d\n", __func__, retry_cnt); + retry_cnt--; + goto read_retry; + } else + printk(KERN_ERR "[ERROR:LCD] %s : 0x%02x read failed\n", __func__, addr); + } + + return ret; +} +#endif +static ssize_t lcdtype_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + char temp[15]; + sprintf(temp, "BOE_BP080WX7\n"); + strcat(buf, temp); + return strlen(buf); +} + +static DEVICE_ATTR(lcd_type, 0664, + lcdtype_show, NULL); + +static ssize_t window_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char temp[15]; + + sprintf(temp, "%x %x %x\n", 0x0, 0x0, 0x0); + + strcat(buf, temp); + return strlen(buf); +} + +static DEVICE_ATTR(window_type, 0444, + window_type_show, NULL); + +static int nt71391_power_on(struct lcd_info *lcd) +{ + +#ifdef NT71391_CHANGE_MINI_LVDS_FREQ_MIPI + int ret = 0; + struct lcd_platform_data *pd = NULL; + pd = lcd->lcd_pd; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + msleep(120); /* power on 50ms, i2c 70ms */ + nt71391_write(lcd, NT71391_UNLOCK_PAGE0, NT71391_WRITE); + nt71391_write(lcd, NT71391_FREQ_SETTING, NT71391_WRITE); + nt71391_write(lcd, NULL, NT71391_LOCK_CMD2); + + + lcd->dsim->ops->cmd_write(lcd->dsim, TURN_ON, 0, 0); +#else + int ret = 0; + struct lcd_platform_data *pd = NULL; + pd = lcd->lcd_pd; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + msleep(120); /* power on 50ms, i2c 70ms */ + + lcd->dsim->ops->cmd_write(lcd->dsim, TURN_ON, 0, 0); +#endif + + lcd->ldi_enable = 1; + + return ret; +} + +static int nt71391_power_off(struct lcd_info *lcd) +{ + int ret = 0; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lcd->ldi_enable = 0; + + msleep(135); + + return ret; +} + +static int nt71391_power(struct lcd_info *lcd, int power) +{ + int ret = 0; + + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) + ret = nt71391_power_on(lcd); + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) + ret = nt71391_power_off(lcd); + + if (!ret) + lcd->power = power; + + return ret; +} + +static int nt71391_set_power(struct lcd_device *ld, int power) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && + power != FB_BLANK_NORMAL) { + dev_err(&lcd->ld->dev, "power value should be 0, 1 or 4.\n"); + return -EINVAL; + } + + return nt71391_power(lcd, power); +} + +static int nt71391_get_power(struct lcd_device *ld) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + return lcd->power; +} + +static struct lcd_ops nt71391_lcd_ops = { + .set_power = nt71391_set_power, + .get_power = nt71391_get_power, +}; + +#ifdef CONFIG_HAS_EARLYSUSPEND +extern void (*lcd_early_suspend)(void); +extern void (*lcd_late_resume)(void); + +struct lcd_info *g_lcd; + +void nt71391_early_suspend(void) +{ + struct lcd_info *lcd = g_lcd; + int err = 0; + + set_dsim_lcd_enabled(0); + + dev_info(&lcd->ld->dev, "+%s\n", __func__); + + nt71391_power(lcd, FB_BLANK_POWERDOWN); + + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + return ; +} + +void nt71391_late_resume(void) +{ + struct lcd_info *lcd = g_lcd; + + dev_info(&lcd->ld->dev, "+%s\n", __func__); + + nt71391_power(lcd, FB_BLANK_UNBLANK); + + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + set_dsim_lcd_enabled(1); + + return ; +} +#endif + + +static int __init nt71391_probe(struct device *dev) +{ + struct lcd_info *lcd; + int ret = 0; + + lcd = kzalloc(sizeof(struct lcd_info), GFP_KERNEL); + if (!lcd) { + pr_err("failed to allocate for lcd\n"); + ret = -ENOMEM; + goto err_alloc; + } + + g_lcd = lcd; + + lcd->ld = lcd_device_register("panel", dev, lcd, &nt71391_lcd_ops); + if (IS_ERR(lcd->ld)) { + pr_err("failed to register lcd device\n"); + ret = PTR_ERR(lcd->ld); + goto out_free_lcd; + } + + lcd->dev = dev; + lcd->connected = 1; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); + lcd->power = FB_BLANK_UNBLANK; + + mutex_init(&lcd->lock); + + dev_set_drvdata(dev, lcd); + + dev_info(dev, "lcd panel driver has been probed.\n"); + +#ifdef CONFIG_HAS_EARLYSUSPEND + lcd_early_suspend = nt71391_early_suspend; + lcd_late_resume = nt71391_late_resume; +#endif + + ret = device_create_file(&lcd->ld->dev, &dev_attr_lcd_type); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries\n"); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_window_type); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add window_type entries\n"); + + return 0; + +out_free_lcd: + kfree(lcd); +err_alloc: + return ret; +} + +static int __devexit nt71391_remove(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + nt71391_power(lcd, FB_BLANK_POWERDOWN); + lcd_device_unregister(lcd->ld); + kfree(lcd); + + return 0; +} + +static void nt71391_shutdown(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + nt71391_power(lcd, FB_BLANK_POWERDOWN); +} + +static struct mipi_lcd_driver nt71391_mipi_driver = { + .name = "nt71391", + .probe = nt71391_probe, + .remove = __devexit_p(nt71391_remove), + .shutdown = nt71391_shutdown, +}; + +static int __init nt71391_init(void) +{ + return s5p_dsim_register_lcd_driver(&nt71391_mipi_driver); +} + +static void __exit nt71391_exit(void) +{ + return; +} + +module_init(nt71391_init); +module_exit(nt71391_exit); + +MODULE_AUTHOR("SAMSUNG"); +MODULE_DESCRIPTION("NT71391 LCD driver"); +MODULE_LICENSE("GPL"); -- cgit v1.1 From 2a6649bf6aa50c44a05fc02e1efb8b788c58e82b Mon Sep 17 00:00:00 2001 From: sakindia123 Date: Sun, 11 Aug 2013 14:20:37 +0200 Subject: Samsung i9300 Update 11 Change-Id: I7f6dbdd97e3ed66634bf123d43224a79524c04e9 --- drivers/gpu/drm/Makefile | 1 - drivers/media/video/samsung/fimc/fimc_dev.c | 54 ++++++++++++++++++++ drivers/media/video/samsung/fimc/fimc_dev_u1.c | 54 ++++++++++++++++++++ drivers/media/video/samsung/jpeg/jpeg_dev.c | 7 +++ .../video/samsung/mali/arch-orion-m400/config.h | 2 +- drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c | 59 ++++++++++++++-------- drivers/video/Makefile | 1 - drivers/video/fbmem.c | 12 +++++ 8 files changed, 167 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 94f9ec1..d11f4f3 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -40,7 +40,6 @@ obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/ obj-$(CONFIG_DRM_VIA) +=via/ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/ ifeq ($(CONFIG_NAPLES_COMMON),y) -obj-$(CONFIG_DRM_EXYNOS) +=exynos_tmp/ else obj-$(CONFIG_DRM_EXYNOS) +=exynos/ endif diff --git a/drivers/media/video/samsung/fimc/fimc_dev.c b/drivers/media/video/samsung/fimc/fimc_dev.c index 1ed79dd..4822587 100644 --- a/drivers/media/video/samsung/fimc/fimc_dev.c +++ b/drivers/media/video/samsung/fimc/fimc_dev.c @@ -898,6 +898,50 @@ static struct vm_operations_struct fimc_mmap_ops = { }; static inline +int fimc_mmap_own_mem(struct file *filp, struct vm_area_struct *vma) +{ + struct fimc_prv_data *prv_data = + (struct fimc_prv_data *)filp->private_data; + struct fimc_control *ctrl = prv_data->ctrl; + u32 start_phy_addr = 0; + u32 size = vma->vm_end - vma->vm_start; + u32 pfn, idx = vma->vm_pgoff; + u32 buf_length = 0; + + buf_length = ctrl->mem.size; + if (size > PAGE_ALIGN(buf_length)) { + fimc_err("Requested mmap size is too big\n"); + return -EINVAL; + } + + start_phy_addr = ctrl->mem.base + (vma->vm_pgoff << PAGE_SHIFT); + + if (!cma_is_registered_region(start_phy_addr, size)) { + pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n", + __func__, buf_length, start_phy_addr); + return -EINVAL; + } + + /* only supports non-cached mmap */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= VM_RESERVED; + + if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) { + fimc_err("writable mapping must be shared\n"); + return -EINVAL; + } + + pfn = __phys_to_pfn(start_phy_addr); + + if (remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot)) { + fimc_err("mmap fail\n"); + return -EINVAL; + } + + return 0; +} + +static inline int fimc_mmap_out_src(struct file *filp, struct vm_area_struct *vma) { struct fimc_prv_data *prv_data = @@ -981,10 +1025,14 @@ static inline int fimc_mmap_out(struct file *filp, struct vm_area_struct *vma) int idx = ctrl->out->ctx[ctx_id].overlay.req_idx; int ret = -1; +#if 0 if (idx >= 0) ret = fimc_mmap_out_dst(filp, vma, idx); else if (idx == FIMC_MMAP_IDX) ret = fimc_mmap_out_src(filp, vma); +#else + ret = fimc_mmap_own_mem(filp, vma); +#endif return ret; } @@ -1002,6 +1050,12 @@ static inline int fimc_mmap_cap(struct file *filp, struct vm_area_struct *vma) vma->vm_flags |= VM_RESERVED; + if (!cma_is_registered_region(ctrl->cap->bufs[idx].base[0], size)) { + pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n", + __func__, size, ctrl->cap->bufs[idx].base[0]); + return -EINVAL; + } + /* * page frame number of the address for a source frame * to be stored at. diff --git a/drivers/media/video/samsung/fimc/fimc_dev_u1.c b/drivers/media/video/samsung/fimc/fimc_dev_u1.c index 811ac96..52246a1 100644 --- a/drivers/media/video/samsung/fimc/fimc_dev_u1.c +++ b/drivers/media/video/samsung/fimc/fimc_dev_u1.c @@ -745,6 +745,50 @@ static struct vm_operations_struct fimc_mmap_ops = { }; static inline +int fimc_mmap_own_mem(struct file *filp, struct vm_area_struct *vma) +{ + struct fimc_prv_data *prv_data = + (struct fimc_prv_data *)filp->private_data; + struct fimc_control *ctrl = prv_data->ctrl; + u32 start_phy_addr = 0; + u32 size = vma->vm_end - vma->vm_start; + u32 pfn, idx = vma->vm_pgoff; + u32 buf_length = 0; + + buf_length = ctrl->mem.size; + if (size > PAGE_ALIGN(buf_length)) { + fimc_err("Requested mmap size is too big\n"); + return -EINVAL; + } + + start_phy_addr = ctrl->mem.base + (vma->vm_pgoff << PAGE_SHIFT); + + if (!cma_is_registered_region(start_phy_addr, size)) { + pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n", + __func__, buf_length, start_phy_addr); + return -EINVAL; + } + + /* only supports non-cached mmap */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= VM_RESERVED; + + if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) { + fimc_err("writable mapping must be shared\n"); + return -EINVAL; + } + + pfn = __phys_to_pfn(start_phy_addr); + + if (remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot)) { + fimc_err("mmap fail\n"); + return -EINVAL; + } + + return 0; +} + +static inline int fimc_mmap_out_src(struct file *filp, struct vm_area_struct *vma) { struct fimc_prv_data *prv_data = @@ -829,10 +873,14 @@ static inline int fimc_mmap_out(struct file *filp, struct vm_area_struct *vma) int idx = ctrl->out->ctx[ctx_id].overlay.req_idx; int ret = -1; +#if 0 if (idx >= 0) ret = fimc_mmap_out_dst(filp, vma, idx); else if (idx == FIMC_MMAP_IDX) ret = fimc_mmap_out_src(filp, vma); +#else + ret = fimc_mmap_own_mem(filp, vma); +#endif return ret; } @@ -849,6 +897,12 @@ static inline int fimc_mmap_cap(struct file *filp, struct vm_area_struct *vma) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_flags |= VM_RESERVED; + if (!cma_is_registered_region(ctrl->cap->bufs[idx].base[0], size)) { + pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n", + __func__, size, ctrl->cap->bufs[idx].base[0]); + return -EINVAL; + } + /* * page frame number of the address for a source frame * to be stored at. diff --git a/drivers/media/video/samsung/jpeg/jpeg_dev.c b/drivers/media/video/samsung/jpeg/jpeg_dev.c index 4038fd2..6ebcfb6 100644 --- a/drivers/media/video/samsung/jpeg/jpeg_dev.c +++ b/drivers/media/video/samsung/jpeg/jpeg_dev.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -247,6 +248,12 @@ int jpeg_mmap(struct file *filp, struct vm_area_struct *vma) size = vma->vm_end - vma->vm_start; + if (!cma_is_registered_region(jpeg_ctrl->mem.base, size)) { + pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n", + __func__, (unsigned int)size, jpeg_ctrl->mem.base); + return -EINVAL; + } + vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); diff --git a/drivers/media/video/samsung/mali/arch-orion-m400/config.h b/drivers/media/video/samsung/mali/arch-orion-m400/config.h index 5c4d79d..73502a2 100644 --- a/drivers/media/video/samsung/mali/arch-orion-m400/config.h +++ b/drivers/media/video/samsung/mali/arch-orion-m400/config.h @@ -130,7 +130,7 @@ static _mali_osk_resource_t arch_configuration [] = #endif/* if USING_OS_MEMORY*/ { .type = MEM_VALIDATION, - .description = "memory validation", + .description = "Framebuffer Memory", .base = MEM_BASE_ADDR, .size = MEM_TOTAL_SIZE, .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c b/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c index 3fa6e55..228be02 100644 --- a/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c +++ b/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c @@ -27,6 +27,8 @@ #include #endif +#include + #ifdef CONFIG_UMP_VCM_ALLOC #include "ump_kernel_interface.h" #endif @@ -881,13 +883,24 @@ long s5p_tvout_tvif_ioctl( goto end_tvif_ioctl; } for (i = 0; i < S5PTV_VP_BUFF_CNT; i++) { - s5ptv_vp_buff.vp_buffs[i].phy_base = buffs[i].phy_base; - s5ptv_vp_buff.vp_buffs[i].vir_base = - (unsigned int)phys_to_virt(buffs[i].phy_base); - s5ptv_vp_buff.vp_buffs[i].size = buffs[i].size; - tvout_dbg("s5ptv_vp_buff phy_base = 0x%x, vir_base = 0x%8x\n", - s5ptv_vp_buff.vp_buffs[i].phy_base, - s5ptv_vp_buff.vp_buffs[i].vir_base); + if (cma_is_registered_region(buffs[i].phy_base, + buffs[i].size)) { + s5ptv_vp_buff.vp_buffs[i].phy_base = + buffs[i].phy_base; + s5ptv_vp_buff.vp_buffs[i].vir_base = + (unsigned int)phys_to_virt(buffs[i].phy_base); + s5ptv_vp_buff.vp_buffs[i].size = buffs[i].size; + tvout_dbg("s5ptv_vp_buff phy_base = 0x%x, " + "vir_base = 0x%8x\n", + s5ptv_vp_buff.vp_buffs[i].phy_base, + s5ptv_vp_buff.vp_buffs[i].vir_base); + } else { + s5ptv_vp_buff.vp_buffs[i].phy_base = 0; + s5ptv_vp_buff.vp_buffs[i].vir_base = 0; + printk(KERN_ERR "Buffer for VP is not CMA region\n"); + ret = -EINVAL; + goto end_tvif_ioctl; + } } goto end_tvif_ioctl; } @@ -1134,6 +1147,25 @@ static int s5p_tvout_vo_s_fmt_type_private( pix_fmt->height, color, field); #else if (pix_fmt->priv) { + if (pix_fmt->pixelformat == V4L2_PIX_FMT_NV12T + || pix_fmt->pixelformat == V4L2_PIX_FMT_NV21T) { + y_size = ALIGN(ALIGN(pix_fmt->width, 128) * + ALIGN(pix_fmt->height, 32), SZ_8K); + cbcr_size = ALIGN(ALIGN(pix_fmt->width, 128) * + ALIGN(pix_fmt->height >> 1, 32), SZ_8K); + } else { + y_size = pix_fmt->width * pix_fmt->height; + cbcr_size = pix_fmt->width * (pix_fmt->height >> 1); + } + if (!cma_is_registered_region((unsigned int)vparam.base_y, + y_size) || + !cma_is_registered_region((unsigned int)vparam.base_c, + cbcr_size)) { + printk(KERN_ERR "Source image for VP is not" + "CMA region\n"); + goto error_on_s_fmt_type_private; + } + copy_buff_idx = s5ptv_vp_buff. copy_buff_idxs[s5ptv_vp_buff.curr_copy_idx]; @@ -1144,19 +1176,6 @@ static int s5p_tvout_vo_s_fmt_type_private( (u32) vparam.base_y, (u32) vparam.base_c, pix_fmt->width, pix_fmt->height, color, field); } else { - if (pix_fmt->pixelformat == - V4L2_PIX_FMT_NV12T - || pix_fmt->pixelformat == V4L2_PIX_FMT_NV21T) { - y_size = ALIGN(ALIGN(pix_fmt->width, 128) * - ALIGN(pix_fmt->height, 32), SZ_8K); - cbcr_size = ALIGN(ALIGN(pix_fmt->width, 128) * - ALIGN(pix_fmt->height >> 1, 32), SZ_8K); - } else { - y_size = pix_fmt->width * pix_fmt->height; - cbcr_size = - pix_fmt->width * (pix_fmt->height >> 1); - } - src_vir_y_addr = (unsigned int)phys_to_virt( (unsigned long)vparam.base_y); src_vir_cb_addr = (unsigned int)phys_to_virt( diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ff3c7b2..1261866 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -182,4 +182,3 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o #video output switch sysfs driver obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o - diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index b585a38..1ca9b20 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -34,6 +34,7 @@ #include #include +#include /* @@ -1380,6 +1381,17 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) /* frame buffer memory */ start = info->fix.smem_start; len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); + +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) + if (!cma_is_registered_region(start, len)) { + pr_err("%s: %x@%x is allowed to map\n", + __func__, (unsigned int)start, + (unsigned int)len); + mutex_unlock(&info->mm_lock); + return -EINVAL; + } +#endif + if (off >= len) { /* memory mapped io */ off -= len; -- cgit v1.1 From 74bcc029c6ab942f252477a74102877f7d093388 Mon Sep 17 00:00:00 2001 From: mcampbellsmith Date: Wed, 20 Nov 2013 22:34:44 +1100 Subject: mali: bulk import of r3p2-01rel3 drivers from i9300-update12 Courtesy of a similar commit from OMNI ROM. Requires updated mali blobs Change-Id: I9ee55b653b57b7c390f8e0e8cd4fc068f1c751c3 --- drivers/Kconfig | 2 + drivers/base/sync.c | 321 ++- drivers/gpu/Makefile | 6 + drivers/gpu/mali400/Kconfig | 26 + drivers/gpu/mali400/r3p2/mali/Kbuild | 220 +++ drivers/gpu/mali400/r3p2/mali/Kconfig | 67 + drivers/gpu/mali400/r3p2/mali/MALI_CONFIGURATION | 24 + drivers/gpu/mali400/r3p2/mali/Makefile | 138 ++ .../gpu/mali400/r3p2/mali/__malidrv_build_info.c | 1 + .../r3p2/mali/common/mali_block_allocator.c | 392 ++++ .../r3p2/mali/common/mali_block_allocator.h | 18 + .../gpu/mali400/r3p2/mali/common/mali_broadcast.c | 129 ++ .../gpu/mali400/r3p2/mali/common/mali_broadcast.h | 52 + drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.c | 217 +++ drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.h | 46 + drivers/gpu/mali400/r3p2/mali/common/mali_gp.c | 364 ++++ drivers/gpu/mali400/r3p2/mali/common/mali_gp.h | 96 + drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.c | 116 ++ drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.h | 152 ++ .../mali400/r3p2/mali/common/mali_gp_scheduler.c | 571 ++++++ .../mali400/r3p2/mali/common/mali_gp_scheduler.h | 47 + drivers/gpu/mali400/r3p2/mali/common/mali_group.c | 2046 ++++++++++++++++++++ drivers/gpu/mali400/r3p2/mali/common/mali_group.h | 283 +++ .../gpu/mali400/r3p2/mali/common/mali_hw_core.c | 47 + .../gpu/mali400/r3p2/mali/common/mali_hw_core.h | 104 + .../mali400/r3p2/mali/common/mali_kernel_common.h | 186 ++ .../mali400/r3p2/mali/common/mali_kernel_core.c | 1293 +++++++++++++ .../mali400/r3p2/mali/common/mali_kernel_core.h | 51 + .../mali/common/mali_kernel_descriptor_mapping.c | 184 ++ .../mali/common/mali_kernel_descriptor_mapping.h | 101 + .../mali400/r3p2/mali/common/mali_kernel_mem_os.c | 351 ++++ .../mali400/r3p2/mali/common/mali_kernel_mem_os.h | 37 + .../r3p2/mali/common/mali_kernel_memory_engine.c | 375 ++++ .../r3p2/mali/common/mali_kernel_memory_engine.h | 152 ++ .../r3p2/mali/common/mali_kernel_utilization.c | 420 ++++ .../r3p2/mali/common/mali_kernel_utilization.h | 68 + .../mali400/r3p2/mali/common/mali_kernel_vsync.c | 51 + .../gpu/mali400/r3p2/mali/common/mali_l2_cache.c | 463 +++++ .../gpu/mali400/r3p2/mali/common/mali_l2_cache.h | 75 + .../mali400/r3p2/mali/common/mali_mem_validation.c | 99 + .../mali400/r3p2/mali/common/mali_mem_validation.h | 19 + drivers/gpu/mali400/r3p2/mali/common/mali_memory.c | 1295 +++++++++++++ drivers/gpu/mali400/r3p2/mali/common/mali_memory.h | 86 + drivers/gpu/mali400/r3p2/mali/common/mali_mmu.c | 452 +++++ drivers/gpu/mali400/r3p2/mali/common/mali_mmu.h | 130 ++ .../r3p2/mali/common/mali_mmu_page_directory.c | 485 +++++ .../r3p2/mali/common/mali_mmu_page_directory.h | 100 + drivers/gpu/mali400/r3p2/mali/common/mali_osk.h | 1811 +++++++++++++++++ .../gpu/mali400/r3p2/mali/common/mali_osk_bitops.h | 166 ++ .../gpu/mali400/r3p2/mali/common/mali_osk_list.h | 183 ++ .../gpu/mali400/r3p2/mali/common/mali_osk_mali.h | 269 +++ .../mali400/r3p2/mali/common/mali_osk_profiling.h | 141 ++ drivers/gpu/mali400/r3p2/mali/common/mali_pm.c | 144 ++ drivers/gpu/mali400/r3p2/mali/common/mali_pm.h | 28 + .../gpu/mali400/r3p2/mali/common/mali_pm_domain.c | 240 +++ .../gpu/mali400/r3p2/mali/common/mali_pm_domain.h | 73 + drivers/gpu/mali400/r3p2/mali/common/mali_pmu.c | 405 ++++ drivers/gpu/mali400/r3p2/mali/common/mali_pmu.h | 113 ++ drivers/gpu/mali400/r3p2/mali/common/mali_pp.c | 521 +++++ drivers/gpu/mali400/r3p2/mali/common/mali_pp.h | 127 ++ drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.c | 169 ++ drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.h | 308 +++ .../mali400/r3p2/mali/common/mali_pp_scheduler.c | 1890 ++++++++++++++++++ .../mali400/r3p2/mali/common/mali_pp_scheduler.h | 80 + .../gpu/mali400/r3p2/mali/common/mali_scheduler.c | 37 + .../gpu/mali400/r3p2/mali/common/mali_scheduler.h | 47 + .../gpu/mali400/r3p2/mali/common/mali_session.c | 47 + .../gpu/mali400/r3p2/mali/common/mali_session.h | 72 + drivers/gpu/mali400/r3p2/mali/common/mali_ukk.h | 626 ++++++ .../r3p2/mali/common/mali_user_settings_db.c | 95 + .../r3p2/mali/common/mali_user_settings_db.h | 40 + .../r3p2/mali/include/linux/mali/mali_utgard.h | 390 ++++ .../mali/include/linux/mali/mali_utgard_counters.h | 264 +++ .../mali/include/linux/mali/mali_utgard_ioctl.h | 90 + .../linux/mali/mali_utgard_profiling_events.h | 172 ++ .../linux/mali/mali_utgard_profiling_gator_api.h | 202 ++ .../mali/include/linux/mali/mali_utgard_uk_types.h | 1165 +++++++++++ .../mali/linux/license/gpl/mali_kernel_license.h | 31 + .../r3p2/mali/linux/mali_device_pause_resume.c | 35 + drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.c | 480 +++++ drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.h | 40 + .../mali400/r3p2/mali/linux/mali_kernel_linux.c | 730 +++++++ .../mali400/r3p2/mali/linux/mali_kernel_linux.h | 37 + .../mali400/r3p2/mali/linux/mali_kernel_sysfs.c | 1709 ++++++++++++++++ .../mali400/r3p2/mali/linux/mali_kernel_sysfs.h | 30 + .../gpu/mali400/r3p2/mali/linux/mali_linux_trace.h | 126 ++ .../gpu/mali400/r3p2/mali/linux/mali_osk_atomics.c | 55 + drivers/gpu/mali400/r3p2/mali/linux/mali_osk_irq.c | 139 ++ .../gpu/mali400/r3p2/mali/linux/mali_osk_locks.c | 303 +++ .../r3p2/mali/linux/mali_osk_low_level_mem.c | 723 +++++++ .../gpu/mali400/r3p2/mali/linux/mali_osk_mali.c | 140 ++ .../gpu/mali400/r3p2/mali/linux/mali_osk_math.c | 22 + .../gpu/mali400/r3p2/mali/linux/mali_osk_memory.c | 61 + .../gpu/mali400/r3p2/mali/linux/mali_osk_misc.c | 64 + .../r3p2/mali/linux/mali_osk_notification.c | 191 ++ drivers/gpu/mali400/r3p2/mali/linux/mali_osk_pm.c | 110 ++ .../mali400/r3p2/mali/linux/mali_osk_profiling.c | 287 +++ .../mali400/r3p2/mali/linux/mali_osk_specific.h | 37 + .../gpu/mali400/r3p2/mali/linux/mali_osk_time.c | 51 + .../gpu/mali400/r3p2/mali/linux/mali_osk_timers.c | 77 + .../mali400/r3p2/mali/linux/mali_osk_wait_queue.c | 73 + drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wq.c | 124 ++ .../r3p2/mali/linux/mali_pmu_power_up_down.c | 75 + .../r3p2/mali/linux/mali_profiling_events.h | 17 + .../r3p2/mali/linux/mali_profiling_gator_api.h | 17 + .../r3p2/mali/linux/mali_profiling_internal.c | 300 +++ .../r3p2/mali/linux/mali_profiling_internal.h | 36 + drivers/gpu/mali400/r3p2/mali/linux/mali_sync.c | 273 +++ drivers/gpu/mali400/r3p2/mali/linux/mali_sync.h | 102 + .../gpu/mali400/r3p2/mali/linux/mali_sync_user.c | 183 ++ .../gpu/mali400/r3p2/mali/linux/mali_uk_types.h | 17 + .../gpu/mali400/r3p2/mali/linux/mali_ukk_core.c | 174 ++ drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_gp.c | 88 + drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_mem.c | 303 +++ drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_pp.c | 95 + .../mali400/r3p2/mali/linux/mali_ukk_profiling.c | 183 ++ .../gpu/mali400/r3p2/mali/linux/mali_ukk_vsync.c | 41 + .../mali400/r3p2/mali/linux/mali_ukk_wrappers.h | 74 + .../r3p2/mali/platform/pegasus-m400/exynos4.c | 405 ++++ .../r3p2/mali/platform/pegasus-m400/exynos4_pmm.c | 1373 +++++++++++++ .../r3p2/mali/platform/pegasus-m400/exynos4_pmm.h | 121 ++ drivers/gpu/mali400/r3p2/mali/regs/mali_200_regs.h | 128 ++ drivers/gpu/mali400/r3p2/mali/regs/mali_gp_regs.h | 173 ++ .../r3p2/mali/timestamp-arm11-cc/mali_timestamp.c | 13 + .../r3p2/mali/timestamp-arm11-cc/mali_timestamp.h | 48 + .../r3p2/mali/timestamp-default/mali_timestamp.c | 13 + .../r3p2/mali/timestamp-default/mali_timestamp.h | 26 + drivers/gpu/mali400/r3p2/ump/Kbuild | 78 + drivers/gpu/mali400/r3p2/ump/Kconfig | 7 + drivers/gpu/mali400/r3p2/ump/Makefile | 67 + drivers/gpu/mali400/r3p2/ump/Makefile.common | 20 + .../mali400/r3p2/ump/arch-pegasus-m400/config.h | 22 + .../gpu/mali400/r3p2/ump/arch/arch-pegasus-m400 | 1 + drivers/gpu/mali400/r3p2/ump/arch/config.h | 22 + .../gpu/mali400/r3p2/ump/common/ump_kernel_api.c | 548 ++++++ .../mali400/r3p2/ump/common/ump_kernel_common.c | 417 ++++ .../mali400/r3p2/ump/common/ump_kernel_common.h | 128 ++ .../ump/common/ump_kernel_descriptor_mapping.c | 166 ++ .../ump/common/ump_kernel_descriptor_mapping.h | 91 + .../r3p2/ump/common/ump_kernel_memory_backend.h | 53 + .../mali400/r3p2/ump/common/ump_kernel_ref_drv.c | 259 +++ .../gpu/mali400/r3p2/ump/common/ump_kernel_types.h | 53 + drivers/gpu/mali400/r3p2/ump/common/ump_osk.h | 52 + drivers/gpu/mali400/r3p2/ump/common/ump_ukk.h | 61 + .../r3p2/ump/include/ump_kernel_interface.h | 236 +++ .../ump/include/ump_kernel_interface_ref_drv.h | 35 + .../mali400/r3p2/ump/include/ump_kernel_platform.h | 48 + .../gpu/mali400/r3p2/ump/include/ump_uk_types.h | 204 ++ .../ump/linux/license/gpl/ump_kernel_license.h | 31 + drivers/gpu/mali400/r3p2/ump/linux/ump_ioctl.h | 59 + .../gpu/mali400/r3p2/ump/linux/ump_kernel_linux.c | 500 +++++ .../gpu/mali400/r3p2/ump/linux/ump_kernel_linux.h | 18 + .../linux/ump_kernel_memory_backend_dedicated.c | 288 +++ .../linux/ump_kernel_memory_backend_dedicated.h | 23 + .../r3p2/ump/linux/ump_kernel_memory_backend_os.c | 263 +++ .../r3p2/ump/linux/ump_kernel_memory_backend_os.h | 23 + .../mali400/r3p2/ump/linux/ump_memory_backend.c | 78 + .../gpu/mali400/r3p2/ump/linux/ump_osk_atomics.c | 27 + .../mali400/r3p2/ump/linux/ump_osk_low_level_mem.c | 507 +++++ drivers/gpu/mali400/r3p2/ump/linux/ump_osk_misc.c | 37 + .../mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.c | 331 ++++ .../mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.h | 44 + .../gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.c | 306 +++ .../gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.h | 47 + drivers/media/video/samsung/Kconfig | 2 - drivers/media/video/samsung/Makefile | 2 - drivers/media/video/samsung/mali/Kbuild_module | 295 --- drivers/media/video/samsung/mali/Kconfig | 63 - drivers/media/video/samsung/mali/Kconfig_module | 30 - drivers/media/video/samsung/mali/Makefile | 337 ---- drivers/media/video/samsung/mali/Makefile_module | 97 - drivers/media/video/samsung/mali/arch | 1 - drivers/media/video/samsung/mali/arch-debug | 1 - .../video/samsung/mali/arch-orion-m400/config.h | 154 -- .../samsung/mali/arch-pb-virtex5-m300/config.h | 85 - .../mali/arch-pb-virtex5-m400-1-direct/config.h | 92 - .../mali/arch-pb-virtex5-m400-1-pmu/config.h | 85 - .../samsung/mali/arch-pb-virtex5-m400-1/config.h | 77 - .../samsung/mali/arch-pb-virtex5-m400-2/config.h | 91 - .../samsung/mali/arch-pb-virtex5-m400-3/config.h | 105 - .../samsung/mali/arch-pb-virtex5-m400-4/config.h | 119 -- .../video/samsung/mali/arch-pegasus-m400/config.h | 154 -- drivers/media/video/samsung/mali/arch-release | 1 - .../samsung/mali/arch-ve-virtex6-m450-8/config.h | 174 -- .../samsung/mali/common/mali_block_allocator.c | 391 ---- .../samsung/mali/common/mali_block_allocator.h | 18 - .../media/video/samsung/mali/common/mali_cluster.c | 218 --- .../media/video/samsung/mali/common/mali_cluster.h | 44 - .../samsung/mali/common/mali_device_pause_resume.c | 46 - .../samsung/mali/common/mali_device_pause_resume.h | 31 - .../media/video/samsung/mali/common/mali_dlbu.c | 285 --- .../media/video/samsung/mali/common/mali_dlbu.h | 45 - drivers/media/video/samsung/mali/common/mali_gp.c | 746 ------- drivers/media/video/samsung/mali/common/mali_gp.h | 46 - .../media/video/samsung/mali/common/mali_gp_job.c | 49 - .../media/video/samsung/mali/common/mali_gp_job.h | 131 -- .../video/samsung/mali/common/mali_gp_scheduler.c | 443 ----- .../video/samsung/mali/common/mali_gp_scheduler.h | 30 - .../media/video/samsung/mali/common/mali_group.c | 841 -------- .../media/video/samsung/mali/common/mali_group.h | 146 -- .../media/video/samsung/mali/common/mali_hw_core.c | 46 - .../media/video/samsung/mali/common/mali_hw_core.h | 71 - .../video/samsung/mali/common/mali_kernel_common.h | 183 -- .../video/samsung/mali/common/mali_kernel_core.c | 980 ---------- .../video/samsung/mali/common/mali_kernel_core.h | 39 - .../mali/common/mali_kernel_descriptor_mapping.c | 184 -- .../mali/common/mali_kernel_descriptor_mapping.h | 101 - .../video/samsung/mali/common/mali_kernel_mem_os.c | 354 ---- .../video/samsung/mali/common/mali_kernel_mem_os.h | 37 - .../mali/common/mali_kernel_memory_engine.c | 376 ---- .../mali/common/mali_kernel_memory_engine.h | 152 -- .../samsung/mali/common/mali_kernel_utilization.c | 218 --- .../samsung/mali/common/mali_kernel_utilization.h | 44 - .../video/samsung/mali/common/mali_kernel_vsync.c | 51 - .../video/samsung/mali/common/mali_l2_cache.c | 414 ---- .../video/samsung/mali/common/mali_l2_cache.h | 43 - .../samsung/mali/common/mali_mem_validation.c | 71 - .../samsung/mali/common/mali_mem_validation.h | 19 - .../media/video/samsung/mali/common/mali_memory.c | 1319 ------------- .../media/video/samsung/mali/common/mali_memory.h | 82 - drivers/media/video/samsung/mali/common/mali_mmu.c | 619 ------ drivers/media/video/samsung/mali/common/mali_mmu.h | 55 - .../samsung/mali/common/mali_mmu_page_directory.c | 475 ----- .../samsung/mali/common/mali_mmu_page_directory.h | 100 - drivers/media/video/samsung/mali/common/mali_osk.h | 1798 ----------------- .../video/samsung/mali/common/mali_osk_bitops.h | 166 -- .../video/samsung/mali/common/mali_osk_list.h | 184 -- .../video/samsung/mali/common/mali_osk_mali.h | 222 --- .../video/samsung/mali/common/mali_osk_profiling.h | 147 -- drivers/media/video/samsung/mali/common/mali_pm.c | 552 ------ drivers/media/video/samsung/mali/common/mali_pm.h | 56 - drivers/media/video/samsung/mali/common/mali_pmu.c | 199 -- drivers/media/video/samsung/mali/common/mali_pmu.h | 70 - drivers/media/video/samsung/mali/common/mali_pp.c | 710 ------- drivers/media/video/samsung/mali/common/mali_pp.h | 47 - .../media/video/samsung/mali/common/mali_pp_job.c | 95 - .../media/video/samsung/mali/common/mali_pp_job.h | 273 --- .../video/samsung/mali/common/mali_pp_scheduler.c | 594 ------ .../video/samsung/mali/common/mali_pp_scheduler.h | 38 - .../video/samsung/mali/common/mali_scheduler.c | 37 - .../video/samsung/mali/common/mali_scheduler.h | 21 - .../media/video/samsung/mali/common/mali_session.c | 47 - .../media/video/samsung/mali/common/mali_session.h | 65 - drivers/media/video/samsung/mali/common/mali_ukk.h | 612 ------ .../samsung/mali/common/mali_user_settings_db.c | 88 - .../samsung/mali/common/mali_user_settings_db.h | 40 - .../samsung/mali/include/linux/mali/mali_utgard.h | 28 - .../mali/include/linux/mali/mali_utgard_counters.h | 264 --- .../mali/include/linux/mali/mali_utgard_ioctl.h | 86 - .../linux/mali/mali_utgard_profiling_events.h | 127 -- .../mali/include/linux/mali/mali_utgard_uk_types.h | 1095 ----------- .../mali/linux/license/gpl/mali_kernel_license.h | 31 - .../media/video/samsung/mali/linux/mali_dma_buf.c | 392 ---- .../media/video/samsung/mali/linux/mali_dma_buf.h | 29 - .../video/samsung/mali/linux/mali_kernel_linux.c | 634 ------ .../video/samsung/mali/linux/mali_kernel_linux.h | 43 - .../video/samsung/mali/linux/mali_kernel_pm.c | 268 --- .../video/samsung/mali/linux/mali_kernel_pm.h | 17 - .../video/samsung/mali/linux/mali_kernel_sysfs.c | 1280 ------------ .../video/samsung/mali/linux/mali_kernel_sysfs.h | 35 - .../media/video/samsung/mali/linux/mali_linux_pm.h | 50 - .../samsung/mali/linux/mali_linux_pm_testsuite.h | 32 - .../video/samsung/mali/linux/mali_linux_trace.h | 126 -- .../video/samsung/mali/linux/mali_osk_atomics.c | 55 - .../media/video/samsung/mali/linux/mali_osk_irq.c | 266 --- .../video/samsung/mali/linux/mali_osk_locks.c | 340 ---- .../samsung/mali/linux/mali_osk_low_level_mem.c | 660 ------- .../media/video/samsung/mali/linux/mali_osk_mali.c | 34 - .../media/video/samsung/mali/linux/mali_osk_math.c | 22 - .../video/samsung/mali/linux/mali_osk_memory.c | 61 - .../media/video/samsung/mali/linux/mali_osk_misc.c | 64 - .../samsung/mali/linux/mali_osk_notification.c | 189 -- .../media/video/samsung/mali/linux/mali_osk_pm.c | 83 - .../samsung/mali/linux/mali_osk_profiling_gator.c | 261 --- .../mali/linux/mali_osk_profiling_internal.c | 324 ---- .../video/samsung/mali/linux/mali_osk_specific.h | 130 -- .../media/video/samsung/mali/linux/mali_osk_time.c | 51 - .../video/samsung/mali/linux/mali_osk_timers.c | 65 - .../video/samsung/mali/linux/mali_osk_wait_queue.c | 73 - .../samsung/mali/linux/mali_pmu_power_up_down.c | 65 - .../samsung/mali/linux/mali_profiling_events.h | 17 - .../media/video/samsung/mali/linux/mali_uk_types.h | 18 - .../media/video/samsung/mali/linux/mali_ukk_core.c | 104 - .../media/video/samsung/mali/linux/mali_ukk_gp.c | 113 -- .../media/video/samsung/mali/linux/mali_ukk_mem.c | 259 --- .../media/video/samsung/mali/linux/mali_ukk_pp.c | 88 - .../video/samsung/mali/linux/mali_ukk_profiling.c | 183 -- .../video/samsung/mali/linux/mali_ukk_vsync.c | 41 - .../video/samsung/mali/linux/mali_ukk_wrappers.h | 68 - .../samsung/mali/platform/default/mali_platform.c | 43 - .../video/samsung/mali/platform/mali_platform.h | 153 -- .../mali_platform_pmu_testing/mali_platform.c | 66 - .../mali/platform/orion-m400/mali_platform.c | 656 ------- .../mali/platform/orion-m400/mali_platform_dvfs.c | 448 ----- .../mali/platform/pegasus-m400/mali_platform.c | 801 -------- .../platform/pegasus-m400/mali_platform_dvfs.c | 847 -------- .../media/video/samsung/mali/regs/mali_200_regs.h | 172 -- .../media/video/samsung/mali/regs/mali_gp_regs.h | 214 -- .../mali/timestamp-arm11-cc/mali_timestamp.c | 13 - .../mali/timestamp-arm11-cc/mali_timestamp.h | 48 - .../mali/timestamp-default/mali_timestamp.c | 13 - .../mali/timestamp-default/mali_timestamp.h | 26 - drivers/media/video/samsung/ump/Kconfig | 58 - drivers/media/video/samsung/ump/Kconfig_module | 16 - drivers/media/video/samsung/ump/Makefile | 93 - drivers/media/video/samsung/ump/Makefile.common | 20 - drivers/media/video/samsung/ump/arch | 1 - drivers/media/video/samsung/ump/arch-debug | 1 - .../video/samsung/ump/arch-orion-m400/config.h | 22 - .../video/samsung/ump/arch-pb-virtex5/config.h | 18 - .../video/samsung/ump/arch-pegasus-m400/config.h | 22 - drivers/media/video/samsung/ump/arch-release | 1 - .../video/samsung/ump/common/ump_kernel_api.c | 551 ------ .../video/samsung/ump/common/ump_kernel_common.c | 414 ---- .../video/samsung/ump/common/ump_kernel_common.h | 128 -- .../ump/common/ump_kernel_descriptor_mapping.c | 165 -- .../ump/common/ump_kernel_descriptor_mapping.h | 91 - .../samsung/ump/common/ump_kernel_memory_backend.h | 51 - .../video/samsung/ump/common/ump_kernel_ref_drv.c | 260 --- .../video/samsung/ump/common/ump_kernel_types.h | 53 - drivers/media/video/samsung/ump/common/ump_osk.h | 51 - .../media/video/samsung/ump/common/ump_uk_types.h | 208 -- drivers/media/video/samsung/ump/common/ump_ukk.h | 61 - .../samsung/ump/include/ump_kernel_interface.h | 236 --- .../ump/include/ump_kernel_interface_ref_drv.h | 35 - .../samsung/ump/include/ump_kernel_platform.h | 48 - .../ump/linux/license/gpl/ump_kernel_license.h | 31 - drivers/media/video/samsung/ump/linux/ump_ioctl.h | 61 - .../video/samsung/ump/linux/ump_kernel_linux.c | 492 ----- .../video/samsung/ump/linux/ump_kernel_linux.h | 18 - .../linux/ump_kernel_memory_backend_dedicated.c | 287 --- .../linux/ump_kernel_memory_backend_dedicated.h | 23 - .../ump/linux/ump_kernel_memory_backend_os.c | 260 --- .../ump/linux/ump_kernel_memory_backend_os.h | 23 - .../ump/linux/ump_kernel_memory_backend_vcm.c | 290 --- .../ump/linux/ump_kernel_memory_backend_vcm.h | 22 - .../video/samsung/ump/linux/ump_memory_backend.c | 77 - .../video/samsung/ump/linux/ump_osk_atomics.c | 27 - .../samsung/ump/linux/ump_osk_low_level_mem.c | 485 ----- .../media/video/samsung/ump/linux/ump_osk_misc.c | 37 - .../video/samsung/ump/linux/ump_ukk_ref_wrappers.c | 320 --- .../video/samsung/ump/linux/ump_ukk_ref_wrappers.h | 43 - .../video/samsung/ump/linux/ump_ukk_wrappers.c | 306 --- .../video/samsung/ump/linux/ump_ukk_wrappers.h | 47 - 344 files changed, 36918 insertions(+), 34751 deletions(-) create mode 100644 drivers/gpu/mali400/Kconfig create mode 100644 drivers/gpu/mali400/r3p2/mali/Kbuild create mode 100644 drivers/gpu/mali400/r3p2/mali/Kconfig create mode 100644 drivers/gpu/mali400/r3p2/mali/MALI_CONFIGURATION create mode 100644 drivers/gpu/mali400/r3p2/mali/Makefile create mode 100644 drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_gp.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_gp.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_group.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_group.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_common.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_kernel_vsync.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_memory.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_memory.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_mmu.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_mmu.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_osk.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_osk_bitops.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_osk_list.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_osk_mali.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_osk_profiling.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pm.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pm.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pmu.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pmu.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pp.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pp.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_session.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_session.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_ukk.h create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.c create mode 100644 drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.h create mode 100644 drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard.h create mode 100644 drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_counters.h create mode 100644 drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_ioctl.h create mode 100644 drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_events.h create mode 100644 drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_gator_api.h create mode 100644 drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_uk_types.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/license/gpl/mali_kernel_license.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_device_pause_resume.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_linux_trace.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_atomics.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_irq.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_locks.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_low_level_mem.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_mali.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_math.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_memory.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_misc.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_notification.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_pm.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_profiling.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_specific.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_time.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_timers.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wait_queue.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wq.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_pmu_power_up_down.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_events.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_gator_api.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_sync.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_sync.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_sync_user.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_uk_types.h create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_core.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_gp.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_mem.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_pp.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_profiling.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_vsync.c create mode 100644 drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_wrappers.h create mode 100644 drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4.c create mode 100644 drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c create mode 100644 drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.h create mode 100644 drivers/gpu/mali400/r3p2/mali/regs/mali_200_regs.h create mode 100644 drivers/gpu/mali400/r3p2/mali/regs/mali_gp_regs.h create mode 100644 drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.c create mode 100644 drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.h create mode 100644 drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.c create mode 100644 drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.h create mode 100644 drivers/gpu/mali400/r3p2/ump/Kbuild create mode 100644 drivers/gpu/mali400/r3p2/ump/Kconfig create mode 100644 drivers/gpu/mali400/r3p2/ump/Makefile create mode 100644 drivers/gpu/mali400/r3p2/ump/Makefile.common create mode 100644 drivers/gpu/mali400/r3p2/ump/arch-pegasus-m400/config.h create mode 120000 drivers/gpu/mali400/r3p2/ump/arch/arch-pegasus-m400 create mode 100644 drivers/gpu/mali400/r3p2/ump/arch/config.h create mode 100644 drivers/gpu/mali400/r3p2/ump/common/ump_kernel_api.c create mode 100644 drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c create mode 100644 drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.h create mode 100644 drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.c create mode 100644 drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.h create mode 100644 drivers/gpu/mali400/r3p2/ump/common/ump_kernel_memory_backend.h create mode 100644 drivers/gpu/mali400/r3p2/ump/common/ump_kernel_ref_drv.c create mode 100644 drivers/gpu/mali400/r3p2/ump/common/ump_kernel_types.h create mode 100644 drivers/gpu/mali400/r3p2/ump/common/ump_osk.h create mode 100644 drivers/gpu/mali400/r3p2/ump/common/ump_ukk.h create mode 100644 drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface.h create mode 100644 drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface_ref_drv.h create mode 100644 drivers/gpu/mali400/r3p2/ump/include/ump_kernel_platform.h create mode 100644 drivers/gpu/mali400/r3p2/ump/include/ump_uk_types.h create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/license/gpl/ump_kernel_license.h create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_ioctl.h create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.c create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.h create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.c create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.h create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.h create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_memory_backend.c create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_osk_atomics.c create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_osk_low_level_mem.c create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_osk_misc.c create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.c create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.h create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.c create mode 100644 drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.h delete mode 100644 drivers/media/video/samsung/mali/Kbuild_module delete mode 100644 drivers/media/video/samsung/mali/Kconfig delete mode 100644 drivers/media/video/samsung/mali/Kconfig_module delete mode 100644 drivers/media/video/samsung/mali/Makefile delete mode 100644 drivers/media/video/samsung/mali/Makefile_module delete mode 120000 drivers/media/video/samsung/mali/arch delete mode 120000 drivers/media/video/samsung/mali/arch-debug delete mode 100644 drivers/media/video/samsung/mali/arch-orion-m400/config.h delete mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h delete mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h delete mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h delete mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h delete mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h delete mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h delete mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h delete mode 100644 drivers/media/video/samsung/mali/arch-pegasus-m400/config.h delete mode 120000 drivers/media/video/samsung/mali/arch-release delete mode 100644 drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_block_allocator.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_block_allocator.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_cluster.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_cluster.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_device_pause_resume.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_device_pause_resume.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_dlbu.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_dlbu.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_gp.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_gp.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_gp_job.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_gp_job.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_gp_scheduler.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_gp_scheduler.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_group.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_group.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_hw_core.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_hw_core.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_common.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_core.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_core.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_mem_os.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_utilization.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_utilization.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_vsync.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_l2_cache.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_l2_cache.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_mem_validation.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_mem_validation.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_memory.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_memory.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_mmu.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_mmu.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_osk.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_osk_bitops.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_osk_list.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_osk_mali.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_osk_profiling.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_pm.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_pm.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_pmu.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_pmu.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_pp.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_pp.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_pp_job.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_pp_job.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_pp_scheduler.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_pp_scheduler.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_scheduler.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_scheduler.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_session.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_session.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_ukk.h delete mode 100644 drivers/media/video/samsung/mali/common/mali_user_settings_db.c delete mode 100644 drivers/media/video/samsung/mali/common/mali_user_settings_db.h delete mode 100644 drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h delete mode 100644 drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h delete mode 100644 drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h delete mode 100644 drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h delete mode 100644 drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h delete mode 100644 drivers/media/video/samsung/mali/linux/license/gpl/mali_kernel_license.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_dma_buf.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_dma_buf.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_linux.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_linux.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_pm.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_pm.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_linux_pm.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_linux_trace.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_atomics.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_irq.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_locks.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_mali.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_math.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_memory.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_misc.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_notification.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_pm.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_specific.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_time.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_timers.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_profiling_events.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_uk_types.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_core.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_gp.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_mem.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_pp.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h delete mode 100644 drivers/media/video/samsung/mali/platform/default/mali_platform.c delete mode 100644 drivers/media/video/samsung/mali/platform/mali_platform.h delete mode 100644 drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c delete mode 100644 drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c delete mode 100644 drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c delete mode 100644 drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c delete mode 100644 drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c delete mode 100644 drivers/media/video/samsung/mali/regs/mali_200_regs.h delete mode 100644 drivers/media/video/samsung/mali/regs/mali_gp_regs.h delete mode 100644 drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c delete mode 100644 drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h delete mode 100644 drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c delete mode 100644 drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h delete mode 100644 drivers/media/video/samsung/ump/Kconfig delete mode 100644 drivers/media/video/samsung/ump/Kconfig_module delete mode 100644 drivers/media/video/samsung/ump/Makefile delete mode 100644 drivers/media/video/samsung/ump/Makefile.common delete mode 120000 drivers/media/video/samsung/ump/arch delete mode 120000 drivers/media/video/samsung/ump/arch-debug delete mode 100644 drivers/media/video/samsung/ump/arch-orion-m400/config.h delete mode 100644 drivers/media/video/samsung/ump/arch-pb-virtex5/config.h delete mode 100644 drivers/media/video/samsung/ump/arch-pegasus-m400/config.h delete mode 120000 drivers/media/video/samsung/ump/arch-release delete mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_api.c delete mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_common.c delete mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_common.h delete mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c delete mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h delete mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h delete mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c delete mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_types.h delete mode 100644 drivers/media/video/samsung/ump/common/ump_osk.h delete mode 100644 drivers/media/video/samsung/ump/common/ump_uk_types.h delete mode 100644 drivers/media/video/samsung/ump/common/ump_ukk.h delete mode 100644 drivers/media/video/samsung/ump/include/ump_kernel_interface.h delete mode 100644 drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h delete mode 100644 drivers/media/video/samsung/ump/include/ump_kernel_platform.h delete mode 100644 drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h delete mode 100644 drivers/media/video/samsung/ump/linux/ump_ioctl.h delete mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_linux.c delete mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_linux.h delete mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c delete mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h delete mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c delete mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h delete mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c delete mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h delete mode 100644 drivers/media/video/samsung/ump/linux/ump_memory_backend.c delete mode 100644 drivers/media/video/samsung/ump/linux/ump_osk_atomics.c delete mode 100644 drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c delete mode 100644 drivers/media/video/samsung/ump/linux/ump_osk_misc.c delete mode 100644 drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c delete mode 100644 drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h delete mode 100644 drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c delete mode 100644 drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index eb24286..b16fa42 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -1,5 +1,7 @@ menu "Device Drivers" +source "drivers/gpu/mali400/Kconfig" + source "drivers/base/Kconfig" source "drivers/connector/Kconfig" diff --git a/drivers/base/sync.c b/drivers/base/sync.c index d6913f8..06a5eac 100644 --- a/drivers/base/sync.c +++ b/drivers/base/sync.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -27,8 +28,13 @@ #include +#define CREATE_TRACE_POINTS +#include + static void sync_fence_signal_pt(struct sync_pt *pt); static int _sync_pt_has_signaled(struct sync_pt *pt); +static void sync_fence_free(struct kref *kref); +static void sync_dump(void); static LIST_HEAD(sync_timeline_list_head); static DEFINE_SPINLOCK(sync_timeline_list_lock); @@ -49,6 +55,7 @@ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, if (obj == NULL) return NULL; + kref_init(&obj->kref); obj->ops = ops; strlcpy(obj->name, name, sizeof(obj->name)); @@ -64,9 +71,12 @@ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, return obj; } +EXPORT_SYMBOL(sync_timeline_create); -static void sync_timeline_free(struct sync_timeline *obj) +static void sync_timeline_free(struct kref *kref) { + struct sync_timeline *obj = + container_of(kref, struct sync_timeline, kref); unsigned long flags; if (obj->ops->release_obj) @@ -81,19 +91,17 @@ static void sync_timeline_free(struct sync_timeline *obj) void sync_timeline_destroy(struct sync_timeline *obj) { - unsigned long flags; - bool needs_freeing; - - spin_lock_irqsave(&obj->child_list_lock, flags); obj->destroyed = true; - needs_freeing = list_empty(&obj->child_list_head); - spin_unlock_irqrestore(&obj->child_list_lock, flags); - if (needs_freeing) - sync_timeline_free(obj); - else + /* + * If this is not the last reference, signal any children + * that their parent is going away. + */ + + if (!kref_put(&obj->kref, sync_timeline_free)) sync_timeline_signal(obj); } +EXPORT_SYMBOL(sync_timeline_destroy); static void sync_timeline_add_pt(struct sync_timeline *obj, struct sync_pt *pt) { @@ -110,7 +118,6 @@ static void sync_timeline_remove_pt(struct sync_pt *pt) { struct sync_timeline *obj = pt->parent; unsigned long flags; - bool needs_freeing; spin_lock_irqsave(&obj->active_list_lock, flags); if (!list_empty(&pt->active_list)) @@ -118,12 +125,10 @@ static void sync_timeline_remove_pt(struct sync_pt *pt) spin_unlock_irqrestore(&obj->active_list_lock, flags); spin_lock_irqsave(&obj->child_list_lock, flags); - list_del(&pt->child_list); - needs_freeing = obj->destroyed && list_empty(&obj->child_list_head); + if (!list_empty(&pt->child_list)) { + list_del_init(&pt->child_list); + } spin_unlock_irqrestore(&obj->child_list_lock, flags); - - if (needs_freeing) - sync_timeline_free(obj); } void sync_timeline_signal(struct sync_timeline *obj) @@ -132,26 +137,33 @@ void sync_timeline_signal(struct sync_timeline *obj) LIST_HEAD(signaled_pts); struct list_head *pos, *n; + trace_sync_timeline(obj); + spin_lock_irqsave(&obj->active_list_lock, flags); list_for_each_safe(pos, n, &obj->active_list_head) { struct sync_pt *pt = container_of(pos, struct sync_pt, active_list); - if (_sync_pt_has_signaled(pt)) - list_move(pos, &signaled_pts); + if (_sync_pt_has_signaled(pt)) { + list_del_init(pos); + list_add(&pt->signaled_list, &signaled_pts); + kref_get(&pt->fence->kref); + } } spin_unlock_irqrestore(&obj->active_list_lock, flags); list_for_each_safe(pos, n, &signaled_pts) { struct sync_pt *pt = - container_of(pos, struct sync_pt, active_list); + container_of(pos, struct sync_pt, signaled_list); list_del_init(pos); sync_fence_signal_pt(pt); + kref_put(&pt->fence->kref, sync_fence_free); } } +EXPORT_SYMBOL(sync_timeline_signal); struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size) { @@ -165,10 +177,12 @@ struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size) return NULL; INIT_LIST_HEAD(&pt->active_list); + kref_get(&parent->kref); sync_timeline_add_pt(parent, pt); return pt; } +EXPORT_SYMBOL(sync_pt_create); void sync_pt_free(struct sync_pt *pt) { @@ -177,8 +191,11 @@ void sync_pt_free(struct sync_pt *pt) sync_timeline_remove_pt(pt); + kref_put(&pt->parent->kref, sync_timeline_free); + kfree(pt); } +EXPORT_SYMBOL(sync_pt_free); /* call with pt->parent->active_list_lock held */ static int _sync_pt_has_signaled(struct sync_pt *pt) @@ -247,6 +264,7 @@ static struct sync_fence *sync_fence_alloc(const char *name) if (fence->file == NULL) goto err; + kref_init(&fence->kref); strlcpy(fence->name, name, sizeof(fence->name)); INIT_LIST_HEAD(&fence->pt_list_head); @@ -282,29 +300,67 @@ struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt) list_add(&pt->pt_list, &fence->pt_list_head); sync_pt_activate(pt); + /* + * signal the fence in case pt was activated before + * sync_pt_activate(pt) was called + */ + sync_fence_signal_pt(pt); + return fence; } +EXPORT_SYMBOL(sync_fence_create); static int sync_fence_copy_pts(struct sync_fence *dst, struct sync_fence *src) { - struct list_head *pos; + struct list_head *pos, *test_pos; list_for_each(pos, &src->pt_list_head) { struct sync_pt *orig_pt = container_of(pos, struct sync_pt, pt_list); - struct sync_pt *new_pt = sync_pt_dup(orig_pt); + struct sync_pt *new_pt; + + /* Skip already signaled points */ + if (1 == orig_pt->status) + continue; + + list_for_each(test_pos, &src->pt_list_head) { + struct sync_pt *test_pt = + container_of(pos, struct sync_pt, pt_list); + if (orig_pt->parent == test_pt->parent) { + int diff; + diff = orig_pt->parent->ops->compare(orig_pt, + test_pt); + if (diff == -1) { + /* Skip orig_pt; another point will + * signal after it */ + continue; + } + break; + } + } + + new_pt = sync_pt_dup(orig_pt); if (new_pt == NULL) return -ENOMEM; new_pt->fence = dst; list_add(&new_pt->pt_list, &dst->pt_list_head); - sync_pt_activate(new_pt); } return 0; } +static void sync_fence_detach_pts(struct sync_fence *fence) +{ + struct list_head *pos, *n; + + list_for_each_safe(pos, n, &fence->pt_list_head) { + struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list); + sync_timeline_remove_pt(pt); + } +} + static void sync_fence_free_pts(struct sync_fence *fence) { struct list_head *pos, *n; @@ -331,16 +387,19 @@ err: fput(file); return NULL; } +EXPORT_SYMBOL(sync_fence_fdget); void sync_fence_put(struct sync_fence *fence) { fput(fence->file); } +EXPORT_SYMBOL(sync_fence_put); void sync_fence_install(struct sync_fence *fence, int fd) { fd_install(fd, fence->file); } +EXPORT_SYMBOL(sync_fence_install); static int sync_fence_get_status(struct sync_fence *fence) { @@ -349,7 +408,13 @@ static int sync_fence_get_status(struct sync_fence *fence) list_for_each(pos, &fence->pt_list_head) { struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list); - int pt_status = pt->status; + int pt_status; + + if (pt == NULL) { + printk(KERN_ERR"[sync driver] sync_fence_get_status : sync_pt is NULL\n"); + break; + } + pt_status = pt->status; if (pt_status < 0) { status = pt_status; @@ -365,6 +430,7 @@ static int sync_fence_get_status(struct sync_fence *fence) struct sync_fence *sync_fence_merge(const char *name, struct sync_fence *a, struct sync_fence *b) { + struct list_head *pos; struct sync_fence *fence; int err; @@ -380,7 +446,29 @@ struct sync_fence *sync_fence_merge(const char *name, if (err < 0) goto err; - fence->status = sync_fence_get_status(fence); + /* Make sure there is at least one point in the fence */ + if (list_empty(&fence->pt_list_head)) { + struct sync_pt *orig_pt = list_first_entry(&a->pt_list_head, + struct sync_pt, pt_list); + struct sync_pt *new_pt = sync_pt_dup(orig_pt); + + new_pt->fence = fence; + list_add(&new_pt->pt_list, &fence->pt_list_head); + } + + list_for_each(pos, &fence->pt_list_head) { + struct sync_pt *pt = + container_of(pos, struct sync_pt, pt_list); + sync_pt_activate(pt); + } + + /* + * signal the fence in case one of it's pts were activated before + * they were activated + */ + sync_fence_signal_pt(list_first_entry(&fence->pt_list_head, + struct sync_pt, + pt_list)); return fence; err: @@ -388,6 +476,7 @@ err: kfree(fence); return NULL; } +EXPORT_SYMBOL(sync_fence_merge); static void sync_fence_signal_pt(struct sync_pt *pt) { @@ -421,33 +510,22 @@ static void sync_fence_signal_pt(struct sync_pt *pt) container_of(pos, struct sync_fence_waiter, waiter_list); - waiter->callback(fence, waiter->callback_data); list_del(pos); - kfree(waiter); + waiter->callback(fence, waiter); } wake_up(&fence->wq); } } int sync_fence_wait_async(struct sync_fence *fence, - void (*callback)(struct sync_fence *, void *data), - void *callback_data) + struct sync_fence_waiter *waiter) { - struct sync_fence_waiter *waiter; unsigned long flags; int err = 0; - waiter = kzalloc(sizeof(struct sync_fence_waiter), GFP_KERNEL); - if (waiter == NULL) - return -ENOMEM; - - waiter->callback = callback; - waiter->callback_data = callback_data; - spin_lock_irqsave(&fence->waiter_list_lock, flags); if (fence->status) { - kfree(waiter); err = fence->status; goto out; } @@ -458,44 +536,120 @@ out: return err; } +EXPORT_SYMBOL(sync_fence_wait_async); + +int sync_fence_cancel_async(struct sync_fence *fence, + struct sync_fence_waiter *waiter) +{ + struct list_head *pos; + struct list_head *n; + unsigned long flags; + int ret = -ENOENT; + + spin_lock_irqsave(&fence->waiter_list_lock, flags); + /* + * Make sure waiter is still in waiter_list because it is possible for + * the waiter to be removed from the list while the callback is still + * pending. + */ + list_for_each_safe(pos, n, &fence->waiter_list_head) { + struct sync_fence_waiter *list_waiter = + container_of(pos, struct sync_fence_waiter, + waiter_list); + if (list_waiter == waiter) { + list_del(pos); + ret = 0; + break; + } + } + spin_unlock_irqrestore(&fence->waiter_list_lock, flags); + return ret; +} +EXPORT_SYMBOL(sync_fence_cancel_async); + +static bool sync_fence_check(struct sync_fence *fence) +{ + /* + * Make sure that reads to fence->status are ordered with the + * wait queue event triggering + */ + smp_rmb(); + return fence->status != 0; +} int sync_fence_wait(struct sync_fence *fence, long timeout) { - int err; + int err = 0; + struct sync_pt *pt; - if (timeout) { + trace_sync_wait(fence, 1); + list_for_each_entry(pt, &fence->pt_list_head, pt_list) + trace_sync_pt(pt); + + if (timeout > 0) { timeout = msecs_to_jiffies(timeout); err = wait_event_interruptible_timeout(fence->wq, - fence->status != 0, + sync_fence_check(fence), timeout); - } else { - err = wait_event_interruptible(fence->wq, fence->status != 0); + } else if (timeout < 0) { + err = wait_event_interruptible(fence->wq, + sync_fence_check(fence)); } + trace_sync_wait(fence, 0); if (err < 0) return err; - if (fence->status < 0) + if (fence->status < 0) { + pr_info("fence error %d on [%p]\n", fence->status, fence); + sync_dump(); return fence->status; + } - if (fence->status == 0) + if (fence->status == 0) { + if (timeout > 0) { + pr_info("fence timeout on [%p] after %dms\n", fence, + jiffies_to_msecs(timeout)); + sync_dump(); + } return -ETIME; + } return 0; } +EXPORT_SYMBOL(sync_fence_wait); + +static void sync_fence_free(struct kref *kref) +{ + struct sync_fence *fence = container_of(kref, struct sync_fence, kref); + + sync_fence_free_pts(fence); + + kfree(fence); +} static int sync_fence_release(struct inode *inode, struct file *file) { struct sync_fence *fence = file->private_data; unsigned long flags; - sync_fence_free_pts(fence); - + /* + * We need to remove all ways to access this fence before droping + * our ref. + * + * start with its membership in the global fence list + */ spin_lock_irqsave(&sync_fence_list_lock, flags); list_del(&fence->sync_fence_list); spin_unlock_irqrestore(&sync_fence_list_lock, flags); - kfree(fence); + /* + * remove its pts from their parents so that sync_timeline_signal() + * can't reference the fence. + */ + sync_fence_detach_pts(fence); + + kref_put(&fence->kref, sync_fence_free); return 0; } @@ -506,6 +660,12 @@ static unsigned int sync_fence_poll(struct file *file, poll_table *wait) poll_wait(file, &fence->wq, wait); + /* + * Make sure that reads to fence->status are ordered with the + * wait queue event triggering + */ + smp_rmb(); + if (fence->status == 1) return POLLIN; else if (fence->status < 0) @@ -516,7 +676,7 @@ static unsigned int sync_fence_poll(struct file *file, poll_table *wait) static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg) { - __u32 value; + __s32 value; if (copy_from_user(&value, (void __user *)arg, sizeof(value))) return -EFAULT; @@ -531,8 +691,13 @@ static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg) struct sync_fence *fence2, *fence3; struct sync_merge_data data; - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) - return -EFAULT; + if (fd < 0) + return fd; + + if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { + err = -EFAULT; + goto err_put_fd; + } fence2 = sync_fence_fdget(data.fd2); if (fence2 == NULL) { @@ -568,7 +733,7 @@ err_put_fd: return err; } -int sync_fill_pt_info(struct sync_pt *pt, void *data, int size) +static int sync_fill_pt_info(struct sync_pt *pt, void *data, int size) { struct sync_pt_info *info = data; int ret; @@ -596,7 +761,6 @@ int sync_fill_pt_info(struct sync_pt *pt, void *data, int size) return info->len; } - static long sync_fence_ioctl_fence_info(struct sync_fence *fence, unsigned long arg) { @@ -690,7 +854,17 @@ static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence) seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec); } - if (pt->parent->ops->print_pt) { + if (pt->parent->ops->timeline_value_str && + pt->parent->ops->pt_value_str) { + char value[64]; + pt->parent->ops->pt_value_str(pt, value, sizeof(value)); + seq_printf(s, ": %s", value); + if (fence) { + pt->parent->ops->timeline_value_str(pt->parent, value, + sizeof(value)); + seq_printf(s, " / %s", value); + } + } else if (pt->parent->ops->print_pt) { seq_printf(s, ": "); pt->parent->ops->print_pt(s, pt); } @@ -705,7 +879,11 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) seq_printf(s, "%s %s", obj->name, obj->ops->driver_name); - if (obj->ops->print_obj) { + if (obj->ops->timeline_value_str) { + char value[64]; + obj->ops->timeline_value_str(obj, value, sizeof(value)); + seq_printf(s, ": %s", value); + } else if (obj->ops->print_obj) { seq_printf(s, ": "); obj->ops->print_obj(s, obj); } @@ -726,7 +904,8 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) struct list_head *pos; unsigned long flags; - seq_printf(s, "%s: %s\n", fence->name, sync_status_str(fence->status)); + seq_printf(s, "[%p] %s: %s\n", fence, fence->name, + sync_status_str(fence->status)); list_for_each(pos, &fence->pt_list_head) { struct sync_pt *pt = @@ -740,8 +919,7 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) container_of(pos, struct sync_fence_waiter, waiter_list); - seq_printf(s, "waiter %pF %p\n", waiter->callback, - waiter->callback_data); + seq_printf(s, "waiter %pF\n", waiter->callback); } spin_unlock_irqrestore(&fence->waiter_list_lock, flags); } @@ -795,7 +973,34 @@ static __init int sync_debugfs_init(void) debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops); return 0; } - late_initcall(sync_debugfs_init); +#define DUMP_CHUNK 256 +static char sync_dump_buf[64 * 1024]; +void sync_dump(void) +{ + struct seq_file s = { + .buf = sync_dump_buf, + .size = sizeof(sync_dump_buf) - 1, + }; + int i; + + sync_debugfs_show(&s, NULL); + + for (i = 0; i < s.count; i += DUMP_CHUNK) { + if ((s.count - i) > DUMP_CHUNK) { + char c = s.buf[i + DUMP_CHUNK]; + s.buf[i + DUMP_CHUNK] = 0; + pr_cont("%s", s.buf + i); + s.buf[i + DUMP_CHUNK] = c; + } else { + s.buf[s.count] = 0; + pr_cont("%s", s.buf + i); + } + } +} +#else +static void sync_dump(void) +{ +} #endif diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile index 00efbf6..8a0ed22 100644 --- a/drivers/gpu/Makefile +++ b/drivers/gpu/Makefile @@ -4,3 +4,9 @@ else obj-y += drm/ vga/ stub/ ion/ endif +ifeq ($(CONFIG_MALI400),y) +ifeq ($(CONFIG_MALI_VER_R3P2),y) +obj-y += mali400/r3p2/mali/ +obj-y += mali400/r3p2/ump/ +endif +endif diff --git a/drivers/gpu/mali400/Kconfig b/drivers/gpu/mali400/Kconfig new file mode 100644 index 0000000..8ec13b3 --- /dev/null +++ b/drivers/gpu/mali400/Kconfig @@ -0,0 +1,26 @@ +menuconfig MALI400 + tristate "Mali-300/400/450 support" + depends on ARM + default y + ---help--- + This enables support for the ARM Mali-300, Mali-400, and Mali-450 + GPUs. + + To compile this driver as a module, choose M here: the module will be + called mali. + +choice +depends on MALI400 +prompt "Select MALI VER" +default MALI_VER_R3P2 +config MALI_VER_R3P2 + bool "Mali400 Version R3P2" + help + Choose this option to select DDK version. + +if MALI_VER_R3P2 +source "drivers/gpu/mali400/r3p2/mali/Kconfig" +source "drivers/gpu/mali400/r3p2/ump/Kconfig" +endif + +endchoice diff --git a/drivers/gpu/mali400/r3p2/mali/Kbuild b/drivers/gpu/mali400/r3p2/mali/Kbuild new file mode 100644 index 0000000..81acbb8 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/Kbuild @@ -0,0 +1,220 @@ +# +# Copyright (C) 2010-2011 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained from Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +# This file is called by the Linux build system. + +# set up defaults if not defined by the user +TIMESTAMP ?= default +OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 +USING_GPU_UTILIZATION ?= 1 +PROFILING_SKIP_PP_JOBS ?= 0 +PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 +MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0 +MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 +MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 +MALI_UPPER_HALF_SCHEDULING ?= 1 +# MALI_SEC +# Include the mapping between TARGET_PLATFORM and KDIR + MALI_PLATFORM +ifeq ($(CONFIG_CPU_EXYNOS4210),y) + TARGET_PLATFORM=pegasus-m400 +endif +ifeq ($(CONFIG_CPU_EXYNOS4212),y) + TARGET_PLATFORM=pegasus-m400 +endif +ifeq ($(CONFIG_CPU_EXYNOS4412),y) + TARGET_PLATFORM=pegasus-m400 +endif +ifeq ($(CONFIG_SOC_EXYNOS3470),y) + TARGET_PLATFORM=exynos4270 +endif + +include $(srctree)/$(src)/MALI_CONFIGURATION +MALI_PLATFORM = $(MALI_PLATFORM-$(TARGET_PLATFORM)) +EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1 +MALI_PLATFORM_FILES = $(subst $(srctree)/$(src)/,,$(wildcard $(srctree)/$(src)/platform/$(MALI_PLATFORM)/*.c)) +# End of MALI_SEC + +# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: +# The ARM proprietary product will only include the license/proprietary directory +# The GPL product will only include the license/gpl directory +$(warning Current directory is $(srctree)/$(src) from $(shell pwd)) +ifeq ($(wildcard $(srctree)/$(src)/linux/license/gpl/*),) + ccflags-y += -I$(srctree)/$(src)/linux/license/proprietary + ifeq ($(CONFIG_MALI400_PROFILING),y) + $(error Profiling is incompatible with non-GPL license) + endif + ifeq ($(CONFIG_PM_RUNTIME),y) + $(error Runtime PM is incompatible with non-GPL license) + endif + ifeq ($(CONFIG_DMA_SHARED_BUFFER),y) + $(error DMA-BUF is incompatible with non-GPL license) + endif + $(error Linux Device integration is incompatible with non-GPL license) +else + ccflags-y += -I$(srctree)/$(src)/linux/license/gpl +endif + +mali-y += \ + linux/mali_osk_atomics.o \ + linux/mali_osk_irq.o \ + linux/mali_osk_wq.o \ + linux/mali_osk_locks.o \ + linux/mali_osk_wait_queue.o \ + linux/mali_osk_low_level_mem.o \ + linux/mali_osk_math.o \ + linux/mali_osk_memory.o \ + linux/mali_osk_misc.o \ + linux/mali_osk_mali.o \ + linux/mali_osk_notification.o \ + linux/mali_osk_time.o \ + linux/mali_osk_timers.o + +mali-y += \ + linux/mali_ukk_mem.o \ + linux/mali_ukk_gp.o \ + linux/mali_ukk_pp.o \ + linux/mali_ukk_core.o + +# Source files which always are included in a build +mali-y += \ + common/mali_kernel_core.o \ + linux/mali_kernel_linux.o \ + common/mali_kernel_descriptor_mapping.o \ + common/mali_session.o \ + linux/mali_device_pause_resume.o \ + common/mali_kernel_vsync.o \ + linux/mali_ukk_vsync.o \ + linux/mali_kernel_sysfs.o \ + common/mali_mmu.o \ + common/mali_mmu_page_directory.o \ + common/mali_memory.o \ + common/mali_kernel_memory_engine.o \ + common/mali_block_allocator.o \ + common/mali_kernel_mem_os.o \ + common/mali_mem_validation.o \ + common/mali_hw_core.o \ + common/mali_gp.o \ + common/mali_pp.o \ + common/mali_pp_job.o \ + common/mali_gp_job.o \ + common/mali_scheduler.o \ + common/mali_gp_scheduler.o \ + common/mali_pp_scheduler.o \ + common/mali_group.o \ + common/mali_dlbu.o \ + common/mali_broadcast.o \ + common/mali_pm.o \ + common/mali_pmu.o \ + common/mali_user_settings_db.o \ + common/mali_kernel_utilization.o \ + common/mali_l2_cache.o \ + common/mali_pm_domain.o \ + linux/mali_osk_pm.o \ + linux/mali_pmu_power_up_down.o \ + __malidrv_build_info.o + +ifneq ($(MALI_PLATFORM_FILES),) + mali-y += $(MALI_PLATFORM_FILES:.c=.o) +endif + +mali-$(CONFIG_MALI400_PROFILING) += linux/mali_ukk_profiling.o +mali-$(CONFIG_MALI400_PROFILING) += linux/mali_osk_profiling.o + +mali-$(CONFIG_MALI400_INTERNAL_PROFILING) += linux/mali_profiling_internal.o timestamp-$(TIMESTAMP)/mali_timestamp.o +ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(srctree)/$(src)/timestamp-$(TIMESTAMP) + +mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_dma_buf.o +mali-$(CONFIG_SYNC) += linux/mali_sync.o linux/mali_sync_user.o + +# Tell the Linux build system from which .o file to create the kernel module +obj-$(CONFIG_MALI400) := mali.o + +ccflags-y += $(EXTRA_DEFINES) + +# Set up our defines, which will be passed to gcc +ccflags-y += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS) +ccflags-y += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS) + +ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) +ccflags-y += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) +ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) +ccflags-y += -DMALI_STATE_TRACKING=1 +ccflags-y += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) +ccflags-y += -DUSING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) + +ifeq ($(MALI_UPPER_HALF_SCHEDULING),1) + ccflags-y += -DMALI_UPPER_HALF_SCHEDULING +endif + +ccflags-$(CONFIG_MALI400_UMP) += -I$(srctree)/$(src)/../../ump/include/ump +ccflags-$(CONFIG_MALI400_DEBUG) += -DDEBUG + +# Use our defines when compiling +ccflags-y += -I$(srctree)/$(src) -I$(srctree)/$(src)/include -I$(srctree)/$(src)/common -I$(srctree)/$(src)/linux -I$(srctree)/$(src)/platform +# MALI_SEC +ccflags-y += -I$(srctree)/$(src)/../ump/include -I$(srctree)/$(src)/include/linux/mali + +# Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available +MALI_RELEASE_NAME=$(shell cat $(srctree)/$(src)/.version 2> /dev/null) + +SVN_INFO = (cd $(srctree)/$(src); svn info 2>/dev/null) + +ifneq ($(shell $(SVN_INFO) 2>/dev/null),) +# SVN detected +SVN_REV := $(shell $(SVN_INFO) | grep '^Revision: '| sed -e 's/^Revision: //' 2>/dev/null) +DRIVER_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV) +CHANGE_DATE := $(shell $(SVN_INFO) | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-) +CHANGED_REVISION := $(shell $(SVN_INFO) | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-) +REPO_URL := $(shell $(SVN_INFO) | grep '^URL: ' | cut -d: -f2- | cut -b2-) + +else # SVN +GIT_REV := $(shell cd $(srctree)/$(src); git describe --always 2>/dev/null) +ifneq ($(GIT_REV),) +# Git detected +DRIVER_REV := $(MALI_RELEASE_NAME)-$(GIT_REV) +CHANGE_DATE := $(shell cd $(srctree)/$(src); git log -1 --format="%ci") +CHANGED_REVISION := $(GIT_REV) +REPO_URL := $(shell cd $(srctree)/$(src); git describe --all --always 2>/dev/null) + +else # Git +# No Git or SVN detected +DRIVER_REV := $(MALI_RELEASE_NAME) +CHANGE_DATE := $(MALI_RELEASE_NAME) +CHANGED_REVISION := $(MALI_RELEASE_NAME) +endif +endif + +ccflags-y += -DSVN_REV_STRING=\"$(DRIVER_REV)\" + +VERSION_STRINGS := +VERSION_STRINGS += API_VERSION=$(shell cd $(srctree)/$(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) +VERSION_STRINGS += REPO_URL=$(REPO_URL) +VERSION_STRINGS += REVISION=$(DRIVER_REV) +VERSION_STRINGS += CHANGED_REVISION=$(CHANGED_REVISION) +VERSION_STRINGS += CHANGE_DATE=$(CHANGE_DATE) +VERSION_STRINGS += BUILD_DATE=$(shell date) +ifdef CONFIG_MALI400_DEBUG +VERSION_STRINGS += BUILD=debug +else +VERSION_STRINGS += BUILD=release +endif +VERSION_STRINGS += TARGET_PLATFORM=$(TARGET_PLATFORM) +VERSION_STRINGS += MALI_PLATFORM=$(MALI_PLATFORM) +VERSION_STRINGS += KDIR=$(KDIR) +VERSION_STRINGS += OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) +VERSION_STRINGS += USING_UMP=$(CONFIG_MALI400_UMP) +VERSION_STRINGS += USING_PROFILING=$(CONFIG_MALI400_PROFILING) +VERSION_STRINGS += USING_INTERNAL_PROFILING=$(CONFIG_MALI400_INTERNAL_PROFILING) +VERSION_STRINGS += USING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) +VERSION_STRINGS += MALI_UPPER_HALF_SCHEDULING=$(MALI_UPPER_HALF_SCHEDULING) + +# Create file with Mali driver configuration +$(srctree)/$(src)/__malidrv_build_info.c: + @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(srctree)/$(src)/__malidrv_build_info.c diff --git a/drivers/gpu/mali400/r3p2/mali/Kconfig b/drivers/gpu/mali400/r3p2/mali/Kconfig new file mode 100644 index 0000000..14af54a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/Kconfig @@ -0,0 +1,67 @@ +config MALI400_DEBUG + bool "Enable debug in Mali driver" + depends on MALI400 + ---help--- + This enabled extra debug checks and messages in the Mali driver. + +config MALI400_PROFILING + bool "Enable Mali profiling" + depends on MALI400 + select TRACEPOINTS + default n + ---help--- + This enables gator profiling of Mali GPU events. + +config MALI400_INTERNAL_PROFILING + bool "Enable internal Mali profiling API" + depends on MALI400_PROFILING + default n + ---help--- + This enables the internal legacy Mali profiling API. + +if CPU_EXYNOS4210 || CPU_EXYNOS4212 || CPU_EXYNOS4412 +config MALI_DVFS + bool "Enable mali DVFS" + depends on MALI400 && PM + default y + ---help--- + This enables Mali driver DVFS. +endif + +if SOC_EXYNOS3470 +config MALI_DVFS + bool "Enable mali DVFS" + depends on MALI400 && PM_DEVFREQ + default y + ---help--- + This enables Mali driver DVFS. +endif + +if CPU_EXYNOS4210 || CPU_EXYNOS4212 || CPU_EXYNOS4412 +config MALI400_UMP + bool "Enable UMP support" + depends on MALI400 + default y + ---help--- + This enables support for the UMP memory sharing API in the Mali driver. +endif + +config MALI_DMA_BUF_MAP_ON_ATTACH + bool "Map dma-buf attachments on attach" + depends on MALI400 && DMA_SHARED_BUFFER + default y + ---help--- + This makes the Mali driver map dma-buf attachments after doing + attach. If this is not set the dma-buf attachments will be mapped for + every time the GPU need to access the buffer. + + Mapping for each access can cause lower performance. + +config MALI_SHARED_INTERRUPTS + bool "Support for shared interrupts" + depends on MALI400 + default n + ---help--- + Adds functionality required to properly support shared interrupts. Without this support, + the device driver will fail during insmod if it detects shared interrupts. Works even if + the GPU is not using shared interrupts, but can cause lower performance. diff --git a/drivers/gpu/mali400/r3p2/mali/MALI_CONFIGURATION b/drivers/gpu/mali400/r3p2/mali/MALI_CONFIGURATION new file mode 100644 index 0000000..4b099b7 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/MALI_CONFIGURATION @@ -0,0 +1,24 @@ +# Location of default kernels +KDIR-odroida:=/projects/pr297/linux/odroid-a/current/linux +KDIR-odroidpc:=/projects/pr297/linux/odroid-pc/current/linux +KDIR-odroidq:=/projects/pr297/linux/odroid-q/current/linux +KDIR-orion:=/projects/pr297/linux/orion/current/linux +KDIR-pegasus:=/projects/pr297/linux/pegasus-smdk/current/linux +KDIR-tcc8900:=/projects/pr297/linux/tcc8900/current/linux +KDIR-pb11mp:=/projects/pr297/linux/pb11mp/current/linux +KDIR-vea9:=/projects/pr297/linux/vea9/current/linux +KDIR-snowball:=/no/default/kernel/yet + +# Name of platform directory with platform specific code (should be built into kernel on a real system) +MALI_PLATFORM-odroida=exynos4 +MALI_PLATFORM-odroidpc=exynos4 +MALI_PLATFORM-odroidq=exynos4 +MALI_PLATFORM-orion=exynos4 +MALI_PLATFORM-pegasus=exynos4 +# MALI_SEC +MALI_PLATFORM-pegasus-m400=pegasus-m400 +MALI_PLATFORM-exynos4270=exynos4270 +MALI_PLATFORM-tcc8900=tcc8900 +MALI_PLATFORM-pb11mp=arm +MALI_PLATFORM-vea9=arm +MALI_PLATFORM-snowball=ux500 diff --git a/drivers/gpu/mali400/r3p2/mali/Makefile b/drivers/gpu/mali400/r3p2/mali/Makefile new file mode 100644 index 0000000..b487011 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/Makefile @@ -0,0 +1,138 @@ +# +# Copyright (C) 2010-2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained from Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +USE_UMPV2=0 +USING_PROFILING ?= 1 +USING_INTERNAL_PROFILING ?= 0 +MALI_DMA_BUF_MAP_ON_ATTACH ?= 1 + +# The Makefile sets up "arch" based on the CONFIG, creates the version info +# string and the __malidrv_build_info.c file, and then call the Linux build +# system to actually build the driver. After that point the Kbuild file takes +# over. + +# set up defaults if not defined by the user +ARCH ?= arm + +OSKOS=linux +FILES_PREFIX= + +check_cc2 = \ + $(shell if $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \ + then \ + echo "$(2)"; \ + else \ + echo "$(3)"; \ + fi ;) + +# This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak +-include ../../../arm_internal.mak + +# Give warning of old config parameters are used +ifneq ($(CONFIG),) +$(warning "You have specified the CONFIG variable which is no longer in used. Use TARGET_PLATFORM instead.") +endif + +ifneq ($(CPU),) +$(warning "You have specified the CPU variable which is no longer in used. Use TARGET_PLATFORM instead.") +endif + +# Include the mapping between TARGET_PLATFORM and KDIR + MALI_PLATFORM +-include MALI_CONFIGURATION +export KDIR ?= $(KDIR-$(TARGET_PLATFORM)) +export MALI_PLATFORM ?= $(MALI_PLATFORM-$(TARGET_PLATFORM)) + +ifneq ($(TARGET_PLATFORM),) +ifeq ($(MALI_PLATFORM),) +$(error "Invalid TARGET_PLATFORM: $(TARGET_PLATFORM)") +endif +endif + +# validate lookup result +ifeq ($(KDIR),) +$(error No KDIR found for platform $(TARGET_PLATFORM)) +endif + + +ifeq ($(USING_UMP),1) +export CONFIG_MALI400_UMP=y +export EXTRA_DEFINES += -DCONFIG_MALI400_UMP=1 +ifeq ($(USE_UMPV2),1) +UMP_SYMVERS_FILE ?= ../umpv2/Module.symvers +else +UMP_SYMVERS_FILE ?= ../ump/Module.symvers +endif +KBUILD_EXTRA_SYMBOLS = $(realpath $(UMP_SYMVERS_FILE)) +$(warning $(KBUILD_EXTRA_SYMBOLS)) +endif + +# Define host system directory +KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build + +include $(KDIR)/.config + +ifeq ($(ARCH), arm) +# when compiling for ARM we're cross compiling +export CROSS_COMPILE ?= $(call check_cc2, arm-linux-gnueabi-gcc, arm-linux-gnueabi-, arm-none-linux-gnueabi-) +endif + +# report detected/selected settings +ifdef ARM_INTERNAL_BUILD +$(warning TARGET_PLATFORM $(TARGET_PLATFORM)) +$(warning KDIR $(KDIR)) +$(warning MALI_PLATFORM $(MALI_PLATFORM)) +endif + +# Set up build config +export CONFIG_MALI400=m + +ifneq ($(MALI_PLATFORM),) +export EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1 +export MALI_PLATFORM_FILES = $(wildcard platform/$(MALI_PLATFORM)/*.c) +endif + +ifeq ($(USING_PROFILING),1) +ifeq ($(CONFIG_TRACEPOINTS),) +$(warning CONFIG_TRACEPOINTS reqired for profiling) +else +export CONFIG_MALI400_PROFILING=y +export EXTRA_DEFINES += -DCONFIG_MALI400_PROFILING=1 +ifeq ($(USING_INTERNAL_PROFILING),1) +export CONFIG_MALI400_INTERNAL_PROFILING=y +export EXTRA_DEFINES += -DCONFIG_MALI400_INTERNAL_PROFILING=1 +endif +endif +endif + +ifeq ($(MALI_DMA_BUF_MAP_ON_ATTACH),1) +export CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH=y +export EXTRA_DEFINES += -DCONFIG_MALI_DMA_BUF_MAP_ON_ATTACH +endif + +ifeq ($(MALI_SHARED_INTERRUPTS),1) +export CONFIG_MALI_SHARED_INTERRUPTS=y +export EXTRA_DEFINES += -DCONFIG_MALI_SHARED_INTERRUPTS +endif + +ifneq ($(BUILD),release) +export CONFIG_MALI400_DEBUG=y +endif + +all: $(UMP_SYMVERS_FILE) + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) modules + @rm $(FILES_PREFIX)__malidrv_build_info.c $(FILES_PREFIX)__malidrv_build_info.o + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + +kernelrelease: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) kernelrelease + +export CONFIG KBUILD_EXTRA_SYMBOLS diff --git a/drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c b/drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c new file mode 100644 index 0000000..af5e808 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c @@ -0,0 +1 @@ +const char *__malidrv_build_info(void) { return "malidrv: API_VERSION=23 REPO_URL=heads/master REVISION=r3p2-01rel3-137c649 CHANGED_REVISION=137c649 CHANGE_DATE=2013-08-22 17:45:49 +0900 BUILD_DATE=Fri Aug 23 20:48:48 KST 2013 BUILD=release TARGET_PLATFORM=pegasus-m400 MALI_PLATFORM=pegasus-m400 KDIR= OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=16 USING_UMP=y USING_PROFILING= USING_INTERNAL_PROFILING= USING_GPU_UTILIZATION=1 MALI_UPPER_HALF_SCHEDULING=1";} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.c b/drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.c new file mode 100644 index 0000000..3651ce5 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.c @@ -0,0 +1,392 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "mali_kernel_common.h" +#include "mali_kernel_memory_engine.h" +#include "mali_block_allocator.h" +#include "mali_osk.h" + +#define MALI_BLOCK_SIZE (256UL * 1024UL) /* 256 kB, remember to keep the ()s */ + +typedef struct block_info +{ + struct block_info * next; +} block_info; + +/* The structure used as the handle produced by block_allocator_allocate, + * and removed by block_allocator_release */ +typedef struct block_allocator_allocation +{ + /* The list will be released in reverse order */ + block_info *last_allocated; + mali_allocation_engine * engine; + mali_memory_allocation * descriptor; + u32 start_offset; + u32 mapping_length; +} block_allocator_allocation; + + +typedef struct block_allocator +{ + _mali_osk_lock_t *mutex; + block_info * all_blocks; + block_info * first_free; + u32 base; + u32 cpu_usage_adjust; + u32 num_blocks; +} block_allocator; + +MALI_STATIC_INLINE u32 get_phys(block_allocator * info, block_info * block); +static mali_physical_memory_allocation_result block_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); +static void block_allocator_release(void * ctx, void * handle); +static mali_physical_memory_allocation_result block_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block); +static void block_allocator_release_page_table_block( mali_page_table_block *page_table_block ); +static void block_allocator_destroy(mali_physical_memory_allocator * allocator); +static u32 block_allocator_stat(mali_physical_memory_allocator * allocator); + +mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size, const char *name) +{ + mali_physical_memory_allocator * allocator; + block_allocator * info; + u32 usable_size; + u32 num_blocks; + + usable_size = size & ~(MALI_BLOCK_SIZE - 1); + MALI_DEBUG_PRINT(3, ("Mali block allocator create for region starting at 0x%08X length 0x%08X\n", base_address, size)); + MALI_DEBUG_PRINT(4, ("%d usable bytes\n", usable_size)); + num_blocks = usable_size / MALI_BLOCK_SIZE; + MALI_DEBUG_PRINT(4, ("which becomes %d blocks\n", num_blocks)); + + if (usable_size == 0) + { + MALI_DEBUG_PRINT(1, ("Memory block of size %d is unusable\n", size)); + return NULL; + } + + allocator = _mali_osk_malloc(sizeof(mali_physical_memory_allocator)); + if (NULL != allocator) + { + info = _mali_osk_malloc(sizeof(block_allocator)); + if (NULL != info) + { + info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_MEM_INFO); + if (NULL != info->mutex) + { + info->all_blocks = _mali_osk_malloc(sizeof(block_info) * num_blocks); + if (NULL != info->all_blocks) + { + u32 i; + info->first_free = NULL; + info->num_blocks = num_blocks; + + info->base = base_address; + info->cpu_usage_adjust = cpu_usage_adjust; + + for ( i = 0; i < num_blocks; i++) + { + info->all_blocks[i].next = info->first_free; + info->first_free = &info->all_blocks[i]; + } + + allocator->allocate = block_allocator_allocate; + allocator->allocate_page_table_block = block_allocator_allocate_page_table_block; + allocator->destroy = block_allocator_destroy; + allocator->stat = block_allocator_stat; + allocator->ctx = info; + allocator->name = name; + + return allocator; + } + _mali_osk_lock_term(info->mutex); + } + _mali_osk_free(info); + } + _mali_osk_free(allocator); + } + + return NULL; +} + +static void block_allocator_destroy(mali_physical_memory_allocator * allocator) +{ + block_allocator * info; + MALI_DEBUG_ASSERT_POINTER(allocator); + MALI_DEBUG_ASSERT_POINTER(allocator->ctx); + info = (block_allocator*)allocator->ctx; + + _mali_osk_free(info->all_blocks); + _mali_osk_lock_term(info->mutex); + _mali_osk_free(info); + _mali_osk_free(allocator); +} + +MALI_STATIC_INLINE u32 get_phys(block_allocator * info, block_info * block) +{ + return info->base + ((block - info->all_blocks) * MALI_BLOCK_SIZE); +} + +static mali_physical_memory_allocation_result block_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + block_allocator * info; + u32 left; + block_info * last_allocated = NULL; + mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_NONE; + block_allocator_allocation *ret_allocation; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(offset); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + info = (block_allocator*)ctx; + left = descriptor->size - *offset; + MALI_DEBUG_ASSERT(0 != left); + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; + + ret_allocation = _mali_osk_malloc( sizeof(block_allocator_allocation) ); + + if ( NULL == ret_allocation ) + { + /* Failure; try another allocator by returning MALI_MEM_ALLOC_NONE */ + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + return result; + } + + ret_allocation->start_offset = *offset; + ret_allocation->mapping_length = 0; + + while ((left > 0) && (info->first_free)) + { + block_info * block; + u32 phys_addr; + u32 padding; + u32 current_mapping_size; + + block = info->first_free; + info->first_free = info->first_free->next; + block->next = last_allocated; + last_allocated = block; + + phys_addr = get_phys(info, block); + + padding = *offset & (MALI_BLOCK_SIZE-1); + + if (MALI_BLOCK_SIZE - padding < left) + { + current_mapping_size = MALI_BLOCK_SIZE - padding; + } + else + { + current_mapping_size = left; + } + + if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, phys_addr + padding, info->cpu_usage_adjust, current_mapping_size)) + { + MALI_DEBUG_PRINT(1, ("Mapping of physical memory failed\n")); + result = MALI_MEM_ALLOC_INTERNAL_FAILURE; + mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->start_offset, ret_allocation->mapping_length, (_mali_osk_mem_mapregion_flags_t)0); + + /* release all memory back to the pool */ + while (last_allocated) + { + /* This relinks every block we've just allocated back into the free-list */ + block = last_allocated->next; + last_allocated->next = info->first_free; + info->first_free = last_allocated; + last_allocated = block; + } + + break; + } + + *offset += current_mapping_size; + left -= current_mapping_size; + ret_allocation->mapping_length += current_mapping_size; + } + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + if (last_allocated) + { + if (left) result = MALI_MEM_ALLOC_PARTIAL; + else result = MALI_MEM_ALLOC_FINISHED; + + /* Record all the information about this allocation */ + ret_allocation->last_allocated = last_allocated; + ret_allocation->engine = engine; + ret_allocation->descriptor = descriptor; + + alloc_info->ctx = info; + alloc_info->handle = ret_allocation; + alloc_info->release = block_allocator_release; + } + else + { + /* Free the allocation information - nothing to be passed back */ + _mali_osk_free( ret_allocation ); + } + + return result; +} + +static void block_allocator_release(void * ctx, void * handle) +{ + block_allocator * info; + block_info * block, * next; + block_allocator_allocation *allocation; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(handle); + + info = (block_allocator*)ctx; + allocation = (block_allocator_allocation*)handle; + block = allocation->last_allocated; + + MALI_DEBUG_ASSERT_POINTER(block); + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) + { + MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); + return; + } + + /* unmap */ + mali_allocation_engine_unmap_physical(allocation->engine, allocation->descriptor, allocation->start_offset, allocation->mapping_length, (_mali_osk_mem_mapregion_flags_t)0); + + while (block) + { + MALI_DEBUG_ASSERT(!((block < info->all_blocks) || (block > (info->all_blocks + info->num_blocks)))); + + next = block->next; + + /* relink into free-list */ + block->next = info->first_free; + info->first_free = block; + + /* advance the loop */ + block = next; + } + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_free( allocation ); +} + + +static mali_physical_memory_allocation_result block_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) +{ + block_allocator * info; + mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_INTERNAL_FAILURE; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(block); + info = (block_allocator*)ctx; + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; + + if (NULL != info->first_free) + { + void * virt; + u32 phys; + u32 size; + block_info * alloc; + alloc = info->first_free; + + phys = get_phys(info, alloc); /* Does not modify info or alloc */ + size = MALI_BLOCK_SIZE; /* Must be multiple of MALI_MMU_PAGE_SIZE */ + virt = _mali_osk_mem_mapioregion( phys, size, "Mali block allocator page tables" ); + + /* Failure of _mali_osk_mem_mapioregion will result in MALI_MEM_ALLOC_INTERNAL_FAILURE, + * because it's unlikely another allocator will be able to map in. */ + + if ( NULL != virt ) + { + block->ctx = info; /* same as incoming ctx */ + block->handle = alloc; + block->phys_base = phys; + block->size = size; + block->release = block_allocator_release_page_table_block; + block->mapping = virt; + + info->first_free = alloc->next; + + alloc->next = NULL; /* Could potentially link many blocks together instead */ + + _mali_osk_memset(block->mapping, 0, size); + + result = MALI_MEM_ALLOC_FINISHED; + } + } + else result = MALI_MEM_ALLOC_NONE; + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + return result; +} + + +static void block_allocator_release_page_table_block( mali_page_table_block *page_table_block ) +{ + block_allocator * info; + block_info * block, * next; + + MALI_DEBUG_ASSERT_POINTER( page_table_block ); + + info = (block_allocator*)page_table_block->ctx; + block = (block_info*)page_table_block->handle; + + MALI_DEBUG_ASSERT_POINTER(info); + MALI_DEBUG_ASSERT_POINTER(block); + + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) + { + MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); + return; + } + + /* Unmap all the physical memory at once */ + _mali_osk_mem_unmapioregion( page_table_block->phys_base, page_table_block->size, page_table_block->mapping ); + + /** @note This loop handles the case where more than one block_info was linked. + * Probably unnecessary for page table block releasing. */ + while (block) + { + next = block->next; + + MALI_DEBUG_ASSERT(!((block < info->all_blocks) || (block > (info->all_blocks + info->num_blocks)))); + + block->next = info->first_free; + info->first_free = block; + + block = next; + } + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); +} + +static u32 block_allocator_stat(mali_physical_memory_allocator * allocator) +{ + block_allocator * info; + block_info *block; + u32 free_blocks = 0; + + MALI_DEBUG_ASSERT_POINTER(allocator); + + info = (block_allocator*)allocator->ctx; + block = info->first_free; + + while(block) + { + free_blocks++; + block = block->next; + } + return (info->num_blocks - free_blocks) * MALI_BLOCK_SIZE; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.h b/drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.h new file mode 100644 index 0000000..d3f0f9b --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_BLOCK_ALLOCATOR_H__ +#define __MALI_BLOCK_ALLOCATOR_H__ + +#include "mali_kernel_memory_engine.h" + +mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size, const char *name); + +#endif /* __MALI_BLOCK_ALLOCATOR_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.c b/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.c new file mode 100644 index 0000000..8b05496 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_broadcast.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" + +static const int bcast_unit_reg_size = 0x1000; +static const int bcast_unit_addr_broadcast_mask = 0x0; +static const int bcast_unit_addr_irq_override_mask = 0x4; + +struct mali_bcast_unit +{ + struct mali_hw_core hw_core; + u32 current_mask; +}; + +struct mali_bcast_unit *mali_bcast_unit_create(const _mali_osk_resource_t *resource) +{ + struct mali_bcast_unit *bcast_unit = NULL; + + MALI_DEBUG_ASSERT_POINTER(resource); + MALI_DEBUG_PRINT(2, ("Mali Broadcast unit: Creating Mali Broadcast unit: %s\n", resource->description)); + + bcast_unit = _mali_osk_malloc(sizeof(struct mali_bcast_unit)); + if (NULL == bcast_unit) + { + MALI_PRINT_ERROR(("Mali Broadcast unit: Failed to allocate memory for Broadcast unit\n")); + return NULL; + } + + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&bcast_unit->hw_core, resource, bcast_unit_reg_size)) + { + bcast_unit->current_mask = 0; + mali_bcast_reset(bcast_unit); + + return bcast_unit; + } + else + { + MALI_PRINT_ERROR(("Mali Broadcast unit: Failed map broadcast unit\n")); + } + + _mali_osk_free(bcast_unit); + + return NULL; +} + +void mali_bcast_unit_delete(struct mali_bcast_unit *bcast_unit) +{ + MALI_DEBUG_ASSERT_POINTER(bcast_unit); + + mali_hw_core_delete(&bcast_unit->hw_core); + _mali_osk_free(bcast_unit); +} + +void mali_bcast_add_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group) +{ + u32 bcast_id; + u32 broadcast_mask; + + MALI_DEBUG_ASSERT_POINTER(bcast_unit); + MALI_DEBUG_ASSERT_POINTER(group); + + bcast_id = mali_pp_core_get_bcast_id(mali_group_get_pp_core(group)); + + broadcast_mask = bcast_unit->current_mask; + + broadcast_mask |= (bcast_id); /* add PP core to broadcast */ + broadcast_mask |= (bcast_id << 16); /* add MMU to broadcast */ + + /* store mask so we can restore on reset */ + bcast_unit->current_mask = broadcast_mask; +} + +void mali_bcast_remove_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group) +{ + u32 bcast_id; + u32 broadcast_mask; + + MALI_DEBUG_ASSERT_POINTER(bcast_unit); + MALI_DEBUG_ASSERT_POINTER(group); + + bcast_id = mali_pp_core_get_bcast_id(mali_group_get_pp_core(group)); + + broadcast_mask = bcast_unit->current_mask; + + broadcast_mask &= ~((bcast_id << 16) | bcast_id); + + /* store mask so we can restore on reset */ + bcast_unit->current_mask = broadcast_mask; +} + +void mali_bcast_reset(struct mali_bcast_unit *bcast_unit) +{ + MALI_DEBUG_ASSERT_POINTER(bcast_unit); + + /* set broadcast mask */ + mali_hw_core_register_write(&bcast_unit->hw_core, + bcast_unit_addr_broadcast_mask, + bcast_unit->current_mask); + + /* set IRQ override mask */ + mali_hw_core_register_write(&bcast_unit->hw_core, + bcast_unit_addr_irq_override_mask, + bcast_unit->current_mask & 0xFF); +} + +void mali_bcast_disable(struct mali_bcast_unit *bcast_unit) +{ + MALI_DEBUG_ASSERT_POINTER(bcast_unit); + + /* set broadcast mask */ + mali_hw_core_register_write(&bcast_unit->hw_core, + bcast_unit_addr_broadcast_mask, + 0x0); + + /* set IRQ override mask */ + mali_hw_core_register_write(&bcast_unit->hw_core, + bcast_unit_addr_irq_override_mask, + 0x0); +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.h b/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.h new file mode 100644 index 0000000..df5f2f9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * Interface for the broadcast unit on Mali-450. + * + * - Represents up to 8 × (MMU + PP) pairs. + * - Supports dynamically changing which (MMU + PP) pairs receive the broadcast by + * setting a mask. + */ + +#include "mali_hw_core.h" +#include "mali_group.h" + +struct mali_bcast_unit; + +struct mali_bcast_unit *mali_bcast_unit_create(const _mali_osk_resource_t *resource); +void mali_bcast_unit_delete(struct mali_bcast_unit *bcast_unit); + +/* Add a group to the list of (MMU + PP) pairs broadcasts go out to. */ +void mali_bcast_add_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group); + +/* Remove a group to the list of (MMU + PP) pairs broadcasts go out to. */ +void mali_bcast_remove_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group); + +/* Re-set cached mask. This needs to be called after having been suspended. */ +void mali_bcast_reset(struct mali_bcast_unit *bcast_unit); + +/** + * Disable broadcast unit + * + * mali_bcast_enable must be called to re-enable the unit. Cores may not be + * added or removed when the unit is disabled. + */ +void mali_bcast_disable(struct mali_bcast_unit *bcast_unit); + +/** + * Re-enable broadcast unit + * + * This resets the masks to include the cores present when mali_bcast_disable was called. + */ +MALI_STATIC_INLINE void mali_bcast_enable(struct mali_bcast_unit *bcast_unit) +{ + mali_bcast_reset(bcast_unit); +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.c b/drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.c new file mode 100644 index 0000000..0181663 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.c @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_dlbu.h" +#include "mali_memory.h" +#include "mali_pp.h" +#include "mali_group.h" +#include "mali_osk.h" +#include "mali_hw_core.h" + +/** + * Size of DLBU registers in bytes + */ +#define MALI_DLBU_SIZE 0x400 + +u32 mali_dlbu_phys_addr = 0; +static mali_io_address mali_dlbu_cpu_addr = 0; + +/** + * DLBU register numbers + * Used in the register read/write routines. + * See the hardware documentation for more information about each register + */ +typedef enum mali_dlbu_register { + MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR = 0x0000, /**< Master tile list physical base address; + 31:12 Physical address to the page used for the DLBU + 0 DLBU enable - set this bit to 1 enables the AXI bus + between PPs and L2s, setting to 0 disables the router and + no further transactions are sent to DLBU */ + MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR = 0x0004, /**< Master tile list virtual base address; + 31:12 Virtual address to the page used for the DLBU */ + MALI_DLBU_REGISTER_TLLIST_VBASEADDR = 0x0008, /**< Tile list virtual base address; + 31:12 Virtual address to the tile list. This address is used when + calculating the call address sent to PP.*/ + MALI_DLBU_REGISTER_FB_DIM = 0x000C, /**< Framebuffer dimension; + 23:16 Number of tiles in Y direction-1 + 7:0 Number of tiles in X direction-1 */ + MALI_DLBU_REGISTER_TLLIST_CONF = 0x0010, /**< Tile list configuration; + 29:28 select the size of each allocated block: 0=128 bytes, 1=256, 2=512, 3=1024 + 21:16 2^n number of tiles to be binned to one tile list in Y direction + 5:0 2^n number of tiles to be binned to one tile list in X direction */ + MALI_DLBU_REGISTER_START_TILE_POS = 0x0014, /**< Start tile positions; + 31:24 start position in Y direction for group 1 + 23:16 start position in X direction for group 1 + 15:8 start position in Y direction for group 0 + 7:0 start position in X direction for group 0 */ + MALI_DLBU_REGISTER_PP_ENABLE_MASK = 0x0018, /**< PP enable mask; + 7 enable PP7 for load balancing + 6 enable PP6 for load balancing + 5 enable PP5 for load balancing + 4 enable PP4 for load balancing + 3 enable PP3 for load balancing + 2 enable PP2 for load balancing + 1 enable PP1 for load balancing + 0 enable PP0 for load balancing */ +} mali_dlbu_register; + +typedef enum +{ + PP0ENABLE = 0, + PP1ENABLE, + PP2ENABLE, + PP3ENABLE, + PP4ENABLE, + PP5ENABLE, + PP6ENABLE, + PP7ENABLE +} mali_dlbu_pp_enable; + +struct mali_dlbu_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + u32 pp_cores_mask; /**< This is a mask for the PP cores whose operation will be controlled by LBU + see MALI_DLBU_REGISTER_PP_ENABLE_MASK register */ +}; + +_mali_osk_errcode_t mali_dlbu_initialize(void) +{ + + MALI_DEBUG_PRINT(2, ("Mali DLBU: Initializing\n")); + + if (_MALI_OSK_ERR_OK == mali_mmu_get_table_page(&mali_dlbu_phys_addr, &mali_dlbu_cpu_addr)) + { + MALI_SUCCESS; + } + + return _MALI_OSK_ERR_FAULT; +} + +void mali_dlbu_terminate(void) +{ + MALI_DEBUG_PRINT(3, ("Mali DLBU: terminating\n")); + + mali_mmu_release_table_page(mali_dlbu_phys_addr); +} + +struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource) +{ + struct mali_dlbu_core *core = NULL; + + MALI_DEBUG_PRINT(2, ("Mali DLBU: Creating Mali dynamic load balancing unit: %s\n", resource->description)); + + core = _mali_osk_malloc(sizeof(struct mali_dlbu_core)); + if (NULL != core) + { + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI_DLBU_SIZE)) + { + core->pp_cores_mask = 0; + if (_MALI_OSK_ERR_OK == mali_dlbu_reset(core)) + { + return core; + } + MALI_PRINT_ERROR(("Failed to reset DLBU %s\n", core->hw_core.description)); + mali_hw_core_delete(&core->hw_core); + } + + _mali_osk_free(core); + } + else + { + MALI_PRINT_ERROR(("Mali DLBU: Failed to allocate memory for DLBU core\n")); + } + + return NULL; +} + +void mali_dlbu_delete(struct mali_dlbu_core *dlbu) +{ + MALI_DEBUG_ASSERT_POINTER(dlbu); + + mali_dlbu_reset(dlbu); + mali_hw_core_delete(&dlbu->hw_core); + _mali_osk_free(dlbu); +} + +_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu) +{ + u32 dlbu_registers[7]; + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + MALI_DEBUG_ASSERT_POINTER(dlbu); + + MALI_DEBUG_PRINT(4, ("Mali DLBU: mali_dlbu_reset: %s\n", dlbu->hw_core.description)); + + dlbu_registers[0] = mali_dlbu_phys_addr | 1; /* bit 0 enables the whole core */ + dlbu_registers[1] = MALI_DLBU_VIRT_ADDR; + dlbu_registers[2] = 0; + dlbu_registers[3] = 0; + dlbu_registers[4] = 0; + dlbu_registers[5] = 0; + dlbu_registers[6] = dlbu->pp_cores_mask; + + /* write reset values to core registers */ + mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, dlbu_registers, 7); + + err = _MALI_OSK_ERR_OK; + + return err; +} + +void mali_dlbu_update_mask(struct mali_dlbu_core *dlbu) +{ + MALI_DEBUG_ASSERT_POINTER(dlbu); + + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask); +} + +void mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group) +{ + struct mali_pp_core *pp_core; + u32 bcast_id; + + MALI_DEBUG_ASSERT_POINTER( dlbu ); + MALI_DEBUG_ASSERT_POINTER( group ); + + pp_core = mali_group_get_pp_core(group); + bcast_id = mali_pp_core_get_bcast_id(pp_core); + + dlbu->pp_cores_mask |= bcast_id; + MALI_DEBUG_PRINT(3, ("Mali DLBU: Adding core[%d] New mask= 0x%02x\n", bcast_id , dlbu->pp_cores_mask)); +} + +/* Remove a group from the DLBU */ +void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group) +{ + struct mali_pp_core *pp_core; + u32 bcast_id; + + MALI_DEBUG_ASSERT_POINTER( dlbu ); + MALI_DEBUG_ASSERT_POINTER( group ); + + pp_core = mali_group_get_pp_core(group); + bcast_id = mali_pp_core_get_bcast_id(pp_core); + + dlbu->pp_cores_mask &= ~bcast_id; + MALI_DEBUG_PRINT(3, ("Mali DLBU: Removing core[%d] New mask= 0x%02x\n", bcast_id, dlbu->pp_cores_mask)); +} + +/* Configure the DLBU for \a job. This needs to be done before the job is started on the groups in the DLBU. */ +void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job) +{ + u32 *registers; + MALI_DEBUG_ASSERT(job); + registers = mali_pp_job_get_dlbu_registers(job); + MALI_DEBUG_PRINT(4, ("Mali DLBU: Starting job\n")); + + /* Writing 4 registers: + * DLBU registers except the first two (written once at DLBU initialisation / reset) and the PP_ENABLE_MASK register */ + mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, registers, 4); + +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.h b/drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.h new file mode 100644 index 0000000..b1a59d6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_DLBU_H__ +#define __MALI_DLBU_H__ + +#define MALI_DLBU_VIRT_ADDR 0xFFF00000 /* master tile virtual address fixed at this value and mapped into every session */ + +#include "mali_osk.h" + +struct mali_pp_job; +struct mali_group; + +extern u32 mali_dlbu_phys_addr; + +struct mali_dlbu_core; + +_mali_osk_errcode_t mali_dlbu_initialize(void); +void mali_dlbu_terminate(void); + +struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource); +void mali_dlbu_delete(struct mali_dlbu_core *dlbu); + +_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu); + +void mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group); +void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group); + +/** @brief Called to update HW after DLBU state changed + * + * This function must be called after \a mali_dlbu_add_group or \a + * mali_dlbu_remove_group to write the updated mask to hardware, unless the + * same is accomplished by calling \a mali_dlbu_reset. + */ +void mali_dlbu_update_mask(struct mali_dlbu_core *dlbu); + +void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job); + +#endif /* __MALI_DLBU_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_gp.c b/drivers/gpu/mali400/r3p2/mali/common/mali_gp.c new file mode 100644 index 0000000..c2b01f9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp.c @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_gp.h" +#include "mali_hw_core.h" +#include "mali_group.h" +#include "mali_osk.h" +#include "regs/mali_gp_regs.h" +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#if defined(CONFIG_MALI400_PROFILING) +#include "mali_osk_profiling.h" +#endif + +static struct mali_gp_core *mali_global_gp_core = NULL; + +/* Interrupt handlers */ +static void mali_gp_irq_probe_trigger(void *data); +static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data); + +struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group) +{ + struct mali_gp_core* core = NULL; + + MALI_DEBUG_ASSERT(NULL == mali_global_gp_core); + MALI_DEBUG_PRINT(2, ("Mali GP: Creating Mali GP core: %s\n", resource->description)); + + core = _mali_osk_malloc(sizeof(struct mali_gp_core)); + if (NULL != core) + { + core->counter_src0_used = MALI_HW_CORE_NO_COUNTER; + core->counter_src1_used = MALI_HW_CORE_NO_COUNTER; + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALIGP2_REGISTER_ADDRESS_SPACE_SIZE)) + { + _mali_osk_errcode_t ret; + + ret = mali_gp_reset(core); + + if (_MALI_OSK_ERR_OK == ret) + { + ret = mali_group_add_gp_core(group, core); + if (_MALI_OSK_ERR_OK == ret) + { + /* Setup IRQ handlers (which will do IRQ probing if needed) */ + core->irq = _mali_osk_irq_init(resource->irq, + mali_group_upper_half_gp, + group, + mali_gp_irq_probe_trigger, + mali_gp_irq_probe_ack, + core, + "mali_gp_irq_handlers"); + if (NULL != core->irq) + { + MALI_DEBUG_PRINT(4, ("Mali GP: set global gp core from 0x%08X to 0x%08X\n", mali_global_gp_core, core)); + mali_global_gp_core = core; + + return core; + } + else + { + MALI_PRINT_ERROR(("Mali GP: Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description)); + } + mali_group_remove_gp_core(group); + } + else + { + MALI_PRINT_ERROR(("Mali GP: Failed to add core %s to group\n", core->hw_core.description)); + } + } + mali_hw_core_delete(&core->hw_core); + } + + _mali_osk_free(core); + } + else + { + MALI_PRINT_ERROR(("Failed to allocate memory for GP core\n")); + } + + return NULL; +} + +void mali_gp_delete(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + _mali_osk_irq_term(core->irq); + mali_hw_core_delete(&core->hw_core); + mali_global_gp_core = NULL; + _mali_osk_free(core); +} + +void mali_gp_stop_bus(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS); +} + +_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core) +{ + int i; + + MALI_DEBUG_ASSERT_POINTER(core); + + /* Send the stop bus command. */ + mali_gp_stop_bus(core); + + /* Wait for bus to be stopped */ + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) + { + break; + } + } + + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_PRINT_ERROR(("Mali GP: Failed to stop bus on %s\n", core->hw_core.description)); + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +void mali_gp_hard_reset(struct mali_gp_core *core) +{ + const u32 reset_wait_target_register = MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW; + const u32 reset_invalid_value = 0xC0FFE000; + const u32 reset_check_value = 0xC01A0000; + const u32 reset_default_value = 0; + int i; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_DEBUG_PRINT(4, ("Mali GP: Hard reset of core %s\n", core->hw_core.description)); + + mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_invalid_value); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_RESET); + + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_check_value); + if (reset_check_value == mali_hw_core_register_read(&core->hw_core, reset_wait_target_register)) + { + break; + } + } + + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_PRINT_ERROR(("Mali GP: The hard reset loop didn't work, unable to recover\n")); + } + + mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_default_value); /* set it back to the default */ + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); + +} + +void mali_gp_reset_async(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + MALI_DEBUG_PRINT(4, ("Mali GP: Reset of core %s\n", core->hw_core.description)); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET); + +} + +_mali_osk_errcode_t mali_gp_reset_wait(struct mali_gp_core *core) +{ + int i; + u32 rawstat = 0; + + MALI_DEBUG_ASSERT_POINTER(core); + + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + rawstat = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT); + if (rawstat & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED) + { + break; + } + } + + if (i == MALI_REG_POLL_COUNT_FAST) + { + MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, rawstat: 0x%08x\n", + core->hw_core.description, rawstat)); + return _MALI_OSK_ERR_FAULT; + } + + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core) +{ + mali_gp_reset_async(core); + return mali_gp_reset_wait(core); +} + +void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job) +{ + u32 startcmd = 0; + u32 *frame_registers = mali_gp_job_get_frame_registers(job); + + core->counter_src0_used = mali_gp_job_get_perf_counter_src0(job); + core->counter_src1_used = mali_gp_job_get_perf_counter_src1(job); + + MALI_DEBUG_ASSERT_POINTER(core); + + if (mali_gp_job_has_vs_job(job)) + { + startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS; + } + + if (mali_gp_job_has_plbu_job(job)) + { + startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU; + } + + MALI_DEBUG_ASSERT(0 != startcmd); + + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR, frame_registers, MALIGP2_NUM_REGS_FRAME); + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); + } + if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); + } + + MALI_DEBUG_PRINT(3, ("Mali GP: Starting job (0x%08x) on core %s with command 0x%08X\n", job, core->hw_core.description, startcmd)); + + /* Barrier to make sure the previous register write is finished */ + _mali_osk_write_mem_barrier(); + + /* This is the command that starts the core. */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, startcmd); + + /* Barrier to make sure the previous register write is finished */ + _mali_osk_write_mem_barrier(); +} + +void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr) +{ + u32 irq_readout; + + MALI_DEBUG_ASSERT_POINTER(core); + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT); + + if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG)); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* re-enable interrupts */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, start_addr); + mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, end_addr); + + MALI_DEBUG_PRINT(3, ("Mali GP: Resuming job\n")); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC); + _mali_osk_write_mem_barrier(); + } + /* + * else: core has been reset between PLBU_OUT_OF_MEM interrupt and this new heap response. + * A timeout or a page fault on Mali-200 PP core can cause this behaviour. + */ +} + +u32 mali_gp_core_get_version(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VERSION); +} + +struct mali_gp_core *mali_gp_get_global_gp_core(void) +{ + return mali_global_gp_core; +} + +/* ------------- interrupt handling below ------------------ */ +static void mali_gp_irq_probe_trigger(void *data) +{ + struct mali_gp_core *core = (struct mali_gp_core *)data; + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG); + _mali_osk_mem_barrier(); +} + +static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data) +{ + struct mali_gp_core *core = (struct mali_gp_core *)data; + u32 irq_readout; + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); + if (MALIGP2_REG_VAL_IRQ_FORCE_HANG & irq_readout) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_FORCE_HANG); + _mali_osk_mem_barrier(); + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + +/* ------ local helper functions below --------- */ +#if MALI_STATE_TRACKING +u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "\tGP: %s\n", core->hw_core.description); + + return n; +} +#endif + +void mali_gp_update_performance_counters(struct mali_gp_core *core, struct mali_gp_job *job, mali_bool suspend) +{ + u32 val0 = 0; + u32 val1 = 0; + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + val0 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE); + mali_gp_job_set_perf_counter_value0(job, val0); + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_report_hw_counter(COUNTER_VP_0_C0, val0); +#endif + + } + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + val1 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE); + mali_gp_job_set_perf_counter_value1(job, val1); + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_report_hw_counter(COUNTER_VP_0_C1, val1); +#endif + } +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_gp.h b/drivers/gpu/mali400/r3p2/mali/common/mali_gp.h new file mode 100644 index 0000000..2750c75 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_GP_H__ +#define __MALI_GP_H__ + +#include "mali_osk.h" +#include "mali_gp_job.h" +#include "mali_hw_core.h" +#include "regs/mali_gp_regs.h" + +struct mali_group; + +/** + * Definition of the GP core struct + * Used to track a GP core in the system. + */ +struct mali_gp_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + _mali_osk_irq_t *irq; /**< IRQ handler */ + u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */ + u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */ +}; + +_mali_osk_errcode_t mali_gp_initialize(void); +void mali_gp_terminate(void); + +struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group); +void mali_gp_delete(struct mali_gp_core *core); + +void mali_gp_stop_bus(struct mali_gp_core *core); +_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core); +void mali_gp_reset_async(struct mali_gp_core *core); +_mali_osk_errcode_t mali_gp_reset_wait(struct mali_gp_core *core); +void mali_gp_hard_reset(struct mali_gp_core *core); +_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core); + +void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job); +void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr); + +u32 mali_gp_core_get_version(struct mali_gp_core *core); + +struct mali_gp_core *mali_gp_get_global_gp_core(void); + +u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size); + +void mali_gp_update_performance_counters(struct mali_gp_core *core, struct mali_gp_job *job, mali_bool suspend); + +/*** Accessor functions ***/ +MALI_STATIC_INLINE const char *mali_gp_get_hw_core_desc(struct mali_gp_core *core) +{ + return core->hw_core.description; +} + +/*** Register reading/writing functions ***/ +MALI_STATIC_INLINE u32 mali_gp_get_int_stat(struct mali_gp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); +} + +MALI_STATIC_INLINE void mali_gp_mask_all_interrupts(struct mali_gp_core *core) +{ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE); +} + +MALI_STATIC_INLINE u32 mali_gp_read_rawstat(struct mali_gp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED; +} + +MALI_STATIC_INLINE u32 mali_gp_read_core_status(struct mali_gp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS); +} + +MALI_STATIC_INLINE void mali_gp_enable_interrupts(struct mali_gp_core *core, u32 irq_exceptions) +{ + /* Enable all interrupts, except those specified in irq_exceptions */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, + MALIGP2_REG_VAL_IRQ_MASK_USED & ~irq_exceptions); +} + +MALI_STATIC_INLINE u32 mali_gp_read_plbu_alloc_start_addr(struct mali_gp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR); +} + +#endif /* __MALI_GP_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.c b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.c new file mode 100644 index 0000000..dae68b1 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_gp_job.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_uk_types.h" + +static u32 gp_counter_src0 = MALI_HW_CORE_NO_COUNTER; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ +static u32 gp_counter_src1 = MALI_HW_CORE_NO_COUNTER; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ + +struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id) +{ + struct mali_gp_job *job; + u32 perf_counter_flag; + + job = _mali_osk_malloc(sizeof(struct mali_gp_job)); + if (NULL != job) + { + job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s)); + if (NULL == job->finished_notification) + { + _mali_osk_free(job); + return NULL; + } + + job->oom_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); + if (NULL == job->oom_notification) + { + _mali_osk_notification_delete(job->finished_notification); + _mali_osk_free(job); + return NULL; + } + + if (0 != copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_gp_start_job_s))) + { + _mali_osk_notification_delete(job->finished_notification); + _mali_osk_notification_delete(job->oom_notification); + _mali_osk_free(job); + return NULL; + } + + perf_counter_flag = mali_gp_job_get_perf_counter_flag(job); + + /* case when no counters came from user space + * so pass the debugfs / DS-5 provided global ones to the job object */ + if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) || + (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))) + { + mali_gp_job_set_perf_counter_src0(job, mali_gp_job_get_gp_counter_src0()); + mali_gp_job_set_perf_counter_src1(job, mali_gp_job_get_gp_counter_src1()); + } + + _mali_osk_list_init(&job->list); + job->session = session; + job->id = id; + job->heap_current_addr = job->uargs.frame_registers[4]; + job->perf_counter_value0 = 0; + job->perf_counter_value1 = 0; + job->pid = _mali_osk_get_pid(); + job->tid = _mali_osk_get_tid(); + + return job; + } + + return NULL; +} + +void mali_gp_job_delete(struct mali_gp_job *job) +{ + + /* de-allocate the pre-allocated oom notifications */ + if (NULL != job->oom_notification) + { + _mali_osk_notification_delete(job->oom_notification); + job->oom_notification = NULL; + } + if (NULL != job->finished_notification) + { + _mali_osk_notification_delete(job->finished_notification); + job->finished_notification = NULL; + } + + _mali_osk_free(job); +} + +u32 mali_gp_job_get_gp_counter_src0(void) +{ + return gp_counter_src0; +} + +mali_bool mali_gp_job_set_gp_counter_src0(u32 counter) +{ + gp_counter_src0 = counter; + + return MALI_TRUE; +} + +u32 mali_gp_job_get_gp_counter_src1(void) +{ + return gp_counter_src1; +} + +mali_bool mali_gp_job_set_gp_counter_src1(u32 counter) +{ + gp_counter_src1 = counter; + + return MALI_TRUE; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.h b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.h new file mode 100644 index 0000000..e021b9b --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_GP_JOB_H__ +#define __MALI_GP_JOB_H__ + +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_uk_types.h" +#include "mali_session.h" + +/** + * The structure represents a GP job, including all sub-jobs + * (This struct unfortunately needs to be public because of how the _mali_osk_list_* + * mechanism works) + */ +struct mali_gp_job +{ + _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */ + struct mali_session_data *session; /**< Session which submitted this job */ + _mali_uk_gp_start_job_s uargs; /**< Arguments from user space */ + u32 id; /**< identifier for this job in kernel space (sequential numbering) */ + u32 heap_current_addr; /**< Holds the current HEAP address when the job has completed */ + u32 perf_counter_value0; /**< Value of performance counter 0 (to be returned to user space) */ + u32 perf_counter_value1; /**< Value of performance counter 1 (to be returned to user space) */ + u32 pid; /**< Process ID of submitting process */ + u32 tid; /**< Thread ID of submitting thread */ + _mali_osk_notification_t *finished_notification; /**< Notification sent back to userspace on job complete */ + _mali_osk_notification_t *oom_notification; /**< Notification sent back to userspace on OOM */ +}; + +struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id); +void mali_gp_job_delete(struct mali_gp_job *job); + +u32 mali_gp_job_get_gp_counter_src0(void); +mali_bool mali_gp_job_set_gp_counter_src0(u32 counter); +u32 mali_gp_job_get_gp_counter_src1(void); +mali_bool mali_gp_job_set_gp_counter_src1(u32 counter); + +MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job) +{ + return (NULL == job) ? 0 : job->id; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_user_id(struct mali_gp_job *job) +{ + return job->uargs.user_job_ptr; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_frame_builder_id(struct mali_gp_job *job) +{ + return job->uargs.frame_builder_id; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_flush_id(struct mali_gp_job *job) +{ + return job->uargs.flush_id; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_pid(struct mali_gp_job *job) +{ + return job->pid; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_tid(struct mali_gp_job *job) +{ + return job->tid; +} + +MALI_STATIC_INLINE u32* mali_gp_job_get_frame_registers(struct mali_gp_job *job) +{ + return job->uargs.frame_registers; +} + +MALI_STATIC_INLINE struct mali_session_data *mali_gp_job_get_session(struct mali_gp_job *job) +{ + return job->session; +} + +MALI_STATIC_INLINE mali_bool mali_gp_job_has_vs_job(struct mali_gp_job *job) +{ + return (job->uargs.frame_registers[0] != job->uargs.frame_registers[1]) ? MALI_TRUE : MALI_FALSE; +} + +MALI_STATIC_INLINE mali_bool mali_gp_job_has_plbu_job(struct mali_gp_job *job) +{ + return (job->uargs.frame_registers[2] != job->uargs.frame_registers[3]) ? MALI_TRUE : MALI_FALSE; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_current_heap_addr(struct mali_gp_job *job) +{ + return job->heap_current_addr; +} + +MALI_STATIC_INLINE void mali_gp_job_set_current_heap_addr(struct mali_gp_job *job, u32 heap_addr) +{ + job->heap_current_addr = heap_addr; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_flag(struct mali_gp_job *job) +{ + return job->uargs.perf_counter_flag; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src0(struct mali_gp_job *job) +{ + return job->uargs.perf_counter_src0; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src1(struct mali_gp_job *job) +{ + return job->uargs.perf_counter_src1; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value0(struct mali_gp_job *job) +{ + return job->perf_counter_value0; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value1(struct mali_gp_job *job) +{ + return job->perf_counter_value1; +} + +MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_src0(struct mali_gp_job *job, u32 src) +{ + job->uargs.perf_counter_src0 = src; +} + +MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_src1(struct mali_gp_job *job, u32 src) +{ + job->uargs.perf_counter_src1 = src; +} + +MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value0(struct mali_gp_job *job, u32 value) +{ + job->perf_counter_value0 = value; +} + +MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value1(struct mali_gp_job *job, u32 value) +{ + job->perf_counter_value1 = value; +} + +#endif /* __MALI_GP_JOB_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.c b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.c new file mode 100644 index 0000000..ebbc281 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.c @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_gp_scheduler.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_scheduler.h" +#include "mali_gp.h" +#include "mali_gp_job.h" +#include "mali_group.h" +#include "mali_pm.h" +#include "mali_kernel_utilization.h" +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) +#include +#include +#endif + +enum mali_gp_slot_state +{ + MALI_GP_SLOT_STATE_IDLE, + MALI_GP_SLOT_STATE_WORKING, + MALI_GP_SLOT_STATE_DISABLED, +}; + +/* A render slot is an entity which jobs can be scheduled onto */ +struct mali_gp_slot +{ + struct mali_group *group; + /* + * We keep track of the state here as well as in the group object + * so we don't need to take the group lock so often (and also avoid clutter with the working lock) + */ + enum mali_gp_slot_state state; + u32 returned_cookie; +}; + +static u32 gp_version = 0; +static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */ +static struct mali_gp_slot slot; + +/* Variables to allow safe pausing of the scheduler */ +static _mali_osk_wait_queue_t *gp_scheduler_working_wait_queue = NULL; +static u32 pause_count = 0; + +static mali_bool mali_gp_scheduler_is_suspended(void); +static void mali_gp_scheduler_job_queued(void); +static void mali_gp_scheduler_job_completed(void); + +static _mali_osk_lock_t *gp_scheduler_lock = NULL; +/* Contains tid of thread that locked the scheduler or 0, if not locked */ + +_mali_osk_errcode_t mali_gp_scheduler_initialize(void) +{ + u32 num_groups; + u32 i; + + _MALI_OSK_INIT_LIST_HEAD(&job_queue); + + gp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); + if (NULL == gp_scheduler_lock) + { + return _MALI_OSK_ERR_NOMEM; + } + + gp_scheduler_working_wait_queue = _mali_osk_wait_queue_init(); + if (NULL == gp_scheduler_working_wait_queue) + { + _mali_osk_lock_term(gp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } + + /* Find all the available GP cores */ + num_groups = mali_group_get_glob_num_groups(); + for (i = 0; i < num_groups; i++) + { + struct mali_group *group = mali_group_get_glob_group(i); + + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) + { + if (0 == gp_version) + { + /* Retrieve GP version */ + gp_version = mali_gp_core_get_version(gp_core); + } + slot.group = group; + slot.state = MALI_GP_SLOT_STATE_IDLE; + break; /* There is only one GP, no point in looking for more */ + } + } + + return _MALI_OSK_ERR_OK; +} + +void mali_gp_scheduler_terminate(void) +{ + MALI_DEBUG_ASSERT( MALI_GP_SLOT_STATE_IDLE == slot.state + || MALI_GP_SLOT_STATE_DISABLED == slot.state); + MALI_DEBUG_ASSERT_POINTER(slot.group); + mali_group_delete(slot.group); + + _mali_osk_wait_queue_term(gp_scheduler_working_wait_queue); + _mali_osk_lock_term(gp_scheduler_lock); +} + +MALI_STATIC_INLINE void mali_gp_scheduler_lock(void) +{ + if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW)) + { + /* Non-interruptable lock failed: this should never happen. */ + MALI_DEBUG_ASSERT(0); + } + MALI_DEBUG_PRINT(5, ("Mali GP scheduler: GP scheduler lock taken\n")); +} + +MALI_STATIC_INLINE void mali_gp_scheduler_unlock(void) +{ + MALI_DEBUG_PRINT(5, ("Mali GP scheduler: Releasing GP scheduler lock\n")); + _mali_osk_lock_signal(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW); +} + +#ifdef DEBUG +MALI_STATIC_INLINE void mali_gp_scheduler_assert_locked(void) +{ + MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock); +} +#define MALI_ASSERT_GP_SCHEDULER_LOCKED() mali_gp_scheduler_assert_locked() +#else +#define MALI_ASSERT_GP_SCHEDULER_LOCKED() +#endif + +static void mali_gp_scheduler_schedule(void) +{ + struct mali_gp_job *job; + + mali_gp_scheduler_lock(); + + if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue)) + { + MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", + pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0)); + mali_gp_scheduler_unlock(); + return; /* Nothing to do, so early out */ + } + + /* Get (and remove) next job in queue */ + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list); + _mali_osk_list_del(&job->list); + + /* Mark slot as busy */ + slot.state = MALI_GP_SLOT_STATE_WORKING; + + mali_gp_scheduler_unlock(); + + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job)); + + mali_group_lock(slot.group); + mali_group_start_gp_job(slot.group, job); + mali_group_unlock(slot.group); +} + +static void mali_gp_scheduler_schedule_on_group(struct mali_group *group) +{ + struct mali_gp_job *job; + + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); + MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock); + + if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue)) + { + mali_gp_scheduler_unlock(); + MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", + pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0)); +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch(mali_gp_get_hw_core_desc(group->gp_core), sched_clock(), 0, 0, 0); +#endif + return; /* Nothing to do, so early out */ + } + + /* Get (and remove) next job in queue */ + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list); + _mali_osk_list_del(&job->list); + + /* Mark slot as busy */ + slot.state = MALI_GP_SLOT_STATE_WORKING; + + mali_gp_scheduler_unlock(); + + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job)); + + mali_group_start_gp_job(slot.group, job); +} + +static void mali_gp_scheduler_return_job_to_user(struct mali_gp_job *job, mali_bool success) +{ + _mali_uk_gp_job_finished_s *jobres = job->finished_notification->result_buffer; + _mali_osk_memset(jobres, 0, sizeof(_mali_uk_gp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ + jobres->user_job_ptr = mali_gp_job_get_user_id(job); + if (MALI_TRUE == success) + { + jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; + } + else + { + jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; + } + + jobres->heap_current_addr = mali_gp_job_get_current_heap_addr(job); + jobres->perf_counter0 = mali_gp_job_get_perf_counter_value0(job); + jobres->perf_counter1 = mali_gp_job_get_perf_counter_value1(job); + + mali_session_send_notification(mali_gp_job_get_session(job), job->finished_notification); + job->finished_notification = NULL; + + mali_gp_job_delete(job); +} + +void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success) +{ + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) completed (%s)\n", mali_gp_job_get_id(job), job, success ? "success" : "failure")); + + mali_gp_scheduler_return_job_to_user(job, success); + + mali_gp_scheduler_lock(); + + /* Mark slot as idle again */ + slot.state = MALI_GP_SLOT_STATE_IDLE; + + /* If paused, then this was the last job, so wake up sleeping workers */ + if (pause_count > 0) + { + _mali_osk_wait_queue_wake_up(gp_scheduler_working_wait_queue); + } + + mali_gp_scheduler_schedule_on_group(group); + + /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ + mali_gp_scheduler_job_completed(); +} + +void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job) +{ + _mali_uk_gp_job_suspended_s * jobres; + _mali_osk_notification_t * notification; + + mali_gp_scheduler_lock(); + + notification = job->oom_notification; + job->oom_notification = NULL; + slot.returned_cookie = mali_gp_job_get_id(job); + + jobres = (_mali_uk_gp_job_suspended_s *)notification->result_buffer; + jobres->user_job_ptr = mali_gp_job_get_user_id(job); + jobres->cookie = mali_gp_job_get_id(job); + + mali_gp_scheduler_unlock(); + + jobres->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY; + + mali_session_send_notification(mali_gp_job_get_session(job), notification); + + /* + * If this function failed, then we could return the job to user space right away, + * but there is a job timer anyway that will do that eventually. + * This is not exactly a common case anyway. + */ +} + +void mali_gp_scheduler_suspend(void) +{ + mali_gp_scheduler_lock(); + pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ + mali_gp_scheduler_unlock(); + + _mali_osk_wait_queue_wait_event(gp_scheduler_working_wait_queue, mali_gp_scheduler_is_suspended); +} + +void mali_gp_scheduler_resume(void) +{ + mali_gp_scheduler_lock(); + pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */ + mali_gp_scheduler_unlock(); + if (0 == pause_count) + { + mali_gp_scheduler_schedule(); + } +} + +_mali_osk_errcode_t _mali_ukk_gp_start_job(void *ctx, _mali_uk_gp_start_job_s *uargs) +{ + struct mali_session_data *session; + struct mali_gp_job *job; + + MALI_DEBUG_ASSERT_POINTER(uargs); + MALI_DEBUG_ASSERT_POINTER(ctx); + + session = (struct mali_session_data*)ctx; + + job = mali_gp_job_create(session, uargs, mali_scheduler_get_new_id()); + if (NULL == job) + { + return _MALI_OSK_ERR_NOMEM; + } + +#if PROFILING_SKIP_PP_AND_GP_JOBS +#warning GP jobs will not be executed + mali_gp_scheduler_return_job_to_user(job, MALI_TRUE); + return _MALI_OSK_ERR_OK; +#endif + +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_job_enqueue(mali_gp_job_get_tid(job), mali_gp_job_get_id(job), "GP"); +#endif + + mali_gp_scheduler_job_queued(); + + mali_gp_scheduler_lock(); + _mali_osk_list_addtail(&job->list, &job_queue); + mali_gp_scheduler_unlock(); + + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job)); + + mali_gp_scheduler_schedule(); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores(_mali_uk_get_gp_number_of_cores_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + args->number_of_cores = 1; + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_get_gp_core_version(_mali_uk_get_gp_core_version_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + args->version = gp_version; + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s *args) +{ + struct mali_session_data *session; + struct mali_gp_job *resumed_job; + _mali_osk_notification_t *new_notification = 0; + + MALI_DEBUG_ASSERT_POINTER(args); + + if (NULL == args->ctx) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } + + session = (struct mali_session_data*)args->ctx; + if (NULL == session) + { + return _MALI_OSK_ERR_FAULT; + } + + if (_MALIGP_JOB_RESUME_WITH_NEW_HEAP == args->code) + { + new_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); + + if (NULL == new_notification) + { + MALI_PRINT_ERROR(("Mali GP scheduler: Failed to allocate notification object. Will abort GP job.\n")); + mali_group_lock(slot.group); + mali_group_abort_gp_job(slot.group, args->cookie); + mali_group_unlock(slot.group); + return _MALI_OSK_ERR_FAULT; + } + } + + mali_group_lock(slot.group); + + if (_MALIGP_JOB_RESUME_WITH_NEW_HEAP == args->code) + { + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Resuming job %u with new heap; 0x%08X - 0x%08X\n", args->cookie, args->arguments[0], args->arguments[1])); + + resumed_job = mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]); + if (NULL != resumed_job) + { + resumed_job->oom_notification = new_notification; + mali_group_unlock(slot.group); + return _MALI_OSK_ERR_OK; + } + else + { + mali_group_unlock(slot.group); + _mali_osk_notification_delete(new_notification); + return _MALI_OSK_ERR_FAULT; + } + } + + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting job %u, no new heap provided\n", args->cookie)); + mali_group_abort_gp_job(slot.group, args->cookie); + mali_group_unlock(slot.group); + return _MALI_OSK_ERR_OK; +} + +void mali_gp_scheduler_abort_session(struct mali_session_data *session) +{ + struct mali_gp_job *job, *tmp; + + mali_gp_scheduler_lock(); + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting all jobs from session 0x%08x\n", session)); + + /* Check queue for jobs and remove */ + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_gp_job, list) + { + if (mali_gp_job_get_session(job) == session) + { + MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Removing GP job 0x%08x from queue\n", job)); + _mali_osk_list_del(&(job->list)); + mali_gp_job_delete(job); + + mali_gp_scheduler_job_completed(); + } + } + + mali_gp_scheduler_unlock(); + + mali_group_abort_session(slot.group, session); +} + +static mali_bool mali_gp_scheduler_is_suspended(void) +{ + mali_bool ret; + + mali_gp_scheduler_lock(); + ret = pause_count > 0 && slot.state == MALI_GP_SLOT_STATE_IDLE; + mali_gp_scheduler_unlock(); + + return ret; +} + + +#if MALI_STATE_TRACKING +u32 mali_gp_scheduler_dump_state(char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "GP\n"); + n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty"); + + n += mali_group_dump_state(slot.group, buf + n, size - n); + n += _mali_osk_snprintf(buf + n, size - n, "\n"); + + return n; +} +#endif + +void mali_gp_scheduler_reset_all_groups(void) +{ + if (NULL != slot.group) + { + mali_group_lock(slot.group); + mali_group_reset(slot.group); + mali_group_unlock(slot.group); + } +} + +void mali_gp_scheduler_zap_all_active(struct mali_session_data *session) +{ + if (NULL != slot.group) + { + mali_group_zap_session(slot.group, session); + } +} + +void mali_gp_scheduler_enable_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT(slot.group == group); + MALI_DEBUG_PRINT(2, ("Mali GP scheduler: enabling gp group %p\n", group)); + + mali_group_lock(group); + + if (MALI_GROUP_STATE_DISABLED != group->state) + { + mali_group_unlock(group); + MALI_DEBUG_PRINT(2, ("Mali GP scheduler: gp group %p already enabled\n", group)); + return; + } + + mali_gp_scheduler_lock(); + + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state); + MALI_DEBUG_ASSERT(MALI_GP_SLOT_STATE_DISABLED == slot.state); + slot.state = MALI_GP_SLOT_STATE_IDLE; + group->state = MALI_GROUP_STATE_IDLE; + + mali_group_power_on_group(group); + mali_group_reset(group); + + mali_gp_scheduler_unlock(); + mali_group_unlock(group); + + /* Pick up any jobs that might have been queued while the GP group was disabled. */ + mali_gp_scheduler_schedule(); +} + +void mali_gp_scheduler_disable_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT(slot.group == group); + MALI_DEBUG_PRINT(2, ("Mali GP scheduler: disabling gp group %p\n", group)); + + mali_gp_scheduler_suspend(); + mali_group_lock(group); + mali_gp_scheduler_lock(); + + MALI_DEBUG_ASSERT( MALI_GROUP_STATE_IDLE == group->state + || MALI_GROUP_STATE_DISABLED == group->state); + + if (MALI_GROUP_STATE_DISABLED == group->state) + { + MALI_DEBUG_ASSERT(MALI_GP_SLOT_STATE_DISABLED == slot.state); + MALI_DEBUG_PRINT(2, ("Mali GP scheduler: gp group %p already disabled\n", group)); + } + else + { + MALI_DEBUG_ASSERT(MALI_GP_SLOT_STATE_IDLE == slot.state); + slot.state = MALI_GP_SLOT_STATE_DISABLED; + group->state = MALI_GROUP_STATE_DISABLED; + + mali_group_power_off_group(group); + } + + mali_gp_scheduler_unlock(); + mali_group_unlock(group); + mali_gp_scheduler_resume(); +} + +static void mali_gp_scheduler_job_queued(void) +{ + /* We hold a PM reference for every job we hold queued (and running) */ + _mali_osk_pm_dev_ref_add(); + + if (mali_utilization_enabled()) + { + /* + * We cheat a little bit by counting the PP as busy from the time a GP job is queued. + * This will be fine because we only loose the tiny idle gap between jobs, but + * we will instead get less utilization work to do (less locks taken) + */ + mali_utilization_gp_start(); + } +} + +static void mali_gp_scheduler_job_completed(void) +{ + /* Release the PM reference we got in the mali_gp_scheduler_job_queued() function */ + _mali_osk_pm_dev_ref_dec(); + + if (mali_utilization_enabled()) + { + mali_utilization_gp_end(); + } +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.h b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.h new file mode 100644 index 0000000..7f61a78 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_GP_SCHEDULER_H__ +#define __MALI_GP_SCHEDULER_H__ + +#include "mali_osk.h" +#include "mali_gp_job.h" +#include "mali_group.h" + +_mali_osk_errcode_t mali_gp_scheduler_initialize(void); +void mali_gp_scheduler_terminate(void); + +void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success); +void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job); +void mali_gp_scheduler_abort_session(struct mali_session_data *session); +u32 mali_gp_scheduler_dump_state(char *buf, u32 size); + +void mali_gp_scheduler_suspend(void); +void mali_gp_scheduler_resume(void); + +/** + * @brief Reset all groups + * + * This function resets all groups known by the GP scheuduler. This must be + * called after the Mali HW has been powered on in order to reset the HW. + */ +void mali_gp_scheduler_reset_all_groups(void); + +/** + * @brief Zap TLB on all groups with \a session active + * + * The scheculer will zap the session on all groups it owns. + */ +void mali_gp_scheduler_zap_all_active(struct mali_session_data *session); + +void mali_gp_scheduler_enable_group(struct mali_group *group); +void mali_gp_scheduler_disable_group(struct mali_group *group); + +#endif /* __MALI_GP_SCHEDULER_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_group.c b/drivers/gpu/mali400/r3p2/mali/common/mali_group.c new file mode 100644 index 0000000..070879e --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_group.c @@ -0,0 +1,2046 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_group.h" +#include "mali_osk.h" +#include "mali_l2_cache.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_mmu.h" +#include "mali_dlbu.h" +#include "mali_broadcast.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" +#include "mali_kernel_core.h" +#include "mali_osk_profiling.h" +#include "mali_pm_domain.h" +#include "mali_pm.h" +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) +#include +#include +#endif + + +static void mali_group_bottom_half_mmu(void *data); +static void mali_group_bottom_half_gp(void *data); +static void mali_group_bottom_half_pp(void *data); + +static void mali_group_timeout(void *data); +static void mali_group_reset_pp(struct mali_group *group); +static void mali_group_reset_mmu(struct mali_group *group); + +#if defined(CONFIG_MALI400_PROFILING) +static void mali_group_report_l2_cache_counters_per_core(struct mali_group *group, u32 core_num); +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ + +/* + * The group object is the most important object in the device driver, + * and acts as the center of many HW operations. + * The reason for this is that operations on the MMU will affect all + * cores connected to this MMU (a group is defined by the MMU and the + * cores which are connected to this). + * The group lock is thus the most important lock, followed by the + * GP and PP scheduler locks. They must be taken in the following + * order: + * GP/PP lock first, then group lock(s). + */ + +static struct mali_group *mali_global_groups[MALI_MAX_NUMBER_OF_GROUPS] = { NULL, }; +static u32 mali_global_num_groups = 0; + +enum mali_group_activate_pd_status +{ + MALI_GROUP_ACTIVATE_PD_STATUS_FAILED, + MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD, + MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD, +}; + +/* local helper functions */ +static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session); +static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session); +static void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session); +static void mali_group_recovery_reset(struct mali_group *group); +static void mali_group_mmu_page_fault(struct mali_group *group); + +static void mali_group_post_process_job_pp(struct mali_group *group); +static void mali_group_post_process_job_gp(struct mali_group *group, mali_bool suspend); + +void mali_group_lock(struct mali_group *group) +{ + if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(group->lock, _MALI_OSK_LOCKMODE_RW)) + { + /* Non-interruptable lock failed: this should never happen. */ + MALI_DEBUG_ASSERT(0); + } + MALI_DEBUG_PRINT(5, ("Mali group: Group lock taken 0x%08X\n", group)); +} + +void mali_group_unlock(struct mali_group *group) +{ + MALI_DEBUG_PRINT(5, ("Mali group: Releasing group lock 0x%08X\n", group)); + _mali_osk_lock_signal(group->lock, _MALI_OSK_LOCKMODE_RW); +} + +#ifdef DEBUG +void mali_group_assert_locked(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); +} +#endif + + +struct mali_group *mali_group_create(struct mali_l2_cache_core *core, struct mali_dlbu_core *dlbu, struct mali_bcast_unit *bcast) +{ + struct mali_group *group = NULL; + _mali_osk_lock_flags_t lock_flags; + +#if defined(MALI_UPPER_HALF_SCHEDULING) + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#else + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#endif + + if (mali_global_num_groups >= MALI_MAX_NUMBER_OF_GROUPS) + { + MALI_PRINT_ERROR(("Mali group: Too many group objects created\n")); + return NULL; + } + + group = _mali_osk_calloc(1, sizeof(struct mali_group)); + if (NULL != group) + { + group->timeout_timer = _mali_osk_timer_init(); + + if (NULL != group->timeout_timer) + { + _mali_osk_lock_order_t order; + _mali_osk_timer_setcallback(group->timeout_timer, mali_group_timeout, (void *)group); + + if (NULL != dlbu) + { + order = _MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL; + } + else + { + order = _MALI_OSK_LOCK_ORDER_GROUP; + } + + group->lock = _mali_osk_lock_init(lock_flags, 0, order); + if (NULL != group->lock) + { + group->l2_cache_core[0] = core; + group->session = NULL; + group->page_dir_ref_count = 0; + group->power_is_on = MALI_TRUE; + group->state = MALI_GROUP_STATE_IDLE; + _mali_osk_list_init(&group->group_list); + _mali_osk_list_init(&group->pp_scheduler_list); + group->parent_group = NULL; + group->l2_cache_core_ref_count[0] = 0; + group->l2_cache_core_ref_count[1] = 0; + group->bcast_core = bcast; + group->dlbu_core = dlbu; + + mali_global_groups[mali_global_num_groups] = group; + mali_global_num_groups++; + + return group; + } + _mali_osk_timer_term(group->timeout_timer); + } + _mali_osk_free(group); + } + + return NULL; +} + +_mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group, struct mali_mmu_core* mmu_core) +{ + /* This group object now owns the MMU core object */ + group->mmu= mmu_core; + group->bottom_half_work_mmu = _mali_osk_wq_create_work(mali_group_bottom_half_mmu, group); + if (NULL == group->bottom_half_work_mmu) + { + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +void mali_group_remove_mmu_core(struct mali_group *group) +{ + /* This group object no longer owns the MMU core object */ + group->mmu = NULL; + if (NULL != group->bottom_half_work_mmu) + { + _mali_osk_wq_delete_work(group->bottom_half_work_mmu); + } +} + +_mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core) +{ + /* This group object now owns the GP core object */ + group->gp_core = gp_core; + group->bottom_half_work_gp = _mali_osk_wq_create_work(mali_group_bottom_half_gp, group); + if (NULL == group->bottom_half_work_gp) + { + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +void mali_group_remove_gp_core(struct mali_group *group) +{ + /* This group object no longer owns the GP core object */ + group->gp_core = NULL; + if (NULL != group->bottom_half_work_gp) + { + _mali_osk_wq_delete_work(group->bottom_half_work_gp); + } +} + +_mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core) +{ + /* This group object now owns the PP core object */ + group->pp_core = pp_core; + group->bottom_half_work_pp = _mali_osk_wq_create_work(mali_group_bottom_half_pp, group); + if (NULL == group->bottom_half_work_pp) + { + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +void mali_group_remove_pp_core(struct mali_group *group) +{ + /* This group object no longer owns the PP core object */ + group->pp_core = NULL; + if (NULL != group->bottom_half_work_pp) + { + _mali_osk_wq_delete_work(group->bottom_half_work_pp); + } +} + +void mali_group_set_pm_domain(struct mali_group *group, struct mali_pm_domain *domain) +{ + group->pm_domain = domain; +} + +void mali_group_delete(struct mali_group *group) +{ + u32 i; + + MALI_DEBUG_PRINT(4, ("Deleting group %p\n", group)); + + MALI_DEBUG_ASSERT(NULL == group->parent_group); + + /* Delete the resources that this group owns */ + if (NULL != group->gp_core) + { + mali_gp_delete(group->gp_core); + } + + if (NULL != group->pp_core) + { + mali_pp_delete(group->pp_core); + } + + if (NULL != group->mmu) + { + mali_mmu_delete(group->mmu); + } + + if (mali_group_is_virtual(group)) + { + /* Remove all groups from virtual group */ + struct mali_group *child; + struct mali_group *temp; + + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + child->parent_group = NULL; + mali_group_delete(child); + } + + mali_dlbu_delete(group->dlbu_core); + + if (NULL != group->bcast_core) + { + mali_bcast_unit_delete(group->bcast_core); + } + } + + for (i = 0; i < mali_global_num_groups; i++) + { + if (mali_global_groups[i] == group) + { + mali_global_groups[i] = NULL; + mali_global_num_groups--; + + if (i != mali_global_num_groups) + { + /* We removed a group from the middle of the array -- move the last + * group to the current position to close the gap */ + mali_global_groups[i] = mali_global_groups[mali_global_num_groups]; + mali_global_groups[mali_global_num_groups] = NULL; + } + + break; + } + } + + if (NULL != group->timeout_timer) + { + _mali_osk_timer_del(group->timeout_timer); + _mali_osk_timer_term(group->timeout_timer); + } + + if (NULL != group->bottom_half_work_mmu) + { + _mali_osk_wq_delete_work(group->bottom_half_work_mmu); + } + + if (NULL != group->bottom_half_work_gp) + { + _mali_osk_wq_delete_work(group->bottom_half_work_gp); + } + + if (NULL != group->bottom_half_work_pp) + { + _mali_osk_wq_delete_work(group->bottom_half_work_pp); + } + + _mali_osk_lock_term(group->lock); + + _mali_osk_free(group); +} + +MALI_DEBUG_CODE(static void mali_group_print_virtual(struct mali_group *vgroup) +{ + u32 i; + struct mali_group *group; + struct mali_group *temp; + + MALI_DEBUG_PRINT(4, ("Virtual group %p\n", vgroup)); + MALI_DEBUG_PRINT(4, ("l2_cache_core[0] = %p, ref = %d\n", vgroup->l2_cache_core[0], vgroup->l2_cache_core_ref_count[0])); + MALI_DEBUG_PRINT(4, ("l2_cache_core[1] = %p, ref = %d\n", vgroup->l2_cache_core[1], vgroup->l2_cache_core_ref_count[1])); + + i = 0; + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &vgroup->group_list, struct mali_group, group_list) + { + MALI_DEBUG_PRINT(4, ("[%d] %p, l2_cache_core[0] = %p\n", i, group, group->l2_cache_core[0])); + i++; + } +}) + +/** + * @brief Add child group to virtual group parent + * + * Before calling this function, child must have it's state set to JOINING_VIRTUAL + * to ensure it's not touched during the transition period. When this function returns, + * child's state will be IN_VIRTUAL. + */ +void mali_group_add_group(struct mali_group *parent, struct mali_group *child, mali_bool update_hw) +{ + mali_bool found; + u32 i; + struct mali_session_data *child_session; + + MALI_DEBUG_PRINT(3, ("Adding group %p to virtual group %p\n", child, parent)); + + MALI_ASSERT_GROUP_LOCKED(parent); + + MALI_DEBUG_ASSERT(mali_group_is_virtual(parent)); + MALI_DEBUG_ASSERT(!mali_group_is_virtual(child)); + MALI_DEBUG_ASSERT(NULL == child->parent_group); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_JOINING_VIRTUAL == child->state); + + _mali_osk_list_addtail(&child->group_list, &parent->group_list); + + child->state = MALI_GROUP_STATE_IN_VIRTUAL; + child->parent_group = parent; + + MALI_DEBUG_ASSERT_POINTER(child->l2_cache_core[0]); + + MALI_DEBUG_PRINT(4, ("parent->l2_cache_core: [0] = %p, [1] = %p\n", parent->l2_cache_core[0], parent->l2_cache_core[1])); + MALI_DEBUG_PRINT(4, ("child->l2_cache_core: [0] = %p, [1] = %p\n", child->l2_cache_core[0], child->l2_cache_core[1])); + + /* Keep track of the L2 cache cores of child groups */ + found = MALI_FALSE; + for (i = 0; i < 2; i++) + { + if (parent->l2_cache_core[i] == child->l2_cache_core[0]) + { + MALI_DEBUG_ASSERT(parent->l2_cache_core_ref_count[i] > 0); + parent->l2_cache_core_ref_count[i]++; + found = MALI_TRUE; + } + } + + if (!found) + { + /* First time we see this L2 cache, add it to our list */ + i = (NULL == parent->l2_cache_core[0]) ? 0 : 1; + + MALI_DEBUG_PRINT(4, ("First time we see l2_cache %p. Adding to [%d] = %p\n", child->l2_cache_core[0], i, parent->l2_cache_core[i])); + + MALI_DEBUG_ASSERT(NULL == parent->l2_cache_core[i]); + + parent->l2_cache_core[i] = child->l2_cache_core[0]; + parent->l2_cache_core_ref_count[i]++; + } + + /* Update Broadcast Unit and DLBU */ + mali_bcast_add_group(parent->bcast_core, child); + mali_dlbu_add_group(parent->dlbu_core, child); + + child_session = child->session; + child->session = NULL; + + /* Above this comment, only software state is updated and the HW is not + * touched. Now, check if Mali is powered and skip the rest if it isn't + * powered. + */ + + if (!update_hw) + { + MALI_DEBUG_CODE(mali_group_print_virtual(parent)); + return; + } + + /* Update MMU */ + MALI_DEBUG_ASSERT(0 == child->page_dir_ref_count); + if (parent->session == child_session) + { + mali_mmu_zap_tlb(child->mmu); + } + else + { + if (NULL == parent->session) + { + mali_mmu_activate_empty_page_directory(child->mmu); + } + else + { + + mali_bool activate_success = mali_mmu_activate_page_directory(child->mmu, + mali_session_get_page_directory(parent->session)); + MALI_DEBUG_ASSERT(activate_success); + MALI_IGNORE(activate_success); + } + } + + /* Update HW only if power is on */ + mali_bcast_reset(parent->bcast_core); + mali_dlbu_update_mask(parent->dlbu_core); + + /* Start job on child when parent is active */ + if (NULL != parent->pp_running_job) + { + struct mali_pp_job *job = parent->pp_running_job; + MALI_DEBUG_PRINT(3, ("Group %x joining running job %d on virtual group %x\n", + child, mali_pp_job_get_id(job), parent)); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_WORKING == parent->state); + mali_pp_job_start(child->pp_core, job, mali_pp_core_get_id(child->pp_core), MALI_TRUE); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))| + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, + mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))| + MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL, + mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); + } + + MALI_DEBUG_CODE(mali_group_print_virtual(parent);) +} + +/** + * @brief Remove child group from virtual group parent + * + * After the child is removed, it's state will be LEAVING_VIRTUAL and must be set + * to IDLE before it can be used. + */ +void mali_group_remove_group(struct mali_group *parent, struct mali_group *child) +{ + u32 i; + + MALI_ASSERT_GROUP_LOCKED(parent); + + MALI_DEBUG_PRINT(3, ("Removing group %p from virtual group %p\n", child, parent)); + + MALI_DEBUG_ASSERT(mali_group_is_virtual(parent)); + MALI_DEBUG_ASSERT(!mali_group_is_virtual(child)); + MALI_DEBUG_ASSERT(parent == child->parent_group); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IN_VIRTUAL == child->state); + /* Removing groups while running is not yet supported. */ + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == parent->state); + + mali_group_lock(child); + + /* Update Broadcast Unit and DLBU */ + mali_bcast_remove_group(parent->bcast_core, child); + mali_dlbu_remove_group(parent->dlbu_core, child); + + /* Update HW only if power is on */ + if (mali_pm_is_power_on()) + { + mali_bcast_reset(parent->bcast_core); + mali_dlbu_update_mask(parent->dlbu_core); + } + + _mali_osk_list_delinit(&child->group_list); + + child->session = parent->session; + child->parent_group = NULL; + child->state = MALI_GROUP_STATE_LEAVING_VIRTUAL; + + /* Keep track of the L2 cache cores of child groups */ + i = (child->l2_cache_core[0] == parent->l2_cache_core[0]) ? 0 : 1; + + MALI_DEBUG_ASSERT(child->l2_cache_core[0] == parent->l2_cache_core[i]); + + parent->l2_cache_core_ref_count[i]--; + + if (parent->l2_cache_core_ref_count[i] == 0) + { + parent->l2_cache_core[i] = NULL; + } + + MALI_DEBUG_CODE(mali_group_print_virtual(parent)); + + mali_group_unlock(child); +} + +struct mali_group *mali_group_acquire_group(struct mali_group *parent) +{ + struct mali_group *child; + + MALI_ASSERT_GROUP_LOCKED(parent); + + MALI_DEBUG_ASSERT(mali_group_is_virtual(parent)); + MALI_DEBUG_ASSERT(!_mali_osk_list_empty(&parent->group_list)); + + child = _MALI_OSK_LIST_ENTRY(parent->group_list.prev, struct mali_group, group_list); + + mali_group_remove_group(parent, child); + + return child; +} + +void mali_group_reset(struct mali_group *group) +{ + /* + * This function should not be used to abort jobs, + * currently only called during insmod and PM resume + */ + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); + MALI_DEBUG_ASSERT(NULL == group->gp_running_job); + MALI_DEBUG_ASSERT(NULL == group->pp_running_job); + + group->session = NULL; + + if (NULL != group->dlbu_core) + { + mali_dlbu_reset(group->dlbu_core); + } + + if (NULL != group->bcast_core) + { + mali_bcast_reset(group->bcast_core); + } + + if (NULL != group->mmu) + { + mali_group_reset_mmu(group); + } + + if (NULL != group->gp_core) + { + mali_gp_reset(group->gp_core); + } + + if (NULL != group->pp_core) + { + mali_group_reset_pp(group); + } +} + +struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group) +{ + return group->gp_core; +} + +struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group) +{ + return group->pp_core; +} + +void mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job) +{ + struct mali_session_data *session; + enum mali_group_activate_pd_status activate_status; + + MALI_ASSERT_GROUP_LOCKED(group); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state); + + session = mali_gp_job_get_session(job); + + if (NULL != group->l2_cache_core[0]) + { + mali_l2_cache_invalidate_conditional(group->l2_cache_core[0], mali_gp_job_get_id(job)); + } + + activate_status = mali_group_activate_page_directory(group, session); + if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) + { + /* if session is NOT kept Zapping is done as part of session switch */ + if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) + { + mali_mmu_zap_tlb_without_stall(group->mmu); + } + mali_gp_job_start(group->gp_core, job); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) | + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, + mali_gp_job_get_frame_builder_id(job), mali_gp_job_get_flush_id(job), 0, 0, 0); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START | + MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), + mali_gp_job_get_pid(job), mali_gp_job_get_tid(job), 0, 0, 0); +#if defined(CONFIG_MALI400_PROFILING) + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + mali_group_report_l2_cache_counters_per_core(group, 0); +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ + +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch(mali_gp_get_hw_core_desc(group->gp_core), sched_clock(), + mali_gp_job_get_pid(job), 0, mali_gp_job_get_id(job)); +#endif + group->gp_running_job = job; + group->state = MALI_GROUP_STATE_WORKING; + + } + + /* Setup the timeout timer value and save the job id for the job running on the gp core */ + _mali_osk_timer_mod(group->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); +} + +void mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job) +{ + struct mali_session_data *session; + enum mali_group_activate_pd_status activate_status; + + MALI_ASSERT_GROUP_LOCKED(group); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state); + + session = mali_pp_job_get_session(job); + + if (NULL != group->l2_cache_core[0]) + { + mali_l2_cache_invalidate_conditional(group->l2_cache_core[0], mali_pp_job_get_id(job)); + } + + if (NULL != group->l2_cache_core[1]) + { + mali_l2_cache_invalidate_conditional(group->l2_cache_core[1], mali_pp_job_get_id(job)); + } + + activate_status = mali_group_activate_page_directory(group, session); + if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) + { + /* if session is NOT kept Zapping is done as part of session switch */ + if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) + { + MALI_DEBUG_PRINT(3, ("PP starting job PD_Switch 0 Flush 1 Zap 1\n")); + mali_mmu_zap_tlb_without_stall(group->mmu); + } + + if (mali_group_is_virtual(group)) + { + struct mali_group *child; + struct mali_group *temp; + u32 core_num = 0; + + /* Configure DLBU for the job */ + mali_dlbu_config_job(group->dlbu_core, job); + + /* Write stack address for each child group */ + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + mali_pp_write_addr_stack(child->pp_core, job); + core_num++; + } + } + + mali_pp_job_start(group->pp_core, job, sub_job, MALI_FALSE); + + /* if the group is virtual, loop through physical groups which belong to this group + * and call profiling events for its cores as virtual */ + if (MALI_TRUE == mali_group_is_virtual(group)) + { + struct mali_group *child; + struct mali_group *temp; + + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))| + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, + mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))| + MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL, + mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); + } +#if defined(CONFIG_MALI400_PROFILING) + if (0 != group->l2_cache_core_ref_count[0]) + { + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0])); + } + } + if (0 != group->l2_cache_core_ref_count[1]) + { + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[1])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[1]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[1])); + } + } +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ + } + else /* group is physical - call profiling events for physical cores */ + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))| + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, + mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))| + MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL, + mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); +#if defined(CONFIG_MALI400_PROFILING) + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0])); + } +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ + } +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch(mali_pp_get_hw_core_desc(group->pp_core), sched_clock(), mali_pp_job_get_tid(job), 0, mali_pp_job_get_id(job)); +#endif + group->pp_running_job = job; + group->pp_running_sub_job = sub_job; + group->state = MALI_GROUP_STATE_WORKING; + + } + + /* Setup the timeout timer value and save the job id for the job running on the pp core */ + _mali_osk_timer_mod(group->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); +} + +struct mali_gp_job *mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (group->state != MALI_GROUP_STATE_OOM || + mali_gp_job_get_id(group->gp_running_job) != job_id) + { + return NULL; /* Illegal request or job has already been aborted */ + } + + if (NULL != group->l2_cache_core[0]) + { + mali_l2_cache_invalidate(group->l2_cache_core[0]); + } + + mali_mmu_zap_tlb_without_stall(group->mmu); + + mali_gp_resume_with_new_heap(group->gp_core, start_addr, end_addr); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0); + + group->state = MALI_GROUP_STATE_WORKING; + + return group->gp_running_job; +} + +static void mali_group_reset_mmu(struct mali_group *group) +{ + struct mali_group *child; + struct mali_group *temp; + _mali_osk_errcode_t err; + + if (!mali_group_is_virtual(group)) + { + /* This is a physical group or an idle virtual group -- simply wait for + * the reset to complete. */ + err = mali_mmu_reset(group->mmu); + MALI_DEBUG_ASSERT(_MALI_OSK_ERR_OK == err); + } + else /* virtual group */ + { + err = mali_mmu_reset(group->mmu); + if (_MALI_OSK_ERR_OK == err) + { + return; + } + + /* Loop through all members of this virtual group and wait + * until they are done resetting. + */ + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + err = mali_mmu_reset(child->mmu); + MALI_DEBUG_ASSERT(_MALI_OSK_ERR_OK == err); + } + } +} + +static void mali_group_reset_pp(struct mali_group *group) +{ + struct mali_group *child; + struct mali_group *temp; + + mali_pp_reset_async(group->pp_core); + + if (!mali_group_is_virtual(group) || NULL == group->pp_running_job) + { + /* This is a physical group or an idle virtual group -- simply wait for + * the reset to complete. */ + mali_pp_reset_wait(group->pp_core); + } + else /* virtual group */ + { + /* Loop through all members of this virtual group and wait until they + * are done resetting. + */ + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + mali_pp_reset_wait(child->pp_core); + } + } +} + +static void mali_group_complete_pp(struct mali_group *group, mali_bool success) +{ + struct mali_pp_job *pp_job_to_return; + u32 pp_sub_job_to_return; + + MALI_DEBUG_ASSERT_POINTER(group->pp_core); + MALI_DEBUG_ASSERT_POINTER(group->pp_running_job); + MALI_ASSERT_GROUP_LOCKED(group); + + mali_group_post_process_job_pp(group); + + if (success) + { + /* Only do soft reset for successful jobs, a full recovery + * reset will be done for failed jobs. */ + mali_pp_reset_async(group->pp_core); + } + + pp_job_to_return = group->pp_running_job; + pp_sub_job_to_return = group->pp_running_sub_job; + group->state = MALI_GROUP_STATE_IDLE; + group->pp_running_job = NULL; + + mali_group_deactivate_page_directory(group, group->session); + + /* Do hard reset if the job failed, or if soft reset fails */ + if (!success || _MALI_OSK_ERR_OK != mali_pp_reset_wait(group->pp_core)) + { + MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n")); + + mali_group_recovery_reset(group); + } + + mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, success); +} + +static void mali_group_complete_gp(struct mali_group *group, mali_bool success) +{ + struct mali_gp_job *gp_job_to_return; + + MALI_DEBUG_ASSERT_POINTER(group->gp_core); + MALI_DEBUG_ASSERT_POINTER(group->gp_running_job); + MALI_ASSERT_GROUP_LOCKED(group); + + mali_group_post_process_job_gp(group, MALI_FALSE); + + mali_gp_reset_async(group->gp_core); + + gp_job_to_return = group->gp_running_job; + group->state = MALI_GROUP_STATE_IDLE; + group->gp_running_job = NULL; + + mali_group_deactivate_page_directory(group, group->session); + + if (_MALI_OSK_ERR_OK != mali_gp_reset_wait(group->gp_core)) + { + MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset GP, need to reset entire group\n")); + + mali_group_recovery_reset(group); + } + + mali_gp_scheduler_job_done(group, gp_job_to_return, success); +} + +void mali_group_abort_gp_job(struct mali_group *group, u32 job_id) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (MALI_GROUP_STATE_IDLE == group->state || + mali_gp_job_get_id(group->gp_running_job) != job_id) + { + return; /* No need to cancel or job has already been aborted or completed */ + } + + mali_group_complete_gp(group, MALI_FALSE); +} + +static void mali_group_abort_pp_job(struct mali_group *group, u32 job_id) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (MALI_GROUP_STATE_IDLE == group->state || + mali_pp_job_get_id(group->pp_running_job) != job_id) + { + return; /* No need to cancel or job has already been aborted or completed */ + } + + mali_group_complete_pp(group, MALI_FALSE); +} + +void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session) +{ + struct mali_gp_job *gp_job; + struct mali_pp_job *pp_job; + u32 gp_job_id = 0; + u32 pp_job_id = 0; + mali_bool abort_pp = MALI_FALSE; + mali_bool abort_gp = MALI_FALSE; + + mali_group_lock(group); + + if (mali_group_is_in_virtual(group)) + { + /* Group is member of a virtual group, don't touch it! */ + mali_group_unlock(group); + return; + } + + gp_job = group->gp_running_job; + pp_job = group->pp_running_job; + + if ((NULL != gp_job) && (mali_gp_job_get_session(gp_job) == session)) + { + MALI_DEBUG_PRINT(4, ("Aborting GP job 0x%08x from session 0x%08x\n", gp_job, session)); + + gp_job_id = mali_gp_job_get_id(gp_job); + abort_gp = MALI_TRUE; + } + + if ((NULL != pp_job) && (mali_pp_job_get_session(pp_job) == session)) + { + MALI_DEBUG_PRINT(4, ("Mali group: Aborting PP job 0x%08x from session 0x%08x\n", pp_job, session)); + + pp_job_id = mali_pp_job_get_id(pp_job); + abort_pp = MALI_TRUE; + } + + if (abort_gp) + { + mali_group_abort_gp_job(group, gp_job_id); + } + if (abort_pp) + { + mali_group_abort_pp_job(group, pp_job_id); + } + + mali_group_remove_session_if_unused(group, session); + + mali_group_unlock(group); +} + +struct mali_group *mali_group_get_glob_group(u32 index) +{ + if(mali_global_num_groups > index) + { + return mali_global_groups[index]; + } + + return NULL; +} + +u32 mali_group_get_glob_num_groups(void) +{ + return mali_global_num_groups; +} + +static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session) +{ + enum mali_group_activate_pd_status retval; + MALI_ASSERT_GROUP_LOCKED(group); + + MALI_DEBUG_PRINT(5, ("Mali group: Activating page directory 0x%08X from session 0x%08X on group 0x%08X\n", mali_session_get_page_directory(session), session, group)); + MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count); + + if (0 != group->page_dir_ref_count) + { + if (group->session != session) + { + MALI_DEBUG_PRINT(4, ("Mali group: Activating session FAILED: 0x%08x on group 0x%08X. Existing session: 0x%08x\n", session, group, group->session)); + return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED; + } + else + { + MALI_DEBUG_PRINT(4, ("Mali group: Activating session already activated: 0x%08x on group 0x%08X. New Ref: %d\n", session, group, 1+group->page_dir_ref_count)); + retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD; + + } + } + else + { + /* There might be another session here, but it is ok to overwrite it since group->page_dir_ref_count==0 */ + if (group->session != session) + { + mali_bool activate_success; + MALI_DEBUG_PRINT(5, ("Mali group: Activate session: %08x previous: %08x on group 0x%08X. Ref: %d\n", session, group->session, group, 1+group->page_dir_ref_count)); + + activate_success = mali_mmu_activate_page_directory(group->mmu, mali_session_get_page_directory(session)); + MALI_DEBUG_ASSERT(activate_success); + if ( MALI_FALSE== activate_success ) return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED; + group->session = session; + retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD; + } + else + { + MALI_DEBUG_PRINT(4, ("Mali group: Activate existing session 0x%08X on group 0x%08X. Ref: %d\n", session->page_directory, group, 1+group->page_dir_ref_count)); + retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD; + } + } + + group->page_dir_ref_count++; + return retval; +} + +static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + MALI_DEBUG_ASSERT(0 < group->page_dir_ref_count); + MALI_DEBUG_ASSERT(session == group->session); + + group->page_dir_ref_count--; + + /* As an optimization, the MMU still points to the group->session even if (0 == group->page_dir_ref_count), + and we do not call mali_mmu_activate_empty_page_directory(group->mmu); */ + MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count); +} + +static void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (0 == group->page_dir_ref_count) + { + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_WORKING != group->state); + + if (group->session == session) + { + MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on); + MALI_DEBUG_PRINT(3, ("Mali group: Deactivating unused session 0x%08X on group %08X\n", session, group)); + mali_mmu_activate_empty_page_directory(group->mmu); + group->session = NULL; + } + } +} + +mali_bool mali_group_power_is_on(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); + return group->power_is_on; +} + +void mali_group_power_on_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); + MALI_DEBUG_ASSERT( MALI_GROUP_STATE_IDLE == group->state + || MALI_GROUP_STATE_IN_VIRTUAL == group->state + || MALI_GROUP_STATE_JOINING_VIRTUAL == group->state + || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state + || MALI_GROUP_STATE_DISABLED == group->state); + + MALI_DEBUG_PRINT(3, ("Group %p powered on\n", group)); + + group->power_is_on = MALI_TRUE; +} + +void mali_group_power_off_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); + MALI_DEBUG_ASSERT( MALI_GROUP_STATE_IDLE == group->state + || MALI_GROUP_STATE_IN_VIRTUAL == group->state + || MALI_GROUP_STATE_JOINING_VIRTUAL == group->state + || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state + || MALI_GROUP_STATE_DISABLED == group->state); + + MALI_DEBUG_PRINT(3, ("Group %p powered off\n", group)); + + /* It is necessary to set group->session = NULL so that the powered off MMU is not written + * to on map/unmap. It is also necessary to set group->power_is_on = MALI_FALSE so that + * pending bottom_halves does not access powered off cores. */ + + group->session = NULL; + group->power_is_on = MALI_FALSE; +} + +void mali_group_power_on(void) +{ + int i; + for (i = 0; i < mali_global_num_groups; i++) + { + struct mali_group *group = mali_global_groups[i]; + + mali_group_lock(group); + if (MALI_GROUP_STATE_DISABLED == group->state) + { + MALI_DEBUG_ASSERT(MALI_FALSE == group->power_is_on); + } + else + { + mali_group_power_on_group(group); + } + mali_group_unlock(group); + } + MALI_DEBUG_PRINT(4, ("Mali Group: power on\n")); +} + +void mali_group_power_off(void) +{ + int i; + + for (i = 0; i < mali_global_num_groups; i++) + { + struct mali_group *group = mali_global_groups[i]; + + mali_group_lock(group); + if (MALI_GROUP_STATE_DISABLED == group->state) + { + MALI_DEBUG_ASSERT(MALI_FALSE == group->power_is_on); + } + else + { + mali_group_power_off_group(group); + } + mali_group_unlock(group); + } + MALI_DEBUG_PRINT(4, ("Mali Group: power off\n")); +} + +static void mali_group_recovery_reset(struct mali_group *group) +{ + _mali_osk_errcode_t err; + + MALI_ASSERT_GROUP_LOCKED(group); + + /* Stop cores, bus stop */ + if (NULL != group->pp_core) + { + mali_pp_stop_bus(group->pp_core); + } + else + { + mali_gp_stop_bus(group->gp_core); + } + + /* Flush MMU and clear page fault (if any) */ + mali_mmu_activate_fault_flush_page_directory(group->mmu); + mali_mmu_page_fault_done(group->mmu); + + /* Wait for cores to stop bus, then do a hard reset on them */ + if (NULL != group->pp_core) + { + if (mali_group_is_virtual(group)) + { + struct mali_group *child, *temp; + + /* Disable the broadcast unit while we do reset directly on the member cores. */ + mali_bcast_disable(group->bcast_core); + + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + mali_pp_stop_bus_wait(child->pp_core); + mali_pp_hard_reset(child->pp_core); + } + + mali_bcast_enable(group->bcast_core); + } + else + { + mali_pp_stop_bus_wait(group->pp_core); + mali_pp_hard_reset(group->pp_core); + } + } + else + { + mali_gp_stop_bus_wait(group->gp_core); + mali_gp_hard_reset(group->gp_core); + } + + /* Reset MMU */ + err = mali_mmu_reset(group->mmu); + MALI_DEBUG_ASSERT(_MALI_OSK_ERR_OK == err); + MALI_IGNORE(err); + + group->session = NULL; +} + +#if MALI_STATE_TRACKING +u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group); + n += _mali_osk_snprintf(buf + n, size - n, "\tstate: %d\n", group->state); + if (group->gp_core) + { + n += mali_gp_dump_state(group->gp_core, buf + n, size - n); + n += _mali_osk_snprintf(buf + n, size - n, "\tGP job: %p\n", group->gp_running_job); + } + if (group->pp_core) + { + n += mali_pp_dump_state(group->pp_core, buf + n, size - n); + n += _mali_osk_snprintf(buf + n, size - n, "\tPP job: %p, subjob %d \n", + group->pp_running_job, group->pp_running_sub_job); + } + + return n; +} +#endif + +static void mali_group_mmu_page_fault(struct mali_group *group) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (NULL != group->pp_core) + { + struct mali_pp_job *pp_job_to_return; + u32 pp_sub_job_to_return; + + MALI_DEBUG_ASSERT_POINTER(group->pp_running_job); + + mali_group_post_process_job_pp(group); + + pp_job_to_return = group->pp_running_job; + pp_sub_job_to_return = group->pp_running_sub_job; + group->state = MALI_GROUP_STATE_IDLE; + group->pp_running_job = NULL; + + mali_group_deactivate_page_directory(group, group->session); + + mali_group_recovery_reset(group); /* This will also clear the page fault itself */ + + mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, MALI_FALSE); + } + else + { + struct mali_gp_job *gp_job_to_return; + + MALI_DEBUG_ASSERT_POINTER(group->gp_running_job); + + mali_group_post_process_job_gp(group, MALI_FALSE); + + gp_job_to_return = group->gp_running_job; + group->state = MALI_GROUP_STATE_IDLE; + group->gp_running_job = NULL; + + mali_group_deactivate_page_directory(group, group->session); + + mali_group_recovery_reset(group); /* This will also clear the page fault itself */ + + mali_gp_scheduler_job_done(group, gp_job_to_return, MALI_FALSE); + } +} + +_mali_osk_errcode_t mali_group_upper_half_mmu(void * data) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + struct mali_group *group = (struct mali_group *)data; + struct mali_mmu_core *mmu = group->mmu; + u32 int_stat; + + MALI_DEBUG_ASSERT_POINTER(mmu); + +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + if (MALI_FALSE == mali_pm_domain_lock_state(group->pm_domain)) + { + goto out; + } +#endif + + /* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */ + int_stat = mali_mmu_get_int_status(mmu); + if (0 != int_stat) + { + struct mali_group *parent = group->parent_group; + + /* page fault or bus error, we thread them both in the same way */ + mali_mmu_mask_all_interrupts(mmu); + if (NULL == parent) + { + _mali_osk_wq_schedule_work(group->bottom_half_work_mmu); + } + else + { + _mali_osk_wq_schedule_work(parent->bottom_half_work_mmu); + } + err = _MALI_OSK_ERR_OK; + goto out; + } + +out: +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + mali_pm_domain_unlock_state(group->pm_domain); +#endif + + return err; +} + +static void mali_group_bottom_half_mmu(void * data) +{ + struct mali_group *group = (struct mali_group *)data; + struct mali_mmu_core *mmu = group->mmu; + u32 rawstat; + MALI_DEBUG_CODE(u32 status); + + MALI_DEBUG_ASSERT_POINTER(mmu); + + mali_group_lock(group); + + MALI_DEBUG_ASSERT(NULL == group->parent_group); + + if ( MALI_FALSE == mali_group_power_is_on(group) ) + { + MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", mmu->hw_core.description)); + mali_group_unlock(group); + return; + } + + rawstat = mali_mmu_get_rawstat(mmu); + MALI_DEBUG_CODE(status = mali_mmu_get_status(mmu)); + + MALI_DEBUG_PRINT(4, ("Mali MMU: Bottom half, interrupt 0x%08X, status 0x%08X\n", rawstat, status)); + + if (rawstat & (MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR)) + { + /* An actual page fault has occurred. */ + u32 fault_address = mali_mmu_get_page_fault_addr(mmu); + MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n", + (void*)fault_address, + (status >> 6) & 0x1F, + (status & 32) ? "write" : "read", + mmu->hw_core.description)); + MALI_IGNORE(fault_address); + + mali_group_mmu_page_fault(group); + } + + mali_group_unlock(group); +} + +_mali_osk_errcode_t mali_group_upper_half_gp(void *data) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + struct mali_group *group = (struct mali_group *)data; + struct mali_gp_core *core = group->gp_core; + u32 irq_readout; + +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + if (MALI_FALSE == mali_pm_domain_lock_state(group->pm_domain)) + { + goto out; + } +#endif + + irq_readout = mali_gp_get_int_stat(core); + + if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout) + { + /* Mask out all IRQs from this core until IRQ is handled */ + mali_gp_mask_all_interrupts(core); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); + + /* We do need to handle this in a bottom half */ + _mali_osk_wq_schedule_work(group->bottom_half_work_gp); + + err = _MALI_OSK_ERR_OK; + goto out; + } + +out: +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + mali_pm_domain_unlock_state(group->pm_domain); +#endif + + return err; +} + +static void mali_group_bottom_half_gp(void *data) +{ + struct mali_group *group = (struct mali_group *)data; + u32 irq_readout; + u32 irq_errors; + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(0), 0, 0); + + mali_group_lock(group); + + if ( MALI_FALSE == mali_group_power_is_on(group) ) + { + MALI_PRINT_ERROR(("Mali group: Interrupt bottom half of %s when core is OFF.", mali_gp_get_hw_core_desc(group->gp_core))); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + irq_readout = mali_gp_read_rawstat(group->gp_core); + + MALI_DEBUG_PRINT(4, ("Mali group: GP bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_gp_get_hw_core_desc(group->gp_core))); + + if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST)) + { + u32 core_status = mali_gp_read_core_status(group->gp_core); + if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE)) + { + MALI_DEBUG_PRINT(4, ("Mali group: GP job completed, calling group handler\n")); + group->core_timed_out = MALI_FALSE; + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + mali_group_complete_gp(group, MALI_TRUE); + mali_group_unlock(group); + return; + } + } + + /* + * Now lets look at the possible error cases (IRQ indicating error or timeout) + * END_CMD_LST, HANG and PLBU_OOM interrupts are not considered error. + */ + irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM); + if (0 != irq_errors) + { + MALI_PRINT_ERROR(("Mali group: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, mali_gp_get_hw_core_desc(group->gp_core))); + group->core_timed_out = MALI_FALSE; + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + mali_group_complete_gp(group, MALI_FALSE); + mali_group_unlock(group); + return; + } + else if (group->core_timed_out) /* SW timeout */ + { + group->core_timed_out = MALI_FALSE; + if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->gp_running_job) + { + MALI_PRINT(("Mali group: Job %d timed out\n", mali_gp_job_get_id(group->gp_running_job))); + mali_group_complete_gp(group, MALI_FALSE); + mali_group_unlock(group); + return; + } + } + else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) + { + /* GP wants more memory in order to continue. */ + MALI_DEBUG_PRINT(3, ("Mali group: PLBU needs more heap memory\n")); + + group->state = MALI_GROUP_STATE_OOM; + mali_group_unlock(group); /* Nothing to do on the HW side, so just release group lock right away */ + mali_gp_scheduler_oom(group, group->gp_running_job); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + /* + * The only way to get here is if we only got one of two needed END_CMD_LST + * interrupts. Enable all but not the complete interrupt that has been + * received and continue to run. + */ + mali_gp_enable_interrupts(group->gp_core, irq_readout & (MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST)); + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); +} + +static void mali_group_post_process_job_gp(struct mali_group *group, mali_bool suspend) +{ + /* Stop the timeout timer. */ + _mali_osk_timer_del_async(group->timeout_timer); + + if (NULL == group->gp_running_job) + { + /* Nothing to do */ + return; + } + + mali_gp_update_performance_counters(group->gp_core, group->gp_running_job, suspend); + +#if defined(CONFIG_MALI400_PROFILING) + if (suspend) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), + mali_gp_job_get_perf_counter_value0(group->gp_running_job), + mali_gp_job_get_perf_counter_value1(group->gp_running_job), + mali_gp_job_get_perf_counter_src0(group->gp_running_job) | (mali_gp_job_get_perf_counter_src1(group->gp_running_job) << 8), + 0, 0); + } + else + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), + mali_gp_job_get_perf_counter_value0(group->gp_running_job), + mali_gp_job_get_perf_counter_value1(group->gp_running_job), + mali_gp_job_get_perf_counter_src0(group->gp_running_job) | (mali_gp_job_get_perf_counter_src1(group->gp_running_job) << 8), + 0, 0); + + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + mali_group_report_l2_cache_counters_per_core(group, 0); + } +#endif + + mali_gp_job_set_current_heap_addr(group->gp_running_job, + mali_gp_read_plbu_alloc_start_addr(group->gp_core)); +} + +_mali_osk_errcode_t mali_group_upper_half_pp(void *data) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + struct mali_group *group = (struct mali_group *)data; + struct mali_pp_core *core = group->pp_core; + u32 irq_readout; + +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + if (MALI_FALSE == mali_pm_domain_lock_state(group->pm_domain)) + { + goto out; + } +#endif + + /* + * For Mali-450 there is one particular case we need to watch out for: + * + * Criteria 1) this function call can be due to a shared interrupt, + * and not necessary because this core signaled an interrupt. + * Criteria 2) this core is a part of a virtual group, and thus it should + * not do any post processing. + * Criteria 3) this core has actually indicated that is has completed by + * having set raw_stat/int_stat registers to != 0 + * + * If all this criteria is meet, then we could incorrectly start post + * processing on the wrong group object (this should only happen on the + * parent group) + */ +#if !defined(MALI_UPPER_HALF_SCHEDULING) + if (mali_group_is_in_virtual(group)) + { + /* + * This check is done without the group lock held, which could lead to + * a potential race. This is however ok, since we will safely re-check + * this with the group lock held at a later stage. This is just an + * early out which will strongly benefit shared IRQ systems. + */ + err = _MALI_OSK_ERR_OK; + goto out; + } +#endif + + irq_readout = mali_pp_get_int_stat(core); + if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout) + { + /* Mask out all IRQs from this core until IRQ is handled */ + mali_pp_mask_all_interrupts(core); + +#if defined(CONFIG_MALI400_PROFILING) + /* Currently no support for this interrupt event for the virtual PP core */ + if (!mali_group_is_virtual(group)) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | + MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, + irq_readout, 0, 0, 0, 0); + } +#endif + +#if defined(MALI_UPPER_HALF_SCHEDULING) + /* Check if job is complete without errors */ + if (MALI200_REG_VAL_IRQ_END_OF_FRAME == irq_readout) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF, + 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + + MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler from upper half\n")); + + mali_group_lock(group); + + /* Check if job is complete without errors, again, after taking the group lock */ + irq_readout = mali_pp_read_rawstat(core); + if (MALI200_REG_VAL_IRQ_END_OF_FRAME != irq_readout) + { + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF, + 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + err = _MALI_OSK_ERR_OK; + goto out; + } + + if (mali_group_is_virtual(group)) + { + u32 status_readout = mali_pp_read_status(group->pp_core); + if (status_readout & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE) + { + MALI_DEBUG_PRINT(6, ("Mali PP: Not all cores in broadcast completed\n")); + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF, + 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + err = _MALI_OSK_ERR_OK; + goto out; + } + } + + if (mali_group_is_in_virtual(group)) + { + /* We're member of a virtual group, so interrupt should be handled by the virtual group */ + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF, + 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + err = _MALI_OSK_ERR_FAULT; + goto out; + } + + group->core_timed_out = MALI_FALSE; + mali_group_complete_pp(group, MALI_TRUE); + /* No need to enable interrupts again, since the core will be reset while completing the job */ + + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF, + 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + + err = _MALI_OSK_ERR_OK; + goto out; + } +#endif + + /* We do need to handle this in a bottom half */ + _mali_osk_wq_schedule_work(group->bottom_half_work_pp); + err = _MALI_OSK_ERR_OK; + goto out; + } + +out: +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + mali_pm_domain_unlock_state(group->pm_domain); +#endif + + return err; +} + +static void mali_group_bottom_half_pp(void *data) +{ + struct mali_group *group = (struct mali_group *)data; + struct mali_pp_core *core = group->pp_core; + u32 irq_readout; + u32 irq_errors; + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + + mali_group_lock(group); + + if (mali_group_is_in_virtual(group)) + { + /* We're member of a virtual group, so interrupt should be handled by the virtual group */ + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + if ( MALI_FALSE == mali_group_power_is_on(group) ) + { + MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", mali_pp_get_hw_core_desc(core))); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + irq_readout = mali_pp_read_rawstat(group->pp_core); + + MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_pp_get_hw_core_desc(group->pp_core))); + + /* Check if job is complete without errors */ + if (MALI200_REG_VAL_IRQ_END_OF_FRAME == irq_readout) + { + if (mali_group_is_virtual(group)) + { + u32 status_readout = mali_pp_read_status(group->pp_core); + + if (status_readout & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE) + { + MALI_DEBUG_PRINT(6, ("Mali PP: Not all cores in broadcast completed\n")); + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + } + + MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n")); + group->core_timed_out = MALI_FALSE; + mali_group_complete_pp(group, MALI_TRUE); + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + /* + * Now lets look at the possible error cases (IRQ indicating error or timeout) + * END_OF_FRAME and HANG interrupts are not considered error. + */ + irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG); + if (0 != irq_errors) + { + MALI_PRINT_ERROR(("Mali PP: Unexpected interrupt 0x%08X from core %s, aborting job\n", + irq_readout, mali_pp_get_hw_core_desc(group->pp_core))); + group->core_timed_out = MALI_FALSE; + mali_group_complete_pp(group, MALI_FALSE); + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + else if (group->core_timed_out) /* SW timeout */ + { + group->core_timed_out = MALI_FALSE; + if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->pp_running_job) + { + MALI_PRINT(("Mali PP: Job %d timed out on core %s\n", + mali_pp_job_get_id(group->pp_running_job), mali_pp_get_hw_core_desc(core))); + mali_group_complete_pp(group, MALI_FALSE); + mali_group_unlock(group); + } + else + { + mali_group_unlock(group); + } + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + /* + * We should never get here, re-enable interrupts and continue + */ + if (0 == irq_readout) + { + MALI_DEBUG_PRINT(3, ("Mali group: No interrupt found on core %s\n", + mali_pp_get_hw_core_desc(group->pp_core))); + } + else + { + MALI_PRINT_ERROR(("Mali group: Unhandled PP interrupt 0x%08X on %s\n", irq_readout, + mali_pp_get_hw_core_desc(group->pp_core))); + } + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); +} + +static void mali_group_post_process_job_pp(struct mali_group *group) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + /* Stop the timeout timer. */ + _mali_osk_timer_del_async(group->timeout_timer); + + if (NULL != group->pp_running_job) + { + if (MALI_TRUE == mali_group_is_virtual(group)) + { + struct mali_group *child; + struct mali_group *temp; + + /* update performance counters from each physical pp core within this virtual group */ + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + mali_pp_update_performance_counters(group->pp_core, child->pp_core, group->pp_running_job, mali_pp_core_get_id(child->pp_core)); + } + +#if defined(CONFIG_MALI400_PROFILING) + /* send profiling data per physical core */ + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))| + MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL, + mali_pp_job_get_perf_counter_value0(group->pp_running_job, mali_pp_core_get_id(child->pp_core)), + mali_pp_job_get_perf_counter_value1(group->pp_running_job, mali_pp_core_get_id(child->pp_core)), + mali_pp_job_get_perf_counter_src0(group->pp_running_job) | (mali_pp_job_get_perf_counter_src1(group->pp_running_job) << 8), + 0, 0); + } + if (0 != group->l2_cache_core_ref_count[0]) + { + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0])); + } + } + if (0 != group->l2_cache_core_ref_count[1]) + { + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[1])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[1]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[1])); + } + } + +#endif + } + else + { + /* update performance counters for a physical group's pp core */ + mali_pp_update_performance_counters(group->pp_core, group->pp_core, group->pp_running_job, group->pp_running_sub_job); + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))| + MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL, + mali_pp_job_get_perf_counter_value0(group->pp_running_job, group->pp_running_sub_job), + mali_pp_job_get_perf_counter_value1(group->pp_running_job, group->pp_running_sub_job), + mali_pp_job_get_perf_counter_src0(group->pp_running_job) | (mali_pp_job_get_perf_counter_src1(group->pp_running_job) << 8), + 0, 0); + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0])); + } +#endif + } + } +} + +static void mali_group_timeout(void *data) +{ + struct mali_group *group = (struct mali_group *)data; + + group->core_timed_out = MALI_TRUE; + + if (NULL != group->gp_core) + { + MALI_DEBUG_PRINT(2, ("Mali group: TIMEOUT on %s\n", mali_gp_get_hw_core_desc(group->gp_core))); + _mali_osk_wq_schedule_work(group->bottom_half_work_gp); + } + else + { + MALI_DEBUG_PRINT(2, ("Mali group: TIMEOUT on %s\n", mali_pp_get_hw_core_desc(group->pp_core))); + _mali_osk_wq_schedule_work(group->bottom_half_work_pp); + } +} + +void mali_group_zap_session(struct mali_group *group, struct mali_session_data *session) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT_POINTER(session); + + /* Early out - safe even if mutex is not held */ + if (group->session != session) return; + + mali_group_lock(group); + + mali_group_remove_session_if_unused(group, session); + + if (group->session == session) + { + /* The Zap also does the stall and disable_stall */ + mali_bool zap_success = mali_mmu_zap_tlb(group->mmu); + if (MALI_TRUE != zap_success) + { + MALI_DEBUG_PRINT(2, ("Mali memory unmap failed. Doing pagefault handling.\n")); + mali_group_mmu_page_fault(group); + } + } + + mali_group_unlock(group); +} + +#if defined(CONFIG_MALI400_PROFILING) +static void mali_group_report_l2_cache_counters_per_core(struct mali_group *group, u32 core_num) +{ + u32 source0 = 0; + u32 value0 = 0; + u32 source1 = 0; + u32 value1 = 0; + u32 profiling_channel = 0; + + switch(core_num) + { + case 0: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS; + break; + case 1: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L21_COUNTERS; + break; + case 2: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L22_COUNTERS; + break; + default: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS; + break; + } + + if (0 == core_num) + { + mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1); + } + if (1 == core_num) + { + if (1 == mali_l2_cache_get_id(group->l2_cache_core[0])) + { + mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1); + } + else if (1 == mali_l2_cache_get_id(group->l2_cache_core[1])) + { + mali_l2_cache_core_get_counter_values(group->l2_cache_core[1], &source0, &value0, &source1, &value1); + } + } + if (2 == core_num) + { + if (2 == mali_l2_cache_get_id(group->l2_cache_core[0])) + { + mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1); + } + else if (2 == mali_l2_cache_get_id(group->l2_cache_core[1])) + { + mali_l2_cache_core_get_counter_values(group->l2_cache_core[1], &source0, &value0, &source1, &value1); + } + } + + _mali_osk_profiling_add_event(profiling_channel, source1 << 8 | source0, value0, value1, 0, 0); +} +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ + +mali_bool mali_group_is_enabled(struct mali_group *group) +{ + mali_bool enabled = MALI_TRUE; + + MALI_DEBUG_ASSERT_POINTER(group); + + mali_group_lock(group); + if (MALI_GROUP_STATE_DISABLED == group->state) + { + enabled = MALI_FALSE; + } + mali_group_unlock(group); + + return enabled; +} + +void mali_group_enable(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT( NULL != mali_group_get_pp_core(group) + || NULL != mali_group_get_gp_core(group)); + + if (NULL != mali_group_get_pp_core(group)) + { + mali_pp_scheduler_enable_group(group); + } + else + { + mali_gp_scheduler_enable_group(group); + } +} + +void mali_group_disable(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT( NULL != mali_group_get_pp_core(group) + || NULL != mali_group_get_gp_core(group)); + + if (NULL != mali_group_get_pp_core(group)) + { + mali_pp_scheduler_disable_group(group); + } + else + { + mali_gp_scheduler_disable_group(group); + } +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_group.h b/drivers/gpu/mali400/r3p2/mali/common/mali_group.h new file mode 100644 index 0000000..6a6a777 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_group.h @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_GROUP_H__ +#define __MALI_GROUP_H__ + +#include "linux/jiffies.h" +#include "mali_osk.h" +#include "mali_l2_cache.h" +#include "mali_mmu.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_session.h" + +/* max runtime [ms] for a core job - used by timeout timers */ +#define MAX_RUNTIME 5000 +/** @brief A mali group object represents a MMU and a PP and/or a GP core. + * + */ +#define MALI_MAX_NUMBER_OF_GROUPS 10 + +enum mali_group_core_state +{ + MALI_GROUP_STATE_IDLE, + MALI_GROUP_STATE_WORKING, + MALI_GROUP_STATE_OOM, + MALI_GROUP_STATE_IN_VIRTUAL, + MALI_GROUP_STATE_JOINING_VIRTUAL, + MALI_GROUP_STATE_LEAVING_VIRTUAL, + MALI_GROUP_STATE_DISABLED, +}; + +/* Forward declaration from mali_pm_domain.h */ +struct mali_pm_domain; + +/** + * The structure represents a render group + * A render group is defined by all the cores that share the same Mali MMU + */ + +struct mali_group +{ + struct mali_mmu_core *mmu; + struct mali_session_data *session; + int page_dir_ref_count; + + mali_bool power_is_on; + enum mali_group_core_state state; + + struct mali_gp_core *gp_core; + struct mali_gp_job *gp_running_job; + + struct mali_pp_core *pp_core; + struct mali_pp_job *pp_running_job; + u32 pp_running_sub_job; + + struct mali_l2_cache_core *l2_cache_core[2]; + u32 l2_cache_core_ref_count[2]; + + struct mali_dlbu_core *dlbu_core; + struct mali_bcast_unit *bcast_core; + + _mali_osk_lock_t *lock; + + _mali_osk_list_t pp_scheduler_list; + + /* List used for virtual groups. For a virtual group, the list represents the + * head element. */ + _mali_osk_list_t group_list; + + struct mali_group *pm_domain_list; + struct mali_pm_domain *pm_domain; + + /* Parent virtual group (if any) */ + struct mali_group *parent_group; + + _mali_osk_wq_work_t *bottom_half_work_mmu; + _mali_osk_wq_work_t *bottom_half_work_gp; + _mali_osk_wq_work_t *bottom_half_work_pp; + + _mali_osk_timer_t *timeout_timer; + mali_bool core_timed_out; +}; + +/** @brief Create a new Mali group object + * + * @param cluster Pointer to the cluster to which the group is connected. + * @param mmu Pointer to the MMU that defines this group + * @return A pointer to a new group object + */ +struct mali_group *mali_group_create(struct mali_l2_cache_core *core, + struct mali_dlbu_core *dlbu, + struct mali_bcast_unit *bcast); + +_mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group, struct mali_mmu_core* mmu_core); +void mali_group_remove_mmu_core(struct mali_group *group); + +_mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core); +void mali_group_remove_gp_core(struct mali_group *group); + +_mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core); +void mali_group_remove_pp_core(struct mali_group *group); + +void mali_group_set_pm_domain(struct mali_group *group, struct mali_pm_domain *domain); + +void mali_group_delete(struct mali_group *group); + +/** @brief Virtual groups */ +void mali_group_add_group(struct mali_group *parent, struct mali_group *child, mali_bool update_hw); +void mali_group_remove_group(struct mali_group *parent, struct mali_group *child); +struct mali_group *mali_group_acquire_group(struct mali_group *parent); + +MALI_STATIC_INLINE mali_bool mali_group_is_virtual(struct mali_group *group) +{ + return (NULL != group->dlbu_core); +} + +/** @brief Check if a group is considered as part of a virtual group + * + * @note A group is considered to be "part of" a virtual group also during the transition + * in to / out of the virtual group. + */ +MALI_STATIC_INLINE mali_bool mali_group_is_in_virtual(struct mali_group *group) +{ + return (MALI_GROUP_STATE_IN_VIRTUAL == group->state || + MALI_GROUP_STATE_JOINING_VIRTUAL == group->state || + MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state); +} + +/** @brief Reset group + * + * This function will reset the entire group, including all the cores present in the group. + * + * @param group Pointer to the group to reset + */ +void mali_group_reset(struct mali_group *group); + +/** @brief Zap MMU TLB on all groups + * + * Zap TLB on group if \a session is active. + */ +void mali_group_zap_session(struct mali_group* group, struct mali_session_data *session); + +/** @brief Get pointer to GP core object + */ +struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group); + +/** @brief Get pointer to PP core object + */ +struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group); + +/** @brief Lock group object + * + * Most group functions will lock the group object themselves. The expection is + * the group_bottom_half which requires the group to be locked on entry. + * + * @param group Pointer to group to lock + */ +void mali_group_lock(struct mali_group *group); + +/** @brief Unlock group object + * + * @param group Pointer to group to unlock + */ +void mali_group_unlock(struct mali_group *group); +#ifdef DEBUG +void mali_group_assert_locked(struct mali_group *group); +#define MALI_ASSERT_GROUP_LOCKED(group) mali_group_assert_locked(group) +#else +#define MALI_ASSERT_GROUP_LOCKED(group) +#endif + +/** @brief Start GP job + */ +void mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job); +/** @brief Start fragment of PP job + */ +void mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job); + +/** @brief Resume GP job that suspended waiting for more heap memory + */ +struct mali_gp_job *mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr); +/** @brief Abort GP job + * + * Used to abort suspended OOM jobs when user space failed to allocte more memory. + */ +void mali_group_abort_gp_job(struct mali_group *group, u32 job_id); +/** @brief Abort all GP jobs from \a session + * + * Used on session close when terminating all running and queued jobs from \a session. + */ +void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session); + +mali_bool mali_group_power_is_on(struct mali_group *group); +void mali_group_power_on_group(struct mali_group *group); +void mali_group_power_off_group(struct mali_group *group); +void mali_group_power_on(void); +void mali_group_power_off(void); + +struct mali_group *mali_group_get_glob_group(u32 index); +u32 mali_group_get_glob_num_groups(void); + +u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size); + +/* MMU-related functions */ +_mali_osk_errcode_t mali_group_upper_half_mmu(void * data); + +/* GP-related functions */ +_mali_osk_errcode_t mali_group_upper_half_gp(void *data); + +/* PP-related functions */ +_mali_osk_errcode_t mali_group_upper_half_pp(void *data); + +/** @brief Check if group is enabled + * + * @param group group to check + * @return MALI_TRUE if enabled, MALI_FALSE if not + */ +mali_bool mali_group_is_enabled(struct mali_group *group); + +/** @brief Enable group + * + * An enabled job is put on the idle scheduler list and can be used to handle jobs. Does nothing if + * group is already enabled. + * + * @param group group to enable + */ +void mali_group_enable(struct mali_group *group); + +/** @brief Disable group + * + * A disabled group will no longer be used by the scheduler. If part of a virtual group, the group + * will be removed before being disabled. Cores part of a disabled group is safe to power down. + * + * @param group group to disable + */ +void mali_group_disable(struct mali_group *group); + +MALI_STATIC_INLINE mali_bool mali_group_virtual_disable_if_empty(struct mali_group *group) +{ + mali_bool empty = MALI_FALSE; + + MALI_ASSERT_GROUP_LOCKED(group); + MALI_DEBUG_ASSERT(mali_group_is_virtual(group)); + + if (_mali_osk_list_empty(&group->group_list)) + { + group->state = MALI_GROUP_STATE_DISABLED; + group->session = NULL; + + empty = MALI_TRUE; + } + + return empty; +} + +MALI_STATIC_INLINE mali_bool mali_group_virtual_enable_if_empty(struct mali_group *group) +{ + mali_bool empty = MALI_FALSE; + + MALI_ASSERT_GROUP_LOCKED(group); + MALI_DEBUG_ASSERT(mali_group_is_virtual(group)); + + if (_mali_osk_list_empty(&group->group_list)) + { + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state); + + group->state = MALI_GROUP_STATE_IDLE; + + empty = MALI_TRUE; + } + + return empty; +} + +#endif /* __MALI_GROUP_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.c b/drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.c new file mode 100644 index 0000000..c3a9c8b --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_hw_core.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" + +_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size) +{ + core->phys_addr = resource->base; + core->description = resource->description; + core->size = reg_size; + + if (_MALI_OSK_ERR_OK == _mali_osk_mem_reqregion(core->phys_addr, core->size, core->description)) + { + core->mapped_registers = _mali_osk_mem_mapioregion(core->phys_addr, core->size, core->description); + if (NULL != core->mapped_registers) + { + return _MALI_OSK_ERR_OK; + } + else + { + MALI_PRINT_ERROR(("Failed to map memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr)); + } + _mali_osk_mem_unreqregion(core->phys_addr, core->size); + } + else + { + MALI_PRINT_ERROR(("Failed to request memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr)); + } + + return _MALI_OSK_ERR_FAULT; +} + +void mali_hw_core_delete(struct mali_hw_core *core) +{ + _mali_osk_mem_unmapioregion(core->phys_addr, core->size, core->mapped_registers); + core->mapped_registers = NULL; + _mali_osk_mem_unreqregion(core->phys_addr, core->size); +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.h b/drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.h new file mode 100644 index 0000000..e687f60 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_HW_CORE_H__ +#define __MALI_HW_CORE_H__ + +#include "mali_osk.h" +#include "mali_kernel_common.h" + +/** + * The common parts for all Mali HW cores (GP, PP, MMU, L2 and PMU) + * This struct is embedded inside all core specific structs. + */ +struct mali_hw_core +{ + u32 phys_addr; /**< Physical address of the registers */ + u32 size; /**< Size of registers */ + mali_io_address mapped_registers; /**< Virtual mapping of the registers */ + const char* description; /**< Name of unit (as specified in device configuration) */ +}; + +#define MALI_REG_POLL_COUNT_FAST 1000 +#define MALI_REG_POLL_COUNT_SLOW 1000000 + +_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size); +void mali_hw_core_delete(struct mali_hw_core *core); + +MALI_STATIC_INLINE u32 mali_hw_core_register_read(struct mali_hw_core *core, u32 relative_address) +{ + u32 read_val; + read_val = _mali_osk_mem_ioread32(core->mapped_registers, relative_address); + MALI_DEBUG_PRINT(6, ("register_read for core %s, relative addr=0x%04X, val=0x%08X\n", + core->description, relative_address, read_val)); + return read_val; +} + +MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed(struct mali_hw_core *core, u32 relative_address, u32 new_val) +{ + MALI_DEBUG_PRINT(6, ("register_write_relaxed for core %s, relative addr=0x%04X, val=0x%08X\n", + core->description, relative_address, new_val)); + _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val); +} + +/* Conditionally write a register. + * The register will only be written if the new value is different from the old_value. + * If the new value is different, the old value will also be updated */ +MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed_conditional(struct mali_hw_core *core, u32 relative_address, u32 new_val, const u32 old_val) +{ + MALI_DEBUG_PRINT(6, ("register_write_relaxed for core %s, relative addr=0x%04X, val=0x%08X\n", + core->description, relative_address, new_val)); + if(old_val != new_val) + { + _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val); + } +} + + +MALI_STATIC_INLINE void mali_hw_core_register_write(struct mali_hw_core *core, u32 relative_address, u32 new_val) +{ + MALI_DEBUG_PRINT(6, ("register_write for core %s, relative addr=0x%04X, val=0x%08X\n", + core->description, relative_address, new_val)); + _mali_osk_mem_iowrite32(core->mapped_registers, relative_address, new_val); +} + +MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed(struct mali_hw_core *core, u32 relative_address, u32 *write_array, u32 nr_of_regs) +{ + u32 i; + MALI_DEBUG_PRINT(6, ("register_write_array: for core %s, relative addr=0x%04X, nr of regs=%u\n", + core->description,relative_address, nr_of_regs)); + + /* Do not use burst writes against the registers */ + for (i = 0; i< nr_of_regs; i++) + { + mali_hw_core_register_write_relaxed(core, relative_address + i*4, write_array[i]); + } +} + +/* Conditionally write a set of registers. + * The register will only be written if the new value is different from the old_value. + * If the new value is different, the old value will also be updated */ +MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed_conditional(struct mali_hw_core *core, u32 relative_address, u32 *write_array, u32 nr_of_regs, const u32* old_array) +{ + u32 i; + MALI_DEBUG_PRINT(6, ("register_write_array: for core %s, relative addr=0x%04X, nr of regs=%u\n", + core->description,relative_address, nr_of_regs)); + + /* Do not use burst writes against the registers */ + for (i = 0; i< nr_of_regs; i++) + { + if(old_array[i] != write_array[i]) + { + mali_hw_core_register_write_relaxed(core, relative_address + i*4, write_array[i]); + } + } +} + +#endif /* __MALI_HW_CORE_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_common.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_common.h new file mode 100644 index 0000000..3376a07 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_common.h @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_COMMON_H__ +#define __MALI_KERNEL_COMMON_H__ + +#include "mali_osk.h" + +/* Make sure debug is defined when it should be */ +#ifndef DEBUG + #if defined(_DEBUG) + #define DEBUG + #endif +#endif + +/* MALI_SEC */ +/* Macro for generating a kernel panic. + * Turned on off by compile-time Makefile settings + */ +#if defined(USING_KERNEL_PANIC) +#include + #define MALI_PANIC(fmt, args...) panic( fmt, ## args ); +#else + #define MALI_PANIC(fmt, args...) +#endif + +/* The file include several useful macros for error checking, debugging and printing. + * - MALI_PRINTF(...) Do not use this function: Will be included in Release builds. + * - MALI_DEBUG_PRINT(nr, (X) ) Prints the second argument if nr<=MALI_DEBUG_LEVEL. + * - MALI_DEBUG_ERROR( (X) ) Prints an errortext, a source trace, and the given error message. + * - MALI_DEBUG_ASSERT(exp,(X)) If the asserted expr is false, the program will exit. + * - MALI_DEBUG_ASSERT_POINTER(pointer) Triggers if the pointer is a zero pointer. + * - MALI_DEBUG_CODE( X ) The code inside the macro is only compiled in Debug builds. + * + * The (X) means that you must add an extra parenthesis around the argumentlist. + * + * The printf function: MALI_PRINTF(...) is routed to _mali_osk_debugmsg + * + * Suggested range for the DEBUG-LEVEL is [1:6] where + * [1:2] Is messages with highest priority, indicate possible errors. + * [3:4] Is messages with medium priority, output important variables. + * [5:6] Is messages with low priority, used during extensive debugging. + */ + + /** + * Fundamental error macro. Reports an error code. This is abstracted to allow us to + * easily switch to a different error reporting method if we want, and also to allow + * us to search for error returns easily. + * + * Note no closing semicolon - this is supplied in typical usage: + * + * MALI_ERROR(MALI_ERROR_OUT_OF_MEMORY); + */ +#define MALI_ERROR(error_code) return (error_code) + +/** + * Basic error macro, to indicate success. + * Note no closing semicolon - this is supplied in typical usage: + * + * MALI_SUCCESS; + */ +#define MALI_SUCCESS MALI_ERROR(_MALI_OSK_ERR_OK) + +/** + * Basic error macro. This checks whether the given condition is true, and if not returns + * from this function with the supplied error code. This is a macro so that we can override it + * for stress testing. + * + * Note that this uses the do-while-0 wrapping to ensure that we don't get problems with dangling + * else clauses. Note also no closing semicolon - this is supplied in typical usage: + * + * MALI_CHECK((p!=NULL), ERROR_NO_OBJECT); + */ +#define MALI_CHECK(condition, error_code) do { if(!(condition)) MALI_ERROR(error_code); } while(0) + +/** + * Error propagation macro. If the expression given is anything other than _MALI_OSK_NO_ERROR, + * then the value is returned from the enclosing function as an error code. This effectively + * acts as a guard clause, and propagates error values up the call stack. This uses a + * temporary value to ensure that the error expression is not evaluated twice. + * If the counter for forcing a failure has been set using _mali_force_error, this error will be + * returned without evaluating the expression in MALI_CHECK_NO_ERROR + */ +#define MALI_CHECK_NO_ERROR(expression) \ + do { _mali_osk_errcode_t _check_no_error_result=(expression); \ + if(_check_no_error_result != _MALI_OSK_ERR_OK) \ + MALI_ERROR(_check_no_error_result); \ + } while(0) + +/** + * Pointer check macro. Checks non-null pointer. + */ +#define MALI_CHECK_NON_NULL(pointer, error_code) MALI_CHECK( ((pointer)!=NULL), (error_code) ) + +/** + * Error macro with goto. This checks whether the given condition is true, and if not jumps + * to the specified label using a goto. The label must therefore be local to the function in + * which this macro appears. This is most usually used to execute some clean-up code before + * exiting with a call to ERROR. + * + * Like the other macros, this is a macro to allow us to override the condition if we wish, + * e.g. to force an error during stress testing. + */ +#define MALI_CHECK_GOTO(condition, label) do { if(!(condition)) goto label; } while(0) + +/** + * Explicitly ignore a parameter passed into a function, to suppress compiler warnings. + * Should only be used with parameter names. + */ +#define MALI_IGNORE(x) x=x + +#define MALI_PRINTF(args) _mali_osk_dbgmsg args; + +#define MALI_PRINT_ERROR(args) do{ \ + MALI_PRINTF(("Mali: ERR: %s\n" ,__FILE__)); \ + MALI_PRINTF((" %s()%4d\n ", __FUNCTION__, __LINE__)) ; \ + MALI_PRINTF(args); \ + MALI_PRINTF(("\n")); \ + } while(0) + +#define MALI_PRINT(args) do{ \ + MALI_PRINTF(("Mali: ")); \ + MALI_PRINTF(args); \ + } while (0) + +#ifdef DEBUG +#ifndef mali_debug_level +extern int mali_debug_level; +#endif + +#define MALI_DEBUG_CODE(code) code +#define MALI_DEBUG_PRINT(level, args) do { \ + if((level) <= mali_debug_level)\ + {MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); } \ + } while (0) + +#define MALI_DEBUG_PRINT_ERROR(args) MALI_PRINT_ERROR(args) + +#define MALI_DEBUG_PRINT_IF(level,condition,args) \ + if((condition)&&((level) <= mali_debug_level))\ + {MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); } + +#define MALI_DEBUG_PRINT_ELSE(level, args)\ + else if((level) <= mali_debug_level)\ + { MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); } + +/** + * @note these variants of DEBUG ASSERTS will cause a debugger breakpoint + * to be entered (see _mali_osk_break() ). An alternative would be to call + * _mali_osk_abort(), on OSs that support it. + */ +#define MALI_DEBUG_PRINT_ASSERT(condition, args) do {if( !(condition)) { MALI_PRINT_ERROR(args); _mali_osk_break(); } } while(0) +#define MALI_DEBUG_ASSERT_POINTER(pointer) do {if( (pointer)== NULL) {MALI_PRINT_ERROR(("NULL pointer " #pointer)); _mali_osk_break();} } while(0) +#define MALI_DEBUG_ASSERT(condition) do {if( !(condition)) {MALI_PRINT_ERROR(("ASSERT failed: " #condition )); _mali_osk_break();} } while(0) + +#else /* DEBUG */ + +#define MALI_DEBUG_CODE(code) +#define MALI_DEBUG_PRINT(string,args) do {} while(0) +#define MALI_DEBUG_PRINT_ERROR(args) do {} while(0) +#define MALI_DEBUG_PRINT_IF(level,condition,args) do {} while(0) +#define MALI_DEBUG_PRINT_ELSE(level,condition,args) do {} while(0) +#define MALI_DEBUG_PRINT_ASSERT(condition,args) do {} while(0) +#define MALI_DEBUG_ASSERT_POINTER(pointer) do {} while(0) +#define MALI_DEBUG_ASSERT(condition) do {} while(0) + +#endif /* DEBUG */ + +/** + * variables from user space cannot be dereferenced from kernel space; tagging them + * with __user allows the GCC compiler to generate a warning. Other compilers may + * not support this so we define it here as an empty macro if the compiler doesn't + * define it. + */ +#ifndef __user +#define __user +#endif + +#endif /* __MALI_KERNEL_COMMON_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.c new file mode 100644 index 0000000..5680374 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.c @@ -0,0 +1,1293 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_ukk.h" +#include "mali_kernel_core.h" +#include "mali_memory.h" +#include "mali_mem_validation.h" +#include "mali_mmu.h" +#include "mali_mmu_page_directory.h" +#include "mali_dlbu.h" +#include "mali_broadcast.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" +#include "mali_group.h" +#include "mali_pm.h" +#include "mali_pmu.h" +#include "mali_scheduler.h" +#include "mali_kernel_utilization.h" +#include "mali_l2_cache.h" +#include "mali_pm_domain.h" +#if defined(CONFIG_MALI400_PROFILING) +#include "mali_osk_profiling.h" +#endif +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) +#include "mali_profiling_internal.h" +#endif + + +/* Mali GPU memory. Real values come from module parameter or from device specific data */ +unsigned int mali_dedicated_mem_start = 0; +unsigned int mali_dedicated_mem_size = 0; +unsigned int mali_shared_mem_size = 0; + +/* Frame buffer memory to be accessible by Mali GPU */ +int mali_fb_start = 0; +int mali_fb_size = 0; + +/** Start profiling from module load? */ +int mali_boot_profiling = 0; + +/** Limits for the number of PP cores behind each L2 cache. */ +int mali_max_pp_cores_group_1 = 0xFF; +int mali_max_pp_cores_group_2 = 0xFF; + +int mali_inited_pp_cores_group_1 = 0; +int mali_inited_pp_cores_group_2 = 0; + +static _mali_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN; +static u32 global_gpu_base_address = 0; +static u32 global_gpu_major_version = 0; +static u32 global_gpu_minor_version = 0; + +#define WATCHDOG_MSECS_DEFAULT 4000 /* 4 s */ + +/* timer related */ +int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT; + +static _mali_osk_errcode_t mali_set_global_gpu_base_address(void) +{ + global_gpu_base_address = _mali_osk_resource_base_address(); + if (0 == global_gpu_base_address) + { + return _MALI_OSK_ERR_ITEM_NOT_FOUND; + } + + return _MALI_OSK_ERR_OK; +} + +static u32 mali_get_bcast_id(_mali_osk_resource_t *resource_pp) +{ + switch (resource_pp->base - global_gpu_base_address) + { + case 0x08000: + case 0x20000: /* fall-through for aliased mapping */ + return 0x01; + case 0x0A000: + case 0x22000: /* fall-through for aliased mapping */ + return 0x02; + case 0x0C000: + case 0x24000: /* fall-through for aliased mapping */ + return 0x04; + case 0x0E000: + case 0x26000: /* fall-through for aliased mapping */ + return 0x08; + case 0x28000: + return 0x10; + case 0x2A000: + return 0x20; + case 0x2C000: + return 0x40; + case 0x2E000: + return 0x80; + default: + return 0; + } +} + +static _mali_osk_errcode_t mali_parse_product_info(void) +{ + /* + * Mali-200 has the PP core first, while Mali-300, Mali-400 and Mali-450 have the GP core first. + * Look at the version register for the first PP core in order to determine the GPU HW revision. + */ + + u32 first_pp_offset; + _mali_osk_resource_t first_pp_resource; + + /* Find out where the first PP core is located */ + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x8000, NULL)) + { + /* Mali-300/400/450 */ + first_pp_offset = 0x8000; + } + else + { + /* Mali-200 */ + first_pp_offset = 0x0000; + } + + /* Find the first PP core resource (again) */ + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + first_pp_offset, &first_pp_resource)) + { + /* Create a dummy PP object for this core so that we can read the version register */ + struct mali_group *group = mali_group_create(NULL, NULL, NULL); + if (NULL != group) + { + struct mali_pp_core *pp_core = mali_pp_create(&first_pp_resource, group, MALI_FALSE, mali_get_bcast_id(&first_pp_resource)); + if (NULL != pp_core) + { + u32 pp_version = mali_pp_core_get_version(pp_core); + mali_group_delete(group); + + global_gpu_major_version = (pp_version >> 8) & 0xFF; + global_gpu_minor_version = pp_version & 0xFF; + + switch (pp_version >> 16) + { + case MALI200_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI200; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-200 r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + MALI_PRINT_ERROR(("Mali-200 is not supported by this driver.\n")); + _mali_osk_abort(); + break; + case MALI300_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI300; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-300 r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + break; + case MALI400_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI400; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-400 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + break; + case MALI450_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI450; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-450 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + break; + default: + MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version)); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; + } + else + { + MALI_PRINT_ERROR(("Failed to create initial PP object\n")); + } + } + else + { + MALI_PRINT_ERROR(("Failed to create initial group object\n")); + } + } + else + { + MALI_PRINT_ERROR(("First PP core not specified in config file\n")); + } + + return _MALI_OSK_ERR_FAULT; +} + + +void mali_resource_count(u32 *pp_count, u32 *l2_count) +{ + *pp_count = 0; + *l2_count = 0; + + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x08000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0A000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0C000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0E000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x28000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2A000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2C000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2E000, NULL)) + { + ++(*pp_count); + } + + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, NULL)) + { + ++(*l2_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, NULL)) + { + ++(*l2_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, NULL)) + { + ++(*l2_count); + } +} + +static void mali_delete_groups(void) +{ + while (0 < mali_group_get_glob_num_groups()) + { + mali_group_delete(mali_group_get_glob_group(0)); + } +} + +static void mali_delete_l2_cache_cores(void) +{ + while (0 < mali_l2_cache_core_get_glob_num_l2_cores()) + { + mali_l2_cache_delete(mali_l2_cache_core_get_glob_l2_core(0)); + } +} + +static struct mali_l2_cache_core *mali_create_l2_cache_core(_mali_osk_resource_t *resource) +{ + struct mali_l2_cache_core *l2_cache = NULL; + + if (NULL != resource) + { + + MALI_DEBUG_PRINT(3, ("Found L2 cache %s\n", resource->description)); + + l2_cache = mali_l2_cache_create(resource); + if (NULL == l2_cache) + { + MALI_PRINT_ERROR(("Failed to create L2 cache object\n")); + return NULL; + } + } + MALI_DEBUG_PRINT(3, ("Created L2 cache core object\n")); + + return l2_cache; +} + +static _mali_osk_errcode_t mali_parse_config_l2_cache(void) +{ + struct mali_l2_cache_core *l2_cache = NULL; + + if (mali_is_mali400()) + { + _mali_osk_resource_t l2_resource; + if (_MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_resource)) + { + MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n")); + return _MALI_OSK_ERR_FAULT; + } + + l2_cache = mali_create_l2_cache_core(&l2_resource); + if (NULL == l2_cache) + { + return _MALI_OSK_ERR_FAULT; + } + } + else if (mali_is_mali450()) + { + /* + * L2 for GP at 0x10000 + * L2 for PP0-3 at 0x01000 + * L2 for PP4-7 at 0x11000 (optional) + */ + + _mali_osk_resource_t l2_gp_resource; + _mali_osk_resource_t l2_pp_grp0_resource; + _mali_osk_resource_t l2_pp_grp1_resource; + + /* Make cluster for GP's L2 */ + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, &l2_gp_resource)) + { + MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for GP\n")); + l2_cache = mali_create_l2_cache_core(&l2_gp_resource); + if (NULL == l2_cache) + { + return _MALI_OSK_ERR_FAULT; + } + } + else + { + MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Make cluster for first PP core group */ + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_pp_grp0_resource)) + { + MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 0\n")); + l2_cache = mali_create_l2_cache_core(&l2_pp_grp0_resource); + if (NULL == l2_cache) + { + return _MALI_OSK_ERR_FAULT; + } + mali_pm_domain_add_l2(MALI_PMU_M450_DOM1, l2_cache); + } + else + { + MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for PP group 0 in config file\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Second PP core group is optional, don't fail if we don't find it */ + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, &l2_pp_grp1_resource)) + { + MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 1\n")); + l2_cache = mali_create_l2_cache_core(&l2_pp_grp1_resource); + if (NULL == l2_cache) + { + return _MALI_OSK_ERR_FAULT; + } + mali_pm_domain_add_l2(MALI_PMU_M450_DOM3, l2_cache); + } + } + + return _MALI_OSK_ERR_OK; +} + +static struct mali_group *mali_create_group(struct mali_l2_cache_core *cache, + _mali_osk_resource_t *resource_mmu, + _mali_osk_resource_t *resource_gp, + _mali_osk_resource_t *resource_pp) +{ + struct mali_mmu_core *mmu; + struct mali_group *group; + + MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description)); + + /* Create the group object */ + group = mali_group_create(cache, NULL, NULL); + if (NULL == group) + { + MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description)); + return NULL; + } + + /* Create the MMU object inside group */ + mmu = mali_mmu_create(resource_mmu, group, MALI_FALSE); + if (NULL == mmu) + { + MALI_PRINT_ERROR(("Failed to create MMU object\n")); + mali_group_delete(group); + return NULL; + } + + if (NULL != resource_gp) + { + /* Create the GP core object inside this group */ + struct mali_gp_core *gp_core = mali_gp_create(resource_gp, group); + if (NULL == gp_core) + { + /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ + MALI_PRINT_ERROR(("Failed to create GP object\n")); + mali_group_delete(group); + return NULL; + } + } + + if (NULL != resource_pp) + { + struct mali_pp_core *pp_core; + + /* Create the PP core object inside this group */ + pp_core = mali_pp_create(resource_pp, group, MALI_FALSE, mali_get_bcast_id(resource_pp)); + if (NULL == pp_core) + { + /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ + MALI_PRINT_ERROR(("Failed to create PP object\n")); + mali_group_delete(group); + return NULL; + } + } + + /* Reset group */ + mali_group_lock(group); + mali_group_reset(group); + mali_group_unlock(group); + + return group; +} + +static _mali_osk_errcode_t mali_create_virtual_group(_mali_osk_resource_t *resource_mmu_pp_bcast, + _mali_osk_resource_t *resource_pp_bcast, + _mali_osk_resource_t *resource_dlbu, + _mali_osk_resource_t *resource_bcast) +{ + struct mali_mmu_core *mmu_pp_bcast_core; + struct mali_pp_core *pp_bcast_core; + struct mali_dlbu_core *dlbu_core; + struct mali_bcast_unit *bcast_core; + struct mali_group *group; + + MALI_DEBUG_PRINT(2, ("Starting new virtual group for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description)); + + /* Create the DLBU core object */ + dlbu_core = mali_dlbu_create(resource_dlbu); + if (NULL == dlbu_core) + { + MALI_PRINT_ERROR(("Failed to create DLBU object \n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Create the Broadcast unit core */ + bcast_core = mali_bcast_unit_create(resource_bcast); + if (NULL == bcast_core) + { + MALI_PRINT_ERROR(("Failed to create Broadcast unit object!\n")); + mali_dlbu_delete(dlbu_core); + return _MALI_OSK_ERR_FAULT; + } + + /* Create the group object */ + group = mali_group_create(NULL, dlbu_core, bcast_core); + if (NULL == group) + { + MALI_PRINT_ERROR(("Failed to create group object for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description)); + mali_bcast_unit_delete(bcast_core); + mali_dlbu_delete(dlbu_core); + return _MALI_OSK_ERR_FAULT; + } + + /* Create the MMU object inside group */ + mmu_pp_bcast_core = mali_mmu_create(resource_mmu_pp_bcast, group, MALI_TRUE); + if (NULL == mmu_pp_bcast_core) + { + MALI_PRINT_ERROR(("Failed to create MMU PP broadcast object\n")); + mali_group_delete(group); + return _MALI_OSK_ERR_FAULT; + } + + /* Create the PP core object inside this group */ + pp_bcast_core = mali_pp_create(resource_pp_bcast, group, MALI_TRUE, 0); + if (NULL == pp_bcast_core) + { + /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ + MALI_PRINT_ERROR(("Failed to create PP object\n")); + mali_group_delete(group); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_parse_config_groups(void) +{ + struct mali_group *group; + int cluster_id_gp = 0; + int cluster_id_pp_grp0 = 0; + int cluster_id_pp_grp1 = 0; + int i; + + _mali_osk_resource_t resource_gp; + _mali_osk_resource_t resource_gp_mmu; + _mali_osk_resource_t resource_pp[8]; + _mali_osk_resource_t resource_pp_mmu[8]; + _mali_osk_resource_t resource_pp_mmu_bcast; + _mali_osk_resource_t resource_pp_bcast; + _mali_osk_resource_t resource_dlbu; + _mali_osk_resource_t resource_bcast; + _mali_osk_errcode_t resource_gp_found; + _mali_osk_errcode_t resource_gp_mmu_found; + _mali_osk_errcode_t resource_pp_found[8]; + _mali_osk_errcode_t resource_pp_mmu_found[8]; + _mali_osk_errcode_t resource_pp_mmu_bcast_found; + _mali_osk_errcode_t resource_pp_bcast_found; + _mali_osk_errcode_t resource_dlbu_found; + _mali_osk_errcode_t resource_bcast_found; + + if (!(mali_is_mali400() || mali_is_mali450())) + { + /* No known HW core */ + return _MALI_OSK_ERR_FAULT; + } + + if (mali_is_mali450()) + { + /* Mali-450 have separate L2s for GP, and PP core group(s) */ + cluster_id_pp_grp0 = 1; + cluster_id_pp_grp1 = 2; + } + + resource_gp_found = _mali_osk_resource_find(global_gpu_base_address + 0x00000, &resource_gp); + resource_gp_mmu_found = _mali_osk_resource_find(global_gpu_base_address + 0x03000, &resource_gp_mmu); + resource_pp_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x08000, &(resource_pp[0])); + resource_pp_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x0A000, &(resource_pp[1])); + resource_pp_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x0C000, &(resource_pp[2])); + resource_pp_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x0E000, &(resource_pp[3])); + resource_pp_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x28000, &(resource_pp[4])); + resource_pp_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x2A000, &(resource_pp[5])); + resource_pp_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x2C000, &(resource_pp[6])); + resource_pp_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x2E000, &(resource_pp[7])); + resource_pp_mmu_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x04000, &(resource_pp_mmu[0])); + resource_pp_mmu_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x05000, &(resource_pp_mmu[1])); + resource_pp_mmu_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x06000, &(resource_pp_mmu[2])); + resource_pp_mmu_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x07000, &(resource_pp_mmu[3])); + resource_pp_mmu_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x1C000, &(resource_pp_mmu[4])); + resource_pp_mmu_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x1D000, &(resource_pp_mmu[5])); + resource_pp_mmu_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x1E000, &(resource_pp_mmu[6])); + resource_pp_mmu_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x1F000, &(resource_pp_mmu[7])); + + + if (mali_is_mali450()) + { + resource_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x13000, &resource_bcast); + resource_dlbu_found = _mali_osk_resource_find(global_gpu_base_address + 0x14000, &resource_dlbu); + resource_pp_mmu_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x15000, &resource_pp_mmu_bcast); + resource_pp_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x16000, &resource_pp_bcast); + + if (_MALI_OSK_ERR_OK != resource_bcast_found || + _MALI_OSK_ERR_OK != resource_dlbu_found || + _MALI_OSK_ERR_OK != resource_pp_mmu_bcast_found || + _MALI_OSK_ERR_OK != resource_pp_bcast_found) + { + /* Missing mandatory core(s) for Mali-450 */ + MALI_DEBUG_PRINT(2, ("Missing mandatory resources, Mali-450 needs DLBU, Broadcast unit, virtual PP core and virtual MMU\n")); + return _MALI_OSK_ERR_FAULT; + } + } + + if (_MALI_OSK_ERR_OK != resource_gp_found || + _MALI_OSK_ERR_OK != resource_gp_mmu_found || + _MALI_OSK_ERR_OK != resource_pp_found[0] || + _MALI_OSK_ERR_OK != resource_pp_mmu_found[0]) + { + /* Missing mandatory core(s) */ + MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU\n")); + return _MALI_OSK_ERR_FAULT; + } + + MALI_DEBUG_ASSERT(1 <= mali_l2_cache_core_get_glob_num_l2_cores()); + group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_gp), &resource_gp_mmu, &resource_gp, NULL); + if (NULL == group) + { + return _MALI_OSK_ERR_FAULT; + } + + /* Create group for first (and mandatory) PP core */ + MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= (cluster_id_pp_grp0 + 1)); /* >= 1 on Mali-300 and Mali-400, >= 2 on Mali-450 */ + group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[0], NULL, &resource_pp[0]); + if (NULL == group) + { + return _MALI_OSK_ERR_FAULT; + } + if (mali_is_mali450()) + { + mali_pm_domain_add_group(MALI_PMU_M450_DOM1, group); + } + else + { + mali_pm_domain_add_group(MALI_PMU_M400_PP0, group); + } + mali_inited_pp_cores_group_1++; + + /* Create groups for rest of the cores in the first PP core group */ + for (i = 1; i < 4; i++) /* First half of the PP cores belong to first core group */ + { + if (mali_inited_pp_cores_group_1 < mali_max_pp_cores_group_1) + { + if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i]) + { + group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[i], NULL, &resource_pp[i]); + if (NULL == group) + { + return _MALI_OSK_ERR_FAULT; + } + if (mali_is_mali450()) + { + mali_pm_domain_add_group(MALI_PMU_M450_DOM2, group); + } + else + { + mali_pm_domain_add_group(MALI_PMU_M400_PP0 + i, group); + } + mali_inited_pp_cores_group_1++; + } + } + } + + /* Create groups for cores in the second PP core group */ + for (i = 4; i < 8; i++) /* Second half of the PP cores belong to second core group */ + { + if (mali_inited_pp_cores_group_2 < mali_max_pp_cores_group_2) + { + if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i]) + { + MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= 2); /* Only Mali-450 have a second core group */ + group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp1), &resource_pp_mmu[i], NULL, &resource_pp[i]); + if (NULL == group) + { + return _MALI_OSK_ERR_FAULT; + } + mali_pm_domain_add_group(MALI_PMU_M450_DOM3, group); + mali_inited_pp_cores_group_2++; + } + } + } + + if(mali_is_mali450()) + { + _mali_osk_errcode_t err = mali_create_virtual_group(&resource_pp_mmu_bcast, &resource_pp_bcast, &resource_dlbu, &resource_bcast); + if (_MALI_OSK_ERR_OK != err) + { + return err; + } + } + + mali_max_pp_cores_group_1 = mali_inited_pp_cores_group_1; + mali_max_pp_cores_group_2 = mali_inited_pp_cores_group_2; + MALI_DEBUG_PRINT(2, ("%d+%d PP cores initialized\n", mali_inited_pp_cores_group_1, mali_inited_pp_cores_group_2)); + + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_check_shared_interrupts(void) +{ +#if !defined(CONFIG_MALI_SHARED_INTERRUPTS) + if (MALI_TRUE == _mali_osk_shared_interrupts()) + { + MALI_PRINT_ERROR(("Shared interrupts detected, but driver support is not enabled\n")); + return _MALI_OSK_ERR_FAULT; + } +#endif /* !defined(CONFIG_MALI_SHARED_INTERRUPTS) */ + + /* It is OK to compile support for shared interrupts even if Mali is not using it. */ + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_create_pm_domains(void) +{ + struct mali_pm_domain *domain; + u32 number_of_pp_cores = 0; + u32 number_of_l2_caches = 0; + + mali_resource_count(&number_of_pp_cores, &number_of_l2_caches); + + if (mali_is_mali450()) + { + MALI_DEBUG_PRINT(2, ("Creating PM domains for Mali-450 MP%d\n", number_of_pp_cores)); + switch (number_of_pp_cores) + { + case 8: /* Fall through */ + case 6: /* Fall through */ + domain = mali_pm_domain_create(MALI_PMU_M450_DOM3, MALI_PMU_M450_DOM3_MASK); + MALI_CHECK(NULL != domain, _MALI_OSK_ERR_NOMEM); + case 4: /* Fall through */ + case 3: /* Fall through */ + case 2: /* Fall through */ + domain = mali_pm_domain_create(MALI_PMU_M450_DOM2, MALI_PMU_M450_DOM2_MASK); + MALI_CHECK(NULL != domain, _MALI_OSK_ERR_NOMEM); + domain = mali_pm_domain_create(MALI_PMU_M450_DOM1, MALI_PMU_M450_DOM1_MASK); + MALI_CHECK(NULL != domain, _MALI_OSK_ERR_NOMEM); + + break; + default: + MALI_PRINT_ERROR(("Unsupported core configuration\n")); + MALI_DEBUG_ASSERT(0); + } + } + else + { + int i; + u32 mask = MALI_PMU_M400_PP0_MASK; + + MALI_DEBUG_PRINT(2, ("Creating PM domains for Mali-400 MP%d\n", number_of_pp_cores)); + + MALI_DEBUG_ASSERT(mali_is_mali400()); + + for (i = 0; i < number_of_pp_cores; i++) + { + MALI_CHECK(NULL != mali_pm_domain_create(i, mask), _MALI_OSK_ERR_NOMEM); + + /* Shift mask up, for next core */ + mask = mask << 1; + } + } + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_parse_config_pmu(void) +{ + _mali_osk_resource_t resource_pmu; + + MALI_DEBUG_ASSERT(0 != global_gpu_base_address); + + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x02000, &resource_pmu)) + { + struct mali_pmu_core *pmu; + u32 number_of_pp_cores = 0; + u32 number_of_l2_caches = 0; + + mali_resource_count(&number_of_pp_cores, &number_of_l2_caches); + + pmu = mali_pmu_create(&resource_pmu, number_of_pp_cores, number_of_l2_caches); + if (NULL == pmu) + { + MALI_PRINT_ERROR(("Failed to create PMU\n")); + return _MALI_OSK_ERR_FAULT; + } + } + + /* It's ok if the PMU doesn't exist */ + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_parse_config_memory(void) +{ + _mali_osk_errcode_t ret; + + if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size) + { + /* Memory settings are not overridden by module parameters, so use device settings */ + struct _mali_osk_device_data data = { 0, }; + + if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) + { + /* Use device specific settings (if defined) */ + mali_dedicated_mem_start = data.dedicated_mem_start; + mali_dedicated_mem_size = data.dedicated_mem_size; + mali_shared_mem_size = data.shared_mem_size; + } + + if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size) + { + /* No GPU memory specified */ + return _MALI_OSK_ERR_INVALID_ARGS; + } + + MALI_DEBUG_PRINT(2, ("Using device defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n", + mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size)); + } + else + { + MALI_DEBUG_PRINT(2, ("Using module defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n", + mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size)); + } + + if (0 < mali_dedicated_mem_size && 0 != mali_dedicated_mem_start) + { + /* Dedicated memory */ + ret = mali_memory_core_resource_dedicated_memory(mali_dedicated_mem_start, mali_dedicated_mem_size); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to register dedicated memory\n")); + mali_memory_terminate(); + return ret; + } + } + + if (0 < mali_shared_mem_size) + { + /* Shared OS memory */ + ret = mali_memory_core_resource_os_memory(mali_shared_mem_size); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to register shared OS memory\n")); + mali_memory_terminate(); + return ret; + } + } + + if (0 == mali_fb_start && 0 == mali_fb_size) + { + /* Frame buffer settings are not overridden by module parameters, so use device settings */ + struct _mali_osk_device_data data = { 0, }; + + if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) + { + /* Use device specific settings (if defined) */ + mali_fb_start = data.fb_start; + mali_fb_size = data.fb_size; + } + + MALI_DEBUG_PRINT(2, ("Using device defined frame buffer settings (0x%08X@0x%08X)\n", + mali_fb_size, mali_fb_start)); + } + else + { + MALI_DEBUG_PRINT(2, ("Using module defined frame buffer settings (0x%08X@0x%08X)\n", + mali_fb_size, mali_fb_start)); + } + + if (0 != mali_fb_size) + { + /* Register frame buffer */ + ret = mali_mem_validation_add_range(mali_fb_start, mali_fb_size); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to register frame buffer memory region\n")); + mali_memory_terminate(); + return ret; + } + } + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_initialize_subsystems(void) +{ + _mali_osk_errcode_t err; + struct mali_pmu_core *pmu; + + err = mali_session_initialize(); + if (_MALI_OSK_ERR_OK != err) goto session_init_failed; + +#if defined(CONFIG_MALI400_PROFILING) + err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE); + if (_MALI_OSK_ERR_OK != err) + { + /* No biggie if we weren't able to initialize the profiling */ + MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n")); + } +#endif + + err = mali_memory_initialize(); + if (_MALI_OSK_ERR_OK != err) goto memory_init_failed; + + /* Configure memory early. Memory allocation needed for mali_mmu_initialize. */ + err = mali_parse_config_memory(); + if (_MALI_OSK_ERR_OK != err) goto parse_memory_config_failed; + + err = mali_set_global_gpu_base_address(); + if (_MALI_OSK_ERR_OK != err) goto set_global_gpu_base_address_failed; + + err = mali_check_shared_interrupts(); + if (_MALI_OSK_ERR_OK != err) goto check_shared_interrupts_failed; + + err = mali_pp_scheduler_initialize(); + if (_MALI_OSK_ERR_OK != err) goto pp_scheduler_init_failed; + + /* Initialize the power management module */ + err = mali_pm_initialize(); + if (_MALI_OSK_ERR_OK != err) goto pm_init_failed; + + /* Initialize the MALI PMU */ + err = mali_parse_config_pmu(); + if (_MALI_OSK_ERR_OK != err) goto parse_pmu_config_failed; + + /* Make sure the power stays on for the rest of this function */ + err = _mali_osk_pm_dev_ref_add(); + if (_MALI_OSK_ERR_OK != err) goto pm_always_on_failed; + + /* + * If run-time PM is used, then the mali_pm module has now already been + * notified that the power now is on (through the resume callback functions). + * However, if run-time PM is not used, then there will probably not be any + * calls to the resume callback functions, so we need to explicitly tell it + * that the power is on. + */ + mali_pm_set_power_is_on(); + + /* Reset PMU HW and ensure all Mali power domains are on */ + pmu = mali_pmu_get_global_pmu_core(); + if (NULL != pmu) + { + err = mali_pmu_reset(pmu); + if (_MALI_OSK_ERR_OK != err) goto pmu_reset_failed; + } + + /* Detect which Mali GPU we are dealing with */ + err = mali_parse_product_info(); + if (_MALI_OSK_ERR_OK != err) goto product_info_parsing_failed; + + /* The global_product_id is now populated with the correct Mali GPU */ + + /* Create PM domains only if PMU exists */ + if (NULL != pmu) + { + err = mali_create_pm_domains(); + if (_MALI_OSK_ERR_OK != err) goto pm_domain_failed; + } + + /* Initialize MMU module */ + err = mali_mmu_initialize(); + if (_MALI_OSK_ERR_OK != err) goto mmu_init_failed; + + if (mali_is_mali450()) + { + err = mali_dlbu_initialize(); + if (_MALI_OSK_ERR_OK != err) goto dlbu_init_failed; + } + + /* Start configuring the actual Mali hardware. */ + err = mali_parse_config_l2_cache(); + if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed; + err = mali_parse_config_groups(); + if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed; + + /* Initialize the schedulers */ + err = mali_scheduler_initialize(); + if (_MALI_OSK_ERR_OK != err) goto scheduler_init_failed; + err = mali_gp_scheduler_initialize(); + if (_MALI_OSK_ERR_OK != err) goto gp_scheduler_init_failed; + + /* PP scheduler population can't fail */ + mali_pp_scheduler_populate(); + + /* Initialize the GPU utilization tracking */ + err = mali_utilization_init(); + if (_MALI_OSK_ERR_OK != err) goto utilization_init_failed; + + /* Allowing the system to be turned off */ + _mali_osk_pm_dev_ref_dec(); + + MALI_SUCCESS; /* all ok */ + + /* Error handling */ + +utilization_init_failed: + mali_pp_scheduler_depopulate(); + mali_gp_scheduler_terminate(); +gp_scheduler_init_failed: + mali_scheduler_terminate(); +scheduler_init_failed: +config_parsing_failed: + mali_delete_groups(); /* Delete any groups not (yet) owned by a scheduler */ + mali_delete_l2_cache_cores(); /* Delete L2 cache cores even if config parsing failed. */ +dlbu_init_failed: + mali_dlbu_terminate(); +mmu_init_failed: + mali_pm_domain_terminate(); +pm_domain_failed: + /* Nothing to roll back */ +product_info_parsing_failed: + /* Nothing to roll back */ +pmu_reset_failed: + /* Allowing the system to be turned off */ + _mali_osk_pm_dev_ref_dec(); +pm_always_on_failed: + pmu = mali_pmu_get_global_pmu_core(); + if (NULL != pmu) + { + mali_pmu_delete(pmu); + } +parse_pmu_config_failed: + mali_pm_terminate(); +pm_init_failed: + mali_pp_scheduler_terminate(); +pp_scheduler_init_failed: +check_shared_interrupts_failed: + global_gpu_base_address = 0; +set_global_gpu_base_address_failed: + global_gpu_base_address = 0; +parse_memory_config_failed: + mali_memory_terminate(); +memory_init_failed: +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_term(); +#endif + mali_session_terminate(); +session_init_failed: + return err; +} + +void mali_terminate_subsystems(void) +{ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n")); + + /* shut down subsystems in reverse order from startup */ + + /* We need the GPU to be powered up for the terminate sequence */ + _mali_osk_pm_dev_ref_add(); + + mali_utilization_term(); + mali_pp_scheduler_depopulate(); + mali_gp_scheduler_terminate(); + mali_scheduler_terminate(); + mali_delete_l2_cache_cores(); + if (mali_is_mali450()) + { + mali_dlbu_terminate(); + } + mali_mmu_terminate(); + if (NULL != pmu) + { + mali_pmu_delete(pmu); + } + mali_pm_terminate(); + mali_memory_terminate(); +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_term(); +#endif + + /* Allowing the system to be turned off */ + _mali_osk_pm_dev_ref_dec(); + + mali_pp_scheduler_terminate(); + mali_session_terminate(); +} + +_mali_product_id_t mali_kernel_core_get_product_id(void) +{ + return global_product_id; +} + +u32 mali_kernel_core_get_gpu_major_version(void) +{ + return global_gpu_major_version; +} + +u32 mali_kernel_core_get_gpu_minor_version(void) +{ + return global_gpu_minor_version; +} + +_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args ) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + /* check compatability */ + if ( args->version == _MALI_UK_API_VERSION ) + { + args->compatible = 1; + } + else + { + args->compatible = 0; + } + + args->version = _MALI_UK_API_VERSION; /* report our version */ + + /* success regardless of being compatible or not */ + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args ) +{ + _mali_osk_errcode_t err; + _mali_osk_notification_t * notification; + _mali_osk_notification_queue_t *queue; + + /* check input */ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + queue = ((struct mali_session_data *)args->ctx)->ioctl_queue; + + /* if the queue does not exist we're currently shutting down */ + if (NULL == queue) + { + MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); + args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS; + MALI_SUCCESS; + } + + /* receive a notification, might sleep */ + err = _mali_osk_notification_queue_receive(queue, ¬ification); + if (_MALI_OSK_ERR_OK != err) + { + MALI_ERROR(err); /* errcode returned, pass on to caller */ + } + + /* copy the buffer to the user */ + args->type = (_mali_uk_notification_type)notification->notification_type; + _mali_osk_memcpy(&args->data, notification->result_buffer, notification->result_buffer_size); + + /* finished with the notification */ + _mali_osk_notification_delete( notification ); + + MALI_SUCCESS; /* all ok */ +} + +_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args ) +{ + _mali_osk_notification_t * notification; + _mali_osk_notification_queue_t *queue; + + /* check input */ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + queue = ((struct mali_session_data *)args->ctx)->ioctl_queue; + + /* if the queue does not exist we're currently shutting down */ + if (NULL == queue) + { + MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); + MALI_SUCCESS; + } + + notification = _mali_osk_notification_create(args->type, 0); + if (NULL == notification) + { + MALI_PRINT_ERROR( ("Failed to create notification object\n")); + return _MALI_OSK_ERR_NOMEM; + } + + _mali_osk_notification_queue_send(queue, notification); + + MALI_SUCCESS; /* all ok */ +} + +_mali_osk_errcode_t _mali_ukk_open(void **context) +{ + struct mali_session_data *session; + + /* allocated struct to track this session */ + session = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data)); + MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_NOMEM); + + MALI_DEBUG_PRINT(3, ("Session starting\n")); + + /* create a response queue for this session */ + session->ioctl_queue = _mali_osk_notification_queue_init(); + if (NULL == session->ioctl_queue) + { + _mali_osk_free(session); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + session->page_directory = mali_mmu_pagedir_alloc(); + if (NULL == session->page_directory) + { + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session->page_directory, MALI_DLBU_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE)) + { + MALI_PRINT_ERROR(("Failed to map DLBU page into session\n")); + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + if (0 != mali_dlbu_phys_addr) + { + mali_mmu_pagedir_update(session->page_directory, MALI_DLBU_VIRT_ADDR, mali_dlbu_phys_addr, + _MALI_OSK_MALI_PAGE_SIZE, MALI_CACHE_STANDARD); + } + + if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session)) + { + mali_mmu_pagedir_free(session->page_directory); + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + +#ifdef CONFIG_SYNC + _mali_osk_list_init(&session->pending_jobs); + session->pending_jobs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK, + 0, _MALI_OSK_LOCK_ORDER_SESSION_PENDING_JOBS); + if (NULL == session->pending_jobs_lock) + { + MALI_PRINT_ERROR(("Failed to create pending jobs lock\n")); + mali_memory_session_end(session); + mali_mmu_pagedir_free(session->page_directory); + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } +#endif + + *context = (void*)session; + + /* Add session to the list of all sessions. */ + mali_session_add(session); + + /* Initialize list of jobs on this session */ + _MALI_OSK_INIT_LIST_HEAD(&session->job_list); + + MALI_DEBUG_PRINT(2, ("Session started\n")); + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_close(void **context) +{ + struct mali_session_data *session; + MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS); + session = (struct mali_session_data *)*context; + + MALI_DEBUG_PRINT(3, ("Session ending\n")); + + /* Remove session from list of all sessions. */ + mali_session_remove(session); + + /* Abort pending jobs */ +#ifdef CONFIG_SYNC + { + _mali_osk_list_t tmp_job_list; + struct mali_pp_job *job, *tmp; + _MALI_OSK_INIT_LIST_HEAD(&tmp_job_list); + + _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + /* Abort asynchronous wait on fence. */ + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &session->pending_jobs, struct mali_pp_job, list) + { + MALI_DEBUG_PRINT(2, ("Sync: Aborting wait for session %x job %x\n", session, job)); + if (sync_fence_cancel_async(job->pre_fence, &job->sync_waiter)) + { + MALI_DEBUG_PRINT(2, ("Sync: Failed to abort job %x\n", job)); + } + _mali_osk_list_add(&job->list, &tmp_job_list); + } + _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_wq_flush(); + + _mali_osk_lock_term(session->pending_jobs_lock); + + /* Delete jobs */ + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &tmp_job_list, struct mali_pp_job, list) + { + mali_pp_job_delete(job); + } + } +#endif + + /* Abort queued and running jobs */ + mali_gp_scheduler_abort_session(session); + mali_pp_scheduler_abort_session(session); + + /* Flush pending work. + * Needed to make sure all bottom half processing related to this + * session has been completed, before we free internal data structures. + */ + _mali_osk_wq_flush(); + + /* Free remaining memory allocated to this session */ + mali_memory_session_end(session); + + /* Free session data structures */ + mali_mmu_pagedir_free(session->page_directory); + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + + *context = NULL; + + MALI_DEBUG_PRINT(2, ("Session has ended\n")); + + MALI_SUCCESS; +} + +#if MALI_STATE_TRACKING +u32 _mali_kernel_core_dump_state(char* buf, u32 size) +{ + int n = 0; /* Number of bytes written to buf */ + + n += mali_gp_scheduler_dump_state(buf + n, size - n); + n += mali_pp_scheduler_dump_state(buf + n, size - n); + + return n; +} +#endif diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.h new file mode 100644 index 0000000..bf56b5c --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_CORE_H__ +#define __MALI_KERNEL_CORE_H__ + +#include "mali_osk.h" + +extern int mali_max_job_runtime; + +typedef enum +{ + _MALI_PRODUCT_ID_UNKNOWN, + _MALI_PRODUCT_ID_MALI200, + _MALI_PRODUCT_ID_MALI300, + _MALI_PRODUCT_ID_MALI400, + _MALI_PRODUCT_ID_MALI450, +} _mali_product_id_t; + +_mali_osk_errcode_t mali_initialize_subsystems(void); + +void mali_terminate_subsystems(void); + +_mali_product_id_t mali_kernel_core_get_product_id(void); + +u32 mali_kernel_core_get_gpu_major_version(void); + +u32 mali_kernel_core_get_gpu_minor_version(void); + +u32 _mali_kernel_core_dump_state(char* buf, u32 size); + +MALI_STATIC_INLINE mali_bool mali_is_mali450(void) +{ + return _MALI_PRODUCT_ID_MALI450 == mali_kernel_core_get_product_id(); +} + +MALI_STATIC_INLINE mali_bool mali_is_mali400(void) +{ + u32 id = mali_kernel_core_get_product_id(); + return _MALI_PRODUCT_ID_MALI400 == id || _MALI_PRODUCT_ID_MALI300 == id; +} + +#endif /* __MALI_KERNEL_CORE_H__ */ + diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.c new file mode 100644 index 0000000..b9f05ca --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_kernel_descriptor_mapping.h" +#include "mali_osk.h" +#include "mali_osk_bitops.h" + +#define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1)) + +/** + * Allocate a descriptor table capable of holding 'count' mappings + * @param count Number of mappings in the table + * @return Pointer to a new table, NULL on error + */ +static mali_descriptor_table * descriptor_table_alloc(int count); + +/** + * Free a descriptor table + * @param table The table to free + */ +static void descriptor_table_free(mali_descriptor_table * table); + +mali_descriptor_mapping * mali_descriptor_mapping_create(int init_entries, int max_entries) +{ + mali_descriptor_mapping * map = _mali_osk_calloc(1, sizeof(mali_descriptor_mapping)); + + init_entries = MALI_PAD_INT(init_entries); + max_entries = MALI_PAD_INT(max_entries); + + if (NULL != map) + { + map->table = descriptor_table_alloc(init_entries); + if (NULL != map->table) + { + map->lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP); + if (NULL != map->lock) + { + _mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */ + map->max_nr_mappings_allowed = max_entries; + map->current_nr_mappings = init_entries; + return map; + } + descriptor_table_free(map->table); + } + _mali_osk_free(map); + } + return NULL; +} + +void mali_descriptor_mapping_destroy(mali_descriptor_mapping * map) +{ + descriptor_table_free(map->table); + _mali_osk_lock_term(map->lock); + _mali_osk_free(map); +} + +_mali_osk_errcode_t mali_descriptor_mapping_allocate_mapping(mali_descriptor_mapping * map, void * target, int *odescriptor) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + int new_descriptor; + + MALI_DEBUG_ASSERT_POINTER(map); + MALI_DEBUG_ASSERT_POINTER(odescriptor); + + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + new_descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); + if (new_descriptor == map->current_nr_mappings) + { + /* no free descriptor, try to expand the table */ + mali_descriptor_table * new_table, * old_table; + if (map->current_nr_mappings >= map->max_nr_mappings_allowed) goto unlock_and_exit; + + map->current_nr_mappings += BITS_PER_LONG; + new_table = descriptor_table_alloc(map->current_nr_mappings); + if (NULL == new_table) goto unlock_and_exit; + + old_table = map->table; + _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); + _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); + map->table = new_table; + descriptor_table_free(old_table); + } + + /* we have found a valid descriptor, set the value and usage bit */ + _mali_osk_set_nonatomic_bit(new_descriptor, map->table->usage); + map->table->mappings[new_descriptor] = target; + *odescriptor = new_descriptor; + err = _MALI_OSK_ERR_OK; + +unlock_and_exit: + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); + MALI_ERROR(err); +} + +void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping * map, void (*callback)(int, void*)) +{ + int i; + + MALI_DEBUG_ASSERT_POINTER(map); + MALI_DEBUG_ASSERT_POINTER(callback); + + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + /* id 0 is skipped as it's an reserved ID not mapping to anything */ + for (i = 1; i < map->current_nr_mappings; ++i) + { + if (_mali_osk_test_bit(i, map->table->usage)) + { + callback(i, map->table->mappings[i]); + } + } + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); +} + +_mali_osk_errcode_t mali_descriptor_mapping_get(mali_descriptor_mapping * map, int descriptor, void** target) +{ + _mali_osk_errcode_t result = _MALI_OSK_ERR_FAULT; + MALI_DEBUG_ASSERT_POINTER(map); + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + *target = map->table->mappings[descriptor]; + result = _MALI_OSK_ERR_OK; + } + else *target = NULL; + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); + MALI_ERROR(result); +} + +_mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping * map, int descriptor, void * target) +{ + _mali_osk_errcode_t result = _MALI_OSK_ERR_FAULT; + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + map->table->mappings[descriptor] = target; + result = _MALI_OSK_ERR_OK; + } + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); + MALI_ERROR(result); +} + +void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor) +{ + void *old_value = NULL; + + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + old_value = map->table->mappings[descriptor]; + map->table->mappings[descriptor] = NULL; + _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage); + } + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); + + return old_value; +} + +static mali_descriptor_table * descriptor_table_alloc(int count) +{ + mali_descriptor_table * table; + + table = _mali_osk_calloc(1, sizeof(mali_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count)); + + if (NULL != table) + { + table->usage = (u32*)((u8*)table + sizeof(mali_descriptor_table)); + table->mappings = (void**)((u8*)table + sizeof(mali_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG)); + } + + return table; +} + +static void descriptor_table_free(mali_descriptor_table * table) +{ + _mali_osk_free(table); +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.h new file mode 100644 index 0000000..82ed94d --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_kernel_descriptor_mapping.h + */ + +#ifndef __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ +#define __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ + +#include "mali_osk.h" + +/** + * The actual descriptor mapping table, never directly accessed by clients + */ +typedef struct mali_descriptor_table +{ + u32 * usage; /**< Pointer to bitpattern indicating if a descriptor is valid/used or not */ + void** mappings; /**< Array of the pointers the descriptors map to */ +} mali_descriptor_table; + +/** + * The descriptor mapping object + * Provides a separate namespace where we can map an integer to a pointer + */ +typedef struct mali_descriptor_mapping +{ + _mali_osk_lock_t *lock; /**< Lock protecting access to the mapping object */ + int max_nr_mappings_allowed; /**< Max number of mappings to support in this namespace */ + int current_nr_mappings; /**< Current number of possible mappings */ + mali_descriptor_table * table; /**< Pointer to the current mapping table */ +} mali_descriptor_mapping; + +/** + * Create a descriptor mapping object + * Create a descriptor mapping capable of holding init_entries growable to max_entries + * @param init_entries Number of entries to preallocate memory for + * @param max_entries Number of entries to max support + * @return Pointer to a descriptor mapping object, NULL on failure + */ +mali_descriptor_mapping * mali_descriptor_mapping_create(int init_entries, int max_entries); + +/** + * Destroy a descriptor mapping object + * @param map The map to free + */ +void mali_descriptor_mapping_destroy(mali_descriptor_mapping * map); + +/** + * Allocate a new mapping entry (descriptor ID) + * Allocates a new entry in the map. + * @param map The map to allocate a new entry in + * @param target The value to map to + * @return The descriptor allocated, a negative value on error + */ +_mali_osk_errcode_t mali_descriptor_mapping_allocate_mapping(mali_descriptor_mapping * map, void * target, int *descriptor); + +/** + * Get the value mapped to by a descriptor ID + * @param map The map to lookup the descriptor id in + * @param descriptor The descriptor ID to lookup + * @param target Pointer to a pointer which will receive the stored value + * @return 0 on successful lookup, negative on error + */ +_mali_osk_errcode_t mali_descriptor_mapping_get(mali_descriptor_mapping * map, int descriptor, void** target); + +/** + * Set the value mapped to by a descriptor ID + * @param map The map to lookup the descriptor id in + * @param descriptor The descriptor ID to lookup + * @param target Pointer to replace the current value with + * @return 0 on successful lookup, negative on error + */ +_mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping * map, int descriptor, void * target); + +/** + * Call the specified callback function for each descriptor in map. + * Entire function is mutex protected. + * @param map The map to do callbacks for + * @param callback A callback function which will be calle for each entry in map + */ +void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping * map, void (*callback)(int, void*)); + +/** + * Free the descriptor ID + * For the descriptor to be reused it has to be freed + * @param map The map to free the descriptor from + * @param descriptor The descriptor ID to free + * + * @return old value of descriptor mapping + */ +void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor); + +#endif /* __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.c new file mode 100644 index 0000000..0ab3a80 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.c @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_kernel_memory_engine.h" +#include "mali_osk.h" + +typedef struct os_allocation +{ + u32 num_pages; + u32 offset_start; + mali_allocation_engine * engine; + mali_memory_allocation * descriptor; +} os_allocation; + +typedef struct os_allocator +{ + _mali_osk_lock_t *mutex; + + /** + * Maximum number of pages to allocate from the OS + */ + u32 num_pages_max; + + /** + * Number of pages allocated from the OS + */ + u32 num_pages_allocated; + + /** CPU Usage adjustment (add to mali physical address to get cpu physical address) */ + u32 cpu_usage_adjust; +} os_allocator; + +static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); +static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block); +static void os_allocator_release(void * ctx, void * handle); +static void os_allocator_page_table_block_release( mali_page_table_block *page_table_block ); +static void os_allocator_destroy(mali_physical_memory_allocator * allocator); +static u32 os_allocator_stat(mali_physical_memory_allocator * allocator); + +mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u32 cpu_usage_adjust, const char *name) +{ + mali_physical_memory_allocator * allocator; + os_allocator * info; + + max_allocation = (max_allocation + _MALI_OSK_CPU_PAGE_SIZE-1) & ~(_MALI_OSK_CPU_PAGE_SIZE-1); + + MALI_DEBUG_PRINT(2, ("Mali OS memory allocator created with max allocation size of 0x%X bytes, cpu_usage_adjust 0x%08X\n", max_allocation, cpu_usage_adjust)); + + allocator = _mali_osk_malloc(sizeof(mali_physical_memory_allocator)); + if (NULL != allocator) + { + info = _mali_osk_malloc(sizeof(os_allocator)); + if (NULL != info) + { + info->num_pages_max = max_allocation / _MALI_OSK_CPU_PAGE_SIZE; + info->num_pages_allocated = 0; + info->cpu_usage_adjust = cpu_usage_adjust; + + info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_MEM_INFO); + if (NULL != info->mutex) + { + allocator->allocate = os_allocator_allocate; + allocator->allocate_page_table_block = os_allocator_allocate_page_table_block; + allocator->destroy = os_allocator_destroy; + allocator->stat = os_allocator_stat; + allocator->ctx = info; + allocator->name = name; + + return allocator; + } + _mali_osk_free(info); + } + _mali_osk_free(allocator); + } + + return NULL; +} + +static u32 os_allocator_stat(mali_physical_memory_allocator * allocator) +{ + os_allocator * info; + info = (os_allocator*)allocator->ctx; + return info->num_pages_allocated * _MALI_OSK_MALI_PAGE_SIZE; +} + +static void os_allocator_destroy(mali_physical_memory_allocator * allocator) +{ + os_allocator * info; + MALI_DEBUG_ASSERT_POINTER(allocator); + MALI_DEBUG_ASSERT_POINTER(allocator->ctx); + info = (os_allocator*)allocator->ctx; + _mali_osk_lock_term(info->mutex); + _mali_osk_free(info); + _mali_osk_free(allocator); +} + +static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_NONE; + u32 left; + os_allocator * info; + os_allocation * allocation; + int pages_allocated = 0; + _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(offset); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + info = (os_allocator*)ctx; + left = descriptor->size - *offset; + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; + + /** @note this code may not work on Linux, or may require a more complex Linux implementation */ + allocation = _mali_osk_malloc(sizeof(os_allocation)); + if (NULL != allocation) + { + /* MALI_SEC */ + //u32 os_mem_max_usage = info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE; + allocation->offset_start = *offset; + allocation->num_pages = ((left + _MALI_OSK_CPU_PAGE_SIZE - 1) & ~(_MALI_OSK_CPU_PAGE_SIZE - 1)) >> _MALI_OSK_CPU_PAGE_ORDER; + MALI_DEBUG_PRINT(6, ("Allocating page array of size %d bytes\n", allocation->num_pages * sizeof(struct page*))); + /* MALI_SEC */ + while (left > 0) + { + err = mali_allocation_engine_map_physical(engine, descriptor, *offset, MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, info->cpu_usage_adjust, _MALI_OSK_CPU_PAGE_SIZE); + if ( _MALI_OSK_ERR_OK != err) + { + if ( _MALI_OSK_ERR_NOMEM == err) + { + /* 'Partial' allocation (or, out-of-memory on first page) */ + break; + } + + MALI_DEBUG_PRINT(1, ("Mapping of physical memory failed\n")); + + /* Fatal error, cleanup any previous pages allocated. */ + if ( pages_allocated > 0 ) + { + mali_allocation_engine_unmap_physical( engine, descriptor, allocation->offset_start, _MALI_OSK_CPU_PAGE_SIZE*pages_allocated, _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR ); + /* (*offset) doesn't need to be restored; it will not be used by the caller on failure */ + } + + pages_allocated = 0; + + result = MALI_MEM_ALLOC_INTERNAL_FAILURE; + break; + } + + /* Loop iteration */ + if (left < _MALI_OSK_CPU_PAGE_SIZE) left = 0; + else left -= _MALI_OSK_CPU_PAGE_SIZE; + + pages_allocated++; + + *offset += _MALI_OSK_CPU_PAGE_SIZE; + } + + if (left) MALI_PRINT(("Out of memory. Mali memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", + (info->num_pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); + + /* Loop termination; decide on result */ + if (pages_allocated) + { + MALI_DEBUG_PRINT(6, ("Allocated %d pages\n", pages_allocated)); + if (left) result = MALI_MEM_ALLOC_PARTIAL; + else result = MALI_MEM_ALLOC_FINISHED; + + /* Some OS do not perform a full cache flush (including all outer caches) for uncached mapped memory. + * They zero the memory through a cached mapping, then flush the inner caches but not the outer caches. + * This is required for MALI to have the correct view of the memory. + */ + _mali_osk_cache_ensure_uncached_range_flushed( (void *)descriptor, allocation->offset_start, pages_allocated *_MALI_OSK_CPU_PAGE_SIZE ); + allocation->num_pages = pages_allocated; + allocation->engine = engine; /* Necessary to make the engine's unmap call */ + allocation->descriptor = descriptor; /* Necessary to make the engine's unmap call */ + info->num_pages_allocated += pages_allocated; + + MALI_DEBUG_PRINT(6, ("%d out of %d pages now allocated\n", info->num_pages_allocated, info->num_pages_max)); + + alloc_info->ctx = info; + alloc_info->handle = allocation; + alloc_info->release = os_allocator_release; + } + else + { + MALI_DEBUG_PRINT(6, ("Releasing pages array due to no pages allocated\n")); + _mali_osk_free( allocation ); + } + } + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + return result; +} + +static void os_allocator_release(void * ctx, void * handle) +{ + os_allocator * info; + os_allocation * allocation; + mali_allocation_engine * engine; + mali_memory_allocation * descriptor; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(handle); + + info = (os_allocator*)ctx; + allocation = (os_allocation*)handle; + engine = allocation->engine; + descriptor = allocation->descriptor; + + MALI_DEBUG_ASSERT_POINTER( engine ); + MALI_DEBUG_ASSERT_POINTER( descriptor ); + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) + { + MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); + return; + } + + MALI_DEBUG_PRINT(6, ("Releasing %d os pages\n", allocation->num_pages)); + + MALI_DEBUG_ASSERT( allocation->num_pages <= info->num_pages_allocated); + info->num_pages_allocated -= allocation->num_pages; + + mali_allocation_engine_unmap_physical( engine, descriptor, allocation->offset_start, _MALI_OSK_CPU_PAGE_SIZE*allocation->num_pages, _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR ); + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_free(allocation); +} + +static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) +{ +/* MALI_SEC 6->10 */ +#ifndef CONFIG_FORCE_MAX_ZONEORDER + int allocation_order = 10; +#else + int allocation_order = CONFIG_FORCE_MAX_ZONEORDER - 1; +#endif + void *virt = NULL; + u32 size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; + os_allocator * info; + + u32 cpu_phys_base; + + MALI_DEBUG_ASSERT_POINTER(ctx); + info = (os_allocator*)ctx; + + /* Ensure we don't allocate more than we're supposed to from the ctx */ + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; + + /* if the number of pages to be requested lead to exceeding the memory + * limit in info->num_pages_max, reduce the size that is to be requested. */ + while ( (info->num_pages_allocated + (1 << allocation_order) > info->num_pages_max) + && _mali_osk_mem_check_allocated(info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE) ) + { + if ( allocation_order > 0 ) { + --allocation_order; + } else { + /* return OOM */ + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + return MALI_MEM_ALLOC_NONE; + } + } + + /* try to allocate 2^(allocation_order) pages, if that fails, try + * allocation_order-1 to allocation_order 0 (inclusive) */ + while ( allocation_order >= 0 ) + { + size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; + virt = _mali_osk_mem_allocioregion( &cpu_phys_base, size ); + + if (NULL != virt) break; + + --allocation_order; + } + + if ( NULL == virt ) + { + MALI_DEBUG_PRINT(1, ("Failed to allocate consistent memory. Is CONSISTENT_DMA_SIZE set too low?\n")); + /* return OOM */ + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + return MALI_MEM_ALLOC_NONE; + } + + MALI_DEBUG_PRINT(5, ("os_allocator_allocate_page_table_block: Allocation of order %i succeeded\n", + allocation_order)); + + /* we now know the size of the allocation since we know for what + * allocation_order the allocation succeeded */ + size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; + + + block->release = os_allocator_page_table_block_release; + block->ctx = ctx; + block->handle = (void*)allocation_order; + block->size = size; + block->phys_base = cpu_phys_base - info->cpu_usage_adjust; + block->mapping = virt; + + info->num_pages_allocated += (1 << allocation_order); + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + return MALI_MEM_ALLOC_FINISHED; +} + +static void os_allocator_page_table_block_release( mali_page_table_block *page_table_block ) +{ + os_allocator * info; + u32 allocation_order; + u32 pages_allocated; + + MALI_DEBUG_ASSERT_POINTER( page_table_block ); + + info = (os_allocator*)page_table_block->ctx; + + MALI_DEBUG_ASSERT_POINTER( info ); + + allocation_order = (u32)page_table_block->handle; + + pages_allocated = 1 << allocation_order; + + MALI_DEBUG_ASSERT( pages_allocated * _MALI_OSK_CPU_PAGE_SIZE == page_table_block->size ); + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) + { + MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); + return; + } + + MALI_DEBUG_ASSERT( pages_allocated <= info->num_pages_allocated); + info->num_pages_allocated -= pages_allocated; + + /* Adjust phys_base from mali physical address to CPU physical address */ + _mali_osk_mem_freeioregion( page_table_block->phys_base + info->cpu_usage_adjust, page_table_block->size, page_table_block->mapping ); + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.h new file mode 100644 index 0000000..0946169 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_MEM_OS_H__ +#define __MALI_KERNEL_MEM_OS_H__ + +/** + * @brief Creates an object that manages allocating OS memory + * + * Creates an object that provides an interface to allocate OS memory and + * have it mapped into the Mali virtual memory space. + * + * The object exposes pointers to + * - allocate OS memory + * - allocate Mali page tables in OS memory + * - destroy the object + * + * Allocations from OS memory are of type mali_physical_memory_allocation + * which provides a function to release the allocation. + * + * @param max_allocation max. number of bytes that can be allocated from OS memory + * @param cpu_usage_adjust value to add to mali physical addresses to obtain CPU physical addresses + * @param name description of the allocator + * @return pointer to mali_physical_memory_allocator object. NULL on failure. + **/ +mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u32 cpu_usage_adjust, const char *name); + +#endif /* __MALI_KERNEL_MEM_OS_H__ */ + + diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.c new file mode 100644 index 0000000..00257ec --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.c @@ -0,0 +1,375 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_kernel_memory_engine.h" +#include "mali_osk.h" +#include "mali_osk_list.h" + +typedef struct memory_engine +{ + mali_kernel_mem_address_manager * mali_address; + mali_kernel_mem_address_manager * process_address; +} memory_engine; + +mali_allocation_engine mali_allocation_engine_create(mali_kernel_mem_address_manager * mali_address_manager, mali_kernel_mem_address_manager * process_address_manager) +{ + memory_engine * engine; + + /* Mali Address Manager need not support unmap_physical */ + MALI_DEBUG_ASSERT_POINTER(mali_address_manager); + MALI_DEBUG_ASSERT_POINTER(mali_address_manager->allocate); + MALI_DEBUG_ASSERT_POINTER(mali_address_manager->release); + MALI_DEBUG_ASSERT_POINTER(mali_address_manager->map_physical); + + /* Process Address Manager must support unmap_physical for OS allocation + * error path handling */ + MALI_DEBUG_ASSERT_POINTER(process_address_manager); + MALI_DEBUG_ASSERT_POINTER(process_address_manager->allocate); + MALI_DEBUG_ASSERT_POINTER(process_address_manager->release); + MALI_DEBUG_ASSERT_POINTER(process_address_manager->map_physical); + MALI_DEBUG_ASSERT_POINTER(process_address_manager->unmap_physical); + + + engine = (memory_engine*)_mali_osk_malloc(sizeof(memory_engine)); + if (NULL == engine) return NULL; + + engine->mali_address = mali_address_manager; + engine->process_address = process_address_manager; + + return (mali_allocation_engine)engine; +} + +void mali_allocation_engine_destroy(mali_allocation_engine engine) +{ + MALI_DEBUG_ASSERT_POINTER(engine); + _mali_osk_free(engine); +} + +_mali_osk_errcode_t mali_allocation_engine_allocate_memory(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, mali_physical_memory_allocator * physical_allocators, _mali_osk_list_t *tracking_list ) +{ + memory_engine * engine = (memory_engine*)mem_engine; + + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(physical_allocators); + /* ASSERT that the list member has been initialized, even if it won't be + * used for tracking. We need it to be initialized to see if we need to + * delete it from a list in the release function. */ + MALI_DEBUG_ASSERT( NULL != descriptor->list.next && NULL != descriptor->list.prev ); + + if (_MALI_OSK_ERR_OK == engine->mali_address->allocate(descriptor)) + { + _mali_osk_errcode_t res = _MALI_OSK_ERR_OK; + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + res = engine->process_address->allocate(descriptor); + } + if ( _MALI_OSK_ERR_OK == res ) + { + /* address space setup OK, commit physical memory to the allocation */ + mali_physical_memory_allocator * active_allocator = physical_allocators; + struct mali_physical_memory_allocation * active_allocation_tracker = &descriptor->physical_allocation; + u32 offset = 0; + + while ( NULL != active_allocator ) + { + switch (active_allocator->allocate(active_allocator->ctx, mem_engine, descriptor, &offset, active_allocation_tracker)) + { + case MALI_MEM_ALLOC_FINISHED: + if ( NULL != tracking_list ) + { + /* Insert into the memory session list */ + /* ASSERT that it is not already part of a list */ + MALI_DEBUG_ASSERT( _mali_osk_list_empty( &descriptor->list ) ); + _mali_osk_list_add( &descriptor->list, tracking_list ); + } + + MALI_SUCCESS; /* all done */ + case MALI_MEM_ALLOC_NONE: + /* reuse current active_allocation_tracker */ + MALI_DEBUG_PRINT( 4, ("Memory Engine Allocate: No allocation on %s, resorting to %s\n", + ( active_allocator->name ) ? active_allocator->name : "UNNAMED", + ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") ); + active_allocator = active_allocator->next; + break; + case MALI_MEM_ALLOC_PARTIAL: + if (NULL != active_allocator->next) + { + /* need a new allocation tracker */ + active_allocation_tracker->next = _mali_osk_calloc(1, sizeof(mali_physical_memory_allocation)); + if (NULL != active_allocation_tracker->next) + { + active_allocation_tracker = active_allocation_tracker->next; + MALI_DEBUG_PRINT( 2, ("Memory Engine Allocate: Partial allocation on %s, resorting to %s\n", + ( active_allocator->name ) ? active_allocator->name : "UNNAMED", + ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") ); + active_allocator = active_allocator->next; + break; + } + } + /* FALL THROUGH */ + case MALI_MEM_ALLOC_INTERNAL_FAILURE: + active_allocator = NULL; /* end the while loop */ + break; + } + } + + MALI_PRINT(("Memory allocate failed, could not allocate size %d kB.\n", descriptor->size/1024)); + + /* allocation failure, start cleanup */ + /* loop over any potential partial allocations */ + active_allocation_tracker = &descriptor->physical_allocation; + while (NULL != active_allocation_tracker) + { + /* handle blank trackers which will show up during failure */ + if (NULL != active_allocation_tracker->release) + { + active_allocation_tracker->release(active_allocation_tracker->ctx, active_allocation_tracker->handle); + } + active_allocation_tracker = active_allocation_tracker->next; + } + + /* free the allocation tracker objects themselves, skipping the tracker stored inside the descriptor itself */ + for ( active_allocation_tracker = descriptor->physical_allocation.next; active_allocation_tracker != NULL; ) + { + void * buf = active_allocation_tracker; + active_allocation_tracker = active_allocation_tracker->next; + _mali_osk_free(buf); + } + + /* release the address spaces */ + + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + engine->process_address->release(descriptor); + } + } + engine->mali_address->release(descriptor); + } + + MALI_ERROR(_MALI_OSK_ERR_FAULT); +} + +void mali_allocation_engine_release_memory(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor) +{ + mali_allocation_engine_release_pt1_mali_pagetables_unmap(mem_engine, descriptor); + mali_allocation_engine_release_pt2_physical_memory_free(mem_engine, descriptor); +} + +void mali_allocation_engine_release_pt1_mali_pagetables_unmap(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor) +{ + memory_engine * engine = (memory_engine*)mem_engine; + + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + + /* Calling: mali_address_manager_release() */ + /* This function is allowed to be called several times, and it only does the release on the first call. */ + engine->mali_address->release(descriptor); +} + +void mali_allocation_engine_release_pt2_physical_memory_free(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor) +{ + memory_engine * engine = (memory_engine*)mem_engine; + mali_physical_memory_allocation * active_allocation_tracker; + + /* Remove this from a tracking list in session_data->memory_head */ + if ( ! _mali_osk_list_empty( &descriptor->list ) ) + { + _mali_osk_list_del( &descriptor->list ); + /* Clear the list for debug mode, catch use-after-free */ + MALI_DEBUG_CODE( descriptor->list.next = descriptor->list.prev = NULL; ) + } + + active_allocation_tracker = &descriptor->physical_allocation; + while (NULL != active_allocation_tracker) + { + MALI_DEBUG_ASSERT_POINTER(active_allocation_tracker->release); + active_allocation_tracker->release(active_allocation_tracker->ctx, active_allocation_tracker->handle); + active_allocation_tracker = active_allocation_tracker->next; + } + + /* free the allocation tracker objects themselves, skipping the tracker stored inside the descriptor itself */ + for ( active_allocation_tracker = descriptor->physical_allocation.next; active_allocation_tracker != NULL; ) + { + void * buf = active_allocation_tracker; + active_allocation_tracker = active_allocation_tracker->next; + _mali_osk_free(buf); + } + + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + engine->process_address->release(descriptor); + } +} + +_mali_osk_errcode_t mali_allocation_engine_map_physical(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, u32 offset, u32 phys, u32 cpu_usage_adjust, u32 size) +{ + _mali_osk_errcode_t err; + memory_engine * engine = (memory_engine*)mem_engine; + _mali_osk_mem_mapregion_flags_t unmap_flags = (_mali_osk_mem_mapregion_flags_t)0; + + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + + MALI_DEBUG_PRINT(7, ("Mapping phys 0x%08X length 0x%08X at offset 0x%08X\n", phys, size, offset)); + + MALI_DEBUG_ASSERT_POINTER(engine->mali_address); + MALI_DEBUG_ASSERT_POINTER(engine->mali_address->map_physical); + + /* Handle process address manager first, because we may need them to + * allocate the physical page */ + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + /* Handle OS-allocated specially, since an adjustment may be required */ + if ( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC == phys ) + { + MALI_DEBUG_ASSERT( _MALI_OSK_CPU_PAGE_SIZE == size ); + + /* Set flags to use on error path */ + unmap_flags |= _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR; + + err = engine->process_address->map_physical(descriptor, offset, &phys, size); + /* Adjust for cpu physical address to mali physical address */ + phys -= cpu_usage_adjust; + } + else + { + u32 cpu_phys; + /* Adjust mali physical address to cpu physical address */ + cpu_phys = phys + cpu_usage_adjust; + err = engine->process_address->map_physical(descriptor, offset, &cpu_phys, size); + } + + if ( _MALI_OSK_ERR_OK != err ) + { + MALI_DEBUG_PRINT(2, ("Map failed: %s %d\n", __FUNCTION__, __LINE__)); + MALI_ERROR( err ); + } + } + + MALI_DEBUG_PRINT(7, ("Mapping phys 0x%08X length 0x%08X at offset 0x%08X to CPUVA 0x%08X\n", phys, size, offset, (u32)(descriptor->mapping) + offset)); + + /* Mali address manager must use the physical address - no point in asking + * it to allocate another one for us */ + MALI_DEBUG_ASSERT( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC != phys ); + + err = engine->mali_address->map_physical(descriptor, offset, &phys, size); + + if ( _MALI_OSK_ERR_OK != err ) + { + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + MALI_DEBUG_PRINT( 2, ("Process address manager succeeded, but Mali Address manager failed for phys=0x%08X size=0x%08X, offset=0x%08X. Will unmap.\n", phys, size, offset)); + engine->process_address->unmap_physical(descriptor, offset, size, unmap_flags); + } + MALI_DEBUG_PRINT(2, ("Map mali failed: %s %d\n", __FUNCTION__, __LINE__)); + MALI_ERROR( err ); + } + + MALI_SUCCESS; +} + +void mali_allocation_engine_unmap_physical(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t unmap_flags ) +{ + memory_engine * engine = (memory_engine*)mem_engine; + + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + + MALI_DEBUG_PRINT(7, ("UnMapping length 0x%08X at offset 0x%08X\n", size, offset)); + + MALI_DEBUG_ASSERT_POINTER(engine->mali_address); + MALI_DEBUG_ASSERT_POINTER(engine->process_address); + + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + /* Mandetory for process_address manager to have an unmap function*/ + engine->process_address->unmap_physical( descriptor, offset, size, unmap_flags ); + } + + /* Optional for mali_address manager to have an unmap function*/ + if ( NULL != engine->mali_address->unmap_physical ) + { + engine->mali_address->unmap_physical( descriptor, offset, size, unmap_flags ); + } +} + + +_mali_osk_errcode_t mali_allocation_engine_allocate_page_tables(mali_allocation_engine engine, mali_page_table_block * descriptor, mali_physical_memory_allocator * physical_provider) +{ + mali_physical_memory_allocator * active_allocator = physical_provider; + + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(physical_provider); + + while ( NULL != active_allocator ) + { + switch (active_allocator->allocate_page_table_block(active_allocator->ctx, descriptor)) + { + case MALI_MEM_ALLOC_FINISHED: + MALI_SUCCESS; /* all done */ + case MALI_MEM_ALLOC_NONE: + /* try next */ + MALI_DEBUG_PRINT( 2, ("Memory Engine Allocate PageTables: No allocation on %s, resorting to %s\n", + ( active_allocator->name ) ? active_allocator->name : "UNNAMED", + ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") ); + active_allocator = active_allocator->next; + break; + case MALI_MEM_ALLOC_PARTIAL: + MALI_DEBUG_PRINT(1, ("Invalid return value from allocate_page_table_block call: MALI_MEM_ALLOC_PARTIAL\n")); + /* FALL THROUGH */ + case MALI_MEM_ALLOC_INTERNAL_FAILURE: + MALI_DEBUG_PRINT(1, ("Aborting due to allocation failure\n")); + active_allocator = NULL; /* end the while loop */ + break; + } + } + + MALI_ERROR(_MALI_OSK_ERR_FAULT); +} + + +void mali_allocation_engine_report_allocators( mali_physical_memory_allocator * physical_provider ) +{ + mali_physical_memory_allocator * active_allocator = physical_provider; + MALI_DEBUG_ASSERT_POINTER(physical_provider); + + MALI_DEBUG_PRINT( 1, ("Mali memory allocators will be used in this order of preference (lowest numbered first) :\n")); + while ( NULL != active_allocator ) + { + if ( NULL != active_allocator->name ) + { + MALI_DEBUG_PRINT( 1, ("\t%d: %s\n", active_allocator->alloc_order, active_allocator->name) ); + } + else + { + MALI_DEBUG_PRINT( 1, ("\t%d: (UNNAMED ALLOCATOR)\n", active_allocator->alloc_order) ); + } + active_allocator = active_allocator->next; + } + +} + +u32 mali_allocation_engine_memory_usage(mali_physical_memory_allocator *allocator) +{ + u32 sum = 0; + while(NULL != allocator) + { + /* Only count allocators that have set up a stat function. */ + if(allocator->stat) + sum += allocator->stat(allocator); + + allocator = allocator->next; + } + + return sum; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.h new file mode 100644 index 0000000..3b41cee --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_MEMORY_ENGINE_H__ +#define __MALI_KERNEL_MEMORY_ENGINE_H__ + +typedef void * mali_allocation_engine; + +typedef enum { MALI_MEM_ALLOC_FINISHED, MALI_MEM_ALLOC_PARTIAL, MALI_MEM_ALLOC_NONE, MALI_MEM_ALLOC_INTERNAL_FAILURE } mali_physical_memory_allocation_result; + +typedef struct mali_physical_memory_allocation +{ + void (*release)(void * ctx, void * handle); /**< Function to call on to release the physical memory */ + void * ctx; + void * handle; + struct mali_physical_memory_allocation * next; +} mali_physical_memory_allocation; + +struct mali_page_table_block; + +typedef struct mali_page_table_block +{ + void (*release)(struct mali_page_table_block *page_table_block); + void * ctx; + void * handle; + u32 size; /**< In bytes, should be a multiple of MALI_MMU_PAGE_SIZE to avoid internal fragementation */ + u32 phys_base; /**< Mali physical address */ + mali_io_address mapping; +} mali_page_table_block; + + +/** @addtogroup _mali_osk_low_level_memory + * @{ */ + +typedef enum +{ + MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE = 0x1, + MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE = 0x2, +} mali_memory_allocation_flag; + +/** + * Supplying this 'magic' physical address requests that the OS allocate the + * physical address at page commit time, rather than committing a specific page + */ +#define MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC ((u32)(-1)) + +typedef struct mali_memory_allocation +{ + /* Information about the allocation */ + void * mapping; /**< CPU virtual address where the memory is mapped at */ + u32 mali_address; /**< The Mali seen address of the memory allocation */ + u32 size; /**< Size of the allocation */ + u32 permission; /**< Permission settings */ + mali_memory_allocation_flag flags; + u32 cache_settings; /* type: mali_memory_cache_settings, found in Ump DD breaks if we include it...*/ + + _mali_osk_lock_t * lock; + + /* Manager specific information pointers */ + void * mali_addr_mapping_info; /**< Mali address allocation specific info */ + void * process_addr_mapping_info; /**< Mapping manager specific info */ + + mali_physical_memory_allocation physical_allocation; + + _mali_osk_list_t list; /**< List for linking together memory allocations into the session's memory head */ +} mali_memory_allocation; +/** @} */ /* end group _mali_osk_low_level_memory */ + + +typedef struct mali_physical_memory_allocator +{ + mali_physical_memory_allocation_result (*allocate)(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); + mali_physical_memory_allocation_result (*allocate_page_table_block)(void * ctx, mali_page_table_block * block); /* MALI_MEM_ALLOC_PARTIAL not allowed */ + void (*destroy)(struct mali_physical_memory_allocator * allocator); + u32 (*stat)(struct mali_physical_memory_allocator * allocator); + void * ctx; + const char * name; /**< Descriptive name for use in mali_allocation_engine_report_allocators, or NULL */ + u32 alloc_order; /**< Order in which the allocations should happen */ + struct mali_physical_memory_allocator * next; +} mali_physical_memory_allocator; + +typedef struct mali_kernel_mem_address_manager +{ + _mali_osk_errcode_t (*allocate)(mali_memory_allocation *); /**< Function to call to reserve an address */ + void (*release)(mali_memory_allocation *); /**< Function to call to free the address allocated */ + + /** + * Function called for each physical sub allocation. + * Called for each physical block allocated by the physical memory manager. + * @param[in] descriptor The memory descriptor in question + * @param[in] off Offset from the start of range + * @param[in,out] phys_addr A pointer to the physical address of the start of the + * physical block. When *phys_addr == MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC + * is used, this requests the function to allocate the physical page + * itself, and return it through the pointer provided. + * @param[in] size Length in bytes of the physical block + * @return _MALI_OSK_ERR_OK on success. + * A value of type _mali_osk_errcode_t other than _MALI_OSK_ERR_OK indicates failure. + * Specifically, _MALI_OSK_ERR_UNSUPPORTED indicates that the function + * does not support allocating physical pages itself. + */ + _mali_osk_errcode_t (*map_physical)(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size); + + /** + * Function called to remove a physical sub allocation. + * Called on error paths where one of the address managers fails. + * + * @note this is optional. For address managers where this is not + * implemented, the value of this member is NULL. The memory engine + * currently does not require the mali address manager to be able to + * unmap individual pages, but the process address manager must have this + * capability. + * + * @param[in] descriptor The memory descriptor in question + * @param[in] off Offset from the start of range + * @param[in] size Length in bytes of the physical block + * @param[in] flags flags to use on a per-page basis. For OS-allocated + * physical pages, this must include _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR. + * @return _MALI_OSK_ERR_OK on success. + * A value of type _mali_osk_errcode_t other than _MALI_OSK_ERR_OK indicates failure. + */ + void (*unmap_physical)(mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags); + +} mali_kernel_mem_address_manager; + +mali_allocation_engine mali_allocation_engine_create(mali_kernel_mem_address_manager * mali_address_manager, mali_kernel_mem_address_manager * process_address_manager); + +void mali_allocation_engine_destroy(mali_allocation_engine engine); + +int mali_allocation_engine_allocate_memory(mali_allocation_engine engine, mali_memory_allocation * descriptor, mali_physical_memory_allocator * physical_provider, _mali_osk_list_t *tracking_list ); +void mali_allocation_engine_release_memory(mali_allocation_engine engine, mali_memory_allocation * descriptor); + +void mali_allocation_engine_release_pt1_mali_pagetables_unmap(mali_allocation_engine engine, mali_memory_allocation * descriptor); +void mali_allocation_engine_release_pt2_physical_memory_free(mali_allocation_engine engine, mali_memory_allocation * descriptor); + +int mali_allocation_engine_map_physical(mali_allocation_engine engine, mali_memory_allocation * descriptor, u32 offset, u32 phys, u32 cpu_usage_adjust, u32 size); +void mali_allocation_engine_unmap_physical(mali_allocation_engine engine, mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t unmap_flags); + +int mali_allocation_engine_allocate_page_tables(mali_allocation_engine, mali_page_table_block * descriptor, mali_physical_memory_allocator * physical_provider); + +void mali_allocation_engine_report_allocators(mali_physical_memory_allocator * physical_provider); + +u32 mali_allocation_engine_memory_usage(mali_physical_memory_allocator *allocator); + +#endif /* __MALI_KERNEL_MEMORY_ENGINE_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.c new file mode 100644 index 0000000..9dae2e8 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.c @@ -0,0 +1,420 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_utilization.h" +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_kernel_common.h" + +/* Define how often to calculate and report GPU utilization, in milliseconds */ +static _mali_osk_lock_t *time_data_lock; + +static u32 num_running_gp_cores; +static u32 num_running_pp_cores; + +static u64 work_start_time_gpu = 0; +static u64 work_start_time_gp = 0; +static u64 work_start_time_pp = 0; +static u64 accumulated_work_time_gpu = 0; +static u64 accumulated_work_time_gp = 0; +static u64 accumulated_work_time_pp = 0; + +static u64 period_start_time = 0; + +#ifndef CONFIG_PM_DEVFREQ /* MALI_SEC */ +static _mali_osk_timer_t *utilization_timer = NULL; +#endif +static mali_bool timer_running = MALI_FALSE; + +static u32 last_utilization_gpu = 0 ; +static u32 last_utilization_gp = 0 ; +static u32 last_utilization_pp = 0 ; + +#ifndef CONFIG_PM_DEVFREQ /* MALI_SEC */ +static u32 mali_utilization_timeout = 100; +#endif +void (*mali_utilization_callback)(struct mali_gpu_utilization_data *data) = NULL; + +#ifndef CONFIG_PM_DEVFREQ +static void calculate_gpu_utilization(void* arg) +{ +#else +void calculate_gpu_utilization(void *arg) +{ +#endif + u64 time_now; + u64 time_period; + u32 leading_zeroes; + u32 shift_val; + u32 work_normalized_gpu; + u32 work_normalized_gp; + u32 work_normalized_pp; + u32 period_normalized; + u32 utilization_gpu; + u32 utilization_gp; + u32 utilization_pp; + + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + if (accumulated_work_time_gpu == 0 && work_start_time_gpu == 0) + { + /* + * No work done for this period + * - No need to reschedule timer + * - Report zero usage + */ + timer_running = MALI_FALSE; + + last_utilization_gpu = 0; + last_utilization_gp = 0; + last_utilization_pp = 0; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + if (NULL != mali_utilization_callback) + { + struct mali_gpu_utilization_data data = { 0, }; + mali_utilization_callback(&data); + } + + return; + } + + time_now = _mali_osk_time_get_ns(); + + time_period = time_now - period_start_time; + + /* If we are currently busy, update working period up to now */ + if (work_start_time_gpu != 0) + { + accumulated_work_time_gpu += (time_now - work_start_time_gpu); + work_start_time_gpu = time_now; + + /* GP and/or PP will also be busy if the GPU is busy at this point */ + + if (work_start_time_gp != 0) + { + accumulated_work_time_gp += (time_now - work_start_time_gp); + work_start_time_gp = time_now; + } + + if (work_start_time_pp != 0) + { + accumulated_work_time_pp += (time_now - work_start_time_pp); + work_start_time_pp = time_now; + } + } + + /* + * We have two 64-bit values, a dividend and a divisor. + * To avoid dependencies to a 64-bit divider, we shift down the two values + * equally first. + * We shift the dividend up and possibly the divisor down, making the result X in 256. + */ + + /* Shift the 64-bit values down so they fit inside a 32-bit integer */ + leading_zeroes = _mali_osk_clz((u32)(time_period >> 32)); + shift_val = 32 - leading_zeroes; + work_normalized_gpu = (u32)(accumulated_work_time_gpu >> shift_val); + work_normalized_gp = (u32)(accumulated_work_time_gp >> shift_val); + work_normalized_pp = (u32)(accumulated_work_time_pp >> shift_val); + period_normalized = (u32)(time_period >> shift_val); + + /* + * Now, we should report the usage in parts of 256 + * this means we must shift up the dividend or down the divisor by 8 + * (we could do a combination, but we just use one for simplicity, + * but the end result should be good enough anyway) + */ + if (period_normalized > 0x00FFFFFF) + { + /* The divisor is so big that it is safe to shift it down */ + period_normalized >>= 8; + } + else + { + /* + * The divisor is so small that we can shift up the dividend, without loosing any data. + * (dividend is always smaller than the divisor) + */ + work_normalized_gpu <<= 8; + work_normalized_gp <<= 8; + work_normalized_pp <<= 8; + } + + utilization_gpu = work_normalized_gpu / period_normalized; + utilization_gp = work_normalized_gp / period_normalized; + utilization_pp = work_normalized_pp / period_normalized; + + last_utilization_gpu = utilization_gpu; + last_utilization_gp = utilization_gp; + last_utilization_pp = utilization_pp; + + /* starting a new period */ + accumulated_work_time_gpu = 0; + accumulated_work_time_gp = 0; + accumulated_work_time_pp = 0; + period_start_time = time_now; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + +#ifndef CONFIG_PM_DEVFREQ + _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout)); +#endif + + if (NULL != mali_utilization_callback) + { + struct mali_gpu_utilization_data data = { utilization_gpu, utilization_gp, utilization_pp }; + mali_utilization_callback(&data); + } +} + +_mali_osk_errcode_t mali_utilization_init(void) +{ +#if USING_GPU_UTILIZATION + struct _mali_osk_device_data data; + if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) + { + /* Use device specific settings (if defined) */ +#ifndef CONFIG_PM_DEVFREQ + if (0 != data.utilization_interval) + { + mali_utilization_timeout = data.utilization_interval; + } +#endif + if (NULL != data.utilization_callback) + { + mali_utilization_callback = data.utilization_callback; + } + } +#endif + + if (NULL != mali_utilization_callback) + { +#ifndef CONFIG_PM_DEVFREQ + MALI_DEBUG_PRINT(2, ("Mali GPU Utilization: Utilization handler installed with interval %u\n", mali_utilization_timeout)); +#endif + } + else + { + MALI_DEBUG_PRINT(2, ("Mali GPU Utilization: No utilization handler installed\n")); + } + + time_data_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | + _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_UTILIZATION); + + if (NULL == time_data_lock) + { + return _MALI_OSK_ERR_FAULT; + } + + num_running_gp_cores = 0; + num_running_pp_cores = 0; + +#ifndef CONFIG_PM_DEVFREQ + utilization_timer = _mali_osk_timer_init(); + if (NULL == utilization_timer) + { + _mali_osk_lock_term(time_data_lock); + return _MALI_OSK_ERR_FAULT; + } + _mali_osk_timer_setcallback(utilization_timer, calculate_gpu_utilization, NULL); +#endif + + return _MALI_OSK_ERR_OK; +} + +#ifndef CONFIG_PM_DEVFREQ +void mali_utilization_suspend(void) +{ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + if (timer_running == MALI_TRUE) + { + timer_running = MALI_FALSE; + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_timer_del(utilization_timer); + return; + } + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); +} +#endif + +void mali_utilization_term(void) +{ +#ifndef CONFIG_PM_DEVFREQ + if (NULL != utilization_timer) + { + _mali_osk_timer_del(utilization_timer); + timer_running = MALI_FALSE; + _mali_osk_timer_term(utilization_timer); + utilization_timer = NULL; + } +#endif + + _mali_osk_lock_term(time_data_lock); +} + +void mali_utilization_gp_start(void) +{ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + ++num_running_gp_cores; + if (1 == num_running_gp_cores) + { + u64 time_now = _mali_osk_time_get_ns(); + + /* First GP core started, consider GP busy from now and onwards */ + work_start_time_gp = time_now; + + if (0 == num_running_pp_cores) + { + /* + * There are no PP cores running, so this is also the point + * at which we consider the GPU to be busy as well. + */ + work_start_time_gpu = time_now; + } + + /* Start a new period (and timer) if needed */ + if (timer_running != MALI_TRUE) + { + timer_running = MALI_TRUE; + period_start_time = time_now; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout)); + } + else + { + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } + } + else + { + /* Nothing to do */ + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } +} + +void mali_utilization_pp_start(void) +{ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + ++num_running_pp_cores; + if (1 == num_running_pp_cores) + { + u64 time_now = _mali_osk_time_get_ns(); + + /* First PP core started, consider PP busy from now and onwards */ + work_start_time_pp = time_now; + + if (0 == num_running_gp_cores) + { + /* + * There are no GP cores running, so this is also the point + * at which we consider the GPU to be busy as well. + */ + work_start_time_gpu = time_now; + } + + /* Start a new period (and timer) if needed */ + if (timer_running != MALI_TRUE) + { + timer_running = MALI_TRUE; + period_start_time = time_now; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); +#ifndef CONFIG_PM_DEVFREQ + _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout)); +#endif + } + else + { + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } + } + else + { + /* Nothing to do */ + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } +} + +void mali_utilization_gp_end(void) +{ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + --num_running_gp_cores; + if (0 == num_running_gp_cores) + { + u64 time_now = _mali_osk_time_get_ns(); + + /* Last GP core ended, consider GP idle from now and onwards */ + accumulated_work_time_gp += (time_now - work_start_time_gp); + work_start_time_gp = 0; + + if (0 == num_running_pp_cores) + { + /* + * There are no PP cores running, so this is also the point + * at which we consider the GPU to be idle as well. + */ + accumulated_work_time_gpu += (time_now - work_start_time_gpu); + work_start_time_gpu = 0; + } + } + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); +} + +void mali_utilization_pp_end(void) +{ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + --num_running_pp_cores; + if (0 == num_running_pp_cores) + { + u64 time_now = _mali_osk_time_get_ns(); + + /* Last PP core ended, consider PP idle from now and onwards */ + accumulated_work_time_pp += (time_now - work_start_time_pp); + work_start_time_pp = 0; + + if (0 == num_running_gp_cores) + { + /* + * There are no GP cores running, so this is also the point + * at which we consider the GPU to be idle as well. + */ + accumulated_work_time_gpu += (time_now - work_start_time_gpu); + work_start_time_gpu = 0; + } + } + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); +} + +u32 _mali_ukk_utilization_gp_pp(void) +{ + return last_utilization_gpu; +} + +u32 _mali_ukk_utilization_gp(void) +{ + return last_utilization_gp; +} + +u32 _mali_ukk_utilization_pp(void) +{ + return last_utilization_pp; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.h new file mode 100644 index 0000000..6ee5101 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_UTILIZATION_H__ +#define __MALI_KERNEL_UTILIZATION_H__ + +#include +#include "mali_osk.h" + +extern void (*mali_utilization_callback)(struct mali_gpu_utilization_data *data); + +#ifdef CONFIG_PM_DEVFREQ /* MALI_SEC */ +void calculate_gpu_utilization(void *arg); +#endif +/** + * Initialize/start the Mali GPU utilization metrics reporting. + * + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t mali_utilization_init(void); + +/** + * Terminate the Mali GPU utilization metrics reporting + */ +void mali_utilization_term(void); + +/** + * Check if Mali utilization is enabled + */ +MALI_STATIC_INLINE mali_bool mali_utilization_enabled(void) +{ + return (NULL != mali_utilization_callback); +} + +/** + * Should be called when a job is about to execute a GP job + */ +void mali_utilization_gp_start(void); + +/** + * Should be called when a job has completed executing a GP job + */ +void mali_utilization_gp_end(void); + +/** + * Should be called when a job is about to execute a PP job + */ +void mali_utilization_pp_start(void); + +/** + * Should be called when a job has completed executing a PP job + */ +void mali_utilization_pp_end(void); + +/** + * Should be called to stop the utilization timer during system suspend + */ +void mali_utilization_suspend(void); + + +#endif /* __MALI_KERNEL_UTILIZATION_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_vsync.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_vsync.c new file mode 100644 index 0000000..a1fdf00 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_vsync.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_ukk.h" + +#if defined(CONFIG_MALI400_PROFILING) +#include "mali_osk_profiling.h" +#endif + +_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args) +{ + _mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event; + MALI_IGNORE(event); /* event is not used for release code, and that is OK */ + +#if defined(CONFIG_MALI400_PROFILING) + /* + * Manually generate user space events in kernel space. + * This saves user space from calling kernel space twice in this case. + * We just need to remember to add pid and tid manually. + */ + if ( event==_MALI_UK_VSYNC_EVENT_BEGIN_WAIT) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC, + _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); + } + + if (event==_MALI_UK_VSYNC_EVENT_END_WAIT) + { + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC, + _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); + } +#endif + + MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event)); + MALI_SUCCESS; +} + diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.c b/drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.c new file mode 100644 index 0000000..b5cfcb5 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.c @@ -0,0 +1,463 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_l2_cache.h" +#include "mali_hw_core.h" +#include "mali_scheduler.h" +#include "mali_pm_domain.h" + +/** + * Size of the Mali L2 cache registers in bytes + */ +#define MALI400_L2_CACHE_REGISTERS_SIZE 0x30 + +/** + * Mali L2 cache register numbers + * Used in the register read/write routines. + * See the hardware documentation for more information about each register + */ +typedef enum mali_l2_cache_register { + MALI400_L2_CACHE_REGISTER_STATUS = 0x0008, + /*unused = 0x000C */ + MALI400_L2_CACHE_REGISTER_COMMAND = 0x0010, /**< Misc cache commands, e.g. clear */ + MALI400_L2_CACHE_REGISTER_CLEAR_PAGE = 0x0014, + MALI400_L2_CACHE_REGISTER_MAX_READS = 0x0018, /**< Limit of outstanding read requests */ + MALI400_L2_CACHE_REGISTER_ENABLE = 0x001C, /**< Enable misc cache features */ + MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0 = 0x0020, + MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0 = 0x0024, + MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1 = 0x0028, + MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1 = 0x002C, +} mali_l2_cache_register; + +/** + * Mali L2 cache commands + * These are the commands that can be sent to the Mali L2 cache unit + */ +typedef enum mali_l2_cache_command +{ + MALI400_L2_CACHE_COMMAND_CLEAR_ALL = 0x01, /**< Clear the entire cache */ + /* Read HW TRM carefully before adding/using other commands than the clear above */ +} mali_l2_cache_command; + +/** + * Mali L2 cache commands + * These are the commands that can be sent to the Mali L2 cache unit + */ +typedef enum mali_l2_cache_enable +{ + MALI400_L2_CACHE_ENABLE_DEFAULT = 0x0, /**< Default state of enable register */ + MALI400_L2_CACHE_ENABLE_ACCESS = 0x01, /**< Permit cacheable accesses */ + MALI400_L2_CACHE_ENABLE_READ_ALLOCATE = 0x02, /**< Permit cache read allocate */ +} mali_l2_cache_enable; + +/** + * Mali L2 cache status bits + */ +typedef enum mali_l2_cache_status +{ + MALI400_L2_CACHE_STATUS_COMMAND_BUSY = 0x01, /**< Command handler of L2 cache is busy */ + MALI400_L2_CACHE_STATUS_DATA_BUSY = 0x02, /**< L2 cache is busy handling data requests */ +} mali_l2_cache_status; + +#define MALI400_L2_MAX_READS_DEFAULT 0x1C + +static struct mali_l2_cache_core *mali_global_l2_cache_cores[MALI_MAX_NUMBER_OF_L2_CACHE_CORES] = { NULL, }; +static u32 mali_global_num_l2_cache_cores = 0; + +int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT; + +/* Local helper functions */ +static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val); + + +struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource) +{ + struct mali_l2_cache_core *cache = NULL; + _mali_osk_lock_flags_t lock_flags; + +#if defined(MALI_UPPER_HALF_SCHEDULING) + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#else + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#endif + + MALI_DEBUG_PRINT(2, ("Mali L2 cache: Creating Mali L2 cache: %s\n", resource->description)); + + if (mali_global_num_l2_cache_cores >= MALI_MAX_NUMBER_OF_L2_CACHE_CORES) + { + MALI_PRINT_ERROR(("Mali L2 cache: Too many L2 cache core objects created\n")); + return NULL; + } + + cache = _mali_osk_malloc(sizeof(struct mali_l2_cache_core)); + if (NULL != cache) + { + cache->core_id = mali_global_num_l2_cache_cores; + cache->counter_src0 = MALI_HW_CORE_NO_COUNTER; + cache->counter_src1 = MALI_HW_CORE_NO_COUNTER; + cache->pm_domain = NULL; + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&cache->hw_core, resource, MALI400_L2_CACHE_REGISTERS_SIZE)) + { + cache->command_lock = _mali_osk_lock_init(lock_flags, 0, _MALI_OSK_LOCK_ORDER_L2_COMMAND); + if (NULL != cache->command_lock) + { + cache->counter_lock = _mali_osk_lock_init(lock_flags, 0, _MALI_OSK_LOCK_ORDER_L2_COUNTER); + if (NULL != cache->counter_lock) + { + mali_l2_cache_reset(cache); + + cache->last_invalidated_id = 0; + + mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = cache; + mali_global_num_l2_cache_cores++; + + return cache; + } + else + { + MALI_PRINT_ERROR(("Mali L2 cache: Failed to create counter lock for L2 cache core %s\n", cache->hw_core.description)); + } + + _mali_osk_lock_term(cache->command_lock); + } + else + { + MALI_PRINT_ERROR(("Mali L2 cache: Failed to create command lock for L2 cache core %s\n", cache->hw_core.description)); + } + + mali_hw_core_delete(&cache->hw_core); + } + + _mali_osk_free(cache); + } + else + { + MALI_PRINT_ERROR(("Mali L2 cache: Failed to allocate memory for L2 cache core\n")); + } + + return NULL; +} + +void mali_l2_cache_delete(struct mali_l2_cache_core *cache) +{ + u32 i; + + /* reset to defaults */ + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)MALI400_L2_MAX_READS_DEFAULT); + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_DEFAULT); + + _mali_osk_lock_term(cache->counter_lock); + _mali_osk_lock_term(cache->command_lock); + mali_hw_core_delete(&cache->hw_core); + + for (i = 0; i < mali_global_num_l2_cache_cores; i++) + { + if (mali_global_l2_cache_cores[i] == cache) + { + mali_global_l2_cache_cores[i] = NULL; + mali_global_num_l2_cache_cores--; + + if (i != mali_global_num_l2_cache_cores) + { + /* We removed a l2 cache from the middle of the array -- move the last + * l2 cache to the current position to close the gap */ + mali_global_l2_cache_cores[i] = mali_global_l2_cache_cores[mali_global_num_l2_cache_cores]; + mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = NULL; + } + + break; + } + } + + _mali_osk_free(cache); +} + +u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache) +{ + return cache->core_id; +} + +mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter) +{ + u32 value = 0; /* disabled src */ + mali_bool core_is_on; + + MALI_DEBUG_ASSERT_POINTER(cache); + + core_is_on = mali_l2_cache_lock_power_state(cache); + + _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + cache->counter_src0 = counter; + + if (MALI_HW_CORE_NO_COUNTER != counter) + { + value = counter; + } + + if (MALI_TRUE == core_is_on) + { + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, value); + } + + _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + mali_l2_cache_unlock_power_state(cache); + + return MALI_TRUE; +} + +mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter) +{ + u32 value = 0; /* disabled src */ + mali_bool core_is_on; + + MALI_DEBUG_ASSERT_POINTER(cache); + + core_is_on = mali_l2_cache_lock_power_state(cache); + + _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + cache->counter_src1 = counter; + + if (MALI_HW_CORE_NO_COUNTER != counter) + { + value = counter; + } + + if (MALI_TRUE == core_is_on) + { + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, value); + } + + _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + mali_l2_cache_unlock_power_state(cache); + + return MALI_TRUE; +} + +u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache) +{ + return cache->counter_src0; +} + +u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache) +{ + return cache->counter_src1; +} + +void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1) +{ + MALI_DEBUG_ASSERT(NULL != src0); + MALI_DEBUG_ASSERT(NULL != value0); + MALI_DEBUG_ASSERT(NULL != src1); + MALI_DEBUG_ASSERT(NULL != value1); + + /* Caller must hold the PM lock and know that we are powered on */ + + _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + *src0 = cache->counter_src0; + *src1 = cache->counter_src1; + + if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) + { + *value0 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0); + } + + if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER) + { + *value1 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1); + } + + _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); +} + +struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index) +{ + if (mali_global_num_l2_cache_cores > index) + { + return mali_global_l2_cache_cores[index]; + } + + return NULL; +} + +u32 mali_l2_cache_core_get_glob_num_l2_cores(void) +{ + return mali_global_num_l2_cache_cores; +} + +void mali_l2_cache_reset(struct mali_l2_cache_core *cache) +{ + /* Invalidate cache (just to keep it in a known state at startup) */ + mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); + + /* Enable cache */ + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_ACCESS | (u32)MALI400_L2_CACHE_ENABLE_READ_ALLOCATE); + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)mali_l2_max_reads); + + /* Restart any performance counters (if enabled) */ + _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) + { + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, cache->counter_src0); + } + + if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER) + { + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, cache->counter_src1); + } + + _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); +} + +void mali_l2_cache_reset_all(void) +{ + int i; + u32 num_cores = mali_l2_cache_core_get_glob_num_l2_cores(); + + for (i = 0; i < num_cores; i++) + { + mali_l2_cache_reset(mali_l2_cache_core_get_glob_l2_core(i)); + } +} + +void mali_l2_cache_invalidate(struct mali_l2_cache_core *cache) +{ + MALI_DEBUG_ASSERT_POINTER(cache); + + if (NULL != cache) + { + cache->last_invalidated_id = mali_scheduler_get_new_id(); + mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); + } +} + +mali_bool mali_l2_cache_invalidate_conditional(struct mali_l2_cache_core *cache, u32 id) +{ + MALI_DEBUG_ASSERT_POINTER(cache); + + if (NULL != cache) + { + /* If the last cache invalidation was done by a job with a higher id we + * don't have to flush. Since user space will store jobs w/ their + * corresponding memory in sequence (first job #0, then job #1, ...), + * we don't have to flush for job n-1 if job n has already invalidated + * the cache since we know for sure that job n-1's memory was already + * written when job n was started. */ + if (((s32)id) <= ((s32)cache->last_invalidated_id)) + { + return MALI_FALSE; + } + else + { + cache->last_invalidated_id = mali_scheduler_get_new_id(); + } + + mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); + } + return MALI_TRUE; +} + +void mali_l2_cache_invalidate_all(void) +{ + u32 i; + for (i = 0; i < mali_global_num_l2_cache_cores; i++) + { + /*additional check*/ + if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_l2_cache_cores[i])) + { + _mali_osk_errcode_t ret; + mali_global_l2_cache_cores[i]->last_invalidated_id = mali_scheduler_get_new_id(); + ret = mali_l2_cache_send_command(mali_global_l2_cache_cores[i], MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to invalidate cache\n")); + } + } + mali_l2_cache_unlock_power_state(mali_global_l2_cache_cores[i]); + } +} + +void mali_l2_cache_invalidate_all_pages(u32 *pages, u32 num_pages) +{ + u32 i; + for (i = 0; i < mali_global_num_l2_cache_cores; i++) + { + /*additional check*/ + if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_l2_cache_cores[i])) + { + u32 j; + for (j = 0; j < num_pages; j++) + { + _mali_osk_errcode_t ret; + ret = mali_l2_cache_send_command(mali_global_l2_cache_cores[i], MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, pages[j]); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to invalidate page cache\n")); + } + } + } + mali_l2_cache_unlock_power_state(mali_global_l2_cache_cores[i]); + } +} + +mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache) +{ + return mali_pm_domain_lock_state(cache->pm_domain); +} + +void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache) +{ + return mali_pm_domain_unlock_state(cache->pm_domain); +} + +/* -------- local helper functions below -------- */ + + +static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val) +{ + int i = 0; + const int loop_count = 100000; + + /* + * Grab lock in order to send commands to the L2 cache in a serialized fashion. + * The L2 cache will ignore commands if it is busy. + */ + _mali_osk_lock_wait(cache->command_lock, _MALI_OSK_LOCKMODE_RW); + + /* First, wait for L2 cache command handler to go idle */ + + for (i = 0; i < loop_count; i++) + { + if (!(mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_STATUS) & (u32)MALI400_L2_CACHE_STATUS_COMMAND_BUSY)) + { + break; + } + } + + if (i == loop_count) + { + _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW); + MALI_DEBUG_PRINT(1, ( "Mali L2 cache: aborting wait for command interface to go idle\n")); + MALI_ERROR( _MALI_OSK_ERR_FAULT ); + } + + /* then issue the command */ + mali_hw_core_register_write(&cache->hw_core, reg, val); + + _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW); + + MALI_SUCCESS; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.h b/drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.h new file mode 100644 index 0000000..cabed39 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_L2_CACHE_H__ +#define __MALI_KERNEL_L2_CACHE_H__ + +#include "mali_osk.h" +#include "mali_hw_core.h" +#include "mali_pm_domain.h" + +#define MALI_MAX_NUMBER_OF_L2_CACHE_CORES 3 +/* Maximum 1 GP and 4 PP for an L2 cache core (Mali-400 Quad-core) */ +#define MALI_MAX_NUMBER_OF_GROUPS_PER_L2_CACHE 5 + +struct mali_group; + +/** + * Definition of the L2 cache core struct + * Used to track a L2 cache unit in the system. + * Contains information about the mapping of the registers + */ +struct mali_l2_cache_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + u32 core_id; /**< Unique core ID */ + _mali_osk_lock_t *command_lock; /**< Serialize all L2 cache commands */ + _mali_osk_lock_t *counter_lock; /**< Synchronize L2 cache counter access */ + u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ + u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ + u32 last_invalidated_id; + struct mali_pm_domain *pm_domain; +}; + +_mali_osk_errcode_t mali_l2_cache_initialize(void); +void mali_l2_cache_terminate(void); + +struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t * resource); +void mali_l2_cache_delete(struct mali_l2_cache_core *cache); + +MALI_STATIC_INLINE void mali_l2_cache_set_pm_domain(struct mali_l2_cache_core *cache, struct mali_pm_domain *domain) +{ + cache->pm_domain = domain; +} + +u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache); + +mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter); +mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter); +u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache); +u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache); +void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1); +struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index); +u32 mali_l2_cache_core_get_glob_num_l2_cores(void); + +void mali_l2_cache_reset(struct mali_l2_cache_core *cache); +void mali_l2_cache_reset_all(void); + +struct mali_group *mali_l2_cache_get_group(struct mali_l2_cache_core *cache, u32 index); + +void mali_l2_cache_invalidate(struct mali_l2_cache_core *cache); +mali_bool mali_l2_cache_invalidate_conditional(struct mali_l2_cache_core *cache, u32 id); +void mali_l2_cache_invalidate_all(void); +void mali_l2_cache_invalidate_all_pages(u32 *pages, u32 num_pages); + +mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache); +void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache); + +#endif /* __MALI_KERNEL_L2_CACHE_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c new file mode 100644 index 0000000..aaf9c73 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_mem_validation.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +/* MALI_SEC */ +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +//#define MALI_SEC_MEM_VALIDATION +#include +#include +#include +#endif + +#define MALI_INVALID_MEM_ADDR 0xFFFFFFFF + +typedef struct +{ + u32 phys_base; /**< Mali physical base of the memory, page aligned */ + u32 size; /**< size in bytes of the memory, multiple of page size */ +} _mali_mem_validation_t; + +/* MALI_SEC */ +#if defined(MALI_SEC_MEM_VALIDATION) +extern struct platform_device exynos4_device_pd[]; +#endif + +static _mali_mem_validation_t mali_mem_validator = { MALI_INVALID_MEM_ADDR, MALI_INVALID_MEM_ADDR }; + +_mali_osk_errcode_t mali_mem_validation_add_range(u32 start, u32 size) +{ + /* MALI_SEC */ +#if defined(MALI_SEC_MEM_VALIDATION) + struct cma_info mem_info; +#endif + + /* Check that no other MEM_VALIDATION resources exist */ + if (MALI_INVALID_MEM_ADDR != mali_mem_validator.phys_base) + { + MALI_PRINT_ERROR(("Failed to add frame buffer memory; another range is already specified\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* MALI_SEC */ +#if defined(MALI_SEC_MEM_VALIDATION) + if (cma_info(&mem_info, &exynos4_device_pd[PD_G3D].dev, "fimd")) { + MALI_PRINT_ERROR(("Failed to get framebuffer information from CMA\n")); + return _MALI_OSK_ERR_FAULT; + } else { + start = mem_info.lower_bound; + size = mem_info.total_size - mem_info.free_size; + } +#endif + + /* Check restrictions on page alignment */ + if ((0 != (start & (~_MALI_OSK_CPU_PAGE_MASK))) || + (0 != (size & (~_MALI_OSK_CPU_PAGE_MASK)))) + { + MALI_PRINT_ERROR(("Failed to add frame buffer memory; incorrect alignment\n")); + return _MALI_OSK_ERR_FAULT; + } + + mali_mem_validator.phys_base = start; + mali_mem_validator.size = size; + MALI_DEBUG_PRINT(2, ("Memory Validator installed for Mali physical address base=0x%08X, size=0x%08X\n", + mali_mem_validator.phys_base, mali_mem_validator.size)); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size) +{ + if (phys_addr < (phys_addr + size)) /* Don't allow overflow (or zero size) */ + { + if ((0 == ( phys_addr & (~_MALI_OSK_CPU_PAGE_MASK))) && + (0 == ( size & (~_MALI_OSK_CPU_PAGE_MASK)))) + { + if ((phys_addr >= mali_mem_validator.phys_base) && + ((phys_addr + (size - 1)) >= mali_mem_validator.phys_base) && + (phys_addr <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) && + ((phys_addr + (size - 1)) <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) ) + { + MALI_DEBUG_PRINT(3, ("Accepted range 0x%08X + size 0x%08X (= 0x%08X)\n", phys_addr, size, (phys_addr + size - 1))); + return _MALI_OSK_ERR_OK; + } + } + } + + MALI_PRINT_ERROR(("MALI PHYSICAL RANGE VALIDATION ERROR: The range supplied was: phys_base=0x%08X, size=0x%08X\n", phys_addr, size)); + + return _MALI_OSK_ERR_FAULT; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.h b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.h new file mode 100644 index 0000000..1eeab38 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_MEM_VALIDATION_H__ +#define __MALI_MEM_VALIDATION_H__ + +#include "mali_osk.h" + +_mali_osk_errcode_t mali_mem_validation_add_range(u32 start, u32 size); +_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size); + +#endif /* __MALI_MEM_VALIDATION_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_memory.c b/drivers/gpu/mali400/r3p2/mali/common/mali_memory.c new file mode 100644 index 0000000..1654675 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_memory.c @@ -0,0 +1,1295 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_kernel_descriptor_mapping.h" +#include "mali_mem_validation.h" +#include "mali_memory.h" +#include "mali_mmu_page_directory.h" +#include "mali_kernel_memory_engine.h" +#include "mali_block_allocator.h" +#include "mali_kernel_mem_os.h" +#include "mali_session.h" +#include "mali_l2_cache.h" +#include "mali_scheduler.h" +#if defined(CONFIG_MALI400_UMP) +#include "ump_kernel_interface.h" +#endif + +/* kernel side OS functions and user-kernel interface */ +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_ukk.h" +#include "mali_osk_list.h" +#include "mali_osk_bitops.h" + +/** + * Per-session memory descriptor mapping table sizes + */ +#define MALI_MEM_DESCRIPTORS_INIT 64 +#define MALI_MEM_DESCRIPTORS_MAX 65536 + +typedef struct dedicated_memory_info +{ + u32 base; + u32 size; + struct dedicated_memory_info * next; +} dedicated_memory_info; + +/* types used for external_memory and ump_memory physical memory allocators, which are using the mali_allocation_engine */ +#if defined(CONFIG_MALI400_UMP) +typedef struct ump_mem_allocation +{ + mali_allocation_engine * engine; + mali_memory_allocation * descriptor; + u32 initial_offset; + u32 size_allocated; + ump_dd_handle ump_mem; +} ump_mem_allocation ; +#endif + +typedef struct external_mem_allocation +{ + mali_allocation_engine * engine; + mali_memory_allocation * descriptor; + u32 initial_offset; + u32 size; +} external_mem_allocation; + +/** + * @brief Internal function for unmapping memory + * + * Worker function for unmapping memory from a user-process. We assume that the + * session/descriptor's lock was obtained before entry. For example, the + * wrapper _mali_ukk_mem_munmap() will lock the descriptor, then call this + * function to do the actual unmapping. mali_memory_core_session_end() could + * also call this directly (depending on compilation options), having locked + * the descriptor. + * + * This function will fail if it is unable to put the MMU in stall mode (which + * might be the case if a page fault is also being processed). + * + * @param args see _mali_uk_mem_munmap_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ); + +#if defined(CONFIG_MALI400_UMP) +static void ump_memory_release(void * ctx, void * handle); +static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); +#endif /* CONFIG_MALI400_UMP */ + + +static void external_memory_release(void * ctx, void * handle); +static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); + + +/* nop functions */ + +/* mali address manager needs to allocate page tables on allocate, write to page table(s) on map, write to page table(s) and release page tables on release */ +static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor); /* validates the range, allocates memory for the page tables if needed */ +static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size); +static void mali_address_manager_release(mali_memory_allocation * descriptor); + +/* MMU variables */ + +typedef struct mali_mmu_page_table_allocation +{ + _mali_osk_list_t list; + u32 * usage_map; + u32 usage_count; + u32 num_pages; + mali_page_table_block pages; +} mali_mmu_page_table_allocation; + +typedef struct mali_mmu_page_table_allocations +{ + _mali_osk_lock_t *lock; + _mali_osk_list_t partial; + _mali_osk_list_t full; + /* we never hold on to a empty allocation */ +} mali_mmu_page_table_allocations; + +static mali_kernel_mem_address_manager mali_address_manager = +{ + mali_address_manager_allocate, /* allocate */ + mali_address_manager_release, /* release */ + mali_address_manager_map, /* map_physical */ + NULL /* unmap_physical not present*/ +}; + +/* the mmu page table cache */ +static struct mali_mmu_page_table_allocations page_table_cache; + + +static mali_kernel_mem_address_manager process_address_manager = +{ + _mali_osk_mem_mapregion_init, /* allocate */ + _mali_osk_mem_mapregion_term, /* release */ + _mali_osk_mem_mapregion_map, /* map_physical */ + _mali_osk_mem_mapregion_unmap /* unmap_physical */ +}; + +static _mali_osk_errcode_t mali_mmu_page_table_cache_create(void); +static void mali_mmu_page_table_cache_destroy(void); + +static mali_allocation_engine memory_engine = NULL; +static mali_physical_memory_allocator * physical_memory_allocators = NULL; + +static dedicated_memory_info * mem_region_registrations = NULL; + +mali_allocation_engine mali_mem_get_memory_engine(void) +{ + return memory_engine; +} + +/* called during module init */ +_mali_osk_errcode_t mali_memory_initialize(void) +{ + _mali_osk_errcode_t err; + + MALI_DEBUG_PRINT(2, ("Memory system initializing\n")); + + err = mali_mmu_page_table_cache_create(); + if(_MALI_OSK_ERR_OK != err) + { + MALI_ERROR(err); + } + + memory_engine = mali_allocation_engine_create(&mali_address_manager, &process_address_manager); + MALI_CHECK_NON_NULL( memory_engine, _MALI_OSK_ERR_FAULT); + + MALI_SUCCESS; +} + +/* called if/when our module is unloaded */ +void mali_memory_terminate(void) +{ + MALI_DEBUG_PRINT(2, ("Memory system terminating\n")); + + mali_mmu_page_table_cache_destroy(); + + while ( NULL != mem_region_registrations) + { + dedicated_memory_info * m; + m = mem_region_registrations; + mem_region_registrations = m->next; + _mali_osk_mem_unreqregion(m->base, m->size); + _mali_osk_free(m); + } + + while ( NULL != physical_memory_allocators) + { + mali_physical_memory_allocator * m; + m = physical_memory_allocators; + physical_memory_allocators = m->next; + m->destroy(m); + } + + if (NULL != memory_engine) + { + mali_allocation_engine_destroy(memory_engine); + memory_engine = NULL; + } +} + +_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data * session_data) +{ + MALI_DEBUG_PRINT(5, ("Memory session begin\n")); + + /* create descriptor mapping table */ + session_data->descriptor_mapping = mali_descriptor_mapping_create(MALI_MEM_DESCRIPTORS_INIT, MALI_MEM_DESCRIPTORS_MAX); + + if (NULL == session_data->descriptor_mapping) + { + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + session_data->memory_lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK + | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_SESSION); + if (NULL == session_data->memory_lock) + { + mali_descriptor_mapping_destroy(session_data->descriptor_mapping); + _mali_osk_free(session_data); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + /* Init the session's memory allocation list */ + _MALI_OSK_INIT_LIST_HEAD( &session_data->memory_head ); + + MALI_DEBUG_PRINT(5, ("MMU session begin: success\n")); + MALI_SUCCESS; +} + +static void descriptor_table_cleanup_callback(int descriptor_id, void* map_target) +{ + mali_memory_allocation * descriptor; + + descriptor = (mali_memory_allocation*)map_target; + + MALI_DEBUG_PRINT(3, ("Cleanup of descriptor %d mapping to 0x%x in descriptor table\n", descriptor_id, map_target)); + MALI_DEBUG_ASSERT(descriptor); + + mali_allocation_engine_release_memory(memory_engine, descriptor); + _mali_osk_free(descriptor); +} + +void mali_memory_session_end(struct mali_session_data *session_data) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_BUSY; + + MALI_DEBUG_PRINT(3, ("MMU session end\n")); + + if (NULL == session_data) + { + MALI_DEBUG_PRINT(1, ("No session data found during session end\n")); + return; + } + + while (err == _MALI_OSK_ERR_BUSY) + { + /* Lock the session so we can modify the memory list */ + _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + err = _MALI_OSK_ERR_OK; + + /* Free all memory engine allocations */ + if (!_mali_osk_list_empty(&session_data->memory_head)) + { + mali_memory_allocation *descriptor; + mali_memory_allocation *temp; + _mali_uk_mem_munmap_s unmap_args; + + MALI_DEBUG_PRINT(1, ("Memory found on session usage list during session termination\n")); + + unmap_args.ctx = session_data; + + /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */ + _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->memory_head, mali_memory_allocation, list) + { + MALI_DEBUG_PRINT(4, ("Freeing block with mali address 0x%x size %d mapped in user space at 0x%x\n", + descriptor->mali_address, descriptor->size, descriptor->size, descriptor->mapping) + ); + /* ASSERT that the descriptor's lock references the correct thing */ + MALI_DEBUG_ASSERT( descriptor->lock == session_data->memory_lock ); + /* Therefore, we have already locked the descriptor */ + + unmap_args.size = descriptor->size; + unmap_args.mapping = descriptor->mapping; + unmap_args.cookie = (u32)descriptor; + + /* + * This removes the descriptor from the list, and frees the descriptor + * + * Does not handle the _MALI_OSK_SPECIFIC_INDIRECT_MMAP case, since + * the only OS we are aware of that requires indirect MMAP also has + * implicit mmap cleanup. + */ + err = _mali_ukk_mem_munmap_internal( &unmap_args ); + + if (err == _MALI_OSK_ERR_BUSY) + { + _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + /* + * Reason for this; + * We where unable to stall the MMU, probably because we are in page fault handling. + * Sleep for a while with the session lock released, then try again. + * Abnormal termination of programs with running Mali jobs is a normal reason for this. + */ + _mali_osk_time_ubusydelay(10); + break; /* Will jump back into: "while (err == _MALI_OSK_ERR_BUSY)" */ + } + } + } + } + /* Assert that we really did free everything */ + MALI_DEBUG_ASSERT( _mali_osk_list_empty(&session_data->memory_head) ); + + if (NULL != session_data->descriptor_mapping) + { + mali_descriptor_mapping_call_for_each(session_data->descriptor_mapping, descriptor_table_cleanup_callback); + mali_descriptor_mapping_destroy(session_data->descriptor_mapping); + session_data->descriptor_mapping = NULL; + } + + _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + /** + * @note Could the VMA close handler mean that we use the session data after it was freed? + * In which case, would need to refcount the session data, and free on VMA close + */ + + /* Free the lock */ + _mali_osk_lock_term( session_data->memory_lock ); + + return; +} + +_mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size) +{ + mali_physical_memory_allocator * allocator; + mali_physical_memory_allocator ** next_allocator_list; + + u32 alloc_order = 1; /* OS memory has second priority */ + + allocator = mali_os_allocator_create(size, 0 /* cpu_usage_adjust */, "Shared Mali GPU memory"); + if (NULL == allocator) + { + MALI_DEBUG_PRINT(1, ("Failed to create OS memory allocator\n")); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + allocator->alloc_order = alloc_order; + + /* link in the allocator: insertion into ordered list + * resources of the same alloc_order will be Last-in-first */ + next_allocator_list = &physical_memory_allocators; + + while (NULL != *next_allocator_list && + (*next_allocator_list)->alloc_order < alloc_order ) + { + next_allocator_list = &((*next_allocator_list)->next); + } + + allocator->next = (*next_allocator_list); + (*next_allocator_list) = allocator; + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size) +{ + mali_physical_memory_allocator * allocator; + mali_physical_memory_allocator ** next_allocator_list; + dedicated_memory_info * cleanup_data; + + u32 alloc_order = 0; /* Dedicated range has first priority */ + + /* do the low level linux operation first */ + + /* Request ownership of the memory */ + if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(start, size, "Dedicated Mali GPU memory")) + { + MALI_DEBUG_PRINT(1, ("Failed to request memory region for frame buffer (0x%08X - 0x%08X)\n", start, start + size - 1)); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + /* create generic block allocator object to handle it */ + allocator = mali_block_allocator_create(start, 0 /* cpu_usage_adjust */, size, "Dedicated Mali GPU memory"); + + if (NULL == allocator) + { + MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n")); + _mali_osk_mem_unreqregion(start, size); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + /* save low level cleanup info */ + allocator->alloc_order = alloc_order; + + cleanup_data = _mali_osk_malloc(sizeof(dedicated_memory_info)); + + if (NULL == cleanup_data) + { + _mali_osk_mem_unreqregion(start, size); + allocator->destroy(allocator); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + cleanup_data->base = start; + cleanup_data->size = size; + + cleanup_data->next = mem_region_registrations; + mem_region_registrations = cleanup_data; + + /* link in the allocator: insertion into ordered list + * resources of the same alloc_order will be Last-in-first */ + next_allocator_list = &physical_memory_allocators; + + while ( NULL != *next_allocator_list && + (*next_allocator_list)->alloc_order < alloc_order ) + { + next_allocator_list = &((*next_allocator_list)->next); + } + + allocator->next = (*next_allocator_list); + (*next_allocator_list) = allocator; + + MALI_SUCCESS; +} + +#if defined(CONFIG_MALI400_UMP) +static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + ump_dd_handle ump_mem; + u32 nr_blocks; + u32 i; + ump_dd_physical_block * ump_blocks; + ump_mem_allocation *ret_allocation; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + ret_allocation = _mali_osk_malloc( sizeof( ump_mem_allocation ) ); + if ( NULL==ret_allocation ) return MALI_MEM_ALLOC_INTERNAL_FAILURE; + + ump_mem = (ump_dd_handle)ctx; + + MALI_DEBUG_PRINT(4, ("In ump_memory_commit\n")); + + nr_blocks = ump_dd_phys_block_count_get(ump_mem); + + MALI_DEBUG_PRINT(4, ("Have %d blocks\n", nr_blocks)); + + if (nr_blocks == 0) + { + MALI_DEBUG_PRINT(1, ("No block count\n")); + _mali_osk_free( ret_allocation ); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + + ump_blocks = _mali_osk_malloc(sizeof(*ump_blocks)*nr_blocks ); + if ( NULL==ump_blocks ) + { + _mali_osk_free( ret_allocation ); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + + if (UMP_DD_INVALID == ump_dd_phys_blocks_get(ump_mem, ump_blocks, nr_blocks)) + { + _mali_osk_free(ump_blocks); + _mali_osk_free( ret_allocation ); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + + /* Store away the initial offset for unmapping purposes */ + ret_allocation->initial_offset = *offset; + + for(i=0; iinitial_offset; + MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n")); + + /* unmap all previous blocks (if any) */ + mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 ); + + _mali_osk_free(ump_blocks); + _mali_osk_free(ret_allocation); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + *offset += ump_blocks[i].size; + } + + if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) + { + /* Map in an extra virtual guard page at the end of the VMA */ + MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n")); + if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[0].addr , 0, _MALI_OSK_MALI_PAGE_SIZE )) + { + u32 size_allocated = *offset - ret_allocation->initial_offset; + MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n")); + + /* unmap all previous blocks (if any) */ + mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 ); + + _mali_osk_free(ump_blocks); + _mali_osk_free(ret_allocation); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + *offset += _MALI_OSK_MALI_PAGE_SIZE; + } + + _mali_osk_free( ump_blocks ); + + ret_allocation->engine = engine; + ret_allocation->descriptor = descriptor; + ret_allocation->ump_mem = ump_mem; + ret_allocation->size_allocated = *offset - ret_allocation->initial_offset; + + alloc_info->ctx = NULL; + alloc_info->handle = ret_allocation; + alloc_info->next = NULL; + alloc_info->release = ump_memory_release; + + return MALI_MEM_ALLOC_FINISHED; +} + +static void ump_memory_release(void * ctx, void * handle) +{ + ump_dd_handle ump_mem; + ump_mem_allocation *allocation; + + allocation = (ump_mem_allocation *)handle; + + MALI_DEBUG_ASSERT_POINTER( allocation ); + + ump_mem = allocation->ump_mem; + + MALI_DEBUG_ASSERT(UMP_DD_HANDLE_INVALID!=ump_mem); + + /* At present, this is a no-op. But, it allows the mali_address_manager to + * do unmapping of a subrange in future. */ + mali_allocation_engine_unmap_physical( allocation->engine, + allocation->descriptor, + allocation->initial_offset, + allocation->size_allocated, + (_mali_osk_mem_mapregion_flags_t)0 + ); + _mali_osk_free( allocation ); + + + ump_dd_reference_release(ump_mem) ; + return; +} + +_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args ) +{ + ump_dd_handle ump_mem; + mali_physical_memory_allocator external_memory_allocator; + struct mali_session_data *session_data; + mali_memory_allocation * descriptor; + int md; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)args->ctx; + MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); + + /* check arguments */ + /* NULL might be a valid Mali address */ + if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + + /* size must be a multiple of the system page size */ + if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + + MALI_DEBUG_PRINT(3, + ("Requested to map ump memory with secure id %d into virtual memory 0x%08X, size 0x%08X\n", + args->secure_id, args->mali_address, args->size)); + + ump_mem = ump_dd_handle_create_from_secure_id( (int)args->secure_id ) ; + + if ( UMP_DD_HANDLE_INVALID==ump_mem ) MALI_ERROR(_MALI_OSK_ERR_FAULT); + + descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); + if (NULL == descriptor) + { + ump_dd_reference_release(ump_mem); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + descriptor->size = args->size; + descriptor->mapping = NULL; + descriptor->mali_address = args->mali_address; + descriptor->mali_addr_mapping_info = (void*)session_data; + descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ + descriptor->cache_settings = (u32) MALI_CACHE_STANDARD; + descriptor->lock = session_data->memory_lock; + + if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) + { + descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; + } + _mali_osk_list_init( &descriptor->list ); + + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md)) + { + ump_dd_reference_release(ump_mem); + _mali_osk_free(descriptor); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + external_memory_allocator.allocate = ump_memory_commit; + external_memory_allocator.allocate_page_table_block = NULL; + external_memory_allocator.ctx = ump_mem; + external_memory_allocator.name = "UMP Memory"; + external_memory_allocator.next = NULL; + + _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL)) + { + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + mali_descriptor_mapping_free(session_data->descriptor_mapping, md); + ump_dd_reference_release(ump_mem); + _mali_osk_free(descriptor); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + args->cookie = md; + + MALI_DEBUG_PRINT(5,("Returning from UMP attach\n")); + + /* All OK */ + MALI_SUCCESS; +} + + +_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args ) +{ + mali_memory_allocation * descriptor; + struct mali_session_data *session_data; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)args->ctx; + MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); + + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor)) + { + MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release ump memory\n", args->cookie)); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + descriptor = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie); + + if (NULL != descriptor) + { + _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + mali_allocation_engine_release_memory(memory_engine, descriptor); + + _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + _mali_osk_free(descriptor); + } + + MALI_SUCCESS; + +} +#endif /* CONFIG_MALI400_UMP */ + + +static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + u32 * data; + external_mem_allocation * ret_allocation; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + ret_allocation = _mali_osk_malloc( sizeof(external_mem_allocation) ); + + if ( NULL == ret_allocation ) + { + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + + data = (u32*)ctx; + + ret_allocation->engine = engine; + ret_allocation->descriptor = descriptor; + ret_allocation->initial_offset = *offset; + + alloc_info->ctx = NULL; + alloc_info->handle = ret_allocation; + alloc_info->next = NULL; + alloc_info->release = external_memory_release; + + MALI_DEBUG_PRINT(5, ("External map: mapping phys 0x%08X at mali virtual address 0x%08X staring at offset 0x%08X length 0x%08X\n", data[0], descriptor->mali_address, *offset, data[1])); + + if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, data[1])) + { + MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n")); + _mali_osk_free(ret_allocation); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + *offset += data[1]; + + if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) + { + /* Map in an extra virtual guard page at the end of the VMA */ + MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n")); + if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, _MALI_OSK_MALI_PAGE_SIZE)) + { + u32 size_allocated = *offset - ret_allocation->initial_offset; + MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n")); + + /* unmap what we previously mapped */ + mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 ); + _mali_osk_free(ret_allocation); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + *offset += _MALI_OSK_MALI_PAGE_SIZE; + } + + ret_allocation->size = *offset - ret_allocation->initial_offset; + + return MALI_MEM_ALLOC_FINISHED; +} + +static void external_memory_release(void * ctx, void * handle) +{ + external_mem_allocation * allocation; + + allocation = (external_mem_allocation *) handle; + MALI_DEBUG_ASSERT_POINTER( allocation ); + + /* At present, this is a no-op. But, it allows the mali_address_manager to + * do unmapping of a subrange in future. */ + + mali_allocation_engine_unmap_physical( allocation->engine, + allocation->descriptor, + allocation->initial_offset, + allocation->size, + (_mali_osk_mem_mapregion_flags_t)0 + ); + + _mali_osk_free( allocation ); + + return; +} + +_mali_osk_errcode_t _mali_ukk_mem_write_safe(_mali_uk_mem_write_safe_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + + if (NULL == args->ctx) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } + + /* Return number of bytes actually copied */ + args->size = _mali_osk_mem_write_safe(args->dest, args->src, args->size); + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args ) +{ + mali_physical_memory_allocator external_memory_allocator; + struct mali_session_data *session_data; + u32 info[2]; + mali_memory_allocation * descriptor; + int md; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)args->ctx; + MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); + + external_memory_allocator.allocate = external_memory_commit; + external_memory_allocator.allocate_page_table_block = NULL; + external_memory_allocator.ctx = &info[0]; + external_memory_allocator.name = "External Memory"; + external_memory_allocator.next = NULL; + + /* check arguments */ + /* NULL might be a valid Mali address */ + if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + + /* size must be a multiple of the system page size */ + if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + + MALI_DEBUG_PRINT(3, + ("Requested to map physical memory 0x%x-0x%x into virtual memory 0x%x\n", + (void*)args->phys_addr, + (void*)(args->phys_addr + args->size -1), + (void*)args->mali_address) + ); + + /* Validate the mali physical range */ + if (_MALI_OSK_ERR_OK != mali_mem_validation_check(args->phys_addr, args->size)) + { + return _MALI_OSK_ERR_FAULT; + } + + info[0] = args->phys_addr; + info[1] = args->size; + + descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); + if (NULL == descriptor) MALI_ERROR(_MALI_OSK_ERR_NOMEM); + + descriptor->size = args->size; + descriptor->mapping = NULL; + descriptor->mali_address = args->mali_address; + descriptor->mali_addr_mapping_info = (void*)session_data; + descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ + descriptor->cache_settings = (u32)MALI_CACHE_STANDARD; + descriptor->lock = session_data->memory_lock; + if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) + { + descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; + } + _mali_osk_list_init( &descriptor->list ); + + _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL)) + { + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_free(descriptor); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md)) + { + mali_allocation_engine_release_memory(memory_engine, descriptor); + _mali_osk_free(descriptor); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + args->cookie = md; + + MALI_DEBUG_PRINT(5,("Returning from range_map_external_memory\n")); + + /* All OK */ + MALI_SUCCESS; +} + + +_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args ) +{ + mali_memory_allocation * descriptor; + void* old_value; + struct mali_session_data *session_data; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)args->ctx; + MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); + + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor)) + { + MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to unmap external memory\n", args->cookie)); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + old_value = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie); + + if (NULL != old_value) + { + _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + mali_allocation_engine_release_memory(memory_engine, descriptor); + + _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + _mali_osk_free(descriptor); + } + + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args ) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + args->memory_size = 2 * 1024 * 1024 * 1024UL; /* 2GB address space */ + args->mali_address_base = 1 * 1024 * 1024 * 1024UL; /* staring at 1GB, causing this layout: (0-1GB unused)(1GB-3G usage by Mali)(3G-4G unused) */ + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args ) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + MALI_SUCCESS; +} + +static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor) +{ + struct mali_session_data *session_data; + u32 actual_size; + + MALI_DEBUG_ASSERT_POINTER(descriptor); + + session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + + actual_size = descriptor->size; + + if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) + { + actual_size += _MALI_OSK_MALI_PAGE_SIZE; + } + + return mali_mmu_pagedir_map(session_data->page_directory, descriptor->mali_address, actual_size); +} + +static void mali_address_manager_release(mali_memory_allocation * descriptor) +{ + const u32 illegal_mali_address = 0xffffffff; + struct mali_session_data *session_data; + MALI_DEBUG_ASSERT_POINTER(descriptor); + + /* It is allowed to call this function several times on the same descriptor. + When memory is released we set the illegal_mali_address so we can early out here. */ + if ( illegal_mali_address == descriptor->mali_address) return; + + session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + mali_mmu_pagedir_unmap(session_data->page_directory, descriptor->mali_address, descriptor->size); + + descriptor->mali_address = illegal_mali_address ; +} + +static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size) +{ + struct mali_session_data *session_data; + u32 mali_address; + + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(phys_addr); + + session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + MALI_DEBUG_ASSERT_POINTER(session_data); + + mali_address = descriptor->mali_address + offset; + + MALI_DEBUG_PRINT(7, ("Mali map: mapping 0x%08X to Mali address 0x%08X length 0x%08X\n", *phys_addr, mali_address, size)); + + mali_mmu_pagedir_update(session_data->page_directory, mali_address, *phys_addr, size, descriptor->cache_settings); + + MALI_SUCCESS; +} + +/* This handler registered to mali_mmap for MMU builds */ +_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args ) +{ + struct mali_session_data *session_data; + mali_memory_allocation * descriptor; + + /* validate input */ + if (NULL == args) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: args was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); } + + /* Unpack arguments */ + session_data = (struct mali_session_data *)args->ctx; + + /* validate input */ + if (NULL == session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_FAULT); } + + descriptor = (mali_memory_allocation*) _mali_osk_calloc( 1, sizeof(mali_memory_allocation) ); + if (NULL == descriptor) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: descriptor was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_NOMEM); } + + descriptor->size = args->size; + descriptor->mali_address = args->phys_addr; + descriptor->mali_addr_mapping_info = (void*)session_data; + + descriptor->process_addr_mapping_info = args->ukk_private; /* save to be used during physical manager callback */ + descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE; + descriptor->cache_settings = (u32) args->cache_settings ; + descriptor->lock = session_data->memory_lock; + _mali_osk_list_init( &descriptor->list ); + + _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + if (0 == mali_allocation_engine_allocate_memory(memory_engine, descriptor, physical_memory_allocators, &session_data->memory_head)) + { + /* We do not FLUSH nor TLB_ZAP on MMAP, since we do both of those on job start*/ + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + args->mapping = descriptor->mapping; + args->cookie = (u32)descriptor; + + MALI_DEBUG_PRINT(7, ("MMAP OK\n")); + MALI_SUCCESS; + } + else + { + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + /* OOM, but not a fatal error */ + MALI_DEBUG_PRINT(4, ("Memory allocation failure, OOM\n")); + _mali_osk_free(descriptor); + /* Linux will free the CPU address allocation, userspace client the Mali address allocation */ + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } +} + +static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ) +{ + struct mali_session_data *session_data; + mali_memory_allocation * descriptor; + + descriptor = (mali_memory_allocation *)args->cookie; + MALI_DEBUG_ASSERT_POINTER(descriptor); + + /** @note args->context unused; we use the memory_session from the cookie */ + /* args->mapping and args->size are also discarded. They are only necessary + for certain do_munmap implementations. However, they could be used to check the + descriptor at this point. */ + + session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + MALI_DEBUG_ASSERT_POINTER(session_data); + + /* Unmapping the memory from the mali virtual address space. + It is allowed to call this function severeal times, which might happen if zapping below fails. */ + mali_allocation_engine_release_pt1_mali_pagetables_unmap(memory_engine, descriptor); + + mali_scheduler_zap_all_active(session_data); + + /* Removes the descriptor from the session's memory list, releases physical memory, releases descriptor */ + mali_allocation_engine_release_pt2_physical_memory_free(memory_engine, descriptor); + + _mali_osk_free(descriptor); + + return _MALI_OSK_ERR_OK; +} + +/* Handler for unmapping memory for MMU builds */ +_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args ) +{ + mali_memory_allocation * descriptor; + _mali_osk_lock_t *descriptor_lock; + _mali_osk_errcode_t err; + + descriptor = (mali_memory_allocation *)args->cookie; + MALI_DEBUG_ASSERT_POINTER(descriptor); + + /** @note args->context unused; we use the memory_session from the cookie */ + /* args->mapping and args->size are also discarded. They are only necessary + for certain do_munmap implementations. However, they could be used to check the + descriptor at this point. */ + + MALI_DEBUG_ASSERT_POINTER((struct mali_session_data *)descriptor->mali_addr_mapping_info); + + descriptor_lock = descriptor->lock; /* should point to the session data lock... */ + + err = _MALI_OSK_ERR_BUSY; + while (err == _MALI_OSK_ERR_BUSY) + { + if (descriptor_lock) + { + _mali_osk_lock_wait( descriptor_lock, _MALI_OSK_LOCKMODE_RW ); + } + + err = _mali_ukk_mem_munmap_internal( args ); + + if (descriptor_lock) + { + _mali_osk_lock_signal( descriptor_lock, _MALI_OSK_LOCKMODE_RW ); + } + + if (err == _MALI_OSK_ERR_BUSY) + { + /* + * Reason for this; + * We where unable to stall the MMU, probably because we are in page fault handling. + * Sleep for a while with the session lock released, then try again. + * Abnormal termination of programs with running Mali jobs is a normal reason for this. + */ + _mali_osk_time_ubusydelay(10); + } + } + + return err; +} + +u32 _mali_ukk_report_memory_usage(void) +{ + return mali_allocation_engine_memory_usage(physical_memory_allocators); +} + +_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping) +{ + _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + + if (!_mali_osk_list_empty(&page_table_cache.partial)) + { + mali_mmu_page_table_allocation * alloc = _MALI_OSK_LIST_ENTRY(page_table_cache.partial.next, mali_mmu_page_table_allocation, list); + int page_number = _mali_osk_find_first_zero_bit(alloc->usage_map, alloc->num_pages); + MALI_DEBUG_PRINT(6, ("Partial page table allocation found, using page offset %d\n", page_number)); + _mali_osk_set_nonatomic_bit(page_number, alloc->usage_map); + alloc->usage_count++; + if (alloc->num_pages == alloc->usage_count) + { + /* full, move alloc to full list*/ + _mali_osk_list_move(&alloc->list, &page_table_cache.full); + } + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + + *table_page = (MALI_MMU_PAGE_SIZE * page_number) + alloc->pages.phys_base; + *mapping = (mali_io_address)((MALI_MMU_PAGE_SIZE * page_number) + (u32)alloc->pages.mapping); + MALI_DEBUG_PRINT(4, ("Page table allocated for VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page )); + MALI_SUCCESS; + } + else + { + mali_mmu_page_table_allocation * alloc; + /* no free pages, allocate a new one */ + + alloc = (mali_mmu_page_table_allocation *)_mali_osk_calloc(1, sizeof(mali_mmu_page_table_allocation)); + if (NULL == alloc) + { + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + *table_page = MALI_INVALID_PAGE; + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + _MALI_OSK_INIT_LIST_HEAD(&alloc->list); + + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_page_tables(memory_engine, &alloc->pages, physical_memory_allocators)) + { + MALI_DEBUG_PRINT(1, ("No more memory for page tables\n")); + _mali_osk_free(alloc); + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + *table_page = MALI_INVALID_PAGE; + *mapping = NULL; + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + /* create the usage map */ + alloc->num_pages = alloc->pages.size / MALI_MMU_PAGE_SIZE; + alloc->usage_count = 1; + MALI_DEBUG_PRINT(3, ("New page table cache expansion, %d pages in new cache allocation\n", alloc->num_pages)); + alloc->usage_map = _mali_osk_calloc(1, ((alloc->num_pages + BITS_PER_LONG - 1) & ~(BITS_PER_LONG-1) / BITS_PER_LONG) * sizeof(unsigned long)); + if (NULL == alloc->usage_map) + { + MALI_DEBUG_PRINT(1, ("Failed to allocate memory to describe MMU page table cache usage\n")); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc); + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + *table_page = MALI_INVALID_PAGE; + *mapping = NULL; + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + _mali_osk_set_nonatomic_bit(0, alloc->usage_map); + + if (alloc->num_pages > 1) + { + _mali_osk_list_add(&alloc->list, &page_table_cache.partial); + } + else + { + _mali_osk_list_add(&alloc->list, &page_table_cache.full); + } + + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + *table_page = alloc->pages.phys_base; /* return the first page */ + *mapping = alloc->pages.mapping; /* Mapping for first page */ + MALI_DEBUG_PRINT(4, ("Page table allocated: VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page )); + MALI_SUCCESS; + } +} + +void mali_mmu_release_table_page(u32 pa) +{ + mali_mmu_page_table_allocation * alloc, * temp_alloc; + + MALI_DEBUG_PRINT_IF(1, pa & 4095, ("Bad page address 0x%x given to mali_mmu_release_table_page\n", (void*)pa)); + + MALI_DEBUG_PRINT(4, ("Releasing table page 0x%08X to the cache\n", pa)); + + _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + + /* find the entry this address belongs to */ + /* first check the partial list */ + _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.partial, mali_mmu_page_table_allocation, list) + { + u32 start = alloc->pages.phys_base; + u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE; + if (pa >= start && pa <= last) + { + MALI_DEBUG_ASSERT(0 != _mali_osk_test_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map)); + _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map); + alloc->usage_count--; + + _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE); + + if (0 == alloc->usage_count) + { + /* empty, release whole page alloc */ + _mali_osk_list_del(&alloc->list); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc->usage_map); + _mali_osk_free(alloc); + } + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + MALI_DEBUG_PRINT(4, ("(partial list)Released table page 0x%08X to the cache\n", pa)); + return; + } + } + + /* the check the full list */ + _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.full, mali_mmu_page_table_allocation, list) + { + u32 start = alloc->pages.phys_base; + u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE; + if (pa >= start && pa <= last) + { + _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map); + alloc->usage_count--; + + _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE); + + + if (0 == alloc->usage_count) + { + /* empty, release whole page alloc */ + _mali_osk_list_del(&alloc->list); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc->usage_map); + _mali_osk_free(alloc); + } + else + { + /* transfer to partial list */ + _mali_osk_list_move(&alloc->list, &page_table_cache.partial); + } + + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + MALI_DEBUG_PRINT(4, ("(full list)Released table page 0x%08X to the cache\n", pa)); + return; + } + } + + MALI_DEBUG_PRINT(1, ("pa 0x%x not found in the page table cache\n", (void*)pa)); + + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); +} + +static _mali_osk_errcode_t mali_mmu_page_table_cache_create(void) +{ + page_table_cache.lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK + | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE); + MALI_CHECK_NON_NULL( page_table_cache.lock, _MALI_OSK_ERR_FAULT ); + _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.partial); + _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.full); + MALI_SUCCESS; +} + +static void mali_mmu_page_table_cache_destroy(void) +{ + mali_mmu_page_table_allocation * alloc, *temp; + + _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.partial, mali_mmu_page_table_allocation, list) + { + MALI_DEBUG_PRINT_IF(1, 0 != alloc->usage_count, ("Destroying page table cache while pages are tagged as in use. %d allocations still marked as in use.\n", alloc->usage_count)); + _mali_osk_list_del(&alloc->list); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc->usage_map); + _mali_osk_free(alloc); + } + + MALI_DEBUG_PRINT_IF(1, !_mali_osk_list_empty(&page_table_cache.full), ("Page table cache full list contains one or more elements \n")); + + _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.full, mali_mmu_page_table_allocation, list) + { + MALI_DEBUG_PRINT(1, ("Destroy alloc 0x%08X with usage count %d\n", (u32)alloc, alloc->usage_count)); + _mali_osk_list_del(&alloc->list); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc->usage_map); + _mali_osk_free(alloc); + } + + _mali_osk_lock_term(page_table_cache.lock); +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_memory.h b/drivers/gpu/mali400/r3p2/mali/common/mali_memory.h new file mode 100644 index 0000000..537c346 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_memory.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_MEMORY_H__ +#define __MALI_MEMORY_H__ + +#include "mali_osk.h" +#include "mali_session.h" + +/** @brief Initialize Mali memory subsystem + * + * Allocate and initialize internal data structures. Must be called before + * allocating Mali memory. + * + * @return On success _MALI_OSK_ERR_OK, othervise some error code describing the error. + */ +_mali_osk_errcode_t mali_memory_initialize(void); + +/** @brief Terminate Mali memory system + * + * Clean up and release internal data structures. + */ +void mali_memory_terminate(void); + +/** @brief Start new Mali memory session + * + * Allocate and prepare session specific memory allocation data data. The + * session page directory, lock, and descriptor map is set up. + * + * @param mali_session_data pointer to the session data structure + */ +_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data *mali_session_data); + +/** @brief Close a Mali memory session + * + * Release session specific memory allocation related data. + * + * @param mali_session_data pointer to the session data structure + */ +void mali_memory_session_end(struct mali_session_data *mali_session_data); + +/** @brief Allocate a page table page + * + * Allocate a page for use as a page directory or page table. The page is + * mapped into kernel space. + * + * @return _MALI_OSK_ERR_OK on success, othervise an error code + * @param table_page GPU pointer to the allocated page + * @param mapping CPU pointer to the mapping of the allocated page + */ +_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping); + +/** @brief Release a page table page + * + * Release a page table page allocated through \a mali_mmu_get_table_page + * + * @param pa the GPU address of the page to release + */ +void mali_mmu_release_table_page(u32 pa); + + +/** @brief Parse resource and prepare the OS memory allocator + * + * @param size Maximum size to allocate for Mali GPU. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size); + +/** @brief Parse resource and prepare the dedicated memory allocator + * + * @param start Physical start address of dedicated Mali GPU memory. + * @param size Size of dedicated Mali GPU memory. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size); + +mali_allocation_engine mali_mem_get_memory_engine(void); + +#endif /* __MALI_MEMORY_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.c b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.c new file mode 100644 index 0000000..158cccf --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.c @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_bitops.h" +#include "mali_osk_list.h" +#include "mali_ukk.h" + +#include "mali_mmu.h" +#include "mali_hw_core.h" +#include "mali_group.h" +#include "mali_mmu_page_directory.h" + +/** + * Size of the MMU registers in bytes + */ +#define MALI_MMU_REGISTERS_SIZE 0x24 + +/** + * MMU commands + * These are the commands that can be sent + * to the MMU unit. + */ +typedef enum mali_mmu_command +{ + MALI_MMU_COMMAND_ENABLE_PAGING = 0x00, /**< Enable paging (memory translation) */ + MALI_MMU_COMMAND_DISABLE_PAGING = 0x01, /**< Disable paging (memory translation) */ + MALI_MMU_COMMAND_ENABLE_STALL = 0x02, /**< Enable stall on page fault */ + MALI_MMU_COMMAND_DISABLE_STALL = 0x03, /**< Disable stall on page fault */ + MALI_MMU_COMMAND_ZAP_CACHE = 0x04, /**< Zap the entire page table cache */ + MALI_MMU_COMMAND_PAGE_FAULT_DONE = 0x05, /**< Page fault processed */ + MALI_MMU_COMMAND_HARD_RESET = 0x06 /**< Reset the MMU back to power-on settings */ +} mali_mmu_command; + +static void mali_mmu_probe_trigger(void *data); +static _mali_osk_errcode_t mali_mmu_probe_ack(void *data); + +MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu); + +/* page fault queue flush helper pages + * note that the mapping pointers are currently unused outside of the initialization functions */ +static u32 mali_page_fault_flush_page_directory = MALI_INVALID_PAGE; +static u32 mali_page_fault_flush_page_table = MALI_INVALID_PAGE; +static u32 mali_page_fault_flush_data_page = MALI_INVALID_PAGE; + +/* an empty page directory (no address valid) which is active on any MMU not currently marked as in use */ +static u32 mali_empty_page_directory = MALI_INVALID_PAGE; + +_mali_osk_errcode_t mali_mmu_initialize(void) +{ + /* allocate the helper pages */ + mali_empty_page_directory = mali_allocate_empty_page(); + if(0 == mali_empty_page_directory) + { + mali_empty_page_directory = MALI_INVALID_PAGE; + return _MALI_OSK_ERR_NOMEM; + } + + if (_MALI_OSK_ERR_OK != mali_create_fault_flush_pages(&mali_page_fault_flush_page_directory, + &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page)) + { + mali_free_empty_page(mali_empty_page_directory); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; +} + +void mali_mmu_terminate(void) +{ + MALI_DEBUG_PRINT(3, ("Mali MMU: terminating\n")); + + /* Free global helper pages */ + mali_free_empty_page(mali_empty_page_directory); + + /* Free the page fault flush pages */ + mali_destroy_fault_flush_pages(&mali_page_fault_flush_page_directory, + &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page); +} + +struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual) +{ + struct mali_mmu_core* mmu = NULL; + + MALI_DEBUG_ASSERT_POINTER(resource); + + MALI_DEBUG_PRINT(2, ("Mali MMU: Creating Mali MMU: %s\n", resource->description)); + + mmu = _mali_osk_calloc(1,sizeof(struct mali_mmu_core)); + if (NULL != mmu) + { + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE)) + { + if (_MALI_OSK_ERR_OK == mali_group_add_mmu_core(group, mmu)) + { + if (is_virtual) + { + /* Skip reset and IRQ setup for virtual MMU */ + return mmu; + } + + if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu)) + { + /* Setup IRQ handlers (which will do IRQ probing if needed) */ + mmu->irq = _mali_osk_irq_init(resource->irq, + mali_group_upper_half_mmu, + group, + mali_mmu_probe_trigger, + mali_mmu_probe_ack, + mmu, + "mali_mmu_irq_handlers"); + if (NULL != mmu->irq) + { + return mmu; + } + else + { + MALI_PRINT_ERROR(("Mali MMU: Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description)); + } + } + mali_group_remove_mmu_core(group); + } + else + { + MALI_PRINT_ERROR(("Mali MMU: Failed to add core %s to group\n", mmu->hw_core.description)); + } + mali_hw_core_delete(&mmu->hw_core); + } + + _mali_osk_free(mmu); + } + else + { + MALI_PRINT_ERROR(("Failed to allocate memory for MMU\n")); + } + + return NULL; +} + +void mali_mmu_delete(struct mali_mmu_core *mmu) +{ + if (NULL != mmu->irq) + { + _mali_osk_irq_term(mmu->irq); + } + + mali_hw_core_delete(&mmu->hw_core); + _mali_osk_free(mmu); +} + +static void mali_mmu_enable_paging(struct mali_mmu_core *mmu) +{ + int i; + + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING); + + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) + { + if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED) + { + break; + } + } + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_PRINT_ERROR(("Enable paging request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); + } +} + +mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu) +{ + int i; + u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + + if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) ) + { + MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enabled.\n")); + return MALI_TRUE; + } + + if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) + { + MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it is in pagefault state.\n")); + return MALI_FALSE; + } + + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL); + + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) + { + mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) + { + break; + } + if ((mmu_status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) && (0 == (mmu_status & MALI_MMU_STATUS_BIT_STALL_NOT_ACTIVE))) + { + break; + } + if (0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED ))) + { + break; + } + } + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_DEBUG_PRINT(2, ("Enable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); + return MALI_FALSE; + } + + if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) + { + MALI_DEBUG_PRINT(2, ("Aborting MMU stall request since it has a pagefault.\n")); + return MALI_FALSE; + } + + return MALI_TRUE; +} + +void mali_mmu_disable_stall(struct mali_mmu_core *mmu) +{ + int i; + u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + + if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) + { + MALI_DEBUG_PRINT(3, ("MMU disable skipped since it was not enabled.\n")); + return; + } + if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) + { + MALI_DEBUG_PRINT(2, ("Aborting MMU disable stall request since it is in pagefault state.\n")); + return; + } + + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL); + + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) + { + u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) ) + { + break; + } + if ( status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) + { + break; + } + if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) + { + break; + } + } + if (MALI_REG_POLL_COUNT_FAST == i) MALI_DEBUG_PRINT(1,("Disable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); +} + +void mali_mmu_page_fault_done(struct mali_mmu_core *mmu) +{ + MALI_DEBUG_PRINT(4, ("Mali MMU: %s: Leaving page fault mode\n", mmu->hw_core.description)); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE); +} + +MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu) +{ + int i; + + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE); + MALI_DEBUG_ASSERT(0xCAFEB000 == mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR)); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_HARD_RESET); + + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) + { + if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR) == 0) + { + break; + } + } + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_PRINT_ERROR(("Reset request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + mali_bool stall_success; + MALI_DEBUG_ASSERT_POINTER(mmu); + + stall_success = mali_mmu_enable_stall(mmu); + if (!stall_success) + { + err = _MALI_OSK_ERR_BUSY; + } + + MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description)); + + if (_MALI_OSK_ERR_OK == mali_mmu_raw_reset(mmu)) + { + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR); + /* no session is active, so just activate the empty page directory */ + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory); + mali_mmu_enable_paging(mmu); + err = _MALI_OSK_ERR_OK; + } + mali_mmu_disable_stall(mmu); + + return err; +} + +mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu) +{ + mali_bool stall_success = mali_mmu_enable_stall(mmu); + + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); + + if (MALI_FALSE == stall_success) + { + /* False means that it is in Pagefault state. Not possible to disable_stall then */ + return MALI_FALSE; + } + + mali_mmu_disable_stall(mmu); + return MALI_TRUE; +} + +void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu) +{ + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); +} + + +void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address) +{ + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_ZAP_ONE_LINE, MALI_MMU_PDE_ENTRY(mali_address)); +} + +static void mali_mmu_activate_address_space(struct mali_mmu_core *mmu, u32 page_directory) +{ + /* The MMU must be in stalled or page fault mode, for this writing to work */ + MALI_DEBUG_ASSERT( 0 != ( mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) + & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) ); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, page_directory); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); + +} + +mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mali_page_directory *pagedir) +{ + mali_bool stall_success; + MALI_DEBUG_ASSERT_POINTER(mmu); + + MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description)); + stall_success = mali_mmu_enable_stall(mmu); + + if ( MALI_FALSE==stall_success ) return MALI_FALSE; + mali_mmu_activate_address_space(mmu, pagedir->page_directory); + mali_mmu_disable_stall(mmu); + return MALI_TRUE; +} + +void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu) +{ + mali_bool stall_success; + + MALI_DEBUG_ASSERT_POINTER(mmu); + MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description)); + + stall_success = mali_mmu_enable_stall(mmu); + + /* This function can only be called when the core is idle, so it could not fail. */ + MALI_DEBUG_ASSERT(stall_success); + MALI_IGNORE(stall_success); + + mali_mmu_activate_address_space(mmu, mali_empty_page_directory); + mali_mmu_disable_stall(mmu); +} + +void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu) +{ + mali_bool stall_success; + MALI_DEBUG_ASSERT_POINTER(mmu); + + MALI_DEBUG_PRINT(3, ("Activating the page fault flush page directory on MMU %s\n", mmu->hw_core.description)); + stall_success = mali_mmu_enable_stall(mmu); + /* This function is expect to fail the stalling, since it might be in PageFault mode when it is called */ + mali_mmu_activate_address_space(mmu, mali_page_fault_flush_page_directory); + if ( MALI_TRUE==stall_success ) mali_mmu_disable_stall(mmu); +} + +/* Is called when we want the mmu to give an interrupt */ +static void mali_mmu_probe_trigger(void *data) +{ + struct mali_mmu_core *mmu = (struct mali_mmu_core *)data; + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT, MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR); +} + +/* Is called when the irq probe wants the mmu to acknowledge an interrupt from the hw */ +static _mali_osk_errcode_t mali_mmu_probe_ack(void *data) +{ + struct mali_mmu_core *mmu = (struct mali_mmu_core *)data; + u32 int_stat; + + int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS); + + MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_acknowledge: intstat 0x%x\n", int_stat)); + if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT) + { + MALI_DEBUG_PRINT(2, ("Probe: Page fault detect: PASSED\n")); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT); + } + else + { + MALI_DEBUG_PRINT(1, ("Probe: Page fault detect: FAILED\n")); + } + + if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR) + { + MALI_DEBUG_PRINT(2, ("Probe: Bus read error detect: PASSED\n")); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR); + } + else + { + MALI_DEBUG_PRINT(1, ("Probe: Bus read error detect: FAILED\n")); + } + + if ( (int_stat & (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) == + (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) + { + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + +#if 0 +void mali_mmu_print_state(struct mali_mmu_core *mmu) +{ + MALI_DEBUG_PRINT(2, ("MMU: State of %s is 0x%08x\n", mmu->hw_core.description, mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); +} +#endif diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.h b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.h new file mode 100644 index 0000000..59b5399 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_MMU_H__ +#define __MALI_MMU_H__ + +#include "mali_osk.h" +#include "mali_mmu_page_directory.h" +#include "mali_hw_core.h" + +/* Forward declaration from mali_group.h */ +struct mali_group; + +/** + * MMU register numbers + * Used in the register read/write routines. + * See the hardware documentation for more information about each register + */ +typedef enum mali_mmu_register { + MALI_MMU_REGISTER_DTE_ADDR = 0x0000, /**< Current Page Directory Pointer */ + MALI_MMU_REGISTER_STATUS = 0x0004, /**< Status of the MMU */ + MALI_MMU_REGISTER_COMMAND = 0x0008, /**< Command register, used to control the MMU */ + MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x000C, /**< Logical address of the last page fault */ + MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x010, /**< Used to invalidate the mapping of a single page from the MMU */ + MALI_MMU_REGISTER_INT_RAWSTAT = 0x0014, /**< Raw interrupt status, all interrupts visible */ + MALI_MMU_REGISTER_INT_CLEAR = 0x0018, /**< Indicate to the MMU that the interrupt has been received */ + MALI_MMU_REGISTER_INT_MASK = 0x001C, /**< Enable/disable types of interrupts */ + MALI_MMU_REGISTER_INT_STATUS = 0x0020 /**< Interrupt status based on the mask */ +} mali_mmu_register; + +/** + * MMU interrupt register bits + * Each cause of the interrupt is reported + * through the (raw) interrupt status registers. + * Multiple interrupts can be pending, so multiple bits + * can be set at once. + */ +typedef enum mali_mmu_interrupt +{ + MALI_MMU_INTERRUPT_PAGE_FAULT = 0x01, /**< A page fault occured */ + MALI_MMU_INTERRUPT_READ_BUS_ERROR = 0x02 /**< A bus read error occured */ +} mali_mmu_interrupt; + +typedef enum mali_mmu_status_bits +{ + MALI_MMU_STATUS_BIT_PAGING_ENABLED = 1 << 0, + MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE = 1 << 1, + MALI_MMU_STATUS_BIT_STALL_ACTIVE = 1 << 2, + MALI_MMU_STATUS_BIT_IDLE = 1 << 3, + MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY = 1 << 4, + MALI_MMU_STATUS_BIT_PAGE_FAULT_IS_WRITE = 1 << 5, + MALI_MMU_STATUS_BIT_STALL_NOT_ACTIVE = 1 << 31, +} mali_mmu_status_bits; + +/** + * Definition of the MMU struct + * Used to track a MMU unit in the system. + * Contains information about the mapping of the registers + */ +struct mali_mmu_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + _mali_osk_irq_t *irq; /**< IRQ handler */ +}; + +_mali_osk_errcode_t mali_mmu_initialize(void); + +void mali_mmu_terminate(void); + +struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual); +void mali_mmu_delete(struct mali_mmu_core *mmu); + +_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu); +mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu); +void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu); +void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address); + +mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core* mmu, struct mali_page_directory *pagedir); +void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu); +void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu); + +/** + * Issues the enable stall command to the MMU and waits for HW to complete the request + * @param mmu The MMU to enable paging for + * @return MALI_TRUE if HW stall was successfully engaged, otherwise MALI_FALSE (req timed out) + */ +mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu); + +/** + * Issues the disable stall command to the MMU and waits for HW to complete the request + * @param mmu The MMU to enable paging for + */ +void mali_mmu_disable_stall(struct mali_mmu_core *mmu); + +void mali_mmu_page_fault_done(struct mali_mmu_core *mmu); + +/*** Register reading/writing functions ***/ +MALI_STATIC_INLINE u32 mali_mmu_get_int_status(struct mali_mmu_core *mmu) +{ + return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS); +} + +MALI_STATIC_INLINE u32 mali_mmu_get_rawstat(struct mali_mmu_core *mmu) +{ + return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT); +} + +MALI_STATIC_INLINE void mali_mmu_mask_all_interrupts(struct mali_mmu_core *mmu) +{ + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, 0); +} + +MALI_STATIC_INLINE u32 mali_mmu_get_status(struct mali_mmu_core *mmu) +{ + return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); +} + +MALI_STATIC_INLINE u32 mali_mmu_get_page_fault_addr(struct mali_mmu_core *mmu) +{ + return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_PAGE_FAULT_ADDR); +} + +#endif /* __MALI_MMU_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.c b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.c new file mode 100644 index 0000000..258fc1b --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.c @@ -0,0 +1,485 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#include "mali_osk.h" +#include "mali_uk_types.h" +#include "mali_mmu_page_directory.h" +#include "mali_memory.h" +#include "mali_l2_cache.h" +#include "mali_group.h" + +static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data); + +u32 mali_allocate_empty_page(void) +{ + _mali_osk_errcode_t err; + mali_io_address mapping; + u32 address; + + if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&address, &mapping)) + { + /* Allocation failed */ + return 0; + } + + MALI_DEBUG_ASSERT_POINTER( mapping ); + + err = fill_page(mapping, 0); + if (_MALI_OSK_ERR_OK != err) + { + mali_mmu_release_table_page(address); + } + return address; +} + +void mali_free_empty_page(u32 address) +{ + if (MALI_INVALID_PAGE != address) + { + mali_mmu_release_table_page(address); + } +} + +_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page) +{ + _mali_osk_errcode_t err; + mali_io_address page_directory_mapping; + mali_io_address page_table_mapping; + mali_io_address data_page_mapping; + + err = mali_mmu_get_table_page(data_page, &data_page_mapping); + if (_MALI_OSK_ERR_OK == err) + { + err = mali_mmu_get_table_page(page_table, &page_table_mapping); + if (_MALI_OSK_ERR_OK == err) + { + err = mali_mmu_get_table_page(page_directory, &page_directory_mapping); + if (_MALI_OSK_ERR_OK == err) + { + fill_page(data_page_mapping, 0); + fill_page(page_table_mapping, *data_page | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT); + fill_page(page_directory_mapping, *page_table | MALI_MMU_FLAGS_PRESENT); + MALI_SUCCESS; + } + mali_mmu_release_table_page(*page_table); + *page_table = MALI_INVALID_PAGE; + } + mali_mmu_release_table_page(*data_page); + *data_page = MALI_INVALID_PAGE; + } + return err; +} + +void mali_destroy_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page) +{ + if (MALI_INVALID_PAGE != *page_directory) + { + mali_mmu_release_table_page(*page_directory); + *page_directory = MALI_INVALID_PAGE; + } + + if (MALI_INVALID_PAGE != *page_table) + { + mali_mmu_release_table_page(*page_table); + *page_table = MALI_INVALID_PAGE; + } + + if (MALI_INVALID_PAGE != *data_page) + { + mali_mmu_release_table_page(*data_page); + *data_page = MALI_INVALID_PAGE; + } +} + +static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data) +{ + int i; + MALI_DEBUG_ASSERT_POINTER( mapping ); + + for(i = 0; i < MALI_MMU_PAGE_SIZE/4; i++) + { + _mali_osk_mem_iowrite32_relaxed( mapping, i * sizeof(u32), data); + } + _mali_osk_mem_barrier(); + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size) +{ + const int first_pde = MALI_MMU_PDE_ENTRY(mali_address); + const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1); + _mali_osk_errcode_t err; + mali_io_address pde_mapping; + u32 pde_phys; + int i; + + for(i = first_pde; i <= last_pde; i++) + { + if(0 == (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & MALI_MMU_FLAGS_PRESENT)) + { + /* Page table not present */ + MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]); + MALI_DEBUG_ASSERT(NULL == pagedir->page_entries_mapped[i]); + + err = mali_mmu_get_table_page(&pde_phys, &pde_mapping); + if(_MALI_OSK_ERR_OK != err) + { + MALI_PRINT_ERROR(("Failed to allocate page table page.\n")); + return err; + } + pagedir->page_entries_mapped[i] = pde_mapping; + + /* Update PDE, mark as present */ + _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32), + pde_phys | MALI_MMU_FLAGS_PRESENT); + + MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]); + pagedir->page_entries_usage_count[i] = 1; + } + else + { + pagedir->page_entries_usage_count[i]++; + } + } + _mali_osk_write_mem_barrier(); + + MALI_SUCCESS; +} + +MALI_STATIC_INLINE void mali_mmu_zero_pte(mali_io_address page_table, u32 mali_address, u32 size) +{ + int i; + const int first_pte = MALI_MMU_PTE_ENTRY(mali_address); + const int last_pte = MALI_MMU_PTE_ENTRY(mali_address + size - 1); + + for (i = first_pte; i <= last_pte; i++) + { + _mali_osk_mem_iowrite32_relaxed(page_table, i * sizeof(u32), 0); + } +} + +_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size) +{ + const int first_pde = MALI_MMU_PDE_ENTRY(mali_address); + const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1); + u32 left = size; + int i; + mali_bool pd_changed = MALI_FALSE; + u32 pages_to_invalidate[3]; /* hard-coded to 3: max two pages from the PT level plus max one page from PD level */ + u32 num_pages_inv = 0; + mali_bool invalidate_all = MALI_FALSE; /* safety mechanism in case page_entries_usage_count is unreliable */ + + /* For all page directory entries in range. */ + for (i = first_pde; i <= last_pde; i++) + { + u32 size_in_pde, offset; + + MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[i]); + MALI_DEBUG_ASSERT(0 != pagedir->page_entries_usage_count[i]); + + /* Offset into page table, 0 if mali_address is 4MiB aligned */ + offset = (mali_address & (MALI_MMU_VIRTUAL_PAGE_SIZE - 1)); + if (left < MALI_MMU_VIRTUAL_PAGE_SIZE - offset) + { + size_in_pde = left; + } + else + { + size_in_pde = MALI_MMU_VIRTUAL_PAGE_SIZE - offset; + } + + pagedir->page_entries_usage_count[i]--; + + /* If entire page table is unused, free it */ + if (0 == pagedir->page_entries_usage_count[i]) + { + u32 page_address; + MALI_DEBUG_PRINT(4, ("Releasing page table as this is the last reference\n")); + /* last reference removed, no need to zero out each PTE */ + + page_address = MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32))); + pagedir->page_entries_mapped[i] = NULL; + _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32), 0); + + mali_mmu_release_table_page(page_address); + pd_changed = MALI_TRUE; + } + else + { + MALI_DEBUG_ASSERT(num_pages_inv < 2); + if (num_pages_inv < 2) + { + pages_to_invalidate[num_pages_inv] = mali_page_directory_get_phys_address(pagedir, i); + num_pages_inv++; + } + else + { + invalidate_all = MALI_TRUE; + } + + /* If part of the page table is still in use, zero the relevant PTEs */ + mali_mmu_zero_pte(pagedir->page_entries_mapped[i], mali_address, size_in_pde); + } + + left -= size_in_pde; + mali_address += size_in_pde; + } + _mali_osk_write_mem_barrier(); + + /* L2 pages invalidation */ + if (MALI_TRUE == pd_changed) + { + MALI_DEBUG_ASSERT(num_pages_inv < 3); + if (num_pages_inv < 3) + { + pages_to_invalidate[num_pages_inv] = pagedir->page_directory; + num_pages_inv++; + } + else + { + invalidate_all = MALI_TRUE; + } + } + + if (invalidate_all) + { + mali_l2_cache_invalidate_all(); + } + else + { + mali_l2_cache_invalidate_all_pages(pages_to_invalidate, num_pages_inv); + } + + MALI_SUCCESS; +} + +struct mali_page_directory *mali_mmu_pagedir_alloc(void) +{ + struct mali_page_directory *pagedir; + + pagedir = _mali_osk_calloc(1, sizeof(struct mali_page_directory)); + if(NULL == pagedir) + { + return NULL; + } + + if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&pagedir->page_directory, &pagedir->page_directory_mapped)) + { + _mali_osk_free(pagedir); + return NULL; + } + + /* Zero page directory */ + fill_page(pagedir->page_directory_mapped, 0); + + return pagedir; +} + +void mali_mmu_pagedir_free(struct mali_page_directory *pagedir) +{ + const int num_page_table_entries = sizeof(pagedir->page_entries_mapped) / sizeof(pagedir->page_entries_mapped[0]); + int i; + + /* Free referenced page tables and zero PDEs. */ + for (i = 0; i < num_page_table_entries; i++) + { + if (pagedir->page_directory_mapped && (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, sizeof(u32)*i) & MALI_MMU_FLAGS_PRESENT)) + { + mali_mmu_release_table_page( _mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK); + _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i * sizeof(u32), 0); + } + } + _mali_osk_write_mem_barrier(); + + /* Free the page directory page. */ + mali_mmu_release_table_page(pagedir->page_directory); + + _mali_osk_free(pagedir); +} + + +void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size, mali_memory_cache_settings cache_settings) +{ + u32 end_address = mali_address + size; + u32 permission_bits; + + switch ( cache_settings ) + { + case MALI_CACHE_GP_READ_ALLOCATE: + MALI_DEBUG_PRINT(5, ("Map L2 GP_Read_allocate\n")); + permission_bits = MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE; + break; + + case MALI_CACHE_STANDARD: + MALI_DEBUG_PRINT(5, ("Map L2 Standard\n")); + /*falltrough */ + default: + if ( MALI_CACHE_STANDARD != cache_settings) MALI_PRINT_ERROR(("Wrong cache settings\n")); + permission_bits = MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT; + } + + /* Map physical pages into MMU page tables */ + for ( ; mali_address < end_address; mali_address += MALI_MMU_PAGE_SIZE, phys_address += MALI_MMU_PAGE_SIZE) + { + MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)]); + _mali_osk_mem_iowrite32_relaxed(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)], + MALI_MMU_PTE_ENTRY(mali_address) * sizeof(u32), + phys_address | permission_bits); + } + _mali_osk_write_mem_barrier(); +} + +u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index) +{ + return (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, index*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK); +} + +/* For instrumented */ +struct dump_info +{ + u32 buffer_left; + u32 register_writes_size; + u32 page_table_dump_size; + u32 *buffer; +}; + +static _mali_osk_errcode_t writereg(u32 where, u32 what, const char *comment, struct dump_info *info) +{ + if (NULL != info) + { + info->register_writes_size += sizeof(u32)*2; /* two 32-bit words */ + + if (NULL != info->buffer) + { + /* check that we have enough space */ + if (info->buffer_left < sizeof(u32)*2) MALI_ERROR(_MALI_OSK_ERR_NOMEM); + + *info->buffer = where; + info->buffer++; + + *info->buffer = what; + info->buffer++; + + info->buffer_left -= sizeof(u32)*2; + } + } + + MALI_SUCCESS; +} + +static _mali_osk_errcode_t dump_page(mali_io_address page, u32 phys_addr, struct dump_info * info) +{ + if (NULL != info) + { + /* 4096 for the page and 4 bytes for the address */ + const u32 page_size_in_elements = MALI_MMU_PAGE_SIZE / 4; + const u32 page_size_in_bytes = MALI_MMU_PAGE_SIZE; + const u32 dump_size_in_bytes = MALI_MMU_PAGE_SIZE + 4; + + info->page_table_dump_size += dump_size_in_bytes; + + if (NULL != info->buffer) + { + if (info->buffer_left < dump_size_in_bytes) MALI_ERROR(_MALI_OSK_ERR_NOMEM); + + *info->buffer = phys_addr; + info->buffer++; + + _mali_osk_memcpy(info->buffer, page, page_size_in_bytes); + info->buffer += page_size_in_elements; + + info->buffer_left -= dump_size_in_bytes; + } + } + + MALI_SUCCESS; +} + +static _mali_osk_errcode_t dump_mmu_page_table(struct mali_page_directory *pagedir, struct dump_info * info) +{ + MALI_DEBUG_ASSERT_POINTER(pagedir); + MALI_DEBUG_ASSERT_POINTER(info); + + if (NULL != pagedir->page_directory_mapped) + { + int i; + + MALI_CHECK_NO_ERROR( + dump_page(pagedir->page_directory_mapped, pagedir->page_directory, info) + ); + + for (i = 0; i < 1024; i++) + { + if (NULL != pagedir->page_entries_mapped[i]) + { + MALI_CHECK_NO_ERROR( + dump_page(pagedir->page_entries_mapped[i], + _mali_osk_mem_ioread32(pagedir->page_directory_mapped, + i * sizeof(u32)) & ~MALI_MMU_FLAGS_MASK, info) + ); + } + } + } + + MALI_SUCCESS; +} + +static _mali_osk_errcode_t dump_mmu_registers(struct mali_page_directory *pagedir, struct dump_info * info) +{ + MALI_CHECK_NO_ERROR(writereg(0x00000000, pagedir->page_directory, + "set the page directory address", info)); + MALI_CHECK_NO_ERROR(writereg(0x00000008, 4, "zap???", info)); + MALI_CHECK_NO_ERROR(writereg(0x00000008, 0, "enable paging", info)); + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args ) +{ + struct dump_info info = { 0, 0, 0, NULL }; + struct mali_session_data * session_data; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)(args->ctx); + + MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info)); + MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info)); + args->size = info.register_writes_size + info.page_table_dump_size; + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args ) +{ + struct dump_info info = { 0, 0, 0, NULL }; + struct mali_session_data * session_data; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + MALI_CHECK_NON_NULL(args->buffer, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)(args->ctx); + + info.buffer_left = args->size; + info.buffer = args->buffer; + + args->register_writes = info.buffer; + MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info)); + + args->page_table_dump = info.buffer; + MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info)); + + args->register_writes_size = info.register_writes_size; + args->page_table_dump_size = info.page_table_dump_size; + + MALI_SUCCESS; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.h b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.h new file mode 100644 index 0000000..628833a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_MMU_PAGE_DIRECTORY_H__ +#define __MALI_MMU_PAGE_DIRECTORY_H__ + +#include "mali_osk.h" + +/** + * Size of an MMU page in bytes + */ +#define MALI_MMU_PAGE_SIZE 0x1000 + +/* + * Size of the address space referenced by a page table page + */ +#define MALI_MMU_VIRTUAL_PAGE_SIZE 0x400000 /* 4 MiB */ + +/** + * Page directory index from address + * Calculates the page directory index from the given address + */ +#define MALI_MMU_PDE_ENTRY(address) (((address)>>22) & 0x03FF) + +/** + * Page table index from address + * Calculates the page table index from the given address + */ +#define MALI_MMU_PTE_ENTRY(address) (((address)>>12) & 0x03FF) + +/** + * Extract the memory address from an PDE/PTE entry + */ +#define MALI_MMU_ENTRY_ADDRESS(value) ((value) & 0xFFFFFC00) + +#define MALI_INVALID_PAGE ((u32)(~0)) + +/** + * + */ +typedef enum mali_mmu_entry_flags +{ + MALI_MMU_FLAGS_PRESENT = 0x01, + MALI_MMU_FLAGS_READ_PERMISSION = 0x02, + MALI_MMU_FLAGS_WRITE_PERMISSION = 0x04, + MALI_MMU_FLAGS_OVERRIDE_CACHE = 0x8, + MALI_MMU_FLAGS_WRITE_CACHEABLE = 0x10, + MALI_MMU_FLAGS_WRITE_ALLOCATE = 0x20, + MALI_MMU_FLAGS_WRITE_BUFFERABLE = 0x40, + MALI_MMU_FLAGS_READ_CACHEABLE = 0x80, + MALI_MMU_FLAGS_READ_ALLOCATE = 0x100, + MALI_MMU_FLAGS_MASK = 0x1FF, +} mali_mmu_entry_flags; + + +#define MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE ( \ +MALI_MMU_FLAGS_PRESENT | \ + MALI_MMU_FLAGS_READ_PERMISSION | \ + MALI_MMU_FLAGS_WRITE_PERMISSION | \ + MALI_MMU_FLAGS_OVERRIDE_CACHE | \ + MALI_MMU_FLAGS_WRITE_CACHEABLE | \ + MALI_MMU_FLAGS_WRITE_BUFFERABLE | \ + MALI_MMU_FLAGS_READ_CACHEABLE | \ + MALI_MMU_FLAGS_READ_ALLOCATE ) + + +struct mali_page_directory +{ + u32 page_directory; /**< Physical address of the memory session's page directory */ + mali_io_address page_directory_mapped; /**< Pointer to the mapped version of the page directory into the kernel's address space */ + + mali_io_address page_entries_mapped[1024]; /**< Pointers to the page tables which exists in the page directory mapped into the kernel's address space */ + u32 page_entries_usage_count[1024]; /**< Tracks usage count of the page table pages, so they can be releases on the last reference */ +}; + +/* Map Mali virtual address space (i.e. ensure page tables exist for the virtual range) */ +_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size); +_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size); + +/* Back virtual address space with actual pages. Assumes input is contiguous and 4k aligned. */ +void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size, u32 cache_settings); + +u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index); + +u32 mali_allocate_empty_page(void); +void mali_free_empty_page(u32 address); +_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page); +void mali_destroy_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page); + +struct mali_page_directory *mali_mmu_pagedir_alloc(void); +void mali_mmu_pagedir_free(struct mali_page_directory *pagedir); + +#endif /* __MALI_MMU_PAGE_DIRECTORY_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_osk.h b/drivers/gpu/mali400/r3p2/mali/common/mali_osk.h new file mode 100644 index 0000000..6217203 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_osk.h @@ -0,0 +1,1811 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk.h + * Defines the OS abstraction layer for the kernel device driver (OSK) + */ + +#ifndef __MALI_OSK_H__ +#define __MALI_OSK_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @addtogroup uddapi Unified Device Driver (UDD) APIs + * + * @{ + */ + +/** + * @addtogroup oskapi UDD OS Abstraction for Kernel-side (OSK) APIs + * + * @{ + */ + +/** @defgroup _mali_osk_miscellaneous OSK Miscellaneous functions, constants and types + * @{ */ + +/* Define integer types used by OSK. Note: these currently clash with Linux so we only define them if not defined already */ +#ifndef __KERNEL__ + typedef unsigned char u8; + typedef signed char s8; + typedef unsigned short u16; + typedef signed short s16; + typedef unsigned int u32; + typedef signed int s32; + typedef unsigned long long u64; + #define BITS_PER_LONG (sizeof(long)*8) +#else + /* Ensure Linux types u32, etc. are defined */ + #include +#endif + +/** @brief Mali Boolean type which uses MALI_TRUE and MALI_FALSE + */ + typedef unsigned long mali_bool; + +#ifndef MALI_TRUE + #define MALI_TRUE ((mali_bool)1) +#endif + +#ifndef MALI_FALSE + #define MALI_FALSE ((mali_bool)0) +#endif + +#define MALI_HW_CORE_NO_COUNTER ((u32)-1) + +/** + * @brief OSK Error codes + * + * Each OS may use its own set of error codes, and may require that the + * User/Kernel interface take certain error code. This means that the common + * error codes need to be sufficiently rich to pass the correct error code + * thorugh from the OSK to U/K layer, across all OSs. + * + * The result is that some error codes will appear redundant on some OSs. + * Under all OSs, the OSK layer must translate native OS error codes to + * _mali_osk_errcode_t codes. Similarly, the U/K layer must translate from + * _mali_osk_errcode_t codes to native OS error codes. + */ +typedef enum +{ + _MALI_OSK_ERR_OK = 0, /**< Success. */ + _MALI_OSK_ERR_FAULT = -1, /**< General non-success */ + _MALI_OSK_ERR_INVALID_FUNC = -2, /**< Invalid function requested through User/Kernel interface (e.g. bad IOCTL number) */ + _MALI_OSK_ERR_INVALID_ARGS = -3, /**< Invalid arguments passed through User/Kernel interface */ + _MALI_OSK_ERR_NOMEM = -4, /**< Insufficient memory */ + _MALI_OSK_ERR_TIMEOUT = -5, /**< Timeout occurred */ + _MALI_OSK_ERR_RESTARTSYSCALL = -6, /**< Special: On certain OSs, must report when an interruptable mutex is interrupted. Ignore otherwise. */ + _MALI_OSK_ERR_ITEM_NOT_FOUND = -7, /**< Table Lookup failed */ + _MALI_OSK_ERR_BUSY = -8, /**< Device/operation is busy. Try again later */ + _MALI_OSK_ERR_UNSUPPORTED = -9, /**< Optional part of the interface used, and is unsupported */ +} _mali_osk_errcode_t; + +/** @} */ /* end group _mali_osk_miscellaneous */ + +/** @defgroup _mali_osk_wq OSK work queues + * @{ */ + +/** @brief Private type for work objects */ +typedef struct _mali_osk_wq_work_t_struct _mali_osk_wq_work_t; + +/** @brief Work queue handler function + * + * This function type is called when the work is scheduled by the work queue, + * e.g. as an IRQ bottom-half handler. + * + * Refer to \ref _mali_osk_wq_schedule_work() for more information on the + * work-queue and work handlers. + * + * @param arg resource-specific data + */ +typedef void (*_mali_osk_wq_work_handler_t)( void * arg ); + +/* @} */ /* end group _mali_osk_wq */ + +/** @defgroup _mali_osk_irq OSK IRQ handling + * @{ */ + +/** @brief Private type for IRQ handling objects */ +typedef struct _mali_osk_irq_t_struct _mali_osk_irq_t; + +/** @brief Optional function to trigger an irq from a resource + * + * This function is implemented by the common layer to allow probing of a resource's IRQ. + * @param arg resource-specific data */ +typedef void (*_mali_osk_irq_trigger_t)( void * arg ); + +/** @brief Optional function to acknowledge an irq from a resource + * + * This function is implemented by the common layer to allow probing of a resource's IRQ. + * @param arg resource-specific data + * @return _MALI_OSK_ERR_OK if the IRQ was successful, or a suitable _mali_osk_errcode_t on failure. */ +typedef _mali_osk_errcode_t (*_mali_osk_irq_ack_t)( void * arg ); + +/** @brief IRQ 'upper-half' handler callback. + * + * This function is implemented by the common layer to do the initial handling of a + * resource's IRQ. This maps on to the concept of an ISR that does the minimum + * work necessary before handing off to an IST. + * + * The communication of the resource-specific data from the ISR to the IST is + * handled by the OSK implementation. + * + * On most systems, the IRQ upper-half handler executes in IRQ context. + * Therefore, the system may have restrictions about what can be done in this + * context + * + * If an IRQ upper-half handler requires more work to be done than can be + * acheived in an IRQ context, then it may defer the work with + * _mali_osk_wq_schedule_work(). Refer to \ref _mali_osk_wq_create_work() for + * more information. + * + * @param arg resource-specific data + * @return _MALI_OSK_ERR_OK if the IRQ was correctly handled, or a suitable + * _mali_osk_errcode_t otherwise. + */ +typedef _mali_osk_errcode_t (*_mali_osk_irq_uhandler_t)( void * arg ); + +/** @} */ /* end group _mali_osk_irq */ + + +/** @defgroup _mali_osk_atomic OSK Atomic counters + * @{ */ + +/** @brief Public type of atomic counters + * + * This is public for allocation on stack. On systems that support it, this is just a single 32-bit value. + * On others, it could be encapsulating an object stored elsewhere. + * + * Regardless of implementation, the \ref _mali_osk_atomic functions \b must be used + * for all accesses to the variable's value, even if atomicity is not required. + * Do not access u.val or u.obj directly. + */ +typedef struct +{ + union + { + u32 val; + void *obj; + } u; +} _mali_osk_atomic_t; +/** @} */ /* end group _mali_osk_atomic */ + + +/** @defgroup _mali_osk_lock OSK Mutual Exclusion Locks + * @{ */ + + +/** @brief OSK Mutual Exclusion Lock ordered list + * + * This lists the various types of locks in the system and is used to check + * that locks are taken in the correct order. + * + * Holding more than one lock of the same order at the same time is not + * allowed. + * + */ +typedef enum +{ + _MALI_OSK_LOCK_ORDER_LAST = 0, + + _MALI_OSK_LOCK_ORDER_SESSION_PENDING_JOBS, + _MALI_OSK_LOCK_ORDER_PM_EXECUTE, + _MALI_OSK_LOCK_ORDER_UTILIZATION, + _MALI_OSK_LOCK_ORDER_L2_COUNTER, + _MALI_OSK_LOCK_ORDER_PROFILING, + _MALI_OSK_LOCK_ORDER_L2_COMMAND, + _MALI_OSK_LOCK_ORDER_PM_CORE_STATE, + _MALI_OSK_LOCK_ORDER_SCHEDULER_DEFERRED, + _MALI_OSK_LOCK_ORDER_SCHEDULER, + _MALI_OSK_LOCK_ORDER_GROUP, + _MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL, + _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP, + _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE, + _MALI_OSK_LOCK_ORDER_MEM_INFO, + _MALI_OSK_LOCK_ORDER_MEM_SESSION, + _MALI_OSK_LOCK_ORDER_SESSIONS, + _MALI_OSK_LOCK_ORDER_PM_DOMAIN, + _MALI_OSK_LOCK_ORDER_PMU, + + _MALI_OSK_LOCK_ORDER_FIRST +} _mali_osk_lock_order_t; + + +/** @brief OSK Mutual Exclusion Lock flags type + * + * Flags are supplied at the point where the Lock is initialized. Each flag can + * be combined with others using bitwise OR, '|'. + * + * The flags must be sufficiently rich to cope with all our OSs. This means + * that on some OSs, certain flags can be completely ignored. We define a + * number of terms that are significant across all OSs: + * + * - Sleeping/non-sleeping mutexs. Sleeping mutexs can block on waiting, and so + * schedule out the current thread. This is significant on OSs where there are + * situations in which the current thread must not be put to sleep. On OSs + * without this restriction, sleeping and non-sleeping mutexes can be treated + * as the same (if that is required). + * - Interruptable/non-interruptable mutexes. For sleeping mutexes, it may be + * possible for the sleep to be interrupted for a reason other than the thread + * being able to obtain the lock. OSs behaving in this way may provide a + * mechanism to control whether sleeping mutexes can be interrupted. On OSs + * that do not support the concept of interruption, \b or they do not support + * control of mutex interruption, then interruptable mutexes may be treated + * as non-interruptable. + * + * Some constrains apply to the lock type flags: + * + * - Spinlocks are by nature, non-interruptable. Hence, they must always be + * combined with the NONINTERRUPTABLE flag, because it is meaningless to ask + * for a spinlock that is interruptable (and this highlights its + * non-interruptable-ness). For example, on certain OSs they should be used when + * you must not sleep. + * - Reader/writer is an optimization hint, and any type of lock can be + * reader/writer. Since this is an optimization hint, the implementation need + * not respect this for any/all types of lock. For example, on certain OSs, + * there's no interruptable reader/writer mutex. If such a thing were requested + * on that OS, the fact that interruptable was requested takes priority over the + * reader/writer-ness, because reader/writer-ness is not necessary for correct + * operation. + * - Any lock can use the order parameter. + * - A onelock is an optimization hint specific to certain OSs. It can be + * specified when it is known that only one lock will be held by the thread, + * and so can provide faster mutual exclusion. This can be safely ignored if + * such optimization is not required/present. + * + * The absence of any flags (the value 0) results in a sleeping-mutex, which is interruptable. + */ +typedef enum +{ + _MALI_OSK_LOCKFLAG_SPINLOCK = 0x1, /**< Specifically, don't sleep on those architectures that require it */ + _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE = 0x2, /**< The mutex cannot be interrupted, e.g. delivery of signals on those architectures where this is required */ + _MALI_OSK_LOCKFLAG_READERWRITER = 0x4, /**< Optimise for readers/writers */ + _MALI_OSK_LOCKFLAG_ORDERED = 0x8, /**< Use the order parameter; otherwise use automatic ordering */ + _MALI_OSK_LOCKFLAG_ONELOCK = 0x10, /**< Each thread can only hold one lock at a time */ + _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ = 0x20, /**< IRQ version of spinlock */ + /** @enum _mali_osk_lock_flags_t + * + * Flags from 0x10000--0x80000000 are RESERVED for User-mode */ + +} _mali_osk_lock_flags_t; + +/** @brief Mutual Exclusion Lock Mode Optimization hint + * + * The lock mode is used to implement the read/write locking of locks specified + * as _MALI_OSK_LOCKFLAG_READERWRITER. In this case, the RO mode can be used + * to allow multiple concurrent readers, but no writers. The RW mode is used for + * writers, and so will wait for all readers to release the lock (if any present). + * Further readers and writers will wait until the writer releases the lock. + * + * The mode is purely an optimization hint: for example, it is permissible for + * all locks to behave in RW mode, regardless of that supplied. + * + * It is an error to attempt to use locks in anything other that RW mode when + * _MALI_OSK_LOCKFLAG_READERWRITER is not supplied. + * + */ +typedef enum +{ + _MALI_OSK_LOCKMODE_UNDEF = -1, /**< Undefined lock mode. For internal use only */ + _MALI_OSK_LOCKMODE_RW = 0x0, /**< Read-write mode, default. All readers and writers are mutually-exclusive */ + _MALI_OSK_LOCKMODE_RO, /**< Read-only mode, to support multiple concurrent readers, but mutual exclusion in the presence of writers. */ + /** @enum _mali_osk_lock_mode_t + * + * Lock modes 0x40--0x7F are RESERVED for User-mode */ +} _mali_osk_lock_mode_t; + +/** @brief Private type for Mutual Exclusion lock objects */ +typedef struct _mali_osk_lock_t_struct _mali_osk_lock_t; + +#ifdef DEBUG +/** @brief Macro for asserting that the current thread holds a given lock + */ +#define MALI_DEBUG_ASSERT_LOCK_HELD(l) MALI_DEBUG_ASSERT(_mali_osk_lock_get_owner(l) == _mali_osk_get_tid()); + +/** @brief returns a lock's owner (thread id) if debugging is enabled + */ +u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock ); +#else +#define MALI_DEBUG_ASSERT_LOCK_HELD(l) do {} while(0) +#endif + +/** @} */ /* end group _mali_osk_lock */ + +/** @defgroup _mali_osk_low_level_memory OSK Low-level Memory Operations + * @{ */ + +/** + * @brief Private data type for use in IO accesses to/from devices. + * + * This represents some range that is accessible from the device. Examples + * include: + * - Device Registers, which could be readable and/or writeable. + * - Memory that the device has access to, for storing configuration structures. + * + * Access to this range must be made through the _mali_osk_mem_ioread32() and + * _mali_osk_mem_iowrite32() functions. + */ +typedef struct _mali_io_address * mali_io_address; + +/** @defgroup _MALI_OSK_CPU_PAGE CPU Physical page size macros. + * + * The order of the page size is supplied for + * ease of use by algorithms that might require it, since it is easier to know + * it ahead of time rather than calculating it. + * + * The Mali Page Mask macro masks off the lower bits of a physical address to + * give the start address of the page for that physical address. + * + * @note The Mali device driver code is designed for systems with 4KB page size. + * Changing these macros will not make the entire Mali device driver work with + * page sizes other than 4KB. + * + * @note The CPU Physical Page Size has been assumed to be the same as the Mali + * Physical Page Size. + * + * @{ + */ + +/** CPU Page Order, as log to base 2 of the Page size. @see _MALI_OSK_CPU_PAGE_SIZE */ +#define _MALI_OSK_CPU_PAGE_ORDER ((u32)12) +/** CPU Page Size, in bytes. */ +#define _MALI_OSK_CPU_PAGE_SIZE (((u32)1) << (_MALI_OSK_CPU_PAGE_ORDER)) +/** CPU Page Mask, which masks off the offset within a page */ +#define _MALI_OSK_CPU_PAGE_MASK (~((((u32)1) << (_MALI_OSK_CPU_PAGE_ORDER)) - ((u32)1))) +/** @} */ /* end of group _MALI_OSK_CPU_PAGE */ + +/** @defgroup _MALI_OSK_MALI_PAGE Mali Physical Page size macros + * + * Mali Physical page size macros. The order of the page size is supplied for + * ease of use by algorithms that might require it, since it is easier to know + * it ahead of time rather than calculating it. + * + * The Mali Page Mask macro masks off the lower bits of a physical address to + * give the start address of the page for that physical address. + * + * @note The Mali device driver code is designed for systems with 4KB page size. + * Changing these macros will not make the entire Mali device driver work with + * page sizes other than 4KB. + * + * @note The Mali Physical Page Size has been assumed to be the same as the CPU + * Physical Page Size. + * + * @{ + */ + +/** Mali Page Order, as log to base 2 of the Page size. @see _MALI_OSK_MALI_PAGE_SIZE */ +#define _MALI_OSK_MALI_PAGE_ORDER ((u32)12) +/** Mali Page Size, in bytes. */ +#define _MALI_OSK_MALI_PAGE_SIZE (((u32)1) << (_MALI_OSK_MALI_PAGE_ORDER)) +/** Mali Page Mask, which masks off the offset within a page */ +#define _MALI_OSK_MALI_PAGE_MASK (~((((u32)1) << (_MALI_OSK_MALI_PAGE_ORDER)) - ((u32)1))) +/** @} */ /* end of group _MALI_OSK_MALI_PAGE*/ + +/** @brief flags for mapping a user-accessible memory range + * + * Where a function with prefix '_mali_osk_mem_mapregion' accepts flags as one + * of the function parameters, it will use one of these. These allow per-page + * control over mappings. Compare with the mali_memory_allocation_flag type, + * which acts over an entire range + * + * These may be OR'd together with bitwise OR (|), but must be cast back into + * the type after OR'ing. + */ +typedef enum +{ + _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR = 0x1, /**< Physical address is OS Allocated */ +} _mali_osk_mem_mapregion_flags_t; +/** @} */ /* end group _mali_osk_low_level_memory */ + +/** @defgroup _mali_osk_notification OSK Notification Queues + * @{ */ + +/** @brief Private type for notification queue objects */ +typedef struct _mali_osk_notification_queue_t_struct _mali_osk_notification_queue_t; + +/** @brief Public notification data object type */ +typedef struct _mali_osk_notification_t_struct +{ + u32 notification_type; /**< The notification type */ + u32 result_buffer_size; /**< Size of the result buffer to copy to user space */ + void * result_buffer; /**< Buffer containing any type specific data */ +} _mali_osk_notification_t; + +/** @} */ /* end group _mali_osk_notification */ + + +/** @defgroup _mali_osk_timer OSK Timer Callbacks + * @{ */ + +/** @brief Function to call when a timer expires + * + * When a timer expires, this function is called. Note that on many systems, + * a timer callback will be executed in IRQ context. Therefore, restrictions + * may apply on what can be done inside the timer callback. + * + * If a timer requires more work to be done than can be acheived in an IRQ + * context, then it may defer the work with a work-queue. For example, it may + * use \ref _mali_osk_wq_schedule_work() to make use of a bottom-half handler + * to carry out the remaining work. + * + * Stopping the timer with \ref _mali_osk_timer_del() blocks on compeletion of + * the callback. Therefore, the callback may not obtain any mutexes also held + * by any callers of _mali_osk_timer_del(). Otherwise, a deadlock may occur. + * + * @param arg Function-specific data */ +typedef void (*_mali_osk_timer_callback_t)(void * arg ); + +/** @brief Private type for Timer Callback Objects */ +typedef struct _mali_osk_timer_t_struct _mali_osk_timer_t; +/** @} */ /* end group _mali_osk_timer */ + + +/** @addtogroup _mali_osk_list OSK Doubly-Linked Circular Lists + * @{ */ + +/** @brief Public List objects. + * + * To use, add a _mali_osk_list_t member to the structure that may become part + * of a list. When traversing the _mali_osk_list_t objects, use the + * _MALI_OSK_CONTAINER_OF() macro to recover the structure from its + *_mali_osk_list_t member + * + * Each structure may have multiple _mali_osk_list_t members, so that the + * structure is part of multiple lists. When traversing lists, ensure that the + * correct _mali_osk_list_t member is used, because type-checking will be + * lost by the compiler. + */ +typedef struct _mali_osk_list_s +{ + struct _mali_osk_list_s *next; + struct _mali_osk_list_s *prev; +} _mali_osk_list_t; + +/** @brief Initialize a list to be a head of an empty list + * @param exp the list to initialize. */ +#define _MALI_OSK_INIT_LIST_HEAD(exp) _mali_osk_list_init(exp) + +/** @brief Define a list variable, which is uninitialized. + * @param exp the name of the variable that the list will be defined as. */ +#define _MALI_OSK_LIST_HEAD(exp) _mali_osk_list_t exp + +/** @brief Define a list variable, which is initialized. + * @param exp the name of the variable that the list will be defined as. */ +#define _MALI_OSK_LIST_HEAD_STATIC_INIT(exp) _mali_osk_list_t exp = { &exp, &exp } + +/** @brief Find the containing structure of another structure + * + * This is the reverse of the operation 'offsetof'. This means that the + * following condition is satisfied: + * + * ptr == _MALI_OSK_CONTAINER_OF( &ptr->member, type, member ) + * + * When ptr is of type 'type'. + * + * Its purpose it to recover a larger structure that has wrapped a smaller one. + * + * @note no type or memory checking occurs to ensure that a wrapper structure + * does in fact exist, and that it is being recovered with respect to the + * correct member. + * + * @param ptr the pointer to the member that is contained within the larger + * structure + * @param type the type of the structure that contains the member + * @param member the name of the member in the structure that ptr points to. + * @return a pointer to a \a type object which contains \a member, as pointed + * to by \a ptr. + */ +#define _MALI_OSK_CONTAINER_OF(ptr, type, member) \ + ((type *)( ((char *)ptr) - offsetof(type,member) )) + +/** @brief Find the containing structure of a list + * + * When traversing a list, this is used to recover the containing structure, + * given that is contains a _mali_osk_list_t member. + * + * Each list must be of structures of one type, and must link the same members + * together, otherwise it will not be possible to correctly recover the + * sturctures that the lists link. + * + * @note no type or memory checking occurs to ensure that a structure does in + * fact exist for the list entry, and that it is being recovered with respect + * to the correct list member. + * + * @param ptr the pointer to the _mali_osk_list_t member in this structure + * @param type the type of the structure that contains the member + * @param member the member of the structure that ptr points to. + * @return a pointer to a \a type object which contains the _mali_osk_list_t + * \a member, as pointed to by the _mali_osk_list_t \a *ptr. + */ +#define _MALI_OSK_LIST_ENTRY(ptr, type, member) \ + _MALI_OSK_CONTAINER_OF(ptr, type, member) + +/** @brief Enumerate a list safely + * + * With this macro, lists can be enumerated in a 'safe' manner. That is, + * entries can be deleted from the list without causing an error during + * enumeration. To achieve this, a 'temporary' pointer is required, which must + * be provided to the macro. + * + * Use it like a 'for()', 'while()' or 'do()' construct, and so it must be + * followed by a statement or compound-statement which will be executed for + * each list entry. + * + * Upon loop completion, providing that an early out was not taken in the + * loop body, then it is guaranteed that ptr->member == list, even if the loop + * body never executed. + * + * @param ptr a pointer to an object of type 'type', which points to the + * structure that contains the currently enumerated list entry. + * @param tmp a pointer to an object of type 'type', which must not be used + * inside the list-execution statement. + * @param list a pointer to a _mali_osk_list_t, from which enumeration will + * begin + * @param type the type of the structure that contains the _mali_osk_list_t + * member that is part of the list to be enumerated. + * @param member the _mali_osk_list_t member of the structure that is part of + * the list to be enumerated. + */ +#define _MALI_OSK_LIST_FOREACHENTRY(ptr, tmp, list, type, member) \ + for (ptr = _MALI_OSK_LIST_ENTRY((list)->next, type, member), \ + tmp = _MALI_OSK_LIST_ENTRY(ptr->member.next, type, member); \ + &ptr->member != (list); \ + ptr = tmp, tmp = _MALI_OSK_LIST_ENTRY(tmp->member.next, type, member)) +/** @} */ /* end group _mali_osk_list */ + + +/** @addtogroup _mali_osk_miscellaneous + * @{ */ + +/** @brief resource description struct + * + * Platform independent representation of a Mali HW resource + */ +typedef struct _mali_osk_resource +{ + const char * description; /**< short description of the resource */ + u32 base; /**< Physical base address of the resource, as seen by Mali resources. */ + u32 irq; /**< IRQ number delivered to the CPU, or -1 to tell the driver to probe for it (if possible) */ +} _mali_osk_resource_t; +/** @} */ /* end group _mali_osk_miscellaneous */ + + +#include "mali_kernel_memory_engine.h" /* include for mali_memory_allocation and mali_physical_memory_allocation type */ + +/** @addtogroup _mali_osk_wq + * @{ */ + +/** @brief Initialize work queues (for deferred work) + * + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_wq_init(void); + +/** @brief Terminate work queues (for deferred work) + */ +void _mali_osk_wq_term(void); + +/** @brief Create work in the work queue + * + * Creates a work object which can be scheduled in the work queue. When + * scheduled, \a handler will be called with \a data as the argument. + * + * Refer to \ref _mali_osk_wq_schedule_work() for details on how work + * is scheduled in the queue. + * + * The returned pointer must be freed with \ref _mali_osk_wq_delete_work() + * when no longer needed. + */ +_mali_osk_wq_work_t *_mali_osk_wq_create_work( _mali_osk_wq_work_handler_t handler, void *data ); + +/** @brief Delete a work object + * + * This will flush the work queue to ensure that the work handler will not + * be called after deletion. + */ +void _mali_osk_wq_delete_work( _mali_osk_wq_work_t *work ); + +/** @brief Delete a work object + * + * This will NOT flush the work queue, so only call this if you are sure that the work handler will + * not be called after deletion. + */ +void _mali_osk_wq_delete_work_nonflush( _mali_osk_wq_work_t *work ); + +/** @brief Cause a queued, deferred call of the work handler + * + * _mali_osk_wq_schedule_work provides a mechanism for enqueuing deferred calls + * to the work handler. After calling \ref _mali_osk_wq_schedule_work(), the + * work handler will be scheduled to run at some point in the future. + * + * Typically this is called by the IRQ upper-half to defer further processing of + * IRQ-related work to the IRQ bottom-half handler. This is necessary for work + * that cannot be done in an IRQ context by the IRQ upper-half handler. Timer + * callbacks also use this mechanism, because they are treated as though they + * operate in an IRQ context. Refer to \ref _mali_osk_timer_t for more + * information. + * + * Code that operates in a kernel-process context (with no IRQ context + * restrictions) may also enqueue deferred calls to the IRQ bottom-half. The + * advantage over direct calling is that deferred calling allows the caller and + * IRQ bottom half to hold the same mutex, with a guarantee that they will not + * deadlock just by using this mechanism. + * + * _mali_osk_wq_schedule_work() places deferred call requests on a queue, to + * allow for more than one thread to make a deferred call. Therfore, if it is + * called 'K' times, then the IRQ bottom-half will be scheduled 'K' times too. + * 'K' is a number that is implementation-specific. + * + * _mali_osk_wq_schedule_work() is guaranteed to not block on: + * - enqueuing a deferred call request. + * - the completion of the work handler. + * + * This is to prevent deadlock. For example, if _mali_osk_wq_schedule_work() + * blocked, then it would cause a deadlock when the following two conditions + * hold: + * - The work handler callback (of type _mali_osk_wq_work_handler_t) locks + * a mutex + * - And, at the same time, the caller of _mali_osk_wq_schedule_work() also + * holds the same mutex + * + * @note care must be taken to not overflow the queue that + * _mali_osk_wq_schedule_work() operates on. Code must be structured to + * ensure that the number of requests made to the queue is bounded. Otherwise, + * work will be lost. + * + * The queue that _mali_osk_wq_schedule_work implements is a FIFO of N-writer, + * 1-reader type. The writers are the callers of _mali_osk_wq_schedule_work + * (all OSK-registered IRQ upper-half handlers in the system, watchdog timers, + * callers from a Kernel-process context). The reader is a single thread that + * handles all OSK-registered work. + * + * @param work a pointer to the _mali_osk_wq_work_t object corresponding to the + * work to begin processing. + */ +void _mali_osk_wq_schedule_work( _mali_osk_wq_work_t *work ); + +/** @brief Flush the work queue + * + * This will flush the OSK work queue, ensuring all work in the queue has + * completed before returning. + * + * Since this blocks on the completion of work in the work-queue, the + * caller of this function \b must \b not hold any mutexes that are taken by + * any registered work handler. To do so may cause a deadlock. + * + */ +void _mali_osk_wq_flush(void); + + +/** @} */ /* end group _mali_osk_wq */ + +/** @addtogroup _mali_osk_irq + * @{ */ + +/** @brief Initialize IRQ handling for a resource + * + * Registers an interrupt handler \a uhandler for the given IRQ number \a irqnum. + * \a data will be passed as argument to the handler when an interrupt occurs. + * + * If \a irqnum is -1, _mali_osk_irq_init will probe for the IRQ number using + * the supplied \a trigger_func and \a ack_func. These functions will also + * receive \a data as their argument. + * + * @param irqnum The IRQ number that the resource uses, as seen by the CPU. + * The value -1 has a special meaning which indicates the use of probing, and + * trigger_func and ack_func must be non-NULL. + * @param uhandler The interrupt handler, corresponding to a ISR handler for + * the resource + * @param int_data resource specific data, which will be passed to uhandler + * @param trigger_func Optional: a function to trigger the resource's irq, to + * probe for the interrupt. Use NULL if irqnum != -1. + * @param ack_func Optional: a function to acknowledge the resource's irq, to + * probe for the interrupt. Use NULL if irqnum != -1. + * @param probe_data resource-specific data, which will be passed to + * (if present) trigger_func and ack_func + * @param description textual description of the IRQ resource. + * @return on success, a pointer to a _mali_osk_irq_t object, which represents + * the IRQ handling on this resource. NULL on failure. + */ +_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, void *int_data, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *probe_data, const char *description ); + +/** @brief Terminate IRQ handling on a resource. + * + * This will disable the interrupt from the device, and then waits for any + * currently executing IRQ handlers to complete. + * + * @note If work is deferred to an IRQ bottom-half handler through + * \ref _mali_osk_wq_schedule_work(), be sure to flush any remaining work + * with \ref _mali_osk_wq_flush() or (implicitly) with \ref _mali_osk_wq_delete_work() + * + * @param irq a pointer to the _mali_osk_irq_t object corresponding to the + * resource whose IRQ handling is to be terminated. + */ +void _mali_osk_irq_term( _mali_osk_irq_t *irq ); + +/** @} */ /* end group _mali_osk_irq */ + + +/** @addtogroup _mali_osk_atomic + * @{ */ + +/** @brief Decrement an atomic counter + * + * @note It is an error to decrement the counter beyond -(1<<23) + * + * @param atom pointer to an atomic counter */ +void _mali_osk_atomic_dec( _mali_osk_atomic_t *atom ); + +/** @brief Decrement an atomic counter, return new value + * + * @param atom pointer to an atomic counter + * @return The new value, after decrement */ +u32 _mali_osk_atomic_dec_return( _mali_osk_atomic_t *atom ); + +/** @brief Increment an atomic counter + * + * @note It is an error to increment the counter beyond (1<<23)-1 + * + * @param atom pointer to an atomic counter */ +void _mali_osk_atomic_inc( _mali_osk_atomic_t *atom ); + +/** @brief Increment an atomic counter, return new value + * + * @param atom pointer to an atomic counter */ +u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom ); + +/** @brief Initialize an atomic counter + * + * @note the parameter required is a u32, and so signed integers should be + * cast to u32. + * + * @param atom pointer to an atomic counter + * @param val the value to initialize the atomic counter. + * @return _MALI_OSK_ERR_OK on success, otherwise, a suitable + * _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_osk_atomic_init( _mali_osk_atomic_t *atom, u32 val ); + +/** @brief Read a value from an atomic counter + * + * This can only be safely used to determine the value of the counter when it + * is guaranteed that other threads will not be modifying the counter. This + * makes its usefulness limited. + * + * @param atom pointer to an atomic counter + */ +u32 _mali_osk_atomic_read( _mali_osk_atomic_t *atom ); + +/** @brief Terminate an atomic counter + * + * @param atom pointer to an atomic counter + */ +void _mali_osk_atomic_term( _mali_osk_atomic_t *atom ); +/** @} */ /* end group _mali_osk_atomic */ + + +/** @defgroup _mali_osk_memory OSK Memory Allocation + * @{ */ + +/** @brief Allocate zero-initialized memory. + * + * Returns a buffer capable of containing at least \a n elements of \a size + * bytes each. The buffer is initialized to zero. + * + * If there is a need for a bigger block of memory (16KB or bigger), then + * consider to use _mali_osk_vmalloc() instead, as this function might + * map down to a OS function with size limitations. + * + * The buffer is suitably aligned for storage and subsequent access of every + * type that the compiler supports. Therefore, the pointer to the start of the + * buffer may be cast into any pointer type, and be subsequently accessed from + * such a pointer, without loss of information. + * + * When the buffer is no longer in use, it must be freed with _mali_osk_free(). + * Failure to do so will cause a memory leak. + * + * @note Most toolchains supply memory allocation functions that meet the + * compiler's alignment requirements. + * + * @param n Number of elements to allocate + * @param size Size of each element + * @return On success, the zero-initialized buffer allocated. NULL on failure + */ +void *_mali_osk_calloc( u32 n, u32 size ); + +/** @brief Allocate memory. + * + * Returns a buffer capable of containing at least \a size bytes. The + * contents of the buffer are undefined. + * + * If there is a need for a bigger block of memory (16KB or bigger), then + * consider to use _mali_osk_vmalloc() instead, as this function might + * map down to a OS function with size limitations. + * + * The buffer is suitably aligned for storage and subsequent access of every + * type that the compiler supports. Therefore, the pointer to the start of the + * buffer may be cast into any pointer type, and be subsequently accessed from + * such a pointer, without loss of information. + * + * When the buffer is no longer in use, it must be freed with _mali_osk_free(). + * Failure to do so will cause a memory leak. + * + * @note Most toolchains supply memory allocation functions that meet the + * compiler's alignment requirements. + * + * Remember to free memory using _mali_osk_free(). + * @param size Number of bytes to allocate + * @return On success, the buffer allocated. NULL on failure. + */ +void *_mali_osk_malloc( u32 size ); + +/** @brief Free memory. + * + * Reclaims the buffer pointed to by the parameter \a ptr for the system. + * All memory returned from _mali_osk_malloc() and _mali_osk_calloc() + * must be freed before the application exits. Otherwise, + * a memory leak will occur. + * + * Memory must be freed once. It is an error to free the same non-NULL pointer + * more than once. + * + * It is legal to free the NULL pointer. + * + * @param ptr Pointer to buffer to free + */ +void _mali_osk_free( void *ptr ); + +/** @brief Allocate memory. + * + * Returns a buffer capable of containing at least \a size bytes. The + * contents of the buffer are undefined. + * + * This function is potentially slower than _mali_osk_malloc() and _mali_osk_calloc(), + * but do support bigger sizes. + * + * The buffer is suitably aligned for storage and subsequent access of every + * type that the compiler supports. Therefore, the pointer to the start of the + * buffer may be cast into any pointer type, and be subsequently accessed from + * such a pointer, without loss of information. + * + * When the buffer is no longer in use, it must be freed with _mali_osk_free(). + * Failure to do so will cause a memory leak. + * + * @note Most toolchains supply memory allocation functions that meet the + * compiler's alignment requirements. + * + * Remember to free memory using _mali_osk_free(). + * @param size Number of bytes to allocate + * @return On success, the buffer allocated. NULL on failure. + */ +void *_mali_osk_valloc( u32 size ); + +/** @brief Free memory. + * + * Reclaims the buffer pointed to by the parameter \a ptr for the system. + * All memory returned from _mali_osk_valloc() must be freed before the + * application exits. Otherwise a memory leak will occur. + * + * Memory must be freed once. It is an error to free the same non-NULL pointer + * more than once. + * + * It is legal to free the NULL pointer. + * + * @param ptr Pointer to buffer to free + */ +void _mali_osk_vfree( void *ptr ); + +/** @brief Copies memory. + * + * Copies the \a len bytes from the buffer pointed by the parameter \a src + * directly to the buffer pointed by \a dst. + * + * It is an error for \a src to overlap \a dst anywhere in \a len bytes. + * + * @param dst Pointer to the destination array where the content is to be + * copied. + * @param src Pointer to the source of data to be copied. + * @param len Number of bytes to copy. + * @return \a dst is always passed through unmodified. + */ +void *_mali_osk_memcpy( void *dst, const void *src, u32 len ); + +/** @brief Fills memory. + * + * Sets the first \a n bytes of the block of memory pointed to by \a s to + * the specified value + * @param s Pointer to the block of memory to fill. + * @param c Value to be set, passed as u32. Only the 8 Least Significant Bits (LSB) + * are used. + * @param n Number of bytes to be set to the value. + * @return \a s is always passed through unmodified + */ +void *_mali_osk_memset( void *s, u32 c, u32 n ); +/** @} */ /* end group _mali_osk_memory */ + + +/** @brief Checks the amount of memory allocated + * + * Checks that not more than \a max_allocated bytes are allocated. + * + * Some OS bring up an interactive out of memory dialogue when the + * system runs out of memory. This can stall non-interactive + * apps (e.g. automated test runs). This function can be used to + * not trigger the OOM dialogue by keeping allocations + * within a certain limit. + * + * @return MALI_TRUE when \a max_allocated bytes are not in use yet. MALI_FALSE + * when at least \a max_allocated bytes are in use. + */ +mali_bool _mali_osk_mem_check_allocated( u32 max_allocated ); + +/** @addtogroup _mali_osk_lock + * @{ */ + +/** @brief Initialize a Mutual Exclusion Lock + * + * Locks are created in the signalled (unlocked) state. + * + * initial must be zero, since there is currently no means of expressing + * whether a reader/writer lock should be initially locked as a reader or + * writer. This would require some encoding to be used. + * + * 'Automatic' ordering means that locks must be obtained in the order that + * they were created. For all locks that can be held at the same time, they must + * either all provide the order parameter, or they all must use 'automatic' + * ordering - because there is no way of mixing 'automatic' and 'manual' + * ordering. + * + * @param flags flags combined with bitwise OR ('|'), or zero. There are + * restrictions on which flags can be combined, @see _mali_osk_lock_flags_t. + * @param initial For future expansion into semaphores. SBZ. + * @param order The locking order of the mutex. That is, locks obtained by the + * same thread must have been created with an increasing order parameter, for + * deadlock prevention. Setting to zero causes 'automatic' ordering to be used. + * @return On success, a pointer to a _mali_osk_lock_t object. NULL on failure. + */ +_mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial, u32 order ); + +/** @brief Wait for a lock to be signalled (obtained) + + * After a thread has successfully waited on the lock, the lock is obtained by + * the thread, and is marked as unsignalled. The thread releases the lock by + * signalling it. + * + * In the case of Reader/Writer locks, multiple readers can obtain a lock in + * the absence of writers, which is a performance optimization (providing that + * the readers never write to the protected resource). + * + * To prevent deadlock, locks must always be obtained in the same order. + * + * For locks marked as _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, it is a + * programming error for the function to exit without obtaining the lock. This + * means that the error code must only be checked for interruptible locks. + * + * @param lock the lock to wait upon (obtain). + * @param mode the mode in which the lock should be obtained. Unless the lock + * was created with _MALI_OSK_LOCKFLAG_READERWRITER, this must be + * _MALI_OSK_LOCKMODE_RW. + * @return On success, _MALI_OSK_ERR_OK. For interruptible locks, a suitable + * _mali_osk_errcode_t will be returned on failure, and the lock will not be + * obtained. In this case, the error code must be propagated up to the U/K + * interface. + */ +_mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode); + + +/** @brief Signal (release) a lock + * + * Locks may only be signalled by the thread that originally waited upon the + * lock. + * + * @note In the OSU, a flag exists to allow any thread to signal a + * lock. Such functionality is not present in the OSK. + * + * @param lock the lock to signal (release). + * @param mode the mode in which the lock should be obtained. This must match + * the mode in which the lock was waited upon. + */ +void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ); + +/** @brief Terminate a lock + * + * This terminates a lock and frees all associated resources. + * + * It is a programming error to terminate the lock when it is held (unsignalled) + * by a thread. + * + * @param lock the lock to terminate. + */ +void _mali_osk_lock_term( _mali_osk_lock_t *lock ); +/** @} */ /* end group _mali_osk_lock */ + + +/** @addtogroup _mali_osk_low_level_memory + * @{ */ + +/** @brief Issue a memory barrier + * + * This defines an arbitrary memory barrier operation, which forces an ordering constraint + * on memory read and write operations. + */ +void _mali_osk_mem_barrier( void ); + +/** @brief Issue a write memory barrier + * + * This defines an write memory barrier operation which forces an ordering constraint + * on memory write operations. + */ +void _mali_osk_write_mem_barrier( void ); + +/** @brief Map a physically contiguous region into kernel space + * + * This is primarily used for mapping in registers from resources, and Mali-MMU + * page tables. The mapping is only visable from kernel-space. + * + * Access has to go through _mali_osk_mem_ioread32 and _mali_osk_mem_iowrite32 + * + * @param phys CPU-physical base address of the memory to map in. This must + * be aligned to the system's page size, which is assumed to be 4K. + * @param size the number of bytes of physically contiguous address space to + * map in + * @param description A textual description of the memory being mapped in. + * @return On success, a Mali IO address through which the mapped-in + * memory/registers can be accessed. NULL on failure. + */ +mali_io_address _mali_osk_mem_mapioregion( u32 phys, u32 size, const char *description ); + +/** @brief Unmap a physically contiguous address range from kernel space. + * + * The address range should be one previously mapped in through + * _mali_osk_mem_mapioregion. + * + * It is a programming error to do (but not limited to) the following: + * - attempt an unmap twice + * - unmap only part of a range obtained through _mali_osk_mem_mapioregion + * - unmap more than the range obtained through _mali_osk_mem_mapioregion + * - unmap an address range that was not successfully mapped using + * _mali_osk_mem_mapioregion + * - provide a mapping that does not map to phys. + * + * @param phys CPU-physical base address of the memory that was originally + * mapped in. This must be aligned to the system's page size, which is assumed + * to be 4K + * @param size The number of bytes that were originally mapped in. + * @param mapping The Mali IO address through which the mapping is + * accessed. + */ +void _mali_osk_mem_unmapioregion( u32 phys, u32 size, mali_io_address mapping ); + +/** @brief Allocate and Map a physically contiguous region into kernel space + * + * This is used for allocating physically contiguous regions (such as Mali-MMU + * page tables) and mapping them into kernel space. The mapping is only + * visible from kernel-space. + * + * The alignment of the returned memory is guaranteed to be at least + * _MALI_OSK_CPU_PAGE_SIZE. + * + * Access must go through _mali_osk_mem_ioread32 and _mali_osk_mem_iowrite32 + * + * @note This function is primarily to provide support for OSs that are + * incapable of separating the tasks 'allocate physically contiguous memory' + * and 'map it into kernel space' + * + * @param[out] phys CPU-physical base address of memory that was allocated. + * (*phys) will be guaranteed to be aligned to at least + * _MALI_OSK_CPU_PAGE_SIZE on success. + * + * @param[in] size the number of bytes of physically contiguous memory to + * allocate. This must be a multiple of _MALI_OSK_CPU_PAGE_SIZE. + * + * @return On success, a Mali IO address through which the mapped-in + * memory/registers can be accessed. NULL on failure, and (*phys) is unmodified. + */ +mali_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 size ); + +/** @brief Free a physically contiguous address range from kernel space. + * + * The address range should be one previously mapped in through + * _mali_osk_mem_allocioregion. + * + * It is a programming error to do (but not limited to) the following: + * - attempt a free twice on the same ioregion + * - free only part of a range obtained through _mali_osk_mem_allocioregion + * - free more than the range obtained through _mali_osk_mem_allocioregion + * - free an address range that was not successfully mapped using + * _mali_osk_mem_allocioregion + * - provide a mapping that does not map to phys. + * + * @param phys CPU-physical base address of the memory that was originally + * mapped in, which was aligned to _MALI_OSK_CPU_PAGE_SIZE. + * @param size The number of bytes that were originally mapped in, which was + * a multiple of _MALI_OSK_CPU_PAGE_SIZE. + * @param mapping The Mali IO address through which the mapping is + * accessed. + */ +void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address mapping ); + +/** @brief Request a region of physically contiguous memory + * + * This is used to ensure exclusive access to a region of physically contigous + * memory. + * + * It is acceptable to implement this as a stub. However, it is then the job + * of the System Integrator to ensure that no other device driver will be using + * the physical address ranges used by Mali, while the Mali device driver is + * loaded. + * + * @param phys CPU-physical base address of the memory to request. This must + * be aligned to the system's page size, which is assumed to be 4K. + * @param size the number of bytes of physically contiguous address space to + * request. + * @param description A textual description of the memory being requested. + * @return _MALI_OSK_ERR_OK on success. Otherwise, a suitable + * _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description ); + +/** @brief Un-request a region of physically contiguous memory + * + * This is used to release a regious of physically contiguous memory previously + * requested through _mali_osk_mem_reqregion, so that other device drivers may + * use it. This will be called at time of Mali device driver termination. + * + * It is a programming error to attempt to: + * - unrequest a region twice + * - unrequest only part of a range obtained through _mali_osk_mem_reqregion + * - unrequest more than the range obtained through _mali_osk_mem_reqregion + * - unrequest an address range that was not successfully requested using + * _mali_osk_mem_reqregion + * + * @param phys CPU-physical base address of the memory to un-request. This must + * be aligned to the system's page size, which is assumed to be 4K + * @param size the number of bytes of physically contiguous address space to + * un-request. + */ +void _mali_osk_mem_unreqregion( u32 phys, u32 size ); + +/** @brief Read from a location currently mapped in through + * _mali_osk_mem_mapioregion + * + * This reads a 32-bit word from a 32-bit aligned location. It is a programming + * error to provide unaligned locations, or to read from memory that is not + * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or + * _mali_osk_mem_allocioregion(). + * + * @param mapping Mali IO address to read from + * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4 + * @return the 32-bit word from the specified location. + */ +u32 _mali_osk_mem_ioread32( volatile mali_io_address mapping, u32 offset ); + +/** @brief Write to a location currently mapped in through + * _mali_osk_mem_mapioregion without memory barriers + * + * This write a 32-bit word to a 32-bit aligned location without using memory barrier. + * It is a programming error to provide unaligned locations, or to write to memory that is not + * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or + * _mali_osk_mem_allocioregion(). + * + * @param mapping Mali IO address to write to + * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4 + * @param val the 32-bit word to write. + */ +void _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val ); + +/** @brief Write to a location currently mapped in through + * _mali_osk_mem_mapioregion with write memory barrier + * + * This write a 32-bit word to a 32-bit aligned location. It is a programming + * error to provide unaligned locations, or to write to memory that is not + * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or + * _mali_osk_mem_allocioregion(). + * + * @param mapping Mali IO address to write to + * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4 + * @param val the 32-bit word to write. + */ +void _mali_osk_mem_iowrite32( volatile mali_io_address mapping, u32 offset, u32 val ); + +/** @brief Flush all CPU caches + * + * This should only be implemented if flushing of the cache is required for + * memory mapped in through _mali_osk_mem_mapregion. + */ +void _mali_osk_cache_flushall( void ); + +/** @brief Flush any caches necessary for the CPU and MALI to have the same view of a range of uncached mapped memory + * + * This should only be implemented if your OS doesn't do a full cache flush (inner & outer) + * after allocating uncached mapped memory. + * + * Some OS do not perform a full cache flush (including all outer caches) for uncached mapped memory. + * They zero the memory through a cached mapping, then flush the inner caches but not the outer caches. + * This is required for MALI to have the correct view of the memory. + */ +void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size ); + +/** @} */ /* end group _mali_osk_low_level_memory */ + + +/** @addtogroup _mali_osk_notification + * + * User space notification framework + * + * Communication with user space of asynchronous events is performed through a + * synchronous call to the \ref u_k_api. + * + * Since the events are asynchronous, the events have to be queued until a + * synchronous U/K API call can be made by user-space. A U/K API call might also + * be received before any event has happened. Therefore the notifications the + * different subsystems wants to send to user space has to be queued for later + * reception, or a U/K API call has to be blocked until an event has occured. + * + * Typical uses of notifications are after running of jobs on the hardware or + * when changes to the system is detected that needs to be relayed to user + * space. + * + * After an event has occured user space has to be notified using some kind of + * message. The notification framework supports sending messages to waiting + * threads or queueing of messages until a U/K API call is made. + * + * The notification queue is a FIFO. There are no restrictions on the numbers + * of readers or writers in the queue. + * + * A message contains what user space needs to identifiy how to handle an + * event. This includes a type field and a possible type specific payload. + * + * A notification to user space is represented by a + * \ref _mali_osk_notification_t object. A sender gets hold of such an object + * using _mali_osk_notification_create(). The buffer given by the + * _mali_osk_notification_t::result_buffer field in the object is used to store + * any type specific data. The other fields are internal to the queue system + * and should not be touched. + * + * @{ */ + +/** @brief Create a notification object + * + * Returns a notification object which can be added to the queue of + * notifications pending for user space transfer. + * + * The implementation will initialize all members of the + * \ref _mali_osk_notification_t object. In particular, the + * _mali_osk_notification_t::result_buffer member will be initialized to point + * to \a size bytes of storage, and that storage will be suitably aligned for + * storage of any structure. That is, the created buffer meets the same + * requirements as _mali_osk_malloc(). + * + * The notification object must be deleted when not in use. Use + * _mali_osk_notification_delete() for deleting it. + * + * @note You \b must \b not call _mali_osk_free() on a \ref _mali_osk_notification_t, + * object, or on a _mali_osk_notification_t::result_buffer. You must only use + * _mali_osk_notification_delete() to free the resources assocaited with a + * \ref _mali_osk_notification_t object. + * + * @param type The notification type + * @param size The size of the type specific buffer to send + * @return Pointer to a notification object with a suitable buffer, or NULL on error. + */ +_mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ); + +/** @brief Delete a notification object + * + * This must be called to reclaim the resources of a notification object. This + * includes: + * - The _mali_osk_notification_t::result_buffer + * - The \ref _mali_osk_notification_t itself. + * + * A notification object \b must \b not be used after it has been deleted by + * _mali_osk_notification_delete(). + * + * In addition, the notification object may not be deleted while it is in a + * queue. That is, if it has been placed on a queue with + * _mali_osk_notification_queue_send(), then it must not be deleted until + * it has been received by a call to _mali_osk_notification_queue_receive(). + * Otherwise, the queue may be corrupted. + * + * @param object the notification object to delete. + */ +void _mali_osk_notification_delete( _mali_osk_notification_t *object ); + +/** @brief Create a notification queue + * + * Creates a notification queue which can be used to queue messages for user + * delivery and get queued messages from + * + * The queue is a FIFO, and has no restrictions on the numbers of readers or + * writers. + * + * When the queue is no longer in use, it must be terminated with + * \ref _mali_osk_notification_queue_term(). Failure to do so will result in a + * memory leak. + * + * @return Pointer to a new notification queue or NULL on error. + */ +_mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void ); + +/** @brief Destroy a notification queue + * + * Destroys a notification queue and frees associated resources from the queue. + * + * A notification queue \b must \b not be destroyed in the following cases: + * - while there are \ref _mali_osk_notification_t objects in the queue. + * - while there are writers currently acting upon the queue. That is, while + * a thread is currently calling \ref _mali_osk_notification_queue_send() on + * the queue, or while a thread may call + * \ref _mali_osk_notification_queue_send() on the queue in the future. + * - while there are readers currently waiting upon the queue. That is, while + * a thread is currently calling \ref _mali_osk_notification_queue_receive() on + * the queue, or while a thread may call + * \ref _mali_osk_notification_queue_receive() on the queue in the future. + * + * Therefore, all \ref _mali_osk_notification_t objects must be flushed and + * deleted by the code that makes use of the notification queues, since only + * they know the structure of the _mali_osk_notification_t::result_buffer + * (even if it may only be a flat sturcture). + * + * @note Since the queue is a FIFO, the code using notification queues may + * create its own 'flush' type of notification, to assist in flushing the + * queue. + * + * Once the queue has been destroyed, it must not be used again. + * + * @param queue The queue to destroy + */ +void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue ); + +/** @brief Schedule notification for delivery + * + * When a \ref _mali_osk_notification_t object has been created successfully + * and set up, it may be added to the queue of objects waiting for user space + * transfer. + * + * The sending will not block if the queue is full. + * + * A \ref _mali_osk_notification_t object \b must \b not be put on two different + * queues at the same time, or enqueued twice onto a single queue before + * reception. However, it is acceptable for it to be requeued \em after reception + * from a call to _mali_osk_notification_queue_receive(), even onto the same queue. + * + * Again, requeuing must also not enqueue onto two different queues at the same + * time, or enqueue onto the same queue twice before reception. + * + * @param queue The notification queue to add this notification to + * @param object The entry to add + */ +void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object ); + +/** @brief Receive a notification from a queue + * + * Receives a single notification from the given queue. + * + * If no notifciations are ready the thread will sleep until one becomes ready. + * Therefore, notifications may not be received into an + * IRQ or 'atomic' context (that is, a context where sleeping is disallowed). + * + * @param queue The queue to receive from + * @param result Pointer to storage of a pointer of type + * \ref _mali_osk_notification_t*. \a result will be written to such that the + * expression \a (*result) will evaluate to a pointer to a valid + * \ref _mali_osk_notification_t object, or NULL if none were received. + * @return _MALI_OSK_ERR_OK on success. _MALI_OSK_ERR_RESTARTSYSCALL if the sleep was interrupted. + */ +_mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ); + +/** @brief Dequeues a notification from a queue + * + * Receives a single notification from the given queue. + * + * If no notifciations are ready the function call will return an error code. + * + * @param queue The queue to receive from + * @param result Pointer to storage of a pointer of type + * \ref _mali_osk_notification_t*. \a result will be written to such that the + * expression \a (*result) will evaluate to a pointer to a valid + * \ref _mali_osk_notification_t object, or NULL if none were received. + * @return _MALI_OSK_ERR_OK on success, _MALI_OSK_ERR_ITEM_NOT_FOUND if queue was empty. + */ +_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ); + +/** @} */ /* end group _mali_osk_notification */ + + +/** @addtogroup _mali_osk_timer + * + * Timers use the OS's representation of time, which are 'ticks'. This is to + * prevent aliasing problems between the internal timer time, and the time + * asked for. + * + * @{ */ + +/** @brief Initialize a timer + * + * Allocates resources for a new timer, and initializes them. This does not + * start the timer. + * + * @return a pointer to the allocated timer object, or NULL on failure. + */ +_mali_osk_timer_t *_mali_osk_timer_init(void); + +/** @brief Start a timer + * + * It is an error to start a timer without setting the callback via + * _mali_osk_timer_setcallback(). + * + * It is an error to use this to start an already started timer. + * + * The timer will expire in \a ticks_to_expire ticks, at which point, the + * callback function will be invoked with the callback-specific data, + * as registered by _mali_osk_timer_setcallback(). + * + * @param tim the timer to start + * @param ticks_to_expire the amount of time in ticks for the timer to run + * before triggering. + */ +void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire ); + +/** @brief Modify a timer + * + * Set the relative time at which a timer will expire, and start it if it is + * stopped. If \a ticks_to_expire 0 the timer fires immediately. + * + * It is an error to modify a timer without setting the callback via + * _mali_osk_timer_setcallback(). + * + * The timer will expire at \a ticks_to_expire from the time of the call, at + * which point, the callback function will be invoked with the + * callback-specific data, as set by _mali_osk_timer_setcallback(). + * + * @param tim the timer to modify, and start if necessary + * @param ticks_to_expire the \em absolute time in ticks at which this timer + * should trigger. + * + */ +void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 ticks_to_expire); + +/** @brief Stop a timer, and block on its completion. + * + * Stop the timer. When the function returns, it is guaranteed that the timer's + * callback will not be running on any CPU core. + * + * Since stoping the timer blocks on compeletion of the callback, the callback + * may not obtain any mutexes that the caller holds. Otherwise, a deadlock will + * occur. + * + * @note While the callback itself is guaranteed to not be running, work + * enqueued on the work-queue by the timer (with + * \ref _mali_osk_wq_schedule_work()) may still run. The timer callback and + * work handler must take this into account. + * + * It is legal to stop an already stopped timer. + * + * @param tim the timer to stop. + * + */ +void _mali_osk_timer_del( _mali_osk_timer_t *tim ); + +/** @brief Stop a timer. + * + * Stop the timer. When the function returns, the timer's callback may still be + * running on any CPU core. + * + * It is legal to stop an already stopped timer. + * + * @param tim the timer to stop. + */ +void _mali_osk_timer_del_async( _mali_osk_timer_t *tim ); + +/** @brief Check if timer is pending. + * + * Check if timer is active. + * + * @param tim the timer to check + * @return MALI_TRUE if time is active, MALI_FALSE if it is not active + */ +mali_bool _mali_osk_timer_pending( _mali_osk_timer_t *tim); + +/** @brief Set a timer's callback parameters. + * + * This must be called at least once before a timer is started/modified. + * + * After a timer has been stopped or expires, the callback remains set. This + * means that restarting the timer will call the same function with the same + * parameters on expiry. + * + * @param tim the timer to set callback on. + * @param callback Function to call when timer expires + * @param data Function-specific data to supply to the function on expiry. + */ +void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data ); + +/** @brief Terminate a timer, and deallocate resources. + * + * The timer must first be stopped by calling _mali_osk_timer_del(). + * + * It is a programming error for _mali_osk_timer_term() to be called on: + * - timer that is currently running + * - a timer that is currently executing its callback. + * + * @param tim the timer to deallocate. + */ +void _mali_osk_timer_term( _mali_osk_timer_t *tim ); +/** @} */ /* end group _mali_osk_timer */ + + +/** @defgroup _mali_osk_time OSK Time functions + * + * \ref _mali_osk_time use the OS's representation of time, which are + * 'ticks'. This is to prevent aliasing problems between the internal timer + * time, and the time asked for. + * + * OS tick time is measured as a u32. The time stored in a u32 may either be + * an absolute time, or a time delta between two events. Whilst it is valid to + * use math opeartors to \em change the tick value represented as a u32, it + * is often only meaningful to do such operations on time deltas, rather than + * on absolute time. However, it is meaningful to add/subtract time deltas to + * absolute times. + * + * Conversion between tick time and milliseconds (ms) may not be loss-less, + * and are \em implementation \em depenedant. + * + * Code use OS time must take this into account, since: + * - a small OS time may (or may not) be rounded + * - a large time may (or may not) overflow + * + * @{ */ + +/** @brief Return whether ticka occurs after tickb + * + * Some OSs handle tick 'rollover' specially, and so can be more robust against + * tick counters rolling-over. This function must therefore be called to + * determine if a time (in ticks) really occurs after another time (in ticks). + * + * @param ticka ticka + * @param tickb tickb + * @return non-zero if ticka represents a time that occurs after tickb. + * Zero otherwise. + */ +int _mali_osk_time_after( u32 ticka, u32 tickb ); + +/** @brief Convert milliseconds to OS 'ticks' + * + * @param ms time interval in milliseconds + * @return the corresponding time interval in OS ticks. + */ +u32 _mali_osk_time_mstoticks( u32 ms ); + +/** @brief Convert OS 'ticks' to milliseconds + * + * @param ticks time interval in OS ticks. + * @return the corresponding time interval in milliseconds + */ +u32 _mali_osk_time_tickstoms( u32 ticks ); + + +/** @brief Get the current time in OS 'ticks'. + * @return the current time in OS 'ticks'. + */ +u32 _mali_osk_time_tickcount( void ); + +/** @brief Cause a microsecond delay + * + * The delay will have microsecond resolution, and is necessary for correct + * operation of the driver. At worst, the delay will be \b at least \a usecs + * microseconds, and so may be (significantly) more. + * + * This function may be implemented as a busy-wait, which is the most sensible + * implementation. On OSs where there are situations in which a thread must not + * sleep, this is definitely implemented as a busy-wait. + * + * @param usecs the number of microseconds to wait for. + */ +void _mali_osk_time_ubusydelay( u32 usecs ); + +/** @brief Return time in nano seconds, since any given reference. + * + * @return Time in nano seconds + */ +u64 _mali_osk_time_get_ns( void ); + + +/** @} */ /* end group _mali_osk_time */ + +/** @defgroup _mali_osk_math OSK Math + * @{ */ + +/** @brief Count Leading Zeros (Little-endian) + * + * @note This function must be implemented to support the reference + * implementation of _mali_osk_find_first_zero_bit, as defined in + * mali_osk_bitops.h. + * + * @param val 32-bit words to count leading zeros on + * @return the number of leading zeros. + */ +u32 _mali_osk_clz( u32 val ); +/** @} */ /* end group _mali_osk_math */ + +/** @defgroup _mali_osk_wait_queue OSK Wait Queue functionality + * @{ */ +/** @brief Private type for wait queue objects */ +typedef struct _mali_osk_wait_queue_t_struct _mali_osk_wait_queue_t; + +/** @brief Initialize an empty Wait Queue */ +_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void ); + +/** @brief Sleep if condition is false + * + * @param queue the queue to use + * @param condition function pointer to a boolean function + * + * Put thread to sleep if the given \a codition function returns false. When + * being asked to wake up again, the condition will be re-checked and the + * thread only woken up if the condition is now true. + */ +void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void) ); + +/** @brief Wake up all threads in wait queue if their respective conditions are + * true + * + * @param queue the queue whose threads should be woken up + * + * Wake up all threads in wait queue \a queue whose condition is now true. + */ +void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue ); + +/** @brief terminate a wait queue + * + * @param queue the queue to terminate. + */ +void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue ); +/** @} */ /* end group _mali_osk_wait_queue */ + + +/** @addtogroup _mali_osk_miscellaneous + * @{ */ + +/** @brief Output a device driver debug message. + * + * The interpretation of \a fmt is the same as the \c format parameter in + * _mali_osu_vsnprintf(). + * + * @param fmt a _mali_osu_vsnprintf() style format string + * @param ... a variable-number of parameters suitable for \a fmt + */ +void _mali_osk_dbgmsg( const char *fmt, ... ); + +/** @brief Print fmt into buf. + * + * The interpretation of \a fmt is the same as the \c format parameter in + * _mali_osu_vsnprintf(). + * + * @param buf a pointer to the result buffer + * @param size the total number of bytes allowed to write to \a buf + * @param fmt a _mali_osu_vsnprintf() style format string + * @param ... a variable-number of parameters suitable for \a fmt + * @return The number of bytes written to \a buf + */ +u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... ); + +/** @brief Abnormal process abort. + * + * Terminates the caller-process if this function is called. + * + * This function will be called from Debug assert-macros in mali_kernel_common.h. + * + * This function will never return - because to continue from a Debug assert + * could cause even more problems, and hinder debugging of the initial problem. + * + * This function is only used in Debug builds, and is not used in Release builds. + */ +void _mali_osk_abort(void); + +/** @brief Sets breakpoint at point where function is called. + * + * This function will be called from Debug assert-macros in mali_kernel_common.h, + * to assist in debugging. If debugging at this level is not required, then this + * function may be implemented as a stub. + * + * This function is only used in Debug builds, and is not used in Release builds. + */ +void _mali_osk_break(void); + +/** @brief Return an identificator for calling process. + * + * @return Identificator for calling process. + */ +u32 _mali_osk_get_pid(void); + +/** @brief Return an identificator for calling thread. + * + * @return Identificator for calling thread. + */ +u32 _mali_osk_get_tid(void); + +/** @brief Enable OS controlled runtime power management + */ +void _mali_osk_pm_dev_enable(void); + +/** @brief Disable OS controlled runtime power management + */ +void _mali_osk_pm_dev_disable(void); + + +/** @brief Take a reference to the power manager system for the Mali device. + * + * When function returns successfully, Mali is ON. + * + * @note Call \a _mali_osk_pm_dev_ref_dec() to release this reference. + */ +_mali_osk_errcode_t _mali_osk_pm_dev_ref_add(void); + + +/** @brief Release the reference to the power manger system for the Mali device. + * + * When reference count reach zero, the cores can be off. + * + * @note This must be used to release references taken with \a _mali_osk_pm_dev_ref_add(). + */ +void _mali_osk_pm_dev_ref_dec(void); + + +/** @brief Take a reference to the power manager system for the Mali device. + * + * Will leave the cores powered off if they are already powered off. + * + * @note Call \a _mali_osk_pm_dev_ref_dec() to release this reference. + * + * @return MALI_TRUE if the Mali GPU is powered on, otherwise MALI_FALSE. + */ +mali_bool _mali_osk_pm_dev_ref_add_no_power_on(void); + + +/** @brief Releasing the reference to the power manger system for the Mali device. + * + * When reference count reach zero, the cores can be off. + * + * @note This must be used to release references taken with \a _mali_osk_pm_dev_ref_add_no_power_on(). + */ +void _mali_osk_pm_dev_ref_dec_no_power_on(void); + +/** @brief Block untill pending PM operations are done + */ +void _mali_osk_pm_dev_barrier(void); + +/** @} */ /* end group _mali_osk_miscellaneous */ + +/** @} */ /* end group osuapi */ + +/** @} */ /* end group uddapi */ + +#ifdef __cplusplus +} +#endif + +#include "mali_osk_specific.h" /* include any per-os specifics */ + +/* Check standard inlines */ +#ifndef MALI_STATIC_INLINE + #error MALI_STATIC_INLINE not defined on your OS +#endif + +#ifndef MALI_NON_STATIC_INLINE + #error MALI_NON_STATIC_INLINE not defined on your OS +#endif + +#endif /* __MALI_OSK_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_osk_bitops.h b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_bitops.h new file mode 100644 index 0000000..f262f7d --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_bitops.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_bitops.h + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#ifndef __MALI_OSK_BITOPS_H__ +#define __MALI_OSK_BITOPS_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +MALI_STATIC_INLINE void _mali_internal_clear_bit( u32 bit, u32 *addr ) +{ + MALI_DEBUG_ASSERT( bit < 32 ); + MALI_DEBUG_ASSERT( NULL != addr ); + + (*addr) &= ~(1 << bit); +} + +MALI_STATIC_INLINE void _mali_internal_set_bit( u32 bit, u32 *addr ) +{ + MALI_DEBUG_ASSERT( bit < 32 ); + MALI_DEBUG_ASSERT( NULL != addr ); + + (*addr) |= (1 << bit); +} + +MALI_STATIC_INLINE u32 _mali_internal_test_bit( u32 bit, u32 value ) +{ + MALI_DEBUG_ASSERT( bit < 32 ); + return value & (1 << bit); +} + +MALI_STATIC_INLINE int _mali_internal_find_first_zero_bit( u32 value ) +{ + u32 inverted; + u32 negated; + u32 isolated; + u32 leading_zeros; + + /* Begin with xxx...x0yyy...y, where ys are 1, number of ys is in range 0..31 */ + inverted = ~value; /* zzz...z1000...0 */ + /* Using count_trailing_zeros on inverted value - + * See ARM System Developers Guide for details of count_trailing_zeros */ + + /* Isolate the zero: it is preceeded by a run of 1s, so add 1 to it */ + negated = (u32)-inverted ; /* -a == ~a + 1 (mod 2^n) for n-bit numbers */ + /* negated = xxx...x1000...0 */ + + isolated = negated & inverted ; /* xxx...x1000...0 & zzz...z1000...0, zs are ~xs */ + /* And so the first zero bit is in the same position as the 1 == number of 1s that preceeded it + * Note that the output is zero if value was all 1s */ + + leading_zeros = _mali_osk_clz( isolated ); + + return 31 - leading_zeros; +} + + +/** @defgroup _mali_osk_bitops OSK Non-atomic Bit-operations + * @{ */ + +/** + * These bit-operations do not work atomically, and so locks must be used if + * atomicity is required. + * + * Reference implementations for Little Endian are provided, and so it should + * not normally be necessary to re-implement these. Efficient bit-twiddling + * techniques are used where possible, implemented in portable C. + * + * Note that these reference implementations rely on _mali_osk_clz() being + * implemented. + */ + +/** @brief Clear a bit in a sequence of 32-bit words + * @param nr bit number to clear, starting from the (Little-endian) least + * significant bit + * @param addr starting point for counting. + */ +MALI_STATIC_INLINE void _mali_osk_clear_nonatomic_bit( u32 nr, u32 *addr ) +{ + addr += nr >> 5; /* find the correct word */ + nr = nr & ((1 << 5)-1); /* The bit number within the word */ + + _mali_internal_clear_bit( nr, addr ); +} + +/** @brief Set a bit in a sequence of 32-bit words + * @param nr bit number to set, starting from the (Little-endian) least + * significant bit + * @param addr starting point for counting. + */ +MALI_STATIC_INLINE void _mali_osk_set_nonatomic_bit( u32 nr, u32 *addr ) +{ + addr += nr >> 5; /* find the correct word */ + nr = nr & ((1 << 5)-1); /* The bit number within the word */ + + _mali_internal_set_bit( nr, addr ); +} + +/** @brief Test a bit in a sequence of 32-bit words + * @param nr bit number to test, starting from the (Little-endian) least + * significant bit + * @param addr starting point for counting. + * @return zero if bit was clear, non-zero if set. Do not rely on the return + * value being related to the actual word under test. + */ +MALI_STATIC_INLINE u32 _mali_osk_test_bit( u32 nr, u32 *addr ) +{ + addr += nr >> 5; /* find the correct word */ + nr = nr & ((1 << 5)-1); /* The bit number within the word */ + + return _mali_internal_test_bit( nr, *addr ); +} + +/* Return maxbit if not found */ +/** @brief Find the first zero bit in a sequence of 32-bit words + * @param addr starting point for search. + * @param maxbit the maximum number of bits to search + * @return the number of the first zero bit found, or maxbit if none were found + * in the specified range. + */ +MALI_STATIC_INLINE u32 _mali_osk_find_first_zero_bit( const u32 *addr, u32 maxbit ) +{ + u32 total; + + for ( total = 0; total < maxbit; total += 32, ++addr ) + { + int result; + result = _mali_internal_find_first_zero_bit( *addr ); + + /* non-negative signifies the bit was found */ + if ( result >= 0 ) + { + total += (u32)result; + break; + } + } + + /* Now check if we reached maxbit or above */ + if ( total >= maxbit ) + { + total = maxbit; + } + + return total; /* either the found bit nr, or maxbit if not found */ +} +/** @} */ /* end group _mali_osk_bitops */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_OSK_BITOPS_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_osk_list.h b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_list.h new file mode 100644 index 0000000..49f01b6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_list.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_list.h + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#ifndef __MALI_OSK_LIST_H__ +#define __MALI_OSK_LIST_H__ + +#include "mali_kernel_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +MALI_STATIC_INLINE void __mali_osk_list_add(_mali_osk_list_t *new_entry, _mali_osk_list_t *prev, _mali_osk_list_t *next) +{ + next->prev = new_entry; + new_entry->next = next; + new_entry->prev = prev; + prev->next = new_entry; +} + +MALI_STATIC_INLINE void __mali_osk_list_del(_mali_osk_list_t *prev, _mali_osk_list_t *next) +{ + next->prev = prev; + prev->next = next; +} + +/** @addtogroup _mali_osk_list + * @{ */ + +/** Reference implementations of Doubly-linked Circular Lists are provided. + * There is often no need to re-implement these. + * + * @note The implementation may differ subtly from any lists the OS provides. + * For this reason, these lists should not be mixed with OS-specific lists + * inside the OSK/UKK implementation. */ + +/** @brief Initialize a list element. + * + * All list elements must be initialized before use. + * + * Do not use on any list element that is present in a list without using + * _mali_osk_list_del first, otherwise this will break the list. + * + * @param list the list element to initialize + */ +MALI_STATIC_INLINE void _mali_osk_list_init( _mali_osk_list_t *list ) +{ + list->next = list; + list->prev = list; +} + +/** @brief Insert a single list element after an entry in a list + * + * As an example, if this is inserted to the head of a list, then this becomes + * the first element of the list. + * + * Do not use to move list elements from one list to another, as it will break + * the originating list. + * + * + * @param newlist the list element to insert + * @param list the list in which to insert. The new element will be the next + * entry in this list + */ +MALI_STATIC_INLINE void _mali_osk_list_add( _mali_osk_list_t *new_entry, _mali_osk_list_t *list ) +{ + __mali_osk_list_add(new_entry, list, list->next); +} + +/** @brief Insert a single list element before an entry in a list + * + * As an example, if this is inserted to the head of a list, then this becomes + * the last element of the list. + * + * Do not use to move list elements from one list to another, as it will break + * the originating list. + * + * @param newlist the list element to insert + * @param list the list in which to insert. The new element will be the previous + * entry in this list + */ +MALI_STATIC_INLINE void _mali_osk_list_addtail( _mali_osk_list_t *new_entry, _mali_osk_list_t *list ) +{ + __mali_osk_list_add(new_entry, list->prev, list); +} + +/** @brief Remove a single element from a list + * + * The element will no longer be present in the list. The removed list element + * will be uninitialized, and so should not be traversed. It must be + * initialized before further use. + * + * @param list the list element to remove. + */ +MALI_STATIC_INLINE void _mali_osk_list_del( _mali_osk_list_t *list ) +{ + __mali_osk_list_del(list->prev, list->next); +} + +/** @brief Remove a single element from a list, and re-initialize it + * + * The element will no longer be present in the list. The removed list element + * will initialized, and so can be used as normal. + * + * @param list the list element to remove and initialize. + */ +MALI_STATIC_INLINE void _mali_osk_list_delinit( _mali_osk_list_t *list ) +{ + __mali_osk_list_del(list->prev, list->next); + _mali_osk_list_init(list); +} + +/** @brief Determine whether a list is empty. + * + * An empty list is one that contains a single element that points to itself. + * + * @param list the list to check. + * @return non-zero if the list is empty, and zero otherwise. + */ +MALI_STATIC_INLINE mali_bool _mali_osk_list_empty( _mali_osk_list_t *list ) +{ + return list->next == list; +} + +/** @brief Move a list element from one list to another. + * + * The list element must be initialized. + * + * As an example, moving a list item to the head of a new list causes this item + * to be the first element in the new list. + * + * @param move the list element to move + * @param list the new list into which the element will be inserted, as the next + * element in the list. + */ +MALI_STATIC_INLINE void _mali_osk_list_move( _mali_osk_list_t *move_entry, _mali_osk_list_t *list ) +{ + __mali_osk_list_del(move_entry->prev, move_entry->next); + _mali_osk_list_add(move_entry, list); +} + +/** @brief Move an entire list + * + * The list element must be initialized. + * + * Allows you to move a list from one list head to another list head + * + * @param old_list The existing list head + * @param new_list The new list head (must be an empty list) + */ +MALI_STATIC_INLINE void _mali_osk_list_move_list( _mali_osk_list_t *old_list, _mali_osk_list_t *new_list ) +{ + MALI_DEBUG_ASSERT(_mali_osk_list_empty(new_list)); + if (!_mali_osk_list_empty(old_list)) + { + new_list->next = old_list->next; + new_list->prev = old_list->prev; + new_list->next->prev = new_list; + new_list->prev->next = new_list; + old_list->next = old_list; + old_list->prev = old_list; + } +} +/** @} */ /* end group _mali_osk_list */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_OSK_LIST_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_osk_mali.h b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_mali.h new file mode 100644 index 0000000..2916a0d --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_mali.h @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_mali.h + * Defines the OS abstraction layer which is specific for the Mali kernel device driver (OSK) + */ + +#ifndef __MALI_OSK_MALI_H__ +#define __MALI_OSK_MALI_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup _mali_osk_miscellaneous + * @{ */ + +/** @brief Struct with device specific configuration data + */ +struct _mali_osk_device_data +{ + /* Dedicated GPU memory range (physical). */ + u32 dedicated_mem_start; + u32 dedicated_mem_size; + + /* Shared GPU memory */ + u32 shared_mem_size; + + /* Frame buffer memory to be accessible by Mali GPU (physical) */ + u32 fb_start; + u32 fb_size; + + /* Report GPU utilization in this interval (specified in ms) */ + u32 utilization_interval; + + /* Function that will receive periodic GPU utilization numbers */ + void (*utilization_callback)(struct mali_gpu_utilization_data *data); + + /* + * Mali PMU switch delay. + * Only needed if the power gates are connected to the PMU in a high fanout + * network. This value is the number of Mali clock cycles it takes to + * enable the power gates and turn on the power mesh. + * This value will have no effect if a daisy chain implementation is used. + */ + u32 pmu_switch_delay; +}; + +/** @brief Find Mali GPU HW resource + * + * @param addr Address of Mali GPU resource to find + * @param res Storage for resource information if resource is found. + * @return _MALI_OSK_ERR_OK on success, _MALI_OSK_ERR_ITEM_NOT_FOUND if resource is not found + */ +_mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res); + + +/** @brief Find Mali GPU HW base address + * + * @return 0 if resources are found, otherwise the Mali GPU component with lowest address. + */ +u32 _mali_osk_resource_base_address(void); + +/** @brief Retrieve the Mali GPU specific data + * + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_device_data_get(struct _mali_osk_device_data *data); + +/** @brief Determines if Mali GPU has been configured with shared interrupts. + * + * @return MALI_TRUE if shared interrupts, MALI_FALSE if not. + */ +mali_bool _mali_osk_shared_interrupts(void); + +/** @} */ /* end group _mali_osk_miscellaneous */ + + + + +/** @addtogroup _mali_osk_low_level_memory + * @{ */ + +/** @brief Initialize a user-space accessible memory range + * + * This initializes a virtual address range such that it is reserved for the + * current process, but does not map any physical pages into this range. + * + * This function may initialize or adjust any members of the + * mali_memory_allocation \a descriptor supplied, before the physical pages are + * mapped in with _mali_osk_mem_mapregion_map(). + * + * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE + * set in \a descriptor->flags. It is an error to call this function without + * setting this flag. Otherwise, \a descriptor->flags bits are reserved for + * future expansion + * + * The \a descriptor's process_addr_mapping_info member can be modified to + * allocate OS-specific information. Note that on input, this will be a + * ukk_private word from the U/K inteface, as inserted by _mali_ukk_mem_mmap(). + * This is used to pass information from the U/K interface to the OSK interface, + * if necessary. The precise usage of the process_addr_mapping_info member + * depends on the U/K implementation of _mali_ukk_mem_mmap(). + * + * Therefore, the U/K implementation of _mali_ukk_mem_mmap() and the OSK + * implementation of _mali_osk_mem_mapregion_init() must agree on the meaning and + * usage of the ukk_private word and process_addr_mapping_info member. + * + * Refer to \ref u_k_api for more information on the U/K interface. + * + * On successful return, \a descriptor's mapping member will be correct for + * use with _mali_osk_mem_mapregion_term() and _mali_osk_mem_mapregion_map(). + * + * @param descriptor the mali_memory_allocation to initialize. + */ +_mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descriptor ); + +/** @brief Terminate a user-space accessible memory range + * + * This terminates a virtual address range reserved in the current user process, + * where none, some or all of the virtual address ranges have mappings to + * physical pages. + * + * It will unmap any physical pages that had been mapped into a reserved + * virtual address range for the current process, and then releases the virtual + * address range. Any extra book-keeping information or resources allocated + * during _mali_osk_mem_mapregion_init() will also be released. + * + * The \a descriptor itself is not freed - this must be handled by the caller of + * _mali_osk_mem_mapregion_term(). + * + * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE + * set in descriptor->flags. It is an error to call this function without + * setting this flag. Otherwise, descriptor->flags bits are reserved for + * future expansion + * + * @param descriptor the mali_memory_allocation to terminate. + */ +void _mali_osk_mem_mapregion_term( mali_memory_allocation * descriptor ); + +/** @brief Map physical pages into a user process's virtual address range + * + * This is used to map a number of physically contigous pages into a + * user-process's virtual address range, which was previously reserved by a + * call to _mali_osk_mem_mapregion_init(). + * + * This need not provide a mapping for the entire virtual address range + * reserved for \a descriptor - it may be used to map single pages per call. + * + * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE + * set in \a descriptor->flags. It is an error to call this function without + * setting this flag. Otherwise, \a descriptor->flags bits are reserved for + * future expansion + * + * The function may supply \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC. + * In this case, \a size must be set to \ref _MALI_OSK_CPU_PAGE_SIZE, and the function + * will allocate the physical page itself. The physical address of the + * allocated page will be returned through \a phys_addr. + * + * It is an error to set \a size != \ref _MALI_OSK_CPU_PAGE_SIZE while + * \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, + * since it is not always possible for OSs to support such a setting through this + * interface. + * + * @note \b IMPORTANT: This code must validate the input parameters. If the + * range defined by \a offset and \a size is outside the range allocated in + * \a descriptor, then this function \b MUST not attempt any mapping, and must + * instead return a suitable \ref _mali_osk_errcode_t \b failure code. + * + * @param[in,out] descriptor the mali_memory_allocation representing the + * user-process's virtual address range to map into. + * + * @param[in] offset the offset into the virtual address range. This is only added + * to the mapping member of the \a descriptor, and not the \a phys_addr parameter. + * It must be a multiple of \ref _MALI_OSK_CPU_PAGE_SIZE. + * + * @param[in,out] phys_addr a pointer to the physical base address to begin the + * mapping from. If \a size == \ref _MALI_OSK_CPU_PAGE_SIZE and + * \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, then this + * function will allocate the physical page itself, and return the + * physical address of the page through \a phys_addr, which will be aligned to + * \ref _MALI_OSK_CPU_PAGE_SIZE. Otherwise, \a *phys_addr must be aligned to + * \ref _MALI_OSK_CPU_PAGE_SIZE, and is unmodified after the call. + * \a phys_addr is unaffected by the \a offset parameter. + * + * @param[in] size the number of bytes to map in. This must be a multiple of + * \ref _MALI_OSK_CPU_PAGE_SIZE. + * + * @return _MALI_OSK_ERR_OK on sucess, otherwise a _mali_osk_errcode_t value + * on failure + * + * @note could expand to use _mali_osk_mem_mapregion_flags_t instead of + * \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, but note that we must + * also modify the mali process address manager in the mmu/memory engine code. + */ +_mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size ); + + +/** @brief Unmap physical pages from a user process's virtual address range + * + * This is used to unmap a number of physically contigous pages from a + * user-process's virtual address range, which were previously mapped by a + * call to _mali_osk_mem_mapregion_map(). If the range specified was allocated + * from OS memory, then that memory will be returned to the OS. Whilst pages + * will be mapped out, the Virtual address range remains reserved, and at the + * same base address. + * + * When this function is used to unmap pages from OS memory + * (_mali_osk_mem_mapregion_map() was called with *phys_addr == + * \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC), then the \a flags must + * include \ref _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR. This is because + * it is not always easy for an OS implementation to discover whether the + * memory was OS allocated or not (and so, how it should release the memory). + * + * For this reason, only a range of pages of the same allocation type (all OS + * allocated, or none OS allocacted) may be unmapped in one call. Multiple + * calls must be made if allocations of these different types exist across the + * entire region described by the \a descriptor. + * + * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE + * set in \a descriptor->flags. It is an error to call this function without + * setting this flag. Otherwise, \a descriptor->flags bits are reserved for + * future expansion + * + * @param[in,out] descriptor the mali_memory_allocation representing the + * user-process's virtual address range to map into. + * + * @param[in] offset the offset into the virtual address range. This is only added + * to the mapping member of the \a descriptor. \a offset must be a multiple of + * \ref _MALI_OSK_CPU_PAGE_SIZE. + * + * @param[in] size the number of bytes to unmap. This must be a multiple of + * \ref _MALI_OSK_CPU_PAGE_SIZE. + * + * @param[in] flags specifies how the memory should be unmapped. For a range + * of pages that were originally OS allocated, this must have + * \ref _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR set. + */ +void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags ); + +/** @brief Copy as much data as possible from src to dest, do not crash if src or dest isn't available. + * + * @param dest Destination buffer (limited to user space mapped Mali memory) + * @param src Source buffer + * @param size Number of bytes to copy + * @return Number of bytes actually copied + */ +u32 _mali_osk_mem_write_safe(void *dest, const void *src, u32 size); + +/** @} */ /* end group _mali_osk_low_level_memory */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_OSK_MALI_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_osk_profiling.h b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_profiling.h new file mode 100644 index 0000000..c4822e2 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_profiling.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_OSK_PROFILING_H__ +#define __MALI_OSK_PROFILING_H__ + +#if defined(CONFIG_MALI400_PROFILING) && defined (CONFIG_TRACEPOINTS) + +#include "mali_linux_trace.h" +#include "mali_profiling_events.h" +#include "mali_profiling_gator_api.h" + +#define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576 + +#define MALI_PROFILING_NO_HW_COUNTER = ((u32)-1) + +/** @defgroup _mali_osk_profiling External profiling connectivity + * @{ */ + +/** + * Initialize the profiling module. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start); + +/* + * Terminate the profiling module. + */ +void _mali_osk_profiling_term(void); + +/** + * Start recording profiling data + * + * The specified limit will determine how large the capture buffer is. + * MALI_PROFILING_MAX_BUFFER_ENTRIES determines the maximum size allowed by the device driver. + * + * @param limit The desired maximum number of events to record on input, the actual maximum on output. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit); + +/** + * Add an profiling event + * + * @param event_id The event identificator. + * @param data0 First data parameter, depending on event_id specified. + * @param data1 Second data parameter, depending on event_id specified. + * @param data2 Third data parameter, depending on event_id specified. + * @param data3 Fourth data parameter, depending on event_id specified. + * @param data4 Fifth data parameter, depending on event_id specified. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +/* Call Linux tracepoint directly */ +#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) trace_mali_timeline_event((event_id), (data0), (data1), (data2), (data3), (data4)) + +/** + * Report a hardware counter event. + * + * @param counter_id The ID of the counter. + * @param value The value of the counter. + */ + +/* Call Linux tracepoint directly */ +#define _mali_osk_profiling_report_hw_counter(counter_id, value) trace_mali_hw_counter(counter_id, value) + +/** + * Report SW counters + * + * @param counters array of counter values + */ +void _mali_osk_profiling_report_sw_counters(u32 *counters); + +/** + * Stop recording profiling data + * + * @param count Returns the number of recorded events. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count); + +/** + * Retrieves the number of events that can be retrieved + * + * @return The number of recorded events that can be retrieved. + */ +u32 _mali_osk_profiling_get_count(void); + +/** + * Retrieve an event + * + * @param index Event index (start with 0 and continue until this function fails to retrieve all events) + * @param timestamp The timestamp for the retrieved event will be stored here. + * @param event_id The event ID for the retrieved event will be stored here. + * @param data The 5 data values for the retrieved event will be stored here. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]); + +/** + * Clear the recorded buffer. + * + * This is needed in order to start another recording. + * + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_clear(void); + +/** + * Checks if a recording of profiling data is in progress + * + * @return MALI_TRUE if recording of profiling data is in progress, MALI_FALSE if not + */ +mali_bool _mali_osk_profiling_is_recording(void); + +/** + * Checks if profiling data is available for retrival + * + * @return MALI_TRUE if profiling data is avaiable, MALI_FALSE if not + */ +mali_bool _mali_osk_profiling_have_recording(void); + +/** @} */ /* end group _mali_osk_profiling */ + +#else /* defined(CONFIG_MALI400_PROFILING) && defined(CONFIG_TRACEPOINTS) */ + + /* Dummy add_event, for when profiling is disabled. */ + +#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) + +#endif /* defined(CONFIG_MALI400_PROFILING) && defined(CONFIG_TRACEPOINTS) */ + +#endif /* __MALI_OSK_PROFILING_H__ */ + + diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pm.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pm.c new file mode 100644 index 0000000..e1d6aa4 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pm.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_pm.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" +#include "mali_scheduler.h" +#include "mali_kernel_utilization.h" +#include "mali_group.h" +#include "mali_pm_domain.h" +#include "mali_pmu.h" + +static mali_bool mali_power_on = MALI_FALSE; + +_mali_osk_errcode_t mali_pm_initialize(void) +{ + _mali_osk_pm_dev_enable(); + return _MALI_OSK_ERR_OK; +} + +void mali_pm_terminate(void) +{ + mali_pm_domain_terminate(); + _mali_osk_pm_dev_disable(); +} + +/* Reset GPU after power up */ +static void mali_pm_reset_gpu(void) +{ + /* Reset all L2 caches */ + mali_l2_cache_reset_all(); + + /* Reset all groups */ + mali_scheduler_reset_all_groups(); +} + +void mali_pm_os_suspend(void) +{ + MALI_DEBUG_PRINT(3, ("Mali PM: OS suspend\n")); + mali_gp_scheduler_suspend(); + mali_pp_scheduler_suspend(); + mali_utilization_suspend(); +/* MALI_SEC */ +#if !defined(CONFIG_PM_RUNTIME) + mali_group_power_off(); + mali_power_on = MALI_FALSE; +#endif +} + +void mali_pm_os_resume(void) +{ +#if !defined(CONFIG_PM_RUNTIME) + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + mali_bool do_reset = MALI_FALSE; +#endif + + MALI_DEBUG_PRINT(3, ("Mali PM: OS resume\n")); +/* MALI_SEC */ +/****************************************************************** + * + * <2013. 08. 23> + * In Pegasus prime, PMU is not enabled(Power off) while + * system wake up(suspend -> resume). + * + * Because PMU power is off, GPU does not work. + * Therefore code is commented like below. + * + *****************************************************************/ +#if !defined(CONFIG_PM_RUNTIME) + if (MALI_TRUE != mali_power_on) + { + do_reset = MALI_TRUE; + } + + if (NULL != pmu) + { + mali_pmu_reset(pmu); + } + + mali_power_on = MALI_TRUE; + _mali_osk_write_mem_barrier(); + + if (do_reset) + { + mali_pm_reset_gpu(); + mali_group_power_on(); + } +#endif + mali_gp_scheduler_resume(); + mali_pp_scheduler_resume(); +} + +void mali_pm_runtime_suspend(void) +{ + MALI_DEBUG_PRINT(3, ("Mali PM: Runtime suspend\n")); + mali_group_power_off(); + mali_power_on = MALI_FALSE; +} + +void mali_pm_runtime_resume(void) +{ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + mali_bool do_reset = MALI_FALSE; + + MALI_DEBUG_PRINT(3, ("Mali PM: Runtime resume\n")); + + if (MALI_TRUE != mali_power_on) + { + do_reset = MALI_TRUE; + } + + if (NULL != pmu) + { + mali_pmu_reset(pmu); + } + + mali_power_on = MALI_TRUE; + _mali_osk_write_mem_barrier(); + + if (do_reset) + { + mali_pm_reset_gpu(); + mali_group_power_on(); + } +} + +void mali_pm_set_power_is_on(void) +{ + mali_power_on = MALI_TRUE; +} + +mali_bool mali_pm_is_power_on(void) +{ + return mali_power_on; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pm.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pm.h new file mode 100644 index 0000000..36f0f50 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pm.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PM_H__ +#define __MALI_PM_H__ + +#include "mali_osk.h" + +_mali_osk_errcode_t mali_pm_initialize(void); +void mali_pm_terminate(void); + +/* Callback functions registered for the runtime PMM system */ +void mali_pm_os_suspend(void); +void mali_pm_os_resume(void); +void mali_pm_runtime_suspend(void); +void mali_pm_runtime_resume(void); + +void mali_pm_set_power_is_on(void); +mali_bool mali_pm_is_power_on(void); + +#endif /* __MALI_PM_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c new file mode 100644 index 0000000..9193778 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_pm_domain.h" +#include "mali_pmu.h" +#include "mali_pm.h" +#include "mali_group.h" + +#define MALI_PM_DOMAIN_MAX_DOMAINS 7 + +static struct mali_pm_domain *mali_pm_domains[MALI_PM_DOMAIN_MAX_DOMAINS] = { NULL, }; + +static void mali_pm_domain_lock(struct mali_pm_domain *domain) +{ + _mali_osk_lock_wait(domain->lock, _MALI_OSK_LOCKMODE_RW); +} + +static void mali_pm_domain_unlock(struct mali_pm_domain *domain) +{ + _mali_osk_lock_signal(domain->lock, _MALI_OSK_LOCKMODE_RW); +} + +MALI_STATIC_INLINE void mali_pm_domain_state_set(struct mali_pm_domain *domain, mali_pm_domain_state state) +{ + domain->state = state; +} + +struct mali_pm_domain *mali_pm_domain_create(u32 id, u32 pmu_mask) +{ + struct mali_pm_domain* domain; + + MALI_DEBUG_PRINT(2, ("Mali PM domain: Creating Mali PM domain (mask=0x%08X)\n", pmu_mask)); + + domain = (struct mali_pm_domain *)_mali_osk_malloc(sizeof(struct mali_pm_domain)); + if (NULL != domain) + { + _mali_osk_lock_flags_t flags = _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; + domain->lock = _mali_osk_lock_init(flags, 0, _MALI_OSK_LOCK_ORDER_PM_DOMAIN); + if (NULL == domain->lock) + { + _mali_osk_free(domain); + return NULL; + } + + domain->state = MALI_PM_DOMAIN_ON; + domain->pmu_mask = pmu_mask; + domain->use_count = 0; + domain->group_list = NULL; + domain->group_count = 0; + domain->l2 = NULL; + + MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_MAX_DOMAINS > id); + mali_pm_domains[id] = domain; + + return domain; + } + else + { + MALI_DEBUG_PRINT_ERROR(("Unable to create PM domain\n")); + } + + return NULL; +} + +void mali_pm_domain_delete(struct mali_pm_domain *domain) +{ + if (NULL == domain) + { + return; + } + _mali_osk_lock_term(domain->lock); + + _mali_osk_free(domain); +} + +void mali_pm_domain_terminate(void) +{ + int i; + + /* Delete all domains */ + for (i = 0; i < MALI_PM_DOMAIN_MAX_DOMAINS; i++) + { + mali_pm_domain_delete(mali_pm_domains[i]); + } +} + +void mali_pm_domain_add_group(u32 id, struct mali_group *group) +{ + struct mali_pm_domain *domain = mali_pm_domain_get(id); + struct mali_group *next; + + if (NULL == domain) return; + + MALI_DEBUG_ASSERT_POINTER(group); + + /* Assume domain is on and group is enabled initially. */ + mali_pm_domain_ref_get(domain); + + ++domain->group_count; + next = domain->group_list; + + domain->group_list = group; + + group->pm_domain_list = next; + + mali_group_set_pm_domain(group, domain); +} + +void mali_pm_domain_add_l2(u32 id, struct mali_l2_cache_core *l2) +{ + struct mali_pm_domain *domain = mali_pm_domain_get(id); + + if (NULL == domain) return; + + MALI_DEBUG_ASSERT(NULL == domain->l2); + MALI_DEBUG_ASSERT(NULL != l2); + + domain->l2 = l2; + + mali_l2_cache_set_pm_domain(l2, domain); +} + +struct mali_pm_domain *mali_pm_domain_get(u32 id) +{ + MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_MAX_DOMAINS > id); + + return mali_pm_domains[id]; +} + +void mali_pm_domain_ref_get(struct mali_pm_domain *domain) +{ + if (NULL == domain) return; + + mali_pm_domain_lock(domain); + ++domain->use_count; + + if (MALI_PM_DOMAIN_ON != domain->state) + { + /* Power on */ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(3, ("PM Domain: Powering on 0x%08x\n", domain->pmu_mask)); + + if (NULL != pmu) + { + _mali_osk_errcode_t err; + + err = mali_pmu_power_up(pmu, domain->pmu_mask); + + if (_MALI_OSK_ERR_OK != err && _MALI_OSK_ERR_BUSY != err) + { + MALI_PRINT_ERROR(("PM Domain: Failed to power up PM domain 0x%08x\n", + domain->pmu_mask)); + } + } + mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_ON); + } + else + { + MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(domain)); + } + + mali_pm_domain_unlock(domain); +} + +void mali_pm_domain_ref_put(struct mali_pm_domain *domain) +{ + if (NULL == domain) return; + + mali_pm_domain_lock(domain); + --domain->use_count; + + if (0 == domain->use_count && MALI_PM_DOMAIN_OFF != domain->state) + { + /* Power off */ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(3, ("PM Domain: Powering off 0x%08x\n", domain->pmu_mask)); + + mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_OFF); + + if (NULL != pmu) + { + _mali_osk_errcode_t err; + + err = mali_pmu_power_down(pmu, domain->pmu_mask); + + if (_MALI_OSK_ERR_OK != err && _MALI_OSK_ERR_BUSY != err) + { + MALI_PRINT_ERROR(("PM Domain: Failed to power down PM domain 0x%08x\n", + domain->pmu_mask)); + } + } + } + mali_pm_domain_unlock(domain); +} + +mali_bool mali_pm_domain_lock_state(struct mali_pm_domain *domain) +{ + mali_bool is_powered = MALI_TRUE; + + /* Take a reference without powering on */ + if (NULL != domain) + { + mali_pm_domain_lock(domain); + ++domain->use_count; + + if (MALI_PM_DOMAIN_ON != domain->state) + { + is_powered = MALI_FALSE; + } + mali_pm_domain_unlock(domain); + } + + if(!_mali_osk_pm_dev_ref_add_no_power_on()) + { + is_powered = MALI_FALSE; + } + + return is_powered; +} + +void mali_pm_domain_unlock_state(struct mali_pm_domain *domain) +{ + _mali_osk_pm_dev_ref_dec_no_power_on(); + + if (NULL != domain) + { + mali_pm_domain_ref_put(domain); + } +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.h new file mode 100644 index 0000000..3f3fa24 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PM_DOMAIN_H__ +#define __MALI_PM_DOMAIN_H__ + +#include "mali_kernel_common.h" +#include "mali_osk.h" + +#include "mali_l2_cache.h" +#include "mali_group.h" +#include "mali_pmu.h" + +typedef enum +{ + MALI_PM_DOMAIN_ON, + MALI_PM_DOMAIN_OFF, +} mali_pm_domain_state; + +struct mali_pm_domain +{ + mali_pm_domain_state state; + _mali_osk_lock_t *lock; + + s32 use_count; + + u32 pmu_mask; + + int group_count; + struct mali_group *group_list; + + struct mali_l2_cache_core *l2; +}; + +struct mali_pm_domain *mali_pm_domain_create(u32 id, u32 pmu_mask); +void mali_pm_domain_add_group(u32 id, struct mali_group *group); +void mali_pm_domain_add_l2(u32 id, struct mali_l2_cache_core *l2); +void mali_pm_domain_delete(struct mali_pm_domain *domain); + +void mali_pm_domain_terminate(void); + +/** Get PM domain from domain ID + */ +struct mali_pm_domain *mali_pm_domain_get(u32 id); + +/* Ref counting */ +void mali_pm_domain_ref_get(struct mali_pm_domain *domain); +void mali_pm_domain_ref_put(struct mali_pm_domain *domain); + +MALI_STATIC_INLINE struct mali_l2_cache_core *mali_pm_domain_l2_get(struct mali_pm_domain *domain) +{ + return domain->l2; +} + +MALI_STATIC_INLINE mali_pm_domain_state mali_pm_domain_state_get(struct mali_pm_domain *domain) +{ + return domain->state; +} + +mali_bool mali_pm_domain_lock_state(struct mali_pm_domain *domain); +void mali_pm_domain_unlock_state(struct mali_pm_domain *domain); + +#define MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) for ((group) = (domain)->group_list;\ + NULL != (group); (group) = (group)->pm_domain_list) + +#endif /* __MALI_PM_DOMAIN_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.c new file mode 100644 index 0000000..668c8e9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.c @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_pmu.c + * Mali driver functions for Mali 400 PMU hardware + */ +#include "mali_hw_core.h" +#include "mali_pmu.h" +#include "mali_pp.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_pm.h" +#include "mali_osk_mali.h" + +static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches); + +/** @brief MALI inbuilt PMU hardware info and PMU hardware has knowledge of cores power mask + */ +struct mali_pmu_core +{ + struct mali_hw_core hw_core; + _mali_osk_lock_t *lock; + u32 registered_cores_mask; + u32 active_cores_mask; + u32 switch_delay; +}; + +static struct mali_pmu_core *mali_global_pmu_core = NULL; + +/** @brief Register layout for hardware PMU + */ +typedef enum { + PMU_REG_ADDR_MGMT_POWER_UP = 0x00, /*< Power up register */ + PMU_REG_ADDR_MGMT_POWER_DOWN = 0x04, /*< Power down register */ + PMU_REG_ADDR_MGMT_STATUS = 0x08, /*< Core sleep status register */ + PMU_REG_ADDR_MGMT_INT_MASK = 0x0C, /*< Interrupt mask register */ + PMU_REG_ADDR_MGMT_INT_RAWSTAT = 0x10, /*< Interrupt raw status register */ + PMU_REG_ADDR_MGMT_INT_CLEAR = 0x18, /*< Interrupt clear register */ + PMU_REG_ADDR_MGMT_SW_DELAY = 0x1C, /*< Switch delay register */ + PMU_REGISTER_ADDRESS_SPACE_SIZE = 0x28, /*< Size of register space */ +} pmu_reg_addr_mgmt_addr; + +#define PMU_REG_VAL_IRQ 1 + +struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches) +{ + struct mali_pmu_core* pmu; + + MALI_DEBUG_ASSERT(NULL == mali_global_pmu_core); + MALI_DEBUG_PRINT(2, ("Mali PMU: Creating Mali PMU core\n")); + + pmu = (struct mali_pmu_core *)_mali_osk_malloc(sizeof(struct mali_pmu_core)); + if (NULL != pmu) + { + pmu->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, + 0, _MALI_OSK_LOCK_ORDER_PMU); + if (NULL != pmu->lock) + { + pmu->registered_cores_mask = mali_pmu_detect_mask(number_of_pp_cores, number_of_l2_caches); + pmu->active_cores_mask = pmu->registered_cores_mask; + + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&pmu->hw_core, resource, PMU_REGISTER_ADDRESS_SPACE_SIZE)) + { + _mali_osk_errcode_t err; + struct _mali_osk_device_data data = { 0, }; + + err = _mali_osk_device_data_get(&data); + if (_MALI_OSK_ERR_OK == err) + { + pmu->switch_delay = data.pmu_switch_delay; + mali_global_pmu_core = pmu; + return pmu; + } + mali_hw_core_delete(&pmu->hw_core); + } + _mali_osk_lock_term(pmu->lock); + } + _mali_osk_free(pmu); + } + + return NULL; +} + +void mali_pmu_delete(struct mali_pmu_core *pmu) +{ + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(pmu == mali_global_pmu_core); + MALI_DEBUG_PRINT(2, ("Mali PMU: Deleting Mali PMU core\n")); + + _mali_osk_lock_term(pmu->lock); + mali_hw_core_delete(&pmu->hw_core); + _mali_osk_free(pmu); + mali_global_pmu_core = NULL; +} + +static void mali_pmu_lock(struct mali_pmu_core *pmu) +{ + _mali_osk_lock_wait(pmu->lock, _MALI_OSK_LOCKMODE_RW); +} +static void mali_pmu_unlock(struct mali_pmu_core *pmu) +{ + _mali_osk_lock_signal(pmu->lock, _MALI_OSK_LOCKMODE_RW); +} + +static _mali_osk_errcode_t mali_pmu_send_command_internal(struct mali_pmu_core *pmu, const u32 command, const u32 mask) +{ + u32 rawstat; + u32 timeout = MALI_REG_POLL_COUNT_SLOW; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(0 == (mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_RAWSTAT) + & PMU_REG_VAL_IRQ)); + + mali_hw_core_register_write(&pmu->hw_core, command, mask); + + /* Wait for the command to complete */ + do + { + rawstat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_RAWSTAT); + --timeout; + } while (0 == (rawstat & PMU_REG_VAL_IRQ) && 0 < timeout); + + MALI_DEBUG_ASSERT(0 < timeout); + if (0 == timeout) + { + return _MALI_OSK_ERR_TIMEOUT; + } + + mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_CLEAR, PMU_REG_VAL_IRQ); + + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_pmu_send_command(struct mali_pmu_core *pmu, const u32 command, const u32 mask) +{ + u32 stat; + + if (0 == mask) return _MALI_OSK_ERR_OK; + + stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); + stat &= pmu->registered_cores_mask; + + switch (command) + { + case PMU_REG_ADDR_MGMT_POWER_DOWN: + if (mask == stat) return _MALI_OSK_ERR_OK; + break; + case PMU_REG_ADDR_MGMT_POWER_UP: + if (0 == (stat & mask)) return _MALI_OSK_ERR_OK; + break; + default: + MALI_DEBUG_ASSERT(0); + break; + } + + mali_pmu_send_command_internal(pmu, command, mask); + +#if defined(DEBUG) + { + /* Get power status of cores */ + stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); + stat &= pmu->registered_cores_mask; + + switch (command) + { + case PMU_REG_ADDR_MGMT_POWER_DOWN: + MALI_DEBUG_ASSERT(mask == (stat & mask)); + MALI_DEBUG_ASSERT(0 == (stat & pmu->active_cores_mask)); + MALI_DEBUG_ASSERT((pmu->registered_cores_mask & ~pmu->active_cores_mask) == stat); + break; + case PMU_REG_ADDR_MGMT_POWER_UP: + MALI_DEBUG_ASSERT(0 == (stat & mask)); + MALI_DEBUG_ASSERT(0 == (stat & pmu->active_cores_mask)); + break; + default: + MALI_DEBUG_ASSERT(0); + break; + } + } +#endif /* defined(DEBUG) */ + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu) +{ + _mali_osk_errcode_t err; + u32 cores_off_mask, cores_on_mask, stat; + + mali_pmu_lock(pmu); + + /* Setup the desired defaults */ + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0); + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_SW_DELAY, pmu->switch_delay); + + /* Get power status of cores */ + stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); + + cores_off_mask = pmu->registered_cores_mask & ~(stat | pmu->active_cores_mask); + cores_on_mask = pmu->registered_cores_mask & (stat & pmu->active_cores_mask); + + if (0 != cores_off_mask) + { + err = mali_pmu_send_command_internal(pmu, PMU_REG_ADDR_MGMT_POWER_DOWN, cores_off_mask); + if (_MALI_OSK_ERR_OK != err) return err; + } + + if (0 != cores_on_mask) + { + err = mali_pmu_send_command_internal(pmu, PMU_REG_ADDR_MGMT_POWER_UP, cores_on_mask); + if (_MALI_OSK_ERR_OK != err) return err; + } + +#if defined(DEBUG) + { + stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); + stat &= pmu->registered_cores_mask; + + MALI_DEBUG_ASSERT(stat == (pmu->registered_cores_mask & ~pmu->active_cores_mask)); + } +#endif /* defined(DEBUG) */ + + mali_pmu_unlock(pmu); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_pmu_power_down(struct mali_pmu_core *pmu, u32 mask) +{ + _mali_osk_errcode_t err; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0 ); + + /* Make sure we have a valid power domain mask */ + if (mask > pmu->registered_cores_mask) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } + + mali_pmu_lock(pmu); + + MALI_DEBUG_PRINT(4, ("Mali PMU: Power down (0x%08X)\n", mask)); + + pmu->active_cores_mask &= ~mask; + + _mali_osk_pm_dev_ref_add_no_power_on(); + if (!mali_pm_is_power_on()) + { + /* Don't touch hardware if all of Mali is powered off. */ + _mali_osk_pm_dev_ref_dec_no_power_on(); + mali_pmu_unlock(pmu); + + MALI_DEBUG_PRINT(4, ("Mali PMU: Skipping power down (0x%08X) since Mali is off\n", mask)); + + return _MALI_OSK_ERR_BUSY; + } + + err = mali_pmu_send_command(pmu, PMU_REG_ADDR_MGMT_POWER_DOWN, mask); + + _mali_osk_pm_dev_ref_dec_no_power_on(); + mali_pmu_unlock(pmu); + + return err; +} + +_mali_osk_errcode_t mali_pmu_power_up(struct mali_pmu_core *pmu, u32 mask) +{ + _mali_osk_errcode_t err; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0 ); + + /* Make sure we have a valid power domain mask */ + if (mask & ~pmu->registered_cores_mask) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } + + mali_pmu_lock(pmu); + + MALI_DEBUG_PRINT(4, ("Mali PMU: Power up (0x%08X)\n", mask)); + + pmu->active_cores_mask |= mask; + + _mali_osk_pm_dev_ref_add_no_power_on(); + if (!mali_pm_is_power_on()) + { + /* Don't touch hardware if all of Mali is powered off. */ + _mali_osk_pm_dev_ref_dec_no_power_on(); + mali_pmu_unlock(pmu); + + MALI_DEBUG_PRINT(4, ("Mali PMU: Skipping power up (0x%08X) since Mali is off\n", mask)); + + return _MALI_OSK_ERR_BUSY; + } + + err = mali_pmu_send_command(pmu, PMU_REG_ADDR_MGMT_POWER_UP, mask); + + _mali_osk_pm_dev_ref_dec_no_power_on(); + mali_pmu_unlock(pmu); + + return err; +} + +_mali_osk_errcode_t mali_pmu_power_down_all(struct mali_pmu_core *pmu) +{ + _mali_osk_errcode_t err; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0); + + mali_pmu_lock(pmu); + + /* Setup the desired defaults in case we were called before mali_pmu_reset() */ + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0); + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_SW_DELAY, pmu->switch_delay); + + err = mali_pmu_send_command(pmu, PMU_REG_ADDR_MGMT_POWER_DOWN, pmu->registered_cores_mask); + + mali_pmu_unlock(pmu); + + return err; +} + +_mali_osk_errcode_t mali_pmu_power_up_all(struct mali_pmu_core *pmu) +{ + _mali_osk_errcode_t err; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0); + + mali_pmu_lock(pmu); + + /* Setup the desired defaults in case we were called before mali_pmu_reset() */ + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0); + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_SW_DELAY, pmu->switch_delay); + + err = mali_pmu_send_command(pmu, PMU_REG_ADDR_MGMT_POWER_UP, pmu->active_cores_mask); + + mali_pmu_unlock(pmu); + return err; +} + +struct mali_pmu_core *mali_pmu_get_global_pmu_core(void) +{ + return mali_global_pmu_core; +} + +static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches) +{ + u32 mask = 0; + + if (number_of_l2_caches == 1) + { + /* Mali-300 or Mali-400 */ + u32 i; + + /* GP */ + mask = 0x01; + + /* L2 cache */ + mask |= 0x01<<1; + + /* Set bit for each PP core */ + for (i = 0; i < number_of_pp_cores; i++) + { + mask |= 0x01<<(i+2); + } + } + else if (number_of_l2_caches > 1) + { + /* Mali-450 */ + + /* GP (including its L2 cache) */ + mask = 0x01; + + /* There is always at least one PP (including its L2 cache) */ + mask |= 0x01<<1; + + /* Additional PP cores in same L2 cache */ + if (number_of_pp_cores >= 2) + { + mask |= 0x01<<2; + } + + /* Additional PP cores in a third L2 cache */ + if (number_of_pp_cores >= 5) + { + mask |= 0x01<<3; + } + } + + MALI_DEBUG_PRINT(4, ("Mali PMU: Power mask is 0x%08X (%u + %u)\n", mask, number_of_pp_cores, number_of_l2_caches)); + + return mask; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.h new file mode 100644 index 0000000..7e2f67c --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_platform.h + * Platform specific Mali driver functions + */ + +#ifndef __MALI_PMU_H__ +#define __MALI_PMU_H__ + +#include "mali_osk.h" + +#define MALI_PMU_M450_DOM1 0 +#define MALI_PMU_M450_DOM1_MASK (1 << 1) +#define MALI_PMU_M450_DOM2 1 +#define MALI_PMU_M450_DOM2_MASK (1 << 2) +#define MALI_PMU_M450_DOM3 2 +#define MALI_PMU_M450_DOM3_MASK (1 << 3) + +#define MALI_PMU_M400_PP0 0 +#define MALI_PMU_M400_PP0_MASK (1 << 2) +#define MALI_PMU_M400_PP1 1 +#define MALI_PMU_M400_PP1_MASK (1 << 3) +#define MALI_PMU_M400_PP2 2 +#define MALI_PMU_M400_PP2_MASK (1 << 4) +#define MALI_PMU_M400_PP3 3 +#define MALI_PMU_M400_PP3_MASK (1 << 5) + +struct mali_pmu_core; + +/** @brief Initialisation of MALI PMU + * + * This is called from entry point of the driver in order to create and intialize the PMU resource + * + * @param resource it will be a pointer to a PMU resource + * @param number_of_pp_cores Number of found PP resources in configuration + * @param number_of_l2_caches Number of found L2 cache resources in configuration + * @return The created PMU object, or NULL in case of failure. + */ +struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches); + +/** @brief It deallocates the PMU resource + * + * This is called on the exit of the driver to terminate the PMU resource + * + * @param pmu Pointer to PMU core object to delete + */ +void mali_pmu_delete(struct mali_pmu_core *pmu); + +/** @brief Reset PMU core + * + * @param pmu Pointer to PMU core object to reset + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu); + +/** @brief MALI GPU power down using MALI in-built PMU + * + * Called to power down the specified cores. The mask will be saved so that \a + * mali_pmu_power_up_all will bring the PMU back to the previous state set with + * this function or \a mali_pmu_power_up. + * + * @param pmu Pointer to PMU core object to power down + * @param mask Mask specifying which power domains to power down + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmu_power_down(struct mali_pmu_core *pmu, u32 mask); + +/** @brief MALI GPU power up using MALI in-built PMU + * + * Called to power up the specified cores. The mask will be saved so that \a + * mali_pmu_power_up_all will bring the PMU back to the previous state set with + * this function or \a mali_pmu_power_down. + * + * @param pmu Pointer to PMU core object to power up + * @param mask Mask specifying which power domains to power up + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmu_power_up(struct mali_pmu_core *pmu, u32 mask); + +/** @brief MALI GPU power down using MALI in-built PMU + * + * called to power down all cores + * + * @param pmu Pointer to PMU core object to power down + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmu_power_down_all(struct mali_pmu_core *pmu); + +/** @brief MALI GPU power up using MALI in-built PMU + * + * called to power up all cores + * + * @param pmu Pointer to PMU core object to power up + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmu_power_up_all(struct mali_pmu_core *pmu); + +/** @brief Retrieves the Mali PMU core object (if any) + * + * @return The Mali PMU object, or NULL if no PMU exists. + */ +struct mali_pmu_core *mali_pmu_get_global_pmu_core(void); + +#endif /* __MALI_PMU_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pp.c new file mode 100644 index 0000000..8273239 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp.c @@ -0,0 +1,521 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_pp_job.h" +#include "mali_pp.h" +#include "mali_hw_core.h" +#include "mali_group.h" +#include "regs/mali_200_regs.h" +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#if defined(CONFIG_MALI400_PROFILING) +#include "mali_osk_profiling.h" +#endif + +/* Number of frame registers on Mali-200 */ +#define MALI_PP_MALI200_NUM_FRAME_REGISTERS ((0x04C/4)+1) +/* Number of frame registers on Mali-300 and later */ +#define MALI_PP_MALI400_NUM_FRAME_REGISTERS ((0x058/4)+1) + +static struct mali_pp_core* mali_global_pp_cores[MALI_MAX_NUMBER_OF_PP_CORES] = { NULL }; +static u32 mali_global_num_pp_cores = 0; + +/* Interrupt handlers */ +static void mali_pp_irq_probe_trigger(void *data); +static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data); + +struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual, u32 bcast_id) +{ + struct mali_pp_core* core = NULL; + + MALI_DEBUG_PRINT(2, ("Mali PP: Creating Mali PP core: %s\n", resource->description)); + MALI_DEBUG_PRINT(2, ("Mali PP: Base address of PP core: 0x%x\n", resource->base)); + + if (mali_global_num_pp_cores >= MALI_MAX_NUMBER_OF_PP_CORES) + { + MALI_PRINT_ERROR(("Mali PP: Too many PP core objects created\n")); + return NULL; + } + + core = _mali_osk_malloc(sizeof(struct mali_pp_core)); + if (NULL != core) + { + core->core_id = mali_global_num_pp_cores; + core->bcast_id = bcast_id; + core->counter_src0_used = MALI_HW_CORE_NO_COUNTER; + core->counter_src1_used = MALI_HW_CORE_NO_COUNTER; + + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI200_REG_SIZEOF_REGISTER_BANK)) + { + _mali_osk_errcode_t ret; + + if (!is_virtual) + { + ret = mali_pp_reset(core); + } + else + { + ret = _MALI_OSK_ERR_OK; + } + + if (_MALI_OSK_ERR_OK == ret) + { + ret = mali_group_add_pp_core(group, core); + if (_MALI_OSK_ERR_OK == ret) + { + /* Setup IRQ handlers (which will do IRQ probing if needed) */ + MALI_DEBUG_ASSERT(!is_virtual || -1 != resource->irq); + + core->irq = _mali_osk_irq_init(resource->irq, + mali_group_upper_half_pp, + group, + mali_pp_irq_probe_trigger, + mali_pp_irq_probe_ack, + core, + "mali_pp_irq_handlers"); + if (NULL != core->irq) + { + mali_global_pp_cores[mali_global_num_pp_cores] = core; + mali_global_num_pp_cores++; + + return core; + } + else + { + MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description)); + } + mali_group_remove_pp_core(group); + } + else + { + MALI_PRINT_ERROR(("Mali PP: Failed to add core %s to group\n", core->hw_core.description)); + } + } + mali_hw_core_delete(&core->hw_core); + } + + _mali_osk_free(core); + } + else + { + MALI_PRINT_ERROR(("Mali PP: Failed to allocate memory for PP core\n")); + } + + return NULL; +} + +void mali_pp_delete(struct mali_pp_core *core) +{ + u32 i; + + MALI_DEBUG_ASSERT_POINTER(core); + + _mali_osk_irq_term(core->irq); + mali_hw_core_delete(&core->hw_core); + + /* Remove core from global list */ + for (i = 0; i < mali_global_num_pp_cores; i++) + { + if (mali_global_pp_cores[i] == core) + { + mali_global_pp_cores[i] = NULL; + mali_global_num_pp_cores--; + + if (i != mali_global_num_pp_cores) + { + /* We removed a PP core from the middle of the array -- move the last + * PP core to the current position to close the gap */ + mali_global_pp_cores[i] = mali_global_pp_cores[mali_global_num_pp_cores]; + mali_global_pp_cores[mali_global_num_pp_cores] = NULL; + } + + break; + } + } + + _mali_osk_free(core); +} + +void mali_pp_stop_bus(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + /* Will only send the stop bus command, and not wait for it to complete */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS); +} + +_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core) +{ + int i; + + MALI_DEBUG_ASSERT_POINTER(core); + + /* Send the stop bus command. */ + mali_pp_stop_bus(core); + + /* Wait for bus to be stopped */ + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED) + break; + } + + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_PRINT_ERROR(("Mali PP: Failed to stop bus on %s. Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +/* Frame register reset values. + * Taken from the Mali400 TRM, 3.6. Pixel processor control register summary */ +static const u32 mali_frame_registers_reset_values[_MALI_PP_MAX_FRAME_REGISTERS] = +{ + 0x0, /* Renderer List Address Register */ + 0x0, /* Renderer State Word Base Address Register */ + 0x0, /* Renderer Vertex Base Register */ + 0x2, /* Feature Enable Register */ + 0x0, /* Z Clear Value Register */ + 0x0, /* Stencil Clear Value Register */ + 0x0, /* ABGR Clear Value 0 Register */ + 0x0, /* ABGR Clear Value 1 Register */ + 0x0, /* ABGR Clear Value 2 Register */ + 0x0, /* ABGR Clear Value 3 Register */ + 0x0, /* Bounding Box Left Right Register */ + 0x0, /* Bounding Box Bottom Register */ + 0x0, /* FS Stack Address Register */ + 0x0, /* FS Stack Size and Initial Value Register */ + 0x0, /* Reserved */ + 0x0, /* Reserved */ + 0x0, /* Origin Offset X Register */ + 0x0, /* Origin Offset Y Register */ + 0x75, /* Subpixel Specifier Register */ + 0x0, /* Tiebreak mode Register */ + 0x0, /* Polygon List Format Register */ + 0x0, /* Scaling Register */ + 0x0 /* Tilebuffer configuration Register */ +}; + +/* WBx register reset values */ +static const u32 mali_wb_registers_reset_values[_MALI_PP_MAX_WB_REGISTERS] = +{ + 0x0, /* WBx Source Select Register */ + 0x0, /* WBx Target Address Register */ + 0x0, /* WBx Target Pixel Format Register */ + 0x0, /* WBx Target AA Format Register */ + 0x0, /* WBx Target Layout */ + 0x0, /* WBx Target Scanline Length */ + 0x0, /* WBx Target Flags Register */ + 0x0, /* WBx MRT Enable Register */ + 0x0, /* WBx MRT Offset Register */ + 0x0, /* WBx Global Test Enable Register */ + 0x0, /* WBx Global Test Reference Value Register */ + 0x0 /* WBx Global Test Compare Function Register */ +}; + +/* Performance Counter 0 Enable Register reset value */ +static const u32 mali_perf_cnt_enable_reset_value = 0; + +_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core) +{ + /* Bus must be stopped before calling this function */ + const u32 reset_invalid_value = 0xC0FFE000; + const u32 reset_check_value = 0xC01A0000; + int i; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_DEBUG_PRINT(2, ("Mali PP: Hard reset of core %s\n", core->hw_core.description)); + + /* Set register to a bogus value. The register will be used to detect when reset is complete */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value); + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); + + /* Force core to reset */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET); + + /* Wait for reset to be complete */ + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_check_value); + if (reset_check_value == mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW)) + { + break; + } + } + + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_PRINT_ERROR(("Mali PP: The hard reset loop didn't work, unable to recover\n")); + } + + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, 0x00000000); /* set it back to the default */ + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); + + return _MALI_OSK_ERR_OK; +} + +void mali_pp_reset_async(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + MALI_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description)); + + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET); +} + +_mali_osk_errcode_t mali_pp_reset_wait(struct mali_pp_core *core) +{ + int i; + u32 rawstat = 0; + + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + if (!(mali_pp_read_status(core) & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE)) + { + rawstat = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT); + if (rawstat == MALI400PP_REG_VAL_IRQ_RESET_COMPLETED) + { + break; + } + } + } + + if (i == MALI_REG_POLL_COUNT_FAST) + { + MALI_PRINT_ERROR(("Mali PP: Failed to reset core %s, rawstat: 0x%08x\n", + core->hw_core.description, rawstat)); + return _MALI_OSK_ERR_FAULT; + } + + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core) +{ + mali_pp_reset_async(core); + return mali_pp_reset_wait(core); +} + +void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job, mali_bool restart_virtual) +{ + u32 relative_address; + u32 start_index; + u32 nr_of_regs; + u32 *frame_registers = mali_pp_job_get_frame_registers(job); + u32 *wb0_registers = mali_pp_job_get_wb0_registers(job); + u32 *wb1_registers = mali_pp_job_get_wb1_registers(job); + u32 *wb2_registers = mali_pp_job_get_wb2_registers(job); + core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job); + core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job); + + MALI_DEBUG_ASSERT_POINTER(core); + + /* Write frame registers */ + + /* + * There are two frame registers which are different for each sub job: + * 1. The Renderer List Address Register (MALI200_REG_ADDR_FRAME) + * 2. The FS Stack Address Register (MALI200_REG_ADDR_STACK) + */ + mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_FRAME / sizeof(u32)]); + + /* For virtual jobs, the stack address shouldn't be broadcast but written individually */ + if (!mali_pp_job_is_virtual(job) || restart_virtual) + { + mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK / sizeof(u32)]); + } + + /* Write registers between MALI200_REG_ADDR_FRAME and MALI200_REG_ADDR_STACK */ + relative_address = MALI200_REG_ADDR_RSW; + start_index = MALI200_REG_ADDR_RSW / sizeof(u32); + nr_of_regs = (MALI200_REG_ADDR_STACK - MALI200_REG_ADDR_RSW) / sizeof(u32); + + mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, + relative_address, &frame_registers[start_index], + nr_of_regs, &mali_frame_registers_reset_values[start_index]); + + /* MALI200_REG_ADDR_STACK_SIZE */ + relative_address = MALI200_REG_ADDR_STACK_SIZE; + start_index = MALI200_REG_ADDR_STACK_SIZE / sizeof(u32); + + mali_hw_core_register_write_relaxed_conditional(&core->hw_core, + relative_address, frame_registers[start_index], + mali_frame_registers_reset_values[start_index]); + + /* Skip 2 reserved registers */ + + /* Write remaining registers */ + relative_address = MALI200_REG_ADDR_ORIGIN_OFFSET_X; + start_index = MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32); + nr_of_regs = MALI_PP_MALI400_NUM_FRAME_REGISTERS - MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32); + + mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, + relative_address, &frame_registers[start_index], + nr_of_regs, &mali_frame_registers_reset_values[start_index]); + + /* Write WBx registers */ + if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ + { + mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values); + } + + if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ + { + mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values); + } + + if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ + { + mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values); + } + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); + mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); + } + if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); + mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); + } + + MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description)); + + /* Adding barrier to make sure all rester writes are finished */ + _mali_osk_write_mem_barrier(); + + /* This is the command that starts the core. */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING); + + /* Adding barrier to make sure previous rester writes is finished */ + _mali_osk_write_mem_barrier(); +} + +u32 mali_pp_core_get_version(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION); +} + +struct mali_pp_core* mali_pp_get_global_pp_core(u32 index) +{ + if (mali_global_num_pp_cores > index) + { + return mali_global_pp_cores[index]; + } + + return NULL; +} + +u32 mali_pp_get_glob_num_pp_cores(void) +{ + return mali_global_num_pp_cores; +} + +/* ------------- interrupt handling below ------------------ */ +static void mali_pp_irq_probe_trigger(void *data) +{ + struct mali_pp_core *core = (struct mali_pp_core *)data; + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG); + _mali_osk_mem_barrier(); +} + +static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data) +{ + struct mali_pp_core *core = (struct mali_pp_core *)data; + u32 irq_readout; + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); + if (MALI200_REG_VAL_IRQ_FORCE_HANG & irq_readout) + { + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_FORCE_HANG); + _mali_osk_mem_barrier(); + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + + +#if 0 +static void mali_pp_print_registers(struct mali_pp_core *core) +{ + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_VERSION = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_MASK = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE))); +} +#endif + +#if 0 +void mali_pp_print_state(struct mali_pp_core *core) +{ + MALI_DEBUG_PRINT(2, ("Mali PP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) )); +} +#endif + +void mali_pp_update_performance_counters(struct mali_pp_core *parent, struct mali_pp_core *child, struct mali_pp_job *job, u32 subjob) +{ + u32 val0 = 0; + u32 val1 = 0; +#if defined(CONFIG_MALI400_PROFILING) + int counter_index = COUNTER_FP_0_C0 + (2 * child->core_id); +#endif + + if (MALI_HW_CORE_NO_COUNTER != parent->counter_src0_used) + { + val0 = mali_hw_core_register_read(&child->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE); + mali_pp_job_set_perf_counter_value0(job, subjob, val0); + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_report_hw_counter(counter_index, val0); +#endif + } + + if (MALI_HW_CORE_NO_COUNTER != parent->counter_src1_used) + { + val1 = mali_hw_core_register_read(&child->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE); + mali_pp_job_set_perf_counter_value1(job, subjob, val1); + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_report_hw_counter(counter_index + 1, val1); +#endif + } +} + +#if MALI_STATE_TRACKING +u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "\tPP #%d: %s\n", core->core_id, core->hw_core.description); + + return n; +} +#endif diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pp.h new file mode 100644 index 0000000..dd8f350 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PP_H__ +#define __MALI_PP_H__ + +#include "mali_osk.h" +#include "mali_pp_job.h" +#include "mali_hw_core.h" + +struct mali_group; + +#define MALI_MAX_NUMBER_OF_PP_CORES 9 + +/** + * Definition of the PP core struct + * Used to track a PP core in the system. + */ +struct mali_pp_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + _mali_osk_irq_t *irq; /**< IRQ handler */ + u32 core_id; /**< Unique core ID */ + u32 bcast_id; /**< The "flag" value used by the Mali-450 broadcast and DLBU unit */ + u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */ + u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */ +}; + +_mali_osk_errcode_t mali_pp_initialize(void); +void mali_pp_terminate(void); + +struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group, mali_bool is_virtual, u32 bcast_id); +void mali_pp_delete(struct mali_pp_core *core); + +void mali_pp_stop_bus(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core); +void mali_pp_reset_async(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_reset_wait(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core); + +void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job, mali_bool restart_virtual); + +u32 mali_pp_core_get_version(struct mali_pp_core *core); + +MALI_STATIC_INLINE u32 mali_pp_core_get_id(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return core->core_id; +} + +MALI_STATIC_INLINE u32 mali_pp_core_get_bcast_id(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return core->bcast_id; +} + +struct mali_pp_core* mali_pp_get_global_pp_core(u32 index); +u32 mali_pp_get_glob_num_pp_cores(void); + +/* Debug */ +u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size); + +/** + * Put instrumented HW counters from the core(s) to the job object (if enabled) + * + * parent and child is always the same, except for virtual jobs on Mali-450. + * In this case, the counters will be enabled on the virtual core (parent), + * but values need to be read from the child cores. + * + * @param parent The core used to see if the counters was enabled + * @param child The core to actually read the values from + * @job Job object to update with counter values (if enabled) + * @subjob Which subjob the counters are applicable for (core ID for virtual jobs) + */ +void mali_pp_update_performance_counters(struct mali_pp_core *parent, struct mali_pp_core *child, struct mali_pp_job *job, u32 subjob); + +MALI_STATIC_INLINE const char *mali_pp_get_hw_core_desc(struct mali_pp_core *core) +{ + return core->hw_core.description; +} + +/*** Register reading/writing functions ***/ +MALI_STATIC_INLINE u32 mali_pp_get_int_stat(struct mali_pp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); +} + +MALI_STATIC_INLINE u32 mali_pp_read_rawstat(struct mali_pp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED; +} + +MALI_STATIC_INLINE u32 mali_pp_read_status(struct mali_pp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS); +} + +MALI_STATIC_INLINE void mali_pp_mask_all_interrupts(struct mali_pp_core *core) +{ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); +} + +MALI_STATIC_INLINE void mali_pp_clear_hang_interrupt(struct mali_pp_core *core) +{ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_HANG); +} + +MALI_STATIC_INLINE void mali_pp_enable_interrupts(struct mali_pp_core *core) +{ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); +} + +MALI_STATIC_INLINE void mali_pp_write_addr_stack(struct mali_pp_core *core, struct mali_pp_job *job) +{ + u32 addr = mali_pp_job_get_addr_stack(job, core->core_id); + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_STACK, addr); +} + +#endif /* __MALI_PP_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.c new file mode 100644 index 0000000..ca0ea05 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_pp_job.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_kernel_common.h" +#include "mali_uk_types.h" +#include "mali_pp_scheduler.h" + +static u32 pp_counter_src0 = MALI_HW_CORE_NO_COUNTER; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ +static u32 pp_counter_src1 = MALI_HW_CORE_NO_COUNTER; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ + +struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id) +{ + struct mali_pp_job *job; + u32 perf_counter_flag; + + job = _mali_osk_calloc(1, sizeof(struct mali_pp_job)); + if (NULL != job) + { + if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_pp_start_job_s))) + { + goto fail; + } + + if (job->uargs.num_cores > _MALI_PP_MAX_SUB_JOBS) + { + MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n")); + goto fail; + } + + if (!mali_pp_job_use_no_notification(job)) + { + job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s)); + if (NULL == job->finished_notification) goto fail; + } + + perf_counter_flag = mali_pp_job_get_perf_counter_flag(job); + + /* case when no counters came from user space + * so pass the debugfs / DS-5 provided global ones to the job object */ + if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) || + (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))) + { + mali_pp_job_set_perf_counter_src0(job, mali_pp_job_get_pp_counter_src0()); + mali_pp_job_set_perf_counter_src1(job, mali_pp_job_get_pp_counter_src1()); + } + + _mali_osk_list_init(&job->list); + job->session = session; + _mali_osk_list_init(&job->session_list); + job->id = id; + + job->sub_jobs_num = job->uargs.num_cores ? job->uargs.num_cores : 1; + job->pid = _mali_osk_get_pid(); + job->tid = _mali_osk_get_tid(); + + job->num_memory_cookies = job->uargs.num_memory_cookies; + if (job->num_memory_cookies > 0) + { + u32 size; + + if (job->uargs.num_memory_cookies > session->descriptor_mapping->current_nr_mappings) + { + MALI_PRINT_ERROR(("Mali PP job: Too many memory cookies specified in job object\n")); + goto fail; + } + + size = sizeof(*job->uargs.memory_cookies) * job->num_memory_cookies; + + job->memory_cookies = _mali_osk_malloc(size); + if (NULL == job->memory_cookies) + { + MALI_PRINT_ERROR(("Mali PP job: Failed to allocate %d bytes of memory cookies!\n", size)); + goto fail; + } + + if (0 != _mali_osk_copy_from_user(job->memory_cookies, job->uargs.memory_cookies, size)) + { + MALI_PRINT_ERROR(("Mali PP job: Failed to copy %d bytes of memory cookies from user!\n", size)); + goto fail; + } + +#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + job->num_dma_bufs = job->num_memory_cookies; + job->dma_bufs = _mali_osk_calloc(job->num_dma_bufs, sizeof(struct mali_dma_buf_attachment *)); + if (NULL == job->dma_bufs) + { + MALI_PRINT_ERROR(("Mali PP job: Failed to allocate dma_bufs array!\n")); + goto fail; + } +#endif + } + else + { + job->memory_cookies = NULL; + } + + return job; + } + +fail: + if (NULL != job) + { + mali_pp_job_delete(job); + } + + return NULL; +} + +void mali_pp_job_delete(struct mali_pp_job *job) +{ +#ifdef CONFIG_SYNC + /* It is safe to delete the work without flushing. */ + if (NULL != job->sync_work) _mali_osk_wq_delete_work_nonflush(job->sync_work); + if (NULL != job->pre_fence) sync_fence_put(job->pre_fence); + if (NULL != job->sync_point) sync_fence_put(job->sync_point->fence); +#endif + if (NULL != job->finished_notification) + { + _mali_osk_notification_delete(job->finished_notification); + } + + _mali_osk_free(job->memory_cookies); + +#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + /* Unmap buffers attached to job */ + if (0 < job->num_dma_bufs) + { + mali_dma_buf_unmap_job(job); + } + + _mali_osk_free(job->dma_bufs); +#endif /* CONFIG_DMA_SHARED_BUFFER */ + + _mali_osk_free(job); +} + +u32 mali_pp_job_get_pp_counter_src0(void) +{ + return pp_counter_src0; +} + +mali_bool mali_pp_job_set_pp_counter_src0(u32 counter) +{ + pp_counter_src0 = counter; + + return MALI_TRUE; +} + +u32 mali_pp_job_get_pp_counter_src1(void) +{ + return pp_counter_src1; +} + +mali_bool mali_pp_job_set_pp_counter_src1(u32 counter) +{ + pp_counter_src1 = counter; + + return MALI_TRUE; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.h new file mode 100644 index 0000000..2aed8cc --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.h @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PP_JOB_H__ +#define __MALI_PP_JOB_H__ + +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_uk_types.h" +#include "mali_session.h" +#include "mali_kernel_common.h" +#include "regs/mali_200_regs.h" +#include "mali_kernel_core.h" +#ifdef CONFIG_SYNC +#include +#endif +#include "mali_dlbu.h" +#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) +#include "linux/mali_dma_buf.h" +#endif + +/** + * The structure represents a PP job, including all sub-jobs + * (This struct unfortunately needs to be public because of how the _mali_osk_list_* + * mechanism works) + */ +struct mali_pp_job +{ + _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */ + struct mali_session_data *session; /**< Session which submitted this job */ + _mali_osk_list_t session_list; /**< Used to link jobs together in the session job list */ + _mali_uk_pp_start_job_s uargs; /**< Arguments from user space */ + u32 id; /**< Identifier for this job in kernel space (sequential numbering) */ + u32 perf_counter_value0[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 0 (to be returned to user space), one for each sub job */ + u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 1 (to be returned to user space), one for each sub job */ + u32 sub_jobs_num; /**< Number of subjobs; set to 1 for Mali-450 if DLBU is used, otherwise equals number of PP cores */ + u32 sub_jobs_started; /**< Total number of sub-jobs started (always started in ascending order) */ + u32 sub_jobs_completed; /**< Number of completed sub-jobs in this superjob */ + u32 sub_job_errors; /**< Bitfield with errors (errors for each single sub-job is or'ed together) */ + u32 pid; /**< Process ID of submitting process */ + u32 tid; /**< Thread ID of submitting thread */ + _mali_osk_notification_t *finished_notification; /**< Notification sent back to userspace on job complete */ + u32 num_memory_cookies; /**< Number of memory cookies attached to job */ + u32 *memory_cookies; /**< Memory cookies attached to job */ +#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + struct mali_dma_buf_attachment **dma_bufs; /**< Array of DMA-bufs used by job */ + u32 num_dma_bufs; /**< Number of DMA-bufs used by job */ +#endif +#ifdef CONFIG_SYNC + mali_sync_pt *sync_point; /**< Sync point to signal on completion */ + struct sync_fence_waiter sync_waiter; /**< Sync waiter for async wait */ + _mali_osk_wq_work_t *sync_work; /**< Work to schedule in callback */ + struct sync_fence *pre_fence; /**< Sync fence this job must wait for */ +#endif +}; + +struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id); +void mali_pp_job_delete(struct mali_pp_job *job); + +u32 mali_pp_job_get_pp_counter_src0(void); +mali_bool mali_pp_job_set_pp_counter_src0(u32 counter); +u32 mali_pp_job_get_pp_counter_src1(void); +mali_bool mali_pp_job_set_pp_counter_src1(u32 counter); + +MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job) +{ + return (NULL == job) ? 0 : job->id; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_user_id(struct mali_pp_job *job) +{ + return job->uargs.user_job_ptr; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_frame_builder_id(struct mali_pp_job *job) +{ + return job->uargs.frame_builder_id; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_flush_id(struct mali_pp_job *job) +{ + return job->uargs.flush_id; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_pid(struct mali_pp_job *job) +{ + return job->pid; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_tid(struct mali_pp_job *job) +{ + return job->tid; +} + +MALI_STATIC_INLINE u32* mali_pp_job_get_frame_registers(struct mali_pp_job *job) +{ + return job->uargs.frame_registers; +} + +MALI_STATIC_INLINE u32* mali_pp_job_get_dlbu_registers(struct mali_pp_job *job) +{ + return job->uargs.dlbu_registers; +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_is_virtual(struct mali_pp_job *job) +{ + return 0 == job->uargs.num_cores; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 sub_job) +{ + if (mali_pp_job_is_virtual(job)) + { + return MALI_DLBU_VIRT_ADDR; + } + else if (0 == sub_job) + { + return job->uargs.frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)]; + } + else if (sub_job < _MALI_PP_MAX_SUB_JOBS) + { + return job->uargs.frame_registers_addr_frame[sub_job - 1]; + } + + return 0; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 sub_job) +{ + if (0 == sub_job) + { + return job->uargs.frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)]; + } + else if (sub_job < _MALI_PP_MAX_SUB_JOBS) + { + return job->uargs.frame_registers_addr_stack[sub_job - 1]; + } + + return 0; +} + +MALI_STATIC_INLINE u32* mali_pp_job_get_wb0_registers(struct mali_pp_job *job) +{ + return job->uargs.wb0_registers; +} + +MALI_STATIC_INLINE u32* mali_pp_job_get_wb1_registers(struct mali_pp_job *job) +{ + return job->uargs.wb1_registers; +} + +MALI_STATIC_INLINE u32* mali_pp_job_get_wb2_registers(struct mali_pp_job *job) +{ + return job->uargs.wb2_registers; +} + +MALI_STATIC_INLINE void mali_pp_job_disable_wb0(struct mali_pp_job *job) +{ + job->uargs.wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; +} + +MALI_STATIC_INLINE void mali_pp_job_disable_wb1(struct mali_pp_job *job) +{ + job->uargs.wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; +} + +MALI_STATIC_INLINE void mali_pp_job_disable_wb2(struct mali_pp_job *job) +{ + job->uargs.wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; +} + +MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali_pp_job *job) +{ + return job->session; +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_has_unstarted_sub_jobs(struct mali_pp_job *job) +{ + return (job->sub_jobs_started < job->sub_jobs_num) ? MALI_TRUE : MALI_FALSE; +} + +/* Function used when we are terminating a session with jobs. Return TRUE if it has a rendering job. + Makes sure that no new subjobs are started. */ +MALI_STATIC_INLINE void mali_pp_job_mark_unstarted_failed(struct mali_pp_job *job) +{ + u32 jobs_remaining = job->sub_jobs_num - job->sub_jobs_started; + job->sub_jobs_started += jobs_remaining; + job->sub_jobs_completed += jobs_remaining; + job->sub_job_errors += jobs_remaining; +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_is_complete(struct mali_pp_job *job) +{ + return (job->sub_jobs_num == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_job *job) +{ + return job->sub_jobs_started; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_sub_job_count(struct mali_pp_job *job) +{ + return job->sub_jobs_num; +} + +MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job, u32 sub_job) +{ + /* Assert that we are marking the "first unstarted sub job" as started */ + MALI_DEBUG_ASSERT(job->sub_jobs_started == sub_job); + job->sub_jobs_started++; +} + +MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_completed(struct mali_pp_job *job, mali_bool success) +{ + job->sub_jobs_completed++; + if ( MALI_FALSE == success ) + { + job->sub_job_errors++; + } +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_was_success(struct mali_pp_job *job) +{ + if ( 0 == job->sub_job_errors ) + { + return MALI_TRUE; + } + return MALI_FALSE; +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_has_active_barrier(struct mali_pp_job *job) +{ + return job->uargs.flags & _MALI_PP_JOB_FLAG_BARRIER ? MALI_TRUE : MALI_FALSE; +} + +MALI_STATIC_INLINE void mali_pp_job_barrier_enforced(struct mali_pp_job *job) +{ + job->uargs.flags &= ~_MALI_PP_JOB_FLAG_BARRIER; +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_use_no_notification(struct mali_pp_job *job) +{ + return job->uargs.flags & _MALI_PP_JOB_FLAG_NO_NOTIFICATION ? MALI_TRUE : MALI_FALSE; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_flag(struct mali_pp_job *job) +{ + return job->uargs.perf_counter_flag; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src0(struct mali_pp_job *job) +{ + return job->uargs.perf_counter_src0; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src1(struct mali_pp_job *job) +{ + return job->uargs.perf_counter_src1; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value0(struct mali_pp_job *job, u32 sub_job) +{ + return job->perf_counter_value0[sub_job]; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value1(struct mali_pp_job *job, u32 sub_job) +{ + return job->perf_counter_value1[sub_job]; +} + +MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_src0(struct mali_pp_job *job, u32 src) +{ + job->uargs.perf_counter_src0 = src; +} + +MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_src1(struct mali_pp_job *job, u32 src) +{ + job->uargs.perf_counter_src1 = src; +} + +MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value0(struct mali_pp_job *job, u32 sub_job, u32 value) +{ + job->perf_counter_value0[sub_job] = value; +} + +MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value1(struct mali_pp_job *job, u32 sub_job, u32 value) +{ + job->perf_counter_value1[sub_job] = value; +} + +MALI_STATIC_INLINE _mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job) +{ + if (mali_pp_job_is_virtual(job) && job->sub_jobs_num != 1) + { + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +#endif /* __MALI_PP_JOB_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.c new file mode 100644 index 0000000..3f10bdc --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.c @@ -0,0 +1,1890 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_pp_scheduler.h" +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_scheduler.h" +#include "mali_pp.h" +#include "mali_pp_job.h" +#include "mali_group.h" +#include "mali_pm.h" +#include "mali_kernel_utilization.h" +#include "mali_session.h" +#include "mali_pm_domain.h" +#include "linux/mali/mali_utgard.h" + +#if defined(CONFIG_DMA_SHARED_BUFFER) +#include "mali_dma_buf.h" +#endif +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) +#include +#include +#endif + + +/* With certain configurations, job deletion involves functions which cannot be called from atomic context. + * This #if checks for those cases and enables job deletion to be deferred and run in a different context. */ +#if defined(CONFIG_SYNC) || !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) +#define MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE 1 +#endif + +/* Maximum of 8 PP cores (a group can only have maximum of 1 PP core) */ +#define MALI_MAX_NUMBER_OF_PP_GROUPS 9 + +static mali_bool mali_pp_scheduler_is_suspended(void); +static void mali_pp_scheduler_do_schedule(void *arg); +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) +static void mali_pp_scheduler_do_job_delete(void *arg); +#endif +static void mali_pp_scheduler_job_queued(void); +static void mali_pp_scheduler_job_completed(void); + +static u32 pp_version = 0; + +/* Physical job queue */ +static _MALI_OSK_LIST_HEAD_STATIC_INIT(job_queue); /* List of physical jobs with some unscheduled work */ +static u32 job_queue_depth = 0; + +/* Physical groups */ +static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_working); /* List of physical groups with working jobs on the pp core */ +static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_idle); /* List of physical groups with idle jobs on the pp core */ +static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_disabled); /* List of disabled physical groups */ + +/* Virtual job queue (Mali-450 only) */ +static _MALI_OSK_LIST_HEAD_STATIC_INIT(virtual_job_queue); /* List of unstarted jobs for the virtual group */ +static u32 virtual_job_queue_depth = 0; + +/* Virtual group (Mali-450 only) */ +static struct mali_group *virtual_group = NULL; /* Virtual group (if any) */ +static enum +{ + VIRTUAL_GROUP_IDLE, + VIRTUAL_GROUP_WORKING, + VIRTUAL_GROUP_DISABLED, +} +virtual_group_state = VIRTUAL_GROUP_IDLE; /* Flag which indicates whether the virtual group is working or idle */ + +/* Number of physical cores */ +static u32 num_cores = 0; +static u32 enabled_cores = 0; + +/* Variables to allow safe pausing of the scheduler */ +static _mali_osk_wait_queue_t *pp_scheduler_working_wait_queue = NULL; +static u32 pause_count = 0; + +static _mali_osk_lock_t *pp_scheduler_lock = NULL; +/* Contains tid of thread that locked the scheduler or 0, if not locked */ +MALI_DEBUG_CODE(static u32 pp_scheduler_lock_owner = 0); + +static _mali_osk_wq_work_t *pp_scheduler_wq_schedule = NULL; + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) +static _mali_osk_wq_work_t *pp_scheduler_wq_job_delete = NULL; +static _mali_osk_lock_t *pp_scheduler_job_delete_lock = NULL; +static _MALI_OSK_LIST_HEAD_STATIC_INIT(pp_scheduler_job_deletion_queue); +#endif + +MALI_STATIC_INLINE mali_bool mali_pp_scheduler_has_virtual_group(void) +{ + return NULL != virtual_group; +} + +_mali_osk_errcode_t mali_pp_scheduler_initialize(void) +{ + _mali_osk_lock_flags_t lock_flags; + +#if defined(MALI_UPPER_HALF_SCHEDULING) + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#else + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#endif + + pp_scheduler_lock = _mali_osk_lock_init(lock_flags, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); + if (NULL == pp_scheduler_lock) + { + return _MALI_OSK_ERR_NOMEM; + } + + pp_scheduler_working_wait_queue = _mali_osk_wait_queue_init(); + if (NULL == pp_scheduler_working_wait_queue) + { + _mali_osk_lock_term(pp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } + + pp_scheduler_wq_schedule = _mali_osk_wq_create_work(mali_pp_scheduler_do_schedule, NULL); + if (NULL == pp_scheduler_wq_schedule) + { + _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); + _mali_osk_lock_term(pp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + pp_scheduler_wq_job_delete = _mali_osk_wq_create_work(mali_pp_scheduler_do_job_delete, NULL); + if (NULL == pp_scheduler_wq_job_delete) + { + _mali_osk_wq_delete_work(pp_scheduler_wq_schedule); + _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); + _mali_osk_lock_term(pp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } + + pp_scheduler_job_delete_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER_DEFERRED); + if (NULL == pp_scheduler_job_delete_lock) + { + _mali_osk_wq_delete_work(pp_scheduler_wq_job_delete); + _mali_osk_wq_delete_work(pp_scheduler_wq_schedule); + _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); + _mali_osk_lock_term(pp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } +#endif + + return _MALI_OSK_ERR_OK; +} + +void mali_pp_scheduler_terminate(void) +{ +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + _mali_osk_lock_term(pp_scheduler_job_delete_lock); + _mali_osk_wq_delete_work(pp_scheduler_wq_job_delete); +#endif + + _mali_osk_wq_delete_work(pp_scheduler_wq_schedule); + _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); + _mali_osk_lock_term(pp_scheduler_lock); +} + +void mali_pp_scheduler_populate(void) +{ + struct mali_group *group; + struct mali_pp_core *pp_core; + u32 num_groups; + u32 i; + + num_groups = mali_group_get_glob_num_groups(); + + /* Do we have a virtual group? */ + for (i = 0; i < num_groups; i++) + { + group = mali_group_get_glob_group(i); + + if (mali_group_is_virtual(group)) + { + MALI_DEBUG_PRINT(3, ("Found virtual group %p\n", group)); + + virtual_group = group; + break; + } + } + + /* Find all the available PP cores */ + for (i = 0; i < num_groups; i++) + { + group = mali_group_get_glob_group(i); + pp_core = mali_group_get_pp_core(group); + + if (NULL != pp_core && !mali_group_is_virtual(group)) + { + if (0 == pp_version) + { + /* Retrieve PP version from the first available PP core */ + pp_version = mali_pp_core_get_version(pp_core); + } + + if (mali_pp_scheduler_has_virtual_group()) + { + /* Add all physical PP cores to the virtual group */ + mali_group_lock(virtual_group); + group->state = MALI_GROUP_STATE_JOINING_VIRTUAL; + mali_group_add_group(virtual_group, group, MALI_TRUE); + mali_group_unlock(virtual_group); + } + else + { + _mali_osk_list_add(&group->pp_scheduler_list, &group_list_idle); + } + + num_cores++; + } + } + enabled_cores = num_cores; +} + +void mali_pp_scheduler_depopulate(void) +{ + struct mali_group *group, *temp; + + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working)); + MALI_DEBUG_ASSERT(VIRTUAL_GROUP_WORKING != virtual_group_state); + + /* Delete all groups owned by scheduler */ + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_delete(virtual_group); + } + + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list) + { + mali_group_delete(group); + } + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_disabled, struct mali_group, pp_scheduler_list) + { + mali_group_delete(group); + } +} + +MALI_STATIC_INLINE void mali_pp_scheduler_lock(void) +{ + if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW)) + { + /* Non-interruptable lock failed: this should never happen. */ + MALI_DEBUG_ASSERT(0); + } + MALI_DEBUG_PRINT(5, ("Mali PP scheduler: PP scheduler lock taken\n")); + MALI_DEBUG_ASSERT(0 == pp_scheduler_lock_owner); + MALI_DEBUG_CODE(pp_scheduler_lock_owner = _mali_osk_get_tid()); +} + +MALI_STATIC_INLINE void mali_pp_scheduler_unlock(void) +{ + MALI_DEBUG_PRINT(5, ("Mali PP scheduler: Releasing PP scheduler lock\n")); + MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner); + MALI_DEBUG_CODE(pp_scheduler_lock_owner = 0); + _mali_osk_lock_signal(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW); +} + +MALI_STATIC_INLINE void mali_pp_scheduler_disable_empty_virtual(void) +{ + MALI_ASSERT_GROUP_LOCKED(virtual_group); + + if (mali_group_virtual_disable_if_empty(virtual_group)) + { + MALI_DEBUG_PRINT(4, ("Disabling empty virtual group\n")); + + MALI_DEBUG_ASSERT(VIRTUAL_GROUP_IDLE == virtual_group_state); + + virtual_group_state = VIRTUAL_GROUP_DISABLED; + } +} + +MALI_STATIC_INLINE void mali_pp_scheduler_enable_empty_virtual(void) +{ + MALI_ASSERT_GROUP_LOCKED(virtual_group); + + if (mali_group_virtual_enable_if_empty(virtual_group)) + { + MALI_DEBUG_PRINT(4, ("Re-enabling empty virtual group\n")); + + MALI_DEBUG_ASSERT(VIRTUAL_GROUP_DISABLED == virtual_group_state); + + virtual_group_state = VIRTUAL_GROUP_IDLE; + } +} + +#ifdef DEBUG +MALI_STATIC_INLINE void mali_pp_scheduler_assert_locked(void) +{ + MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner); +} +#define MALI_ASSERT_PP_SCHEDULER_LOCKED() mali_pp_scheduler_assert_locked() +#else +#define MALI_ASSERT_PP_SCHEDULER_LOCKED() +#endif + +/** + * Returns a physical job if a physical job is ready to run (no barrier present) + */ +MALI_STATIC_INLINE struct mali_pp_job *mali_pp_scheduler_get_physical_job(void) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + + if (!_mali_osk_list_empty(&job_queue)) + { + struct mali_pp_job *job; + + MALI_DEBUG_ASSERT(job_queue_depth > 0); + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); + + if (!mali_pp_job_has_active_barrier(job)) + { + return job; + } + } + + return NULL; +} + +MALI_STATIC_INLINE void mali_pp_scheduler_dequeue_physical_job(struct mali_pp_job *job) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + MALI_DEBUG_ASSERT(job_queue_depth > 0); + + /* Remove job from queue */ + if (!mali_pp_job_has_unstarted_sub_jobs(job)) + { + /* All sub jobs have been started: remove job from queue */ + _mali_osk_list_delinit(&job->list); + } + + --job_queue_depth; +} + +/** + * Returns a virtual job if a virtual job is ready to run (no barrier present) + */ +MALI_STATIC_INLINE struct mali_pp_job *mali_pp_scheduler_get_virtual_job(void) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + MALI_DEBUG_ASSERT_POINTER(virtual_group); + + if (!_mali_osk_list_empty(&virtual_job_queue)) + { + struct mali_pp_job *job; + + MALI_DEBUG_ASSERT(virtual_job_queue_depth > 0); + job = _MALI_OSK_LIST_ENTRY(virtual_job_queue.next, struct mali_pp_job, list); + + if (!mali_pp_job_has_active_barrier(job)) + { + return job; + } + } + + return NULL; +} + +MALI_STATIC_INLINE void mali_pp_scheduler_dequeue_virtual_job(struct mali_pp_job *job) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + MALI_DEBUG_ASSERT(virtual_job_queue_depth > 0); + + /* Remove job from queue */ + _mali_osk_list_delinit(&job->list); + --virtual_job_queue_depth; +} + +/** + * Checks if the criteria is met for removing a physical core from virtual group + */ +MALI_STATIC_INLINE mali_bool mali_pp_scheduler_can_move_virtual_to_physical(void) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + MALI_DEBUG_ASSERT(mali_pp_scheduler_has_virtual_group()); + MALI_ASSERT_GROUP_LOCKED(virtual_group); + /* + * The criteria for taking out a physical group from a virtual group are the following: + * - There virtual group is idle + * - There are currently no physical groups (idle and working) + * - There are physical jobs to be scheduled (without a barrier) + */ + return (VIRTUAL_GROUP_IDLE == virtual_group_state) && + _mali_osk_list_empty(&group_list_idle) && + _mali_osk_list_empty(&group_list_working) && + (NULL != mali_pp_scheduler_get_physical_job()); +} + +MALI_STATIC_INLINE struct mali_group *mali_pp_scheduler_acquire_physical_group(void) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + + if (!_mali_osk_list_empty(&group_list_idle)) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquiring physical group from idle list\n")); + return _MALI_OSK_LIST_ENTRY(group_list_idle.next, struct mali_group, pp_scheduler_list); + } + else if (mali_pp_scheduler_has_virtual_group()) + { + MALI_ASSERT_GROUP_LOCKED(virtual_group); + if (mali_pp_scheduler_can_move_virtual_to_physical()) + { + struct mali_group *group; + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquiring physical group from virtual group\n")); + group = mali_group_acquire_group(virtual_group); + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_pp_scheduler_disable_empty_virtual(); + } + + return group; + } + } + + return NULL; +} + +static void mali_pp_scheduler_schedule(void) +{ + struct mali_group* physical_groups_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS-1]; + struct mali_pp_job* physical_jobs_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS-1]; + u32 physical_subjobs_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS-1]; + int num_physical_jobs_to_start = 0; + int i; + + if (mali_pp_scheduler_has_virtual_group()) + { + /* Need to lock the virtual group because we might need to grab a physical group from it */ + mali_group_lock(virtual_group); + } + + mali_pp_scheduler_lock(); + if (pause_count > 0) + { + /* Scheduler is suspended, don't schedule any jobs */ + mali_pp_scheduler_unlock(); + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_unlock(virtual_group); + } + return; + } + + /* Find physical job(s) to schedule first */ + while (1) + { + struct mali_group *group; + struct mali_pp_job *job; + u32 subjob; + + job = mali_pp_scheduler_get_physical_job(); + if (NULL == job) + { + break; /* No job, early out */ + } + + MALI_DEBUG_ASSERT(!mali_pp_job_is_virtual(job)); + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); + MALI_DEBUG_ASSERT(1 <= mali_pp_job_get_sub_job_count(job)); + + /* Acquire a physical group, either from the idle list or from the virtual group. + * In case the group was acquired from the virtual group, it's state will be + * LEAVING_VIRTUAL and must be set to IDLE before it can be used. */ + group = mali_pp_scheduler_acquire_physical_group(); + if (NULL == group) + { + /* Could not get a group to run the job on, early out */ + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: No more physical groups available.\n")); + break; + } + + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquired physical group %p\n", group)); + + /* Mark subjob as started */ + subjob = mali_pp_job_get_first_unstarted_sub_job(job); + mali_pp_job_mark_sub_job_started(job, subjob); + + /* Remove job from queue (if we now got the last subjob) */ + mali_pp_scheduler_dequeue_physical_job(job); + + /* Move group to working list */ + _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_working); + + /* Keep track of this group, so that we actually can start the job once we are done with the scheduler lock we are now holding */ + physical_groups_to_start[num_physical_jobs_to_start] = group; + physical_jobs_to_start[num_physical_jobs_to_start] = job; + physical_subjobs_to_start[num_physical_jobs_to_start] = subjob; + ++num_physical_jobs_to_start; + + MALI_DEBUG_ASSERT(num_physical_jobs_to_start < MALI_MAX_NUMBER_OF_PP_GROUPS); + } + + /* See if we have a virtual job to schedule */ + if (mali_pp_scheduler_has_virtual_group()) + { + if (VIRTUAL_GROUP_IDLE == virtual_group_state) + { + struct mali_pp_job *job = mali_pp_scheduler_get_virtual_job(); + if (NULL != job) + { + MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job)); + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); + MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job)); + + /* Mark the one and only subjob as started */ + mali_pp_job_mark_sub_job_started(job, 0); + + /* Remove job from queue */ + mali_pp_scheduler_dequeue_virtual_job(job); + + /* Virtual group is now working */ + virtual_group_state = VIRTUAL_GROUP_WORKING; + + /* + * We no longer need the scheduler lock, + * but we still need the virtual lock in order to start the virtual job + */ + mali_pp_scheduler_unlock(); + + /* Start job */ + mali_group_start_pp_job(virtual_group, job, 0); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Virtual job %u (0x%08X) part %u/%u started (from schedule)\n", + mali_pp_job_get_id(job), job, 1, + mali_pp_job_get_sub_job_count(job))); + + /* And now we are all done with the virtual_group lock as well */ + mali_group_unlock(virtual_group); + } + else + { + /* No virtual job, release the two locks we are holding */ + mali_pp_scheduler_unlock(); + mali_group_unlock(virtual_group); + } + } + else + { + /* Virtual core busy, release the two locks we are holding */ + mali_pp_scheduler_unlock(); + mali_group_unlock(virtual_group); + } + + } + else + { + /* There is no virtual group, release the only lock we are holding */ + mali_pp_scheduler_unlock(); + } + + /* + * Now we have released the scheduler lock, and we are ready to kick of the actual starting of the + * physical jobs. + * The reason we want to wait until we have released the scheduler lock is that job start actually + * may take quite a bit of time (quite many registers needs to be written). This will allow new jobs + * from user space to come in, and post processing of other PP jobs to happen at the same time as we + * start jobs. + */ + for (i = 0; i < num_physical_jobs_to_start; i++) + { + struct mali_group *group = physical_groups_to_start[i]; + struct mali_pp_job *job = physical_jobs_to_start[i]; + u32 sub_job = physical_subjobs_to_start[i]; + + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT_POINTER(job); + + mali_group_lock(group); + + /* In case this group was acquired from a virtual core, update it's state to IDLE */ + group->state = MALI_GROUP_STATE_IDLE; + + mali_group_start_pp_job(group, job, sub_job); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from schedule)\n", + mali_pp_job_get_id(job), job, sub_job + 1, + mali_pp_job_get_sub_job_count(job))); + + mali_group_unlock(group); + + /* remove the return value from mali_group_start_xx_job, since we can't fail on Mali-300++ */ + } +} + +static void mali_pp_scheduler_return_job_to_user(struct mali_pp_job *job, mali_bool deferred) +{ + if (MALI_FALSE == mali_pp_job_use_no_notification(job)) + { + u32 i; + u32 num_counters_to_copy; + mali_bool success = mali_pp_job_was_success(job); + + _mali_uk_pp_job_finished_s *jobres = job->finished_notification->result_buffer; + _mali_osk_memset(jobres, 0, sizeof(_mali_uk_pp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ + jobres->user_job_ptr = mali_pp_job_get_user_id(job); + if (MALI_TRUE == success) + { + jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; + } + else + { + jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; + } + + if (mali_pp_job_is_virtual(job)) + { + num_counters_to_copy = num_cores; /* Number of physical cores available */ + } + else + { + num_counters_to_copy = mali_pp_job_get_sub_job_count(job); + } + + for (i = 0; i < num_counters_to_copy; i++) + { + jobres->perf_counter0[i] = mali_pp_job_get_perf_counter_value0(job, i); + jobres->perf_counter1[i] = mali_pp_job_get_perf_counter_value1(job, i); + } + + mali_session_send_notification(mali_pp_job_get_session(job), job->finished_notification); + job->finished_notification = NULL; + } + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + if (MALI_TRUE == deferred) + { + /* The deletion of the job object (releasing sync refs etc) must be done in a different context */ + _mali_osk_lock_wait(pp_scheduler_job_delete_lock, _MALI_OSK_LOCKMODE_RW); + + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->list)); /* This job object should not be on any list */ + _mali_osk_list_addtail(&job->list, &pp_scheduler_job_deletion_queue); + + _mali_osk_lock_signal(pp_scheduler_job_delete_lock, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_wq_schedule_work(pp_scheduler_wq_job_delete); + } + else + { + mali_pp_job_delete(job); + } +#else + MALI_DEBUG_ASSERT(MALI_FALSE == deferred); /* no use cases need this in this configuration */ + mali_pp_job_delete(job); +#endif +} + +static void mali_pp_scheduler_do_schedule(void *arg) +{ + MALI_IGNORE(arg); + + mali_pp_scheduler_schedule(); +} + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) +static void mali_pp_scheduler_do_job_delete(void *arg) +{ + _MALI_OSK_LIST_HEAD_STATIC_INIT(list); + struct mali_pp_job *job; + struct mali_pp_job *tmp; + + MALI_IGNORE(arg); + + _mali_osk_lock_wait(pp_scheduler_job_delete_lock, _MALI_OSK_LOCKMODE_RW); + + /* + * Quickly "unhook" the jobs pending to be deleted, so we can release the lock before + * we start deleting the job objects (without any locks held + */ + _mali_osk_list_move_list(&pp_scheduler_job_deletion_queue, &list); + + _mali_osk_lock_signal(pp_scheduler_job_delete_lock, _MALI_OSK_LOCKMODE_RW); + + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &list, struct mali_pp_job, list) + { + mali_pp_job_delete(job); /* delete the job object itself */ + } +} +#endif + +void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success) +{ + mali_bool job_is_done; + mali_bool barrier_enforced = MALI_FALSE; + + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: %s job %u (0x%08X) part %u/%u completed (%s)\n", + mali_pp_job_is_virtual(job) ? "Virtual" : "Physical", + mali_pp_job_get_id(job), + job, sub_job + 1, + mali_pp_job_get_sub_job_count(job), + success ? "success" : "failure")); + MALI_ASSERT_GROUP_LOCKED(group); + mali_pp_scheduler_lock(); + + mali_pp_job_mark_sub_job_completed(job, success); + + MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job) == mali_group_is_virtual(group)); + + job_is_done = mali_pp_job_is_complete(job); + + if (job_is_done) + { + struct mali_session_data *session = mali_pp_job_get_session(job); + struct mali_pp_job *job_head; + + /* Remove job from session list */ + _mali_osk_list_del(&job->session_list); + + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for %s job %u (0x%08X)\n", + mali_pp_job_is_virtual(job) ? "virtual" : "physical", + mali_pp_job_get_id(job), job)); +#if defined(CONFIG_SYNC) + if (job->sync_point) + { + int error; + if (success) error = 0; + else error = -EFAULT; + MALI_DEBUG_PRINT(4, ("Sync: Signal %spoint for job %d\n", + success ? "" : "failed ", + mali_pp_job_get_id(job))); + mali_sync_signal_pt(job->sync_point, error); + } +#endif + + /* Send notification back to user space */ +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + mali_pp_scheduler_return_job_to_user(job, MALI_TRUE); +#else + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); +#endif + + mali_pp_scheduler_job_completed(); + + /* Resolve any barriers */ + if (!_mali_osk_list_empty(&session->job_list)) + { + job_head = _MALI_OSK_LIST_ENTRY(session->job_list.next, struct mali_pp_job, session_list); + if (mali_pp_job_has_active_barrier(job_head)) + { + barrier_enforced = MALI_TRUE; + mali_pp_job_barrier_enforced(job_head); + } + } + } + + /* If paused, then this was the last job, so wake up sleeping workers */ + if (pause_count > 0) + { + /* Wake up sleeping workers. Their wake-up condition is that + * num_slots == num_slots_idle, so unless we are done working, no + * threads will actually be woken up. + */ + if (mali_group_is_virtual(group)) + { + virtual_group_state = VIRTUAL_GROUP_IDLE; + } + else + { + _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle); + } +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch(mali_pp_get_hw_core_desc(group->pp_core), sched_clock(), 0, 0, 0); +#endif + _mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue); + mali_pp_scheduler_unlock(); + return; + } + + if (barrier_enforced) + { + /* A barrier was resolved, so schedule previously blocked jobs */ + _mali_osk_wq_schedule_work(pp_scheduler_wq_schedule); + } + + /* Recycle variables */ + job = NULL; + sub_job = 0; + + if (mali_group_is_virtual(group)) + { + /* Virtual group */ + + /* Now that the virtual group is idle, check if we should reconfigure */ + struct mali_pp_job *physical_job = NULL; + struct mali_group *physical_group = NULL; + + /* Obey the policy */ + virtual_group_state = VIRTUAL_GROUP_IDLE; + + if (mali_pp_scheduler_can_move_virtual_to_physical()) + { + /* There is a runnable physical job and we can acquire a physical group */ + physical_job = mali_pp_scheduler_get_physical_job(); + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(physical_job)); + + /* Mark subjob as started */ + sub_job = mali_pp_job_get_first_unstarted_sub_job(physical_job); + mali_pp_job_mark_sub_job_started(physical_job, sub_job); + + /* Remove job from queue (if we now got the last subjob) */ + mali_pp_scheduler_dequeue_physical_job(physical_job); + + /* Acquire a physical group from the virtual group + * It's state will be LEAVING_VIRTUAL and must be set to IDLE before it can be used */ + physical_group = mali_group_acquire_group(virtual_group); + + /* Move physical group to the working list, as we will soon start a job on it */ + _mali_osk_list_move(&(physical_group->pp_scheduler_list), &group_list_working); + + mali_pp_scheduler_disable_empty_virtual(); + } + + /* Start the next virtual job */ + job = mali_pp_scheduler_get_virtual_job(); + if (NULL != job && VIRTUAL_GROUP_IDLE == virtual_group_state) + { + /* There is a runnable virtual job */ + MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job)); + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); + MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job)); + + mali_pp_job_mark_sub_job_started(job, 0); + + /* Remove job from queue */ + mali_pp_scheduler_dequeue_virtual_job(job); + + /* Virtual group is now working */ + virtual_group_state = VIRTUAL_GROUP_WORKING; + + mali_pp_scheduler_unlock(); + + /* Start job */ + mali_group_start_pp_job(group, job, 0); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Virtual job %u (0x%08X) part %u/%u started (from job_done)\n", + mali_pp_job_get_id(job), job, 1, + mali_pp_job_get_sub_job_count(job))); + } + else + { +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch("Mali_Virtual_PP", sched_clock(), 0, 0, 0); +#endif + mali_pp_scheduler_unlock(); + } + + /* Start a physical job (if we acquired a physical group earlier) */ + if (NULL != physical_job && NULL != physical_group) + { + mali_group_lock(physical_group); + + /* Set the group state from LEAVING_VIRTUAL to IDLE to complete the transition */ + physical_group->state = MALI_GROUP_STATE_IDLE; + + /* Start job on core */ + mali_group_start_pp_job(physical_group, physical_job, sub_job); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from job_done)\n", + mali_pp_job_get_id(physical_job), physical_job, sub_job + 1, + mali_pp_job_get_sub_job_count(physical_job))); + + mali_group_unlock(physical_group); + } + } + else + { + /* Physical group */ + job = mali_pp_scheduler_get_physical_job(); + if (NULL != job) + { + /* There is a runnable physical job */ + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); + + /* Mark subjob as started */ + sub_job = mali_pp_job_get_first_unstarted_sub_job(job); + mali_pp_job_mark_sub_job_started(job, sub_job); + + /* Remove job from queue (if we now got the last subjob) */ + mali_pp_scheduler_dequeue_physical_job(job); + + mali_pp_scheduler_unlock(); + + /* Group is already on the working list, so start the job */ + mali_group_start_pp_job(group, job, sub_job); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from job_done)\n", + mali_pp_job_get_id(job), job, sub_job + 1, + mali_pp_job_get_sub_job_count(job))); + } + else if (mali_pp_scheduler_has_virtual_group()) + { + /* Rejoin virtual group */ + /* In the future, a policy check might be useful here */ + + /* We're no longer needed on the scheduler list */ + _mali_osk_list_delinit(&(group->pp_scheduler_list)); + + /* Make sure no interrupts are handled for this group during + * the transition from physical to virtual */ + group->state = MALI_GROUP_STATE_JOINING_VIRTUAL; + + mali_pp_scheduler_unlock(); + mali_group_unlock(group); + + mali_group_lock(virtual_group); + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_pp_scheduler_enable_empty_virtual(); + } + + /* We need to recheck the group state since it is possible that someone has + * modified the group before we locked the virtual group. */ + if (MALI_GROUP_STATE_JOINING_VIRTUAL == group->state) + { + mali_group_add_group(virtual_group, group, MALI_TRUE); + } + + mali_group_unlock(virtual_group); + + if (mali_pp_scheduler_has_virtual_group() && VIRTUAL_GROUP_IDLE == virtual_group_state) + { + _mali_osk_wq_schedule_work(pp_scheduler_wq_schedule); + } + + /* We need to return from this function with the group lock held */ + mali_group_lock(group); + } + else + { + _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle); +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch(mali_pp_get_hw_core_desc(group->pp_core), sched_clock(), 0, 0, 0); +#endif + mali_pp_scheduler_unlock(); + } + } +} + +void mali_pp_scheduler_suspend(void) +{ + mali_pp_scheduler_lock(); + pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ + mali_pp_scheduler_unlock(); + + /* Go to sleep. When woken up again (in mali_pp_scheduler_job_done), the + * mali_pp_scheduler_suspended() function will be called. This will return true + * iff state is idle and pause_count > 0, so if the core is active this + * will not do anything. + */ + _mali_osk_wait_queue_wait_event(pp_scheduler_working_wait_queue, mali_pp_scheduler_is_suspended); +} + +void mali_pp_scheduler_resume(void) +{ + mali_pp_scheduler_lock(); + pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */ + mali_pp_scheduler_unlock(); + if (0 == pause_count) + { + mali_pp_scheduler_schedule(); + } +} + +MALI_STATIC_INLINE void mali_pp_scheduler_queue_job(struct mali_pp_job *job, struct mali_session_data *session) +{ + MALI_DEBUG_ASSERT_POINTER(job); + +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_job_enqueue(mali_pp_job_get_tid(job), mali_pp_job_get_id(job), "PP"); +#endif + +#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + /* Map buffers attached to job */ + if (0 != job->num_memory_cookies) + { + mali_dma_buf_map_job(job); + } +#endif /* CONFIG_DMA_SHARED_BUFFER */ + + mali_pp_scheduler_job_queued(); + + mali_pp_scheduler_lock(); + + if (mali_pp_job_is_virtual(job)) + { + /* Virtual job */ + virtual_job_queue_depth += 1; + _mali_osk_list_addtail(&job->list, &virtual_job_queue); + } + else + { + job_queue_depth += mali_pp_job_get_sub_job_count(job); + _mali_osk_list_addtail(&job->list, &job_queue); + } + + if (mali_pp_job_has_active_barrier(job) && _mali_osk_list_empty(&session->job_list)) + { + /* No running jobs on this session, so barrier condition already met */ + mali_pp_job_barrier_enforced(job); + } + + /* Add job to session list */ + _mali_osk_list_addtail(&job->session_list, &session->job_list); + + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: %s job %u (0x%08X) with %u parts queued\n", + mali_pp_job_is_virtual(job) ? "Virtual" : "Physical", + mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job))); + + mali_pp_scheduler_unlock(); +} + +#if defined(CONFIG_SYNC) +static void sync_callback(struct sync_fence *fence, struct sync_fence_waiter *waiter) +{ + struct mali_pp_job *job = _MALI_OSK_CONTAINER_OF(waiter, struct mali_pp_job, sync_waiter); + + /* Schedule sync_callback_work */ + _mali_osk_wq_schedule_work(job->sync_work); +} + +static void sync_callback_work(void *arg) +{ + struct mali_pp_job *job = (struct mali_pp_job *)arg; + struct mali_session_data *session; + int err; + + MALI_DEBUG_ASSERT_POINTER(job); + + session = job->session; + + /* Remove job from session pending job list */ + _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_delinit(&job->list); + _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + + err = sync_fence_wait(job->pre_fence, 0); + if (likely(0 == err)) + { + MALI_DEBUG_PRINT(3, ("Mali sync: Job %d ready to run\n", mali_pp_job_get_id(job))); + + mali_pp_scheduler_queue_job(job, session); + + mali_pp_scheduler_schedule(); + } + else + { + /* Fence signaled error */ + MALI_DEBUG_PRINT(3, ("Mali sync: Job %d abort due to sync error\n", mali_pp_job_get_id(job))); + + if (job->sync_point) mali_sync_signal_pt(job->sync_point, err); + + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + } +} +#endif + +_mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *uargs, int *fence) +{ + struct mali_session_data *session; + struct mali_pp_job *job; + + MALI_DEBUG_ASSERT_POINTER(uargs); + MALI_DEBUG_ASSERT_POINTER(ctx); + + session = (struct mali_session_data*)ctx; + + job = mali_pp_job_create(session, uargs, mali_scheduler_get_new_id()); + if (NULL == job) + { + MALI_PRINT_ERROR(("Failed to create job!\n")); + return _MALI_OSK_ERR_NOMEM; + } + + if (_MALI_OSK_ERR_OK != mali_pp_job_check(job)) + { + /* Not a valid job, return to user immediately */ + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + +#if PROFILING_SKIP_PP_JOBS || PROFILING_SKIP_PP_AND_GP_JOBS +#warning PP jobs will not be executed + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); + return _MALI_OSK_ERR_OK; +#endif + +#if defined(CONFIG_SYNC) + if (_MALI_PP_JOB_FLAG_FENCE & job->uargs.flags) + { + int post_fence = -1; + + job->sync_point = mali_stream_create_point(job->uargs.stream); + + if (unlikely(NULL == job->sync_point)) + { + /* Fence creation failed. */ + MALI_DEBUG_PRINT(2, ("Failed to create sync point for job %d\n", mali_pp_job_get_id(job))); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + + post_fence = mali_stream_create_fence(job->sync_point); + + if (unlikely(0 > post_fence)) + { + /* Fence creation failed. */ + /* mali_stream_create_fence already freed the sync_point */ + MALI_DEBUG_PRINT(2, ("Failed to create fence for job %d\n", mali_pp_job_get_id(job))); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + + /* Grab a reference to the fence. It must be around when the + * job is completed, so the point can be signalled. */ + sync_fence_fdget(post_fence); + + *fence = post_fence; + + MALI_DEBUG_PRINT(3, ("Sync: Created fence %d for job %d\n", post_fence, mali_pp_job_get_id(job))); + } + else if (_MALI_PP_JOB_FLAG_EMPTY_FENCE & job->uargs.flags) + { + int empty_fence_fd = job->uargs.stream; + struct sync_fence *empty_fence; + struct sync_pt *pt; + int ret; + + /* Grab and keep a reference to the fence. It must be around + * when the job is completed, so the point can be signalled. */ + empty_fence = sync_fence_fdget(empty_fence_fd); + + if (unlikely(NULL == empty_fence)) + { + MALI_DEBUG_PRINT_ERROR(("Failed to accept empty fence: %d\n", empty_fence_fd)); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; + } + + if (unlikely(list_empty(&empty_fence->pt_list_head))) + { + MALI_DEBUG_PRINT_ERROR(("Failed to accept empty fence: %d\n", empty_fence_fd)); + sync_fence_put(empty_fence); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; + } + + pt = list_first_entry(&empty_fence->pt_list_head, struct sync_pt, pt_list); + + ret = mali_sync_timed_commit(pt); + + if (unlikely(0 != ret)) + { + MALI_DEBUG_PRINT_ERROR(("Empty fence not valid: %d\n", empty_fence_fd)); + sync_fence_put(empty_fence); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; + } + + job->sync_point = pt; + + *fence = empty_fence_fd; + + MALI_DEBUG_PRINT(3, ("Sync: Job %d now backs fence %d\n", mali_pp_job_get_id(job), empty_fence_fd)); + } + + if (0 < job->uargs.fence) + { + int pre_fence_fd = job->uargs.fence; + int err; + + MALI_DEBUG_PRINT(3, ("Sync: Job %d waiting for fence %d\n", mali_pp_job_get_id(job), pre_fence_fd)); + + job->pre_fence = sync_fence_fdget(pre_fence_fd); /* Reference will be released when job is deleted. */ + if (NULL == job->pre_fence) + { + MALI_DEBUG_PRINT(2, ("Failed to import fence %d\n", pre_fence_fd)); + if (job->sync_point) mali_sync_signal_pt(job->sync_point, -EINVAL); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + + job->sync_work = _mali_osk_wq_create_work(sync_callback_work, (void*)job); + if (NULL == job->sync_work) + { + if (job->sync_point) mali_sync_signal_pt(job->sync_point, -ENOMEM); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + + /* Add pending job to session pending job list */ + _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_addtail(&job->list, &session->pending_jobs); + _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + + sync_fence_waiter_init(&job->sync_waiter, sync_callback); + err = sync_fence_wait_async(job->pre_fence, &job->sync_waiter); + + if (0 != err) + { + /* No async wait started, remove job from session pending job list */ + _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_delinit(&job->list); + _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + } + + if (1 == err) + { + /* Fence has already signalled */ + mali_pp_scheduler_queue_job(job, session); + if (!_mali_osk_list_empty(&group_list_idle) || VIRTUAL_GROUP_IDLE == virtual_group_state) + { + mali_pp_scheduler_schedule(); + } + return _MALI_OSK_ERR_OK; + } + else if (0 > err) + { + /* Sync fail */ + if (job->sync_point) mali_sync_signal_pt(job->sync_point, err); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + + } + else +#endif /* CONFIG_SYNC */ + { + mali_pp_scheduler_queue_job(job, session); + + if (!_mali_osk_list_empty(&group_list_idle) || VIRTUAL_GROUP_IDLE == virtual_group_state) + { + mali_pp_scheduler_schedule(); + } + } + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores(_mali_uk_get_pp_number_of_cores_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); + args->number_of_total_cores = num_cores; + args->number_of_enabled_cores = enabled_cores; + return _MALI_OSK_ERR_OK; +} + +u32 mali_pp_scheduler_get_num_cores_total(void) +{ + return num_cores; +} + +u32 mali_pp_scheduler_get_num_cores_enabled(void) +{ + return enabled_cores; +} + +_mali_osk_errcode_t _mali_ukk_get_pp_core_version(_mali_uk_get_pp_core_version_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); + args->version = pp_version; + return _MALI_OSK_ERR_OK; +} + +void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args) +{ + struct mali_session_data *session; + struct mali_pp_job *job; + struct mali_pp_job *tmp; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); + + session = (struct mali_session_data*)args->ctx; + + /* Check queue for jobs that match */ + mali_pp_scheduler_lock(); + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list) + { + if (mali_pp_job_get_session(job) == session && + mali_pp_job_get_frame_builder_id(job) == (u32)args->fb_id && + mali_pp_job_get_flush_id(job) == (u32)args->flush_id) + { + if (args->wbx & _MALI_UK_PP_JOB_WB0) + { + mali_pp_job_disable_wb0(job); + } + if (args->wbx & _MALI_UK_PP_JOB_WB1) + { + mali_pp_job_disable_wb1(job); + } + if (args->wbx & _MALI_UK_PP_JOB_WB2) + { + mali_pp_job_disable_wb2(job); + } + break; + } + } + mali_pp_scheduler_unlock(); +} + +void mali_pp_scheduler_abort_session(struct mali_session_data *session) +{ + struct mali_pp_job *job, *tmp_job; + struct mali_group *group, *tmp_group; + struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS]; + s32 i = 0; +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + _MALI_OSK_LIST_HEAD_STATIC_INIT(deferred_deletion_list); +#endif + + mali_pp_scheduler_lock(); + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Aborting all jobs from session 0x%08x\n", session)); + + _MALI_OSK_LIST_FOREACHENTRY(job, tmp_job, &session->job_list, struct mali_pp_job, session_list) + { + /* Remove job from queue (if it's not queued, list_del has no effect) */ + _mali_osk_list_delinit(&job->list); + + if (mali_pp_job_is_virtual(job)) + { + MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job)); + if (0 == mali_pp_job_get_first_unstarted_sub_job(job)) + { + --virtual_job_queue_depth; + } + } + else + { + job_queue_depth -= mali_pp_job_get_sub_job_count(job) - mali_pp_job_get_first_unstarted_sub_job(job); + } + + /* Mark all unstarted jobs as failed */ + mali_pp_job_mark_unstarted_failed(job); + + if (mali_pp_job_is_complete(job)) + { + _mali_osk_list_del(&job->session_list); + + /* It is safe to delete the job, since it won't land in job_done() */ + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Aborted PP job 0x%08x\n", job)); + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->list)); + _mali_osk_list_addtail(&job->list, &deferred_deletion_list); +#else + mali_pp_job_delete(job); +#endif + + mali_pp_scheduler_job_completed(); + } + else + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Keeping partially started PP job 0x%08x in session\n", job)); + } + } + + _MALI_OSK_LIST_FOREACHENTRY(group, tmp_group, &group_list_working, struct mali_group, pp_scheduler_list) + { + groups[i++] = group; + } + + _MALI_OSK_LIST_FOREACHENTRY(group, tmp_group, &group_list_idle, struct mali_group, pp_scheduler_list) + { + groups[i++] = group; + } + + mali_pp_scheduler_unlock(); + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + _MALI_OSK_LIST_FOREACHENTRY(job, tmp_job, &deferred_deletion_list, struct mali_pp_job, list) + { + mali_pp_job_delete(job); + } +#endif + + /* Abort running jobs from this session */ + while (i > 0) + { + mali_group_abort_session(groups[--i], session); + } + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_abort_session(virtual_group, session); + } +} + +static mali_bool mali_pp_scheduler_is_suspended(void) +{ + mali_bool ret; + + mali_pp_scheduler_lock(); + + ret = pause_count > 0 + && _mali_osk_list_empty(&group_list_working) + && VIRTUAL_GROUP_WORKING != virtual_group_state; + + mali_pp_scheduler_unlock(); + + return ret; +} + +int mali_pp_scheduler_get_queue_depth(void) +{ + return job_queue_depth; +} + +#if MALI_STATE_TRACKING +u32 mali_pp_scheduler_dump_state(char *buf, u32 size) +{ + int n = 0; + struct mali_group *group; + struct mali_group *temp; + + n += _mali_osk_snprintf(buf + n, size - n, "PP:\n"); + n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty"); + n += _mali_osk_snprintf(buf + n, size - n, "\n"); + + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_working, struct mali_group, pp_scheduler_list) + { + n += mali_group_dump_state(group, buf + n, size - n); + } + + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list) + { + n += mali_group_dump_state(group, buf + n, size - n); + } + + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_disabled, struct mali_group, pp_scheduler_list) + { + n += mali_group_dump_state(group, buf + n, size - n); + } + + if (mali_pp_scheduler_has_virtual_group()) + { + n += mali_group_dump_state(virtual_group, buf + n, size -n); + } + + n += _mali_osk_snprintf(buf + n, size - n, "\n"); + return n; +} +#endif + +/* This function is intended for power on reset of all cores. + * No locking is done for the list iteration, which can only be safe if the + * scheduler is paused and all cores idle. That is always the case on init and + * power on. */ +void mali_pp_scheduler_reset_all_groups(void) +{ + struct mali_group *group, *temp; + struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS]; + s32 i = 0; + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_lock(virtual_group); + mali_group_reset(virtual_group); + mali_group_unlock(virtual_group); + } + + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working)); + MALI_DEBUG_ASSERT(VIRTUAL_GROUP_WORKING != virtual_group_state); + mali_pp_scheduler_lock(); + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list) + { + groups[i++] = group; + } + mali_pp_scheduler_unlock(); + + while (i > 0) + { + group = groups[--i]; + + mali_group_lock(group); + mali_group_reset(group); + mali_group_unlock(group); + } +} + +void mali_pp_scheduler_zap_all_active(struct mali_session_data *session) +{ + struct mali_group *group, *temp; + struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS]; + s32 i = 0; + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_zap_session(virtual_group, session); + } + + mali_pp_scheduler_lock(); + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_working, struct mali_group, pp_scheduler_list) + { + groups[i++] = group; + } + mali_pp_scheduler_unlock(); + + while (i > 0) + { + mali_group_zap_session(groups[--i], session); + } +} + +/* A pm reference must be taken with _mali_osk_pm_dev_ref_add_no_power_on + * before calling this function to avoid Mali powering down as HW is accessed. + */ +static void mali_pp_scheduler_enable_group_internal(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + + mali_group_lock(group); + + if (MALI_GROUP_STATE_DISABLED != group->state) + { + mali_group_unlock(group); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: PP group %p already enabled\n", group)); + return; + } + + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Enabling PP group %p\n", group)); + + mali_pp_scheduler_lock(); + + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state); + ++enabled_cores; + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_bool update_hw; + + /* Add group to virtual group */ + _mali_osk_list_delinit(&(group->pp_scheduler_list)); + group->state = MALI_GROUP_STATE_JOINING_VIRTUAL; + + mali_pp_scheduler_unlock(); + mali_group_unlock(group); + + mali_group_lock(virtual_group); + + update_hw = mali_pm_is_power_on(); + + mali_pm_domain_ref_get(group->pm_domain); + MALI_DEBUG_ASSERT(NULL == group->pm_domain || + MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(group->pm_domain)); + + if (update_hw) + { + mali_group_lock(group); + mali_group_power_on_group(group); + mali_group_reset(group); + mali_group_unlock(group); + } + + mali_pp_scheduler_enable_empty_virtual(); + mali_group_add_group(virtual_group, group, update_hw); + MALI_DEBUG_PRINT(4, ("Done enabling group %p. Added to virtual group.\n", group)); + + mali_group_unlock(virtual_group); + } + else + { + mali_pm_domain_ref_get(group->pm_domain); + MALI_DEBUG_ASSERT(NULL == group->pm_domain || + MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(group->pm_domain)); + + /* Put group on idle list */ + if (mali_pm_is_power_on()) + { + mali_group_power_on_group(group); + mali_group_reset(group); + } + + _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle); + group->state = MALI_GROUP_STATE_IDLE; + + MALI_DEBUG_PRINT(4, ("Done enabling group %p. Now on idle list.\n", group)); + mali_pp_scheduler_unlock(); + mali_group_unlock(group); + } +} + +void mali_pp_scheduler_enable_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + + _mali_osk_pm_dev_ref_add_no_power_on(); + + mali_pp_scheduler_enable_group_internal(group); + + _mali_osk_pm_dev_ref_dec_no_power_on(); + + /* Pick up any jobs that might have been queued if all PP groups were disabled. */ + mali_pp_scheduler_schedule(); +} + +static void mali_pp_scheduler_disable_group_internal(struct mali_group *group) +{ + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_lock(virtual_group); + + MALI_DEBUG_ASSERT(VIRTUAL_GROUP_WORKING != virtual_group_state); + if (MALI_GROUP_STATE_JOINING_VIRTUAL == group->state) + { + /* The group was in the process of being added to the virtual group. We + * only need to change the state to reverse this. */ + group->state = MALI_GROUP_STATE_LEAVING_VIRTUAL; + } + else if (MALI_GROUP_STATE_IN_VIRTUAL == group->state) + { + /* Remove group from virtual group. The state of the group will be + * LEAVING_VIRTUAL and the group will not be on any scheduler list. */ + mali_group_remove_group(virtual_group, group); + + mali_pp_scheduler_disable_empty_virtual(); + } + + mali_group_unlock(virtual_group); + } + + mali_group_lock(group); + mali_pp_scheduler_lock(); + + MALI_DEBUG_ASSERT( MALI_GROUP_STATE_IDLE == group->state + || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state + || MALI_GROUP_STATE_DISABLED == group->state); + + if (MALI_GROUP_STATE_DISABLED == group->state) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: PP group %p already disabled\n", group)); + } + else + { + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Disabling PP group %p\n", group)); + + --enabled_cores; + _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_disabled); + group->state = MALI_GROUP_STATE_DISABLED; + + mali_group_power_off_group(group); + mali_pm_domain_ref_put(group->pm_domain); + } + + mali_pp_scheduler_unlock(); + mali_group_unlock(group); +} + +void mali_pp_scheduler_disable_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + + mali_pp_scheduler_suspend(); + _mali_osk_pm_dev_ref_add_no_power_on(); + + mali_pp_scheduler_disable_group_internal(group); + + _mali_osk_pm_dev_ref_dec_no_power_on(); + mali_pp_scheduler_resume(); +} + + +static void mali_pp_scheduler_notify_core_change(u32 num_cores) +{ + if (!mali_is_mali450()) + { + /* Notify all user space sessions about the change, so number of master tile lists can be adapter */ + struct mali_session_data *session, *tmp; + + mali_session_lock(); + MALI_SESSION_FOREACH(session, tmp, link) + { + _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_NUM_CORE_CHANGE, sizeof(_mali_uk_pp_num_cores_changed_s)); + if (NULL != notobj) + { + _mali_uk_pp_num_cores_changed_s *data = notobj->result_buffer; + data->number_of_enabled_cores = num_cores; + mali_session_send_notification(session, notobj); + } + else + { + MALI_PRINT_ERROR(("Failed to notify user space session about num PP core change\n")); + } + } + mali_session_unlock(); + } +} + +static void mali_pp_scheduler_set_perf_level_mali400(u32 target_core_nr) +{ + struct mali_group *group; + MALI_DEBUG_ASSERT(mali_is_mali400()); + + if (target_core_nr > enabled_cores) + { + MALI_DEBUG_PRINT(2, ("Requesting %d cores: enabling %d cores\n", target_core_nr, target_core_nr - enabled_cores)); + + _mali_osk_pm_dev_ref_add_no_power_on(); + _mali_osk_pm_dev_barrier(); + + while (target_core_nr > enabled_cores) + { + mali_pp_scheduler_lock(); + + MALI_DEBUG_ASSERT(!_mali_osk_list_empty(&group_list_disabled)); + + group = _MALI_OSK_LIST_ENTRY(group_list_disabled.next, struct mali_group, pp_scheduler_list); + + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state); + + mali_pp_scheduler_unlock(); + + mali_pp_scheduler_enable_group_internal(group); + } + + _mali_osk_pm_dev_ref_dec_no_power_on(); + + mali_pp_scheduler_schedule(); + } + else if (target_core_nr < enabled_cores) + { + MALI_DEBUG_PRINT(2, ("Requesting %d cores: disabling %d cores\n", target_core_nr, enabled_cores - target_core_nr)); + + mali_pp_scheduler_suspend(); + + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working)); + + while (target_core_nr < enabled_cores) + { + mali_pp_scheduler_lock(); + + MALI_DEBUG_ASSERT(!_mali_osk_list_empty(&group_list_idle)); + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working)); + + group = _MALI_OSK_LIST_ENTRY(group_list_idle.next, struct mali_group, pp_scheduler_list); + + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT( MALI_GROUP_STATE_IDLE == group->state + || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state + || MALI_GROUP_STATE_DISABLED == group->state); + + mali_pp_scheduler_unlock(); + + mali_pp_scheduler_disable_group_internal(group); + } + + mali_pp_scheduler_resume(); + } + + mali_pp_scheduler_notify_core_change(target_core_nr); +} + +static void mali_pp_scheduler_set_perf_level_mali450(u32 target_core_nr) +{ + struct mali_group *group; + MALI_DEBUG_ASSERT(mali_is_mali450()); + + if (target_core_nr > enabled_cores) + { + /* Enable some cores */ + struct mali_pm_domain *domain; + + MALI_DEBUG_PRINT(2, ("Requesting %d cores: enabling %d cores\n", target_core_nr, target_core_nr - enabled_cores)); + + _mali_osk_pm_dev_ref_add_no_power_on(); + _mali_osk_pm_dev_barrier(); + + domain = mali_pm_domain_get(MALI_PMU_M450_DOM2); + + MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) + { + mali_pp_scheduler_enable_group_internal(group); + if (target_core_nr == enabled_cores) break; + } + + if (target_core_nr > enabled_cores) + { + domain = mali_pm_domain_get(MALI_PMU_M450_DOM3); + MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) + { + mali_pp_scheduler_enable_group_internal(group); + if (target_core_nr == enabled_cores) break; + } + } + + MALI_DEBUG_ASSERT(target_core_nr == enabled_cores); + + _mali_osk_pm_dev_ref_dec_no_power_on(); + + mali_pp_scheduler_schedule(); + } + else if (target_core_nr < enabled_cores) + { + /* Disable some cores */ + struct mali_pm_domain *domain; + + MALI_DEBUG_PRINT(2, ("Requesting %d cores: disabling %d cores\n", target_core_nr, enabled_cores - target_core_nr)); + + mali_pp_scheduler_suspend(); + + domain = mali_pm_domain_get(MALI_PMU_M450_DOM3); + if (NULL != domain) + { + MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) + { + mali_pp_scheduler_disable_group_internal(group); + if (target_core_nr == enabled_cores) break; + } + } + + if (target_core_nr < enabled_cores) + { + domain = mali_pm_domain_get(MALI_PMU_M450_DOM2); + MALI_DEBUG_ASSERT_POINTER(domain); + MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) + { + mali_pp_scheduler_disable_group_internal(group); + if (target_core_nr == enabled_cores) break; + } + } + + MALI_DEBUG_ASSERT(target_core_nr == enabled_cores); + + mali_pp_scheduler_resume(); + } +} + +int mali_pp_scheduler_set_perf_level(unsigned int cores) +{ + if (cores == enabled_cores) return 0; + if (cores > num_cores) return -EINVAL; + if (0 == cores) return -EINVAL; + + if (!mali_pp_scheduler_has_virtual_group()) + { + /* Mali-400 */ + mali_pp_scheduler_set_perf_level_mali400(cores); + } + else + { + /* Mali-450 */ + mali_pp_scheduler_set_perf_level_mali450(cores); + } + + return 0; +} + +static void mali_pp_scheduler_job_queued(void) +{ + /* We hold a PM reference for every job we hold queued (and running) */ + _mali_osk_pm_dev_ref_add(); + + if (mali_utilization_enabled()) + { + /* + * We cheat a little bit by counting the PP as busy from the time a PP job is queued. + * This will be fine because we only loose the tiny idle gap between jobs, but + * we will instead get less utilization work to do (less locks taken) + */ + mali_utilization_pp_start(); + } +} + +static void mali_pp_scheduler_job_completed(void) +{ + /* Release the PM reference we got in the mali_pp_scheduler_job_queued() function */ + _mali_osk_pm_dev_ref_dec(); + + if (mali_utilization_enabled()) + { + mali_utilization_pp_end(); + } +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.h new file mode 100644 index 0000000..71ec042 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PP_SCHEDULER_H__ +#define __MALI_PP_SCHEDULER_H__ + +#include "mali_osk.h" +#include "mali_pp_job.h" +#include "mali_group.h" +#include "linux/mali/mali_utgard.h" + +/** Initalize the HW independent parts of the PP scheduler + */ +_mali_osk_errcode_t mali_pp_scheduler_initialize(void); +void mali_pp_scheduler_terminate(void); + +/** Poplulate the PP scheduler with groups + */ +void mali_pp_scheduler_populate(void); +void mali_pp_scheduler_depopulate(void); + +void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success); + +void mali_pp_scheduler_suspend(void); +void mali_pp_scheduler_resume(void); + +/** @brief Abort all PP jobs from session running or queued + * + * This functions aborts all PP jobs from the specified session. Queued jobs are removed from the queue and jobs + * currently running on a core will be aborted. + * + * @param session Pointer to session whose jobs should be aborted + */ +void mali_pp_scheduler_abort_session(struct mali_session_data *session); + +/** + * @brief Reset all groups + * + * This function resets all groups known by the PP scheuduler. This must be + * called after the Mali HW has been powered on in order to reset the HW. + * + * This function is intended for power on reset of all cores. + * No locking is done, which can only be safe if the scheduler is paused and + * all cores idle. That is always the case on init and power on. + */ +void mali_pp_scheduler_reset_all_groups(void); + +/** + * @brief Zap TLB on all groups with \a session active + * + * The scheculer will zap the session on all groups it owns. + */ +void mali_pp_scheduler_zap_all_active(struct mali_session_data *session); + +int mali_pp_scheduler_get_queue_depth(void); +u32 mali_pp_scheduler_dump_state(char *buf, u32 size); + +void mali_pp_scheduler_enable_group(struct mali_group *group); +void mali_pp_scheduler_disable_group(struct mali_group *group); + +int mali_pp_scheduler_set_perf_level(u32 cores); + +u32 mali_pp_scheduler_get_num_cores_total(void); +u32 mali_pp_scheduler_get_num_cores_enabled(void); + +/** + * @brief Returns the number of Pixel Processors in the system irrespective of the context + * + * @return number of physical Pixel Processor cores in the system + */ +u32 mali_pp_scheduler_get_num_cores_total(void); + +#endif /* __MALI_PP_SCHEDULER_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.c b/drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.c new file mode 100644 index 0000000..f360209 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" + +static _mali_osk_atomic_t mali_job_autonumber; + +_mali_osk_errcode_t mali_scheduler_initialize(void) +{ + if ( _MALI_OSK_ERR_OK != _mali_osk_atomic_init(&mali_job_autonumber, 0)) + { + MALI_DEBUG_PRINT(1, ("Initialization of atomic job id counter failed.\n")); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; +} + +void mali_scheduler_terminate(void) +{ + _mali_osk_atomic_term(&mali_job_autonumber); +} + +u32 mali_scheduler_get_new_id(void) +{ + u32 job_id = _mali_osk_atomic_inc_return(&mali_job_autonumber); + return job_id; +} + diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.h b/drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.h new file mode 100644 index 0000000..63e5be8 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_SCHEDULER_H__ +#define __MALI_SCHEDULER_H__ + +#include "mali_osk.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" + +_mali_osk_errcode_t mali_scheduler_initialize(void); +void mali_scheduler_terminate(void); + +u32 mali_scheduler_get_new_id(void); + +/** + * @brief Reset all groups + * + * This function resets all groups known by the both the PP and GP scheuduler. + * This must be called after the Mali HW has been powered on in order to reset + * the HW. + */ +MALI_STATIC_INLINE void mali_scheduler_reset_all_groups(void) +{ + mali_gp_scheduler_reset_all_groups(); + mali_pp_scheduler_reset_all_groups(); +} + +/** + * @brief Zap TLB on all active groups running \a session + * + * @param session Pointer to the session to zap + */ +MALI_STATIC_INLINE void mali_scheduler_zap_all_active(struct mali_session_data *session) +{ + mali_gp_scheduler_zap_all_active(session); + mali_pp_scheduler_zap_all_active(session); +} + +#endif /* __MALI_SCHEDULER_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_session.c b/drivers/gpu/mali400/r3p2/mali/common/mali_session.c new file mode 100644 index 0000000..2394bb9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_session.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_session.h" + +_MALI_OSK_LIST_HEAD(mali_sessions); + +_mali_osk_lock_t *mali_sessions_lock; + +_mali_osk_errcode_t mali_session_initialize(void) +{ + _MALI_OSK_INIT_LIST_HEAD(&mali_sessions); + + mali_sessions_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_SESSIONS); + + if (NULL == mali_sessions_lock) return _MALI_OSK_ERR_NOMEM; + + return _MALI_OSK_ERR_OK; +} + +void mali_session_terminate(void) +{ + _mali_osk_lock_term(mali_sessions_lock); +} + +void mali_session_add(struct mali_session_data *session) +{ + mali_session_lock(); + _mali_osk_list_add(&session->link, &mali_sessions); + mali_session_unlock(); +} + +void mali_session_remove(struct mali_session_data *session) +{ + mali_session_lock(); + _mali_osk_list_delinit(&session->link); + mali_session_unlock(); +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_session.h b/drivers/gpu/mali400/r3p2/mali/common/mali_session.h new file mode 100644 index 0000000..5c34dde --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_session.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_SESSION_H__ +#define __MALI_SESSION_H__ + +#include "mali_mmu_page_directory.h" +#include "mali_kernel_descriptor_mapping.h" +#include "mali_osk.h" +#include "mali_osk_list.h" + +struct mali_session_data +{ + _mali_osk_notification_queue_t * ioctl_queue; + +#ifdef CONFIG_SYNC + _mali_osk_list_t pending_jobs; + _mali_osk_lock_t *pending_jobs_lock; +#endif + + _mali_osk_lock_t *memory_lock; /**< Lock protecting the vm manipulation */ + mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */ + _mali_osk_list_t memory_head; /**< Track all the memory allocated in this session, for freeing on abnormal termination */ + + struct mali_page_directory *page_directory; /**< MMU page directory for this session */ + + _MALI_OSK_LIST_HEAD(link); /**< Link for list of all sessions */ + + _MALI_OSK_LIST_HEAD(job_list); /**< List of all jobs on this session */ +}; + +_mali_osk_errcode_t mali_session_initialize(void); +void mali_session_terminate(void); + +/* List of all sessions. Actual list head in mali_kernel_core.c */ +extern _mali_osk_list_t mali_sessions; +/* Lock to protect modification and access to the mali_sessions list */ +extern _mali_osk_lock_t *mali_sessions_lock; + +MALI_STATIC_INLINE void mali_session_lock(void) +{ + _mali_osk_lock_wait(mali_sessions_lock, _MALI_OSK_LOCKMODE_RW); +} + +MALI_STATIC_INLINE void mali_session_unlock(void) +{ + _mali_osk_lock_signal(mali_sessions_lock, _MALI_OSK_LOCKMODE_RW); +} + +void mali_session_add(struct mali_session_data *session); +void mali_session_remove(struct mali_session_data *session); +#define MALI_SESSION_FOREACH(session, tmp, link) \ + _MALI_OSK_LIST_FOREACHENTRY(session, tmp, &mali_sessions, struct mali_session_data, link) + +MALI_STATIC_INLINE struct mali_page_directory *mali_session_get_page_directory(struct mali_session_data *session) +{ + return session->page_directory; +} + +MALI_STATIC_INLINE void mali_session_send_notification(struct mali_session_data *session, _mali_osk_notification_t *object) +{ + _mali_osk_notification_queue_send(session->ioctl_queue, object); +} + +#endif /* __MALI_SESSION_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_ukk.h b/drivers/gpu/mali400/r3p2/mali/common/mali_ukk.h new file mode 100644 index 0000000..1f8a320 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_ukk.h @@ -0,0 +1,626 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_ukk.h + * Defines the kernel-side interface of the user-kernel interface + */ + +#ifndef __MALI_UKK_H__ +#define __MALI_UKK_H__ + +#include "mali_osk.h" +#include "mali_uk_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @addtogroup uddapi Unified Device Driver (UDD) APIs + * + * @{ + */ + +/** + * @addtogroup u_k_api UDD User/Kernel Interface (U/K) APIs + * + * - The _mali_uk functions are an abstraction of the interface to the device + * driver. On certain OSs, this would be implemented via the IOCTL interface. + * On other OSs, it could be via extension of some Device Driver Class, or + * direct function call for Bare metal/RTOSs. + * - It is important to note that: + * - The Device Driver has implemented the _mali_ukk set of functions + * - The Base Driver calls the corresponding set of _mali_uku functions. + * - What requires porting is solely the calling mechanism from User-side to + * Kernel-side, and propagating back the results. + * - Each U/K function is associated with a (group, number) pair from + * \ref _mali_uk_functions to make it possible for a common function in the + * Base Driver and Device Driver to route User/Kernel calls from/to the + * correct _mali_uk function. For example, in an IOCTL system, the IOCTL number + * would be formed based on the group and number assigned to the _mali_uk + * function, as listed in \ref _mali_uk_functions. On the user-side, each + * _mali_uku function would just make an IOCTL with the IOCTL-code being an + * encoded form of the (group, number) pair. On the kernel-side, the Device + * Driver's IOCTL handler decodes the IOCTL-code back into a (group, number) + * pair, and uses this to determine which corresponding _mali_ukk should be + * called. + * - Refer to \ref _mali_uk_functions for more information about this + * (group, number) pairing. + * - In a system where there is no distinction between user and kernel-side, + * the U/K interface may be implemented as:@code + * MALI_STATIC_INLINE _mali_osk_errcode_t _mali_uku_examplefunction( _mali_uk_examplefunction_s *args ) + * { + * return mali_ukk_examplefunction( args ); + * } + * @endcode + * - Therefore, all U/K calls behave \em as \em though they were direct + * function calls (but the \b implementation \em need \em not be a direct + * function calls) + * + * @note Naming the _mali_uk functions the same on both User and Kernel sides + * on non-RTOS systems causes debugging issues when setting breakpoints. In + * this case, it is not clear which function the breakpoint is put on. + * Therefore the _mali_uk functions in user space are prefixed with \c _mali_uku + * and in kernel space with \c _mali_ukk. The naming for the argument + * structures is unaffected. + * + * - The _mali_uk functions are synchronous. + * - Arguments to the _mali_uk functions are passed in a structure. The only + * parameter passed to the _mali_uk functions is a pointer to this structure. + * This first member of this structure, ctx, is a pointer to a context returned + * by _mali_uku_open(). For example:@code + * typedef struct + * { + * void *ctx; + * u32 number_of_cores; + * } _mali_uk_get_gp_number_of_cores_s; + * @endcode + * + * - Each _mali_uk function has its own argument structure named after the + * function. The argument is distinguished by the _s suffix. + * - The argument types are defined by the base driver and user-kernel + * interface. + * - All _mali_uk functions return a standard \ref _mali_osk_errcode_t. + * - Only arguments of type input or input/output need be initialized before + * calling a _mali_uk function. + * - Arguments of type output and input/output are only valid when the + * _mali_uk function returns \ref _MALI_OSK_ERR_OK. + * - The \c ctx member is always invalid after it has been used by a + * _mali_uk function, except for the context management functions + * + * + * \b Interface \b restrictions + * + * The requirements of the interface mean that an implementation of the + * User-kernel interface may do no 'real' work. For example, the following are + * illegal in the User-kernel implementation: + * - Calling functions necessary for operation on all systems, which would + * not otherwise get called on RTOS systems. + * - For example, a U/K interface that calls multiple _mali_ukk functions + * during one particular U/K call. This could not be achieved by the same code + * which uses direct function calls for the U/K interface. + * - Writing in values to the args members, when otherwise these members would + * not hold a useful value for a direct function call U/K interface. + * - For example, U/K interface implementation that take NULL members in + * their arguments structure from the user side, but those members are + * replaced with non-NULL values in the kernel-side of the U/K interface + * implementation. A scratch area for writing data is one such example. In this + * case, a direct function call U/K interface would segfault, because no code + * would be present to replace the NULL pointer with a meaningful pointer. + * - Note that we discourage the case where the U/K implementation changes + * a NULL argument member to non-NULL, and then the Device Driver code (outside + * of the U/K layer) re-checks this member for NULL, and corrects it when + * necessary. Whilst such code works even on direct function call U/K + * intefaces, it reduces the testing coverage of the Device Driver code. This + * is because we have no way of testing the NULL == value path on an OS + * implementation. + * + * A number of allowable examples exist where U/K interfaces do 'real' work: + * - The 'pointer switching' technique for \ref _mali_ukk_get_system_info + * - In this case, without the pointer switching on direct function call + * U/K interface, the Device Driver code still sees the same thing: a pointer + * to which it can write memory. This is because such a system has no + * distinction between a user and kernel pointer. + * - Writing an OS-specific value into the ukk_private member for + * _mali_ukk_mem_mmap(). + * - In this case, this value is passed around by Device Driver code, but + * its actual value is never checked. Device Driver code simply passes it from + * the U/K layer to the OSK layer, where it can be acted upon. In this case, + * \em some OS implementations of the U/K (_mali_ukk_mem_mmap()) and OSK + * (_mali_osk_mem_mapregion_init()) functions will collaborate on the + * meaning of ukk_private member. On other OSs, it may be unused by both + * U/K and OSK layers + * - Therefore, on error inside the U/K interface implementation itself, + * it will be as though the _mali_ukk function itself had failed, and cleaned + * up after itself. + * - Compare this to a direct function call U/K implementation, where all + * error cleanup is handled by the _mali_ukk function itself. The direct + * function call U/K interface implementation is automatically atomic. + * + * The last example highlights a consequence of all U/K interface + * implementations: they must be atomic with respect to the Device Driver code. + * And therefore, should Device Driver code succeed but the U/K implementation + * fail afterwards (but before return to user-space), then the U/K + * implementation must cause appropriate cleanup actions to preserve the + * atomicity of the interface. + * + * @{ + */ + + +/** @defgroup _mali_uk_context U/K Context management + * + * These functions allow for initialisation of the user-kernel interface once per process. + * + * Generally the context will store the OS specific object to communicate with the kernel device driver and further + * state information required by the specific implementation. The context is shareable among all threads in the caller process. + * + * On IOCTL systems, this is likely to be a file descriptor as a result of opening the kernel device driver. + * + * On a bare-metal/RTOS system with no distinction between kernel and + * user-space, the U/K interface simply calls the _mali_ukk variant of the + * function by direct function call. In this case, the context returned is the + * mali_session_data from _mali_ukk_open(). + * + * The kernel side implementations of the U/K interface expect the first member of the argument structure to + * be the context created by _mali_uku_open(). On some OS implementations, the meaning of this context + * will be different between user-side and kernel-side. In which case, the kernel-side will need to replace this context + * with the kernel-side equivalent, because user-side will not have access to kernel-side data. The context parameter + * in the argument structure therefore has to be of type input/output. + * + * It should be noted that the caller cannot reuse the \c ctx member of U/K + * argument structure after a U/K call, because it may be overwritten. Instead, + * the context handle must always be stored elsewhere, and copied into + * the appropriate U/K argument structure for each user-side call to + * the U/K interface. This is not usually a problem, since U/K argument + * structures are usually placed on the stack. + * + * @{ */ + +/** @brief Begin a new Mali Device Driver session + * + * This is used to obtain a per-process context handle for all future U/K calls. + * + * @param context pointer to storage to return a (void*)context handle. + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_open( void **context ); + +/** @brief End a Mali Device Driver session + * + * This should be called when the process no longer requires use of the Mali Device Driver. + * + * The context handle must not be used after it has been closed. + * + * @param context pointer to a stored (void*)context handle. + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_close( void **context ); + +/** @} */ /* end group _mali_uk_context */ + + +/** @addtogroup _mali_uk_core U/K Core + * + * The core functions provide the following functionality: + * - verify that the user and kernel API are compatible + * - retrieve information about the cores and memory banks in the system + * - wait for the result of jobs started on a core + * + * @{ */ + +/** @brief Waits for a job notification. + * + * Sleeps until notified or a timeout occurs. Returns information about the notification. + * + * @param args see _mali_uk_wait_for_notification_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args ); + +/** @brief Post a notification to the notification queue of this application. + * + * @param args see _mali_uk_post_notification_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args ); + +/** @brief Verifies if the user and kernel side of this API are compatible. + * + * @param args see _mali_uk_get_api_version_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args ); + +/** @brief Get the user space settings applicable for calling process. + * + * @param args see _mali_uk_get_user_settings_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args); + +/** @brief Get a user space setting applicable for calling process. + * + * @param args see _mali_uk_get_user_setting_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args); + +/** @} */ /* end group _mali_uk_core */ + + +/** @addtogroup _mali_uk_memory U/K Memory + * + * The memory functions provide functionality with and without a Mali-MMU present. + * + * For Mali-MMU based systems, the following functionality is provided: + * - Initialize and terminate MALI virtual address space + * - Allocate/deallocate physical memory to a MALI virtual address range and map into/unmap from the + * current process address space + * - Map/unmap external physical memory into the MALI virtual address range + * + * For Mali-nonMMU based systems: + * - Allocate/deallocate MALI memory + * + * @{ */ + +/** + * @brief Initialize the Mali-MMU Memory system + * + * For Mali-MMU builds of the drivers, this function must be called before any + * other functions in the \ref _mali_uk_memory group are called. + * + * @note This function is for Mali-MMU builds \b only. It should not be called + * when the drivers are built without Mali-MMU support. + * + * @param args see \ref _mali_uk_init_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable + * _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args ); + +/** + * @brief Terminate the MMU Memory system + * + * For Mali-MMU builds of the drivers, this function must be called when + * functions in the \ref _mali_uk_memory group will no longer be called. This + * function must be called before the application terminates. + * + * @note This function is for Mali-MMU builds \b only. It should not be called + * when the drivers are built without Mali-MMU support. + * + * @param args see \ref _mali_uk_term_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable + * _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args ); + +/** @brief Map Mali Memory into the current user process + * + * Maps Mali memory into the current user process in a generic way. + * + * This function is to be used for Mali-MMU mode. The function is available in both Mali-MMU and Mali-nonMMU modes, + * but should not be called by a user process in Mali-nonMMU mode. + * + * The implementation and operation of _mali_ukk_mem_mmap() is dependant on whether the driver is built for Mali-MMU + * or Mali-nonMMU: + * - In the nonMMU case, _mali_ukk_mem_mmap() requires a physical address to be specified. For this reason, an OS U/K + * implementation should not allow this to be called from user-space. In any case, nonMMU implementations are + * inherently insecure, and so the overall impact is minimal. Mali-MMU mode should be used if security is desired. + * - In the MMU case, _mali_ukk_mem_mmap() the _mali_uk_mem_mmap_s::phys_addr + * member is used for the \em Mali-virtual address desired for the mapping. The + * implementation of _mali_ukk_mem_mmap() will allocate both the CPU-virtual + * and CPU-physical addresses, and can cope with mapping a contiguous virtual + * address range to a sequence of non-contiguous physical pages. In this case, + * the CPU-physical addresses are not communicated back to the user-side, as + * they are unnecsessary; the \em Mali-virtual address range must be used for + * programming Mali structures. + * + * In the second (MMU) case, _mali_ukk_mem_mmap() handles management of + * CPU-virtual and CPU-physical ranges, but the \em caller must manage the + * \em Mali-virtual address range from the user-side. + * + * @note Mali-virtual address ranges are entirely separate between processes. + * It is not possible for a process to accidentally corrupt another process' + * \em Mali-virtual address space. + * + * @param args see _mali_uk_mem_mmap_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args ); + +/** @brief Unmap Mali Memory from the current user process + * + * Unmaps Mali memory from the current user process in a generic way. This only operates on Mali memory supplied + * from _mali_ukk_mem_mmap(). + * + * @param args see _mali_uk_mem_munmap_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args ); + +/** @brief Determine the buffer size necessary for an MMU page table dump. + * @param args see _mali_uk_query_mmu_page_table_dump_size_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args ); +/** @brief Dump MMU Page tables. + * @param args see _mali_uk_dump_mmu_page_table_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args ); + +/** @brief Write user data to specified Mali memory without causing segfaults. + * @param args see _mali_uk_mem_write_safe_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_mem_write_safe( _mali_uk_mem_write_safe_s *args ); + +/** @brief Map a physically contiguous range of memory into Mali + * @param args see _mali_uk_map_external_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args ); + +/** @brief Unmap a physically contiguous range of memory from Mali + * @param args see _mali_uk_unmap_external_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args ); + +#if defined(CONFIG_MALI400_UMP) +/** @brief Map UMP memory into Mali + * @param args see _mali_uk_attach_ump_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args ); +/** @brief Unmap UMP memory from Mali + * @param args see _mali_uk_release_ump_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args ); +#endif /* CONFIG_MALI400_UMP */ + +/** @brief Determine virtual-to-physical mapping of a contiguous memory range + * (optional) + * + * This allows the user-side to do a virtual-to-physical address translation. + * In conjunction with _mali_uku_map_external_mem, this can be used to do + * direct rendering. + * + * This function will only succeed on a virtual range that is mapped into the + * current process, and that is contigious. + * + * If va is not page-aligned, then it is rounded down to the next page + * boundary. The remainer is added to size, such that ((u32)va)+size before + * rounding is equal to ((u32)va)+size after rounding. The rounded modified + * va and size will be written out into args on success. + * + * If the supplied size is zero, or not a multiple of the system's PAGE_SIZE, + * then size will be rounded up to the next multiple of PAGE_SIZE before + * translation occurs. The rounded up size will be written out into args on + * success. + * + * On most OSs, virtual-to-physical address translation is a priveledged + * function. Therefore, the implementer must validate the range supplied, to + * ensure they are not providing arbitrary virtual-to-physical address + * translations. While it is unlikely such a mechanism could be used to + * compromise the security of a system on its own, it is possible it could be + * combined with another small security risk to cause a much larger security + * risk. + * + * @note This is an optional part of the interface, and is only used by certain + * implementations of libEGL. If the platform layer in your libEGL + * implementation does not require Virtual-to-Physical address translation, + * then this function need not be implemented. A stub implementation should not + * be required either, as it would only be removed by the compiler's dead code + * elimination. + * + * @note if implemented, this function is entirely platform-dependant, and does + * not exist in common code. + * + * @param args see _mali_uk_va_to_mali_pa_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args ); + +/** @} */ /* end group _mali_uk_memory */ + + +/** @addtogroup _mali_uk_pp U/K Fragment Processor + * + * The Fragment Processor (aka PP (Pixel Processor)) functions provide the following functionality: + * - retrieving version of the fragment processors + * - determine number of fragment processors + * - starting a job on a fragment processor + * + * @{ */ + +/** @brief Issue a request to start a new job on a Fragment Processor. + * + * If the request fails args->status is set to _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE and you can + * try to start the job again. + * + * An existing job could be returned for requeueing if the new job has a higher priority than a previously started job + * which the hardware hasn't actually started processing yet. In this case the new job will be started instead and the + * existing one returned, otherwise the new job is started and the status field args->status is set to + * _MALI_UK_START_JOB_STARTED. + * + * Job completion can be awaited with _mali_ukk_wait_for_notification(). + * + * @oaram ctx user-kernel context (mali_session) + * @param uargs see _mali_uk_pp_start_job_s in "mali_utgard_uk_types.h". Use _mali_osk_copy_from_user to retrieve data! + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_pp_start_job( void *ctx, _mali_uk_pp_start_job_s *uargs, int *fence ); + +/** @brief Returns the number of Fragment Processors in the system + * + * @param args see _mali_uk_get_pp_number_of_cores_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores( _mali_uk_get_pp_number_of_cores_s *args ); + +/** @brief Returns the version that all Fragment Processor cores are compatible with. + * + * This function may only be called when _mali_ukk_get_pp_number_of_cores() indicated at least one Fragment + * Processor core is available. + * + * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_get_pp_core_version( _mali_uk_get_pp_core_version_s *args ); + +/** @brief Disable Write-back unit(s) on specified job + * + * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h" + */ +void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args); + + +/** @} */ /* end group _mali_uk_pp */ + + +/** @addtogroup _mali_uk_gp U/K Vertex Processor + * + * The Vertex Processor (aka GP (Geometry Processor)) functions provide the following functionality: + * - retrieving version of the Vertex Processors + * - determine number of Vertex Processors available + * - starting a job on a Vertex Processor + * + * @{ */ + +/** @brief Issue a request to start a new job on a Vertex Processor. + * + * If the request fails args->status is set to _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE and you can + * try to start the job again. + * + * An existing job could be returned for requeueing if the new job has a higher priority than a previously started job + * which the hardware hasn't actually started processing yet. In this case the new job will be started and the + * existing one returned, otherwise the new job is started and the status field args->status is set to + * _MALI_UK_START_JOB_STARTED. + * + * Job completion can be awaited with _mali_ukk_wait_for_notification(). + * + * @oaram ctx user-kernel context (mali_session) + * @param uargs see _mali_uk_gp_start_job_s in "mali_utgard_uk_types.h". Use _mali_osk_copy_from_user to retrieve data! + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_gp_start_job( void *ctx, _mali_uk_gp_start_job_s *uargs ); + +/** @brief Returns the number of Vertex Processors in the system. + * + * @param args see _mali_uk_get_gp_number_of_cores_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores( _mali_uk_get_gp_number_of_cores_s *args ); + +/** @brief Returns the version that all Vertex Processor cores are compatible with. + * + * This function may only be called when _mali_uk_get_gp_number_of_cores() indicated at least one Vertex + * Processor core is available. + * + * @param args see _mali_uk_get_gp_core_version_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_get_gp_core_version( _mali_uk_get_gp_core_version_s *args ); + +/** @brief Resume or abort suspended Vertex Processor jobs. + * + * After receiving notification that a Vertex Processor job was suspended from + * _mali_ukk_wait_for_notification() you can use this function to resume or abort the job. + * + * @param args see _mali_uk_gp_suspend_response_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_gp_suspend_response( _mali_uk_gp_suspend_response_s *args ); + +/** @} */ /* end group _mali_uk_gp */ + +#if defined(CONFIG_MALI400_PROFILING) +/** @addtogroup _mali_uk_profiling U/K Timeline profiling module + * @{ */ + +/** @brief Start recording profiling events. + * + * @param args see _mali_uk_profiling_start_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args); + +/** @brief Add event to profiling buffer. + * + * @param args see _mali_uk_profiling_add_event_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args); + +/** @brief Stop recording profiling events. + * + * @param args see _mali_uk_profiling_stop_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args); + +/** @brief Retrieve a recorded profiling event. + * + * @param args see _mali_uk_profiling_get_event_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args); + +/** @brief Clear recorded profiling events. + * + * @param args see _mali_uk_profiling_clear_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args); + +/** @} */ /* end group _mali_uk_profiling */ +#endif + +/** @addtogroup _mali_uk_vsync U/K VSYNC reporting module + * @{ */ + +/** @brief Report events related to vsync. + * + * @note Events should be reported when starting to wait for vsync and when the + * waiting is finished. This information can then be used in kernel space to + * complement the GPU utilization metric. + * + * @param args see _mali_uk_vsync_event_report_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args); + +/** @} */ /* end group _mali_uk_vsync */ + +/** @addtogroup _mali_sw_counters_report U/K Software counter reporting + * @{ */ + +/** @brief Report software counters. + * + * @param args see _mali_uk_sw_counters_report_s in "mali_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args); + +/** @} */ /* end group _mali_sw_counters_report */ + +/** @} */ /* end group u_k_api */ + +/** @} */ /* end group uddapi */ + +u32 _mali_ukk_report_memory_usage(void); + +u32 _mali_ukk_utilization_gp_pp(void); + +u32 _mali_ukk_utilization_gp(void); + +u32 _mali_ukk_utilization_pp(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_UKK_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.c b/drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.c new file mode 100644 index 0000000..8720b9a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.c @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_uk_types.h" +#include "mali_user_settings_db.h" +#include "mali_session.h" + +static u32 mali_user_settings[_MALI_UK_USER_SETTING_MAX]; +const char *_mali_uk_user_setting_descriptions[] = _MALI_UK_USER_SETTING_DESCRIPTIONS; + +static void mali_user_settings_notify(_mali_uk_user_setting_t setting, u32 value) +{ + struct mali_session_data *session, *tmp; + + mali_session_lock(); + MALI_SESSION_FOREACH(session, tmp, link) + { + _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_SETTINGS_CHANGED, sizeof(_mali_uk_settings_changed_s)); + _mali_uk_settings_changed_s *data = notobj->result_buffer; + data->setting = setting; + data->value = value; + + mali_session_send_notification(session, notobj); + } + mali_session_unlock(); +} + +void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value) +{ + mali_bool notify = MALI_FALSE; + + if (setting >= _MALI_UK_USER_SETTING_MAX || setting < 0) + { + MALI_DEBUG_PRINT_ERROR(("Invalid user setting %ud\n")); + return; + } + + if (mali_user_settings[setting] != value) + { + notify = MALI_TRUE; + } + + mali_user_settings[setting] = value; + + if (notify) + { + mali_user_settings_notify(setting, value); + } +} + +u32 mali_get_user_setting(_mali_uk_user_setting_t setting) +{ + if (setting >= _MALI_UK_USER_SETTING_MAX || setting < 0) + { + return 0; + } + + return mali_user_settings[setting]; +} + +_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args) +{ + _mali_uk_user_setting_t setting; + MALI_DEBUG_ASSERT_POINTER(args); + + setting = args->setting; + + if (0 <= setting && _MALI_UK_USER_SETTING_MAX > setting) + { + args->value = mali_user_settings[setting]; + return _MALI_OSK_ERR_OK; + } + else + { + return _MALI_OSK_ERR_INVALID_ARGS; + } +} + +_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + + _mali_osk_memcpy(args->settings, mali_user_settings, sizeof(mali_user_settings)); + + return _MALI_OSK_ERR_OK; +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.h b/drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.h new file mode 100644 index 0000000..fbb9415 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.h @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_USER_SETTINGS_DB_H__ +#define __MALI_USER_SETTINGS_DB_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mali_uk_types.h" + +/** @brief Set Mali user setting in DB + * + * Update the DB with a new value for \a setting. If the value is different from theprevious set value running sessions will be notified of the change. + * + * @param setting the setting to be changed + * @param value the new value to set + */ +void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value); + +/** @brief Get current Mali user setting value from DB + * + * @param setting the setting to extract + * @return the value of the selected setting + */ +u32 mali_get_user_setting(_mali_uk_user_setting_t setting); + +#ifdef __cplusplus +} +#endif +#endif /* __MALI_KERNEL_USER_SETTING__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard.h new file mode 100644 index 0000000..cf3374a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard.h @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_utgard.h + * Defines types and interface exposed by the Mali Utgard device driver + */ + +#ifndef __MALI_UTGARD_H__ +#define __MALI_UTGARD_H__ + +#define MALI_GPU_NAME_UTGARD "mali-utgard" + +/* Mali-200 */ + +#define MALI_GPU_RESOURCES_MALI200(base_addr, gp_irq, pp_irq, mmu_irq) \ + MALI_GPU_RESOURCE_PP(base_addr + 0x0000, pp_irq) \ + MALI_GPU_RESOURCE_GP(base_addr + 0x2000, gp_irq) \ + MALI_GPU_RESOURCE_MMU(base_addr + 0x3000, mmu_irq) + +/* Mali-300 */ + +#define MALI_GPU_RESOURCES_MALI300(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) + +#define MALI_GPU_RESOURCES_MALI300_PMU(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP1_PMU(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) + +/* Mali-400 */ + +#define MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) + +#define MALI_GPU_RESOURCES_MALI400_MP1_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) + +#define MALI_GPU_RESOURCES_MALI400_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq) + +#define MALI_GPU_RESOURCES_MALI400_MP2_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) + +#define MALI_GPU_RESOURCES_MALI400_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0xC000, pp2_irq, base_addr + 0x6000, pp2_mmu_irq) + +#define MALI_GPU_RESOURCES_MALI400_MP3_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) + +#define MALI_GPU_RESOURCES_MALI400_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0xC000, pp2_irq, base_addr + 0x6000, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0xE000, pp3_irq, base_addr + 0x7000, pp3_mmu_irq) + +#define MALI_GPU_RESOURCES_MALI400_MP4_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) + +/* Mali-450 */ +#define MALI_GPU_RESOURCES_MALI450_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \ + MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \ + MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) + +#define MALI_GPU_RESOURCES_MALI450_MP2_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCES_MALI450_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \ + +#define MALI_GPU_RESOURCES_MALI450_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \ + MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \ + MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) + +#define MALI_GPU_RESOURCES_MALI450_MP3_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCES_MALI450_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \ + +#define MALI_GPU_RESOURCES_MALI450_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x0E000, pp3_irq, base_addr + 0x07000, pp3_mmu_irq) \ + MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \ + MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \ + MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) + +#define MALI_GPU_RESOURCES_MALI450_MP4_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCES_MALI450_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \ + +#define MALI_GPU_RESOURCES_MALI450_MP6(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x11000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x28000, pp3_irq, base_addr + 0x1C000, pp3_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(4, base_addr + 0x2A000, pp4_irq, base_addr + 0x1D000, pp4_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(5, base_addr + 0x2C000, pp5_irq, base_addr + 0x1E000, pp5_mmu_irq) \ + MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \ + MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \ + MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) + +#define MALI_GPU_RESOURCES_MALI450_MP6_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCES_MALI450_MP6(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \ + +#define MALI_GPU_RESOURCES_MALI450_MP8(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x0E000, pp3_irq, base_addr + 0x07000, pp3_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x11000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(4, base_addr + 0x28000, pp4_irq, base_addr + 0x1C000, pp4_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(5, base_addr + 0x2A000, pp5_irq, base_addr + 0x1D000, pp5_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(6, base_addr + 0x2C000, pp6_irq, base_addr + 0x1E000, pp6_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(7, base_addr + 0x2E000, pp7_irq, base_addr + 0x1F000, pp7_mmu_irq) \ + MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \ + MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \ + MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) + +#define MALI_GPU_RESOURCES_MALI450_MP8_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCES_MALI450_MP8(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \ + +#define MALI_GPU_RESOURCE_L2(addr) \ + { \ + .name = "Mali_L2", \ + .flags = IORESOURCE_MEM, \ + .start = addr, \ + .end = addr + 0x200, \ + }, + +#define MALI_GPU_RESOURCE_GP(gp_addr, gp_irq) \ + { \ + .name = "Mali_GP", \ + .flags = IORESOURCE_MEM, \ + .start = gp_addr, \ + .end = gp_addr + 0x100, \ + }, \ + { \ + .name = "Mali_GP_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = gp_irq, \ + .end = gp_irq, \ + }, \ + +#define MALI_GPU_RESOURCE_GP_WITH_MMU(gp_addr, gp_irq, gp_mmu_addr, gp_mmu_irq) \ + { \ + .name = "Mali_GP", \ + .flags = IORESOURCE_MEM, \ + .start = gp_addr, \ + .end = gp_addr + 0x100, \ + }, \ + { \ + .name = "Mali_GP_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = gp_irq, \ + .end = gp_irq, \ + }, \ + { \ + .name = "Mali_GP_MMU", \ + .flags = IORESOURCE_MEM, \ + .start = gp_mmu_addr, \ + .end = gp_mmu_addr + 0x100, \ + }, \ + { \ + .name = "Mali_GP_MMU_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = gp_mmu_irq, \ + .end = gp_mmu_irq, \ + }, + +#define MALI_GPU_RESOURCE_PP(pp_addr, pp_irq) \ + { \ + .name = "Mali_PP", \ + .flags = IORESOURCE_MEM, \ + .start = pp_addr, \ + .end = pp_addr + 0x1100, \ + }, \ + { \ + .name = "Mali_PP_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = pp_irq, \ + .end = pp_irq, \ + }, \ + +#define MALI_GPU_RESOURCE_PP_WITH_MMU(id, pp_addr, pp_irq, pp_mmu_addr, pp_mmu_irq) \ + { \ + .name = "Mali_PP" #id, \ + .flags = IORESOURCE_MEM, \ + .start = pp_addr, \ + .end = pp_addr + 0x1100, \ + }, \ + { \ + .name = "Mali_PP" #id "_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = pp_irq, \ + .end = pp_irq, \ + }, \ + { \ + .name = "Mali_PP" #id "_MMU", \ + .flags = IORESOURCE_MEM, \ + .start = pp_mmu_addr, \ + .end = pp_mmu_addr + 0x100, \ + }, \ + { \ + .name = "Mali_PP" #id "_MMU_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = pp_mmu_irq, \ + .end = pp_mmu_irq, \ + }, + +#define MALI_GPU_RESOURCE_MMU(mmu_addr, mmu_irq) \ + { \ + .name = "Mali_MMU", \ + .flags = IORESOURCE_MEM, \ + .start = mmu_addr, \ + .end = mmu_addr + 0x100, \ + }, \ + { \ + .name = "Mali_MMU_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = mmu_irq, \ + .end = mmu_irq, \ + }, + +#define MALI_GPU_RESOURCE_PMU(pmu_addr) \ + { \ + .name = "Mali_PMU", \ + .flags = IORESOURCE_MEM, \ + .start = pmu_addr, \ + .end = pmu_addr + 0x100, \ + }, + +#define MALI_GPU_RESOURCE_DLBU(dlbu_addr) \ + { \ + .name = "Mali_DLBU", \ + .flags = IORESOURCE_MEM, \ + .start = dlbu_addr, \ + .end = dlbu_addr + 0x100, \ + }, + +#define MALI_GPU_RESOURCE_BCAST(bcast_addr) \ + { \ + .name = "Mali_Broadcast", \ + .flags = IORESOURCE_MEM, \ + .start = bcast_addr, \ + .end = bcast_addr + 0x100, \ + }, + +#define MALI_GPU_RESOURCE_PP_BCAST(pp_addr, pp_irq) \ + { \ + .name = "Mali_PP_Broadcast", \ + .flags = IORESOURCE_MEM, \ + .start = pp_addr, \ + .end = pp_addr + 0x1100, \ + }, \ + { \ + .name = "Mali_PP_Broadcast_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = pp_irq, \ + .end = pp_irq, \ + }, \ + +#define MALI_GPU_RESOURCE_PP_MMU_BCAST(pp_mmu_bcast_addr) \ + { \ + .name = "Mali_PP_MMU_Broadcast", \ + .flags = IORESOURCE_MEM, \ + .start = pp_mmu_bcast_addr, \ + .end = pp_mmu_bcast_addr + 0x100, \ + }, + +struct mali_gpu_utilization_data +{ + unsigned int utilization_gpu; /* Utilization for GP and all PP cores combined, 0 = no utilization, 256 = full utilization */ + unsigned int utilization_gp; /* Utilization for GP core only, 0 = no utilization, 256 = full utilization */ + unsigned int utilization_pp; /* Utilization for all PP cores combined, 0 = no utilization, 256 = full utilization */ +}; + +struct mali_gpu_device_data +{ + /* Dedicated GPU memory range (physical). */ + unsigned long dedicated_mem_start; + unsigned long dedicated_mem_size; + + /* Shared GPU memory */ + unsigned long shared_mem_size; + + /* Frame buffer memory to be accessible by Mali GPU (physical) */ + unsigned long fb_start; + unsigned long fb_size; + + /* Report GPU utilization in this interval (specified in ms) */ + unsigned long utilization_interval; + + /* Function that will receive periodic GPU utilization numbers */ + void (*utilization_callback)(struct mali_gpu_utilization_data *data); + + /* + * Mali PMU switch delay. + * Only needed if the power gates are connected to the PMU in a high fanout + * network. This value is the number of Mali clock cycles it takes to + * enable the power gates and turn on the power mesh. + * This value will have no effect if a daisy chain implementation is used. + */ + unsigned long pmu_switch_delay; +}; + +/** @brief MALI GPU power down using MALI in-built PMU + * + * called to power down all cores + */ +int mali_pmu_powerdown(void); + + +/** @brief MALI GPU power up using MALI in-built PMU + * + * called to power up all cores + */ +int mali_pmu_powerup(void); + +/** + * Pause the scheduling and power state changes of Mali device driver. + * mali_dev_resume() must always be called as soon as possible after this function + * in order to resume normal operation of the Mali driver. + */ +void mali_dev_pause(void); + +/** + * Resume scheduling and allow power changes in Mali device driver. + * This must always be called after mali_dev_pause(). + */ +void mali_dev_resume(void); + +/** @brief Set the desired number of PP cores to use. + * + * The internal Mali PMU will be used, if present, to physically power off the PP cores. + * + * @param num_cores The number of desired cores + * @return 0 on success, otherwise error. -EINVAL means an invalid number of cores was specified. + */ +int mali_perf_set_num_pp_cores(unsigned int num_cores); + +#endif diff --git a/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_counters.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_counters.h new file mode 100644 index 0000000..3ef9a28 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_counters.h @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _MALI_UTGARD_COUNTERS_H_ +#define _MALI_UTGARD_COUNTERS_H_ + +typedef struct +{ + void *unused; +} mali_cinstr_counter_info; + +typedef enum +{ + MALI_CINSTR_COUNTER_SOURCE_EGL = 0, + MALI_CINSTR_COUNTER_SOURCE_OPENGLES = 1000, + MALI_CINSTR_COUNTER_SOURCE_OPENVG = 2000, + MALI_CINSTR_COUNTER_SOURCE_GP = 3000, + MALI_CINSTR_COUNTER_SOURCE_PP = 4000, +} cinstr_counter_source; + +#define MALI_CINSTR_EGL_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_EGL +#define MALI_CINSTR_EGL_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_EGL + 999) + +#define MALI_CINSTR_GLES_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_OPENGLES +#define MALI_CINSTR_GLES_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 999) + +#define MALI_CINSTR_VG_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_OPENVG +#define MALI_CINSTR_VG_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_OPENVG + 999) + +#define MALI_CINSTR_GP_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_GP +#define MALI_CINSTR_GP_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_GP + 999) + +#define MALI_CINSTR_PP_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_PP +#define MALI_CINSTR_PP_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_PP + 999) + + +typedef enum +{ + /* EGL counters */ + + MALI_CINSTR_EGL_BLIT_TIME = MALI_CINSTR_COUNTER_SOURCE_EGL + 0, + + /* Last counter in the EGL set */ + MALI_CINSTR_EGL_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_EGL + 1, + + /* GLES counters */ + + MALI_CINSTR_GLES_DRAW_ELEMENTS_CALLS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 0, + MALI_CINSTR_GLES_DRAW_ELEMENTS_NUM_INDICES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 1, + MALI_CINSTR_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 2, + MALI_CINSTR_GLES_DRAW_ARRAYS_CALLS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 3, + MALI_CINSTR_GLES_DRAW_ARRAYS_NUM_TRANSFORMED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 4, + MALI_CINSTR_GLES_DRAW_POINTS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 5, + MALI_CINSTR_GLES_DRAW_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 6, + MALI_CINSTR_GLES_DRAW_LINE_LOOP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 7, + MALI_CINSTR_GLES_DRAW_LINE_STRIP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 8, + MALI_CINSTR_GLES_DRAW_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 9, + MALI_CINSTR_GLES_DRAW_TRIANGLE_STRIP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 10, + MALI_CINSTR_GLES_DRAW_TRIANGLE_FAN = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 11, + MALI_CINSTR_GLES_NON_VBO_DATA_COPY_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 12, + MALI_CINSTR_GLES_UNIFORM_BYTES_COPIED_TO_MALI = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 13, + MALI_CINSTR_GLES_UPLOAD_TEXTURE_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 14, + MALI_CINSTR_GLES_UPLOAD_VBO_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 15, + MALI_CINSTR_GLES_NUM_FLUSHES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 16, + MALI_CINSTR_GLES_NUM_VSHADERS_GENERATED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 17, + MALI_CINSTR_GLES_NUM_FSHADERS_GENERATED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 18, + MALI_CINSTR_GLES_VSHADER_GEN_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 19, + MALI_CINSTR_GLES_FSHADER_GEN_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 20, + MALI_CINSTR_GLES_INPUT_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 21, + MALI_CINSTR_GLES_VXCACHE_HIT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 22, + MALI_CINSTR_GLES_VXCACHE_MISS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 23, + MALI_CINSTR_GLES_VXCACHE_COLLISION = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 24, + MALI_CINSTR_GLES_CULLED_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 25, + MALI_CINSTR_GLES_CULLED_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 26, + MALI_CINSTR_GLES_BACKFACE_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 27, + MALI_CINSTR_GLES_GBCLIP_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 28, + MALI_CINSTR_GLES_GBCLIP_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 29, + MALI_CINSTR_GLES_TRIANGLES_DRAWN = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 30, + MALI_CINSTR_GLES_DRAWCALL_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 31, + MALI_CINSTR_GLES_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 32, + MALI_CINSTR_GLES_INDEPENDENT_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 33, + MALI_CINSTR_GLES_STRIP_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 34, + MALI_CINSTR_GLES_FAN_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 35, + MALI_CINSTR_GLES_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 36, + MALI_CINSTR_GLES_INDEPENDENT_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 37, + MALI_CINSTR_GLES_STRIP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 38, + MALI_CINSTR_GLES_LOOP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 39, + MALI_CINSTR_GLES_POINTS_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 40, + + /* Last counter in the GLES set */ + MALI_CINSTR_GLES_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 41, + + /* OpenVG counters */ + + MALI_CINSTR_VG_MASK_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 0, + MALI_CINSTR_VG_CLEAR_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 1, + MALI_CINSTR_VG_APPEND_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 2, + MALI_CINSTR_VG_APPEND_PATH_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 3, + MALI_CINSTR_VG_MODIFY_PATH_COORDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 4, + MALI_CINSTR_VG_TRANSFORM_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 5, + MALI_CINSTR_VG_INTERPOLATE_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 6, + MALI_CINSTR_VG_PATH_LENGTH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 7, + MALI_CINSTR_VG_POINT_ALONG_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 8, + MALI_CINSTR_VG_PATH_BOUNDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 9, + MALI_CINSTR_VG_PATH_TRANSFORMED_BOUNDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 10, + MALI_CINSTR_VG_DRAW_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 11, + MALI_CINSTR_VG_CLEAR_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 12, + MALI_CINSTR_VG_IMAGE_SUB_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 13, + MALI_CINSTR_VG_GET_IMAGE_SUB_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 14, + MALI_CINSTR_VG_COPY_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 15, + MALI_CINSTR_VG_DRAW_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 16, + MALI_CINSTR_VG_SET_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 17, + MALI_CINSTR_VG_WRITE_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 18, + MALI_CINSTR_VG_GET_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 19, + MALI_CINSTR_VG_READ_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 20, + MALI_CINSTR_VG_COPY_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 21, + MALI_CINSTR_VG_COLOR_MATRIX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 22, + MALI_CINSTR_VG_CONVOLVE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 23, + MALI_CINSTR_VG_SEPARABLE_CONVOLVE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 24, + MALI_CINSTR_VG_GAUSSIAN_BLUR_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 25, + MALI_CINSTR_VG_LOOKUP_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 26, + MALI_CINSTR_VG_LOOKUP_SINGLE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 27, + MALI_CINSTR_VG_CONTEXT_CREATE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 28, + MALI_CINSTR_VG_STROKED_CUBICS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 29, + MALI_CINSTR_VG_STROKED_QUADS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 30, + MALI_CINSTR_VG_STROKED_ARCS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 31, + MALI_CINSTR_VG_STROKED_LINES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 32, + MALI_CINSTR_VG_FILLED_CUBICS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 33, + MALI_CINSTR_VG_FILLED_QUADS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 34, + MALI_CINSTR_VG_FILLED_ARCS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 35, + MALI_CINSTR_VG_FILLED_LINES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 36, + MALI_CINSTR_VG_DRAW_PATH_CALLS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 37, + MALI_CINSTR_VG_TRIANGLES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 38, + MALI_CINSTR_VG_VERTICES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 39, + MALI_CINSTR_VG_INDICES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 40, + MALI_CINSTR_VG_FILLED_PATHS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 41, + MALI_CINSTR_VG_STROKED_PATHS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 42, + MALI_CINSTR_VG_FILL_EXTRACT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 43, + MALI_CINSTR_VG_DRAW_FILLED_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 44, + MALI_CINSTR_VG_STROKE_EXTRACT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 45, + MALI_CINSTR_VG_DRAW_STROKED_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 46, + MALI_CINSTR_VG_DRAW_PAINT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 47, + MALI_CINSTR_VG_DATA_STRUCTURES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 48, + MALI_CINSTR_VG_MEM_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 49, + MALI_CINSTR_VG_RSW_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 50, + + /* Last counter in the VG set */ + MALI_CINSTR_VG_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 51, + + /* Mali GP counters */ + + MALI_CINSTR_GP_DEPRECATED_0 = MALI_CINSTR_COUNTER_SOURCE_GP + 0, + MALI_CINSTR_GP_ACTIVE_CYCLES_GP = MALI_CINSTR_COUNTER_SOURCE_GP + 1, + MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_SHADER = MALI_CINSTR_COUNTER_SOURCE_GP + 2, + MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_STORER = MALI_CINSTR_COUNTER_SOURCE_GP + 3, + MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_LOADER = MALI_CINSTR_COUNTER_SOURCE_GP + 4, + MALI_CINSTR_GP_CYCLES_VERTEX_LOADER_WAITING_FOR_VERTEX_SHADER = MALI_CINSTR_COUNTER_SOURCE_GP + 5, + MALI_CINSTR_GP_NUMBER_OF_WORDS_READ = MALI_CINSTR_COUNTER_SOURCE_GP + 6, + MALI_CINSTR_GP_NUMBER_OF_WORDS_WRITTEN = MALI_CINSTR_COUNTER_SOURCE_GP + 7, + MALI_CINSTR_GP_NUMBER_OF_READ_BURSTS = MALI_CINSTR_COUNTER_SOURCE_GP + 8, + MALI_CINSTR_GP_NUMBER_OF_WRITE_BURSTS = MALI_CINSTR_COUNTER_SOURCE_GP + 9, + MALI_CINSTR_GP_NUMBER_OF_VERTICES_PROCESSED = MALI_CINSTR_COUNTER_SOURCE_GP + 10, + MALI_CINSTR_GP_NUMBER_OF_VERTICES_FETCHED = MALI_CINSTR_COUNTER_SOURCE_GP + 11, + MALI_CINSTR_GP_NUMBER_OF_PRIMITIVES_FETCHED = MALI_CINSTR_COUNTER_SOURCE_GP + 12, + MALI_CINSTR_GP_RESERVED_13 = MALI_CINSTR_COUNTER_SOURCE_GP + 13, + MALI_CINSTR_GP_NUMBER_OF_BACKFACE_CULLINGS_DONE = MALI_CINSTR_COUNTER_SOURCE_GP + 14, + MALI_CINSTR_GP_NUMBER_OF_COMMANDS_WRITTEN_TO_TILES = MALI_CINSTR_COUNTER_SOURCE_GP + 15, + MALI_CINSTR_GP_NUMBER_OF_MEMORY_BLOCKS_ALLOCATED = MALI_CINSTR_COUNTER_SOURCE_GP + 16, + MALI_CINSTR_GP_RESERVED_17 = MALI_CINSTR_COUNTER_SOURCE_GP + 17, + MALI_CINSTR_GP_RESERVED_18 = MALI_CINSTR_COUNTER_SOURCE_GP + 18, + MALI_CINSTR_GP_NUMBER_OF_VERTEX_LOADER_CACHE_MISSES = MALI_CINSTR_COUNTER_SOURCE_GP + 19, + MALI_CINSTR_GP_RESERVED_20 = MALI_CINSTR_COUNTER_SOURCE_GP + 20, + MALI_CINSTR_GP_RESERVED_21 = MALI_CINSTR_COUNTER_SOURCE_GP + 21, + MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_SHADER_COMMAND_PROCESSOR = MALI_CINSTR_COUNTER_SOURCE_GP + 22, + MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_COMMAND_PROCESSOR = MALI_CINSTR_COUNTER_SOURCE_GP + 23, + MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_LIST_WRITER = MALI_CINSTR_COUNTER_SOURCE_GP + 24, + MALI_CINSTR_GP_ACTIVE_CYCLES_THROUGH_THE_PREPARE_LIST_COMMANDS = MALI_CINSTR_COUNTER_SOURCE_GP + 25, + MALI_CINSTR_GP_RESERVED_26 = MALI_CINSTR_COUNTER_SOURCE_GP + 26, + MALI_CINSTR_GP_ACTIVE_CYCLES_PRIMITIVE_ASSEMBLY = MALI_CINSTR_COUNTER_SOURCE_GP + 27, + MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_VERTEX_FETCHER = MALI_CINSTR_COUNTER_SOURCE_GP + 28, + MALI_CINSTR_GP_RESERVED_29 = MALI_CINSTR_COUNTER_SOURCE_GP + 29, + MALI_CINSTR_GP_ACTIVE_CYCLES_BOUNDINGBOX_AND_COMMAND_GENERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 30, + MALI_CINSTR_GP_RESERVED_31 = MALI_CINSTR_COUNTER_SOURCE_GP + 31, + MALI_CINSTR_GP_ACTIVE_CYCLES_SCISSOR_TILE_ITERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 32, + MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_TILE_ITERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 33, + MALI_CINSTR_GP_JOB_COUNT = MALI_CINSTR_COUNTER_SOURCE_GP + 900, + + /* Mali PP counters */ + + MALI_CINSTR_PP_ACTIVE_CLOCK_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 0, + MALI_CINSTR_PP_TOTAL_CLOCK_CYCLES_COUNT_REMOVED = MALI_CINSTR_COUNTER_SOURCE_PP + 1, + MALI_CINSTR_PP_TOTAL_BUS_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 2, + MALI_CINSTR_PP_TOTAL_BUS_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 3, + MALI_CINSTR_PP_BUS_READ_REQUEST_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 4, + MALI_CINSTR_PP_BUS_WRITE_REQUEST_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 5, + MALI_CINSTR_PP_BUS_READ_TRANSACTIONS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 6, + MALI_CINSTR_PP_BUS_WRITE_TRANSACTIONS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 7, + MALI_CINSTR_PP_RESERVED_08 = MALI_CINSTR_COUNTER_SOURCE_PP + 8, + MALI_CINSTR_PP_TILE_WRITEBACK_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 9, + MALI_CINSTR_PP_STORE_UNIT_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 10, + MALI_CINSTR_PP_RESERVED_11 = MALI_CINSTR_COUNTER_SOURCE_PP + 11, + MALI_CINSTR_PP_PALETTE_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 12, + MALI_CINSTR_PP_TEXTURE_CACHE_UNCOMPRESSED_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 13, + MALI_CINSTR_PP_POLYGON_LIST_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 14, + MALI_CINSTR_PP_RSW_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 15, + MALI_CINSTR_PP_VERTEX_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 16, + MALI_CINSTR_PP_UNIFORM_REMAPPING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 17, + MALI_CINSTR_PP_PROGRAM_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 18, + MALI_CINSTR_PP_VARYING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 19, + MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 20, + MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_REMAPPING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 21, + MALI_CINSTR_PP_TEXTURE_CACHE_COMPRESSED_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 22, + MALI_CINSTR_PP_LOAD_UNIT_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 23, + MALI_CINSTR_PP_POLYGON_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 24, + MALI_CINSTR_PP_PIXEL_RECTANGLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 25, + MALI_CINSTR_PP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 26, + MALI_CINSTR_PP_POINTS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 27, + MALI_CINSTR_PP_STALL_CYCLES_POLYGON_LIST_READER = MALI_CINSTR_COUNTER_SOURCE_PP + 28, + MALI_CINSTR_PP_STALL_CYCLES_TRIANGLE_SETUP = MALI_CINSTR_COUNTER_SOURCE_PP + 29, + MALI_CINSTR_PP_QUAD_RASTERIZED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 30, + MALI_CINSTR_PP_FRAGMENT_RASTERIZED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 31, + MALI_CINSTR_PP_FRAGMENT_REJECTED_FRAGMENT_KILL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 32, + MALI_CINSTR_PP_FRAGMENT_REJECTED_FWD_FRAGMENT_KILL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 33, + MALI_CINSTR_PP_FRAGMENT_PASSED_ZSTENCIL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 34, + MALI_CINSTR_PP_PATCHES_REJECTED_EARLY_Z_STENCIL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 35, + MALI_CINSTR_PP_PATCHES_EVALUATED = MALI_CINSTR_COUNTER_SOURCE_PP + 36, + MALI_CINSTR_PP_INSTRUCTION_COMPLETED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 37, + MALI_CINSTR_PP_INSTRUCTION_FAILED_RENDEZVOUS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 38, + MALI_CINSTR_PP_INSTRUCTION_FAILED_VARYING_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 39, + MALI_CINSTR_PP_INSTRUCTION_FAILED_TEXTURE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 40, + MALI_CINSTR_PP_INSTRUCTION_FAILED_LOAD_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 41, + MALI_CINSTR_PP_INSTRUCTION_FAILED_TILE_READ_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 42, + MALI_CINSTR_PP_INSTRUCTION_FAILED_STORE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 43, + MALI_CINSTR_PP_RENDEZVOUS_BREAKAGE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 44, + MALI_CINSTR_PP_PIPELINE_BUBBLES_CYCLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 45, + MALI_CINSTR_PP_TEXTURE_MAPPER_MULTIPASS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 46, + MALI_CINSTR_PP_TEXTURE_MAPPER_CYCLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 47, + MALI_CINSTR_PP_VERTEX_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 48, + MALI_CINSTR_PP_VERTEX_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 49, + MALI_CINSTR_PP_VARYING_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 50, + MALI_CINSTR_PP_VARYING_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 51, + MALI_CINSTR_PP_VARYING_CACHE_CONFLICT_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 52, + MALI_CINSTR_PP_TEXTURE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 53, + MALI_CINSTR_PP_TEXTURE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 54, + MALI_CINSTR_PP_TEXTURE_CACHE_CONFLICT_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 55, + MALI_CINSTR_PP_PALETTE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 56, /* Mali 200 only */ + MALI_CINSTR_PP_PALETTE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 57, /* Mali 200 only */ + MALI_CINSTR_PP_COMPRESSED_TEXTURE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 56, /* Mali 400 class only */ + MALI_CINSTR_PP_COMPRESSED_TEXTURE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 57, /* Mali 400 class only */ + MALI_CINSTR_PP_LOAD_STORE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 58, + MALI_CINSTR_PP_LOAD_STORE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 59, + MALI_CINSTR_PP_PROGRAM_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 60, + MALI_CINSTR_PP_PROGRAM_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 61, + MALI_CINSTR_PP_JOB_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 900, +} cinstr_counters_m200_t; + +#endif /*_MALI_UTGARD_COUNTERS_H_*/ diff --git a/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_ioctl.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_ioctl.h new file mode 100644 index 0000000..6043a7d --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_ioctl.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_UTGARD_IOCTL_H__ +#define __MALI_UTGARD_IOCTL_H__ + +#include +#include +#include /* file system operations */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @file mali_kernel_ioctl.h + * Interface to the Linux device driver. + * This file describes the interface needed to use the Linux device driver. + * Its interface is designed to used by the HAL implementation through a thin arch layer. + */ + +/** + * ioctl commands + */ + +#define MALI_IOC_BASE 0x82 +#define MALI_IOC_CORE_BASE (_MALI_UK_CORE_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_MEMORY_BASE (_MALI_UK_MEMORY_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_PP_BASE (_MALI_UK_PP_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_GP_BASE (_MALI_UK_GP_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_PROFILING_BASE (_MALI_UK_PROFILING_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_VSYNC_BASE (_MALI_UK_VSYNC_SUBSYSTEM + MALI_IOC_BASE) + +#define MALI_IOC_WAIT_FOR_NOTIFICATION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_WAIT_FOR_NOTIFICATION, _mali_uk_wait_for_notification_s *) +#define MALI_IOC_GET_API_VERSION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_API_VERSION, _mali_uk_get_api_version_s *) +#define MALI_IOC_POST_NOTIFICATION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_POST_NOTIFICATION, _mali_uk_post_notification_s *) +#define MALI_IOC_GET_USER_SETTING _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTING, _mali_uk_get_user_setting_s *) +#define MALI_IOC_GET_USER_SETTINGS _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTINGS, _mali_uk_get_user_settings_s *) +#define MALI_IOC_STREAM_CREATE _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_STREAM_CREATE, _mali_uk_stream_create_s *) +#define MALI_IOC_FENCE_CREATE_EMPTY _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_FENCE_CREATE_EMPTY, _mali_uk_fence_create_empty_s *) +#define MALI_IOC_FENCE_VALIDATE _IOR(MALI_IOC_CORE_BASE, _MALI_UK_FENCE_VALIDATE, _mali_uk_fence_validate_s *) + +#define MALI_IOC_MEM_GET_BIG_BLOCK _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, void *) +#define MALI_IOC_MEM_FREE_BIG_BLOCK _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_FREE_BIG_BLOCK, void *) +#define MALI_IOC_MEM_INIT _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_INIT_MEM, _mali_uk_init_mem_s *) +#define MALI_IOC_MEM_TERM _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_TERM_MEM, _mali_uk_term_mem_s *) +#define MALI_IOC_MEM_MAP_EXT _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MAP_EXT_MEM, _mali_uk_map_external_mem_s *) +#define MALI_IOC_MEM_UNMAP_EXT _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_UNMAP_EXT_MEM, _mali_uk_unmap_external_mem_s *) +#define MALI_IOC_MEM_ATTACH_DMA_BUF _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_ATTACH_DMA_BUF, _mali_uk_attach_dma_buf_s *) +#define MALI_IOC_MEM_RELEASE_DMA_BUF _IOW(MALI_IOC_MEMORY_BASE, _MALI_UK_RELEASE_DMA_BUF, _mali_uk_release_dma_buf_s *) +#define MALI_IOC_MEM_DMA_BUF_GET_SIZE _IOR(MALI_IOC_MEMORY_BASE, _MALI_UK_DMA_BUF_GET_SIZE, _mali_uk_dma_buf_get_size_s *) +#define MALI_IOC_MEM_ATTACH_UMP _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_ATTACH_UMP_MEM, _mali_uk_attach_ump_mem_s *) +#define MALI_IOC_MEM_RELEASE_UMP _IOW(MALI_IOC_MEMORY_BASE, _MALI_UK_RELEASE_UMP_MEM, _mali_uk_release_ump_mem_s *) +#define MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, _mali_uk_query_mmu_page_table_dump_size_s *) +#define MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_DUMP_MMU_PAGE_TABLE, _mali_uk_dump_mmu_page_table_s *) +#define MALI_IOC_MEM_WRITE_SAFE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MEM_WRITE_SAFE, _mali_uk_mem_write_safe_s *) + +#define MALI_IOC_PP_START_JOB _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_START_JOB, _mali_uk_pp_start_job_s *) +#define MALI_IOC_PP_NUMBER_OF_CORES_GET _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_NUMBER_OF_CORES, _mali_uk_get_pp_number_of_cores_s *) +#define MALI_IOC_PP_CORE_VERSION_GET _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_CORE_VERSION, _mali_uk_get_pp_core_version_s * ) +#define MALI_IOC_PP_DISABLE_WB _IOW (MALI_IOC_PP_BASE, _MALI_UK_PP_DISABLE_WB, _mali_uk_pp_disable_wb_s * ) + +#define MALI_IOC_GP2_START_JOB _IOWR(MALI_IOC_GP_BASE, _MALI_UK_GP_START_JOB, _mali_uk_gp_start_job_s *) +#define MALI_IOC_GP2_NUMBER_OF_CORES_GET _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_NUMBER_OF_CORES, _mali_uk_get_gp_number_of_cores_s *) +#define MALI_IOC_GP2_CORE_VERSION_GET _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_CORE_VERSION, _mali_uk_get_gp_core_version_s *) +#define MALI_IOC_GP2_SUSPEND_RESPONSE _IOW (MALI_IOC_GP_BASE, _MALI_UK_GP_SUSPEND_RESPONSE,_mali_uk_gp_suspend_response_s *) + +#define MALI_IOC_PROFILING_START _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_START, _mali_uk_profiling_start_s *) +#define MALI_IOC_PROFILING_ADD_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_ADD_EVENT, _mali_uk_profiling_add_event_s*) +#define MALI_IOC_PROFILING_STOP _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_STOP, _mali_uk_profiling_stop_s *) +#define MALI_IOC_PROFILING_GET_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_EVENT, _mali_uk_profiling_get_event_s *) +#define MALI_IOC_PROFILING_CLEAR _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_CLEAR, _mali_uk_profiling_clear_s *) +#define MALI_IOC_PROFILING_GET_CONFIG _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_CONFIG, _mali_uk_get_user_settings_s *) +#define MALI_IOC_PROFILING_REPORT_SW_COUNTERS _IOW (MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_REPORT_SW_COUNTERS, _mali_uk_sw_counters_report_s *) + +#define MALI_IOC_VSYNC_EVENT_REPORT _IOW (MALI_IOC_VSYNC_BASE, _MALI_UK_VSYNC_EVENT_REPORT, _mali_uk_vsync_event_report_s *) + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_UTGARD_IOCTL_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_events.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_events.h new file mode 100644 index 0000000..99864b8 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_events.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _MALI_UTGARD_PROFILING_EVENTS_H_ +#define _MALI_UTGARD_PROFILING_EVENTS_H_ + +/* + * The event ID is a 32 bit value consisting of different fields + * reserved, 4 bits, for future use + * event type, 4 bits, cinstr_profiling_event_type_t + * event channel, 8 bits, the source of the event. + * event data, 16 bit field, data depending on event type + */ + +/** + * Specifies what kind of event this is + */ +typedef enum +{ + MALI_PROFILING_EVENT_TYPE_SINGLE = 0 << 24, + MALI_PROFILING_EVENT_TYPE_START = 1 << 24, + MALI_PROFILING_EVENT_TYPE_STOP = 2 << 24, + MALI_PROFILING_EVENT_TYPE_SUSPEND = 3 << 24, + MALI_PROFILING_EVENT_TYPE_RESUME = 4 << 24, +} cinstr_profiling_event_type_t; + + +/** + * Secifies the channel/source of the event + */ +typedef enum +{ + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE = 0 << 16, + MALI_PROFILING_EVENT_CHANNEL_GP0 = 1 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP0 = 5 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP1 = 6 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP2 = 7 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP3 = 8 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP4 = 9 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP5 = 10 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP6 = 11 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP7 = 12 << 16, + MALI_PROFILING_EVENT_CHANNEL_GPU = 21 << 16, +} cinstr_profiling_event_channel_t; + + +#define MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(num) (((MALI_PROFILING_EVENT_CHANNEL_GP0 >> 16) + (num)) << 16) +#define MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(num) (((MALI_PROFILING_EVENT_CHANNEL_PP0 >> 16) + (num)) << 16) + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from software channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SINGLE_SW_NONE = 0, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_NEW_FRAME = 1, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_FLUSH = 2, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_SWAP_BUFFERS = 3, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_FB_EVENT = 4, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_GP_ENQUEUE = 5, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_PP_ENQUEUE = 6, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_READBACK = 7, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_WRITEBACK = 8, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_ENTER_API_FUNC = 10, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC = 11, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_DISCARD_ATTACHMENTS = 13, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_TRY_LOCK = 53, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_LOCK = 54, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_UNLOCK = 55, + MALI_PROFILING_EVENT_REASON_SINGLE_LOCK_CONTENDED = 56, +} cinstr_profiling_event_reason_single_sw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel + * to inform whether the core is physical or virtual + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL = 0, + MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL = 1, +} cinstr_profiling_event_reason_start_stop_hw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel + */ +typedef enum +{ + /*MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE = 0,*/ + MALI_PROFILING_EVENT_REASON_START_STOP_SW_MALI = 1, + MALI_PROFILING_EVENT_REASON_START_STOP_SW_CALLBACK_THREAD = 2, + MALI_PROFILING_EVENT_REASON_START_STOP_SW_WORKER_THREAD = 3, + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF = 4, + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF = 5, +} cinstr_profiling_event_reason_start_stop_sw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SUSPEND/RESUME is used from software channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_NONE = 0, /* used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PIPELINE_FULL = 1, /* NOT used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC = 26, /* used in some build configurations */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_WAIT = 27, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_SYNC = 28, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_FILTER_CLEANUP = 29, /* used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_TEXTURE = 30, /* used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_MIPLEVEL = 31, /* used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_READPIXELS = 32, /* used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_WAIT_SWAP_IMMEDIATE= 33, /* NOT used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_ICS_QUEUE_BUFFER = 34, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_ICS_DEQUEUE_BUFFER = 35, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_UMP_LOCK = 36, /* Not currently used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_GLOBAL_LOCK = 37, /* Not currently used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_SWAP = 38, /* Not currently used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_MALI_EGL_IMAGE_SYNC_WAIT = 39, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GP_JOB_HANDLING =40, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PP_JOB_HANDLING =41, /* USED */ +} cinstr_profiling_event_reason_suspend_resume_sw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from a HW channel (GPx+PPx) + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SINGLE_HW_NONE = 0, + MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT = 1, + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH = 2, +} cinstr_profiling_event_reason_single_hw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_NONE = 0, + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS = 2, + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L21_COUNTERS = 3, + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L22_COUNTERS = 4, +} cinstr_profiling_event_reason_single_gpu_t; + +/** + * These values are applicable for the 3rd data parameter when + * the type MALI_PROFILING_EVENT_TYPE_START is used from the software channel + * with the MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF reason. + */ +typedef enum +{ + MALI_PROFILING_EVENT_DATA_CORE_GP0 = 1, + MALI_PROFILING_EVENT_DATA_CORE_PP0 = 5, + MALI_PROFILING_EVENT_DATA_CORE_PP1 = 6, + MALI_PROFILING_EVENT_DATA_CORE_PP2 = 7, + MALI_PROFILING_EVENT_DATA_CORE_PP3 = 8, + MALI_PROFILING_EVENT_DATA_CORE_PP4 = 9, + MALI_PROFILING_EVENT_DATA_CORE_PP5 = 10, + MALI_PROFILING_EVENT_DATA_CORE_PP6 = 11, + MALI_PROFILING_EVENT_DATA_CORE_PP7 = 12, +} cinstr_profiling_event_data_core_t; + +#define MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(num) (MALI_PROFILING_EVENT_DATA_CORE_GP0 + (num)) +#define MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(num) (MALI_PROFILING_EVENT_DATA_CORE_PP0 + (num)) + + +#endif /*_MALI_UTGARD_PROFILING_EVENTS_H_*/ diff --git a/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_gator_api.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_gator_api.h new file mode 100644 index 0000000..c449215 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_gator_api.h @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_UTGARD_PROFILING_GATOR_API_H__ +#define __MALI_UTGARD_PROFILING_GATOR_API_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MALI_PROFILING_API_VERSION 4 + +#define MAX_NUM_L2_CACHE_CORES 3 +#define MAX_NUM_FP_CORES 8 +#define MAX_NUM_VP_CORES 1 + +/** The list of events supported by the Mali DDK. */ +typedef enum +{ + /* Vertex processor activity */ + ACTIVITY_VP_0 = 0, + + /* Fragment processor activity */ + ACTIVITY_FP_0, + ACTIVITY_FP_1, + ACTIVITY_FP_2, + ACTIVITY_FP_3, + ACTIVITY_FP_4, + ACTIVITY_FP_5, + ACTIVITY_FP_6, + ACTIVITY_FP_7, + + /* L2 cache counters */ + COUNTER_L2_0_C0, + COUNTER_L2_0_C1, + COUNTER_L2_1_C0, + COUNTER_L2_1_C1, + COUNTER_L2_2_C0, + COUNTER_L2_2_C1, + + /* Vertex processor counters */ + COUNTER_VP_0_C0, + COUNTER_VP_0_C1, + + /* Fragment processor counters */ + COUNTER_FP_0_C0, + COUNTER_FP_0_C1, + COUNTER_FP_1_C0, + COUNTER_FP_1_C1, + COUNTER_FP_2_C0, + COUNTER_FP_2_C1, + COUNTER_FP_3_C0, + COUNTER_FP_3_C1, + COUNTER_FP_4_C0, + COUNTER_FP_4_C1, + COUNTER_FP_5_C0, + COUNTER_FP_5_C1, + COUNTER_FP_6_C0, + COUNTER_FP_6_C1, + COUNTER_FP_7_C0, + COUNTER_FP_7_C1, + + /* + * If more hardware counters are added, the _mali_osk_hw_counter_table + * below should also be updated. + */ + + /* EGL software counters */ + COUNTER_EGL_BLIT_TIME, + + /* GLES software counters */ + COUNTER_GLES_DRAW_ELEMENTS_CALLS, + COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, + COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_ARRAYS_CALLS, + COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_POINTS, + COUNTER_GLES_DRAW_LINES, + COUNTER_GLES_DRAW_LINE_LOOP, + COUNTER_GLES_DRAW_LINE_STRIP, + COUNTER_GLES_DRAW_TRIANGLES, + COUNTER_GLES_DRAW_TRIANGLE_STRIP, + COUNTER_GLES_DRAW_TRIANGLE_FAN, + COUNTER_GLES_NON_VBO_DATA_COPY_TIME, + COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, + COUNTER_GLES_UPLOAD_TEXTURE_TIME, + COUNTER_GLES_UPLOAD_VBO_TIME, + COUNTER_GLES_NUM_FLUSHES, + COUNTER_GLES_NUM_VSHADERS_GENERATED, + COUNTER_GLES_NUM_FSHADERS_GENERATED, + COUNTER_GLES_VSHADER_GEN_TIME, + COUNTER_GLES_FSHADER_GEN_TIME, + COUNTER_GLES_INPUT_TRIANGLES, + COUNTER_GLES_VXCACHE_HIT, + COUNTER_GLES_VXCACHE_MISS, + COUNTER_GLES_VXCACHE_COLLISION, + COUNTER_GLES_CULLED_TRIANGLES, + COUNTER_GLES_CULLED_LINES, + COUNTER_GLES_BACKFACE_TRIANGLES, + COUNTER_GLES_GBCLIP_TRIANGLES, + COUNTER_GLES_GBCLIP_LINES, + COUNTER_GLES_TRIANGLES_DRAWN, + COUNTER_GLES_DRAWCALL_TIME, + COUNTER_GLES_TRIANGLES_COUNT, + COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, + COUNTER_GLES_STRIP_TRIANGLES_COUNT, + COUNTER_GLES_FAN_TRIANGLES_COUNT, + COUNTER_GLES_LINES_COUNT, + COUNTER_GLES_INDEPENDENT_LINES_COUNT, + COUNTER_GLES_STRIP_LINES_COUNT, + COUNTER_GLES_LOOP_LINES_COUNT, + + /* Framebuffer capture pseudo-counter */ + COUNTER_FILMSTRIP, + + NUMBER_OF_EVENTS +} _mali_osk_counter_id; + +#define FIRST_ACTIVITY_EVENT ACTIVITY_VP_0 +#define LAST_ACTIVITY_EVENT ACTIVITY_FP_7 + +#define FIRST_HW_COUNTER COUNTER_L2_0_C0 +#define LAST_HW_COUNTER COUNTER_FP_7_C1 + +#define FIRST_SW_COUNTER COUNTER_EGL_BLIT_TIME +#define LAST_SW_COUNTER COUNTER_GLES_LOOP_LINES_COUNT + +#define FIRST_SPECIAL_COUNTER COUNTER_FILMSTRIP +#define LAST_SPECIAL_COUNTER COUNTER_FILMSTRIP + +/** + * Structure to pass performance counter data of a Mali core + */ +typedef struct _mali_profiling_core_counters +{ + u32 source0; + u32 value0; + u32 source1; + u32 value1; +} _mali_profiling_core_counters; + +/** + * Structure to pass performance counter data of Mali L2 cache cores + */ +typedef struct _mali_profiling_l2_counter_values +{ + struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES]; +} _mali_profiling_l2_counter_values; + +/** + * Structure to pass data defining Mali instance in use: + * + * mali_product_id - Mali product id + * mali_version_major - Mali version major number + * mali_version_minor - Mali version minor number + * num_of_l2_cores - number of L2 cache cores + * num_of_fp_cores - number of fragment processor cores + * num_of_vp_cores - number of vertex processor cores + */ +typedef struct _mali_profiling_mali_version +{ + u32 mali_product_id; + u32 mali_version_major; + u32 mali_version_minor; + u32 num_of_l2_cores; + u32 num_of_fp_cores; + u32 num_of_vp_cores; +} _mali_profiling_mali_version; + +/* + * List of possible actions to be controlled by Streamline. + * The following numbers are used by gator to control the frame buffer dumping and s/w counter reporting. + * We cannot use the enums in mali_uk_types.h because they are unknown inside gator. + */ +#define FBDUMP_CONTROL_ENABLE (1) +#define FBDUMP_CONTROL_RATE (2) +#define SW_COUNTER_ENABLE (3) +#define FBDUMP_CONTROL_RESIZE_FACTOR (4) + +void _mali_profiling_control(u32 action, u32 value); + +u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values); + +int _mali_profiling_set_event(u32 counter_id, s32 event_id); + +u32 _mali_profiling_get_api_version(void); + +void _mali_profiling_get_mali_version(struct _mali_profiling_mali_version *values); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_UTGARD_PROFILING_GATOR_API_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_uk_types.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_uk_types.h new file mode 100644 index 0000000..4957095 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_uk_types.h @@ -0,0 +1,1165 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_uk_types.h + * Defines the types and constants used in the user-kernel interface + */ + +#ifndef __MALI_UTGARD_UK_TYPES_H__ +#define __MALI_UTGARD_UK_TYPES_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @addtogroup uddapi Unified Device Driver (UDD) APIs + * + * @{ + */ + +/** + * @addtogroup u_k_api UDD User/Kernel Interface (U/K) APIs + * + * @{ + */ + +/** @defgroup _mali_uk_core U/K Core + * @{ */ + +/** Definition of subsystem numbers, to assist in creating a unique identifier + * for each U/K call. + * + * @see _mali_uk_functions */ +typedef enum +{ + _MALI_UK_CORE_SUBSYSTEM, /**< Core Group of U/K calls */ + _MALI_UK_MEMORY_SUBSYSTEM, /**< Memory Group of U/K calls */ + _MALI_UK_PP_SUBSYSTEM, /**< Fragment Processor Group of U/K calls */ + _MALI_UK_GP_SUBSYSTEM, /**< Vertex Processor Group of U/K calls */ + _MALI_UK_PROFILING_SUBSYSTEM, /**< Profiling Group of U/K calls */ + _MALI_UK_PMM_SUBSYSTEM, /**< Power Management Module Group of U/K calls */ + _MALI_UK_VSYNC_SUBSYSTEM, /**< VSYNC Group of U/K calls */ +} _mali_uk_subsystem_t; + +/** Within a function group each function has its unique sequence number + * to assist in creating a unique identifier for each U/K call. + * + * An ordered pair of numbers selected from + * ( \ref _mali_uk_subsystem_t,\ref _mali_uk_functions) will uniquely identify the + * U/K call across all groups of functions, and all functions. */ +typedef enum +{ + /** Core functions */ + + _MALI_UK_OPEN = 0, /**< _mali_ukk_open() */ + _MALI_UK_CLOSE, /**< _mali_ukk_close() */ + _MALI_UK_WAIT_FOR_NOTIFICATION, /**< _mali_ukk_wait_for_notification() */ + _MALI_UK_GET_API_VERSION, /**< _mali_ukk_get_api_version() */ + _MALI_UK_POST_NOTIFICATION, /**< _mali_ukk_post_notification() */ + _MALI_UK_GET_USER_SETTING, /**< _mali_ukk_get_user_setting() *//**< [out] */ + _MALI_UK_GET_USER_SETTINGS, /**< _mali_ukk_get_user_settings() *//**< [out] */ + _MALI_UK_STREAM_CREATE, /**< _mali_ukk_stream_create() */ + _MALI_UK_FENCE_CREATE_EMPTY, /**< _mali_ukk_fence_create_empty() */ + _MALI_UK_FENCE_VALIDATE, /**< _mali_ukk_fence_validate() */ + + /** Memory functions */ + + _MALI_UK_INIT_MEM = 0, /**< _mali_ukk_init_mem() */ + _MALI_UK_TERM_MEM, /**< _mali_ukk_term_mem() */ + _MALI_UK_GET_BIG_BLOCK, /**< _mali_ukk_get_big_block() */ + _MALI_UK_FREE_BIG_BLOCK, /**< _mali_ukk_free_big_block() */ + _MALI_UK_MAP_MEM, /**< _mali_ukk_mem_mmap() */ + _MALI_UK_UNMAP_MEM, /**< _mali_ukk_mem_munmap() */ + _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, /**< _mali_ukk_mem_get_mmu_page_table_dump_size() */ + _MALI_UK_DUMP_MMU_PAGE_TABLE, /**< _mali_ukk_mem_dump_mmu_page_table() */ + _MALI_UK_ATTACH_DMA_BUF, /**< _mali_ukk_attach_dma_buf() */ + _MALI_UK_RELEASE_DMA_BUF, /**< _mali_ukk_release_dma_buf() */ + _MALI_UK_DMA_BUF_GET_SIZE, /**< _mali_ukk_dma_buf_get_size() */ + _MALI_UK_ATTACH_UMP_MEM, /**< _mali_ukk_attach_ump_mem() */ + _MALI_UK_RELEASE_UMP_MEM, /**< _mali_ukk_release_ump_mem() */ + _MALI_UK_MAP_EXT_MEM, /**< _mali_uku_map_external_mem() */ + _MALI_UK_UNMAP_EXT_MEM, /**< _mali_uku_unmap_external_mem() */ + _MALI_UK_VA_TO_MALI_PA, /**< _mali_uku_va_to_mali_pa() */ + _MALI_UK_MEM_WRITE_SAFE, /**< _mali_uku_mem_write_safe() */ + + /** Common functions for each core */ + + _MALI_UK_START_JOB = 0, /**< Start a Fragment/Vertex Processor Job on a core */ + _MALI_UK_GET_NUMBER_OF_CORES, /**< Get the number of Fragment/Vertex Processor cores */ + _MALI_UK_GET_CORE_VERSION, /**< Get the Fragment/Vertex Processor version compatible with all cores */ + + /** Fragment Processor Functions */ + + _MALI_UK_PP_START_JOB = _MALI_UK_START_JOB, /**< _mali_ukk_pp_start_job() */ + _MALI_UK_GET_PP_NUMBER_OF_CORES = _MALI_UK_GET_NUMBER_OF_CORES, /**< _mali_ukk_get_pp_number_of_cores() */ + _MALI_UK_GET_PP_CORE_VERSION = _MALI_UK_GET_CORE_VERSION, /**< _mali_ukk_get_pp_core_version() */ + _MALI_UK_PP_DISABLE_WB, /**< _mali_ukk_pp_job_disable_wb() */ + + /** Vertex Processor Functions */ + + _MALI_UK_GP_START_JOB = _MALI_UK_START_JOB, /**< _mali_ukk_gp_start_job() */ + _MALI_UK_GET_GP_NUMBER_OF_CORES = _MALI_UK_GET_NUMBER_OF_CORES, /**< _mali_ukk_get_gp_number_of_cores() */ + _MALI_UK_GET_GP_CORE_VERSION = _MALI_UK_GET_CORE_VERSION, /**< _mali_ukk_get_gp_core_version() */ + _MALI_UK_GP_SUSPEND_RESPONSE, /**< _mali_ukk_gp_suspend_response() */ + + /** Profiling functions */ + + _MALI_UK_PROFILING_START = 0, /**< __mali_uku_profiling_start() */ + _MALI_UK_PROFILING_ADD_EVENT, /**< __mali_uku_profiling_add_event() */ + _MALI_UK_PROFILING_STOP, /**< __mali_uku_profiling_stop() */ + _MALI_UK_PROFILING_GET_EVENT, /**< __mali_uku_profiling_get_event() */ + _MALI_UK_PROFILING_CLEAR, /**< __mali_uku_profiling_clear() */ + _MALI_UK_PROFILING_GET_CONFIG, /**< __mali_uku_profiling_get_config() */ + _MALI_UK_PROFILING_REPORT_SW_COUNTERS,/**< __mali_uku_profiling_report_sw_counters() */ + + /** VSYNC reporting fuctions */ + _MALI_UK_VSYNC_EVENT_REPORT = 0, /**< _mali_ukk_vsync_event_report() */ + +} _mali_uk_functions; + +/** @brief Get the size necessary for system info + * + * @see _mali_ukk_get_system_info_size() + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 size; /**< [out] size of buffer necessary to hold system information data, in bytes */ +} _mali_uk_get_system_info_size_s; + + +/** @defgroup _mali_uk_getsysteminfo U/K Get System Info + * @{ */ + +/** + * Type definition for the core version number. + * Used when returning the version number read from a core + * + * Its format is that of the 32-bit Version register for a particular core. + * Refer to the "Mali200 and MaliGP2 3D Graphics Processor Technical Reference + * Manual", ARM DDI 0415C, for more information. + */ +typedef u32 _mali_core_version; + +/** + * Enum values for the different modes the driver can be put in. + * Normal is the default mode. The driver then uses a job queue and takes job objects from the clients. + * Job completion is reported using the _mali_ukk_wait_for_notification call. + * The driver blocks this io command until a job has completed or failed or a timeout occurs. + * + * The 'raw' mode is reserved for future expansion. + */ +typedef enum _mali_driver_mode +{ + _MALI_DRIVER_MODE_RAW = 1, /**< Reserved for future expansion */ + _MALI_DRIVER_MODE_NORMAL = 2 /**< Normal mode of operation */ +} _mali_driver_mode; + +/** @brief List of possible cores + * + * add new entries to the end of this enum */ +typedef enum _mali_core_type +{ + _MALI_GP2 = 2, /**< MaliGP2 Programmable Vertex Processor */ + _MALI_200 = 5, /**< Mali200 Programmable Fragment Processor */ + _MALI_400_GP = 6, /**< Mali400 Programmable Vertex Processor */ + _MALI_400_PP = 7, /**< Mali400 Programmable Fragment Processor */ + /* insert new core here, do NOT alter the existing values */ +} _mali_core_type; + + +/** @brief Capabilities of Memory Banks + * + * These may be used to restrict memory banks for certain uses. They may be + * used when access is not possible (e.g. Bus does not support access to it) + * or when access is possible but not desired (e.g. Access is slow). + * + * In the case of 'possible but not desired', there is no way of specifying + * the flags as an optimization hint, so that the memory could be used as a + * last resort. + * + * @see _mali_mem_info + */ +typedef enum _mali_bus_usage +{ + + _MALI_PP_READABLE = (1<<0), /** Readable by the Fragment Processor */ + _MALI_PP_WRITEABLE = (1<<1), /** Writeable by the Fragment Processor */ + _MALI_GP_READABLE = (1<<2), /** Readable by the Vertex Processor */ + _MALI_GP_WRITEABLE = (1<<3), /** Writeable by the Vertex Processor */ + _MALI_CPU_READABLE = (1<<4), /** Readable by the CPU */ + _MALI_CPU_WRITEABLE = (1<<5), /** Writeable by the CPU */ + _MALI_GP_L2_ALLOC = (1<<6), /** GP allocate mali L2 cache lines*/ + _MALI_MMU_READABLE = _MALI_PP_READABLE | _MALI_GP_READABLE, /** Readable by the MMU (including all cores behind it) */ + _MALI_MMU_WRITEABLE = _MALI_PP_WRITEABLE | _MALI_GP_WRITEABLE, /** Writeable by the MMU (including all cores behind it) */ +} _mali_bus_usage; + +typedef enum mali_memory_cache_settings +{ + MALI_CACHE_STANDARD = 0, + MALI_CACHE_GP_READ_ALLOCATE = 1, +} mali_memory_cache_settings ; + + +/** @brief Information about the Mali Memory system + * + * Information is stored in a linked list, which is stored entirely in the + * buffer pointed to by the system_info member of the + * _mali_uk_get_system_info_s arguments provided to _mali_ukk_get_system_info() + * + * Each element of the linked list describes a single Mali Memory bank. + * Each allocation can only come from one bank, and will not cross multiple + * banks. + * + * On Mali-MMU systems, there is only one bank, which describes the maximum + * possible address range that could be allocated (which may be much less than + * the available physical memory) + * + * The flags member describes the capabilities of the memory. It is an error + * to attempt to build a job for a particular core (PP or GP) when the memory + * regions used do not have the capabilities for supporting that core. This + * would result in a job abort from the Device Driver. + * + * For example, it is correct to build a PP job where read-only data structures + * are taken from a memory with _MALI_PP_READABLE set and + * _MALI_PP_WRITEABLE clear, and a framebuffer with _MALI_PP_WRITEABLE set and + * _MALI_PP_READABLE clear. However, it would be incorrect to use a framebuffer + * where _MALI_PP_WRITEABLE is clear. + */ +typedef struct _mali_mem_info +{ + u32 size; /**< Size of the memory bank in bytes */ + _mali_bus_usage flags; /**< Capabilitiy flags of the memory */ + u32 maximum_order_supported; /**< log2 supported size */ + u32 identifier; /* mali_memory_cache_settings cache_settings; */ + struct _mali_mem_info * next; /**< Next List Link */ +} _mali_mem_info; + + + +/** @} */ /* end group _mali_uk_core */ + + +/** @defgroup _mali_uk_gp U/K Vertex Processor + * @{ */ + +/** @defgroup _mali_uk_gp_suspend_response_s Vertex Processor Suspend Response + * @{ */ + +/** @brief Arguments for _mali_ukk_gp_suspend_response() + * + * When _mali_wait_for_notification() receives notification that a + * Vertex Processor job was suspended, you need to send a response to indicate + * what needs to happen with this job. You can either abort or resume the job. + * + * - set @c code to indicate response code. This is either @c _MALIGP_JOB_ABORT or + * @c _MALIGP_JOB_RESUME_WITH_NEW_HEAP to indicate you will provide a new heap + * for the job that will resolve the out of memory condition for the job. + * - copy the @c cookie value from the @c _mali_uk_gp_job_suspended_s notification; + * this is an identifier for the suspended job + * - set @c arguments[0] and @c arguments[1] to zero if you abort the job. If + * you resume it, @c argument[0] should specify the Mali start address for the new + * heap and @c argument[1] the Mali end address of the heap. + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * + */ +typedef enum _maligp_job_suspended_response_code +{ + _MALIGP_JOB_ABORT, /**< Abort the Vertex Processor job */ + _MALIGP_JOB_RESUME_WITH_NEW_HEAP /**< Resume the Vertex Processor job with a new heap */ +} _maligp_job_suspended_response_code; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 cookie; /**< [in] cookie from the _mali_uk_gp_job_suspended_s notification */ + _maligp_job_suspended_response_code code; /**< [in] abort or resume response code, see \ref _maligp_job_suspended_response_code */ + u32 arguments[2]; /**< [in] 0 when aborting a job. When resuming a job, the Mali start and end address for a new heap to resume the job with */ +} _mali_uk_gp_suspend_response_s; + +/** @} */ /* end group _mali_uk_gp_suspend_response_s */ + +/** @defgroup _mali_uk_gpstartjob_s Vertex Processor Start Job + * @{ */ + +/** @brief Status indicating the result of starting a Vertex or Fragment processor job */ +typedef enum +{ + _MALI_UK_START_JOB_STARTED, /**< Job started */ + _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE /**< Job could not be started at this time. Try starting the job again */ +} _mali_uk_start_job_status; + +/** @brief Status indicating the result of the execution of a Vertex or Fragment processor job */ + +typedef enum +{ + _MALI_UK_JOB_STATUS_END_SUCCESS = 1<<(16+0), + _MALI_UK_JOB_STATUS_END_OOM = 1<<(16+1), + _MALI_UK_JOB_STATUS_END_ABORT = 1<<(16+2), + _MALI_UK_JOB_STATUS_END_TIMEOUT_SW = 1<<(16+3), + _MALI_UK_JOB_STATUS_END_HANG = 1<<(16+4), + _MALI_UK_JOB_STATUS_END_SEG_FAULT = 1<<(16+5), + _MALI_UK_JOB_STATUS_END_ILLEGAL_JOB = 1<<(16+6), + _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR = 1<<(16+7), + _MALI_UK_JOB_STATUS_END_SHUTDOWN = 1<<(16+8), + _MALI_UK_JOB_STATUS_END_SYSTEM_UNUSABLE = 1<<(16+9) +} _mali_uk_job_status; + +#define MALIGP2_NUM_REGS_FRAME (6) + +/** @brief Arguments for _mali_ukk_gp_start_job() + * + * To start a Vertex Processor job + * - associate the request with a reference to a @c mali_gp_job_info by setting + * user_job_ptr to the address of the @c mali_gp_job_info of the job. + * - set @c priority to the priority of the @c mali_gp_job_info + * - specify a timeout for the job by setting @c watchdog_msecs to the number of + * milliseconds the job is allowed to run. Specifying a value of 0 selects the + * default timeout in use by the device driver. + * - copy the frame registers from the @c mali_gp_job_info into @c frame_registers. + * - set the @c perf_counter_flag, @c perf_counter_src0 and @c perf_counter_src1 to zero + * for a non-instrumented build. For an instrumented build you can use up + * to two performance counters. Set the corresponding bit in @c perf_counter_flag + * to enable them. @c perf_counter_src0 and @c perf_counter_src1 specify + * the source of what needs to get counted (e.g. number of vertex loader + * cache hits). For source id values, see ARM DDI0415A, Table 3-60. + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * + * When @c _mali_ukk_gp_start_job() returns @c _MALI_OSK_ERR_OK, status contains the + * result of the request (see \ref _mali_uk_start_job_status). If the job could + * not get started (@c _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE) it should be + * tried again. + * + * After the job has started, @c _mali_wait_for_notification() will be notified + * that the job finished or got suspended. It may get suspended due to + * resource shortage. If it finished (see _mali_ukk_wait_for_notification()) + * the notification will contain a @c _mali_uk_gp_job_finished_s result. If + * it got suspended the notification will contain a @c _mali_uk_gp_job_suspended_s + * result. + * + * The @c _mali_uk_gp_job_finished_s contains the job status (see \ref _mali_uk_job_status), + * the number of milliseconds the job took to render, and values of core registers + * when the job finished (irq status, performance counters, renderer list + * address). A job has finished succesfully when its status is + * @c _MALI_UK_JOB_STATUS_FINISHED. If the hardware detected a timeout while rendering + * the job, or software detected the job is taking more than watchdog_msecs to + * complete, the status will indicate @c _MALI_UK_JOB_STATUS_HANG. + * If the hardware detected a bus error while accessing memory associated with the + * job, status will indicate @c _MALI_UK_JOB_STATUS_SEG_FAULT. + * status will indicate @c _MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to + * stop the job but the job didn't start on the hardware yet, e.g. when the + * driver shutdown. + * + * In case the job got suspended, @c _mali_uk_gp_job_suspended_s contains + * the @c user_job_ptr identifier used to start the job with, the @c reason + * why the job stalled (see \ref _maligp_job_suspended_reason) and a @c cookie + * to identify the core on which the job stalled. This @c cookie will be needed + * when responding to this nofication by means of _mali_ukk_gp_suspend_response(). + * (see _mali_ukk_gp_suspend_response()). The response is either to abort or + * resume the job. If the job got suspended due to an out of memory condition + * you may be able to resolve this by providing more memory and resuming the job. + * + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 user_job_ptr; /**< [in] identifier for the job in user space, a @c mali_gp_job_info* */ + u32 priority; /**< [in] job priority. A lower number means higher priority */ + u32 frame_registers[MALIGP2_NUM_REGS_FRAME]; /**< [in] core specific registers associated with this job */ + u32 perf_counter_flag; /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ + u32 perf_counter_src0; /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ + u32 perf_counter_src1; /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ + u32 frame_builder_id; /**< [in] id of the originating frame builder */ + u32 flush_id; /**< [in] flush id within the originating frame builder */ +} _mali_uk_gp_start_job_s; + +#define _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE (1<<0) /**< Enable performance counter SRC0 for a job */ +#define _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE (1<<1) /**< Enable performance counter SRC1 for a job */ + +/** @} */ /* end group _mali_uk_gpstartjob_s */ + +typedef struct +{ + u32 user_job_ptr; /**< [out] identifier for the job in user space */ + _mali_uk_job_status status; /**< [out] status of finished job */ + u32 heap_current_addr; /**< [out] value of the GP PLB PL heap start address register */ + u32 perf_counter0; /**< [out] value of perfomance counter 0 (see ARM DDI0415A) */ + u32 perf_counter1; /**< [out] value of perfomance counter 1 (see ARM DDI0415A) */ +} _mali_uk_gp_job_finished_s; + +typedef enum _maligp_job_suspended_reason +{ + _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY /**< Polygon list builder unit (PLBU) has run out of memory */ +} _maligp_job_suspended_reason; + +typedef struct +{ + u32 user_job_ptr; /**< [out] identifier for the job in user space */ + _maligp_job_suspended_reason reason; /**< [out] reason why the job stalled */ + u32 cookie; /**< [out] identifier for the core in kernel space on which the job stalled */ +} _mali_uk_gp_job_suspended_s; + +/** @} */ /* end group _mali_uk_gp */ + + +/** @defgroup _mali_uk_pp U/K Fragment Processor + * @{ */ + +#define _MALI_PP_MAX_SUB_JOBS 8 + +#define _MALI_PP_MAX_FRAME_REGISTERS ((0x058/4)+1) + +#define _MALI_PP_MAX_WB_REGISTERS ((0x02C/4)+1) + +#define _MALI_DLBU_MAX_REGISTERS 4 + +/** Flag for _mali_uk_pp_start_job_s */ +#define _MALI_PP_JOB_FLAG_NO_NOTIFICATION (1<<0) +#define _MALI_PP_JOB_FLAG_BARRIER (1<<1) +#define _MALI_PP_JOB_FLAG_FENCE (1<<2) +#define _MALI_PP_JOB_FLAG_EMPTY_FENCE (1<<3) + +/** @defgroup _mali_uk_ppstartjob_s Fragment Processor Start Job + * @{ */ + +/** @brief Arguments for _mali_ukk_pp_start_job() + * + * To start a Fragment Processor job + * - associate the request with a reference to a mali_pp_job by setting + * @c user_job_ptr to the address of the @c mali_pp_job of the job. + * - set @c priority to the priority of the mali_pp_job + * - specify a timeout for the job by setting @c watchdog_msecs to the number of + * milliseconds the job is allowed to run. Specifying a value of 0 selects the + * default timeout in use by the device driver. + * - copy the frame registers from the @c mali_pp_job into @c frame_registers. + * For MALI200 you also need to copy the write back 0,1 and 2 registers. + * - set the @c perf_counter_flag, @c perf_counter_src0 and @c perf_counter_src1 to zero + * for a non-instrumented build. For an instrumented build you can use up + * to two performance counters. Set the corresponding bit in @c perf_counter_flag + * to enable them. @c perf_counter_src0 and @c perf_counter_src1 specify + * the source of what needs to get counted (e.g. number of vertex loader + * cache hits). For source id values, see ARM DDI0415A, Table 3-60. + * - pass in the user-kernel context in @c ctx that was returned from _mali_ukk_open() + * + * When _mali_ukk_pp_start_job() returns @c _MALI_OSK_ERR_OK, @c status contains the + * result of the request (see \ref _mali_uk_start_job_status). If the job could + * not get started (@c _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE) it should be + * tried again. + * + * After the job has started, _mali_wait_for_notification() will be notified + * when the job finished. The notification will contain a + * @c _mali_uk_pp_job_finished_s result. It contains the @c user_job_ptr + * identifier used to start the job with, the job @c status (see \ref _mali_uk_job_status), + * the number of milliseconds the job took to render, and values of core registers + * when the job finished (irq status, performance counters, renderer list + * address). A job has finished succesfully when its status is + * @c _MALI_UK_JOB_STATUS_FINISHED. If the hardware detected a timeout while rendering + * the job, or software detected the job is taking more than @c watchdog_msecs to + * complete, the status will indicate @c _MALI_UK_JOB_STATUS_HANG. + * If the hardware detected a bus error while accessing memory associated with the + * job, status will indicate @c _MALI_UK_JOB_STATUS_SEG_FAULT. + * status will indicate @c _MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to + * stop the job but the job didn't start on the hardware yet, e.g. when the + * driver shutdown. + * + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 user_job_ptr; /**< [in] identifier for the job in user space */ + u32 priority; /**< [in] job priority. A lower number means higher priority */ + u32 frame_registers[_MALI_PP_MAX_FRAME_REGISTERS]; /**< [in] core specific registers associated with first sub job, see ARM DDI0415A */ + u32 frame_registers_addr_frame[_MALI_PP_MAX_SUB_JOBS - 1]; /**< [in] ADDR_FRAME registers for sub job 1-7 */ + u32 frame_registers_addr_stack[_MALI_PP_MAX_SUB_JOBS - 1]; /**< [in] ADDR_STACK registers for sub job 1-7 */ + u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS]; + u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS]; + u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS]; + u32 dlbu_registers[_MALI_DLBU_MAX_REGISTERS]; /**< [in] Dynamic load balancing unit registers */ + u32 num_cores; /**< [in] Number of cores to set up (valid range: 1-4) */ + u32 perf_counter_flag; /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ + u32 perf_counter_src0; /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ + u32 perf_counter_src1; /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ + u32 frame_builder_id; /**< [in] id of the originating frame builder */ + u32 flush_id; /**< [in] flush id within the originating frame builder */ + u32 flags; /**< [in] See _MALI_PP_JOB_FLAG_* for a list of avaiable flags */ + s32 fence; /**< [in,out] Fence to wait on / fence that will be signalled on job completion, if _MALI_PP_JOB_FLAG_FENCE is set */ + s32 stream; /**< [in] Steam identifier if _MALI_PP_JOB_FLAG_FENCE, an empty fence to use for this job if _MALI_PP_JOB_FLAG_EMPTY_FENCE is set */ + u32 num_memory_cookies; /**< [in] number of memory cookies attached to job */ + u32 *memory_cookies; /**< [in] memory cookies attached to job */ +} _mali_uk_pp_start_job_s; +/** @} */ /* end group _mali_uk_ppstartjob_s */ + +typedef struct +{ + u32 user_job_ptr; /**< [out] identifier for the job in user space */ + _mali_uk_job_status status; /**< [out] status of finished job */ + u32 perf_counter0[_MALI_PP_MAX_SUB_JOBS]; /**< [out] value of perfomance counter 0 (see ARM DDI0415A), one for each sub job */ + u32 perf_counter1[_MALI_PP_MAX_SUB_JOBS]; /**< [out] value of perfomance counter 1 (see ARM DDI0415A), one for each sub job */ +} _mali_uk_pp_job_finished_s; + +typedef struct +{ + u32 number_of_enabled_cores; /**< [out] the new number of enabled cores */ +} _mali_uk_pp_num_cores_changed_s; + + + +/** + * Flags to indicate write-back units + */ +typedef enum +{ + _MALI_UK_PP_JOB_WB0 = 1, + _MALI_UK_PP_JOB_WB1 = 2, + _MALI_UK_PP_JOB_WB2 = 4, +} _mali_uk_pp_job_wbx_flag; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 fb_id; /**< [in] Frame builder ID of job to disable WB units for */ + u32 flush_id; /**< [in] Flush ID of job to disable WB units for */ + _mali_uk_pp_job_wbx_flag wbx; /**< [in] write-back units to disable */ +} _mali_uk_pp_disable_wb_s; + + +/** @} */ /* end group _mali_uk_pp */ + + +/** @addtogroup _mali_uk_core U/K Core + * @{ */ + +/** @defgroup _mali_uk_waitfornotification_s Wait For Notification + * @{ */ + +/** @brief Notification type encodings + * + * Each Notification type is an ordered pair of (subsystem,id), and is unique. + * + * The encoding of subsystem,id into a 32-bit word is: + * encoding = (( subsystem << _MALI_NOTIFICATION_SUBSYSTEM_SHIFT ) & _MALI_NOTIFICATION_SUBSYSTEM_MASK) + * | (( id << _MALI_NOTIFICATION_ID_SHIFT ) & _MALI_NOTIFICATION_ID_MASK) + * + * @see _mali_uk_wait_for_notification_s + */ +typedef enum +{ + /** core notifications */ + + _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x20, + _MALI_NOTIFICATION_APPLICATION_QUIT = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x40, + _MALI_NOTIFICATION_SETTINGS_CHANGED = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x80, + + /** Fragment Processor notifications */ + + _MALI_NOTIFICATION_PP_FINISHED = (_MALI_UK_PP_SUBSYSTEM << 16) | 0x10, + _MALI_NOTIFICATION_PP_NUM_CORE_CHANGE = (_MALI_UK_PP_SUBSYSTEM << 16) | 0x20, + + /** Vertex Processor notifications */ + + _MALI_NOTIFICATION_GP_FINISHED = (_MALI_UK_GP_SUBSYSTEM << 16) | 0x10, + _MALI_NOTIFICATION_GP_STALLED = (_MALI_UK_GP_SUBSYSTEM << 16) | 0x20, + +} _mali_uk_notification_type; + +/** to assist in splitting up 32-bit notification value in subsystem and id value */ +#define _MALI_NOTIFICATION_SUBSYSTEM_MASK 0xFFFF0000 +#define _MALI_NOTIFICATION_SUBSYSTEM_SHIFT 16 +#define _MALI_NOTIFICATION_ID_MASK 0x0000FFFF +#define _MALI_NOTIFICATION_ID_SHIFT 0 + + +/** @brief Enumeration of possible settings which match mali_setting_t in user space + * + * + */ +typedef enum +{ + _MALI_UK_USER_SETTING_SW_EVENTS_ENABLE = 0, + _MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, + _MALI_UK_USER_SETTING_DEPTHBUFFER_CAPTURE_ENABLED, + _MALI_UK_USER_SETTING_STENCILBUFFER_CAPTURE_ENABLED, + _MALI_UK_USER_SETTING_PER_TILE_COUNTERS_CAPTURE_ENABLED, + _MALI_UK_USER_SETTING_BUFFER_CAPTURE_COMPOSITOR, + _MALI_UK_USER_SETTING_BUFFER_CAPTURE_WINDOW, + _MALI_UK_USER_SETTING_BUFFER_CAPTURE_OTHER, + _MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, + _MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, + _MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, + _MALI_UK_USER_SETTING_MAX, +} _mali_uk_user_setting_t; + +/* See mali_user_settings_db.c */ +extern const char *_mali_uk_user_setting_descriptions[]; +#define _MALI_UK_USER_SETTING_DESCRIPTIONS \ +{ \ + "sw_events_enable", \ + "colorbuffer_capture_enable", \ + "depthbuffer_capture_enable", \ + "stencilbuffer_capture_enable", \ + "per_tile_counters_enable", \ + "buffer_capture_compositor", \ + "buffer_capture_window", \ + "buffer_capture_other", \ + "buffer_capture_n_frames", \ + "buffer_capture_resize_factor", \ + "sw_counters_enable", \ +}; + +/** @brief struct to hold the value to a particular setting as seen in the kernel space + */ +typedef struct +{ + _mali_uk_user_setting_t setting; + u32 value; +} _mali_uk_settings_changed_s; + +/** @brief Arguments for _mali_ukk_wait_for_notification() + * + * On successful return from _mali_ukk_wait_for_notification(), the members of + * this structure will indicate the reason for notification. + * + * Specifically, the source of the notification can be identified by the + * subsystem and id fields of the mali_uk_notification_type in the code.type + * member. The type member is encoded in a way to divide up the types into a + * subsystem field, and a per-subsystem ID field. See + * _mali_uk_notification_type for more information. + * + * Interpreting the data union member depends on the notification type: + * + * - type == _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS + * - The kernel side is shutting down. No further + * _mali_uk_wait_for_notification() calls should be made. + * - In this case, the value of the data union member is undefined. + * - This is used to indicate to the user space client that it should close + * the connection to the Mali Device Driver. + * - type == _MALI_NOTIFICATION_PP_FINISHED + * - The notification data is of type _mali_uk_pp_job_finished_s. It contains the user_job_ptr + * identifier used to start the job with, the job status, the number of milliseconds the job took to render, + * and values of core registers when the job finished (irq status, performance counters, renderer list + * address). + * - A job has finished succesfully when its status member is _MALI_UK_JOB_STATUS_FINISHED. + * - If the hardware detected a timeout while rendering the job, or software detected the job is + * taking more than watchdog_msecs (see _mali_ukk_pp_start_job()) to complete, the status member will + * indicate _MALI_UK_JOB_STATUS_HANG. + * - If the hardware detected a bus error while accessing memory associated with the job, status will + * indicate _MALI_UK_JOB_STATUS_SEG_FAULT. + * - Status will indicate MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to stop the job but the job + * didn't start the hardware yet, e.g. when the driver closes. + * - type == _MALI_NOTIFICATION_GP_FINISHED + * - The notification data is of type _mali_uk_gp_job_finished_s. The notification is similar to that of + * type == _MALI_NOTIFICATION_PP_FINISHED, except that several other GP core register values are returned. + * The status values have the same meaning for type == _MALI_NOTIFICATION_PP_FINISHED. + * - type == _MALI_NOTIFICATION_GP_STALLED + * - The nofication data is of type _mali_uk_gp_job_suspended_s. It contains the user_job_ptr + * identifier used to start the job with, the reason why the job stalled and a cookie to identify the core on + * which the job stalled. + * - The reason member of gp_job_suspended is set to _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY + * when the polygon list builder unit has run out of memory. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_notification_type type; /**< [out] Type of notification available */ + union + { + _mali_uk_gp_job_suspended_s gp_job_suspended;/**< [out] Notification data for _MALI_NOTIFICATION_GP_STALLED notification type */ + _mali_uk_gp_job_finished_s gp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_GP_FINISHED notification type */ + _mali_uk_pp_job_finished_s pp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_PP_FINISHED notification type */ + _mali_uk_settings_changed_s setting_changed;/**< [out] Notification data for _MALI_NOTIFICAATION_SETTINGS_CHANGED notification type */ + } data; +} _mali_uk_wait_for_notification_s; + +/** @brief Arguments for _mali_ukk_post_notification() + * + * Posts the specified notification to the notification queue for this application. + * This is used to send a quit message to the callback thread. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_notification_type type; /**< [in] Type of notification to post */ +} _mali_uk_post_notification_s; + +/** @} */ /* end group _mali_uk_waitfornotification_s */ + +/** @defgroup _mali_uk_getapiversion_s Get API Version + * @{ */ + +/** helpers for Device Driver API version handling */ + +/** @brief Encode a version ID from a 16-bit input + * + * @note the input is assumed to be 16 bits. It must not exceed 16 bits. */ +#define _MAKE_VERSION_ID(x) (((x) << 16UL) | (x)) + +/** @brief Check whether a 32-bit value is likely to be Device Driver API + * version ID. */ +#define _IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF)) + +/** @brief Decode a 16-bit version number from a 32-bit Device Driver API version + * ID */ +#define _GET_VERSION(x) (((x) >> 16UL) & 0xFFFF) + +/** @brief Determine whether two 32-bit encoded version IDs match */ +#define _IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y)))) + +/** + * API version define. + * Indicates the version of the kernel API + * The version is a 16bit integer incremented on each API change. + * The 16bit integer is stored twice in a 32bit integer + * For example, for version 1 the value would be 0x00010001 + */ +#define _MALI_API_VERSION 23 +#define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION) + +/** + * The API version is a 16-bit integer stored in both the lower and upper 16-bits + * of a 32-bit value. The 16-bit API version value is incremented on each API + * change. Version 1 would be 0x00010001. Used in _mali_uk_get_api_version_s. + */ +typedef u32 _mali_uk_api_version; + +/** @brief Arguments for _mali_uk_get_api_version() + * + * The user-side interface version must be written into the version member, + * encoded using _MAKE_VERSION_ID(). It will be compared to the API version of + * the kernel-side interface. + * + * On successful return, the version member will be the API version of the + * kernel-side interface. _MALI_UK_API_VERSION macro defines the current version + * of the API. + * + * The compatible member must be checked to see if the version of the user-side + * interface is compatible with the kernel-side interface, since future versions + * of the interface may be backwards compatible. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_api_version version; /**< [in,out] API version of user-side interface. */ + int compatible; /**< [out] @c 1 when @version is compatible, @c 0 otherwise */ +} _mali_uk_get_api_version_s; +/** @} */ /* end group _mali_uk_getapiversion_s */ + +/** @defgroup _mali_uk_get_user_settings_s Get user space settings */ + +/** @brief struct to keep the matching values of the user space settings within certain context + * + * Each member of the settings array corresponds to a matching setting in the user space and its value is the value + * of that particular setting. + * + * All settings are given reference to the context pointed to by the ctx pointer. + * + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 settings[_MALI_UK_USER_SETTING_MAX]; /**< [out] The values for all settings */ +} _mali_uk_get_user_settings_s; + +/** @brief struct to hold the value of a particular setting from the user space within a given context + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_user_setting_t setting; /**< [in] setting to get */ + u32 value; /**< [out] value of setting */ +} _mali_uk_get_user_setting_s; + +/** @} */ /* end group _mali_uk_core */ + + +/** @defgroup _mali_uk_memory U/K Memory + * @{ */ + +/** @brief Arguments for _mali_ukk_init_mem(). */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 mali_address_base; /**< [out] start of MALI address space */ + u32 memory_size; /**< [out] total MALI address space available */ +} _mali_uk_init_mem_s; + +/** @brief Arguments for _mali_ukk_term_mem(). */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ +} _mali_uk_term_mem_s; + +/** Flag for _mali_uk_map_external_mem_s, _mali_uk_attach_ump_mem_s and _mali_uk_attach_dma_buf_s */ +#define _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE (1<<0) + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 phys_addr; /**< [in] physical address */ + u32 size; /**< [in] size */ + u32 mali_address; /**< [in] mali address to map the physical memory to */ + u32 rights; /**< [in] rights necessary for accessing memory */ + u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */ + u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ +} _mali_uk_map_external_mem_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ +} _mali_uk_unmap_external_mem_s; + +/** @note This is identical to _mali_uk_map_external_mem_s above, however phys_addr is replaced by memory descriptor */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 mem_fd; /**< [in] Memory descriptor */ + u32 size; /**< [in] size */ + u32 mali_address; /**< [in] mali address to map the physical memory to */ + u32 rights; /**< [in] rights necessary for accessing memory */ + u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */ + u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ +} _mali_uk_attach_dma_buf_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 mem_fd; /**< [in] Memory descriptor */ + u32 size; /**< [out] size */ +} _mali_uk_dma_buf_get_size_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 cookie; /**< [in] identifier for mapped memory object in kernel space */ +} _mali_uk_release_dma_buf_s; + +/** @note This is identical to _mali_uk_map_external_mem_s above, however phys_addr is replaced by secure_id */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< [in] secure id */ + u32 size; /**< [in] size */ + u32 mali_address; /**< [in] mali address to map the physical memory to */ + u32 rights; /**< [in] rights necessary for accessing memory */ + u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */ + u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ +} _mali_uk_attach_ump_mem_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 cookie; /**< [in] identifier for mapped memory object in kernel space */ +} _mali_uk_release_ump_mem_s; + +/** @brief Arguments for _mali_ukk_va_to_mali_pa() + * + * if size is zero or not a multiple of the system's page size, it will be + * rounded up to the next multiple of the page size. This will occur before + * any other use of the size parameter. + * + * if va is not PAGE_SIZE aligned, it will be rounded down to the next page + * boundary. + * + * The range (va) to ((u32)va)+(size-1) inclusive will be checked for physical + * contiguity. + * + * The implementor will check that the entire physical range is allowed to be mapped + * into user-space. + * + * Failure will occur if either of the above are not satisfied. + * + * Otherwise, the physical base address of the range is returned through pa, + * va is updated to be page aligned, and size is updated to be a non-zero + * multiple of the system's pagesize. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *va; /**< [in,out] Virtual address of the start of the range */ + u32 pa; /**< [out] Physical base address of the range */ + u32 size; /**< [in,out] Size of the range, in bytes. */ +} _mali_uk_va_to_mali_pa_s; + +/** + * @brief Arguments for _mali_uk[uk]_mem_write_safe() + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + const void *src; /**< [in] Pointer to source data */ + void *dest; /**< [in] Destination Mali buffer */ + u32 size; /**< [in,out] Number of bytes to write/copy on input, number of bytes actually written/copied on output */ +} _mali_uk_mem_write_safe_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 size; /**< [out] size of MMU page table information (registers + page tables) */ +} _mali_uk_query_mmu_page_table_dump_size_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 size; /**< [in] size of buffer to receive mmu page table information */ + void *buffer; /**< [in,out] buffer to receive mmu page table information */ + u32 register_writes_size; /**< [out] size of MMU register dump */ + u32 *register_writes; /**< [out] pointer within buffer where MMU register dump is stored */ + u32 page_table_dump_size; /**< [out] size of MMU page table dump */ + u32 *page_table_dump; /**< [out] pointer within buffer where MMU page table dump is stored */ +} _mali_uk_dump_mmu_page_table_s; + +/** @} */ /* end group _mali_uk_memory */ + + +/** @addtogroup _mali_uk_pp U/K Fragment Processor + * @{ */ + +/** @brief Arguments for _mali_ukk_get_pp_number_of_cores() + * + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * - Upon successful return from _mali_ukk_get_pp_number_of_cores(), @c number_of_cores + * will contain the number of Fragment Processor cores in the system. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 number_of_total_cores; /**< [out] Total number of Fragment Processor cores in the system */ + u32 number_of_enabled_cores; /**< [out] Number of enabled Fragment Processor cores */ +} _mali_uk_get_pp_number_of_cores_s; + +/** @brief Arguments for _mali_ukk_get_pp_core_version() + * + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * - Upon successful return from _mali_ukk_get_pp_core_version(), @c version contains + * the version that all Fragment Processor cores are compatible with. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_core_version version; /**< [out] version returned from core, see \ref _mali_core_version */ +} _mali_uk_get_pp_core_version_s; + +/** @} */ /* end group _mali_uk_pp */ + + +/** @addtogroup _mali_uk_gp U/K Vertex Processor + * @{ */ + +/** @brief Arguments for _mali_ukk_get_gp_number_of_cores() + * + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * - Upon successful return from _mali_ukk_get_gp_number_of_cores(), @c number_of_cores + * will contain the number of Vertex Processor cores in the system. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 number_of_cores; /**< [out] number of Vertex Processor cores in the system */ +} _mali_uk_get_gp_number_of_cores_s; + +/** @brief Arguments for _mali_ukk_get_gp_core_version() + * + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * - Upon successful return from _mali_ukk_get_gp_core_version(), @c version contains + * the version that all Vertex Processor cores are compatible with. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_core_version version; /**< [out] version returned from core, see \ref _mali_core_version */ +} _mali_uk_get_gp_core_version_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 limit; /**< [in,out] The desired limit for number of events to record on input, actual limit on output */ +} _mali_uk_profiling_start_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 event_id; /**< [in] event id to register (see enum mali_profiling_events for values) */ + u32 data[5]; /**< [in] event specific data */ +} _mali_uk_profiling_add_event_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 count; /**< [out] The number of events sampled */ +} _mali_uk_profiling_stop_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 index; /**< [in] which index to get (starting at zero) */ + u64 timestamp; /**< [out] timestamp of event */ + u32 event_id; /**< [out] event id of event (see enum mali_profiling_events for values) */ + u32 data[5]; /**< [out] event specific data */ +} _mali_uk_profiling_get_event_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ +} _mali_uk_profiling_clear_s; + +/** @} */ /* end group _mali_uk_gp */ + + +/** @addtogroup _mali_uk_memory U/K Memory + * @{ */ + +/** @brief Arguments to _mali_ukk_mem_mmap() + * + * Use of the phys_addr member depends on whether the driver is compiled for + * Mali-MMU or nonMMU: + * - in the nonMMU case, this is the physical address of the memory as seen by + * the CPU (which may be a constant offset from that used by Mali) + * - in the MMU case, this is the Mali Virtual base address of the memory to + * allocate, and the particular physical pages used to back the memory are + * entirely determined by _mali_ukk_mem_mmap(). The details of the physical pages + * are not reported to user-space for security reasons. + * + * The cookie member must be stored for use later when freeing the memory by + * calling _mali_ukk_mem_munmap(). In the Mali-MMU case, the cookie is secure. + * + * The ukk_private word must be set to zero when calling from user-space. On + * Kernel-side, the OS implementation of the U/K interface can use it to + * communicate data to the OS implementation of the OSK layer. In particular, + * _mali_ukk_get_big_block() directly calls _mali_ukk_mem_mmap directly, and + * will communicate its own ukk_private word through the ukk_private member + * here. The common code itself will not inspect or modify the ukk_private + * word, and so it may be safely used for whatever purposes necessary to + * integrate Mali Memory handling into the OS. + * + * The uku_private member is currently reserved for use by the user-side + * implementation of the U/K interface. Its value must be zero. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *mapping; /**< [out] Returns user-space virtual address for the mapping */ + u32 size; /**< [in] Size of the requested mapping */ + u32 phys_addr; /**< [in] Physical address - could be offset, depending on caller+callee convention */ + u32 cookie; /**< [out] Returns a cookie for use in munmap calls */ + void *uku_private; /**< [in] User-side Private word used by U/K interface */ + void *ukk_private; /**< [in] Kernel-side Private word used by U/K interface */ + mali_memory_cache_settings cache_settings; /**< [in] Option to set special cache flags, tuning L2 efficency */ +} _mali_uk_mem_mmap_s; + +/** @brief Arguments to _mali_ukk_mem_munmap() + * + * The cookie and mapping members must be that returned from the same previous + * call to _mali_ukk_mem_mmap(). The size member must correspond to cookie + * and mapping - that is, it must be the value originally supplied to a call to + * _mali_ukk_mem_mmap that returned the values of mapping and cookie. + * + * An error will be returned if an attempt is made to unmap only part of the + * originally obtained range, or to unmap more than was originally obtained. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *mapping; /**< [in] The mapping returned from mmap call */ + u32 size; /**< [in] The size passed to mmap call */ + u32 cookie; /**< [in] Cookie from mmap call */ +} _mali_uk_mem_munmap_s; +/** @} */ /* end group _mali_uk_memory */ + +/** @defgroup _mali_uk_vsync U/K VSYNC Wait Reporting Module + * @{ */ + +/** @brief VSYNC events + * + * These events are reported when DDK starts to wait for vsync and when the + * vsync has occured and the DDK can continue on the next frame. + */ +typedef enum _mali_uk_vsync_event +{ + _MALI_UK_VSYNC_EVENT_BEGIN_WAIT = 0, + _MALI_UK_VSYNC_EVENT_END_WAIT +} _mali_uk_vsync_event; + +/** @brief Arguments to _mali_ukk_vsync_event() + * + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_vsync_event event; /**< [in] VSYNCH event type */ +} _mali_uk_vsync_event_report_s; + +/** @} */ /* end group _mali_uk_vsync */ + +/** @defgroup _mali_uk_sw_counters_report U/K Software Counter Reporting + * @{ */ + +/** @brief Software counter values + * + * Values recorded for each of the software counters during a single renderpass. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32* counters; /**< [in] The array of counter values */ + u32 num_counters; /**< [in] The number of elements in counters array */ +} _mali_uk_sw_counters_report_s; + +/** @} */ /* end group _mali_uk_sw_counters_report */ + +/** @defgroup _mali_uk_stream U/K Mali stream module + * @{ */ + +/** @brief Create stream + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + int fd; /**< [out] file descriptor describing stream */ +} _mali_uk_stream_create_s; + +/** @brief Destroy stream +*/ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + int fd; /**< [in] file descriptor describing stream */ +} _mali_uk_stream_destroy_s; + +/** @brief Create empty fence + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + s32 stream; /**< [in] stream to create fence on */ + s32 fence; /**< [out] file descriptor describing fence */ +} _mali_uk_fence_create_empty_s; + +/** @brief Check fence validity + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + int fd; /**< [in] file descriptor describing fence */ +} _mali_uk_fence_validate_s; + +/** @} */ /* end group _mali_uk_stream */ + +/** @} */ /* end group u_k_api */ + +/** @} */ /* end group uddapi */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_UTGARD_UK_TYPES_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/license/gpl/mali_kernel_license.h b/drivers/gpu/mali400/r3p2/mali/linux/license/gpl/mali_kernel_license.h new file mode 100644 index 0000000..e9e5e55 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/license/gpl/mali_kernel_license.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_kernel_license.h + * Defines for the macro MODULE_LICENSE. + */ + +#ifndef __MALI_KERNEL_LICENSE_H__ +#define __MALI_KERNEL_LICENSE_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MALI_KERNEL_LINUX_LICENSE "GPL" +#define MALI_LICENSE_IS_GPL 1 + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_KERNEL_LICENSE_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_device_pause_resume.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_device_pause_resume.c new file mode 100644 index 0000000..0b82cba --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_device_pause_resume.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_device_pause_resume.c + * Implementation of the Mali pause/resume functionality + */ + +#include +#include +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" + +void mali_dev_pause(void) +{ + mali_gp_scheduler_suspend(); + mali_pp_scheduler_suspend(); +} + +EXPORT_SYMBOL(mali_dev_pause); + +void mali_dev_resume(void) +{ + mali_gp_scheduler_resume(); + mali_pp_scheduler_resume(); +} + +EXPORT_SYMBOL(mali_dev_resume); diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.c new file mode 100644 index 0000000..c34b2c6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.c @@ -0,0 +1,480 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include /* file system operations */ +#include /* user space access */ +#include +#include +#include +#include +#include +#include +#include + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_kernel_linux.h" + +#include "mali_kernel_memory_engine.h" +#include "mali_memory.h" +#include "mali_dma_buf.h" + + +struct mali_dma_buf_attachment { + struct dma_buf *buf; + struct dma_buf_attachment *attachment; + struct sg_table *sgt; + struct mali_session_data *session; + int map_ref; + struct mutex map_lock; + mali_bool is_mapped; + wait_queue_head_t wait_queue; +}; + +void mali_dma_buf_release(void *ctx, void *handle) +{ + struct mali_dma_buf_attachment *mem; + + mem = (struct mali_dma_buf_attachment *)handle; + + MALI_DEBUG_PRINT(3, ("Mali DMA-buf: release attachment %p\n", mem)); + + MALI_DEBUG_ASSERT_POINTER(mem); + MALI_DEBUG_ASSERT_POINTER(mem->attachment); + MALI_DEBUG_ASSERT_POINTER(mem->buf); + +#if defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + /* We mapped implicitly on attach, so we need to unmap on release */ + mali_dma_buf_unmap(mem); +#endif + + /* Wait for buffer to become unmapped */ + wait_event(mem->wait_queue, !mem->is_mapped); + MALI_DEBUG_ASSERT(!mem->is_mapped); + + dma_buf_detach(mem->buf, mem->attachment); + dma_buf_put(mem->buf); + + _mali_osk_free(mem); +} + +/* + * Map DMA buf attachment \a mem into \a session at virtual address \a virt. + */ +int mali_dma_buf_map(struct mali_dma_buf_attachment *mem, struct mali_session_data *session, u32 virt, u32 *offset, u32 flags) +{ + struct mali_page_directory *pagedir; + struct scatterlist *sg; + int i; + + MALI_DEBUG_ASSERT_POINTER(mem); + MALI_DEBUG_ASSERT_POINTER(session); + MALI_DEBUG_ASSERT(mem->session == session); + + mutex_lock(&mem->map_lock); + + mem->map_ref++; + + MALI_DEBUG_PRINT(5, ("Mali DMA-buf: map attachment %p, new map_ref = %d\n", mem, mem->map_ref)); + + if (1 == mem->map_ref) + { + /* First reference taken, so we need to map the dma buf */ + MALI_DEBUG_ASSERT(!mem->is_mapped); + + pagedir = mali_session_get_page_directory(session); + MALI_DEBUG_ASSERT_POINTER(pagedir); + + mem->sgt = dma_buf_map_attachment(mem->attachment, DMA_BIDIRECTIONAL); + if (IS_ERR_OR_NULL(mem->sgt)) + { + MALI_DEBUG_PRINT_ERROR(("Failed to map dma-buf attachment\n")); + return -EFAULT; + } + + for_each_sg(mem->sgt->sgl, sg, mem->sgt->nents, i) + { + u32 size = sg_dma_len(sg); + dma_addr_t phys = sg_dma_address(sg); + + /* sg must be page aligned. */ + MALI_DEBUG_ASSERT(0 == size % MALI_MMU_PAGE_SIZE); + + mali_mmu_pagedir_update(pagedir, virt, phys, size, MALI_CACHE_STANDARD); + + virt += size; + *offset += size; + } + + if (flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) + { + u32 guard_phys; + MALI_DEBUG_PRINT(7, ("Mapping in extra guard page\n")); + + guard_phys = sg_dma_address(mem->sgt->sgl); + mali_mmu_pagedir_update(pagedir, virt, guard_phys, MALI_MMU_PAGE_SIZE, MALI_CACHE_STANDARD); + } + + mem->is_mapped = MALI_TRUE; + mutex_unlock(&mem->map_lock); + + /* Wake up any thread waiting for buffer to become mapped */ + wake_up_all(&mem->wait_queue); + } + else + { + MALI_DEBUG_ASSERT(mem->is_mapped); + mutex_unlock(&mem->map_lock); + } + + return 0; +} + +void mali_dma_buf_unmap(struct mali_dma_buf_attachment *mem) +{ + MALI_DEBUG_ASSERT_POINTER(mem); + MALI_DEBUG_ASSERT_POINTER(mem->attachment); + MALI_DEBUG_ASSERT_POINTER(mem->buf); + + mutex_lock(&mem->map_lock); + + mem->map_ref--; + + MALI_DEBUG_PRINT(5, ("Mali DMA-buf: unmap attachment %p, new map_ref = %d\n", mem, mem->map_ref)); + + if (0 == mem->map_ref) + { + dma_buf_unmap_attachment(mem->attachment, mem->sgt, DMA_BIDIRECTIONAL); + + mem->is_mapped = MALI_FALSE; + } + + mutex_unlock(&mem->map_lock); + + /* Wake up any thread waiting for buffer to become unmapped */ + wake_up_all(&mem->wait_queue); +} + +#if !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) +int mali_dma_buf_map_job(struct mali_pp_job *job) +{ + mali_memory_allocation *descriptor; + struct mali_dma_buf_attachment *mem; + _mali_osk_errcode_t err; + int i; + u32 offset = 0; + int ret = 0; + + _mali_osk_lock_wait( job->session->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + for (i = 0; i < job->num_memory_cookies; i++) + { + int cookie = job->memory_cookies[i]; + + if (0 == cookie) + { + /* 0 is not a valid cookie */ + MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]); + continue; + } + + MALI_DEBUG_ASSERT(0 < cookie); + + err = mali_descriptor_mapping_get(job->session->descriptor_mapping, + cookie, (void**)&descriptor); + + if (_MALI_OSK_ERR_OK != err) + { + MALI_DEBUG_PRINT_ERROR(("Mali DMA-buf: Failed to get descriptor for cookie %d\n", cookie)); + ret = -EFAULT; + MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]); + continue; + } + + if (mali_dma_buf_release != descriptor->physical_allocation.release) + { + /* Not a DMA-buf */ + MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]); + continue; + } + + mem = (struct mali_dma_buf_attachment *)descriptor->physical_allocation.handle; + + MALI_DEBUG_ASSERT_POINTER(mem); + MALI_DEBUG_ASSERT(mem->session == job->session); + + err = mali_dma_buf_map(mem, mem->session, descriptor->mali_address, &offset, descriptor->flags); + if (0 != err) + { + MALI_DEBUG_PRINT_ERROR(("Mali DMA-buf: Failed to map dma-buf for cookie %d at mali address %x\b", + cookie, descriptor->mali_address)); + ret = -EFAULT; + MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]); + continue; + } + + /* Add mem to list of DMA-bufs mapped for this job */ + job->dma_bufs[i] = mem; + } + + _mali_osk_lock_signal( job->session->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + return ret; +} + +void mali_dma_buf_unmap_job(struct mali_pp_job *job) +{ + int i; + for (i = 0; i < job->num_dma_bufs; i++) + { + if (NULL == job->dma_bufs[i]) continue; + + mali_dma_buf_unmap(job->dma_bufs[i]); + job->dma_bufs[i] = NULL; + } +} +#endif /* !CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH */ + +/* Callback from memory engine which will map into Mali virtual address space */ +static mali_physical_memory_allocation_result mali_dma_buf_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + struct mali_session_data *session; + struct mali_dma_buf_attachment *mem; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(offset); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + /* Mapping dma-buf with an offset is not supported. */ + MALI_DEBUG_ASSERT(0 == *offset); + + session = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + MALI_DEBUG_ASSERT_POINTER(session); + + mem = (struct mali_dma_buf_attachment *)ctx; + + MALI_DEBUG_ASSERT(mem->session == session); + +#if defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + if (0 == mali_dma_buf_map(mem, session, descriptor->mali_address, offset, descriptor->flags)) + { + MALI_DEBUG_ASSERT(*offset == descriptor->size); +#else + { +#endif + alloc_info->ctx = NULL; + alloc_info->handle = mem; + alloc_info->next = NULL; + alloc_info->release = mali_dma_buf_release; + + return MALI_MEM_ALLOC_FINISHED; + } + + return MALI_MEM_ALLOC_INTERNAL_FAILURE; +} + +int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *user_arg) +{ + mali_physical_memory_allocator external_memory_allocator; + struct dma_buf *buf; + struct mali_dma_buf_attachment *mem; + _mali_uk_attach_dma_buf_s args; + mali_memory_allocation *descriptor; + int md; + int fd; + + /* Get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if (0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_attach_dma_buf_s))) + { + return -EFAULT; + } + + fd = args.mem_fd; + + buf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(buf)) + { + MALI_DEBUG_PRINT_ERROR(("Failed to get dma-buf from fd: %d\n", fd)); + return PTR_RET(buf); + } + + /* Currently, mapping of the full buffer are supported. */ + if (args.size != buf->size) + { + MALI_DEBUG_PRINT_ERROR(("dma-buf size doesn't match mapping size.\n")); + dma_buf_put(buf); + return -EINVAL; + } + + mem = _mali_osk_calloc(1, sizeof(struct mali_dma_buf_attachment)); + if (NULL == mem) + { + MALI_DEBUG_PRINT_ERROR(("Failed to allocate dma-buf tracing struct\n")); + dma_buf_put(buf); + return -ENOMEM; + } + + mem->buf = buf; + mem->session = session; + mem->map_ref = 0; + mutex_init(&mem->map_lock); + init_waitqueue_head(&mem->wait_queue); + + mem->attachment = dma_buf_attach(mem->buf, &mali_platform_device->dev); + if (NULL == mem->attachment) + { + MALI_DEBUG_PRINT_ERROR(("Failed to attach to dma-buf %d\n", fd)); + dma_buf_put(mem->buf); + _mali_osk_free(mem); + return -EFAULT; + } + + /* Map dma-buf into this session's page tables */ + + /* Set up Mali memory descriptor */ + descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); + if (NULL == descriptor) + { + MALI_DEBUG_PRINT_ERROR(("Failed to allocate descriptor dma-buf %d\n", fd)); + mali_dma_buf_release(NULL, mem); + return -ENOMEM; + } + + descriptor->size = args.size; + descriptor->mapping = NULL; + descriptor->mali_address = args.mali_address; + descriptor->mali_addr_mapping_info = (void*)session; + descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ + descriptor->lock = session->memory_lock; + + if (args.flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) + { + descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; + } + _mali_osk_list_init( &descriptor->list ); + + /* Get descriptor mapping for memory. */ + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &md)) + { + MALI_DEBUG_PRINT_ERROR(("Failed to create descriptor mapping for dma-buf %d\n", fd)); + _mali_osk_free(descriptor); + mali_dma_buf_release(NULL, mem); + return -EFAULT; + } + + MALI_DEBUG_ASSERT(0 < md); + + external_memory_allocator.allocate = mali_dma_buf_commit; + external_memory_allocator.allocate_page_table_block = NULL; + external_memory_allocator.ctx = mem; + external_memory_allocator.name = "DMA-BUF Memory"; + external_memory_allocator.next = NULL; + + /* Map memory into session's Mali virtual address space. */ + _mali_osk_lock_wait(session->memory_lock, _MALI_OSK_LOCKMODE_RW); + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(mali_mem_get_memory_engine(), descriptor, &external_memory_allocator, NULL)) + { + _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); + + MALI_DEBUG_PRINT_ERROR(("Failed to map dma-buf %d into Mali address space\n", fd)); + mali_descriptor_mapping_free(session->descriptor_mapping, md); + mali_dma_buf_release(NULL, mem); + return -ENOMEM; + } + _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); + + /* Return stuff to user space */ + if (0 != put_user(md, &user_arg->cookie)) + { + /* Roll back */ + MALI_DEBUG_PRINT_ERROR(("Failed to return descriptor to user space for dma-buf %d\n", fd)); + mali_descriptor_mapping_free(session->descriptor_mapping, md); + mali_dma_buf_release(NULL, mem); + return -EFAULT; + } + + return 0; +} + +int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *user_arg) +{ + int ret = 0; + _mali_uk_release_dma_buf_s args; + mali_memory_allocation *descriptor; + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_release_dma_buf_s)) ) + { + return -EFAULT; + } + + MALI_DEBUG_PRINT(3, ("Mali DMA-buf: release descriptor cookie %d\n", args.cookie)); + + _mali_osk_lock_wait( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + descriptor = mali_descriptor_mapping_free(session->descriptor_mapping, args.cookie); + + if (NULL != descriptor) + { + MALI_DEBUG_PRINT(3, ("Mali DMA-buf: Releasing dma-buf at mali address %x\n", descriptor->mali_address)); + + /* Will call back to mali_dma_buf_release() which will release the dma-buf attachment. */ + mali_allocation_engine_release_memory(mali_mem_get_memory_engine(), descriptor); + + _mali_osk_free(descriptor); + } + else + { + MALI_DEBUG_PRINT_ERROR(("Invalid memory descriptor %d used to release dma-buf\n", args.cookie)); + ret = -EINVAL; + } + + _mali_osk_lock_signal( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + /* Return the error that _mali_ukk_map_external_ump_mem produced */ + return ret; +} + +int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *user_arg) +{ + _mali_uk_dma_buf_get_size_s args; + int fd; + struct dma_buf *buf; + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_dma_buf_get_size_s)) ) + { + return -EFAULT; + } + + /* Do DMA-BUF stuff */ + fd = args.mem_fd; + + buf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(buf)) + { + MALI_DEBUG_PRINT_ERROR(("Failed to get dma-buf from fd: %d\n", fd)); + return PTR_RET(buf); + } + + if (0 != put_user(buf->size, &user_arg->size)) + { + dma_buf_put(buf); + return -EFAULT; + } + + dma_buf_put(buf); + + return 0; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.h new file mode 100644 index 0000000..1af3efc --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_DMA_BUF_H__ +#define __MALI_DMA_BUF_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mali_osk.h" +#include "common/mali_pp_job.h" + +struct mali_dma_buf_attachment; + +int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *arg); +int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *arg); +int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *arg); +int mali_dma_buf_map(struct mali_dma_buf_attachment *mem, struct mali_session_data *session, u32 virt, u32 *offset, u32 flags); +void mali_dma_buf_unmap(struct mali_dma_buf_attachment *mem); +void mali_dma_buf_release(void *ctx, void *handle); + +#if !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) +int mali_dma_buf_map_job(struct mali_pp_job *job); +void mali_dma_buf_unmap_job(struct mali_pp_job *job); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_KERNEL_LINUX_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.c new file mode 100644 index 0000000..f337d09 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.c @@ -0,0 +1,730 @@ +/** + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_kernel_linux.c + * Implementation of the Linux device driver entrypoints + */ +#include /* kernel module definitions */ +#include /* file system operations */ +#include /* character device definitions */ +#include /* memory manager definitions */ +#include +#include +#include +#include "mali_kernel_license.h" +#include +#include +#include +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_kernel_core.h" +#include "mali_osk.h" +#include "mali_kernel_linux.h" +#include "mali_ukk.h" +#include "mali_ukk_wrappers.h" +#include "mali_kernel_sysfs.h" +#include "mali_pm.h" +#include "mali_kernel_license.h" +#include "mali_dma_buf.h" +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) +#include "mali_profiling_internal.h" +#endif +/* MALI_SEC */ +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) || defined(CONFIG_CPU_EXYNOS4210) +#include "../platform/pegasus-m400/exynos4_pmm.h" +#elif defined(CONFIG_SOC_EXYNOS3470) +#include "../platform/exynos4270/exynos4_pmm.h" +#endif + +/* Streamline support for the Mali driver */ +#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_MALI400_PROFILING) +/* Ask Linux to create the tracepoints */ +#define CREATE_TRACE_POINTS +#include "mali_linux_trace.h" +#endif /* CONFIG_TRACEPOINTS */ + +/* from the __malidrv_build_info.c file that is generated during build */ +extern const char *__malidrv_build_info(void); + +/* Module parameter to control log level */ +int mali_debug_level = 2; +module_param(mali_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(mali_debug_level, "Higher number, more dmesg output"); + +module_param(mali_max_job_runtime, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_max_job_runtime, "Maximum allowed job runtime in msecs.\nJobs will be killed after this no matter what"); + +extern int mali_l2_max_reads; +module_param(mali_l2_max_reads, int, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_l2_max_reads, "Maximum reads for Mali L2 cache"); + +extern unsigned int mali_dedicated_mem_start; +module_param(mali_dedicated_mem_start, uint, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_dedicated_mem_start, "Physical start address of dedicated Mali GPU memory."); + +extern unsigned int mali_dedicated_mem_size; +module_param(mali_dedicated_mem_size, uint, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_dedicated_mem_size, "Size of dedicated Mali GPU memory."); + +extern unsigned int mali_shared_mem_size; +module_param(mali_shared_mem_size, uint, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_shared_mem_size, "Size of shared Mali GPU memory."); + +#if defined(CONFIG_MALI400_PROFILING) +extern int mali_boot_profiling; +module_param(mali_boot_profiling, int, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_boot_profiling, "Start profiling as a part of Mali driver initialization"); +#endif + +extern int mali_max_pp_cores_group_1; +module_param(mali_max_pp_cores_group_1, int, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_max_pp_cores_group_1, "Limit the number of PP cores to use from first PP group."); + +extern int mali_max_pp_cores_group_2; +module_param(mali_max_pp_cores_group_2, int, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_max_pp_cores_group_2, "Limit the number of PP cores to use from second PP group (Mali-450 only)."); + +/* Export symbols from common code: mali_user_settings.c */ +#include "mali_user_settings_db.h" +EXPORT_SYMBOL(mali_set_user_setting); +EXPORT_SYMBOL(mali_get_user_setting); + +static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */ + +/* This driver only supports one Mali device, and this variable stores this single platform device */ +struct platform_device *mali_platform_device = NULL; + +/* This driver only supports one Mali device, and this variable stores the exposed misc device (/dev/mali) */ +static struct miscdevice mali_miscdevice = { 0, }; + +static int mali_miscdevice_register(struct platform_device *pdev); +static void mali_miscdevice_unregister(void); + +static int mali_open(struct inode *inode, struct file *filp); +static int mali_release(struct inode *inode, struct file *filp); +#ifdef HAVE_UNLOCKED_IOCTL +static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#endif +static int mali_mmap(struct file * filp, struct vm_area_struct * vma); + +static int mali_probe(struct platform_device *pdev); +static int mali_remove(struct platform_device *pdev); + +static int mali_driver_suspend_scheduler(struct device *dev); +static int mali_driver_resume_scheduler(struct device *dev); + +#ifdef CONFIG_PM_RUNTIME +static int mali_driver_runtime_suspend(struct device *dev); +static int mali_driver_runtime_resume(struct device *dev); +static int mali_driver_runtime_idle(struct device *dev); +#endif + +#if defined(MALI_FAKE_PLATFORM_DEVICE) +extern int mali_platform_device_register(void); +extern int mali_platform_device_unregister(void); +#endif + +/* Linux power management operations provided by the Mali device driver */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) +struct pm_ext_ops mali_dev_ext_pm_ops = +{ + .base = + { + .suspend = mali_driver_suspend_scheduler, + .resume = mali_driver_resume_scheduler, + .freeze = mali_driver_suspend_scheduler, + .thaw = mali_driver_resume_scheduler, + }, +}; +#else +static const struct dev_pm_ops mali_dev_pm_ops = +{ +#ifdef CONFIG_PM_RUNTIME + .runtime_suspend = mali_driver_runtime_suspend, + .runtime_resume = mali_driver_runtime_resume, + .runtime_idle = mali_driver_runtime_idle, +#endif + .suspend = mali_driver_suspend_scheduler, + .resume = mali_driver_resume_scheduler, + .freeze = mali_driver_suspend_scheduler, + .thaw = mali_driver_resume_scheduler, +}; +#endif + +/* The Mali device driver struct */ +static struct platform_driver mali_platform_driver = +{ + .probe = mali_probe, + .remove = mali_remove, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) + .pm = &mali_dev_ext_pm_ops, +#endif + .driver = + { + .name = "mali_dev", /* MALI_SEC MALI_GPU_NAME_UTGARD, */ + .owner = THIS_MODULE, + .bus = &platform_bus_type, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) + .pm = &mali_dev_pm_ops, +#endif + }, +}; + +/* Linux misc device operations (/dev/mali) */ +struct file_operations mali_fops = +{ + .owner = THIS_MODULE, + .open = mali_open, + .release = mali_release, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = mali_ioctl, +#else + .ioctl = mali_ioctl, +#endif + .mmap = mali_mmap +}; + +int mali_module_init(void) +{ + int err = 0; + + MALI_DEBUG_PRINT(2, ("Inserting Mali v%d device driver. \n",_MALI_API_VERSION)); + MALI_DEBUG_PRINT(2, ("Compiled: %s, time: %s.\n", __DATE__, __TIME__)); + MALI_DEBUG_PRINT(2, ("Driver revision: %s\n", SVN_REV_STRING)); + + /* Initialize module wide settings */ + mali_osk_low_level_mem_init(); + +#if defined(MALI_FAKE_PLATFORM_DEVICE) + MALI_DEBUG_PRINT(2, ("mali_module_init() registering device\n")); + err = mali_platform_device_register(); + if (0 != err) + { + return err; + } +#endif + + MALI_DEBUG_PRINT(2, ("mali_module_init() registering driver\n")); + + err = platform_driver_register(&mali_platform_driver); + + if (0 != err) + { + MALI_DEBUG_PRINT(2, ("mali_module_init() Failed to register driver (%d)\n", err)); +#if defined(MALI_FAKE_PLATFORM_DEVICE) + mali_platform_device_unregister(); +#endif + mali_platform_device = NULL; + return err; + } + +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) + err = _mali_internal_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE); + if (0 != err) + { + /* No biggie if we wheren't able to initialize the profiling */ + MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n")); + } +#endif + + MALI_PRINT(("Mali device driver loaded\n")); + + return 0; /* Success */ +} + +void mali_module_exit(void) +{ + MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n",_MALI_API_VERSION)); + + MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering driver\n")); + +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) + _mali_internal_profiling_term(); +#endif + + platform_driver_unregister(&mali_platform_driver); + +#if defined(MALI_FAKE_PLATFORM_DEVICE) + MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering device\n")); + mali_platform_device_unregister(); +#endif + + mali_osk_low_level_mem_term(); + + MALI_PRINT(("Mali device driver unloaded\n")); +} + +static int mali_probe(struct platform_device *pdev) +{ + int err; + + MALI_DEBUG_PRINT(2, ("mali_probe(): Called for platform device %s\n", pdev->name)); + + if (NULL != mali_platform_device) + { + /* Already connected to a device, return error */ + MALI_PRINT_ERROR(("mali_probe(): The Mali driver is already connected with a Mali device.")); + return -EEXIST; + } + + mali_platform_device = pdev; + + if (_MALI_OSK_ERR_OK == _mali_osk_wq_init()) + { + /* Initialize the Mali GPU HW specified by pdev */ + if (_MALI_OSK_ERR_OK == mali_initialize_subsystems()) + { + /* Register a misc device (so we are accessible from user space) */ + err = mali_miscdevice_register(pdev); + if (0 == err) + { + /* Setup sysfs entries */ + err = mali_sysfs_register(mali_dev_name); + if (0 == err) + { + MALI_DEBUG_PRINT(2, ("mali_probe(): Successfully initialized driver for platform device %s\n", pdev->name)); + return 0; + } + else + { + MALI_PRINT_ERROR(("mali_probe(): failed to register sysfs entries")); + } + mali_miscdevice_unregister(); + } + else + { + MALI_PRINT_ERROR(("mali_probe(): failed to register Mali misc device.")); + } + mali_terminate_subsystems(); + } + else + { + MALI_PRINT_ERROR(("mali_probe(): Failed to initialize Mali device driver.")); + } + _mali_osk_wq_term(); + } + + mali_platform_device = NULL; + return -EFAULT; +} + +static int mali_remove(struct platform_device *pdev) +{ + MALI_DEBUG_PRINT(2, ("mali_remove() called for platform device %s\n", pdev->name)); + mali_sysfs_unregister(); + mali_miscdevice_unregister(); + mali_terminate_subsystems(); + _mali_osk_wq_term(); + mali_platform_device = NULL; + return 0; +} + +static int mali_miscdevice_register(struct platform_device *pdev) +{ + int err; + + mali_miscdevice.minor = MISC_DYNAMIC_MINOR; + mali_miscdevice.name = mali_dev_name; + mali_miscdevice.fops = &mali_fops; + mali_miscdevice.parent = get_device(&pdev->dev); + + err = misc_register(&mali_miscdevice); + if (0 != err) + { + MALI_PRINT_ERROR(("Failed to register misc device, misc_register() returned %d\n", err)); + } + + return err; +} + +static void mali_miscdevice_unregister(void) +{ + misc_deregister(&mali_miscdevice); +} + +static int mali_driver_suspend_scheduler(struct device *dev) +{ + mali_pm_os_suspend(); + /* MALI_SEC */ + mali_platform_power_mode_change(dev, MALI_POWER_MODE_DEEP_SLEEP); + return 0; +} + +static int mali_driver_resume_scheduler(struct device *dev) +{ + /* MALI_SEC */ + mali_platform_power_mode_change(dev, MALI_POWER_MODE_ON); + mali_pm_os_resume(); + return 0; +} + +#ifdef CONFIG_PM_RUNTIME +static int mali_driver_runtime_suspend(struct device *dev) +{ + mali_pm_runtime_suspend(); + /* MALI_SEC */ + mali_platform_power_mode_change(dev, MALI_POWER_MODE_LIGHT_SLEEP); + return 0; +} + +static int mali_driver_runtime_resume(struct device *dev) +{ + /* MALI_SEC */ + mali_platform_power_mode_change(dev, MALI_POWER_MODE_ON); + mali_pm_runtime_resume(); + return 0; +} + +static int mali_driver_runtime_idle(struct device *dev) +{ + /* Nothing to do */ + return 0; +} +#endif + +/** @note munmap handler is done by vma close handler */ +static int mali_mmap(struct file * filp, struct vm_area_struct * vma) +{ + struct mali_session_data * session_data; + _mali_uk_mem_mmap_s args = {0, }; + + session_data = (struct mali_session_data *)filp->private_data; + if (NULL == session_data) + { + MALI_PRINT_ERROR(("mmap called without any session data available\n")); + return -EFAULT; + } + + MALI_DEBUG_PRINT(4, ("MMap() handler: start=0x%08X, phys=0x%08X, size=0x%08X vma->flags 0x%08x\n", (unsigned int)vma->vm_start, (unsigned int)(vma->vm_pgoff << PAGE_SHIFT), (unsigned int)(vma->vm_end - vma->vm_start), vma->vm_flags)); + + /* Re-pack the arguments that mmap() packed for us */ + args.ctx = session_data; + args.phys_addr = vma->vm_pgoff << PAGE_SHIFT; + args.size = vma->vm_end - vma->vm_start; + args.ukk_private = vma; + + if ( VM_SHARED== (VM_SHARED & vma->vm_flags)) + { + args.cache_settings = MALI_CACHE_STANDARD ; + MALI_DEBUG_PRINT(3,("Allocate - Standard - Size: %d kb\n", args.size/1024)); + } + else + { + args.cache_settings = MALI_CACHE_GP_READ_ALLOCATE; + MALI_DEBUG_PRINT(3,("Allocate - GP Cached - Size: %d kb\n", args.size/1024)); + } + /* Setting it equal to VM_SHARED and not Private, which would have made the later io_remap fail for MALI_CACHE_GP_READ_ALLOCATE */ + vma->vm_flags = 0x000000fb; + + /* Call the common mmap handler */ + MALI_CHECK(_MALI_OSK_ERR_OK ==_mali_ukk_mem_mmap( &args ), -EFAULT); + + return 0; +} + +static int mali_open(struct inode *inode, struct file *filp) +{ + struct mali_session_data * session_data; + _mali_osk_errcode_t err; + + /* input validation */ + if (mali_miscdevice.minor != iminor(inode)) + { + MALI_PRINT_ERROR(("mali_open() Minor does not match\n")); + return -ENODEV; + } + + /* allocated struct to track this session */ + err = _mali_ukk_open((void **)&session_data); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + /* initialize file pointer */ + filp->f_pos = 0; + + /* link in our session data */ + filp->private_data = (void*)session_data; + + return 0; +} + +static int mali_release(struct inode *inode, struct file *filp) +{ + _mali_osk_errcode_t err; + + /* input validation */ + if (mali_miscdevice.minor != iminor(inode)) + { + MALI_PRINT_ERROR(("mali_release() Minor does not match\n")); + return -ENODEV; + } + + err = _mali_ukk_close((void **)&filp->private_data); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + return 0; +} + +int map_errcode( _mali_osk_errcode_t err ) +{ + switch(err) + { + case _MALI_OSK_ERR_OK : return 0; + case _MALI_OSK_ERR_FAULT: return -EFAULT; + case _MALI_OSK_ERR_INVALID_FUNC: return -ENOTTY; + case _MALI_OSK_ERR_INVALID_ARGS: return -EINVAL; + case _MALI_OSK_ERR_NOMEM: return -ENOMEM; + case _MALI_OSK_ERR_TIMEOUT: return -ETIMEDOUT; + case _MALI_OSK_ERR_RESTARTSYSCALL: return -ERESTARTSYS; + case _MALI_OSK_ERR_ITEM_NOT_FOUND: return -ENOENT; + default: return -EFAULT; + } +} + +#ifdef HAVE_UNLOCKED_IOCTL +static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +#else +static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +#endif +{ + int err; + struct mali_session_data *session_data; + +#ifndef HAVE_UNLOCKED_IOCTL + /* inode not used */ + (void)inode; +#endif + + MALI_DEBUG_PRINT(7, ("Ioctl received 0x%08X 0x%08lX\n", cmd, arg)); + + session_data = (struct mali_session_data *)filp->private_data; + if (NULL == session_data) + { + MALI_DEBUG_PRINT(7, ("filp->private_data was NULL\n")); + return -ENOTTY; + } + + if (NULL == (void *)arg) + { + MALI_DEBUG_PRINT(7, ("arg was NULL\n")); + return -ENOTTY; + } + + switch(cmd) + { + case MALI_IOC_WAIT_FOR_NOTIFICATION: + err = wait_for_notification_wrapper(session_data, (_mali_uk_wait_for_notification_s __user *)arg); + break; + + case MALI_IOC_GET_API_VERSION: + err = get_api_version_wrapper(session_data, (_mali_uk_get_api_version_s __user *)arg); + break; + + case MALI_IOC_POST_NOTIFICATION: + err = post_notification_wrapper(session_data, (_mali_uk_post_notification_s __user *)arg); + break; + + case MALI_IOC_GET_USER_SETTINGS: + err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg); + break; + +#if defined(CONFIG_MALI400_PROFILING) + case MALI_IOC_PROFILING_START: + err = profiling_start_wrapper(session_data, (_mali_uk_profiling_start_s __user *)arg); + break; + + case MALI_IOC_PROFILING_ADD_EVENT: + err = profiling_add_event_wrapper(session_data, (_mali_uk_profiling_add_event_s __user *)arg); + break; + + case MALI_IOC_PROFILING_STOP: + err = profiling_stop_wrapper(session_data, (_mali_uk_profiling_stop_s __user *)arg); + break; + + case MALI_IOC_PROFILING_GET_EVENT: + err = profiling_get_event_wrapper(session_data, (_mali_uk_profiling_get_event_s __user *)arg); + break; + + case MALI_IOC_PROFILING_CLEAR: + err = profiling_clear_wrapper(session_data, (_mali_uk_profiling_clear_s __user *)arg); + break; + + case MALI_IOC_PROFILING_GET_CONFIG: + /* Deprecated: still compatible with get_user_settings */ + err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg); + break; + + case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: + err = profiling_report_sw_counters_wrapper(session_data, (_mali_uk_sw_counters_report_s __user *)arg); + break; + +#else + + case MALI_IOC_PROFILING_START: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_ADD_EVENT: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_STOP: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_GET_EVENT: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_CLEAR: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_GET_CONFIG: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: /* FALL-THROUGH */ + MALI_DEBUG_PRINT(2, ("Profiling not supported\n")); + err = -ENOTTY; + break; + +#endif + + case MALI_IOC_MEM_INIT: + err = mem_init_wrapper(session_data, (_mali_uk_init_mem_s __user *)arg); + break; + + case MALI_IOC_MEM_TERM: + err = mem_term_wrapper(session_data, (_mali_uk_term_mem_s __user *)arg); + break; + + case MALI_IOC_MEM_WRITE_SAFE: + err = mem_write_safe_wrapper(session_data, (_mali_uk_mem_write_safe_s __user *)arg); + break; + + case MALI_IOC_MEM_MAP_EXT: + err = mem_map_ext_wrapper(session_data, (_mali_uk_map_external_mem_s __user *)arg); + break; + + case MALI_IOC_MEM_UNMAP_EXT: + err = mem_unmap_ext_wrapper(session_data, (_mali_uk_unmap_external_mem_s __user *)arg); + break; + + case MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE: + err = mem_query_mmu_page_table_dump_size_wrapper(session_data, (_mali_uk_query_mmu_page_table_dump_size_s __user *)arg); + break; + + case MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE: + err = mem_dump_mmu_page_table_wrapper(session_data, (_mali_uk_dump_mmu_page_table_s __user *)arg); + break; + +#if defined(CONFIG_MALI400_UMP) + + case MALI_IOC_MEM_ATTACH_UMP: + err = mem_attach_ump_wrapper(session_data, (_mali_uk_attach_ump_mem_s __user *)arg); + break; + + case MALI_IOC_MEM_RELEASE_UMP: + err = mem_release_ump_wrapper(session_data, (_mali_uk_release_ump_mem_s __user *)arg); + break; + +#else + + case MALI_IOC_MEM_ATTACH_UMP: + case MALI_IOC_MEM_RELEASE_UMP: /* FALL-THROUGH */ + MALI_DEBUG_PRINT(2, ("UMP not supported\n")); + err = -ENOTTY; + break; +#endif + +#ifdef CONFIG_DMA_SHARED_BUFFER + case MALI_IOC_MEM_ATTACH_DMA_BUF: + err = mali_attach_dma_buf(session_data, (_mali_uk_attach_dma_buf_s __user *)arg); + break; + + case MALI_IOC_MEM_RELEASE_DMA_BUF: + err = mali_release_dma_buf(session_data, (_mali_uk_release_dma_buf_s __user *)arg); + break; + + case MALI_IOC_MEM_DMA_BUF_GET_SIZE: + err = mali_dma_buf_get_size(session_data, (_mali_uk_dma_buf_get_size_s __user *)arg); + break; +#else + + case MALI_IOC_MEM_ATTACH_DMA_BUF: /* FALL-THROUGH */ + case MALI_IOC_MEM_RELEASE_DMA_BUF: /* FALL-THROUGH */ + case MALI_IOC_MEM_DMA_BUF_GET_SIZE: /* FALL-THROUGH */ + MALI_DEBUG_PRINT(2, ("DMA-BUF not supported\n")); + err = -ENOTTY; + break; +#endif + + case MALI_IOC_PP_START_JOB: + err = pp_start_job_wrapper(session_data, (_mali_uk_pp_start_job_s __user *)arg); + break; + + case MALI_IOC_PP_NUMBER_OF_CORES_GET: + err = pp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_pp_number_of_cores_s __user *)arg); + break; + + case MALI_IOC_PP_CORE_VERSION_GET: + err = pp_get_core_version_wrapper(session_data, (_mali_uk_get_pp_core_version_s __user *)arg); + break; + + case MALI_IOC_PP_DISABLE_WB: + err = pp_disable_wb_wrapper(session_data, (_mali_uk_pp_disable_wb_s __user *)arg); + break; + + case MALI_IOC_GP2_START_JOB: + err = gp_start_job_wrapper(session_data, (_mali_uk_gp_start_job_s __user *)arg); + break; + + case MALI_IOC_GP2_NUMBER_OF_CORES_GET: + err = gp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_gp_number_of_cores_s __user *)arg); + break; + + case MALI_IOC_GP2_CORE_VERSION_GET: + err = gp_get_core_version_wrapper(session_data, (_mali_uk_get_gp_core_version_s __user *)arg); + break; + + case MALI_IOC_GP2_SUSPEND_RESPONSE: + err = gp_suspend_response_wrapper(session_data, (_mali_uk_gp_suspend_response_s __user *)arg); + break; + + case MALI_IOC_VSYNC_EVENT_REPORT: + err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg); + break; + + case MALI_IOC_STREAM_CREATE: +#if defined(CONFIG_SYNC) + err = stream_create_wrapper(session_data, (_mali_uk_stream_create_s __user *)arg); + break; +#endif + case MALI_IOC_FENCE_CREATE_EMPTY: +#if defined(CONFIG_SYNC) + err = sync_fence_create_empty_wrapper(session_data, (_mali_uk_fence_create_empty_s __user *)arg); + break; +#endif + case MALI_IOC_FENCE_VALIDATE: +#if defined(CONFIG_SYNC) + err = sync_fence_validate_wrapper(session_data, (_mali_uk_fence_validate_s __user *)arg); + break; +#else + MALI_DEBUG_PRINT(2, ("Sync objects not supported\n")); + err = -ENOTTY; + break; +#endif + + case MALI_IOC_MEM_GET_BIG_BLOCK: /* Fallthrough */ + case MALI_IOC_MEM_FREE_BIG_BLOCK: + MALI_PRINT_ERROR(("Non-MMU mode is no longer supported.\n")); + err = -ENOTTY; + break; + + default: + MALI_DEBUG_PRINT(2, ("No handler for ioctl 0x%08X 0x%08lX\n", cmd, arg)); + err = -ENOTTY; + }; + + return err; +} + + +module_init(mali_module_init); +module_exit(mali_module_exit); + +MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION(SVN_REV_STRING); diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.h new file mode 100644 index 0000000..8bc4c39 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_LINUX_H__ +#define __MALI_KERNEL_LINUX_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include /* character device definitions */ +#include "mali_kernel_license.h" +#include "mali_osk.h" + +extern struct platform_device *mali_platform_device; + +#if MALI_LICENSE_IS_GPL +/* Defined in mali_osk_irq.h */ +extern struct workqueue_struct * mali_wq; +#endif + +void mali_osk_low_level_mem_init(void); +void mali_osk_low_level_mem_term(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_KERNEL_LINUX_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.c new file mode 100644 index 0000000..fa1fa9c --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.c @@ -0,0 +1,1709 @@ +/** + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +/** + * @file mali_kernel_sysfs.c + * Implementation of some sysfs data exports + */ + +#include +#include +#include +#include +#include "mali_kernel_license.h" +#include "mali_kernel_common.h" +#include "mali_ukk.h" + +#if MALI_LICENSE_IS_GPL + +#include +#include +#include +#include +#include +#include "mali_kernel_sysfs.h" +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) +#include +#include "mali_osk_profiling.h" +#endif + +#include +#include "mali_pm.h" +#include "mali_pmu.h" +#include "mali_group.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_l2_cache.h" +#include "mali_hw_core.h" +#include "mali_kernel_core.h" +#include "mali_user_settings_db.h" +#include "mali_profiling_internal.h" +#include "mali_gp_job.h" +#include "mali_pp_job.h" +#include "mali_pp_scheduler.h" + +#define POWER_BUFFER_SIZE 3 + +static struct dentry *mali_debugfs_dir = NULL; + +typedef enum +{ + _MALI_DEVICE_SUSPEND, + _MALI_DEVICE_RESUME, + _MALI_DEVICE_DVFS_PAUSE, + _MALI_DEVICE_DVFS_RESUME, + _MALI_MAX_EVENTS +} _mali_device_debug_power_events; + +static const char* const mali_power_events[_MALI_MAX_EVENTS] = { + [_MALI_DEVICE_SUSPEND] = "suspend", + [_MALI_DEVICE_RESUME] = "resume", + [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause", + [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume", +}; + +static mali_bool power_always_on_enabled = MALI_FALSE; + +static int open_copy_private_data(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->i_private; + return 0; +} + +static ssize_t group_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) +{ + int r; + char buffer[64]; + struct mali_group *group; + + group = (struct mali_group *)filp->private_data; + MALI_DEBUG_ASSERT_POINTER(group); + + r = sprintf(buffer, "%u\n", mali_group_is_enabled(group) ? 1 : 0); + + return simple_read_from_buffer(buf, count, offp, buffer, r); +} + +static ssize_t group_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp) +{ + int r; + char buffer[64]; + unsigned long val; + struct mali_group *group; + + group = (struct mali_group *)filp->private_data; + MALI_DEBUG_ASSERT_POINTER(group); + + if (count >= sizeof(buffer)) + { + return -ENOMEM; + } + + if (copy_from_user(&buffer[0], buf, count)) + { + return -EFAULT; + } + buffer[count] = '\0'; + + r = strict_strtoul(&buffer[0], 10, &val); + if (0 != r) + { + return -EINVAL; + } + + switch (val) + { + case 1: + mali_group_enable(group); + break; + case 0: + mali_group_disable(group); + break; + default: + return -EINVAL; + break; + } + + *offp += count; + return count; +} + +static const struct file_operations group_enabled_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = group_enabled_read, + .write = group_enabled_write, +}; + +static ssize_t hw_core_base_addr_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) +{ + int r; + char buffer[64]; + struct mali_hw_core *hw_core; + + hw_core = (struct mali_hw_core *)filp->private_data; + MALI_DEBUG_ASSERT_POINTER(hw_core); + + r = sprintf(buffer, "0x%08X\n", hw_core->phys_addr); + + return simple_read_from_buffer(buf, count, offp, buffer, r); +} + +static const struct file_operations hw_core_base_addr_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = hw_core_base_addr_read, +}; + +static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) +{ + char buf[64]; + int r; + u32 val; + + if (0 == src_id) + { + val = mali_gp_job_get_gp_counter_src0(); + } + else + { + val = mali_gp_job_get_gp_counter_src1(); + } + + if (MALI_HW_CORE_NO_COUNTER == val) + { + r = sprintf(buf, "-1\n"); + } + else + { + r = sprintf(buf, "%u\n", val); + } + return simple_read_from_buffer(ubuf, cnt, gpos, buf, r); +} + +static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + if (0 == src_id) + { + if (MALI_TRUE != mali_gp_job_set_gp_counter_src0((u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_gp_job_set_gp_counter_src1((u32)val)) + { + return 0; + } + } + + *gpos += cnt; + return cnt; +} + +static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + u32 num_groups; + int i; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + num_groups = mali_group_get_glob_num_groups(); + for (i = 0; i < num_groups; i++) + { + struct mali_group *group = mali_group_get_glob_group(i); + + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) + { + if (0 == src_id) + { + if (MALI_TRUE != mali_gp_job_set_gp_counter_src0((u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_gp_job_set_gp_counter_src1((u32)val)) + { + return 0; + } + } + } + } + + *gpos += cnt; + return cnt; +} + +static ssize_t gp_gpx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 0); +} + +static ssize_t gp_gpx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 1); +} + +static ssize_t gp_gpx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 0); +} + +static ssize_t gp_gpx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 1); +} + +static ssize_t gp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 0); +} + +static ssize_t gp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 1); +} + +static const struct file_operations gp_gpx_counter_src0_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = gp_gpx_counter_src0_read, + .write = gp_gpx_counter_src0_write, +}; + +static const struct file_operations gp_gpx_counter_src1_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = gp_gpx_counter_src1_read, + .write = gp_gpx_counter_src1_write, +}; + +static const struct file_operations gp_all_counter_src0_fops = { + .owner = THIS_MODULE, + .write = gp_all_counter_src0_write, +}; + +static const struct file_operations gp_all_counter_src1_fops = { + .owner = THIS_MODULE, + .write = gp_all_counter_src1_write, +}; + +static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + int r; + u32 val; + + if (0 == src_id) + { + val = mali_pp_job_get_pp_counter_src0(); + } + else + { + val = mali_pp_job_get_pp_counter_src1(); + } + + if (MALI_HW_CORE_NO_COUNTER == val) + { + r = sprintf(buf, "-1\n"); + } + else + { + r = sprintf(buf, "%u\n", val); + } + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + if (0 == src_id) + { + if (MALI_TRUE != mali_pp_job_set_pp_counter_src0((u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_pp_job_set_pp_counter_src1((u32)val)) + { + return 0; + } + } + + *ppos += cnt; + return cnt; +} + +static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + u32 num_groups; + int i; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + num_groups = mali_group_get_glob_num_groups(); + for (i = 0; i < num_groups; i++) + { + struct mali_group *group = mali_group_get_glob_group(i); + + struct mali_pp_core *pp_core = mali_group_get_pp_core(group); + if (NULL != pp_core) + { + if (0 == src_id) + { + if (MALI_TRUE != mali_pp_job_set_pp_counter_src0((u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_pp_job_set_pp_counter_src1((u32)val)) + { + return 0; + } + } + } + } + + *ppos += cnt; + return cnt; +} + +static ssize_t pp_ppx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t pp_ppx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t pp_ppx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t pp_ppx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t pp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t pp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static const struct file_operations pp_ppx_counter_src0_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = pp_ppx_counter_src0_read, + .write = pp_ppx_counter_src0_write, +}; + +static const struct file_operations pp_ppx_counter_src1_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = pp_ppx_counter_src1_read, + .write = pp_ppx_counter_src1_write, +}; + +static const struct file_operations pp_all_counter_src0_fops = { + .owner = THIS_MODULE, + .write = pp_all_counter_src0_write, +}; + +static const struct file_operations pp_all_counter_src1_fops = { + .owner = THIS_MODULE, + .write = pp_all_counter_src1_write, +}; + +static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + int r; + u32 val; + struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data; + + if (0 == src_id) + { + val = mali_l2_cache_core_get_counter_src0(l2_core); + } + else + { + val = mali_l2_cache_core_get_counter_src1(l2_core); + } + + if (MALI_HW_CORE_NO_COUNTER == val) + { + r = sprintf(buf, "-1\n"); + } + else + { + r = sprintf(buf, "%u\n", val); + } + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data; + char buf[64]; + long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + if (0 == src_id) + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_core, (u32)val)) + { + return 0; + } + } + + *ppos += cnt; + return cnt; +} + +static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + u32 l2_id; + struct mali_l2_cache_core *l2_cache; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + l2_id = 0; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + while (NULL != l2_cache) + { + if (0 == src_id) + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_cache, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_cache, (u32)val)) + { + return 0; + } + } + + /* try next L2 */ + l2_id++; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + } + + *ppos += cnt; + return cnt; +} + +static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static const struct file_operations l2_l2x_counter_src0_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = l2_l2x_counter_src0_read, + .write = l2_l2x_counter_src0_write, +}; + +static const struct file_operations l2_l2x_counter_src1_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = l2_l2x_counter_src1_read, + .write = l2_l2x_counter_src1_write, +}; + +static const struct file_operations l2_all_counter_src0_fops = { + .owner = THIS_MODULE, + .write = l2_all_counter_src0_write, +}; + +static const struct file_operations l2_all_counter_src1_fops = { + .owner = THIS_MODULE, + .write = l2_all_counter_src1_write, +}; + +static ssize_t power_always_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + unsigned long val; + int ret; + char buf[32]; + + cnt = min(cnt, sizeof(buf) - 1); + if (copy_from_user(buf, ubuf, cnt)) + { + return -EFAULT; + } + buf[cnt] = '\0'; + + ret = strict_strtoul(buf, 10, &val); + if (0 != ret) + { + return ret; + } + + /* Update setting (not exactly thread safe) */ + if (1 == val && MALI_FALSE == power_always_on_enabled) + { + power_always_on_enabled = MALI_TRUE; + _mali_osk_pm_dev_ref_add(); + } + else if (0 == val && MALI_TRUE == power_always_on_enabled) + { + power_always_on_enabled = MALI_FALSE; + _mali_osk_pm_dev_ref_dec(); + } + + *ppos += cnt; + return cnt; +} + +static ssize_t power_always_on_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + if (MALI_TRUE == power_always_on_enabled) + { + return simple_read_from_buffer(ubuf, cnt, ppos, "1\n", 2); + } + else + { + return simple_read_from_buffer(ubuf, cnt, ppos, "0\n", 2); + } +} + +static const struct file_operations power_always_on_fops = { + .owner = THIS_MODULE, + .read = power_always_on_read, + .write = power_always_on_write, +}; + +static ssize_t power_power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + + if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND]))) + { + mali_pm_os_suspend(); + + } + else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME]))) + { + mali_pm_os_resume(); + } + else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE]))) + { + mali_dev_pause(); + } + else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME]))) + { + mali_dev_resume(); + } + *ppos += cnt; + return cnt; +} + +static loff_t power_power_events_seek(struct file *file, loff_t offset, int orig) +{ + file->f_pos = offset; + return 0; +} + +static const struct file_operations power_power_events_fops = { + .owner = THIS_MODULE, + .write = power_power_events_write, + .llseek = power_power_events_seek, +}; + +#if MALI_STATE_TRACKING +static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v) +{ + u32 len = 0; + u32 size; + char *buf; + + size = seq_get_buf(seq_file, &buf); + + if(!size) + { + return -ENOMEM; + } + + /* Create the internal state dump. */ + len = snprintf(buf+len, size-len, "Mali device driver %s\n", SVN_REV_STRING); + len += snprintf(buf+len, size-len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE); + + len += _mali_kernel_core_dump_state(buf + len, size - len); + + seq_commit(seq_file, len); + + return 0; +} + +static int mali_seq_internal_state_open(struct inode *inode, struct file *file) +{ + return single_open(file, mali_seq_internal_state_show, NULL); +} + +static const struct file_operations mali_seq_internal_state_fops = { + .owner = THIS_MODULE, + .open = mali_seq_internal_state_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif /* MALI_STATE_TRACKING */ + +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) +static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + int r; + + r = sprintf(buf, "%u\n", _mali_internal_profiling_is_recording() ? 1 : 0); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + unsigned long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtoul(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val != 0) + { + u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */ + + /* check if we are already recording */ + if (MALI_TRUE == _mali_internal_profiling_is_recording()) + { + MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n")); + return -EFAULT; + } + + /* check if we need to clear out an old recording first */ + if (MALI_TRUE == _mali_internal_profiling_have_recording()) + { + if (_MALI_OSK_ERR_OK != _mali_internal_profiling_clear()) + { + MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n")); + return -EFAULT; + } + } + + /* start recording profiling data */ + if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit)) + { + MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n")); + return -EFAULT; + } + + MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit)); + } + else + { + /* stop recording profiling data */ + u32 count = 0; + if (_MALI_OSK_ERR_OK != _mali_internal_profiling_stop(&count)) + { + MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n")); + return -EFAULT; + } + + MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count)); + } + + *ppos += cnt; + return cnt; +} + +static const struct file_operations profiling_record_fops = { + .owner = THIS_MODULE, + .read = profiling_record_read, + .write = profiling_record_write, +}; + +static void *profiling_events_start(struct seq_file *s, loff_t *pos) +{ + loff_t *spos; + + /* check if we have data avaiable */ + if (MALI_TRUE != _mali_internal_profiling_have_recording()) + { + return NULL; + } + + spos = kmalloc(sizeof(loff_t), GFP_KERNEL); + if (NULL == spos) + { + return NULL; + } + + *spos = *pos; + return spos; +} + +static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos) +{ + loff_t *spos = v; + + /* check if we have data avaiable */ + if (MALI_TRUE != _mali_internal_profiling_have_recording()) + { + return NULL; + } + + /* check if the next entry actually is avaiable */ + if (_mali_internal_profiling_get_count() <= (u32)(*spos + 1)) + { + return NULL; + } + + *pos = ++*spos; + return spos; +} + +static void profiling_events_stop(struct seq_file *s, void *v) +{ + kfree(v); +} + +static int profiling_events_show(struct seq_file *seq_file, void *v) +{ + loff_t *spos = v; + u32 index; + u64 timestamp; + u32 event_id; + u32 data[5]; + + index = (u32)*spos; + + /* Retrieve all events */ + if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, ×tamp, &event_id, data)) + { + seq_printf(seq_file, "%llu %u %u %u %u %u %u\n", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]); + return 0; + } + + return 0; +} + +static int profiling_events_show_human_readable(struct seq_file *seq_file, void *v) +{ + #define MALI_EVENT_ID_IS_HW(event_id) (((event_id & 0x00FF0000) >= MALI_PROFILING_EVENT_CHANNEL_GP0) && ((event_id & 0x00FF0000) <= MALI_PROFILING_EVENT_CHANNEL_PP7)) + + static u64 start_time = 0; + loff_t *spos = v; + u32 index; + u64 timestamp; + u32 event_id; + u32 data[5]; + + index = (u32)*spos; + + /* Retrieve all events */ + if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, ×tamp, &event_id, data)) + { + seq_printf(seq_file, "%llu %u %u %u %u %u %u # ", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]); + + if (0 == index) + { + start_time = timestamp; + } + + seq_printf(seq_file, "[%06u] ", index); + + switch(event_id & 0x0F000000) + { + case MALI_PROFILING_EVENT_TYPE_SINGLE: + seq_printf(seq_file, "SINGLE | "); + break; + case MALI_PROFILING_EVENT_TYPE_START: + seq_printf(seq_file, "START | "); + break; + case MALI_PROFILING_EVENT_TYPE_STOP: + seq_printf(seq_file, "STOP | "); + break; + case MALI_PROFILING_EVENT_TYPE_SUSPEND: + seq_printf(seq_file, "SUSPEND | "); + break; + case MALI_PROFILING_EVENT_TYPE_RESUME: + seq_printf(seq_file, "RESUME | "); + break; + default: + seq_printf(seq_file, "0x%01X | ", (event_id & 0x0F000000) >> 24); + break; + } + + switch(event_id & 0x00FF0000) + { + case MALI_PROFILING_EVENT_CHANNEL_SOFTWARE: + seq_printf(seq_file, "SW | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_GP0: + seq_printf(seq_file, "GP0 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP0: + seq_printf(seq_file, "PP0 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP1: + seq_printf(seq_file, "PP1 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP2: + seq_printf(seq_file, "PP2 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP3: + seq_printf(seq_file, "PP3 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP4: + seq_printf(seq_file, "PP4 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP5: + seq_printf(seq_file, "PP5 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP6: + seq_printf(seq_file, "PP6 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP7: + seq_printf(seq_file, "PP7 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_GPU: + seq_printf(seq_file, "GPU | "); + break; + default: + seq_printf(seq_file, "0x%02X | ", (event_id & 0x00FF0000) >> 16); + break; + } + + if (MALI_EVENT_ID_IS_HW(event_id)) + { + if (((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_START) || ((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_STOP)) + { + switch(event_id & 0x0000FFFF) + { + case MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL: + seq_printf(seq_file, "PHYSICAL | "); + break; + case MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL: + seq_printf(seq_file, "VIRTUAL | "); + break; + default: + seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF); + break; + } + } + else + { + seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF); + } + } + else + { + seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF); + } + + seq_printf(seq_file, "T0 + 0x%016llX\n", timestamp - start_time); + + return 0; + } + + return 0; +} + +static const struct seq_operations profiling_events_seq_ops = { + .start = profiling_events_start, + .next = profiling_events_next, + .stop = profiling_events_stop, + .show = profiling_events_show +}; + +static int profiling_events_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &profiling_events_seq_ops); +} + +static const struct file_operations profiling_events_fops = { + .owner = THIS_MODULE, + .open = profiling_events_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct seq_operations profiling_events_human_readable_seq_ops = { + .start = profiling_events_start, + .next = profiling_events_next, + .stop = profiling_events_stop, + .show = profiling_events_show_human_readable +}; + +static int profiling_events_human_readable_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &profiling_events_human_readable_seq_ops); +} + +static const struct file_operations profiling_events_human_readable_fops = { + .owner = THIS_MODULE, + .open = profiling_events_human_readable_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +#endif + +static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 mem = _mali_ukk_report_memory_usage(); + + r = snprintf(buf, 64, "%u\n", mem); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static const struct file_operations memory_usage_fops = { + .owner = THIS_MODULE, + .read = memory_used_read, +}; + +static ssize_t utilization_gp_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 uval= _mali_ukk_utilization_gp_pp(); + + r = snprintf(buf, 64, "%u\n", uval); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t utilization_gp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 uval= _mali_ukk_utilization_gp(); + + r = snprintf(buf, 64, "%u\n", uval); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t utilization_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 uval= _mali_ukk_utilization_pp(); + + r = snprintf(buf, 64, "%u\n", uval); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + + +static const struct file_operations utilization_gp_pp_fops = { + .owner = THIS_MODULE, + .read = utilization_gp_pp_read, +}; + +static const struct file_operations utilization_gp_fops = { + .owner = THIS_MODULE, + .read = utilization_gp_read, +}; + +static const struct file_operations utilization_pp_fops = { + .owner = THIS_MODULE, + .read = utilization_pp_read, +}; + +static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + unsigned long val; + int ret; + _mali_uk_user_setting_t setting; + char buf[32]; + + cnt = min(cnt, sizeof(buf) - 1); + if (copy_from_user(buf, ubuf, cnt)) + { + return -EFAULT; + } + buf[cnt] = '\0'; + + ret = strict_strtoul(buf, 10, &val); + if (0 != ret) + { + return ret; + } + + /* Update setting */ + setting = (_mali_uk_user_setting_t)(filp->private_data); + mali_set_user_setting(setting, val); + + *ppos += cnt; + return cnt; +} + +static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 value; + _mali_uk_user_setting_t setting; + + setting = (_mali_uk_user_setting_t)(filp->private_data); + value = mali_get_user_setting(setting); + + r = snprintf(buf, 64, "%u\n", value); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static const struct file_operations user_settings_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = user_settings_read, + .write = user_settings_write, +}; + +static int mali_sysfs_user_settings_register(void) +{ + struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir); + + if (mali_user_settings_dir != NULL) + { + int i; + for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++) + { + debugfs_create_file(_mali_uk_user_setting_descriptions[i], 0600, mali_user_settings_dir, (void*)i, &user_settings_fops); + } + } + + return 0; +} + +static ssize_t pmu_power_down_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp) +{ + int ret; + char buffer[32]; + unsigned long val; + struct mali_pmu_core *pmu; + _mali_osk_errcode_t err; + + if (count >= sizeof(buffer)) + { + return -ENOMEM; + } + + if (copy_from_user(&buffer[0], buf, count)) + { + return -EFAULT; + } + buffer[count] = '\0'; + + ret = strict_strtoul(&buffer[0], 10, &val); + if (0 != ret) + { + return -EINVAL; + } + + pmu = mali_pmu_get_global_pmu_core(); + MALI_DEBUG_ASSERT_POINTER(pmu); + + err = mali_pmu_power_down(pmu, val); + if (_MALI_OSK_ERR_OK != err) + { + return -EINVAL; + } + + *offp += count; + return count; +} + +static ssize_t pmu_power_up_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp) +{ + int ret; + char buffer[32]; + unsigned long val; + struct mali_pmu_core *pmu; + _mali_osk_errcode_t err; + + if (count >= sizeof(buffer)) + { + return -ENOMEM; + } + + if (copy_from_user(&buffer[0], buf, count)) + { + return -EFAULT; + } + buffer[count] = '\0'; + + ret = strict_strtoul(&buffer[0], 10, &val); + if (0 != ret) + { + return -EINVAL; + } + + pmu = mali_pmu_get_global_pmu_core(); + MALI_DEBUG_ASSERT_POINTER(pmu); + + err = mali_pmu_power_up(pmu, val); + if (_MALI_OSK_ERR_OK != err) + { + return -EINVAL; + } + + *offp += count; + return count; +} + +static const struct file_operations pmu_power_down_fops = { + .owner = THIS_MODULE, + .write = pmu_power_down_write, +}; + +static const struct file_operations pmu_power_up_fops = { + .owner = THIS_MODULE, + .write = pmu_power_up_write, +}; + +static ssize_t pp_num_cores_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp) +{ + int ret; + char buffer[32]; + unsigned long val; + + if (count >= sizeof(buffer)) + { + return -ENOMEM; + } + + if (copy_from_user(&buffer[0], buf, count)) + { + return -EFAULT; + } + buffer[count] = '\0'; + + ret = strict_strtoul(&buffer[0], 10, &val); + if (0 != ret) + { + return -EINVAL; + } + + ret = mali_perf_set_num_pp_cores(val); + if (ret) + { + return ret; + } + + *offp += count; + return count; +} + +static ssize_t pp_num_cores_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) +{ + int r; + char buffer[64]; + + r = sprintf(buffer, "%u\n", mali_pp_scheduler_get_num_cores_enabled()); + + return simple_read_from_buffer(buf, count, offp, buffer, r); +} + +static const struct file_operations pp_num_cores_enabled_fops = { + .owner = THIS_MODULE, + .write = pp_num_cores_enabled_write, + .read = pp_num_cores_enabled_read, +}; + +static ssize_t pp_num_cores_total_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) +{ + int r; + char buffer[64]; + + r = sprintf(buffer, "%u\n", mali_pp_scheduler_get_num_cores_total()); + + return simple_read_from_buffer(buf, count, offp, buffer, r); +} + +static const struct file_operations pp_num_cores_total_fops = { + .owner = THIS_MODULE, + .read = pp_num_cores_total_read, +}; + + +static ssize_t version_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) +{ + int r = 0; + char buffer[64]; + + switch (mali_kernel_core_get_product_id()) + { + case _MALI_PRODUCT_ID_MALI200: + r = sprintf(buffer, "Mali-200\n"); + break; + case _MALI_PRODUCT_ID_MALI300: + r = sprintf(buffer, "Mali-300\n"); + break; + case _MALI_PRODUCT_ID_MALI400: + r = sprintf(buffer, "Mali-400 MP\n"); + break; + case _MALI_PRODUCT_ID_MALI450: + r = sprintf(buffer, "Mali-450 MP\n"); + break; + case _MALI_PRODUCT_ID_UNKNOWN: + return -EINVAL; + break; + }; + + return simple_read_from_buffer(buf, count, offp, buffer, r); +} + +static const struct file_operations version_fops = { + .owner = THIS_MODULE, + .read = version_read, +}; + +int mali_sysfs_register(const char *mali_dev_name) +{ + mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL); + if(ERR_PTR(-ENODEV) == mali_debugfs_dir) + { + /* Debugfs not supported. */ + mali_debugfs_dir = NULL; + } + else + { + if(NULL != mali_debugfs_dir) + { + /* Debugfs directory created successfully; create files now */ + struct dentry *mali_pmu_dir; + struct dentry *mali_power_dir; + struct dentry *mali_gp_dir; + struct dentry *mali_pp_dir; + struct dentry *mali_l2_dir; +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) + struct dentry *mali_profiling_dir; +#endif + + debugfs_create_file("version", 0400, mali_debugfs_dir, NULL, &version_fops); + + mali_pmu_dir = debugfs_create_dir("pmu", mali_debugfs_dir); + if (NULL != mali_pmu_dir) + { + debugfs_create_file("power_down", 0200, mali_pmu_dir, NULL, &pmu_power_down_fops); + debugfs_create_file("power_up", 0200, mali_pmu_dir, NULL, &pmu_power_up_fops); + } + + mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir); + if (mali_power_dir != NULL) + { + /* MALI_SEC : 0600 -> 0400 */ + debugfs_create_file("always_on", 0400, mali_power_dir, NULL, &power_always_on_fops); + /* MALI_SEC : 0200 -> 0400 */ + debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_power_events_fops); + } + + mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir); + if (mali_gp_dir != NULL) + { + struct dentry *mali_gp_all_dir; + u32 num_groups; + int i; + + mali_gp_all_dir = debugfs_create_dir("all", mali_gp_dir); + if (mali_gp_all_dir != NULL) + { + debugfs_create_file("counter_src0", 0200, mali_gp_all_dir, NULL, &gp_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0200, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops); + } + + num_groups = mali_group_get_glob_num_groups(); + for (i = 0; i < num_groups; i++) + { + struct mali_group *group = mali_group_get_glob_group(i); + + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) + { + struct dentry *mali_gp_gpx_dir; + mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir); + if (NULL != mali_gp_gpx_dir) + { + debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops); + debugfs_create_file("base_addr", 0400, mali_gp_gpx_dir, &gp_core->hw_core, &hw_core_base_addr_fops); + debugfs_create_file("enabled", 0600, mali_gp_gpx_dir, group, &group_enabled_fops); + } + break; /* no need to look for any other GP cores */ + } + + } + } + + mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir); + if (mali_pp_dir != NULL) + { + struct dentry *mali_pp_all_dir; + u32 num_groups; + int i; + + debugfs_create_file("num_cores_total", 0400, mali_pp_dir, NULL, &pp_num_cores_total_fops); + debugfs_create_file("num_cores_enabled", 0600, mali_pp_dir, NULL, &pp_num_cores_enabled_fops); + + mali_pp_all_dir = debugfs_create_dir("all", mali_pp_dir); + if (mali_pp_all_dir != NULL) + { + debugfs_create_file("counter_src0", 0200, mali_pp_all_dir, NULL, &pp_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0200, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops); + } + + num_groups = mali_group_get_glob_num_groups(); + for (i = 0; i < num_groups; i++) + { + struct mali_group *group = mali_group_get_glob_group(i); + + struct mali_pp_core *pp_core = mali_group_get_pp_core(group); + if (NULL != pp_core) + { + char buf[16]; + struct dentry *mali_pp_ppx_dir; + _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core)); + mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir); + if (NULL != mali_pp_ppx_dir) + { + debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops); + debugfs_create_file("base_addr", 0400, mali_pp_ppx_dir, &pp_core->hw_core, &hw_core_base_addr_fops); + if (!mali_group_is_virtual(group)) + { + debugfs_create_file("enabled", 0600, mali_pp_ppx_dir, group, &group_enabled_fops); + } + } + } + } + } + + mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir); + if (mali_l2_dir != NULL) + { + struct dentry *mali_l2_all_dir; + u32 l2_id; + struct mali_l2_cache_core *l2_cache; + + mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir); + if (mali_l2_all_dir != NULL) + { + debugfs_create_file("counter_src0", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops); + } + + l2_id = 0; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + while (NULL != l2_cache) + { + char buf[16]; + struct dentry *mali_l2_l2x_dir; + _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id); + mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir); + if (NULL != mali_l2_l2x_dir) + { + debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops); + debugfs_create_file("base_addr", 0400, mali_l2_l2x_dir, &l2_cache->hw_core, &hw_core_base_addr_fops); + } + + /* try next L2 */ + l2_id++; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + } + } + + debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops); + + debugfs_create_file("utilization_gp_pp", 0400, mali_debugfs_dir, NULL, &utilization_gp_pp_fops); + debugfs_create_file("utilization_gp", 0400, mali_debugfs_dir, NULL, &utilization_gp_fops); + debugfs_create_file("utilization_pp", 0400, mali_debugfs_dir, NULL, &utilization_pp_fops); + +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) + mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir); + if (mali_profiling_dir != NULL) + { + struct dentry *mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir); + if (mali_profiling_proc_dir != NULL) + { + struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir); + if (mali_profiling_proc_default_dir != NULL) + { + debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void*)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops); + } + } + debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops); + debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops); + debugfs_create_file("events_human_readable", 0400, mali_profiling_dir, NULL, &profiling_events_human_readable_fops); + } +#endif + +#if MALI_STATE_TRACKING + debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops); +#endif + + if (mali_sysfs_user_settings_register()) + { + /* Failed to create the debugfs entries for the user settings DB. */ + MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n")); + } + } + } + + /* Success! */ + return 0; +} + +int mali_sysfs_unregister(void) +{ + if(NULL != mali_debugfs_dir) + { + debugfs_remove_recursive(mali_debugfs_dir); + } + return 0; +} + +#else /* MALI_LICENSE_IS_GPL */ + +/* Dummy implementations for non-GPL */ + +int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name) +{ + return 0; +} + +int mali_sysfs_unregister(void) +{ + return 0; +} + +#endif /* MALI_LICENSE_IS_GPL */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.h new file mode 100644 index 0000000..f970f0f --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_SYSFS_H__ +#define __MALI_KERNEL_SYSFS_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#define MALI_PROC_DIR "driver/mali" + +int mali_sysfs_register(const char *mali_dev_name); +int mali_sysfs_unregister(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_KERNEL_LINUX_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_linux_trace.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_linux_trace.h new file mode 100644 index 0000000..5329ba3 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_linux_trace.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if !defined (MALI_LINUX_TRACE_H) || defined (TRACE_HEADER_MULTI_READ) +#define MALI_LINUX_TRACE_H + +#include + +#include +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali +#define TRACE_SYSTEM_STRING __stringfy(TRACE_SYSTEM) + +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE mali_linux_trace + +/** + * Define the tracepoint used to communicate the status of a GPU. Called + * when a GPU turns on or turns off. + * + * @param event_id The type of the event. This parameter is a bitfield + * encoding the type of the event. + * + * @param d0 First data parameter. + * @param d1 Second data parameter. + * @param d2 Third data parameter. + * @param d3 Fourth data parameter. + * @param d4 Fifth data parameter. + */ +TRACE_EVENT(mali_timeline_event, + + TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, + unsigned int d2, unsigned int d3, unsigned int d4), + + TP_ARGS(event_id, d0, d1, d2, d3, d4), + + TP_STRUCT__entry( + __field(unsigned int, event_id) + __field(unsigned int, d0) + __field(unsigned int, d1) + __field(unsigned int, d2) + __field(unsigned int, d3) + __field(unsigned int, d4) + ), + + TP_fast_assign( + __entry->event_id = event_id; + __entry->d0 = d0; + __entry->d1 = d1; + __entry->d2 = d2; + __entry->d3 = d3; + __entry->d4 = d4; + ), + + TP_printk("event=%d", __entry->event_id) +); + +/** + * Define a tracepoint used to regsiter the value of a hardware counter. + * Hardware counters belonging to the vertex or fragment processor are + * reported via this tracepoint each frame, whilst L2 cache hardware + * counters are reported continuously. + * + * @param counter_id The counter ID. + * @param value The value of the counter. + */ +TRACE_EVENT(mali_hw_counter, + + TP_PROTO(unsigned int counter_id, unsigned int value), + + TP_ARGS(counter_id, value), + + TP_STRUCT__entry( + __field(unsigned int, counter_id) + __field(unsigned int, value) + ), + + TP_fast_assign( + __entry->counter_id = counter_id; + ), + + TP_printk("event %d = %d", __entry->counter_id, __entry->value) +); + +/** + * Define a tracepoint used to send a bundle of software counters. + * + * @param counters The bundle of counters. + */ +TRACE_EVENT(mali_sw_counters, + + TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters), + + TP_ARGS(pid, tid, surface_id, counters), + + TP_STRUCT__entry( + __field(pid_t, pid) + __field(pid_t, tid) + __field(void *, surface_id) + __field(unsigned int *, counters) + ), + + TP_fast_assign( + __entry->pid = pid; + __entry->tid = tid; + __entry->surface_id = surface_id; + __entry->counters = counters; + ), + + TP_printk("counters were %s", __entry->counters == NULL? "NULL" : "not NULL") +); + +#endif /* MALI_LINUX_TRACE_H */ + +/* This part must exist outside the header guard. */ +#include + diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_atomics.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_atomics.c new file mode 100644 index 0000000..05831c5 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_atomics.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_atomics.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include "mali_osk.h" +#include +#include "mali_kernel_common.h" + +void _mali_osk_atomic_dec( _mali_osk_atomic_t *atom ) +{ + atomic_dec((atomic_t *)&atom->u.val); +} + +u32 _mali_osk_atomic_dec_return( _mali_osk_atomic_t *atom ) +{ + return atomic_dec_return((atomic_t *)&atom->u.val); +} + +void _mali_osk_atomic_inc( _mali_osk_atomic_t *atom ) +{ + atomic_inc((atomic_t *)&atom->u.val); +} + +u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom ) +{ + return atomic_inc_return((atomic_t *)&atom->u.val); +} + +_mali_osk_errcode_t _mali_osk_atomic_init( _mali_osk_atomic_t *atom, u32 val ) +{ + MALI_CHECK_NON_NULL(atom, _MALI_OSK_ERR_INVALID_ARGS); + atomic_set((atomic_t *)&atom->u.val, val); + return _MALI_OSK_ERR_OK; +} + +u32 _mali_osk_atomic_read( _mali_osk_atomic_t *atom ) +{ + return atomic_read((atomic_t *)&atom->u.val); +} + +void _mali_osk_atomic_term( _mali_osk_atomic_t *atom ) +{ + MALI_IGNORE(atom); +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_irq.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_irq.c new file mode 100644 index 0000000..787a145 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_irq.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_irq.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include /* For memory allocation */ + +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "linux/interrupt.h" + +typedef struct _mali_osk_irq_t_struct +{ + u32 irqnum; + void *data; + _mali_osk_irq_uhandler_t uhandler; +} mali_osk_irq_object_t; + +typedef irqreturn_t (*irq_handler_func_t)(int, void *, struct pt_regs *); +static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ); /* , struct pt_regs *regs*/ + +_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, void *int_data, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *probe_data, const char *description ) +{ + mali_osk_irq_object_t *irq_object; + unsigned long irq_flags = 0; + +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + irq_flags |= IRQF_SHARED; +#endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */ + + irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL); + if (NULL == irq_object) + { + return NULL; + } + + if (-1 == irqnum) + { + /* Probe for IRQ */ + if ( (NULL != trigger_func) && (NULL != ack_func) ) + { + unsigned long probe_count = 3; + _mali_osk_errcode_t err; + int irq; + + MALI_DEBUG_PRINT(2, ("Probing for irq\n")); + + do + { + unsigned long mask; + + mask = probe_irq_on(); + trigger_func(probe_data); + + _mali_osk_time_ubusydelay(5); + + irq = probe_irq_off(mask); + err = ack_func(probe_data); + } + while (irq < 0 && (err == _MALI_OSK_ERR_OK) && probe_count--); + + if (irq < 0 || (_MALI_OSK_ERR_OK != err)) irqnum = -1; + else irqnum = irq; + } + else irqnum = -1; /* no probe functions, fault */ + + if (-1 != irqnum) + { + /* found an irq */ + MALI_DEBUG_PRINT(2, ("Found irq %d\n", irqnum)); + } + else + { + MALI_DEBUG_PRINT(2, ("Probe for irq failed\n")); + } + } + + irq_object->irqnum = irqnum; + irq_object->uhandler = uhandler; + irq_object->data = int_data; + + if (-1 == irqnum) + { + MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description)); + kfree(irq_object); + return NULL; + } + + if (0 != request_irq(irqnum, irq_handler_upper_half, irq_flags, description, irq_object)) + { + MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description)); + kfree(irq_object); + return NULL; + } + + return irq_object; +} + +void _mali_osk_irq_term( _mali_osk_irq_t *irq ) +{ + mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq; + free_irq(irq_object->irqnum, irq_object); + kfree(irq_object); +} + + +/** This function is called directly in interrupt context from the OS just after + * the CPU get the hw-irq from mali, or other devices on the same IRQ-channel. + * It is registered one of these function for each mali core. When an interrupt + * arrives this function will be called equal times as registered mali cores. + * That means that we only check one mali core in one function call, and the + * core we check for each turn is given by the \a dev_id variable. + * If we detect an pending interrupt on the given core, we mask the interrupt + * out by settging the core's IRQ_MASK register to zero. + * Then we schedule the mali_core_irq_handler_bottom_half to run as high priority + * work queue job. + */ +static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ) /* , struct pt_regs *regs*/ +{ + irqreturn_t ret = IRQ_NONE; + mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)dev_id; + + if (_MALI_OSK_ERR_OK == irq_object->uhandler(irq_object->data)) + { + ret = IRQ_HANDLED; + } + + return ret; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_locks.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_locks.c new file mode 100644 index 0000000..cce946a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_locks.c @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_locks.c + * Implemenation of the OS abstraction layer for the kernel device driver + */ + +#include +#include +#include + +#include + +#include "mali_osk.h" +#include "mali_kernel_common.h" + +/* These are all the locks we implement: */ +typedef enum +{ + _MALI_OSK_INTERNAL_LOCKTYPE_SPIN, /* Mutex, implicitly non-interruptable, use spin_lock/spin_unlock */ + _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ, /* Mutex, IRQ version of spinlock, use spin_lock_irqsave/spin_unlock_irqrestore */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX, /* Interruptable, use mutex_unlock()/down_interruptable() */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT, /* Non-Interruptable, use mutex_unlock()/down() */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW, /* Non-interruptable, Reader/Writer, use {mutex_unlock,down}{read,write}() */ + + /* Linux supports, but we do not support: + * Non-Interruptable Reader/Writer spinlock mutexes - RW optimization will be switched off + */ + + /* Linux does not support: + * One-locks, of any sort - no optimization for this fact will be made. + */ + +} _mali_osk_internal_locktype; + +struct _mali_osk_lock_t_struct +{ + _mali_osk_internal_locktype type; + unsigned long flags; + union + { + spinlock_t spinlock; + struct mutex mutex; + struct rw_semaphore rw_sema; + } obj; + MALI_DEBUG_CODE( + /** original flags for debug checking */ + _mali_osk_lock_flags_t orig_flags; + + /* id of the thread currently holding this lock, 0 if no + * threads hold it. */ + u32 owner; + /* what mode the lock was taken in */ + _mali_osk_lock_mode_t mode; + ); /* MALI_DEBUG_CODE */ +}; + +_mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial, u32 order ) +{ + _mali_osk_lock_t *lock = NULL; + + /* Validate parameters: */ + /* Flags acceptable */ + MALI_DEBUG_ASSERT( 0 == ( flags & ~(_MALI_OSK_LOCKFLAG_SPINLOCK + | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ + | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE + | _MALI_OSK_LOCKFLAG_READERWRITER + | _MALI_OSK_LOCKFLAG_ORDERED + | _MALI_OSK_LOCKFLAG_ONELOCK )) ); + /* Spinlocks are always non-interruptable */ + MALI_DEBUG_ASSERT( (((flags & _MALI_OSK_LOCKFLAG_SPINLOCK) || (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ)) && (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE)) + || !(flags & _MALI_OSK_LOCKFLAG_SPINLOCK)); + /* Parameter initial SBZ - for future expansion */ + MALI_DEBUG_ASSERT( 0 == initial ); + + lock = kmalloc(sizeof(_mali_osk_lock_t), GFP_KERNEL); + + if ( NULL == lock ) + { + return lock; + } + + /* Determine type of mutex: */ + /* defaults to interruptable mutex if no flags are specified */ + + if ( (flags & _MALI_OSK_LOCKFLAG_SPINLOCK) ) + { + /* Non-interruptable Spinlocks override all others */ + lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_SPIN; + spin_lock_init( &lock->obj.spinlock ); + } + else if ( (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ ) ) + { + lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ; + lock->flags = 0; + spin_lock_init( &lock->obj.spinlock ); + } + else if ( (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE) + && (flags & _MALI_OSK_LOCKFLAG_READERWRITER) ) + { + lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW; + init_rwsem( &lock->obj.rw_sema ); + } + else + { + /* Usual mutex types */ + if ( (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE) ) + { + lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT; + } + else + { + lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX; + } + + /* Initially unlocked */ + mutex_init(&lock->obj.mutex); + } + +#ifdef DEBUG + /* Debug tracking of flags */ + lock->orig_flags = flags; + + /* Debug tracking of lock owner */ + lock->owner = 0; +#endif /* DEBUG */ + + return lock; +} + +#ifdef DEBUG +u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock ) +{ + return lock->owner; +} + +u32 _mali_osk_lock_get_mode( _mali_osk_lock_t *lock ) +{ + return lock->mode; +} +#endif /* DEBUG */ + +_mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; + + /* Parameter validation */ + MALI_DEBUG_ASSERT_POINTER( lock ); + + MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode + || _MALI_OSK_LOCKMODE_RO == mode ); + + /* Only allow RO locks when the initial object was a Reader/Writer lock + * Since information is lost on the internal locktype, we use the original + * information, which is only stored when built for DEBUG */ + MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode + || (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) ); + + switch ( lock->type ) + { + case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN: + spin_lock(&lock->obj.spinlock); + break; + case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ: + { + unsigned long tmp_flags; + spin_lock_irqsave(&lock->obj.spinlock, tmp_flags); + lock->flags = tmp_flags; + } + break; + + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX: + if (mutex_lock_interruptible(&lock->obj.mutex)) + { + MALI_PRINT_ERROR(("Can not lock mutex\n")); + err = _MALI_OSK_ERR_RESTARTSYSCALL; + } + break; + + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT: + mutex_lock(&lock->obj.mutex); + break; + + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW: + if (mode == _MALI_OSK_LOCKMODE_RO) + { + down_read(&lock->obj.rw_sema); + } + else + { + down_write(&lock->obj.rw_sema); + } + break; + + default: + /* Reaching here indicates a programming error, so you will not get here + * on non-DEBUG builds */ + MALI_DEBUG_PRINT_ERROR( ("Invalid internal lock type: %.8X", lock->type ) ); + break; + } + +#ifdef DEBUG + /* This thread is now the owner of this lock */ + if (_MALI_OSK_ERR_OK == err) + { + if (mode == _MALI_OSK_LOCKMODE_RW) + { + if (0 != lock->owner) + { + printk(KERN_ERR "%d: ERROR: Lock %p already has owner %d\n", _mali_osk_get_tid(), lock, lock->owner); + dump_stack(); + } + lock->owner = _mali_osk_get_tid(); + lock->mode = mode; + } + else /* mode == _MALI_OSK_LOCKMODE_RO */ + { + lock->mode = mode; + } + } +#endif + + return err; +} + +void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ) +{ + /* Parameter validation */ + MALI_DEBUG_ASSERT_POINTER( lock ); + + MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode + || _MALI_OSK_LOCKMODE_RO == mode ); + + /* Only allow RO locks when the initial object was a Reader/Writer lock + * Since information is lost on the internal locktype, we use the original + * information, which is only stored when built for DEBUG */ + MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode + || (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) ); + +#ifdef DEBUG + /* make sure the thread releasing the lock actually was the owner */ + if (mode == _MALI_OSK_LOCKMODE_RW) + { + if (_mali_osk_get_tid() != lock->owner) + { + printk(KERN_ERR "%d: ERROR: Lock %p owner was %d\n", _mali_osk_get_tid(), lock, lock->owner); + dump_stack(); + } + /* This lock now has no owner */ + lock->owner = 0; + } /* else if (mode == _MALI_OSK_LOCKMODE_RO) Nothing to check */ +#endif /* DEBUG */ + + switch ( lock->type ) + { + case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN: + spin_unlock(&lock->obj.spinlock); + break; + case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ: + spin_unlock_irqrestore(&lock->obj.spinlock, lock->flags); + break; + + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX: + /* FALLTHROUGH */ + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT: + mutex_unlock(&lock->obj.mutex); + break; + + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW: + if (mode == _MALI_OSK_LOCKMODE_RO) + { + up_read(&lock->obj.rw_sema); + } + else + { + up_write(&lock->obj.rw_sema); + } + break; + + default: + /* Reaching here indicates a programming error, so you will not get here + * on non-DEBUG builds */ + MALI_DEBUG_PRINT_ERROR( ("Invalid internal lock type: %.8X", lock->type ) ); + break; + } +} + +void _mali_osk_lock_term( _mali_osk_lock_t *lock ) +{ + /* Parameter validation */ + MALI_DEBUG_ASSERT_POINTER( lock ); + + /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */ + kfree(lock); +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_low_level_mem.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_low_level_mem.c new file mode 100644 index 0000000..8c0ef17 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_low_level_mem.c @@ -0,0 +1,723 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_low_level_mem.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +/* needed to detect kernel version specific code */ +#include + +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) +#include +#endif +#include +#include +#include + +#include "mali_osk.h" +#include "mali_ukk.h" /* required to hook in _mali_ukk_mem_mmap handling */ +#include "mali_kernel_common.h" +#include "mali_kernel_linux.h" + +static void mali_kernel_memory_vma_open(struct vm_area_struct * vma); +static void mali_kernel_memory_vma_close(struct vm_area_struct * vma); + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf); +#else +static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address); +#endif + + +typedef struct mali_vma_usage_tracker +{ + int references; + u32 cookie; +} mali_vma_usage_tracker; + +#define INVALID_PAGE 0xffffffff + +/* Linked list structure to hold details of all OS allocations in a particular + * mapping + */ +struct AllocationList +{ + struct AllocationList *next; + u32 offset; + u32 physaddr; +}; + +typedef struct AllocationList AllocationList; + +/* Private structure to store details of a mapping region returned + * from _mali_osk_mem_mapregion_init + */ +struct MappingInfo +{ + struct vm_area_struct *vma; + struct AllocationList *list; + struct AllocationList *tail; +}; + +typedef struct MappingInfo MappingInfo; + + +static u32 _kernel_page_allocate(void); +static void _kernel_page_release(u32 physical_address); +static AllocationList * _allocation_list_item_get(void); +static void _allocation_list_item_release(AllocationList * item); + + +/* Variable declarations */ +static DEFINE_SPINLOCK(allocation_list_spinlock); +static AllocationList * pre_allocated_memory = (AllocationList*) NULL ; +static int pre_allocated_memory_size_current = 0; +#ifdef MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB + static int pre_allocated_memory_size_max = MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB * 1024 * 1024; +#else + static int pre_allocated_memory_size_max = 16 * 1024 * 1024; /* 6 MiB */ +#endif + +static struct vm_operations_struct mali_kernel_vm_ops = +{ + .open = mali_kernel_memory_vma_open, + .close = mali_kernel_memory_vma_close, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + .fault = mali_kernel_memory_cpu_page_fault_handler +#else + .nopfn = mali_kernel_memory_cpu_page_fault_handler +#endif +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) +static int mali_mem_shrink(int nr_to_scan, gfp_t gfp_mask) + #else +static int mali_mem_shrink(struct shrinker *shrinker, int nr_to_scan, gfp_t gfp_mask) + #endif +#else +static int mali_mem_shrink(struct shrinker *shrinker, struct shrink_control *sc) +#endif +{ + unsigned long flags; + AllocationList *item; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + int nr = nr_to_scan; +#else + int nr = sc->nr_to_scan; +#endif + + if (0 == nr) + { + return pre_allocated_memory_size_current / PAGE_SIZE; + } + + if (0 == pre_allocated_memory_size_current) + { + /* No pages availble */ + return 0; + } + + if (0 == spin_trylock_irqsave(&allocation_list_spinlock, flags)) + { + /* Not able to lock. */ + return -1; + } + + while (pre_allocated_memory && nr > 0) + { + item = pre_allocated_memory; + pre_allocated_memory = item->next; + + _kernel_page_release(item->physaddr); + _mali_osk_free(item); + + pre_allocated_memory_size_current -= PAGE_SIZE; + --nr; + } + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + + return pre_allocated_memory_size_current / PAGE_SIZE; +} + +struct shrinker mali_mem_shrinker = { + .shrink = mali_mem_shrink, + .seeks = DEFAULT_SEEKS, +}; + +void mali_osk_low_level_mem_init(void) +{ + pre_allocated_memory = (AllocationList*) NULL ; + + register_shrinker(&mali_mem_shrinker); +} + +void mali_osk_low_level_mem_term(void) +{ + unregister_shrinker(&mali_mem_shrinker); + + while ( NULL != pre_allocated_memory ) + { + AllocationList *item; + item = pre_allocated_memory; + pre_allocated_memory = item->next; + _kernel_page_release(item->physaddr); + _mali_osk_free( item ); + } + pre_allocated_memory_size_current = 0; +} + +static u32 _kernel_page_allocate(void) +{ + struct page *new_page; + u32 linux_phys_addr; + + new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD); + + if ( NULL == new_page ) + { + return INVALID_PAGE; + } + + /* Ensure page is flushed from CPU caches. */ + linux_phys_addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); + + return linux_phys_addr; +} + +static void _kernel_page_release(u32 physical_address) +{ + struct page *unmap_page; + + #if 1 + dma_unmap_page(NULL, physical_address, PAGE_SIZE, DMA_BIDIRECTIONAL); + #endif + + unmap_page = pfn_to_page( physical_address >> PAGE_SHIFT ); + MALI_DEBUG_ASSERT_POINTER( unmap_page ); + __free_page( unmap_page ); +} + +static AllocationList * _allocation_list_item_get(void) +{ + AllocationList *item = NULL; + unsigned long flags; + + spin_lock_irqsave(&allocation_list_spinlock,flags); + if ( pre_allocated_memory ) + { + item = pre_allocated_memory; + pre_allocated_memory = pre_allocated_memory->next; + pre_allocated_memory_size_current -= PAGE_SIZE; + + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + return item; + } + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + + item = _mali_osk_malloc( sizeof(AllocationList) ); + if ( NULL == item) + { + return NULL; + } + + item->physaddr = _kernel_page_allocate(); + if ( INVALID_PAGE == item->physaddr ) + { + /* Non-fatal error condition, out of memory. Upper levels will handle this. */ + _mali_osk_free( item ); + return NULL; + } + return item; +} + +static void _allocation_list_item_release(AllocationList * item) +{ + unsigned long flags; + spin_lock_irqsave(&allocation_list_spinlock,flags); + if ( pre_allocated_memory_size_current < pre_allocated_memory_size_max) + { + item->next = pre_allocated_memory; + pre_allocated_memory = item; + pre_allocated_memory_size_current += PAGE_SIZE; + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + return; + } + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + + _kernel_page_release(item->physaddr); + _mali_osk_free( item ); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf) +#else +static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + void __user * address; + address = vmf->virtual_address; +#endif + /* + * We always fail the call since all memory is pre-faulted when assigned to the process. + * Only the Mali cores can use page faults to extend buffers. + */ + + MALI_DEBUG_PRINT(1, ("Page-fault in Mali memory region caused by the CPU.\n")); + MALI_DEBUG_PRINT(1, ("Tried to access %p (process local virtual address) which is not currently mapped to any Mali memory.\n", (void*)address)); + + MALI_IGNORE(address); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + return VM_FAULT_SIGBUS; +#else + return NOPFN_SIGBUS; +#endif +} + +static void mali_kernel_memory_vma_open(struct vm_area_struct * vma) +{ + mali_vma_usage_tracker * vma_usage_tracker; + MALI_DEBUG_PRINT(4, ("Open called on vma %p\n", vma)); + + vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data; + vma_usage_tracker->references++; + + return; +} + +static void mali_kernel_memory_vma_close(struct vm_area_struct * vma) +{ + _mali_uk_mem_munmap_s args = {0, }; + mali_memory_allocation * descriptor; + mali_vma_usage_tracker * vma_usage_tracker; + MALI_DEBUG_PRINT(3, ("Close called on vma %p\n", vma)); + + vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data; + + BUG_ON(!vma_usage_tracker); + BUG_ON(0 == vma_usage_tracker->references); + + vma_usage_tracker->references--; + + if (0 != vma_usage_tracker->references) + { + MALI_DEBUG_PRINT(3, ("Ignoring this close, %d references still exists\n", vma_usage_tracker->references)); + return; + } + + /** @note args->context unused, initialized to 0. + * Instead, we use the memory_session from the cookie */ + + descriptor = (mali_memory_allocation *)vma_usage_tracker->cookie; + + args.cookie = (u32)descriptor; + args.mapping = descriptor->mapping; + args.size = descriptor->size; + + _mali_ukk_mem_munmap( &args ); + + /* vma_usage_tracker is free()d by _mali_osk_mem_mapregion_term(). + * In the case of the memory engine, it is called as the release function that has been registered with the engine*/ +} + +void _mali_osk_mem_barrier( void ) +{ + mb(); +} + +void _mali_osk_write_mem_barrier( void ) +{ + wmb(); +} + +mali_io_address _mali_osk_mem_mapioregion( u32 phys, u32 size, const char *description ) +{ + return (mali_io_address)ioremap_nocache(phys, size); +} + +void _mali_osk_mem_unmapioregion( u32 phys, u32 size, mali_io_address virt ) +{ + iounmap((void*)virt); +} + +mali_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 size ) +{ + void * virt; + MALI_DEBUG_ASSERT_POINTER( phys ); + MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) ); + MALI_DEBUG_ASSERT( 0 != size ); + + /* dma_alloc_* uses a limited region of address space. On most arch/marchs + * 2 to 14 MiB is available. This should be enough for the page tables, which + * currently is the only user of this function. */ + virt = dma_alloc_writecombine(NULL, size, phys, GFP_KERNEL | GFP_DMA | __GFP_ZERO); + + MALI_DEBUG_PRINT(3, ("Page table virt: 0x%x = dma_alloc_coherent(size:%d, phys:0x%x, )\n", virt, size, phys)); + + if ( NULL == virt ) + { + MALI_DEBUG_PRINT(5, ("allocioregion: Failed to allocate Pagetable memory, size=0x%.8X\n", size )); + return 0; + } + + MALI_DEBUG_ASSERT( 0 == (*phys & ~_MALI_OSK_CPU_PAGE_MASK) ); + + return (mali_io_address)virt; +} + +void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address virt ) +{ + MALI_DEBUG_ASSERT_POINTER( (void*)virt ); + MALI_DEBUG_ASSERT( 0 != size ); + MALI_DEBUG_ASSERT( 0 == (phys & ( (1 << PAGE_SHIFT) - 1 )) ); + + dma_free_writecombine(NULL, size, virt, phys); +} + +_mali_osk_errcode_t inline _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description ) +{ +#if MALI_LICENSE_IS_GPL + return _MALI_OSK_ERR_OK; /* GPL driver gets the mem region for the resources registered automatically */ +#else + return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK); +#endif +} + +void inline _mali_osk_mem_unreqregion( u32 phys, u32 size ) +{ +#if !MALI_LICENSE_IS_GPL + release_mem_region(phys, size); +#endif +} + +void inline _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val ) +{ + __raw_writel(cpu_to_le32(val),((u8*)addr) + offset); +} + +u32 inline _mali_osk_mem_ioread32( volatile mali_io_address addr, u32 offset ) +{ + return ioread32(((u8*)addr) + offset); +} + +void inline _mali_osk_mem_iowrite32( volatile mali_io_address addr, u32 offset, u32 val ) +{ + iowrite32(val, ((u8*)addr) + offset); +} + +void _mali_osk_cache_flushall( void ) +{ + /** @note Cached memory is not currently supported in this implementation */ +} + +void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size ) +{ + _mali_osk_write_mem_barrier(); +} + +_mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descriptor ) +{ + struct vm_area_struct *vma; + mali_vma_usage_tracker * vma_usage_tracker; + MappingInfo *mappingInfo; + + if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; + + MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); + + vma = (struct vm_area_struct*)descriptor->process_addr_mapping_info; + + if (NULL == vma ) return _MALI_OSK_ERR_FAULT; + + /* Re-write the process_addr_mapping_info */ + mappingInfo = _mali_osk_calloc( 1, sizeof(MappingInfo) ); + + if ( NULL == mappingInfo ) return _MALI_OSK_ERR_FAULT; + + vma_usage_tracker = _mali_osk_calloc( 1, sizeof(mali_vma_usage_tracker) ); + + if (NULL == vma_usage_tracker) + { + MALI_DEBUG_PRINT(2, ("Failed to allocate memory to track memory usage\n")); + _mali_osk_free( mappingInfo ); + return _MALI_OSK_ERR_FAULT; + } + + mappingInfo->vma = vma; + descriptor->process_addr_mapping_info = mappingInfo; + + /* Do the va range allocation - in this case, it was done earlier, so we copy in that information */ + descriptor->mapping = (void __user*)vma->vm_start; + /* list member is already NULL */ + + /* + set some bits which indicate that: + The memory is IO memory, meaning that no paging is to be performed and the memory should not be included in crash dumps + The memory is reserved, meaning that it's present and can never be paged out (see also previous entry) + */ + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_DONTCOPY; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + vma->vm_flags |= VM_RESERVED; +#else + vma->vm_flags |= VM_DONTDUMP; + vma->vm_flags |= VM_DONTEXPAND; + vma->vm_flags |= VM_PFNMAP; +#endif + + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + vma->vm_ops = &mali_kernel_vm_ops; /* Operations used on any memory system */ + + vma_usage_tracker->references = 1; /* set initial reference count to be 1 as vma_open won't be called for the first mmap call */ + vma_usage_tracker->cookie = (u32)descriptor; /* cookie for munmap */ + + vma->vm_private_data = vma_usage_tracker; + + return _MALI_OSK_ERR_OK; +} + +void _mali_osk_mem_mapregion_term( mali_memory_allocation * descriptor ) +{ + struct vm_area_struct* vma; + mali_vma_usage_tracker * vma_usage_tracker; + MappingInfo *mappingInfo; + + if (NULL == descriptor) return; + + MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); + + mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; + + MALI_DEBUG_ASSERT_POINTER( mappingInfo ); + + /* Linux does the right thing as part of munmap to remove the mapping + * All that remains is that we remove the vma_usage_tracker setup in init() */ + vma = mappingInfo->vma; + + MALI_DEBUG_ASSERT_POINTER( vma ); + + /* ASSERT that there are no allocations on the list. Unmap should've been + * called on all OS allocations. */ + MALI_DEBUG_ASSERT( NULL == mappingInfo->list ); + + vma_usage_tracker = vma->vm_private_data; + + /* We only get called if mem_mapregion_init succeeded */ + _mali_osk_free(vma_usage_tracker); + + _mali_osk_free( mappingInfo ); + return; +} + +_mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size ) +{ + struct vm_area_struct *vma; + MappingInfo *mappingInfo; + + if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; + + MALI_DEBUG_ASSERT_POINTER( phys_addr ); + + MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); + + MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) ); + + MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK)); + + if (NULL == descriptor->mapping) return _MALI_OSK_ERR_INVALID_ARGS; + + if (size > (descriptor->size - offset)) + { + MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_map: virtual memory area not large enough to map physical 0x%x size %x into area 0x%x at offset 0x%xr\n", + *phys_addr, size, descriptor->mapping, offset)); + return _MALI_OSK_ERR_FAULT; + } + + mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; + + MALI_DEBUG_ASSERT_POINTER( mappingInfo ); + + vma = mappingInfo->vma; + + if (NULL == vma ) return _MALI_OSK_ERR_FAULT; + + MALI_DEBUG_PRINT(7, ("Process map: mapping 0x%08X to process address 0x%08lX length 0x%08X\n", *phys_addr, (long unsigned int)(descriptor->mapping + offset), size)); + + if ( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC == *phys_addr ) + { + _mali_osk_errcode_t ret; + AllocationList *alloc_item; + u32 linux_phys_frame_num; + + alloc_item = _allocation_list_item_get(); + if (NULL == alloc_item) + { + MALI_DEBUG_PRINT(1, ("Failed to allocate list item\n")); + return _MALI_OSK_ERR_NOMEM; + } + + linux_phys_frame_num = alloc_item->physaddr >> PAGE_SHIFT; + + ret = ( remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, linux_phys_frame_num, size, vma->vm_page_prot) ) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK; + + if ( ret != _MALI_OSK_ERR_OK) + { + MALI_PRINT_ERROR(("%s %d could not remap_pfn_range()\n", __FUNCTION__, __LINE__)); + _allocation_list_item_release(alloc_item); + return ret; + } + + /* Put our alloc_item into the list of allocations on success */ + if (NULL == mappingInfo->list) + { + mappingInfo->list = alloc_item; + } + else + { + mappingInfo->tail->next = alloc_item; + } + + mappingInfo->tail = alloc_item; + alloc_item->next = NULL; + alloc_item->offset = offset; + + /* Write out new physical address on success */ + *phys_addr = alloc_item->physaddr; + + return ret; + } + + /* Otherwise, Use the supplied physical address */ + + /* ASSERT that supplied phys_addr is page aligned */ + MALI_DEBUG_ASSERT( 0 == ((*phys_addr) & ~_MALI_OSK_CPU_PAGE_MASK) ); + + return ( remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, *phys_addr >> PAGE_SHIFT, size, vma->vm_page_prot) ) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK; + +} + +void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags ) +{ + MappingInfo *mappingInfo; + + if (NULL == descriptor) return; + + MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); + + MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) ); + + MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK) ); + + if (NULL == descriptor->mapping) return; + + if (size > (descriptor->size - offset)) + { + MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_unmap: virtual memory area not large enough to unmap size %x from area 0x%x at offset 0x%x\n", + size, descriptor->mapping, offset)); + return; + } + mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; + + MALI_DEBUG_ASSERT_POINTER( mappingInfo ); + + if ( 0 != (flags & _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR) ) + { + /* This physical RAM was allocated in _mali_osk_mem_mapregion_map and + * so needs to be unmapped + */ + while (size) + { + /* First find the allocation in the list of allocations */ + AllocationList *alloc = mappingInfo->list; + AllocationList **prev = &(mappingInfo->list); + + while (NULL != alloc && alloc->offset != offset) + { + prev = &(alloc->next); + alloc = alloc->next; + } + if (alloc == NULL) { + MALI_DEBUG_PRINT(1, ("Unmapping memory that isn't mapped\n")); + size -= _MALI_OSK_CPU_PAGE_SIZE; + offset += _MALI_OSK_CPU_PAGE_SIZE; + continue; + } + + *prev = alloc->next; + _allocation_list_item_release(alloc); + + /* Move onto the next allocation */ + size -= _MALI_OSK_CPU_PAGE_SIZE; + offset += _MALI_OSK_CPU_PAGE_SIZE; + } + } + + /* Linux does the right thing as part of munmap to remove the mapping */ + + return; +} + +u32 _mali_osk_mem_write_safe(void *dest, const void *src, u32 size) +{ +#define MALI_MEM_SAFE_COPY_BLOCK_SIZE 4096 + u32 retval = 0; + void *temp_buf; + + temp_buf = kmalloc(MALI_MEM_SAFE_COPY_BLOCK_SIZE, GFP_KERNEL); + if (NULL != temp_buf) + { + u32 bytes_left_to_copy = size; + u32 i; + for (i = 0; i < size; i += MALI_MEM_SAFE_COPY_BLOCK_SIZE) + { + u32 size_to_copy; + u32 size_copied; + u32 bytes_left; + + if (bytes_left_to_copy > MALI_MEM_SAFE_COPY_BLOCK_SIZE) + { + size_to_copy = MALI_MEM_SAFE_COPY_BLOCK_SIZE; + } + else + { + size_to_copy = bytes_left_to_copy; + } + + bytes_left = copy_from_user(temp_buf, ((char*)src) + i, size_to_copy); + size_copied = size_to_copy - bytes_left; + + bytes_left = copy_to_user(((char*)dest) + i, temp_buf, size_copied); + size_copied -= bytes_left; + + bytes_left_to_copy -= size_copied; + retval += size_copied; + + if (size_copied != size_to_copy) + { + break; /* Early out, we was not able to copy this entire block */ + } + } + + kfree(temp_buf); + } + + return retval; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_mali.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_mali.c new file mode 100644 index 0000000..50d6ddf --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_mali.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_mali.c + * Implementation of the OS abstraction layer which is specific for the Mali kernel device driver + */ +#include +#include +#include +#include + +#include "mali_osk_mali.h" +#include "mali_kernel_common.h" /* MALI_xxx macros */ +#include "mali_osk.h" /* kernel side OS functions */ +#include "mali_uk_types.h" +#include "mali_kernel_linux.h" + +_mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res) +{ + int i; + + if (NULL == mali_platform_device) + { + /* Not connected to a device */ + return _MALI_OSK_ERR_ITEM_NOT_FOUND; + } + + for (i = 0; i < mali_platform_device->num_resources; i++) + { + if (IORESOURCE_MEM == resource_type(&(mali_platform_device->resource[i])) && + mali_platform_device->resource[i].start == addr) + { + if (NULL != res) + { + res->base = addr; + res->description = mali_platform_device->resource[i].name; + + /* Any (optional) IRQ resource belonging to this resource will follow */ + if ((i + 1) < mali_platform_device->num_resources && + IORESOURCE_IRQ == resource_type(&(mali_platform_device->resource[i+1]))) + { + res->irq = mali_platform_device->resource[i+1].start; + } + else + { + res->irq = -1; + } + } + return _MALI_OSK_ERR_OK; + } + } + + return _MALI_OSK_ERR_ITEM_NOT_FOUND; +} + +u32 _mali_osk_resource_base_address(void) +{ + u32 lowest_addr = 0xFFFFFFFF; + u32 ret = 0; + + if (NULL != mali_platform_device) + { + int i; + for (i = 0; i < mali_platform_device->num_resources; i++) + { + if (mali_platform_device->resource[i].flags & IORESOURCE_MEM && + mali_platform_device->resource[i].start < lowest_addr) + { + lowest_addr = mali_platform_device->resource[i].start; + ret = lowest_addr; + } + } + } + + return ret; +} + +_mali_osk_errcode_t _mali_osk_device_data_get(struct _mali_osk_device_data *data) +{ + MALI_DEBUG_ASSERT_POINTER(data); + + if (NULL != mali_platform_device) + { + struct mali_gpu_device_data* os_data = NULL; + + os_data = (struct mali_gpu_device_data*)mali_platform_device->dev.platform_data; + if (NULL != os_data) + { + /* Copy data from OS dependant struct to Mali neutral struct (identical!) */ + data->dedicated_mem_start = os_data->dedicated_mem_start; + data->dedicated_mem_size = os_data->dedicated_mem_size; + data->shared_mem_size = os_data->shared_mem_size; + data->fb_start = os_data->fb_start; + data->fb_size = os_data->fb_size; + data->utilization_interval = os_data->utilization_interval; + data->utilization_callback = os_data->utilization_callback; + data->pmu_switch_delay = os_data->pmu_switch_delay; + return _MALI_OSK_ERR_OK; + } + } + + return _MALI_OSK_ERR_ITEM_NOT_FOUND; +} + +mali_bool _mali_osk_shared_interrupts(void) +{ + u32 irqs[128]; + u32 i, j, irq, num_irqs_found = 0; + + MALI_DEBUG_ASSERT_POINTER(mali_platform_device); + MALI_DEBUG_ASSERT(128 >= mali_platform_device->num_resources); + + for (i = 0; i < mali_platform_device->num_resources; i++) + { + if (IORESOURCE_IRQ & mali_platform_device->resource[i].flags) + { + irq = mali_platform_device->resource[i].start; + + for (j = 0; j < num_irqs_found; ++j) + { + if (irq == irqs[j]) + { + return MALI_TRUE; + } + } + + irqs[num_irqs_found++] = irq; + } + } + + return MALI_FALSE; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_math.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_math.c new file mode 100644 index 0000000..3e62e51 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_math.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_math.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include "mali_osk.h" +#include + +u32 inline _mali_osk_clz( u32 input ) +{ + return 32-fls(input); +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_memory.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_memory.c new file mode 100644 index 0000000..7bb470f --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_memory.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_memory.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include "mali_osk.h" +#include +#include + +void inline *_mali_osk_calloc( u32 n, u32 size ) +{ + return kcalloc(n, size, GFP_KERNEL); +} + +void inline *_mali_osk_malloc( u32 size ) +{ + return kmalloc(size, GFP_KERNEL); +} + +void inline _mali_osk_free( void *ptr ) +{ + kfree(ptr); +} + +void inline *_mali_osk_valloc( u32 size ) +{ + return vmalloc(size); +} + +void inline _mali_osk_vfree( void *ptr ) +{ + vfree(ptr); +} + +void inline *_mali_osk_memcpy( void *dst, const void *src, u32 len ) +{ + return memcpy(dst, src, len); +} + +void inline *_mali_osk_memset( void *s, u32 c, u32 n ) +{ + return memset(s, c, n); +} + +mali_bool _mali_osk_mem_check_allocated( u32 max_allocated ) +{ + /* No need to prevent an out-of-memory dialogue appearing on Linux, + * so we always return MALI_TRUE. + */ + return MALI_TRUE; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_misc.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_misc.c new file mode 100644 index 0000000..ad486db --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_misc.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_misc.c + * Implementation of the OS abstraction layer for the kernel device driver + */ +#include +#include +#include +#include +#include +#include "mali_osk.h" + +void _mali_osk_dbgmsg( const char *fmt, ... ) +{ + va_list args; + va_start(args, fmt); + vprintk(fmt, args); + va_end(args); +} + +u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... ) +{ + int res; + va_list args; + va_start(args, fmt); + + res = vscnprintf(buf, (size_t)size, fmt, args); + + va_end(args); + return res; +} + +void _mali_osk_abort(void) +{ + /* make a simple fault by dereferencing a NULL pointer */ + dump_stack(); + *(int *)0 = 0; +} + +void _mali_osk_break(void) +{ + _mali_osk_abort(); +} + +u32 _mali_osk_get_pid(void) +{ + /* Thread group ID is the process ID on Linux */ + return (u32)current->tgid; +} + +u32 _mali_osk_get_tid(void) +{ + /* pid is actually identifying the thread on Linux */ + return (u32)current->pid; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_notification.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_notification.c new file mode 100644 index 0000000..c265f88 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_notification.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_notification.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include "mali_osk.h" +#include "mali_kernel_common.h" + +#include +#include +#include + +/** + * Declaration of the notification queue object type + * Contains a linked list of notification pending delivery to user space. + * It also contains a wait queue of exclusive waiters blocked in the ioctl + * When a new notification is posted a single thread is resumed. + */ +struct _mali_osk_notification_queue_t_struct +{ + spinlock_t mutex; /**< Mutex protecting the list */ + wait_queue_head_t receive_queue; /**< Threads waiting for new entries to the queue */ + struct list_head head; /**< List of notifications waiting to be picked up */ +}; + +typedef struct _mali_osk_notification_wrapper_t_struct +{ + struct list_head list; /**< Internal linked list variable */ + _mali_osk_notification_t data; /**< Notification data */ +} _mali_osk_notification_wrapper_t; + +_mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void ) +{ + _mali_osk_notification_queue_t * result; + + result = (_mali_osk_notification_queue_t *)kmalloc(sizeof(_mali_osk_notification_queue_t), GFP_KERNEL); + if (NULL == result) return NULL; + + spin_lock_init(&result->mutex); + init_waitqueue_head(&result->receive_queue); + INIT_LIST_HEAD(&result->head); + + return result; +} + +_mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ) +{ + /* OPT Recycling of notification objects */ + _mali_osk_notification_wrapper_t *notification; + + notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size, + GFP_KERNEL | __GFP_HIGH | __GFP_REPEAT); + if (NULL == notification) + { + MALI_DEBUG_PRINT(1, ("Failed to create a notification object\n")); + return NULL; + } + + /* Init the list */ + INIT_LIST_HEAD(¬ification->list); + + if (0 != size) + { + notification->data.result_buffer = ((u8*)notification) + sizeof(_mali_osk_notification_wrapper_t); + } + else + { + notification->data.result_buffer = NULL; + } + + /* set up the non-allocating fields */ + notification->data.notification_type = type; + notification->data.result_buffer_size = size; + + /* all ok */ + return &(notification->data); +} + +void _mali_osk_notification_delete( _mali_osk_notification_t *object ) +{ + _mali_osk_notification_wrapper_t *notification; + MALI_DEBUG_ASSERT_POINTER( object ); + + notification = container_of( object, _mali_osk_notification_wrapper_t, data ); + + /* Free the container */ + kfree(notification); +} + +void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue ) +{ + _mali_osk_notification_t *result; + MALI_DEBUG_ASSERT_POINTER( queue ); + + while (_MALI_OSK_ERR_OK == _mali_osk_notification_queue_dequeue(queue, &result)) + { + _mali_osk_notification_delete( result ); + } + + /* not much to do, just free the memory */ + kfree(queue); +} +void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object ) +{ +#if defined(MALI_UPPER_HALF_SCHEDULING) + unsigned long irq_flags; +#endif + + _mali_osk_notification_wrapper_t *notification; + MALI_DEBUG_ASSERT_POINTER( queue ); + MALI_DEBUG_ASSERT_POINTER( object ); + + notification = container_of( object, _mali_osk_notification_wrapper_t, data ); + +#if defined(MALI_UPPER_HALF_SCHEDULING) + spin_lock_irqsave(&queue->mutex, irq_flags); +#else + spin_lock(&queue->mutex); +#endif + + list_add_tail(¬ification->list, &queue->head); + +#if defined(MALI_UPPER_HALF_SCHEDULING) + spin_unlock_irqrestore(&queue->mutex, irq_flags); +#else + spin_unlock(&queue->mutex); +#endif + + /* and wake up one possible exclusive waiter */ + wake_up(&queue->receive_queue); +} + +_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ) +{ +#if defined(MALI_UPPER_HALF_SCHEDULING) + unsigned long irq_flags; +#endif + + _mali_osk_errcode_t ret = _MALI_OSK_ERR_ITEM_NOT_FOUND; + _mali_osk_notification_wrapper_t *wrapper_object; + +#if defined(MALI_UPPER_HALF_SCHEDULING) + spin_lock_irqsave(&queue->mutex, irq_flags); +#else + spin_lock(&queue->mutex); +#endif + + if (!list_empty(&queue->head)) + { + wrapper_object = list_entry(queue->head.next, _mali_osk_notification_wrapper_t, list); + *result = &(wrapper_object->data); + list_del_init(&wrapper_object->list); + ret = _MALI_OSK_ERR_OK; + } + +#if defined(MALI_UPPER_HALF_SCHEDULING) + spin_unlock_irqrestore(&queue->mutex, irq_flags); +#else + spin_unlock(&queue->mutex); +#endif + + return ret; +} + +_mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ) +{ + /* check input */ + MALI_DEBUG_ASSERT_POINTER( queue ); + MALI_DEBUG_ASSERT_POINTER( result ); + + /* default result */ + *result = NULL; + + if (wait_event_interruptible(queue->receive_queue, + _MALI_OSK_ERR_OK == _mali_osk_notification_queue_dequeue(queue, result))) + { + return _MALI_OSK_ERR_RESTARTSYSCALL; + } + + return _MALI_OSK_ERR_OK; /* all ok */ +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_pm.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_pm.c new file mode 100644 index 0000000..bc19af9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_pm.c @@ -0,0 +1,110 @@ +/** + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_pm.c + * Implementation of the callback functions from common power management + */ + +#include + +#ifdef CONFIG_PM_RUNTIME +#include +#endif /* CONFIG_PM_RUNTIME */ +#include +#include +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_kernel_linux.h" + +static _mali_osk_atomic_t mali_pm_ref_count; + +void _mali_osk_pm_dev_enable(void) +{ + _mali_osk_atomic_init(&mali_pm_ref_count, 0); +} + +void _mali_osk_pm_dev_disable(void) +{ + _mali_osk_atomic_term(&mali_pm_ref_count); +} + +/* Can NOT run in atomic context */ +_mali_osk_errcode_t _mali_osk_pm_dev_ref_add(void) +{ +#ifdef CONFIG_PM_RUNTIME + int err; + MALI_DEBUG_ASSERT_POINTER(mali_platform_device); + err = pm_runtime_get_sync(&(mali_platform_device->dev)); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + pm_runtime_mark_last_busy(&(mali_platform_device->dev)); +#endif + if (0 > err) + { + MALI_PRINT_ERROR(("Mali OSK PM: pm_runtime_get_sync() returned error code %d\n", err)); + return _MALI_OSK_ERR_FAULT; + } + _mali_osk_atomic_inc(&mali_pm_ref_count); + MALI_DEBUG_PRINT(4, ("Mali OSK PM: Power ref taken (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count))); +#endif + return _MALI_OSK_ERR_OK; +} + +/* Can run in atomic context */ +void _mali_osk_pm_dev_ref_dec(void) +{ +#ifdef CONFIG_PM_RUNTIME + MALI_DEBUG_ASSERT_POINTER(mali_platform_device); + _mali_osk_atomic_dec(&mali_pm_ref_count); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + pm_runtime_mark_last_busy(&(mali_platform_device->dev)); + pm_runtime_put_autosuspend(&(mali_platform_device->dev)); +#else + pm_runtime_put(&(mali_platform_device->dev)); +#endif + MALI_DEBUG_PRINT(4, ("Mali OSK PM: Power ref released (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count))); +#endif +} + +/* Can run in atomic context */ +mali_bool _mali_osk_pm_dev_ref_add_no_power_on(void) +{ +#ifdef CONFIG_PM_RUNTIME + u32 ref; + MALI_DEBUG_ASSERT_POINTER(mali_platform_device); + pm_runtime_get_noresume(&(mali_platform_device->dev)); + ref = _mali_osk_atomic_read(&mali_pm_ref_count); + MALI_DEBUG_PRINT(4, ("Mali OSK PM: No-power ref taken (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count))); + return ref > 0 ? MALI_TRUE : MALI_FALSE; +#else + return MALI_TRUE; +#endif +} + +/* Can run in atomic context */ +void _mali_osk_pm_dev_ref_dec_no_power_on(void) +{ +#ifdef CONFIG_PM_RUNTIME + MALI_DEBUG_ASSERT_POINTER(mali_platform_device); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + pm_runtime_put_autosuspend(&(mali_platform_device->dev)); +#else + pm_runtime_put(&(mali_platform_device->dev)); +#endif + MALI_DEBUG_PRINT(4, ("Mali OSK PM: No-power ref released (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count))); +#endif +} + +void _mali_osk_pm_dev_barrier(void) +{ +#ifdef CONFIG_PM_RUNTIME + pm_runtime_barrier(&(mali_platform_device->dev)); +#endif +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_profiling.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_profiling.c new file mode 100644 index 0000000..5429329 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_profiling.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_ukk.h" +#include "mali_uk_types.h" +#include "mali_osk_profiling.h" +#include "mali_linux_trace.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_pp_scheduler.h" +#include "mali_l2_cache.h" +#include "mali_user_settings_db.h" + +_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start) +{ + if (MALI_TRUE == auto_start) + { + mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); + } + + return _MALI_OSK_ERR_OK; +} + +void _mali_osk_profiling_term(void) +{ + /* Nothing to do */ +} + +_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_osk_profiling_stop(u32 *count) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +u32 _mali_osk_profiling_get_count(void) +{ + return 0; +} + +_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_osk_profiling_clear(void) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +mali_bool _mali_osk_profiling_is_recording(void) +{ + return MALI_FALSE; +} + +mali_bool _mali_osk_profiling_have_recording(void) +{ + return MALI_FALSE; +} + +void _mali_osk_profiling_report_sw_counters(u32 *counters) +{ + trace_mali_sw_counters(_mali_osk_get_pid(), _mali_osk_get_tid(), NULL, counters); +} + + +_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args) +{ + return _mali_osk_profiling_start(&args->limit); +} + +_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) +{ + /* Always add process and thread identificator in the first two data elements for events from user space */ + _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args) +{ + return _mali_osk_profiling_stop(&args->count); +} + +_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args) +{ + return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data); +} + +_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args) +{ + return _mali_osk_profiling_clear(); +} + +_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args) +{ + _mali_osk_profiling_report_sw_counters(args->counters); + return _MALI_OSK_ERR_OK; +} + +/** + * Called by gator.ko to set HW counters + * + * @param counter_id The counter ID. + * @param event_id Event ID that the counter should count (HW counter value from TRM). + * + * @return 1 on success, 0 on failure. + */ +int _mali_profiling_set_event(u32 counter_id, s32 event_id) +{ + if (COUNTER_VP_0_C0 == counter_id) + { + if (MALI_TRUE == mali_gp_job_set_gp_counter_src0(event_id)) + { + return 1; + } + } + + if (COUNTER_VP_0_C1 == counter_id) + { + if (MALI_TRUE == mali_gp_job_set_gp_counter_src1(event_id)) + { + return 1; + } + } + + if (COUNTER_FP_0_C0 == counter_id) + { + if (MALI_TRUE == mali_pp_job_set_pp_counter_src0(event_id)) + { + return 1; + } + } + + if (COUNTER_FP_0_C1 == counter_id) + { + if (MALI_TRUE == mali_pp_job_set_pp_counter_src1(event_id)) + { + return 1; + } + } + + if (COUNTER_L2_0_C0 <= counter_id && COUNTER_L2_2_C1 >= counter_id) + { + u32 core_id = (counter_id - COUNTER_L2_0_C0) >> 1; + struct mali_l2_cache_core* l2_cache_core = mali_l2_cache_core_get_glob_l2_core(core_id); + + if (NULL != l2_cache_core) + { + u32 counter_src = (counter_id - COUNTER_L2_0_C0) & 1; + if (0 == counter_src) + { + if (MALI_TRUE == mali_l2_cache_core_set_counter_src0(l2_cache_core, event_id)) + { + return 1; + } + } + else + { + if (MALI_TRUE == mali_l2_cache_core_set_counter_src1(l2_cache_core, event_id)) + { + return 1; + } + } + } + } + + return 0; +} + +/** + * Called by gator.ko to retrieve the L2 cache counter values for all L2 cache cores. + * The L2 cache counters are unique in that they are polled by gator, rather than being + * transmitted via the tracepoint mechanism. + * + * @param values Pointer to a _mali_profiling_l2_counter_values structure where + * the counter sources and values will be output + * @return 0 if all went well; otherwise, return the mask with the bits set for the powered off cores + */ +u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values) +{ + struct mali_l2_cache_core *l2_cache; + u32 l2_cores_num = mali_l2_cache_core_get_glob_num_l2_cores(); + u32 i; + u32 ret = 0; + + MALI_DEBUG_ASSERT(l2_cores_num <= 3); + + for (i = 0; i < l2_cores_num; i++) + { + l2_cache = mali_l2_cache_core_get_glob_l2_core(i); + + if (NULL == l2_cache) + { + continue; + } + + if (MALI_TRUE == mali_l2_cache_lock_power_state(l2_cache)) + { + /* It is now safe to access the L2 cache core in order to retrieve the counters */ + mali_l2_cache_core_get_counter_values(l2_cache, + &values->cores[i].source0, + &values->cores[i].value0, + &values->cores[i].source1, + &values->cores[i].value1); + } + else + { + /* The core was not available, set the right bit in the mask. */ + ret |= (1 << i); + } + mali_l2_cache_unlock_power_state(l2_cache); + } + + return ret; +} + +/** + * Called by gator to control the production of profiling information at runtime. + */ +void _mali_profiling_control(u32 action, u32 value) +{ + switch(action) + { + case FBDUMP_CONTROL_ENABLE: + mali_set_user_setting(_MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, (value == 0 ? MALI_FALSE : MALI_TRUE)); + break; + case FBDUMP_CONTROL_RATE: + mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, value); + break; + case SW_COUNTER_ENABLE: + mali_set_user_setting(_MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, value); + break; + case FBDUMP_CONTROL_RESIZE_FACTOR: + mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, value); + break; + default: + break; /* Ignore unimplemented actions */ + } +} + +/** + * Called by gator to get mali api version. + */ +u32 _mali_profiling_get_api_version(void) +{ + return MALI_PROFILING_API_VERSION; +} + +/** +* Called by gator to get the data about Mali instance in use: +* product id, version, number of cores +*/ +void _mali_profiling_get_mali_version(struct _mali_profiling_mali_version *values) +{ + values->mali_product_id = (u32)mali_kernel_core_get_product_id(); + values->mali_version_major = mali_kernel_core_get_gpu_major_version(); + values->mali_version_minor = mali_kernel_core_get_gpu_minor_version(); + values->num_of_l2_cores = mali_l2_cache_core_get_glob_num_l2_cores(); + values->num_of_fp_cores = mali_pp_scheduler_get_num_cores_total(); + values->num_of_vp_cores = 1; +} + +EXPORT_SYMBOL(_mali_profiling_set_event); +EXPORT_SYMBOL(_mali_profiling_get_l2_counters); +EXPORT_SYMBOL(_mali_profiling_control); +EXPORT_SYMBOL(_mali_profiling_get_api_version); +EXPORT_SYMBOL(_mali_profiling_get_mali_version); diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_specific.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_specific.h new file mode 100644 index 0000000..15d98e0 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_specific.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_specific.h + * Defines per-OS Kernel level specifics, such as unusual workarounds for + * certain OSs. + */ + +#ifndef __MALI_OSK_SPECIFIC_H__ +#define __MALI_OSK_SPECIFIC_H__ + +#include + +#include "mali_sync.h" + +#define MALI_STATIC_INLINE static inline +#define MALI_NON_STATIC_INLINE inline + +#ifdef CONFIG_SYNC +typedef struct sync_timeline mali_sync_tl; +typedef struct sync_pt mali_sync_pt; +#endif /* CONFIG_SYNC */ + +MALI_STATIC_INLINE u32 _mali_osk_copy_from_user(void *to, void *from, u32 n) +{ + return (u32)copy_from_user(to, from, (unsigned long)n); +} + +#endif /* __MALI_OSK_SPECIFIC_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_time.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_time.c new file mode 100644 index 0000000..2aa6588 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_time.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_time.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include "mali_osk.h" +#include +#include +#include + +int _mali_osk_time_after( u32 ticka, u32 tickb ) +{ + return time_after((unsigned long)ticka, (unsigned long)tickb); +} + +u32 _mali_osk_time_mstoticks( u32 ms ) +{ + return msecs_to_jiffies(ms); +} + +u32 _mali_osk_time_tickstoms( u32 ticks ) +{ + return jiffies_to_msecs(ticks); +} + +u32 _mali_osk_time_tickcount( void ) +{ + return jiffies; +} + +void _mali_osk_time_ubusydelay( u32 usecs ) +{ + udelay(usecs); +} + +u64 _mali_osk_time_get_ns( void ) +{ + struct timespec tsval; + getnstimeofday(&tsval); + return (u64)timespec_to_ns(&tsval); +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_timers.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_timers.c new file mode 100644 index 0000000..0e28b32 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_timers.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_timers.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include +#include +#include "mali_osk.h" +#include "mali_kernel_common.h" + +struct _mali_osk_timer_t_struct +{ + struct timer_list timer; +}; + +typedef void (*timer_timeout_function_t)(unsigned long); + +_mali_osk_timer_t *_mali_osk_timer_init(void) +{ + _mali_osk_timer_t *t = (_mali_osk_timer_t*)kmalloc(sizeof(_mali_osk_timer_t), GFP_KERNEL); + if (NULL != t) init_timer(&t->timer); + return t; +} + +void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + tim->timer.expires = jiffies + ticks_to_expire; + add_timer(&(tim->timer)); +} + +void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 ticks_to_expire) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + mod_timer(&(tim->timer), jiffies + ticks_to_expire); +} + +void _mali_osk_timer_del( _mali_osk_timer_t *tim ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + del_timer_sync(&(tim->timer)); +} + +void _mali_osk_timer_del_async( _mali_osk_timer_t *tim ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + del_timer(&(tim->timer)); +} + +mali_bool _mali_osk_timer_pending( _mali_osk_timer_t *tim ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + return 1 == timer_pending(&(tim->timer)); +} + +void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + tim->timer.data = (unsigned long)data; + tim->timer.function = (timer_timeout_function_t)callback; +} + +void _mali_osk_timer_term( _mali_osk_timer_t *tim ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + kfree(tim); +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wait_queue.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wait_queue.c new file mode 100644 index 0000000..ce0561d --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wait_queue.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_wait_queue.c + * Implemenation of the OS abstraction layer for the kernel device driver + */ + +#include +#include +#include + +#include "mali_osk.h" +#include "mali_kernel_common.h" + +struct _mali_osk_wait_queue_t_struct +{ + wait_queue_head_t wait_queue; +}; + +_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void ) +{ + _mali_osk_wait_queue_t* ret = NULL; + + ret = kmalloc(sizeof(_mali_osk_wait_queue_t), GFP_KERNEL); + + if (NULL == ret) + { + return ret; + } + + init_waitqueue_head(&ret->wait_queue); + MALI_DEBUG_ASSERT(!waitqueue_active(&ret->wait_queue)); + + return ret; +} + +void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void) ) +{ + MALI_DEBUG_ASSERT_POINTER( queue ); + MALI_DEBUG_PRINT(6, ("Adding to wait queue %p\n", queue)); + wait_event(queue->wait_queue, condition()); +} + +void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue ) +{ + MALI_DEBUG_ASSERT_POINTER( queue ); + + /* if queue is empty, don't attempt to wake up its elements */ + if (!waitqueue_active(&queue->wait_queue)) return; + + MALI_DEBUG_PRINT(6, ("Waking up elements in wait queue %p ....\n", queue)); + + wake_up_all(&queue->wait_queue); + + MALI_DEBUG_PRINT(6, ("... elements in wait queue %p woken up\n", queue)); +} + +void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue ) +{ + /* Parameter validation */ + MALI_DEBUG_ASSERT_POINTER( queue ); + + /* Linux requires no explicit termination of wait queues */ + kfree(queue); +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wq.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wq.c new file mode 100644 index 0000000..23f5720 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wq.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_wq.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include /* For memory allocation */ +#include +#include + +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_kernel_license.h" +#include "mali_kernel_linux.h" + +typedef struct _mali_osk_wq_work_t_struct +{ + _mali_osk_wq_work_handler_t handler; + void *data; + struct work_struct work_handle; +} mali_osk_wq_work_object_t; + +#if MALI_LICENSE_IS_GPL +struct workqueue_struct *mali_wq = NULL; +#endif + +static void _mali_osk_wq_work_func ( struct work_struct *work ); + +_mali_osk_errcode_t _mali_osk_wq_init(void) +{ +#if MALI_LICENSE_IS_GPL + MALI_DEBUG_ASSERT(NULL == mali_wq); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) + mali_wq = alloc_workqueue("mali", WQ_UNBOUND, 0); +#else + mali_wq = create_workqueue("mali"); +#endif + if(NULL == mali_wq) + { + MALI_PRINT_ERROR(("Unable to create Mali workqueue\n")); + return _MALI_OSK_ERR_FAULT; + } +#endif + + return _MALI_OSK_ERR_OK; +} + +void _mali_osk_wq_flush(void) +{ +#if MALI_LICENSE_IS_GPL + flush_workqueue(mali_wq); +#else + flush_scheduled_work(); +#endif +} + +void _mali_osk_wq_term(void) +{ +#if MALI_LICENSE_IS_GPL + MALI_DEBUG_ASSERT(NULL != mali_wq); + + flush_workqueue(mali_wq); + destroy_workqueue(mali_wq); + mali_wq = NULL; +#else + flush_scheduled_work(); +#endif +} + +_mali_osk_wq_work_t *_mali_osk_wq_create_work( _mali_osk_wq_work_handler_t handler, void *data ) +{ + mali_osk_wq_work_object_t *work = kmalloc(sizeof(mali_osk_wq_work_object_t), GFP_KERNEL); + + if (NULL == work) return NULL; + + work->handler = handler; + work->data = data; + + INIT_WORK( &work->work_handle, _mali_osk_wq_work_func ); + + return work; +} + +void _mali_osk_wq_delete_work( _mali_osk_wq_work_t *work ) +{ + mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work; + _mali_osk_wq_flush(); + kfree(work_object); +} + +void _mali_osk_wq_delete_work_nonflush( _mali_osk_wq_work_t *work ) +{ + mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work; + kfree(work_object); +} + +void _mali_osk_wq_schedule_work( _mali_osk_wq_work_t *work ) +{ + mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work; +#if MALI_LICENSE_IS_GPL + queue_work(mali_wq, &work_object->work_handle); +#else + schedule_work(&work_object->work_handle); +#endif +} + +static void _mali_osk_wq_work_func ( struct work_struct *work ) +{ + mali_osk_wq_work_object_t *work_object; + + work_object = _MALI_OSK_CONTAINER_OF(work, mali_osk_wq_work_object_t, work_handle); + work_object->handler(work_object->data); +} + diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_pmu_power_up_down.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_pmu_power_up_down.c new file mode 100644 index 0000000..05dc291 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_pmu_power_up_down.c @@ -0,0 +1,75 @@ +/** + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_pmu_power_up_down.c + */ + +#include +#include +#include +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_pmu.h" +#include "mali_pp_scheduler.h" +#include "linux/mali/mali_utgard.h" + +/* Mali PMU power up/down APIs */ + +int mali_pmu_powerup(void) +{ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(5, ("Mali PMU: Power up\n")); + + MALI_DEBUG_ASSERT_POINTER(pmu); + if (NULL == pmu) + { + return -ENXIO; + } + + if (_MALI_OSK_ERR_OK != mali_pmu_power_up_all(pmu)) + { + return -EFAULT; + } + + return 0; +} + +EXPORT_SYMBOL(mali_pmu_powerup); + +int mali_pmu_powerdown(void) +{ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(5, ("Mali PMU: Power down\n")); + + MALI_DEBUG_ASSERT_POINTER(pmu); + if (NULL == pmu) + { + return -ENXIO; + } + + if (_MALI_OSK_ERR_OK != mali_pmu_power_down_all(pmu)) + { + return -EFAULT; + } + + return 0; +} + +EXPORT_SYMBOL(mali_pmu_powerdown); + +int mali_perf_set_num_pp_cores(unsigned int num_cores) +{ + return mali_pp_scheduler_set_perf_level(num_cores); +} + +EXPORT_SYMBOL(mali_perf_set_num_pp_cores); diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_events.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_events.h new file mode 100644 index 0000000..2639a40 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_events.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PROFILING_EVENTS_H__ +#define __MALI_PROFILING_EVENTS_H__ + +/* Simple wrapper in order to find the OS specific location of this file */ +#include + +#endif /* __MALI_PROFILING_EVENTS_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_gator_api.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_gator_api.h new file mode 100644 index 0000000..c111cfd --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_gator_api.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PROFILING_GATOR_API_H__ +#define __MALI_PROFILING_GATOR_API_H__ + +/* Simple wrapper in order to find the OS specific location of this file */ +#include + +#endif /* __MALI_PROFILING_GATOR_API_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.c new file mode 100644 index 0000000..e40a800 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_ukk.h" +#include "mali_timestamp.h" +#include "mali_osk_profiling.h" +#include "mali_user_settings_db.h" +#include "mali_profiling_internal.h" + +typedef struct mali_profiling_entry +{ + u64 timestamp; + u32 event_id; + u32 data[5]; +} mali_profiling_entry; + + +typedef enum mali_profiling_state +{ + MALI_PROFILING_STATE_UNINITIALIZED, + MALI_PROFILING_STATE_IDLE, + MALI_PROFILING_STATE_RUNNING, + MALI_PROFILING_STATE_RETURN, +} mali_profiling_state; + +static _mali_osk_lock_t *lock = NULL; +static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED; +static mali_profiling_entry* profile_entries = NULL; +static _mali_osk_atomic_t profile_insert_index; +static u32 profile_mask = 0; +static inline void add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4); + +void probe_mali_timeline_event(void *data, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned + int d2, unsigned int d3, unsigned int d4)) +{ + add_event(event_id, d0, d1, d2, d3, d4); +} + +_mali_osk_errcode_t _mali_internal_profiling_init(mali_bool auto_start) +{ + profile_entries = NULL; + profile_mask = 0; + _mali_osk_atomic_init(&profile_insert_index, 0); + + lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PROFILING); + if (NULL == lock) + { + return _MALI_OSK_ERR_FAULT; + } + + prof_state = MALI_PROFILING_STATE_IDLE; + + if (MALI_TRUE == auto_start) + { + u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* Use maximum buffer size */ + + mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); + if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit)) + { + return _MALI_OSK_ERR_FAULT; + } + } + + return _MALI_OSK_ERR_OK; +} + +void _mali_internal_profiling_term(void) +{ + u32 count; + + /* Ensure profiling is stopped */ + _mali_internal_profiling_stop(&count); + + prof_state = MALI_PROFILING_STATE_UNINITIALIZED; + + if (NULL != profile_entries) + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + if (NULL != lock) + { + _mali_osk_lock_term(lock); + lock = NULL; + } +} + +_mali_osk_errcode_t _mali_internal_profiling_start(u32 * limit) +{ + _mali_osk_errcode_t ret; + mali_profiling_entry *new_profile_entries; + + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (MALI_PROFILING_STATE_RUNNING == prof_state) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_BUSY; + } + + new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry)); + + if (NULL == new_profile_entries) + { + _mali_osk_vfree(new_profile_entries); + return _MALI_OSK_ERR_NOMEM; + } + + if (MALI_PROFILING_MAX_BUFFER_ENTRIES < *limit) + { + *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; + } + + profile_mask = 1; + while (profile_mask <= *limit) + { + profile_mask <<= 1; + } + profile_mask >>= 1; + + *limit = profile_mask; + + profile_mask--; /* turns the power of two into a mask of one less */ + + if (MALI_PROFILING_STATE_IDLE != prof_state) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_vfree(new_profile_entries); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + profile_entries = new_profile_entries; + + ret = _mali_timestamp_reset(); + + if (_MALI_OSK_ERR_OK == ret) + { + prof_state = MALI_PROFILING_STATE_RUNNING; + } + else + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + register_trace_mali_timeline_event(probe_mali_timeline_event, NULL); + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return ret; +} + +static inline void add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4) +{ + u32 cur_index = (_mali_osk_atomic_inc_return(&profile_insert_index) - 1) & profile_mask; + + profile_entries[cur_index].timestamp = _mali_timestamp_get(); + profile_entries[cur_index].event_id = event_id; + profile_entries[cur_index].data[0] = data0; + profile_entries[cur_index].data[1] = data1; + profile_entries[cur_index].data[2] = data2; + profile_entries[cur_index].data[3] = data3; + profile_entries[cur_index].data[4] = data4; + + /* If event is "leave API function", add current memory usage to the event + * as data point 4. This is used in timeline profiling to indicate how + * much memory was used when leaving a function. */ + if (event_id == (MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC)) + { + profile_entries[cur_index].data[4] = _mali_ukk_report_memory_usage(); + } +} + +_mali_osk_errcode_t _mali_internal_profiling_stop(u32 * count) +{ + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (MALI_PROFILING_STATE_RUNNING != prof_state) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + /* go into return state (user to retreive events), no more events will be added after this */ + prof_state = MALI_PROFILING_STATE_RETURN; + + unregister_trace_mali_timeline_event(probe_mali_timeline_event, NULL); + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + + tracepoint_synchronize_unregister(); + + *count = _mali_osk_atomic_read(&profile_insert_index); + if (*count > profile_mask) *count = profile_mask; + + return _MALI_OSK_ERR_OK; +} + +u32 _mali_internal_profiling_get_count(void) +{ + u32 retval = 0; + + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + if (MALI_PROFILING_STATE_RETURN == prof_state) + { + retval = _mali_osk_atomic_read(&profile_insert_index); + if (retval > profile_mask) retval = profile_mask; + } + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + + return retval; +} + +_mali_osk_errcode_t _mali_internal_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) +{ + u32 raw_index = _mali_osk_atomic_read(&profile_insert_index); + + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (index < profile_mask) + { + if ((raw_index & ~profile_mask) != 0) + { + index += raw_index; + index &= profile_mask; + } + + if (prof_state != MALI_PROFILING_STATE_RETURN) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + if(index >= raw_index) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_FAULT; + } + + *timestamp = profile_entries[index].timestamp; + *event_id = profile_entries[index].event_id; + data[0] = profile_entries[index].data[0]; + data[1] = profile_entries[index].data[1]; + data[2] = profile_entries[index].data[2]; + data[3] = profile_entries[index].data[3]; + data[4] = profile_entries[index].data[4]; + } + else + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_FAULT; + } + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_internal_profiling_clear(void) +{ + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (MALI_PROFILING_STATE_RETURN != prof_state) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + prof_state = MALI_PROFILING_STATE_IDLE; + profile_mask = 0; + _mali_osk_atomic_init(&profile_insert_index, 0); + + if (NULL != profile_entries) + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_OK; +} + +mali_bool _mali_internal_profiling_is_recording(void) +{ + return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE; +} + +mali_bool _mali_internal_profiling_have_recording(void) +{ + return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.h new file mode 100644 index 0000000..092b9b0 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PROFILING_INTERNAL_H__ +#define __MALI_PROFILING_INTERNAL_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mali_osk.h" + +int _mali_internal_profiling_init(mali_bool auto_start); +void _mali_internal_profiling_term(void); + +mali_bool _mali_internal_profiling_is_recording(void); +mali_bool _mali_internal_profiling_have_recording(void); +_mali_osk_errcode_t _mali_internal_profiling_clear(void); +_mali_osk_errcode_t _mali_internal_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]); +u32 _mali_internal_profiling_get_count(void); +int _mali_internal_profiling_stop(u32 * count); +int _mali_internal_profiling_start(u32 * limit); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_PROFILING_INTERNAL_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.c new file mode 100644 index 0000000..6293610 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.c @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_sync.c + * + */ + +#include +#include +#include + +#include "mali_osk.h" +#include "mali_kernel_common.h" + +struct mali_sync_timeline +{ + struct sync_timeline timeline; + atomic_t counter; + atomic_t signalled; +}; + +struct mali_sync_pt +{ + struct sync_pt pt; + u32 order; + s32 error; + struct timer_list timer; +}; + +static void mali_sync_timed_pt_timeout(unsigned long data); + +static inline struct mali_sync_timeline *to_mali_sync_timeline(struct sync_timeline *timeline) +{ + return container_of(timeline, struct mali_sync_timeline, timeline); +} + +static inline struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt) +{ + return container_of(pt, struct mali_sync_pt, pt); +} + +static struct sync_pt *timeline_dup(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_pt *new_mpt; + struct sync_pt *new_pt = sync_pt_create(pt->parent, sizeof(struct mali_sync_pt)); + + if (!new_pt) + { + return NULL; + } + + new_mpt = to_mali_sync_pt(new_pt); + new_mpt->order = mpt->order; + + return new_pt; + +} + +static int timeline_has_signaled(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent); + long diff; + + if (0 != mpt->error) + { + return mpt->error; + } + + diff = atomic_read(&mtl->signalled) - mpt->order; + + return diff >= 0; +} + +static int timeline_compare(struct sync_pt *a, struct sync_pt *b) +{ + struct mali_sync_pt *ma = container_of(a, struct mali_sync_pt, pt); + struct mali_sync_pt *mb = container_of(b, struct mali_sync_pt, pt); + + long diff = ma->order - mb->order; + + if (diff < 0) + { + return -1; + } + else if (diff == 0) + { + return 0; + } + else + { + return 1; + } +} + +static void timeline_free_pt(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + + if (mpt->timer.function == mali_sync_timed_pt_timeout) + { + del_timer_sync(&mpt->timer); + } +} + +static void timeline_print_tl(struct seq_file *s, struct sync_timeline *sync_timeline) +{ + struct mali_sync_timeline *mtl = to_mali_sync_timeline(sync_timeline); + + seq_printf(s, "%u, %u", atomic_read(&mtl->signalled), atomic_read(&mtl->counter)); +} + +static void timeline_print_pt(struct seq_file *s, struct sync_pt *sync_pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(sync_pt); + + seq_printf(s, "%u", mpt->order); + +} + +static struct sync_timeline_ops mali_timeline_ops = { + .driver_name = "Mali", + .dup = timeline_dup, + .has_signaled = timeline_has_signaled, + .compare = timeline_compare, + .free_pt = timeline_free_pt, + .print_obj = timeline_print_tl, + .print_pt = timeline_print_pt +}; + +int mali_sync_timeline_is_ours(struct sync_timeline *timeline) +{ + return (timeline->ops == &mali_timeline_ops); +} + +struct sync_timeline *mali_sync_timeline_alloc(const char * name) +{ + struct sync_timeline *tl; + struct mali_sync_timeline *mtl; + + tl = sync_timeline_create(&mali_timeline_ops, + sizeof(struct mali_sync_timeline), name); + if (!tl) + { + return NULL; + } + + /* Set the counter in our private struct */ + mtl = to_mali_sync_timeline(tl); + atomic_set(&mtl->counter, 0); + atomic_set(&mtl->signalled, 0); + + return tl; +} + +struct sync_pt *mali_sync_pt_alloc(struct sync_timeline *parent) +{ + struct sync_pt *pt = sync_pt_create(parent, sizeof(struct mali_sync_pt)); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(parent); + struct mali_sync_pt *mpt; + + if (!pt) + { + return NULL; + } + + mpt = to_mali_sync_pt(pt); + mpt->order = atomic_inc_return(&mtl->counter); + mpt->error = 0; + + return pt; +} + +static void mali_sync_timed_pt_timeout(unsigned long data) +{ + struct sync_pt *pt = (struct sync_pt *)data; + + MALI_DEBUG_ASSERT_POINTER(pt); + + mali_sync_signal_pt(pt, -ETIME); +} + +struct sync_pt *mali_sync_timed_pt_alloc(struct sync_timeline *parent) +{ + struct sync_pt *pt; + struct mali_sync_pt *mpt; + const u32 timeout = msecs_to_jiffies(MALI_SYNC_TIMED_FENCE_TIMEOUT); + + pt = mali_sync_pt_alloc(parent); + if (NULL == pt) return NULL; + mpt = to_mali_sync_pt(pt); + + init_timer(&mpt->timer); + + mpt->timer.function = mali_sync_timed_pt_timeout; + mpt->timer.data = (unsigned long)pt; + mpt->timer.expires = jiffies + timeout; + + add_timer(&mpt->timer); + + return pt; +} + +/* + * Returns 0 if sync_pt has been committed and are ready for use, -ETIME if + * timeout already happened and the fence has been signalled. + * + * If an error occurs the sync point can not be used. + */ +int mali_sync_timed_commit(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + int ret; + + if (!mali_sync_timeline_is_ours(pt->parent)) + { + return -EINVAL; + } + + /* Stop timer */ + ret = del_timer_sync(&mpt->timer); + + if (0 == ret) + { + return -ETIME; + } + + MALI_DEBUG_ASSERT(0 == timeline_has_signaled(pt)); + + return 0; +} + +void mali_sync_signal_pt(struct sync_pt *pt, int error) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent); + int signalled; + long diff; + + if (0 != error) + { + MALI_DEBUG_ASSERT(0 > error); + mpt->error = error; + } + + do { + + signalled = atomic_read(&mtl->signalled); + + diff = signalled - mpt->order; + + if (diff > 0) + { + /* The timeline is already at or ahead of this point. This should not happen unless userspace + * has been signalling fences out of order, so warn but don't violate the sync_pt API. + * The warning is only in debug builds to prevent a malicious user being able to spam dmesg. + */ + MALI_DEBUG_PRINT_ERROR(("Sync points were triggerd in a different order to allocation!\n")); + return; + } + } while (atomic_cmpxchg(&mtl->signalled, signalled, mpt->order) != signalled); + + sync_timeline_signal(pt->parent); +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.h new file mode 100644 index 0000000..4415ec6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_sync.h + * + */ + +#ifndef _MALI_SYNC_H_ +#define _MALI_SYNC_H_ + +#ifdef CONFIG_SYNC + +#include +#include + +#define MALI_SYNC_TIMED_FENCE_TIMEOUT 4000 /* 4s */ + +/* + * Create a stream object. + * Built on top of timeline object. + * Exposed as a file descriptor. + * Life-time controlled via the file descriptor: + * - dup to add a ref + * - close to remove a ref + */ +_mali_osk_errcode_t mali_stream_create(const char * name, int * out_fd); + +/* + * Create a fence in a stream object + */ +struct sync_pt *mali_stream_create_point(int tl_fd); +int mali_stream_create_fence(struct sync_pt *pt); +int mali_stream_create_empty_fence(int tl_fd); + +/** + * Commit an empty timed fence + * + * This stops the timer of the empty fence and returns wether or not the fence + * is still suitable for use. + * + * Returns -ETIME if fence is already signalled, in which case it can not be + * used, or 0 when the timer was stopped and the fence is OK to use. + */ +int mali_sync_timed_commit(struct sync_pt *pt); + +/* + * Validate a fd to be a valid fence + * No reference is taken. + * + * This function is only usable to catch unintentional user errors early, + * it does not stop malicious code changing the fd after this function returns. + */ +_mali_osk_errcode_t mali_fence_validate(int fd); + + +/* Returns true if the specified timeline is allocated by Mali */ +int mali_sync_timeline_is_ours(struct sync_timeline *timeline); + +/* Allocates a timeline for Mali + * + * One timeline should be allocated per API context. + */ +struct sync_timeline *mali_sync_timeline_alloc(const char *name); + +/* Allocates a sync point within the timeline. + * + * The timeline must be the one allocated by mali_sync_timeline_alloc + * + * Sync points must be triggered in *exactly* the same order as they are allocated. + */ +struct sync_pt *mali_sync_pt_alloc(struct sync_timeline *parent); + +/* Allocates a timed sync point within the timeline. + * + * The timeline must be the one allocated by mali_sync_timeline_alloc + * + * Sync points must be triggered in *exactly* the same order as they are allocated. + * + * Timed sync points should be backed by a proper event before reaching the + * timeout. If timeout is reached the fence will be signalled with an error (-ETIME). + */ +struct sync_pt *mali_sync_timed_pt_alloc(struct sync_timeline *parent); + +/* Signals a particular sync point + * + * Sync points must be triggered in *exactly* the same order as they are allocated. + * + * If they are signalled in the wrong order then a message will be printed in debug + * builds and otherwise attempts to signal order sync_pts will be ignored. + */ +void mali_sync_signal_pt(struct sync_pt *pt, int error); + +#endif /* CONFIG_SYNC */ +#endif /* _MALI_SYNC_H_ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_sync_user.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync_user.c new file mode 100644 index 0000000..7f0fddfc --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync_user.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_sync_user.c + * + */ + +#ifdef CONFIG_SYNC + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_sync.h" + +static int mali_stream_close(struct inode * inode, struct file * file) +{ + struct sync_timeline * tl; + tl = (struct sync_timeline*)file->private_data; + BUG_ON(!tl); + sync_timeline_destroy(tl); + return 0; +} + +static struct file_operations stream_fops = +{ + .owner = THIS_MODULE, + .release = mali_stream_close, +}; + +_mali_osk_errcode_t mali_stream_create(const char * name, int *out_fd) +{ + struct sync_timeline * tl; + BUG_ON(!out_fd); + + tl = mali_sync_timeline_alloc(name); + if (!tl) + { + return _MALI_OSK_ERR_FAULT; + } + + *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY | O_CLOEXEC); + + if (*out_fd < 0) + { + sync_timeline_destroy(tl); + return _MALI_OSK_ERR_FAULT; + } + else + { + return _MALI_OSK_ERR_OK; + } +} + +static mali_sync_pt *mali_stream_create_point_internal(int tl_fd, mali_bool timed) +{ + struct sync_timeline *tl; + struct sync_pt * pt; + struct file *tl_file; + + tl_file = fget(tl_fd); + if (tl_file == NULL) + return NULL; + + if (tl_file->f_op != &stream_fops) + { + pt = NULL; + goto out; + } + + tl = tl_file->private_data; + + if (unlikely(timed)) + { + pt = mali_sync_timed_pt_alloc(tl); + } + else + { + pt = mali_sync_pt_alloc(tl); + } + + if (!pt) + { + pt = NULL; + goto out; + } + +out: + fput(tl_file); + + return pt; +} + +mali_sync_pt *mali_stream_create_point(int tl_fd) +{ + return mali_stream_create_point_internal(tl_fd, MALI_FALSE); +} + +int mali_stream_create_fence(mali_sync_pt *pt) +{ + struct sync_fence *fence; + struct fdtable * fdt; + struct files_struct * files; + int fd = -1; + + fence = sync_fence_create("mali_fence", pt); + if (!fence) + { + sync_pt_free(pt); + fd = -EFAULT; + goto out; + } + + /* create a fd representing the fence */ + fd = get_unused_fd(); + if (fd < 0) + { + sync_fence_put(fence); + goto out; + } + + files = current->files; + spin_lock(&files->file_lock); + fdt = files_fdtable(files); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) + __set_close_on_exec(fd, fdt); +#else + FD_SET(fd, fdt->close_on_exec); +#endif + spin_unlock(&files->file_lock); + + /* bind fence to the new fd */ + sync_fence_install(fence, fd); + +out: + return fd; +} + +int mali_stream_create_empty_fence(int tl_fd) +{ + int fd; + mali_sync_pt *pt; + + pt = mali_stream_create_point_internal(tl_fd, MALI_TRUE); + + if (NULL == pt) return -ENOMEM; + + fd = mali_stream_create_fence(pt); + + return fd; +} + +_mali_osk_errcode_t mali_fence_validate(int fd) +{ + struct sync_fence * fence; + fence = sync_fence_fdget(fd); + if (NULL != fence) + { + sync_fence_put(fence); + return _MALI_OSK_ERR_OK; + } + else + { + return _MALI_OSK_ERR_FAULT; + } +} + +#endif /* CONFIG_SYNC */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_uk_types.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_uk_types.h new file mode 100644 index 0000000..fbe902a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_uk_types.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_UK_TYPES_H__ +#define __MALI_UK_TYPES_H__ + +/* Simple wrapper in order to find the OS specific location of this file */ +#include + +#endif /* __MALI_UK_TYPES_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_core.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_core.c new file mode 100644 index 0000000..1768ff2 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_core.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* memort allocation functions */ +#include /* user space access */ +#include + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" +#include "mali_sync.h" + +int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs) +{ + _mali_uk_get_api_version_s kargs; + _mali_osk_errcode_t err; + + u32 mem = _mali_ukk_report_memory_usage(); + printk("Mali: mem_usage before %d : %u\n", _mali_osk_get_pid(), mem); + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != get_user(kargs.version, &uargs->version)) return -EFAULT; + + kargs.ctx = session_data; + err = _mali_ukk_get_api_version(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT; + if (0 != put_user(kargs.compatible, &uargs->compatible)) return -EFAULT; + + return 0; +} + +int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs) +{ + _mali_uk_wait_for_notification_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_wait_for_notification(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if(_MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS != kargs.type) + { + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_wait_for_notification_s))) return -EFAULT; + } + else + { + if (0 != put_user(kargs.type, &uargs->type)) return -EFAULT; + } + + return 0; +} + +int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs) +{ + _mali_uk_post_notification_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + + if (0 != get_user(kargs.type, &uargs->type)) + { + return -EFAULT; + } + + err = _mali_ukk_post_notification(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + +int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs) +{ + _mali_uk_get_user_settings_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_get_user_settings(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_get_user_settings_s))) return -EFAULT; + + return 0; +} + +#ifdef CONFIG_SYNC +int stream_create_wrapper(struct mali_session_data *session_data, _mali_uk_stream_create_s __user *uargs) +{ + _mali_uk_stream_create_s kargs; + _mali_osk_errcode_t err; + char name[32]; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + snprintf(name, 32, "mali-%u", _mali_osk_get_pid()); + + kargs.ctx = session_data; + err = mali_stream_create(name, &kargs.fd); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_stream_create_s))) return -EFAULT; + + return 0; +} + +int sync_fence_create_empty_wrapper(struct mali_session_data *session_data, _mali_uk_fence_create_empty_s __user *uargs) +{ + _mali_uk_fence_create_empty_s kargs; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != get_user(kargs.stream, &uargs->stream)) return -EFAULT; + + kargs.fence = mali_stream_create_empty_fence(kargs.stream); + if (0 > kargs.fence) + { + return kargs.fence; + } + + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_fence_create_empty_s))) return -EFAULT; + + return 0; +} + +int sync_fence_validate_wrapper(struct mali_session_data *session, _mali_uk_fence_validate_s __user *uargs) +{ + int fd; + _mali_osk_errcode_t err; + + if (0 != get_user(fd, &uargs->fd)) + { + return -EFAULT; + } + + err = mali_fence_validate(fd); + + if (_MALI_OSK_ERR_OK == err) + { + return 0; + } + + return -EINVAL; +} +#endif diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_gp.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_gp.c new file mode 100644 index 0000000..4ee4a81 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_gp.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + +int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs) +{ + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + err = _mali_ukk_gp_start_job(session_data, uargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + return 0; +} + +int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs) +{ + _mali_uk_get_gp_core_version_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_get_gp_core_version(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + /* no known transactions to roll-back */ + + if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT; + + return 0; +} + +int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs) +{ + _mali_uk_gp_suspend_response_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_suspend_response_s))) return -EFAULT; + + kargs.ctx = session_data; + err = _mali_ukk_gp_suspend_response(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if (0 != put_user(kargs.cookie, &uargs->cookie)) return -EFAULT; + + /* no known transactions to roll-back */ + return 0; +} + +int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs) +{ + _mali_uk_get_gp_number_of_cores_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_get_gp_number_of_cores(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + /* no known transactions to roll-back */ + + if (0 != put_user(kargs.number_of_cores, &uargs->number_of_cores)) return -EFAULT; + + return 0; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_mem.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_mem.c new file mode 100644 index 0000000..7d1d23d --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_mem.c @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + +int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs) +{ + _mali_uk_init_mem_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_init_mem(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + if (0 != put_user(kargs.mali_address_base, &uargs->mali_address_base)) goto mem_init_rollback; + if (0 != put_user(kargs.memory_size, &uargs->memory_size)) goto mem_init_rollback; + + return 0; + +mem_init_rollback: + { + _mali_uk_term_mem_s kargs; + kargs.ctx = session_data; + err = _mali_ukk_term_mem(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_init_mem, as a result of failing put_user(), failed\n")); + } + } + return -EFAULT; +} + +int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs) +{ + _mali_uk_term_mem_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_term_mem(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + +int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs) +{ + _mali_uk_mem_write_safe_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_mem_write_safe_s))) + { + return -EFAULT; + } + + kargs.ctx = session_data; + + /* Check if we can access the buffers */ + if (!access_ok(VERIFY_WRITE, kargs.dest, kargs.size) + || !access_ok(VERIFY_READ, kargs.src, kargs.size)) + { + return -EINVAL; + } + + /* Check if size wraps */ + if ((kargs.size + kargs.dest) <= kargs.dest + || (kargs.size + kargs.src) <= kargs.src) + { + return -EINVAL; + } + + err = _mali_ukk_mem_write_safe(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + if (0 != put_user(kargs.size, &uargs->size)) + { + return -EFAULT; + } + + return 0; +} + +int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument) +{ + _mali_uk_map_external_mem_s uk_args; + _mali_osk_errcode_t err_code; + + /* validate input */ + /* the session_data pointer was validated by caller */ + MALI_CHECK_NON_NULL( argument, -EINVAL); + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_map_external_mem_s)) ) + { + return -EFAULT; + } + + uk_args.ctx = session_data; + err_code = _mali_ukk_map_external_mem( &uk_args ); + + if (0 != put_user(uk_args.cookie, &argument->cookie)) + { + if (_MALI_OSK_ERR_OK == err_code) + { + /* Rollback */ + _mali_uk_unmap_external_mem_s uk_args_unmap; + + uk_args_unmap.ctx = session_data; + uk_args_unmap.cookie = uk_args.cookie; + err_code = _mali_ukk_unmap_external_mem( &uk_args_unmap ); + if (_MALI_OSK_ERR_OK != err_code) + { + MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_unmap_external_mem, as a result of failing put_user(), failed\n")); + } + } + return -EFAULT; + } + + /* Return the error that _mali_ukk_free_big_block produced */ + return map_errcode(err_code); +} + +int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument) +{ + _mali_uk_unmap_external_mem_s uk_args; + _mali_osk_errcode_t err_code; + + /* validate input */ + /* the session_data pointer was validated by caller */ + MALI_CHECK_NON_NULL( argument, -EINVAL); + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_unmap_external_mem_s)) ) + { + return -EFAULT; + } + + uk_args.ctx = session_data; + err_code = _mali_ukk_unmap_external_mem( &uk_args ); + + /* Return the error that _mali_ukk_free_big_block produced */ + return map_errcode(err_code); +} + +#if defined(CONFIG_MALI400_UMP) +int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument) +{ + _mali_uk_release_ump_mem_s uk_args; + _mali_osk_errcode_t err_code; + + /* validate input */ + /* the session_data pointer was validated by caller */ + MALI_CHECK_NON_NULL( argument, -EINVAL); + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_release_ump_mem_s)) ) + { + return -EFAULT; + } + + uk_args.ctx = session_data; + err_code = _mali_ukk_release_ump_mem( &uk_args ); + + /* Return the error that _mali_ukk_free_big_block produced */ + return map_errcode(err_code); +} + +int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument) +{ + _mali_uk_attach_ump_mem_s uk_args; + _mali_osk_errcode_t err_code; + + /* validate input */ + /* the session_data pointer was validated by caller */ + MALI_CHECK_NON_NULL( argument, -EINVAL); + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_attach_ump_mem_s)) ) + { + return -EFAULT; + } + + uk_args.ctx = session_data; + err_code = _mali_ukk_attach_ump_mem( &uk_args ); + + if (0 != put_user(uk_args.cookie, &argument->cookie)) + { + if (_MALI_OSK_ERR_OK == err_code) + { + /* Rollback */ + _mali_uk_release_ump_mem_s uk_args_unmap; + + uk_args_unmap.ctx = session_data; + uk_args_unmap.cookie = uk_args.cookie; + err_code = _mali_ukk_release_ump_mem( &uk_args_unmap ); + if (_MALI_OSK_ERR_OK != err_code) + { + MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_attach_mem, as a result of failing put_user(), failed\n")); + } + } + return -EFAULT; + } + + /* Return the error that _mali_ukk_map_external_ump_mem produced */ + return map_errcode(err_code); +} +#endif /* CONFIG_MALI400_UMP */ + +int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs) +{ + _mali_uk_query_mmu_page_table_dump_size_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + kargs.ctx = session_data; + + err = _mali_ukk_query_mmu_page_table_dump_size(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT; + + return 0; +} + +int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs) +{ + _mali_uk_dump_mmu_page_table_s kargs; + _mali_osk_errcode_t err; + void *buffer; + int rc = -EFAULT; + + /* validate input */ + MALI_CHECK_NON_NULL(uargs, -EINVAL); + /* the session_data pointer was validated by caller */ + + kargs.buffer = NULL; + + /* get location of user buffer */ + if (0 != get_user(buffer, &uargs->buffer)) goto err_exit; + /* get size of mmu page table info buffer from user space */ + if ( 0 != get_user(kargs.size, &uargs->size) ) goto err_exit; + /* verify we can access the whole of the user buffer */ + if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit; + + /* allocate temporary buffer (kernel side) to store mmu page table info */ + MALI_CHECK(kargs.size > 0, -ENOMEM); + kargs.buffer = _mali_osk_valloc(kargs.size); + if (NULL == kargs.buffer) + { + rc = -ENOMEM; + goto err_exit; + } + + kargs.ctx = session_data; + err = _mali_ukk_dump_mmu_page_table(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + rc = map_errcode(err); + goto err_exit; + } + + /* copy mmu page table info back to user space and update pointers */ + if (0 != copy_to_user(uargs->buffer, kargs.buffer, kargs.size) ) goto err_exit; + if (0 != put_user((kargs.register_writes - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->register_writes)) goto err_exit; + if (0 != put_user((kargs.page_table_dump - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->page_table_dump)) goto err_exit; + if (0 != put_user(kargs.register_writes_size, &uargs->register_writes_size)) goto err_exit; + if (0 != put_user(kargs.page_table_dump_size, &uargs->page_table_dump_size)) goto err_exit; + rc = 0; + +err_exit: + if (kargs.buffer) _mali_osk_vfree(kargs.buffer); + return rc; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_pp.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_pp.c new file mode 100644 index 0000000..6663e7f --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_pp.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + +int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs) +{ + _mali_osk_errcode_t err; + int fence = -1; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + err = _mali_ukk_pp_start_job(session_data, uargs, &fence); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + +#if defined(CONFIG_SYNC) + if (0 != put_user(fence, &uargs->fence)) + { + /* Since the job has started we can't return an error. */ + } +#endif /* CONFIG_SYNC */ + + return 0; +} + +int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs) +{ + _mali_uk_get_pp_number_of_cores_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + kargs.ctx = session_data; + + err = _mali_ukk_get_pp_number_of_cores(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_get_pp_number_of_cores_s))) + { + return -EFAULT; + } + + return 0; +} + +int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs) +{ + _mali_uk_get_pp_core_version_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_get_pp_core_version(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT; + + return 0; +} + +int pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs) +{ + _mali_uk_pp_disable_wb_s kargs; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_disable_wb_s))) return -EFAULT; + + kargs.ctx = session_data; + _mali_ukk_pp_job_disable_wb(&kargs); + + return 0; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_profiling.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_profiling.c new file mode 100644 index 0000000..f4e31c9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_profiling.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ +#include + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + +int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs) +{ + _mali_uk_profiling_start_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_start_s))) + { + return -EFAULT; + } + + kargs.ctx = session_data; + err = _mali_ukk_profiling_start(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + if (0 != put_user(kargs.limit, &uargs->limit)) + { + return -EFAULT; + } + + return 0; +} + +int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_add_event_s __user *uargs) +{ + _mali_uk_profiling_add_event_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_add_event_s))) + { + return -EFAULT; + } + + kargs.ctx = session_data; + err = _mali_ukk_profiling_add_event(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + +int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_stop_s __user *uargs) +{ + _mali_uk_profiling_stop_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_profiling_stop(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + if (0 != put_user(kargs.count, &uargs->count)) + { + return -EFAULT; + } + + return 0; +} + +int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs) +{ + _mali_uk_profiling_get_event_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != get_user(kargs.index, &uargs->index)) + { + return -EFAULT; + } + + kargs.ctx = session_data; + + err = _mali_ukk_profiling_get_event(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_profiling_get_event_s))) + { + return -EFAULT; + } + + return 0; +} + +int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs) +{ + _mali_uk_profiling_clear_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_profiling_clear(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + +int profiling_report_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_report_s __user *uargs) +{ + _mali_uk_sw_counters_report_s kargs; + _mali_osk_errcode_t err; + u32 *counter_buffer; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_sw_counters_report_s))) + { + return -EFAULT; + } + + /* make sure that kargs.num_counters is [at least somewhat] sane */ + if (kargs.num_counters > 10000) { + MALI_DEBUG_PRINT(1, ("User space attempted to allocate too many counters.\n")); + return -EINVAL; + } + + counter_buffer = (u32*)kmalloc(sizeof(u32) * kargs.num_counters, GFP_KERNEL); + if (NULL == counter_buffer) + { + return -ENOMEM; + } + + if (0 != copy_from_user(counter_buffer, kargs.counters, sizeof(u32) * kargs.num_counters)) + { + kfree(counter_buffer); + return -EFAULT; + } + + kargs.ctx = session_data; + kargs.counters = counter_buffer; + + err = _mali_ukk_sw_counters_report(&kargs); + + kfree(counter_buffer); + + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + + diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_vsync.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_vsync.c new file mode 100644 index 0000000..f9b5a3e --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_vsync.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + + +int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs) +{ + _mali_uk_vsync_event_report_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_vsync_event_report_s))) + { + return -EFAULT; + } + + kargs.ctx = session_data; + err = _mali_ukk_vsync_event_report(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_wrappers.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_wrappers.h new file mode 100644 index 0000000..08bdae4 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_wrappers.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_ukk_wrappers.h + * Defines the wrapper functions for each user-kernel function + */ + +#ifndef __MALI_UKK_WRAPPERS_H__ +#define __MALI_UKK_WRAPPERS_H__ + +#include "mali_uk_types.h" +#include "mali_osk.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs); +int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs); +int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs); +#if defined(CONFIG_SYNC) +int stream_create_wrapper(struct mali_session_data *session_data, _mali_uk_stream_create_s __user *uargs); +int sync_fence_create_empty_wrapper(struct mali_session_data *session_data, _mali_uk_fence_create_empty_s __user *uargs); +int sync_fence_validate_wrapper(struct mali_session_data *session, _mali_uk_fence_validate_s __user *uargs); +#endif +int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs); +int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs); +int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs); +int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs); +int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument); +int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument); +int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs); +int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs); + +#if defined(CONFIG_MALI400_UMP) +int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument); +int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument); +#endif + +int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs); +int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs); +int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs); +int pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs); +int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs); +int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs); +int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs); +int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs); + +int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs); +int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_add_event_s __user *uargs); +int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_stop_s __user *uargs); +int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs); +int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs); +int profiling_report_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_report_s __user *uargs); + +int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs); + + +int map_errcode( _mali_osk_errcode_t err ); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_UKK_WRAPPERS_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4.c b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4.c new file mode 100644 index 0000000..bf83249 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4.c @@ -0,0 +1,405 @@ +/* drivers/gpu/mali400/mali/platform/pegasus-m400/exynos4.c + * + * Copyright 2011 by S.LSI. Samsung Electronics Inc. + * San#24, Nongseo-Dong, Giheung-Gu, Yongin, Korea + * + * Samsung SoC Mali400 DVFS 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. + */ + +/** + * @file exynos4.c + * Platform specific Mali driver functions for the exynos 4XXX based platforms + */ +#include +#include +#include +#include + +#ifdef CONFIG_PM_RUNTIME +#include +#endif + +#ifdef CONFIG_MALI_DVFS +#include "mali_kernel_utilization.h" +#endif /* CONFIG_MALI_DVFS */ + +#include +#include "mali_kernel_common.h" +#include "mali_kernel_linux.h" +#include "mali_pm.h" + +#include + +#include "exynos4_pmm.h" + +#if defined(CONFIG_PM_RUNTIME) +/* We does not need PM NOTIFIER in r3p2 DDK */ +//#define USE_PM_NOTIFIER +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) +struct exynos_pm_domain; +extern struct exynos_pm_domain exynos4_pd_g3d; +void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, struct exynos_pm_domain *pd); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) +extern struct platform_device exynos4_device_pd[]; +#else +extern struct platform_device s5pv310_device_pd[]; +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) */ + +static void mali_platform_device_release(struct device *device); + +#if defined(CONFIG_PM_RUNTIME) +#if defined(USE_PM_NOTIFIER) +static int mali_os_suspend(struct device *device); +static int mali_os_resume(struct device *device); +static int mali_os_freeze(struct device *device); +static int mali_os_thaw(struct device *device); + +static int mali_runtime_suspend(struct device *device); +static int mali_runtime_resume(struct device *device); +static int mali_runtime_idle(struct device *device); +#endif +#endif + +#if defined(CONFIG_ARCH_S5PV310) && !defined(CONFIG_BOARD_HKDKC210) + +/* This is for other SMDK boards */ +#define MALI_BASE_IRQ 232 + +#else + +/* This is for the Odroid boards */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) +#define MALI_BASE_IRQ 182 +#else +#define MALI_BASE_IRQ 150 +#endif + +#endif + +#define MALI_GP_IRQ MALI_BASE_IRQ + 9 +#define MALI_PP0_IRQ MALI_BASE_IRQ + 5 +#define MALI_PP1_IRQ MALI_BASE_IRQ + 6 +#define MALI_PP2_IRQ MALI_BASE_IRQ + 7 +#define MALI_PP3_IRQ MALI_BASE_IRQ + 8 +#define MALI_GP_MMU_IRQ MALI_BASE_IRQ + 4 +#define MALI_PP0_MMU_IRQ MALI_BASE_IRQ + 0 +#define MALI_PP1_MMU_IRQ MALI_BASE_IRQ + 1 +#define MALI_PP2_MMU_IRQ MALI_BASE_IRQ + 2 +#define MALI_PP3_MMU_IRQ MALI_BASE_IRQ + 3 + +static struct resource mali_gpu_resources[] = +{ + MALI_GPU_RESOURCES_MALI400_MP4(0x13000000, + MALI_GP_IRQ, MALI_GP_MMU_IRQ, + MALI_PP0_IRQ, MALI_PP0_MMU_IRQ, + MALI_PP1_IRQ, MALI_PP1_MMU_IRQ, + MALI_PP2_IRQ, MALI_PP2_MMU_IRQ, + MALI_PP3_IRQ, MALI_PP3_MMU_IRQ) +}; + +#ifdef CONFIG_PM_RUNTIME +#if defined(USE_PM_NOTIFIER) +static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy); + +static struct notifier_block mali_pwr_notif_block = { + .notifier_call = mali_pwr_suspend_notifier +}; +#endif +#endif /* CONFIG_PM_RUNTIME */ + +#if 0 +static struct dev_pm_ops mali_gpu_device_type_pm_ops = +{ +#ifndef CONFIG_PM_RUNTIME + .suspend = mali_os_suspend, + .resume = mali_os_resume, +#endif + .freeze = mali_os_freeze, + .thaw = mali_os_thaw, +#ifdef CONFIG_PM_RUNTIME + .runtime_suspend = mali_runtime_suspend, + .runtime_resume = mali_runtime_resume, + .runtime_idle = mali_runtime_idle, +#endif +}; +#endif + +#if defined(USE_PM_NOTIFIER) +static struct device_type mali_gpu_device_device_type = +{ + .pm = &mali_gpu_device_type_pm_ops, +}; +#endif + +static struct platform_device mali_gpu_device = +{ + .name = "mali_dev", /* MALI_SEC MALI_GPU_NAME_UTGARD, */ + .id = 0, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) + /* Set in mali_platform_device_register() for these kernels */ +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) + .dev.parent = &exynos4_device_pd[PD_G3D].dev, +#else + .dev.parent = &s5pv310_device_pd[PD_G3D].dev, +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) */ + .dev.release = mali_platform_device_release, +#if 0 + /* + * We temporarily make use of a device type so that we can control the Mali power + * from within the mali.ko (since the default platform bus implementation will not do that). + * Ideally .dev.pm_domain should be used instead, as this is the new framework designed + * to control the power of devices. + */ + .dev.type = &mali_gpu_device_device_type, /* We should probably use the pm_domain instead of type on newer kernels */ +#endif +}; + +static struct mali_gpu_device_data mali_gpu_data = +{ + .shared_mem_size = 256 * 1024 * 1024, /* 256MB */ + .fb_start = 0x40000000, + .fb_size = 0xb1000000, + .utilization_interval = 100, /* 100ms */ + .utilization_callback = mali_gpu_utilization_handler, +}; + +int mali_platform_device_register(void) +{ + int err; + + MALI_DEBUG_PRINT(4, ("mali_platform_device_register() called\n")); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) + exynos_pm_add_dev_to_genpd(&mali_gpu_device, &exynos4_pd_g3d); +#endif + + /* Connect resources to the device */ + err = platform_device_add_resources(&mali_gpu_device, mali_gpu_resources, sizeof(mali_gpu_resources) / sizeof(mali_gpu_resources[0])); + if (0 == err) + { + err = platform_device_add_data(&mali_gpu_device, &mali_gpu_data, sizeof(mali_gpu_data)); + if (0 == err) + { +#ifdef CONFIG_PM_RUNTIME +#if defined(USE_PM_NOTIFIER) + err = register_pm_notifier(&mali_pwr_notif_block); + if (err) + { + goto plat_init_err; + } +#endif +#endif /* CONFIG_PM_RUNTIME */ + + /* Register the platform device */ + err = platform_device_register(&mali_gpu_device); + if (0 == err) + { + mali_platform_init(&(mali_gpu_device.dev)); + +#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + pm_runtime_set_autosuspend_delay(&(mali_gpu_device.dev), 1000); + pm_runtime_use_autosuspend(&(mali_gpu_device.dev)); +#endif + pm_runtime_enable(&(mali_gpu_device.dev)); +#endif + + return 0; + } + } + +#ifdef CONFIG_PM_RUNTIME +#if defined(USE_PM_NOTIFIER) +plat_init_err: + unregister_pm_notifier(&mali_pwr_notif_block); +#endif +#endif /* CONFIG_PM_RUNTIME */ + platform_device_unregister(&mali_gpu_device); + } + + return err; +} + +void mali_platform_device_unregister(void) +{ + MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n")); + +#ifdef CONFIG_PM_RUNTIME +#if defined(USE_PM_NOTIFIER) + unregister_pm_notifier(&mali_pwr_notif_block); +#endif +#endif /* CONFIG_PM_RUNTIME */ + + mali_platform_deinit(&(mali_gpu_device.dev)); + + platform_device_unregister(&mali_gpu_device); +} + +static void mali_platform_device_release(struct device *device) +{ + MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n")); +} + +#ifdef CONFIG_PM_RUNTIME +#if defined(USE_PM_NOTIFIER) +static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy) +{ + int err = 0; + switch (event) + { + case PM_SUSPEND_PREPARE: + mali_pm_os_suspend(); + err = mali_os_suspend(&(mali_platform_device->dev)); + break; + + case PM_POST_SUSPEND: + err = mali_os_resume(&(mali_platform_device->dev)); + mali_pm_os_resume(); + break; + default: + break; + } + return err; +} + +static int mali_os_suspend(struct device *device) +{ + int ret = 0; + MALI_DEBUG_PRINT(4, ("mali_os_suspend() called\n")); + +#ifdef CONFIG_MALI_DVFS + mali_utilization_suspend(); +#endif + + if (NULL != device && + NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->suspend) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->suspend(device); + } + + mali_platform_power_mode_change(device, MALI_POWER_MODE_DEEP_SLEEP); + + return ret; +} + +static int mali_os_resume(struct device *device) +{ + int ret = 0; + + MALI_DEBUG_PRINT(4, ("mali_os_resume() called\n")); +#ifdef CONFIG_REGULATOR + mali_regulator_enable(); + g3d_power_domain_control(1); +#endif + mali_platform_power_mode_change(device, MALI_POWER_MODE_ON); + + if (NULL != device && + NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->resume) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->resume(device); + } + + return ret; +} + +static int mali_os_freeze(struct device *device) +{ + int ret = 0; + MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n")); + + if (NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->freeze) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->freeze(device); + } + + return ret; +} + +static int mali_os_thaw(struct device *device) +{ + int ret = 0; + MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n")); + + if (NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->thaw) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->thaw(device); + } + + return ret; +} + +static int mali_runtime_suspend(struct device *device) +{ + int ret = 0; + + MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n")); + if (NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->runtime_suspend) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->runtime_suspend(device); + } + + mali_platform_power_mode_change(device, MALI_POWER_MODE_LIGHT_SLEEP); + + return ret; +} + +static int mali_runtime_resume(struct device *device) +{ + int ret = 0; + MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n")); + + mali_platform_power_mode_change(device, MALI_POWER_MODE_ON); + + if (NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->runtime_resume) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->runtime_resume(device); + } + + return ret; +} + +static int mali_runtime_idle(struct device *device) +{ + MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n")); + if (NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->runtime_idle) + { + int ret = 0; + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->runtime_idle(device); + if (0 != ret) + { + return ret; + } + } + + return 1; +} + +#endif /* USE_PM_NOTIFIER */ +#endif /* CONFIG_PM_RUNTIME */ diff --git a/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c new file mode 100644 index 0000000..346ad7f --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c @@ -0,0 +1,1373 @@ +/* drivers/gpu/mali400/mali/platform/pegasus-m400/exynos4_pmm.c + * + * Copyright 2011 by S.LSI. Samsung Electronics Inc. + * San#24, Nongseo-Dong, Giheung-Gu, Yongin, Korea + * + * Samsung SoC Mali400 DVFS 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. + */ + +/** + * @file exynos4_pmm.c + * Platform specific Mali driver functions for the exynos 4XXX based platforms + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "exynos4_pmm.h" +#include +#include +#include +#include +#include + +#if defined(CONFIG_MALI400_PROFILING) +#include "mali_osk_profiling.h" +#endif + +#if defined(CONFIG_PM_RUNTIME) +#include +#endif + +#include +#include + +#include + +#ifdef CONFIG_CPU_EXYNOS4210 +#define MALI_DVFS_STEPS 2 +#define MALI_DVFS_WATING 10 /* msec */ +#define MALI_DVFS_DEFAULT_STEP 0 +#else +#define MALI_DVFS_STEPS 5 +#define MALI_DVFS_WATING 10 /* msec */ +#define MALI_DVFS_DEFAULT_STEP 1 +#define PD_G3D_LOCK_FLAG 2 +#endif + +#ifdef CONFIG_CPU_FREQ +#include +#define EXYNOS4_ASV_ENABLED +#endif + +#define MALI_DVFS_CLK_DEBUG 0 +#define SEC_THRESHOLD 1 + +#define CPUFREQ_LOCK_DURING_440 0 +#define CHIPID_REG (S5P_VA_CHIPID + 0x4) + +static int bMaliDvfsRun = 0; + +typedef struct mali_dvfs_tableTag{ + unsigned int clock; + unsigned int freq; + unsigned int vol; +#if SEC_THRESHOLD + unsigned int downthreshold; + unsigned int upthreshold; +#endif +}mali_dvfs_table; + +typedef struct mali_dvfs_statusTag{ + unsigned int currentStep; + mali_dvfs_table * pCurrentDvfs; + +} mali_dvfs_status_t; + +/* dvfs status */ +mali_dvfs_status_t maliDvfsStatus; +int mali_dvfs_control; + +typedef struct mali_runtime_resumeTag{ + int clk; + int vol; + unsigned int step; +}mali_runtime_resume_table; + +mali_runtime_resume_table mali_runtime_resume = {266, 900000, 1}; + +/* dvfs table */ +mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) + /* step 0 */{160 ,1000000 ,875000 , 0 , 70}, + /* step 1 */{266 ,1000000 ,900000 ,62 , 90}, + /* step 2 */{350 ,1000000 ,950000 ,85 , 90}, + /* step 3 */{440 ,1000000 ,1025000 ,85 , 90}, + /* step 4 */{533 ,1000000 ,1075000 ,95 ,100} }; +#else + /* step 0 */{134 ,1000000 , 950000 ,85 , 90}, + /* step 1 */{267 ,1000000 ,1050000 ,85 ,100} }; +#endif + +#ifdef EXYNOS4_ASV_ENABLED +#define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */ +#define ASV_LEVEL_PRIME 13 /* ASV0, 1, 12 is reserved */ +#define ASV_LEVEL_PD 13 +#define ASV_LEVEL_4210_12 8 +#define ASV_LEVEL_4210_14 5 + +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = { + { 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000, 900000, 900000, 900000, 875000}, /* L3(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 1000000, 975000, 975000, 975000, 950000, 950000, 950000, 900000, 900000, 900000, 900000, 875000}, /* L2(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1075000, 1050000, 1050000, 1050000, 1000000, 1000000, 1000000, 975000, 975000, 975000, 975000, 925000}, /* L1(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1125000, 1100000, 1100000, 1100000, 1075000, 1075000, 1075000, 1025000, 1025000, 1025000, 1025000, 975000}, /* L0(440Mhz) */ +#endif +#endif +#endif +}; +static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS-1][ASV_LEVEL] = { + { 950000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 975000, 950000, 925000, 925000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000}, /* L2(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1050000, 1025000, 1000000, 1000000, 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000}, /* L1(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1100000, 1075000, 1050000, 1050000, 1050000, 1025000, 1025000, 1000000, 1000000, 1000000, 975000, 950000}, /* L0(440Mhz) */ +#endif +#endif +#endif +}; + +static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL_PRIME] = { + { 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 875000, 862500, 850000, 850000, 850000}, /* L4(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 900000, 887500, 875000, 875000, 875000}, /* L3(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 912500, 900000, 887500}, /* L2(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 975000, 962500, 950000}, /* L1(440Mhz) */ +#if (MALI_DVFS_STEPS > 4) + { 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1075000, 1062500, 1037500, 1025000, 1012500}, /* L0(533Mhz) */ +#endif +#endif +#endif +#endif +}; + +static unsigned int asv_3d_volt_4212_9_table[MALI_DVFS_STEPS][ASV_LEVEL_PD] = { + { 950000, 925000, 900000, 900000, 900000, 900000, 900000, 900000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 975000, 950000, 925000, 925000, 925000, 925000, 925000, 900000, 900000, 900000, 875000, 875000, 875000}, /* L2(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1025000, 1000000, 975000, 975000, 975000, 950000, 950000, 925000, 925000, 925000, 925000, 900000, 875000}, /* L1(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1100000, 1075000, 1050000, 1050000, 1050000, 1050000, 1025000, 1000000, 1000000, 975000, 975000, 950000, 925000}, /* L0(440Mhz) */ +#endif +#endif +#endif +}; + +#else + +static unsigned int asv_3d_volt_4210_12_table[MALI_DVFS_STEPS][ASV_LEVEL_4210_12] = { + { 1000000, 1000000, 1000000, 950000, 950000, 950000, 950000, 950000}, /* L1(134Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 1100000, 1100000, 1100000, 1000000, 1000000, 1000000, 1000000, 950000}, /* L0(266Mhz) */ +#endif +}; + +static unsigned int asv_3d_volt_4210_14_table[MALI_DVFS_STEPS][ASV_LEVEL_4210_14] = { + { 1000000, 1000000, 950000, 950000, 950000}, /* L1(134Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 1100000, 1100000, 1000000, 1000000, 950000}, /* L0(266Mhz) */ +#endif +}; +#endif +#endif /* ASV_LEVEL */ + +#define EXTXTALCLK_NAME "ext_xtal" +#define VPLLSRCCLK_NAME "vpll_src" +#define FOUTVPLLCLK_NAME "fout_vpll" +#define SCLVPLLCLK_NAME "sclk_vpll" +#define GPUMOUT1CLK_NAME "mout_g3d1" + +#define MPLLCLK_NAME "mout_mpll" +#define GPUMOUT0CLK_NAME "mout_g3d0" +#define GPUCLK_NAME "sclk_g3d" +#define CLK_DIV_STAT_G3D 0x1003C62C +#define CLK_DESC "clk-divider-status" + +static struct clk *ext_xtal_clock = NULL; +static struct clk *vpll_src_clock = NULL; +static struct clk *fout_vpll_clock = NULL; +static struct clk *sclk_vpll_clock = NULL; + +static struct clk *mpll_clock = NULL; +static struct clk *mali_parent_clock = NULL; +static struct clk *mali_mout0_clock = NULL; +static struct clk *mali_clock = NULL; + +#if defined(CONFIG_CPU_EXYNOS4412) || defined(CONFIG_CPU_EXYNOS4212) +/* Pegasus */ +static const mali_bool bis_vpll = MALI_TRUE; +int mali_gpu_clk = 440; +int mali_gpu_vol = 1025000; +#else +/* Orion */ +static const mali_bool bis_vpll = MALI_FALSE; +int mali_gpu_clk = 267; +int mali_gpu_vol = 1050000; +#endif + +static unsigned int GPU_MHZ = 1000000; + +int gpu_power_state; +static int bPoweroff; +atomic_t clk_active; + +#define MAX_MALI_DVFS_STEPS 5 +static _mali_osk_atomic_t bottomlock_status; +int bottom_lock_step = 0; + +#if MALI_VOLTAGE_LOCK +int mali_lock_vol = 0; +static _mali_osk_atomic_t voltage_lock_status; +static mali_bool mali_vol_lock_flag = 0; +#endif + +/* Declare for sysfs */ +#ifdef CONFIG_MALI_DVFS +module_param(mali_dvfs_control, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(mali_dvfs_control, "Mali Current DVFS"); + +DEVICE_ATTR(time_in_state, S_IRUGO|S_IWUSR, show_time_in_state, set_time_in_state); +MODULE_PARM_DESC(time_in_state, "Time-in-state of Mali DVFS"); +#endif + +module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(mali_gpu_clk, "Mali Current Clock"); + +module_param(mali_gpu_vol, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(mali_gpu_vol, "Mali Current Voltage"); + +module_param(gpu_power_state, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(gpu_power_state, "Mali Power State"); + +#ifdef CONFIG_REGULATOR +struct regulator *g3d_regulator = NULL; +#endif + +mali_io_address clk_register_map = 0; + +/* DVFS */ +static unsigned int mali_dvfs_utilization = 255; +u64 mali_dvfs_time[MALI_DVFS_STEPS]; +#ifdef CONFIG_MALI_DVFS +static void update_time_in_state(int level); +#endif +static void mali_dvfs_work_handler(struct work_struct *w); +static struct workqueue_struct *mali_dvfs_wq = 0; +extern mali_io_address clk_register_map; +_mali_osk_lock_t *mali_dvfs_lock; +int mali_runtime_resumed = -1; +static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler); + +#ifdef CONFIG_REGULATOR +void mali_regulator_disable(void) +{ + if(IS_ERR_OR_NULL(g3d_regulator)) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n")); + return; + } + regulator_disable(g3d_regulator); +} + +void mali_regulator_enable(void) +{ + if(IS_ERR_OR_NULL(g3d_regulator)) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n")); + return; + } + regulator_enable(g3d_regulator); +} + +void mali_regulator_set_voltage(int min_uV, int max_uV) +{ + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + if(IS_ERR_OR_NULL(g3d_regulator)) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n")); + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + return; + } + MALI_PRINT(("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); + regulator_set_voltage(g3d_regulator, min_uV, max_uV); + mali_gpu_vol = regulator_get_voltage(g3d_regulator); + MALI_DEBUG_PRINT(1, ("Mali voltage: %d\n", mali_gpu_vol)); + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); +} +#endif + +unsigned long mali_clk_get_rate(void) +{ + return clk_get_rate(mali_clock); +} + + +static unsigned int get_mali_dvfs_status(void) +{ + return maliDvfsStatus.currentStep; +} + +mali_bool mali_clk_get(void) +{ + if (bis_vpll) + { + if (ext_xtal_clock == NULL) + { + ext_xtal_clock = clk_get(NULL, EXTXTALCLK_NAME); + if (IS_ERR(ext_xtal_clock)) { + MALI_PRINT(("MALI Error : failed to get source ext_xtal_clock\n")); + return MALI_FALSE; + } + } + + if (vpll_src_clock == NULL) + { + vpll_src_clock = clk_get(NULL, VPLLSRCCLK_NAME); + if (IS_ERR(vpll_src_clock)) { + MALI_PRINT(("MALI Error : failed to get source vpll_src_clock\n")); + return MALI_FALSE; + } + } + + if (fout_vpll_clock == NULL) + { + fout_vpll_clock = clk_get(NULL, FOUTVPLLCLK_NAME); + if (IS_ERR(fout_vpll_clock)) { + MALI_PRINT(("MALI Error : failed to get source fout_vpll_clock\n")); + return MALI_FALSE; + } + } + + if (sclk_vpll_clock == NULL) + { + sclk_vpll_clock = clk_get(NULL, SCLVPLLCLK_NAME); + if (IS_ERR(sclk_vpll_clock)) { + MALI_PRINT(("MALI Error : failed to get source sclk_vpll_clock\n")); + return MALI_FALSE; + } + } + + if (mali_parent_clock == NULL) + { + mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME); + + if (IS_ERR(mali_parent_clock)) { + MALI_PRINT(( "MALI Error : failed to get source mali parent clock\n")); + return MALI_FALSE; + } + } + + if (mali_mout0_clock == NULL) + { + mali_mout0_clock = clk_get(NULL, GPUMOUT0CLK_NAME); + + if (IS_ERR(mali_mout0_clock)) { + MALI_PRINT( ( "MALI Error : failed to get source mali mout0 clock\n")); + return MALI_FALSE; + } + } + } + else /* mpll */ + { + if (mpll_clock == NULL) + { + mpll_clock = clk_get(NULL, MPLLCLK_NAME); + + if (IS_ERR(mpll_clock)) { + MALI_PRINT(("MALI Error : failed to get source mpll clock\n")); + return MALI_FALSE; + } + } + + if (mali_parent_clock == NULL) + { + mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME); + + if (IS_ERR(mali_parent_clock)) { + MALI_PRINT(( "MALI Error : failed to get source mali parent clock\n")); + return MALI_FALSE; + } + } + } + + /* mali clock get always. */ + if (mali_clock == NULL) + { + mali_clock = clk_get(NULL, GPUCLK_NAME); + + if (IS_ERR(mali_clock)) { + MALI_PRINT(("MALI Error : failed to get source mali clock\n")); + return MALI_FALSE; + } + } + + return MALI_TRUE; +} + +void mali_clk_put(mali_bool binc_mali_clock) +{ + if (mali_parent_clock) + { + clk_put(mali_parent_clock); + mali_parent_clock = NULL; + } + + if (mali_mout0_clock) + { + clk_put(mali_mout0_clock); + mali_mout0_clock = NULL; + } + + if (mpll_clock) + { + clk_put(mpll_clock); + mpll_clock = NULL; + } + + if (sclk_vpll_clock) + { + clk_put(sclk_vpll_clock); + sclk_vpll_clock = NULL; + } + + if (binc_mali_clock && fout_vpll_clock) + { + clk_put(fout_vpll_clock); + fout_vpll_clock = NULL; + } + + if (vpll_src_clock) + { + clk_put(vpll_src_clock); + vpll_src_clock = NULL; + } + + if (ext_xtal_clock) + { + clk_put(ext_xtal_clock); + ext_xtal_clock = NULL; + } + + if (binc_mali_clock && mali_clock) + { + clk_put(mali_clock); + mali_clock = NULL; + } +} + +void mali_clk_set_rate(unsigned int clk, unsigned int mhz) +{ + int err; + unsigned long rate = (unsigned long)clk * (unsigned long)mhz; + + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + MALI_DEBUG_PRINT(3, ("Mali platform: Setting frequency to %d mhz\n", clk)); + + if (mali_clk_get() == MALI_FALSE) { + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + return; + } + + if (bis_vpll) + { + clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ); + clk_set_parent(vpll_src_clock, ext_xtal_clock); + clk_set_parent(sclk_vpll_clock, fout_vpll_clock); + + clk_set_parent(mali_parent_clock, sclk_vpll_clock); + clk_set_parent(mali_clock, mali_parent_clock); + } + else + { + clk_set_parent(mali_parent_clock, mpll_clock); + clk_set_parent(mali_clock, mali_parent_clock); + } + + if (atomic_read(&clk_active) == 0) { + if (clk_enable(mali_clock) < 0) { + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + return; + } + atomic_set(&clk_active, 1); + } + + err = clk_set_rate(mali_clock, rate); + if (err > 0) + MALI_PRINT_ERROR(("Failed to set Mali clock: %d\n", err)); + + rate = mali_clk_get_rate(); + + MALI_PRINT(("Mali frequency %d\n", rate / mhz)); + GPU_MHZ = mhz; + mali_gpu_clk = (int)(rate / mhz); + + mali_clk_put(MALI_FALSE); + + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); +} + +int get_mali_dvfs_control_status(void) +{ + return mali_dvfs_control; +} + +mali_bool set_mali_dvfs_current_step(unsigned int step) +{ + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + maliDvfsStatus.currentStep = step % MALI_DVFS_STEPS; + if (step >= MALI_DVFS_STEPS) + mali_runtime_resumed = maliDvfsStatus.currentStep; + + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + return MALI_TRUE; +} + + +static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup) +{ + u32 validatedStep=step; +#if MALI_DVFS_CLK_DEBUG + unsigned int *pRegMaliClkDiv; + unsigned int *pRegMaliMpll; +#endif + + if(boostup) { +#ifdef CONFIG_REGULATOR + /* change the voltage */ + mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); +#endif + /* change the clock */ + mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); + } else { + /* change the clock */ + mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); +#ifdef CONFIG_REGULATOR + /* change the voltage */ + mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); +#endif + } + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| + MALI_PROFILING_EVENT_CHANNEL_GPU| + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, + mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); +#endif + mali_clk_put(MALI_FALSE); + +#if MALI_DVFS_CLK_DEBUG + pRegMaliClkDiv = ioremap(0x1003c52c,32); + pRegMaliMpll = ioremap(0x1003c22c,32); + MALI_PRINT(("Mali MPLL reg:%d, CLK DIV: %d \n",*pRegMaliMpll, *pRegMaliClkDiv)); +#endif + +#ifdef EXYNOS4_ASV_ENABLED + if (samsung_rev() < EXYNOS4412_REV_2_0) { + if (mali_dvfs[step].clock == 160) + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); + else + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); + } +#endif + + set_mali_dvfs_current_step(validatedStep); + /* for future use */ + maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep]; + +#if CPUFREQ_LOCK_DURING_440 + /* lock/unlock CPU freq by Mali */ + if (mali_dvfs[step].clock >= 440) + err = cpufreq_lock_by_mali(400); + else + cpufreq_unlock_by_mali(); +#endif + + + return MALI_TRUE; +} + +static void mali_platform_wating(u32 msec) +{ + /* + * sample wating + * change this in the future with proper check routine. + */ + unsigned int read_val; + while(1) { + read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00); + if ((read_val & 0x8000)==0x0000) break; + + _mali_osk_time_ubusydelay(100); /* 1000 -> 100 : 20101218 */ + } +} + +static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup ) +{ + MALI_DEBUG_PRINT(4, ("> change_mali_dvfs_status: %d, %d \n",step, boostup)); + + if (!set_mali_dvfs_status(step, boostup)) { + MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup)); + return MALI_FALSE; + } + + /* wait until clock and voltage is stablized */ + mali_platform_wating(MALI_DVFS_WATING); /* msec */ + + return MALI_TRUE; +} + +#ifdef EXYNOS4_ASV_ENABLED +extern unsigned int exynos_result_of_asv; + +static mali_bool mali_dvfs_table_update(void) +{ + unsigned int step_num = MALI_DVFS_STEPS; + +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) + unsigned int i, tmp, g3d_lock_volt = 0; + bool lock_flag_g3d = false; + + if(samsung_rev() < EXYNOS4412_REV_2_0) + step_num = MALI_DVFS_STEPS - 1; + + if(soc_is_exynos4412()) { + if (exynos_armclk_max == 1000000) { + MALI_PRINT(("::C::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table_1ghz_type[i][exynos_result_of_asv]; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } + } else if(((is_special_flag() >> G3D_LOCK_FLAG) & 0x1) && (samsung_rev() >= EXYNOS4412_REV_2_0)) { + MALI_PRINT(("::L::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv] + 25000; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n ", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } + } else if (samsung_rev() >= EXYNOS4412_REV_2_0) { + MALI_PRINT(("::P::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv]; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } + } else { + MALI_PRINT(("::Q::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv]; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } + } + } + else if(soc_is_exynos4212()) { + tmp = __raw_readl(CHIPID_REG); + lock_flag_g3d = (tmp >> PD_G3D_LOCK_FLAG) & 0x1; + if (lock_flag_g3d) + g3d_lock_volt = 25000; + + for (i = 0; i < step_num; i++) { + MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + mali_dvfs[i].vol = asv_3d_volt_4212_9_table[i][exynos_result_of_asv] + g3d_lock_volt; + MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } + } +#else + unsigned int i, exynos_result_of_asv_group, target_asv; + + exynos_result_of_asv_group = exynos_result_of_asv & 0xf; + target_asv = exynos_result_of_asv >> 28; + MALI_PRINT(("exynos_result_of_asv_group = 0x%x, target_asv = 0x%x\n", exynos_result_of_asv_group, target_asv)); + + for (i = 0; i < step_num; i++) { + if (target_asv == 0x8) { //SUPPORT_1400MHZ + mali_dvfs[i].vol = asv_3d_volt_4210_14_table[i][exynos_result_of_asv_group]; + } else if (target_asv == 0x4){ //SUPPORT_1200MHZ + mali_dvfs[i].vol = asv_3d_volt_4210_12_table[i][exynos_result_of_asv_group]; + } + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } +#endif + + return MALI_TRUE; +} +#endif + +static unsigned int decideNextStatus(unsigned int utilization) +{ + static unsigned int level = 0; + int iStepCount = 0; + if (mali_runtime_resumed >= 0) { + level = mali_runtime_resumed; + mali_runtime_resumed = -1; + } + + if (mali_dvfs_control == 0 && level == get_mali_dvfs_status()) { + if (utilization > (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].upthreshold / 100) && + level < MALI_DVFS_STEPS - 1) { + level++; + if ((samsung_rev() < EXYNOS4412_REV_2_0) && 3 == get_mali_dvfs_status()) { + level=get_mali_dvfs_status(); + } + } + else if (utilization < (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].downthreshold / 100) && + level > 0) { + level--; + } + + if (_mali_osk_atomic_read(&bottomlock_status) > 0) { + if (level < bottom_lock_step) + level = bottom_lock_step; + } + } else { + for (iStepCount = MALI_DVFS_STEPS-1; iStepCount >= 0; iStepCount--) { + if ( mali_dvfs_control >= mali_dvfs[iStepCount].clock ) { + level = iStepCount; + break; + } + } + } + + return level; +} + + +static mali_bool mali_dvfs_status(unsigned int utilization) +{ + unsigned int nextStatus = 0; + unsigned int curStatus = 0; + mali_bool boostup = MALI_FALSE; + static int stay_count = 5; + + MALI_DEBUG_PRINT(4, ("> mali_dvfs_status: %d \n",utilization)); + + /* decide next step */ + curStatus = get_mali_dvfs_status(); + nextStatus = decideNextStatus(utilization); + + MALI_DEBUG_PRINT(4, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep)); + /* if next status is same with current status, don't change anything */ + if(curStatus != nextStatus) { + /*check if boost up or not*/ + if(maliDvfsStatus.currentStep < nextStatus) { + boostup = 1; + stay_count = 5; + } else if (maliDvfsStatus.currentStep > nextStatus){ + stay_count--; + } + if( boostup == 1 || stay_count <= 0){ + /*change mali dvfs status*/ +#ifdef CONFIG_MALI_DVFS + update_time_in_state(curStatus); +#endif + if (!change_mali_dvfs_status(nextStatus,boostup)) { + MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n")); + return MALI_FALSE; + } + boostup = 0; + stay_count = 5; + } + } + else + stay_count = 5; + return MALI_TRUE; +} + + +int mali_dvfs_is_running(void) +{ + return bMaliDvfsRun; +} + + +static void mali_dvfs_work_handler(struct work_struct *w) +{ + bMaliDvfsRun=1; + + MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n")); + + if(!mali_dvfs_status(mali_dvfs_utilization)) + MALI_DEBUG_PRINT(1, ( "error on mali dvfs status in mali_dvfs_work_handler")); + + bMaliDvfsRun=0; +} + +mali_bool init_mali_dvfs_status(void) +{ + /* + * default status + * add here with the right function to get initilization value. + */ + + if (!mali_dvfs_wq) + mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs"); + + _mali_osk_atomic_init(&bottomlock_status, 0); + + /* add a error handling here */ + maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP; + + return MALI_TRUE; +} + +void deinit_mali_dvfs_status(void) +{ + if (mali_dvfs_wq) + destroy_workqueue(mali_dvfs_wq); + + _mali_osk_atomic_term(&bottomlock_status); + + mali_dvfs_wq = NULL; +} + +mali_bool mali_dvfs_handler(unsigned int utilization) +{ + mali_dvfs_utilization = utilization; + queue_work_on(0, mali_dvfs_wq, &mali_dvfs_work); + + return MALI_TRUE; +} + +static mali_bool init_mali_clock(void) +{ + mali_bool ret = MALI_TRUE; + gpu_power_state = 1; + bPoweroff = 1; + + if (mali_clock != 0) + return ret; /* already initialized */ + + mali_dvfs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE + | _MALI_OSK_LOCKFLAG_ONELOCK, 0, 0); + if (mali_dvfs_lock == NULL) + return _MALI_OSK_ERR_FAULT; + + if (!mali_clk_get()) + { + MALI_PRINT(("Error: Failed to get Mali clock\n")); + goto err_clk; + } + + mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ); + + MALI_PRINT(("init_mali_clock mali_clock %x\n", mali_clock)); + +#ifdef CONFIG_REGULATOR + g3d_regulator = regulator_get(NULL, "vdd_g3d"); + + if (IS_ERR(g3d_regulator)) + { + MALI_PRINT(("MALI Error : failed to get vdd_g3d\n")); + ret = MALI_FALSE; + goto err_regulator; + } + + regulator_enable(g3d_regulator); + mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol); + +#ifdef EXYNOS4_ASV_ENABLED + if (samsung_rev() < EXYNOS4412_REV_2_0) { + if (mali_gpu_clk == 160) + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); + else + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); + } +#endif +#endif + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| + MALI_PROFILING_EVENT_CHANNEL_GPU| + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, + mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); +#endif + + mali_clk_put(MALI_FALSE); + + return MALI_TRUE; + +#ifdef CONFIG_REGULATOR +err_regulator: + regulator_put(g3d_regulator); +#endif +err_clk: + mali_clk_put(MALI_TRUE); + + return ret; +} + +static mali_bool deinit_mali_clock(void) +{ + if (mali_clock == 0) + return MALI_TRUE; + +#ifdef CONFIG_REGULATOR + if (g3d_regulator) + { + regulator_put(g3d_regulator); + g3d_regulator = NULL; + } +#endif + + mali_clk_put(MALI_TRUE); + + return MALI_TRUE; +} + + +static _mali_osk_errcode_t enable_mali_clocks(void) +{ + int err; + + if (atomic_read(&clk_active) == 0) { + err = clk_enable(mali_clock); + MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err)); + atomic_set(&clk_active, 1); + gpu_power_state = 1; + } + + /* set clock rate */ +#ifdef CONFIG_MALI_DVFS + if (get_mali_dvfs_control_status() != 0 || mali_gpu_clk >= mali_runtime_resume.clk) { + mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); + } else { +#ifdef CONFIG_REGULATOR + mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol); + +#ifdef EXYNOS4_ASV_ENABLED + if (samsung_rev() < EXYNOS4412_REV_2_0) { + if (mali_runtime_resume.clk == 160) + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); + else + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); + } +#endif +#endif + mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ); + set_mali_dvfs_current_step(mali_runtime_resume.step); + } +#else + mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ); + maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP; +#endif + + + MALI_SUCCESS; +} + +static _mali_osk_errcode_t disable_mali_clocks(void) +{ + if (atomic_read(&clk_active) == 1) { + clk_disable(mali_clock); + atomic_set(&clk_active, 0); + gpu_power_state = 0; + } + MALI_DEBUG_PRINT(3, ("disable_mali_clocks mali_clock %p \n", mali_clock)); + + MALI_SUCCESS; +} + +/* Some defines changed names in later Odroid-A kernels. Make sure it works for both. */ +#ifndef S5P_G3D_CONFIGURATION +#define S5P_G3D_CONFIGURATION S5P_PMU_G3D_CONF +#endif +#ifndef S5P_G3D_STATUS +#define S5P_G3D_STATUS S5P_PMU_G3D_CONF + 0x4 +#endif + +_mali_osk_errcode_t g3d_power_domain_control(int bpower_on) +{ + if (bpower_on) + { + void __iomem *status; + u32 timeout; + __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_G3D_CONFIGURATION); + status = S5P_G3D_STATUS; + + timeout = 10; + while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) + != S5P_INT_LOCAL_PWR_EN) { + if (timeout == 0) { + MALI_PRINTF(("Power domain enable failed.\n")); + return -ETIMEDOUT; + } + timeout--; + _mali_osk_time_ubusydelay(100); + } + } + else + { + void __iomem *status; + u32 timeout; + __raw_writel(0, S5P_G3D_CONFIGURATION); + + status = S5P_G3D_STATUS; + /* Wait max 1ms */ + timeout = 10; + while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) + { + if (timeout == 0) { + MALI_PRINTF(("Power domain disable failed.\n" )); + return -ETIMEDOUT; + } + timeout--; + _mali_osk_time_ubusydelay(100); + } + } + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_init(struct device *dev) +{ +#ifdef EXYNOS4_ASV_ENABLED + mali_dvfs_table_update(); +#endif + + MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT); + + atomic_set(&clk_active, 0); + +#ifdef CONFIG_MALI_DVFS + /* Create sysfs for time-in-state */ + if (device_create_file(dev, &dev_attr_time_in_state)) { + dev_err(dev, "Couldn't create sysfs file [time_in_state]\n"); + } + + if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC ); + if (!init_mali_dvfs_status()) + MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n")); +#endif + + mali_platform_power_mode_change(dev, MALI_POWER_MODE_ON); + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_deinit(struct device *dev) +{ + + mali_platform_power_mode_change(dev, MALI_POWER_MODE_DEEP_SLEEP); + deinit_mali_clock(); + +#ifdef CONFIG_MALI_DVFS + deinit_mali_dvfs_status(); + if (clk_register_map ) + { + _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map); + clk_register_map = NULL; + } +#endif + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_power_mode_change(struct device *dev, mali_power_mode power_mode) +{ + switch (power_mode) + { + case MALI_POWER_MODE_ON: + MALI_DEBUG_PRINT(3, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n", + bPoweroff ? "powering on" : "already on")); + if (bPoweroff == 1) + { +#if !defined(CONFIG_PM_RUNTIME) + g3d_power_domain_control(1); +#endif + MALI_DEBUG_PRINT(4, ("enable clock \n")); + enable_mali_clocks(); +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, + mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); + +#endif + bPoweroff=0; + } + break; + case MALI_POWER_MODE_LIGHT_SLEEP: + case MALI_POWER_MODE_DEEP_SLEEP: + MALI_DEBUG_PRINT(3, ("Mali platform: Got %s event, %s\n", power_mode == + MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" : + "MALI_POWER_MODE_DEEP_SLEEP", bPoweroff ? "already off" : "powering off")); + if (bPoweroff == 0) + { + disable_mali_clocks(); +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, + 0, 0, 0, 0, 0); +#endif + +#if !defined(CONFIG_PM_RUNTIME) + g3d_power_domain_control(0); +#endif + bPoweroff=1; + } + + break; + } + MALI_SUCCESS; +} + +void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data) +{ + if (bPoweroff==0) + { +#ifdef CONFIG_MALI_DVFS + if(!mali_dvfs_handler(data->utilization_gpu)) + MALI_DEBUG_PRINT(1, ("error on mali dvfs status in utilization\n")); +#endif + } +} + +#ifdef CONFIG_CPU_EXYNOS4210 +int mali_dvfs_bottom_lock_push() +{ + int prev_status = _mali_osk_atomic_read(&bottomlock_status); + + if (prev_status < 0) { + MALI_PRINT(("gpu bottom lock status is not valid for push\n")); + return -1; + } + if (prev_status == 0) { + mali_regulator_set_voltage(mali_dvfs[1].vol, mali_dvfs[1].vol); + mali_clk_set_rate(mali_dvfs[1].clock, mali_dvfs[1].freq); + set_mali_dvfs_current_step(1); + } + return _mali_osk_atomic_inc_return(&bottomlock_status); +} +#else +int mali_dvfs_bottom_lock_push(int lock_step) +{ + int prev_status = _mali_osk_atomic_read(&bottomlock_status); + + if (prev_status < 0) { + MALI_PRINT(("gpu bottom lock status is not valid for push\n")); + return -1; + } + if (bottom_lock_step < lock_step) { + bottom_lock_step = lock_step; + if (get_mali_dvfs_status() < lock_step) { + mali_regulator_set_voltage(mali_dvfs[lock_step].vol, mali_dvfs[lock_step].vol); + mali_clk_set_rate(mali_dvfs[lock_step].clock, mali_dvfs[lock_step].freq); + set_mali_dvfs_current_step(lock_step); + } + } + return _mali_osk_atomic_inc_return(&bottomlock_status); +} +#endif + +int mali_dvfs_bottom_lock_pop(void) +{ + int prev_status = _mali_osk_atomic_read(&bottomlock_status); + if (prev_status <= 0) { + MALI_PRINT(("gpu bottom lock status is not valid for pop\n")); + return -1; + } else if (prev_status == 1) { + bottom_lock_step = 0; + MALI_PRINT(("gpu bottom lock release\n")); + } + + return _mali_osk_atomic_dec_return(&bottomlock_status); +} + +int mali_dvfs_get_vol(int step) +{ + step = step % MAX_MALI_DVFS_STEPS; + MALI_DEBUG_ASSERT(step= vol) + return mali_dvfs[i].vol; + } + MALI_PRINT(("Failed to get voltage from mali_dvfs table, maximum voltage is %d uV\n", mali_dvfs[MALI_DVFS_STEPS-1].vol)); + return 0; +} +#endif + +#ifdef CONFIG_MALI_DVFS +static void update_time_in_state(int level) +{ + u64 current_time; + static u64 prev_time=0; + + if (prev_time ==0) + prev_time=get_jiffies_64(); + + current_time = get_jiffies_64(); + mali_dvfs_time[level] += current_time-prev_time; + prev_time = current_time; +} + +ssize_t show_time_in_state(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + int i; + + update_time_in_state(maliDvfsStatus.currentStep); + + for (i = 0; i < MALI_DVFS_STEPS; i++) { + ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d %llu\n", + mali_dvfs[i].clock, + mali_dvfs_time[i]); + } + + if (ret < PAGE_SIZE - 1) { + ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n"); + } else { + buf[PAGE_SIZE-2] = '\n'; + buf[PAGE_SIZE-1] = '\0'; + ret = PAGE_SIZE-1; + } + + return ret; +} + +ssize_t set_time_in_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + int i; + + for (i = 0; i < MALI_DVFS_STEPS; i++) { + mali_dvfs_time[i] = 0; + } + + return count; +} +#endif diff --git a/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.h b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.h new file mode 100644 index 0000000..1b9cf57 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.h @@ -0,0 +1,121 @@ +/* drivers/gpu/mali400/mali/platform/pegasus-m400/exynos4_pmm.h + * + * Copyright 2011 by S.LSI. Samsung Electronics Inc. + * San#24, Nongseo-Dong, Giheung-Gu, Yongin, Korea + * + * Samsung SoC Mali400 DVFS 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. + */ + +/** + * @file exynos4_pmm.h + * Platform specific Mali driver functions for the exynos 4XXX based platforms + */ + +#ifndef __EXYNOS4_PMM_H__ +#define __EXYNOS4_PMM_H__ + +#include "mali_utgard.h" +#include "mali_osk.h" +#include +/* @Enable or Disable Mali GPU Bottom Lock feature */ +#define MALI_GPU_BOTTOM_LOCK 1 +#define MALI_VOLTAGE_LOCK 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief description of power change reasons + */ +typedef enum mali_power_mode_tag +{ + MALI_POWER_MODE_ON, + MALI_POWER_MODE_LIGHT_SLEEP, + MALI_POWER_MODE_DEEP_SLEEP, +} mali_power_mode; + +/** @brief Platform specific setup and initialisation of MALI + * + * This is called from the entrypoint of the driver to initialize the platform + * + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_platform_init(struct device *dev); + +/** @brief Platform specific deinitialisation of MALI + * + * This is called on the exit of the driver to terminate the platform + * + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_platform_deinit(struct device *dev); + +/** @brief Platform specific powerdown sequence of MALI + * + * Call as part of platform init if there is no PMM support, else the + * PMM will call it. + * There are three power modes defined: + * 1) MALI_POWER_MODE_ON + * 2) MALI_POWER_MODE_LIGHT_SLEEP + * 3) MALI_POWER_MODE_DEEP_SLEEP + * MALI power management module transitions to MALI_POWER_MODE_LIGHT_SLEEP mode when MALI is idle + * for idle timer (software timer defined in mali_pmm_policy_jobcontrol.h) duration, MALI transitions + * to MALI_POWER_MODE_LIGHT_SLEEP mode during timeout if there are no more jobs queued. + * MALI power management module transitions to MALI_POWER_MODE_DEEP_SLEEP mode when OS does system power + * off. + * Customer has to add power down code when MALI transitions to MALI_POWER_MODE_LIGHT_SLEEP or MALI_POWER_MODE_DEEP_SLEEP + * mode. + * MALI_POWER_MODE_ON mode is entered when the MALI is to powered up. Some customers want to control voltage regulators during + * the whole system powers on/off. Customer can track in this function whether the MALI is powered up from + * MALI_POWER_MODE_LIGHT_SLEEP or MALI_POWER_MODE_DEEP_SLEEP mode and manage the voltage regulators as well. + * @param power_mode defines the power modes + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_platform_power_mode_change(struct device *dev, mali_power_mode power_mode); + + +/** @brief Platform specific handling of GPU utilization data + * + * When GPU utilization data is enabled, this function will be + * periodically called. + * + * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization. + */ +void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data); + +_mali_osk_errcode_t g3d_power_domain_control(int bpower_on); + +#ifdef CONFIG_REGULATOR +void mali_regulator_disable(void); +void mali_regulator_enable(void); +void mali_regulator_set_voltage(int min_uV, int max_uV); +#endif + +#ifdef CONFIG_MALI_DVFS +ssize_t show_time_in_state(struct device *dev, struct device_attribute *attr, char *buf); +ssize_t set_time_in_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +#ifdef CONFIG_CPU_EXYNOS4210 +#if MALI_GPU_BOTTOM_LOCK +int mali_dvfs_bottom_lock_push(void); +int mali_dvfs_bottom_lock_pop(void); +#endif +#else +int mali_dvfs_bottom_lock_push(int lock_step); +int mali_dvfs_bottom_lock_pop(void); +#endif +#endif + +#if MALI_VOLTAGE_LOCK +int mali_voltage_lock_push(int lock_vol); +int mali_voltage_lock_pop(void); +int mali_voltage_lock_init(void); +int mali_vol_get_from_table(int vol); +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/drivers/gpu/mali400/r3p2/mali/regs/mali_200_regs.h b/drivers/gpu/mali400/r3p2/mali/regs/mali_200_regs.h new file mode 100644 index 0000000..dd75149 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/regs/mali_200_regs.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _MALI200_REGS_H_ +#define _MALI200_REGS_H_ + +/** + * Enum for management register addresses. + */ +enum mali200_mgmt_reg +{ + MALI200_REG_ADDR_MGMT_VERSION = 0x1000, + MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x1004, + MALI200_REG_ADDR_MGMT_STATUS = 0x1008, + MALI200_REG_ADDR_MGMT_CTRL_MGMT = 0x100c, + + MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x1020, + MALI200_REG_ADDR_MGMT_INT_CLEAR = 0x1024, + MALI200_REG_ADDR_MGMT_INT_MASK = 0x1028, + MALI200_REG_ADDR_MGMT_INT_STATUS = 0x102c, + + MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW = 0x1044, + + MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x1050, + + MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x1080, + MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x1084, + MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x108c, + + MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x10a0, + MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x10a4, + MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x10ac, + + MALI200_REG_SIZEOF_REGISTER_BANK = 0x10f0 + +}; + +#define MALI200_REG_VAL_PERF_CNT_ENABLE 1 + +enum mali200_mgmt_ctrl_mgmt { + MALI200_REG_VAL_CTRL_MGMT_STOP_BUS = (1<<0), + MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES = (1<<3), + MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET = (1<<5), + MALI200_REG_VAL_CTRL_MGMT_START_RENDERING = (1<<6), + MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET = (1<<7), /* Only valid for Mali-300 and later */ +}; + +enum mali200_mgmt_irq { + MALI200_REG_VAL_IRQ_END_OF_FRAME = (1<<0), + MALI200_REG_VAL_IRQ_END_OF_TILE = (1<<1), + MALI200_REG_VAL_IRQ_HANG = (1<<2), + MALI200_REG_VAL_IRQ_FORCE_HANG = (1<<3), + MALI200_REG_VAL_IRQ_BUS_ERROR = (1<<4), + MALI200_REG_VAL_IRQ_BUS_STOP = (1<<5), + MALI200_REG_VAL_IRQ_CNT_0_LIMIT = (1<<6), + MALI200_REG_VAL_IRQ_CNT_1_LIMIT = (1<<7), + MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR = (1<<8), + MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND = (1<<9), + MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW = (1<<10), + MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW = (1<<11), + MALI400PP_REG_VAL_IRQ_RESET_COMPLETED = (1<<12), +}; + +#define MALI200_REG_VAL_IRQ_MASK_ALL ((enum mali200_mgmt_irq) (\ + MALI200_REG_VAL_IRQ_END_OF_FRAME |\ + MALI200_REG_VAL_IRQ_END_OF_TILE |\ + MALI200_REG_VAL_IRQ_HANG |\ + MALI200_REG_VAL_IRQ_FORCE_HANG |\ + MALI200_REG_VAL_IRQ_BUS_ERROR |\ + MALI200_REG_VAL_IRQ_BUS_STOP |\ + MALI200_REG_VAL_IRQ_CNT_0_LIMIT |\ + MALI200_REG_VAL_IRQ_CNT_1_LIMIT |\ + MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR |\ + MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND |\ + MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW |\ + MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW |\ + MALI400PP_REG_VAL_IRQ_RESET_COMPLETED)) + +#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\ + MALI200_REG_VAL_IRQ_END_OF_FRAME |\ + MALI200_REG_VAL_IRQ_FORCE_HANG |\ + MALI200_REG_VAL_IRQ_BUS_ERROR |\ + MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR |\ + MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND |\ + MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW |\ + MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW)) + +#define MALI200_REG_VAL_IRQ_MASK_NONE ((enum mali200_mgmt_irq)(0)) + +enum mali200_mgmt_status { + MALI200_REG_VAL_STATUS_RENDERING_ACTIVE = (1<<0), + MALI200_REG_VAL_STATUS_BUS_STOPPED = (1<<4), +}; + +enum mali200_render_unit +{ + MALI200_REG_ADDR_FRAME = 0x0000, + MALI200_REG_ADDR_RSW = 0x0004, + MALI200_REG_ADDR_STACK = 0x0030, + MALI200_REG_ADDR_STACK_SIZE = 0x0034, + MALI200_REG_ADDR_ORIGIN_OFFSET_X = 0x0040 +}; + +enum mali200_wb_unit { + MALI200_REG_ADDR_WB0 = 0x0100, + MALI200_REG_ADDR_WB1 = 0x0200, + MALI200_REG_ADDR_WB2 = 0x0300 +}; + +enum mali200_wb_unit_regs { + MALI200_REG_ADDR_WB_SOURCE_SELECT = 0x0000, +}; + +/* This should be in the top 16 bit of the version register of Mali PP */ +#define MALI200_PP_PRODUCT_ID 0xC807 +#define MALI300_PP_PRODUCT_ID 0xCE07 +#define MALI400_PP_PRODUCT_ID 0xCD07 +#define MALI450_PP_PRODUCT_ID 0xCF07 + + +#endif /* _MALI200_REGS_H_ */ diff --git a/drivers/gpu/mali400/r3p2/mali/regs/mali_gp_regs.h b/drivers/gpu/mali400/r3p2/mali/regs/mali_gp_regs.h new file mode 100644 index 0000000..c204901 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/regs/mali_gp_regs.h @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _MALIGP2_CONROL_REGS_H_ +#define _MALIGP2_CONROL_REGS_H_ + +/** + * These are the different geometry processor control registers. + * Their usage is to control and monitor the operation of the + * Vertex Shader and the Polygon List Builder in the geometry processor. + * Addresses are in 32-bit word relative sizes. + * @see [P0081] "Geometry Processor Data Structures" for details + */ + +typedef enum { + MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR = 0x00, + MALIGP2_REG_ADDR_MGMT_VSCL_END_ADDR = 0x04, + MALIGP2_REG_ADDR_MGMT_PLBUCL_START_ADDR = 0x08, + MALIGP2_REG_ADDR_MGMT_PLBUCL_END_ADDR = 0x0c, + MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR = 0x10, + MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR = 0x14, + MALIGP2_REG_ADDR_MGMT_CMD = 0x20, + MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT = 0x24, + MALIGP2_REG_ADDR_MGMT_INT_CLEAR = 0x28, + MALIGP2_REG_ADDR_MGMT_INT_MASK = 0x2C, + MALIGP2_REG_ADDR_MGMT_INT_STAT = 0x30, + MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW = 0x34, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x3C, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x40, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x44, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x48, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x4C, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x50, + MALIGP2_REG_ADDR_MGMT_STATUS = 0x68, + MALIGP2_REG_ADDR_MGMT_VERSION = 0x6C, + MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR_READ = 0x80, + MALIGP2_REG_ADDR_MGMT_PLBCL_START_ADDR_READ = 0x84, + MALIGP2_CONTR_AXI_BUS_ERROR_STAT = 0x94, + MALIGP2_REGISTER_ADDRESS_SPACE_SIZE = 0x98, +} maligp_reg_addr_mgmt_addr; + +#define MALIGP2_REG_VAL_PERF_CNT_ENABLE 1 + +/** + * Commands to geometry processor. + * @see MALIGP2_CTRL_REG_CMD + */ +typedef enum +{ + MALIGP2_REG_VAL_CMD_START_VS = (1<< 0), + MALIGP2_REG_VAL_CMD_START_PLBU = (1<< 1), + MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC = (1<< 4), + MALIGP2_REG_VAL_CMD_RESET = (1<< 5), + MALIGP2_REG_VAL_CMD_FORCE_HANG = (1<< 6), + MALIGP2_REG_VAL_CMD_STOP_BUS = (1<< 9), + MALI400GP_REG_VAL_CMD_SOFT_RESET = (1<<10), /* only valid for Mali-300 and later */ +} mgp_contr_reg_val_cmd; + + +/** @defgroup MALIGP2_IRQ + * Interrupt status of geometry processor. + * @see MALIGP2_CTRL_REG_INT_RAWSTAT, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, + * MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_ADDR_MGMT_INT_STAT + * @{ + */ +#define MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST (1 << 0) +#define MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST (1 << 1) +#define MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM (1 << 2) +#define MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ (1 << 3) +#define MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ (1 << 4) +#define MALIGP2_REG_VAL_IRQ_HANG (1 << 5) +#define MALIGP2_REG_VAL_IRQ_FORCE_HANG (1 << 6) +#define MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT (1 << 7) +#define MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT (1 << 8) +#define MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR (1 << 9) +#define MALIGP2_REG_VAL_IRQ_SYNC_ERROR (1 << 10) +#define MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR (1 << 11) +#define MALI400GP_REG_VAL_IRQ_AXI_BUS_STOPPED (1 << 12) +#define MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD (1 << 13) +#define MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD (1 << 14) +#define MALI400GP_REG_VAL_IRQ_RESET_COMPLETED (1 << 19) +#define MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW (1 << 20) +#define MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW (1 << 21) +#define MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS (1 << 22) + +/* Mask defining all IRQs in Mali GP */ +#define MALIGP2_REG_VAL_IRQ_MASK_ALL \ + (\ + MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ + MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ | \ + MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ | \ + MALIGP2_REG_VAL_IRQ_HANG | \ + MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ + MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT | \ + MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT | \ + MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ + MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ + MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR | \ + MALI400GP_REG_VAL_IRQ_AXI_BUS_STOPPED | \ + MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD | \ + MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD | \ + MALI400GP_REG_VAL_IRQ_RESET_COMPLETED | \ + MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \ + MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW | \ + MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS) + +/* Mask defining the IRQs in Mali GP which we use */ +#define MALIGP2_REG_VAL_IRQ_MASK_USED \ + (\ + MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ + MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ + MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ + MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ + MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR | \ + MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD | \ + MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD | \ + MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \ + MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW | \ + MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS) + +/* Mask defining non IRQs on MaliGP2*/ +#define MALIGP2_REG_VAL_IRQ_MASK_NONE 0 + +/** }@ defgroup MALIGP2_IRQ*/ + +/** @defgroup MALIGP2_STATUS + * The different Status values to the geometry processor. + * @see MALIGP2_CTRL_REG_STATUS + * @{ + */ +#define MALIGP2_REG_VAL_STATUS_VS_ACTIVE 0x0002 +#define MALIGP2_REG_VAL_STATUS_BUS_STOPPED 0x0004 +#define MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE 0x0008 +#define MALIGP2_REG_VAL_STATUS_BUS_ERROR 0x0040 +#define MALIGP2_REG_VAL_STATUS_WRITE_BOUND_ERR 0x0100 +/** }@ defgroup MALIGP2_STATUS*/ + +#define MALIGP2_REG_VAL_STATUS_MASK_ACTIVE (\ + MALIGP2_REG_VAL_STATUS_VS_ACTIVE|\ + MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE) + + +#define MALIGP2_REG_VAL_STATUS_MASK_ERROR (\ + MALIGP2_REG_VAL_STATUS_BUS_ERROR |\ + MALIGP2_REG_VAL_STATUS_WRITE_BOUND_ERR ) + +/* This should be in the top 16 bit of the version register of gp.*/ +#define MALI200_GP_PRODUCT_ID 0xA07 +#define MALI300_GP_PRODUCT_ID 0xC07 +#define MALI400_GP_PRODUCT_ID 0xB07 +#define MALI450_GP_PRODUCT_ID 0xD07 + +/** + * The different sources for instrumented on the geometry processor. + * @see MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC + */ + +enum MALIGP2_cont_reg_perf_cnt_src { + MALIGP2_REG_VAL_PERF_CNT1_SRC_NUMBER_OF_VERTICES_PROCESSED = 0x0a, +}; + +#endif diff --git a/drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.c b/drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.c new file mode 100644 index 0000000..a6b1d76 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.c @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_timestamp.h" + +/* This file is intentionally left empty, as all functions are inlined in mali_profiling_sampler.h */ diff --git a/drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.h b/drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.h new file mode 100644 index 0000000..3279dae --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_TIMESTAMP_H__ +#define __MALI_TIMESTAMP_H__ + +#include "mali_osk.h" + +MALI_STATIC_INLINE _mali_osk_errcode_t _mali_timestamp_reset(void) +{ + /* + * reset counters and overflow flags + */ + + u32 mask = (1 << 0) | /* enable all three counters */ + (0 << 1) | /* reset both Count Registers to 0x0 */ + (1 << 2) | /* reset the Cycle Counter Register to 0x0 */ + (0 << 3) | /* 1 = Cycle Counter Register counts every 64th processor clock cycle */ + (0 << 4) | /* Count Register 0 interrupt enable */ + (0 << 5) | /* Count Register 1 interrupt enable */ + (0 << 6) | /* Cycle Counter interrupt enable */ + (0 << 8) | /* Count Register 0 overflow flag (clear or write, flag on read) */ + (0 << 9) | /* Count Register 1 overflow flag (clear or write, flag on read) */ + (1 << 10); /* Cycle Counter Register overflow flag (clear or write, flag on read) */ + + __asm__ __volatile__ ("MCR p15, 0, %0, c15, c12, 0" : : "r" (mask) ); + + return _MALI_OSK_ERR_OK; +} + +MALI_STATIC_INLINE u64 _mali_timestamp_get(void) +{ + u32 result; + + /* this is for the clock cycles */ + __asm__ __volatile__ ("MRC p15, 0, %0, c15, c12, 1" : "=r" (result)); + + return (u64)result; +} + +#endif /* __MALI_TIMESTAMP_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.c b/drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.c new file mode 100644 index 0000000..a6b1d76 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.c @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_timestamp.h" + +/* This file is intentionally left empty, as all functions are inlined in mali_profiling_sampler.h */ diff --git a/drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.h b/drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.h new file mode 100644 index 0000000..94b842a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_TIMESTAMP_H__ +#define __MALI_TIMESTAMP_H__ + +#include "mali_osk.h" + +MALI_STATIC_INLINE _mali_osk_errcode_t _mali_timestamp_reset(void) +{ + return _MALI_OSK_ERR_OK; +} + +MALI_STATIC_INLINE u64 _mali_timestamp_get(void) +{ + return _mali_osk_time_get_ns(); +} + +#endif /* __MALI_TIMESTAMP_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/Kbuild b/drivers/gpu/mali400/r3p2/ump/Kbuild new file mode 100644 index 0000000..4ca1aae --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/Kbuild @@ -0,0 +1,78 @@ +# +# Copyright (C) 2010-2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained from Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +# Set default configuration to use, if Makefile didn't provide one. +# Change this to use a different config.h +# MALI_SEC +# CONFIG ?= os_memory_64m +CONFIG ?= pegasus-m400 + +# Validate selected config +ifneq ($(shell [ -d $(srctree)/$(src)/arch-$(CONFIG) ] && [ -f $(srctree)/$(src)/arch-$(CONFIG)/config.h ] && echo "OK"), OK) +$(warning Current directory is $(srctree)/$(src)) +$(error No configuration found for config $(CONFIG). Check that arch-$(CONFIG)/config.h exists) +else +# Link arch to the selected arch-config directory +$(shell [ -L $(srctree)/$(src)/arch ] && rm $(srctree)/$(src)/arch) +$(shell ln -sf arch-$(CONFIG) $(srctree)/$(src)/arch) +$(shell touch $(srctree)/$(src)/arch/config.h) +endif + +UDD_FILE_PREFIX = ../mali/ + +# Get subversion revision number, fall back to 0000 if no svn info is available +SVN_REV := 0000 + +ccflags-y += -DSVN_REV=$(SVN_REV) +ccflags-y += -DSVN_REV_STRING=\"$(SVN_REV)\" + +ccflags-y += -I$(srctree)/$(src) -I$(srctree)/$(src)/common -I$(srctree)/$(src)/linux -I$(srctree)/$(src)/../mali/common -I$(srctree)/$(src)/../mali/linux -I$(srctree)/$(src)/../../ump/include/ump + +# MALI_SEC +ccflags-y += -I$(srctree)/$(src)/include +ccflags-y += -DUSING_MEMORY=1 -DUMP_MEM_SIZE=512 + +ccflags-y += -DMALI_STATE_TRACKING=0 +ccflags-$(CONFIG_UMP_DEBUG) += -DDEBUG + +# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: +# The ARM proprietary product will only include the license/proprietary directory +# The GPL product will only include the license/gpl directory + +ifeq ($(wildcard $(srctree)/$(src)/linux/license/gpl/*),) +ccflags-y += -I$(srctree)/$(src)/linux/license/proprietary +else +ccflags-y += -I$(srctree)/$(src)/linux/license/gpl +endif + +ump-y = common/ump_kernel_common.o \ + common/ump_kernel_descriptor_mapping.o \ + common/ump_kernel_api.o \ + common/ump_kernel_ref_drv.o \ + linux/ump_kernel_linux.o \ + linux/ump_kernel_memory_backend_os.o \ + linux/ump_kernel_memory_backend_dedicated.o \ + linux/ump_memory_backend.o \ + linux/ump_ukk_wrappers.o \ + linux/ump_ukk_ref_wrappers.o \ + linux/ump_osk_atomics.o \ + linux/ump_osk_low_level_mem.o \ + linux/ump_osk_misc.o + +# MALI_SEC +# $(UDD_FILE_PREFIX)linux/mali_osk_atomics.o \ +# $(UDD_FILE_PREFIX)linux/mali_osk_locks.o \ +# $(UDD_FILE_PREFIX)linux/mali_osk_memory.o \ +# $(UDD_FILE_PREFIX)linux/mali_osk_math.o \ +# $(UDD_FILE_PREFIX)linux/mali_osk_misc.o + +# MALI_SEC +obj-$(CONFIG_MALI400_UMP) := ump.o + diff --git a/drivers/gpu/mali400/r3p2/ump/Kconfig b/drivers/gpu/mali400/r3p2/ump/Kconfig new file mode 100644 index 0000000..13785e2 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/Kconfig @@ -0,0 +1,7 @@ +config UMP_DEBUG + bool "Enable extra debug in UMP" + depends on MALI400_UMP + default n + ---help--- + This enabled extra debug checks and messages in UMP. + diff --git a/drivers/gpu/mali400/r3p2/ump/Makefile b/drivers/gpu/mali400/r3p2/ump/Makefile new file mode 100644 index 0000000..e2aa8e5 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/Makefile @@ -0,0 +1,67 @@ +# +# Copyright (C) 2010-2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained from Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +# For each arch check: CROSS_COMPILE , KDIR , CFLAGS += -DARCH + +export ARCH ?= arm +BUILD ?= debug + +check_cc2 = \ + $(shell if $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \ + then \ + echo "$(2)"; \ + else \ + echo "$(3)"; \ + fi ;) + +# Check that required parameters are supplied. +ifeq ($(CONFIG),) +$(error "CONFIG must be specified.") +endif +ifeq ($(CPU)$(KDIR),) +$(error "KDIR or CPU must be specified.") +endif + +# Get any user defined KDIR- or maybe even a hardcoded KDIR +-include KDIR_CONFIGURATION + +# Define host system directory +KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build + +ifeq ($(ARCH), arm) +# when compiling for ARM we're cross compiling +export CROSS_COMPILE ?= $(call check_cc2, arm-linux-gnueabi-gcc, arm-linux-gnueabi-, arm-none-linux-gnueabi-) +endif + +# look up KDIR based om CPU selection +KDIR ?= $(KDIR-$(CPU)) + +export CONFIG + +export CONFIG_UMP := m +ifeq ($(BUILD),debug) +export CONFIG_UMP_DEBUG := y +else +export CONFIG_UMP_DEBUG := n +endif + +ifeq ($(KDIR),) +$(error No KDIR found for platform $(CPU)) +endif + +all: + $(MAKE) -C $(KDIR) M=$(CURDIR) modules + +kernelrelease: + $(MAKE) -C $(KDIR) kernelrelease + +clean: + $(MAKE) -C $(KDIR) M=$(CURDIR) clean + $(MAKE) -C $(KDIR) M=$(CURDIR)/../mali clean diff --git a/drivers/gpu/mali400/r3p2/ump/Makefile.common b/drivers/gpu/mali400/r3p2/ump/Makefile.common new file mode 100644 index 0000000..c6aa633 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/Makefile.common @@ -0,0 +1,20 @@ +# +# Copyright (C) 2010-2011 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained from Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +SRC = $(UMP_FILE_PREFIX)common/ump_kernel_common.c \ + $(UMP_FILE_PREFIX)common/ump_kernel_descriptor_mapping.c \ + $(UMP_FILE_PREFIX)common/ump_kernel_api.c \ + $(UMP_FILE_PREFIX)common/ump_kernel_ref_drv.c + +# Get subversion revision number, fall back to 0000 if no svn info is available +SVN_REV:=$(shell ((svnversion | grep -qv exported && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') + +EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV) +EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\" diff --git a/drivers/gpu/mali400/r3p2/ump/arch-pegasus-m400/config.h b/drivers/gpu/mali400/r3p2/ump/arch-pegasus-m400/config.h new file mode 100644 index 0000000..7afbca6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/arch-pegasus-m400/config.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_UMP_H__ +#define __ARCH_CONFIG_UMP_H__ + +#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY +#if (USING_MEMORY == 0) /* Dedicated Memory */ +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000 +#else +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0 +#endif + +#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024 +#endif /* __ARCH_CONFIG_UMP_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/arch/arch-pegasus-m400 b/drivers/gpu/mali400/r3p2/ump/arch/arch-pegasus-m400 new file mode 120000 index 0000000..4006f31 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/arch/arch-pegasus-m400 @@ -0,0 +1 @@ +arch-pegasus-m400 \ No newline at end of file diff --git a/drivers/gpu/mali400/r3p2/ump/arch/config.h b/drivers/gpu/mali400/r3p2/ump/arch/config.h new file mode 100644 index 0000000..7afbca6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/arch/config.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_UMP_H__ +#define __ARCH_CONFIG_UMP_H__ + +#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY +#if (USING_MEMORY == 0) /* Dedicated Memory */ +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000 +#else +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0 +#endif + +#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024 +#endif /* __ARCH_CONFIG_UMP_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_api.c b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_api.c new file mode 100644 index 0000000..013f4c6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_api.c @@ -0,0 +1,548 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "ump_osk.h" +#include "ump_uk_types.h" +#include "ump_kernel_interface.h" +#include "ump_kernel_common.h" + + + +/* ---------------- UMP kernel space API functions follows ---------------- */ + + + +UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(ump_dd_handle memh) +{ + ump_dd_mem * mem = (ump_dd_mem *)memh; + + DEBUG_ASSERT_POINTER(mem); + + DBG_MSG(5, ("Returning secure ID. ID: %u\n", mem->secure_id)); + + return mem->secure_id; +} + + + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id) +{ + ump_dd_mem * mem; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id)); + if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id)); + return UMP_DD_HANDLE_INVALID; + } + + ump_dd_reference_add(mem); + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return (ump_dd_handle)mem; +} + +/* MALI_SEC */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id) +{ + ump_dd_mem * mem; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id)); + if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id)); + return UMP_DD_HANDLE_INVALID; + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return (ump_dd_handle)mem; +} + +UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle memh) +{ + ump_dd_mem * mem = (ump_dd_mem*) memh; + + DEBUG_ASSERT_POINTER(mem); + + return mem->nr_blocks; +} + + + +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle memh, ump_dd_physical_block * blocks, unsigned long num_blocks) +{ + ump_dd_mem * mem = (ump_dd_mem *)memh; + + DEBUG_ASSERT_POINTER(mem); + + if (blocks == NULL) + { + DBG_MSG(1, ("NULL parameter in ump_dd_phys_blocks_get()\n")); + return UMP_DD_INVALID; + } + + if (mem->nr_blocks != num_blocks) + { + DBG_MSG(1, ("Specified number of blocks do not match actual number of blocks\n")); + return UMP_DD_INVALID; + } + + DBG_MSG(5, ("Returning physical block information. ID: %u\n", mem->secure_id)); + + _mali_osk_memcpy(blocks, mem->block_array, sizeof(ump_dd_physical_block) * mem->nr_blocks); + + return UMP_DD_SUCCESS; +} + + + +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle memh, unsigned long index, ump_dd_physical_block * block) +{ + ump_dd_mem * mem = (ump_dd_mem *)memh; + + DEBUG_ASSERT_POINTER(mem); + + if (block == NULL) + { + DBG_MSG(1, ("NULL parameter in ump_dd_phys_block_get()\n")); + return UMP_DD_INVALID; + } + + if (index >= mem->nr_blocks) + { + DBG_MSG(5, ("Invalid index specified in ump_dd_phys_block_get()\n")); + return UMP_DD_INVALID; + } + + DBG_MSG(5, ("Returning physical block information. ID: %u, index: %lu\n", mem->secure_id, index)); + + *block = mem->block_array[index]; + + return UMP_DD_SUCCESS; +} + + + +UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle memh) +{ + ump_dd_mem * mem = (ump_dd_mem*)memh; + + DEBUG_ASSERT_POINTER(mem); + + DBG_MSG(5, ("Returning size. ID: %u, size: %lu\n", mem->secure_id, mem->size_bytes)); + + return mem->size_bytes; +} + + + +UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle memh) +{ + ump_dd_mem * mem = (ump_dd_mem*)memh; + int new_ref; + + DEBUG_ASSERT_POINTER(mem); + + new_ref = _ump_osk_atomic_inc_and_read(&mem->ref_count); + + DBG_MSG(5, ("Memory reference incremented. ID: %u, new value: %d\n", mem->secure_id, new_ref)); +} + + + +UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle memh) +{ + int new_ref; + ump_dd_mem * mem = (ump_dd_mem*)memh; + + DEBUG_ASSERT_POINTER(mem); + + /* We must hold this mutex while doing the atomic_dec_and_read, to protect + that elements in the ump_descriptor_mapping table is always valid. If they + are not, userspace may accidently map in this secure_ids right before its freed + giving a mapped backdoor into unallocated memory.*/ + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + new_ref = _ump_osk_atomic_dec_and_read(&mem->ref_count); + + DBG_MSG(5, ("Memory reference decremented. ID: %u, new value: %d\n", mem->secure_id, new_ref)); + + if (0 == new_ref) + { + DBG_MSG(3, ("Final release of memory. ID: %u\n", mem->secure_id)); + + ump_descriptor_mapping_free(device.secure_id_map, (int)mem->secure_id); + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + mem->release_func(mem->ctx, mem); + _mali_osk_free(mem); + } + else + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + } +} + + + +/* --------------- Handling of user space requests follows --------------- */ + + +_mali_osk_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args ) +{ + ump_session_data * session_data; + + DEBUG_ASSERT_POINTER( args ); + DEBUG_ASSERT_POINTER( args->ctx ); + + session_data = (ump_session_data *)args->ctx; + + /* check compatability */ + if (args->version == UMP_IOCTL_API_VERSION) + { + DBG_MSG(3, ("API version set to newest %d (compatible)\n", GET_VERSION(args->version))); + args->compatible = 1; + session_data->api_version = args->version; + } + else if (args->version == MAKE_VERSION_ID(1)) + { + DBG_MSG(2, ("API version set to depricated: %d (compatible)\n", GET_VERSION(args->version))); + args->compatible = 1; + session_data->api_version = args->version; + } + else + { + DBG_MSG(2, ("API version set to %d (incompatible with client version %d)\n", GET_VERSION(UMP_IOCTL_API_VERSION), GET_VERSION(args->version))); + args->compatible = 0; + args->version = UMP_IOCTL_API_VERSION; /* report our version */ + } + + return _MALI_OSK_ERR_OK; +} + + +_mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info ) +{ + ump_session_memory_list_element * session_memory_element; + ump_session_memory_list_element * tmp; + ump_session_data * session_data; + _mali_osk_errcode_t ret = _MALI_OSK_ERR_INVALID_FUNC; + int secure_id; + + DEBUG_ASSERT_POINTER( release_info ); + DEBUG_ASSERT_POINTER( release_info->ctx ); + + /* Retreive the session data */ + session_data = (ump_session_data*)release_info->ctx; + + /* If there are many items in the memory session list we + * could be de-referencing this pointer a lot so keep a local copy + */ + secure_id = release_info->secure_id; + + DBG_MSG(4, ("Releasing memory with IOCTL, ID: %u\n", secure_id)); + + /* Iterate through the memory list looking for the requested secure ID */ + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _MALI_OSK_LIST_FOREACHENTRY(session_memory_element, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list) + { + if ( session_memory_element->mem->secure_id == secure_id) + { + ump_dd_mem *release_mem; + + release_mem = session_memory_element->mem; + _mali_osk_list_del(&session_memory_element->list); + ump_dd_reference_release(release_mem); + _mali_osk_free(session_memory_element); + + ret = _MALI_OSK_ERR_OK; + break; + } + } + + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id)); + + DBG_MSG(4, ("_ump_ukk_release() returning 0x%x\n", ret)); + return ret; +} + +_mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction ) +{ + ump_dd_mem * mem; + _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT; + + DEBUG_ASSERT_POINTER( user_interaction ); + + /* We lock the mappings so things don't get removed while we are looking for the memory */ + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)user_interaction->secure_id, (void**)&mem)) + { + user_interaction->size = mem->size_bytes; + DBG_MSG(4, ("Returning size. ID: %u, size: %lu ", (ump_secure_id)user_interaction->secure_id, (unsigned long)user_interaction->size)); + ret = _MALI_OSK_ERR_OK; + } + else + { + user_interaction->size = 0; + DBG_MSG(1, ("Failed to look up mapping in ump_ioctl_size_get(). ID: %u\n", (ump_secure_id)user_interaction->secure_id)); + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + return ret; +} + + + +void _ump_ukk_msync( _ump_uk_msync_s *args ) +{ + ump_dd_mem * mem = NULL; + void *virtual = NULL; + u32 size = 0; + u32 offset = 0; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); + + if (NULL == mem) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_msync(). ID: %u\n", (ump_secure_id)args->secure_id)); + return; + } + /* Ensure the memory doesn't dissapear when we are flushing it. */ + ump_dd_reference_add(mem); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + /* Returns the cache settings back to Userspace */ + args->is_cached=mem->is_cached; + + /* If this flag is the only one set, we should not do the actual flush, only the readout */ + if ( _UMP_UK_MSYNC_READOUT_CACHE_ENABLED==args->op ) + { + DBG_MSG(3, ("_ump_ukk_msync READOUT ID: %u Enabled: %d\n", (ump_secure_id)args->secure_id, mem->is_cached)); + goto msync_release_and_return; + } + + /* Nothing to do if the memory is not caches */ + if ( 0==mem->is_cached ) + { + DBG_MSG(3, ("_ump_ukk_msync IGNORING ID: %u Enabled: %d OP: %d\n", (ump_secure_id)args->secure_id, mem->is_cached, args->op)); + goto msync_release_and_return; + } + DBG_MSG(3, ("UMP[%02u] _ump_ukk_msync Flush OP: %d Address: 0x%08x Mapping: 0x%08x\n", + (ump_secure_id)args->secure_id, args->op, args->address, args->mapping)); + + if ( args->address ) + { + virtual = (void *)((u32)args->address); + offset = (u32)((args->address) - (args->mapping)); + } else { + /* Flush entire mapping when no address is specified. */ + virtual = args->mapping; + } + if ( args->size ) + { + size = args->size; + } else { + /* Flush entire mapping when no size is specified. */ + size = mem->size_bytes - offset; + } + + if ( (offset + size) > mem->size_bytes ) + { + DBG_MSG(1, ("Trying to flush more than the entire UMP allocation: offset: %u + size: %u > %u\n", offset, size, mem->size_bytes)); + goto msync_release_and_return; + } + + /* The actual cache flush - Implemented for each OS*/ + _ump_osk_msync( mem, virtual, offset, size, args->op, NULL); + +msync_release_and_return: + ump_dd_reference_release(mem); + return; +} + +void _ump_ukk_cache_operations_control(_ump_uk_cache_operations_control_s* args) +{ + ump_session_data * session_data; + ump_uk_cache_op_control op; + + DEBUG_ASSERT_POINTER( args ); + DEBUG_ASSERT_POINTER( args->ctx ); + + op = args->op; + session_data = (ump_session_data *)args->ctx; + + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + if ( op== _UMP_UK_CACHE_OP_START ) + { + session_data->cache_operations_ongoing++; + DBG_MSG(4, ("Cache ops start\n" )); + if ( session_data->cache_operations_ongoing != 1 ) + { + DBG_MSG(2, ("UMP: Number of simultanious cache control ops: %d\n", session_data->cache_operations_ongoing) ); + } + } + else if ( op== _UMP_UK_CACHE_OP_FINISH ) + { + DBG_MSG(4, ("Cache ops finish\n")); + session_data->cache_operations_ongoing--; + #if 0 + if ( session_data->has_pending_level1_cache_flush) + { + /* This function will set has_pending_level1_cache_flush=0 */ + _ump_osk_msync( NULL, NULL, 0, 0, _UMP_UK_MSYNC_FLUSH_L1, session_data); + } + #endif + + /* to be on the safe side: always flush l1 cache when cache operations are done */ + _ump_osk_msync( NULL, NULL, 0, 0, _UMP_UK_MSYNC_FLUSH_L1, session_data); + DBG_MSG(4, ("Cache ops finish end\n" )); + } + else + { + DBG_MSG(1, ("Illegal call to %s at line %d\n", __FUNCTION__, __LINE__)); + } + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + +} + +void _ump_ukk_switch_hw_usage(_ump_uk_switch_hw_usage_s *args ) +{ + ump_dd_mem * mem = NULL; + ump_uk_user old_user; + ump_uk_msync_op cache_op = _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE; + ump_session_data *session_data; + + DEBUG_ASSERT_POINTER( args ); + DEBUG_ASSERT_POINTER( args->ctx ); + + session_data = (ump_session_data *)args->ctx; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); + + if (NULL == mem) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_switch_hw_usage(). ID: %u\n", (ump_secure_id)args->secure_id)); + return; + } + + old_user = mem->hw_device; + mem->hw_device = args->new_user; + + DBG_MSG(3, ("UMP[%02u] Switch usage Start New: %s Prev: %s.\n", (ump_secure_id)args->secure_id, args->new_user?"MALI":"CPU",old_user?"MALI":"CPU")); + + if ( ! mem->is_cached ) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(3, ("UMP[%02u] Changing owner of uncached memory. Cache flushing not needed.\n", (ump_secure_id)args->secure_id)); + return; + } + + if ( old_user == args->new_user) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(4, ("UMP[%02u] Setting the new_user equal to previous for. Cache flushing not needed.\n", (ump_secure_id)args->secure_id)); + return; + } + if ( + /* Previous AND new is both different from CPU */ + (old_user != _UMP_UK_USED_BY_CPU) && (args->new_user != _UMP_UK_USED_BY_CPU ) + ) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(4, ("UMP[%02u] Previous and new user is not CPU. Cache flushing not needed.\n", (ump_secure_id)args->secure_id)); + return; + } + + if ( (old_user != _UMP_UK_USED_BY_CPU ) && (args->new_user==_UMP_UK_USED_BY_CPU) ) + { + cache_op =_UMP_UK_MSYNC_INVALIDATE; + DBG_MSG(4, ("UMP[%02u] Cache invalidation needed\n", (ump_secure_id)args->secure_id)); +#ifdef UMP_SKIP_INVALIDATION +#error + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(4, ("UMP[%02u] Performing Cache invalidation SKIPPED\n", (ump_secure_id)args->secure_id)); + return; +#endif + } + /* Ensure the memory doesn't dissapear when we are flushing it. */ + ump_dd_reference_add(mem); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + /* Take lock to protect: session->cache_operations_ongoing and session->has_pending_level1_cache_flush */ + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + /* Actual cache flush */ + _ump_osk_msync( mem, NULL, 0, mem->size_bytes, cache_op, session_data); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + + ump_dd_reference_release(mem); + DBG_MSG(4, ("UMP[%02u] Switch usage Finish\n", (ump_secure_id)args->secure_id)); + return; +} + +void _ump_ukk_lock(_ump_uk_lock_s *args ) +{ + ump_dd_mem * mem = NULL; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); + + if (NULL == mem) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("UMP[%02u] Failed to look up mapping in _ump_ukk_lock(). ID: %u\n", (ump_secure_id)args->secure_id)); + return; + } + ump_dd_reference_add(mem); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + DBG_MSG(1, ("UMP[%02u] Lock. New lock flag: %d. Old Lock flag:\n", (u32)args->secure_id, (u32)args->lock_usage, (u32) mem->lock_usage )); + + mem->lock_usage = (ump_lock_usage) args->lock_usage; + + ump_dd_reference_release(mem); +} + +void _ump_ukk_unlock(_ump_uk_unlock_s *args ) +{ + ump_dd_mem * mem = NULL; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); + + if (NULL == mem) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_unlock(). ID: %u\n", (ump_secure_id)args->secure_id)); + return; + } + ump_dd_reference_add(mem); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + DBG_MSG(1, ("UMP[%02u] Unlocking. Old Lock flag:\n", (u32)args->secure_id, (u32) mem->lock_usage )); + + mem->lock_usage = (ump_lock_usage) UMP_NOT_LOCKED; + + ump_dd_reference_release(mem); +} diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c new file mode 100644 index 0000000..306ea3d --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_bitops.h" +#include "mali_osk_list.h" +#include "ump_osk.h" +#include "ump_uk_types.h" +#include "ump_ukk.h" +#include "ump_kernel_common.h" +#include "ump_kernel_descriptor_mapping.h" +#include "ump_kernel_memory_backend.h" + + + +/** + * Define the initial and maximum size of number of secure_ids on the system + */ +#define UMP_SECURE_ID_TABLE_ENTRIES_INITIAL (128 ) +#define UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM (4096 ) + + +/** + * Define the initial and maximum size of the ump_session_data::cookies_map, + * which is a \ref ump_descriptor_mapping. This limits how many secure_ids + * may be mapped into a particular process using _ump_ukk_map_mem(). + */ + +#define UMP_COOKIES_PER_SESSION_INITIAL (UMP_SECURE_ID_TABLE_ENTRIES_INITIAL ) +#define UMP_COOKIES_PER_SESSION_MAXIMUM (UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM) + +struct ump_dev device; + +_mali_osk_errcode_t ump_kernel_constructor(void) +{ + _mali_osk_errcode_t err; + + /* Perform OS Specific initialization */ + err = _ump_osk_init(); + if( _MALI_OSK_ERR_OK != err ) + { + MSG_ERR(("Failed to initiaze the UMP Device Driver")); + return err; + } + + /* Init the global device */ + _mali_osk_memset(&device, 0, sizeof(device) ); + + /* Create the descriptor map, which will be used for mapping secure ID to ump_dd_mem structs */ + device.secure_id_map_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0 , 0); + if (NULL == device.secure_id_map_lock) + { + MSG_ERR(("Failed to create OSK lock for secure id lookup table\n")); + return _MALI_OSK_ERR_NOMEM; + } + + device.secure_id_map = ump_descriptor_mapping_create(UMP_SECURE_ID_TABLE_ENTRIES_INITIAL, UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM); + if (NULL == device.secure_id_map) + { + _mali_osk_lock_term(device.secure_id_map_lock); + MSG_ERR(("Failed to create secure id lookup table\n")); + return _MALI_OSK_ERR_NOMEM; + } + + /* Init memory backend */ + device.backend = ump_memory_backend_create(); + if (NULL == device.backend) + { + MSG_ERR(("Failed to create memory backend\n")); + _mali_osk_lock_term(device.secure_id_map_lock); + ump_descriptor_mapping_destroy(device.secure_id_map); + return _MALI_OSK_ERR_NOMEM; + } + + return _MALI_OSK_ERR_OK; +} + +void ump_kernel_destructor(void) +{ + DEBUG_ASSERT_POINTER(device.secure_id_map); + DEBUG_ASSERT_POINTER(device.secure_id_map_lock); + + _mali_osk_lock_term(device.secure_id_map_lock); + device.secure_id_map_lock = NULL; + + ump_descriptor_mapping_destroy(device.secure_id_map); + device.secure_id_map = NULL; + + device.backend->shutdown(device.backend); + device.backend = NULL; + + ump_memory_backend_destroy(); + + _ump_osk_term(); +} + +/** Creates a new UMP session + */ +_mali_osk_errcode_t _ump_ukk_open( void** context ) +{ + struct ump_session_data * session_data; + + /* allocated struct to track this session */ + session_data = (struct ump_session_data *)_mali_osk_malloc(sizeof(struct ump_session_data)); + if (NULL == session_data) + { + MSG_ERR(("Failed to allocate ump_session_data in ump_file_open()\n")); + return _MALI_OSK_ERR_NOMEM; + } + + session_data->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0); + if( NULL == session_data->lock ) + { + MSG_ERR(("Failed to initialize lock for ump_session_data in ump_file_open()\n")); + _mali_osk_free(session_data); + return _MALI_OSK_ERR_NOMEM; + } + + session_data->cookies_map = ump_descriptor_mapping_create( UMP_COOKIES_PER_SESSION_INITIAL, UMP_COOKIES_PER_SESSION_MAXIMUM ); + + if ( NULL == session_data->cookies_map ) + { + MSG_ERR(("Failed to create descriptor mapping for _ump_ukk_map_mem cookies\n")); + + _mali_osk_lock_term( session_data->lock ); + _mali_osk_free( session_data ); + return _MALI_OSK_ERR_NOMEM; + } + + _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_list); + + _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_mappings_list); + + /* Since initial version of the UMP interface did not use the API_VERSION ioctl we have to assume + that it is this version, and not the "latest" one: UMP_IOCTL_API_VERSION + Current and later API versions would do an additional call to this IOCTL and update this variable + to the correct one.*/ + session_data->api_version = MAKE_VERSION_ID(1); + + *context = (void*)session_data; + + session_data->cache_operations_ongoing = 0 ; + session_data->has_pending_level1_cache_flush = 0; + + DBG_MSG(2, ("New session opened\n")); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _ump_ukk_close( void** context ) +{ + struct ump_session_data * session_data; + ump_session_memory_list_element * item; + ump_session_memory_list_element * tmp; + + session_data = (struct ump_session_data *)*context; + if (NULL == session_data) + { + MSG_ERR(("Session data is NULL in _ump_ukk_close()\n")); + return _MALI_OSK_ERR_INVALID_ARGS; + } + + /* Unmap any descriptors mapped in. */ + if (0 == _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list)) + { + ump_memory_allocation *descriptor; + ump_memory_allocation *temp; + + DBG_MSG(1, ("Memory mappings found on session usage list during session termination\n")); + + /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */ + _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->list_head_session_memory_mappings_list, ump_memory_allocation, list) + { + _ump_uk_unmap_mem_s unmap_args; + DBG_MSG(4, ("Freeing block with phys address 0x%x size 0x%x mapped in user space at 0x%x\n", + descriptor->phys_addr, descriptor->size, descriptor->mapping)); + unmap_args.ctx = (void*)session_data; + unmap_args.mapping = descriptor->mapping; + unmap_args.size = descriptor->size; + unmap_args._ukk_private = NULL; /* NOTE: unused */ + unmap_args.cookie = descriptor->cookie; + + /* NOTE: This modifies the list_head_session_memory_mappings_list */ + _ump_ukk_unmap_mem( &unmap_args ); + } + } + + /* ASSERT that we really did free everything, because _ump_ukk_unmap_mem() + * can fail silently. */ + DEBUG_ASSERT( _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list) ); + + _MALI_OSK_LIST_FOREACHENTRY(item, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list) + { + _mali_osk_list_del(&item->list); + DBG_MSG(2, ("Releasing UMP memory %u as part of file close\n", item->mem->secure_id)); + ump_dd_reference_release(item->mem); + _mali_osk_free(item); + } + + ump_descriptor_mapping_destroy( session_data->cookies_map ); + + _mali_osk_lock_term(session_data->lock); + _mali_osk_free(session_data); + + DBG_MSG(2, ("Session closed\n")); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ) +{ + struct ump_session_data * session_data; + ump_memory_allocation * descriptor; /* Describes current mapping of memory */ + _mali_osk_errcode_t err; + unsigned long offset = 0; + unsigned long left; + ump_dd_handle handle; /* The real UMP handle for this memory. Its real datatype is ump_dd_mem* */ + ump_dd_mem * mem; /* The real UMP memory. It is equal to the handle, but with exposed struct */ + u32 block; + int map_id; + + session_data = (ump_session_data *)args->ctx; + if( NULL == session_data ) + { + MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); + return _MALI_OSK_ERR_INVALID_ARGS; + } + /* MALI_SEC */ + /* SEC kernel stability 2012-02-17 */ + if (NULL == session_data->cookies_map) + { + MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n")); + return _MALI_OSK_ERR_INVALID_ARGS; + } + descriptor = (ump_memory_allocation*) _mali_osk_calloc( 1, sizeof(ump_memory_allocation)); + if (NULL == descriptor) + { + MSG_ERR(("ump_ukk_map_mem: descriptor allocation failed\n")); + return _MALI_OSK_ERR_NOMEM; + } + + handle = ump_dd_handle_create_from_secure_id(args->secure_id); + if ( UMP_DD_HANDLE_INVALID == handle) + { + _mali_osk_free(descriptor); + DBG_MSG(1, ("Trying to map unknown secure ID %u\n", args->secure_id)); + return _MALI_OSK_ERR_FAULT; + } + + mem = (ump_dd_mem*)handle; + DEBUG_ASSERT(mem); + if (mem->size_bytes != args->size) + { + _mali_osk_free(descriptor); + ump_dd_reference_release(handle); + DBG_MSG(1, ("Trying to map too much or little. ID: %u, virtual size=%lu, UMP size: %lu\n", args->secure_id, args->size, mem->size_bytes)); + return _MALI_OSK_ERR_FAULT; + } + + map_id = ump_descriptor_mapping_allocate_mapping( session_data->cookies_map, (void*) descriptor ); + + if (map_id < 0) + { + _mali_osk_free(descriptor); + ump_dd_reference_release(handle); + DBG_MSG(1, ("ump_ukk_map_mem: unable to allocate a descriptor_mapping for return cookie\n")); + + return _MALI_OSK_ERR_NOMEM; + } + + descriptor->size = args->size; + descriptor->handle = handle; + descriptor->phys_addr = args->phys_addr; + descriptor->process_mapping_info = args->_ukk_private; + descriptor->ump_session = session_data; + descriptor->cookie = (u32)map_id; + + if ( mem->is_cached ) + { + descriptor->is_cached = 1; + args->is_cached = 1; + DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id)); + } + /* MALI_SEC */ + else if ( args->is_cached) + { + mem->is_cached = 1; + descriptor->is_cached = 1; + DBG_MSG(3, ("Warning mapping UMP secure_id: %d. As cached, while it was allocated uncached.\n", args->secure_id)); + } + else + { + descriptor->is_cached = 0; + args->is_cached = 0; + DBG_MSG(3, ("Mapping UMP secure_id: %d as Uncached.\n", args->secure_id)); + } + + _mali_osk_list_init( &descriptor->list ); + + err = _ump_osk_mem_mapregion_init( descriptor ); + if( _MALI_OSK_ERR_OK != err ) + { + DBG_MSG(1, ("Failed to initialize memory mapping in _ump_ukk_map_mem(). ID: %u\n", args->secure_id)); + ump_descriptor_mapping_free( session_data->cookies_map, map_id ); + _mali_osk_free(descriptor); + ump_dd_reference_release(mem); + return err; + } + + DBG_MSG(4, ("Mapping virtual to physical memory: ID: %u, size:%lu, first physical addr: 0x%08lx, number of regions: %lu\n", + mem->secure_id, + mem->size_bytes, + ((NULL != mem->block_array) ? mem->block_array->addr : 0), + mem->nr_blocks)); + + left = descriptor->size; + /* loop over all blocks and map them in */ + for (block = 0; block < mem->nr_blocks; block++) + { + unsigned long size_to_map; + + if (left > mem->block_array[block].size) + { + size_to_map = mem->block_array[block].size; + } + else + { + size_to_map = left; + } + + if (_MALI_OSK_ERR_OK != _ump_osk_mem_mapregion_map(descriptor, offset, (u32 *)&(mem->block_array[block].addr), size_to_map ) ) + { + DBG_MSG(1, ("WARNING: _ump_ukk_map_mem failed to map memory into userspace\n")); + ump_descriptor_mapping_free( session_data->cookies_map, map_id ); + ump_dd_reference_release(mem); + _ump_osk_mem_mapregion_term( descriptor ); + _mali_osk_free(descriptor); + return _MALI_OSK_ERR_FAULT; + } + left -= size_to_map; + offset += size_to_map; + } + + /* Add to the ump_memory_allocation tracking list */ + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_add( &descriptor->list, &session_data->list_head_session_memory_mappings_list ); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + + args->mapping = descriptor->mapping; + args->cookie = descriptor->cookie; + + return _MALI_OSK_ERR_OK; +} + +void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args ) +{ + struct ump_session_data * session_data; + ump_memory_allocation * descriptor; + ump_dd_handle handle; + + session_data = (ump_session_data *)args->ctx; + + if( NULL == session_data ) + { + MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); + return; + } + /* MALI_SEC */ + /* SEC kernel stability 2012-02-17 */ + if (NULL == session_data->cookies_map) + { + MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n")); + return; + } + if (0 != ump_descriptor_mapping_get( session_data->cookies_map, (int)args->cookie, (void**)&descriptor) ) + { + MSG_ERR(("_ump_ukk_map_mem: cookie 0x%X not found for this session\n", args->cookie )); + return; + } + + DEBUG_ASSERT_POINTER(descriptor); + + handle = descriptor->handle; + if ( UMP_DD_HANDLE_INVALID == handle) + { + DBG_MSG(1, ("WARNING: Trying to unmap unknown handle: UNKNOWN\n")); + return; + } + + /* Remove the ump_memory_allocation from the list of tracked mappings */ + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_del( &descriptor->list ); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + + ump_descriptor_mapping_free( session_data->cookies_map, (int)args->cookie ); + + ump_dd_reference_release(handle); + + _ump_osk_mem_mapregion_term( descriptor ); + _mali_osk_free(descriptor); +} + +u32 _ump_ukk_report_memory_usage( void ) +{ + if(device.backend->stat) + return device.backend->stat(device.backend); + else + return 0; +} diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.h b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.h new file mode 100644 index 0000000..6e3a2e9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __UMP_KERNEL_COMMON_H__ +#define __UMP_KERNEL_COMMON_H__ + +#include "ump_kernel_types.h" +#include "ump_kernel_interface.h" +#include "ump_kernel_descriptor_mapping.h" +#include "ump_kernel_memory_backend.h" + + +#ifdef DEBUG + extern int ump_debug_level; + #define UMP_DEBUG_PRINT(args) _mali_osk_dbgmsg args + #define UMP_DEBUG_CODE(args) args + #define DBG_MSG(level,args) do { /* args should be in brackets */ \ + ((level) <= ump_debug_level)?\ + UMP_DEBUG_PRINT(("UMP<" #level ">: ")), \ + UMP_DEBUG_PRINT(args):0; \ + } while (0) + + #define DBG_MSG_IF(level,condition,args) /* args should be in brackets */ \ + if((condition)&&((level) <= ump_debug_level)) {\ + UMP_DEBUG_PRINT(("UMP<" #level ">: ")); \ + UMP_DEBUG_PRINT(args); \ + } + + #define DBG_MSG_ELSE(level,args) /* args should be in brackets */ \ + else if((level) <= ump_debug_level) { \ + UMP_DEBUG_PRINT(("UMP<" #level ">: ")); \ + UMP_DEBUG_PRINT(args); \ + } + + #define DEBUG_ASSERT_POINTER(pointer) do {if( (pointer)== NULL) MSG_ERR(("NULL pointer " #pointer)); } while(0) + #define DEBUG_ASSERT(condition) do {if(!(condition)) MSG_ERR(("ASSERT failed: " #condition)); } while(0) +#else /* DEBUG */ + #define UMP_DEBUG_PRINT(args) do {} while(0) + #define UMP_DEBUG_CODE(args) + #define DBG_MSG(level,args) do {} while(0) + #define DBG_MSG_IF(level,condition,args) do {} while(0) + #define DBG_MSG_ELSE(level,args) do {} while(0) + #define DEBUG_ASSERT(condition) do {} while(0) + #define DEBUG_ASSERT_POINTER(pointer) do {} while(0) +#endif /* DEBUG */ + +#define MSG_ERR(args) do{ /* args should be in brackets */ \ + _mali_osk_dbgmsg("UMP: ERR: %s\n" ,__FILE__); \ + _mali_osk_dbgmsg( " %s()%4d\n", __FUNCTION__, __LINE__) ; \ + _mali_osk_dbgmsg args ; \ + _mali_osk_dbgmsg("\n"); \ + } while(0) + +#define MSG(args) do{ /* args should be in brackets */ \ + _mali_osk_dbgmsg("UMP: "); \ + _mali_osk_dbgmsg args; \ + } while (0) + + + +/* + * This struct is used to store per session data. + * A session is created when someone open() the device, and + * closed when someone close() it or the user space application terminates. + */ +typedef struct ump_session_data +{ + _mali_osk_list_t list_head_session_memory_list; /**< List of ump allocations made by the process (elements are ump_session_memory_list_element) */ + _mali_osk_list_t list_head_session_memory_mappings_list; /**< List of ump_memory_allocations mapped in */ + int api_version; + _mali_osk_lock_t * lock; + ump_descriptor_mapping * cookies_map; /**< Secure mapping of cookies from _ump_ukk_map_mem() */ + int cache_operations_ongoing; + int has_pending_level1_cache_flush; +} ump_session_data; + + + +/* + * This struct is used to track the UMP memory references a session has. + * We need to track this in order to be able to clean up after user space processes + * which don't do it themself (e.g. due to a crash or premature termination). + */ +typedef struct ump_session_memory_list_element +{ + struct ump_dd_mem * mem; + _mali_osk_list_t list; +} ump_session_memory_list_element; + + + +/* + * Device specific data, created when device driver is loaded, and then kept as the global variable device. + */ +typedef struct ump_dev +{ + _mali_osk_lock_t * secure_id_map_lock; + ump_descriptor_mapping * secure_id_map; + ump_memory_backend * backend; +} ump_dev; + + + +extern int ump_debug_level; +extern struct ump_dev device; + +_mali_osk_errcode_t ump_kernel_constructor(void); +void ump_kernel_destructor(void); +int map_errcode( _mali_osk_errcode_t err ); + +/** + * variables from user space cannot be dereferenced from kernel space; tagging them + * with __user allows the GCC compiler to generate a warning. Other compilers may + * not support this so we define it here as an empty macro if the compiler doesn't + * define it. + */ +#ifndef __user +#define __user +#endif + +#endif /* __UMP_KERNEL_COMMON_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.c b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.c new file mode 100644 index 0000000..2531f80 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_bitops.h" +#include "ump_kernel_common.h" +#include "ump_kernel_descriptor_mapping.h" + +#define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1)) + +/** + * Allocate a descriptor table capable of holding 'count' mappings + * @param count Number of mappings in the table + * @return Pointer to a new table, NULL on error + */ +static ump_descriptor_table * descriptor_table_alloc(int count); + +/** + * Free a descriptor table + * @param table The table to free + */ +static void descriptor_table_free(ump_descriptor_table * table); + +ump_descriptor_mapping * ump_descriptor_mapping_create(int init_entries, int max_entries) +{ + ump_descriptor_mapping * map = _mali_osk_calloc(1, sizeof(ump_descriptor_mapping) ); + + init_entries = MALI_PAD_INT(init_entries); + max_entries = MALI_PAD_INT(max_entries); + + if (NULL != map) + { + map->table = descriptor_table_alloc(init_entries); + if (NULL != map->table) + { + map->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_READERWRITER, 0 , 0); + if ( NULL != map->lock ) + { + _mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */ + map->max_nr_mappings_allowed = max_entries; + map->current_nr_mappings = init_entries; + return map; + } + descriptor_table_free(map->table); + } + _mali_osk_free(map); + } + return NULL; +} + +void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map) +{ + descriptor_table_free(map->table); + _mali_osk_lock_term( map->lock ); + _mali_osk_free(map); +} + +int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target) +{ + int descriptor = -1;/*-EFAULT;*/ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); + if (descriptor == map->current_nr_mappings) + { + int nr_mappings_new; + /* no free descriptor, try to expand the table */ + ump_descriptor_table * new_table; + ump_descriptor_table * old_table = map->table; + nr_mappings_new= map->current_nr_mappings *2; + + if (map->current_nr_mappings >= map->max_nr_mappings_allowed) + { + descriptor = -1; + goto unlock_and_exit; + } + + new_table = descriptor_table_alloc(nr_mappings_new); + if (NULL == new_table) + { + descriptor = -1; + goto unlock_and_exit; + } + + _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); + _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); + map->table = new_table; + map->current_nr_mappings = nr_mappings_new; + descriptor_table_free(old_table); + } + + /* we have found a valid descriptor, set the value and usage bit */ + _mali_osk_set_nonatomic_bit(descriptor, map->table->usage); + map->table->mappings[descriptor] = target; + +unlock_and_exit: + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); + return descriptor; +} + +int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target) +{ + int result = -1;/*-EFAULT;*/ + DEBUG_ASSERT(map); + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + *target = map->table->mappings[descriptor]; + result = 0; + } + else *target = NULL; + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); + return result; +} + +int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target) +{ + int result = -1;/*-EFAULT;*/ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + map->table->mappings[descriptor] = target; + result = 0; + } + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); + return result; +} + +void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor) +{ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + map->table->mappings[descriptor] = NULL; + _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage); + } + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); +} + +static ump_descriptor_table * descriptor_table_alloc(int count) +{ + ump_descriptor_table * table; + + table = _mali_osk_calloc(1, sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count) ); + + if (NULL != table) + { + table->usage = (u32*)((u8*)table + sizeof(ump_descriptor_table)); + table->mappings = (void**)((u8*)table + sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG)); + } + + return table; +} + +static void descriptor_table_free(ump_descriptor_table * table) +{ + _mali_osk_free(table); +} + diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.h b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.h new file mode 100644 index 0000000..92bbe54 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_descriptor_mapping.h + */ + +#ifndef __UMP_KERNEL_DESCRIPTOR_MAPPING_H__ +#define __UMP_KERNEL_DESCRIPTOR_MAPPING_H__ + +#include "mali_osk.h" + +/** + * The actual descriptor mapping table, never directly accessed by clients + */ +typedef struct ump_descriptor_table +{ + u32 * usage; /**< Pointer to bitpattern indicating if a descriptor is valid/used or not */ + void** mappings; /**< Array of the pointers the descriptors map to */ +} ump_descriptor_table; + +/** + * The descriptor mapping object + * Provides a separate namespace where we can map an integer to a pointer + */ +typedef struct ump_descriptor_mapping +{ + _mali_osk_lock_t *lock; /**< Lock protecting access to the mapping object */ + int max_nr_mappings_allowed; /**< Max number of mappings to support in this namespace */ + int current_nr_mappings; /**< Current number of possible mappings */ + ump_descriptor_table * table; /**< Pointer to the current mapping table */ +} ump_descriptor_mapping; + +/** + * Create a descriptor mapping object + * Create a descriptor mapping capable of holding init_entries growable to max_entries + * @param init_entries Number of entries to preallocate memory for + * @param max_entries Number of entries to max support + * @return Pointer to a descriptor mapping object, NULL on failure + */ +ump_descriptor_mapping * ump_descriptor_mapping_create(int init_entries, int max_entries); + +/** + * Destroy a descriptor mapping object + * @param map The map to free + */ +void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map); + +/** + * Allocate a new mapping entry (descriptor ID) + * Allocates a new entry in the map. + * @param map The map to allocate a new entry in + * @param target The value to map to + * @return The descriptor allocated, a negative value on error + */ +int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target); + +/** + * Get the value mapped to by a descriptor ID + * @param map The map to lookup the descriptor id in + * @param descriptor The descriptor ID to lookup + * @param target Pointer to a pointer which will receive the stored value + * @return 0 on successful lookup, negative on error + */ +int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target); + +/** + * Set the value mapped to by a descriptor ID + * @param map The map to lookup the descriptor id in + * @param descriptor The descriptor ID to lookup + * @param target Pointer to replace the current value with + * @return 0 on successful lookup, negative on error + */ +int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target); + +/** + * Free the descriptor ID + * For the descriptor to be reused it has to be freed + * @param map The map to free the descriptor from + * @param descriptor The descriptor ID to free + */ +void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor); + +#endif /* __UMP_KERNEL_DESCRIPTOR_MAPPING_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_memory_backend.h b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_memory_backend.h new file mode 100644 index 0000000..8b11452 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_memory_backend.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_memory_mapping.h + */ + +#ifndef __UMP_KERNEL_MEMORY_BACKEND_H__ +#define __UMP_KERNEL_MEMORY_BACKEND_H__ + +#include "ump_kernel_interface.h" +#include "ump_kernel_types.h" + + +typedef struct ump_memory_allocation +{ + void * phys_addr; + void * mapping; + unsigned long size; + ump_dd_handle handle; + void * process_mapping_info; + u32 cookie; /**< necessary on some U/K interface implementations */ + struct ump_session_data * ump_session; /**< Session that this allocation belongs to */ + _mali_osk_list_t list; /**< List for linking together memory allocations into the session's memory head */ + u32 is_cached; +} ump_memory_allocation; + +typedef struct ump_memory_backend +{ + int (*allocate)(void* ctx, ump_dd_mem * descriptor); + void (*release)(void* ctx, ump_dd_mem * descriptor); + void (*shutdown)(struct ump_memory_backend * backend); + u32 (*stat)(struct ump_memory_backend *backend); + int (*pre_allocate_physical_check)(void *ctx, u32 size); + u32 (*adjust_to_mali_phys)(void *ctx, u32 cpu_phys); + /* MALI_SEC */ + void *(*get)(ump_dd_mem *mem, void *args); + void (*set)(ump_dd_mem *mem, void *args); + void * ctx; +} ump_memory_backend; + +ump_memory_backend * ump_memory_backend_create ( void ); +void ump_memory_backend_destroy( void ); + +#endif /*__UMP_KERNEL_MEMORY_BACKEND_H__ */ + diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_ref_drv.c b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_ref_drv.c new file mode 100644 index 0000000..6335bf6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_ref_drv.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "ump_osk.h" +#include "ump_uk_types.h" + +#include "ump_kernel_interface_ref_drv.h" +#include "ump_kernel_common.h" +#include "ump_kernel_descriptor_mapping.h" + +#define UMP_MINIMUM_SIZE 4096 +#define UMP_MINIMUM_SIZE_MASK (~(UMP_MINIMUM_SIZE-1)) +#define UMP_SIZE_ALIGN(x) (((x)+UMP_MINIMUM_SIZE-1)&UMP_MINIMUM_SIZE_MASK) +#define UMP_ADDR_ALIGN_OFFSET(x) ((x)&(UMP_MINIMUM_SIZE-1)) +static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor); + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks) +{ + ump_dd_mem * mem; + unsigned long size_total = 0; + int map_id; + u32 i; + + /* Go through the input blocks and verify that they are sane */ + for (i=0; i < num_blocks; i++) + { + unsigned long addr = blocks[i].addr; + unsigned long size = blocks[i].size; + + DBG_MSG(5, ("Adding physical memory to new handle. Address: 0x%08lx, size: %lu\n", addr, size)); + size_total += blocks[i].size; + + if (0 != UMP_ADDR_ALIGN_OFFSET(addr)) + { + MSG_ERR(("Trying to create UMP memory from unaligned physical address. Address: 0x%08lx\n", addr)); + return UMP_DD_HANDLE_INVALID; + } + + if (0 != UMP_ADDR_ALIGN_OFFSET(size)) + { + MSG_ERR(("Trying to create UMP memory with unaligned size. Size: %lu\n", size)); + return UMP_DD_HANDLE_INVALID; + } + } + + /* Allocate the ump_dd_mem struct for this allocation */ + mem = _mali_osk_malloc(sizeof(*mem)); + if (NULL == mem) + { + DBG_MSG(1, ("Could not allocate ump_dd_mem in ump_dd_handle_create_from_phys_blocks()\n")); + return UMP_DD_HANDLE_INVALID; + } + + /* Find a secure ID for this allocation */ + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*) mem); + + if (map_id < 0) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_free(mem); + DBG_MSG(1, ("Failed to allocate secure ID in ump_dd_handle_create_from_phys_blocks()\n")); + return UMP_DD_HANDLE_INVALID; + } + + /* Now, make a copy of the block information supplied by the user */ + mem->block_array = _mali_osk_malloc(sizeof(ump_dd_physical_block)* num_blocks); + if (NULL == mem->block_array) + { + ump_descriptor_mapping_free(device.secure_id_map, map_id); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_free(mem); + DBG_MSG(1, ("Could not allocate a mem handle for function ump_dd_handle_create_from_phys_blocks().\n")); + return UMP_DD_HANDLE_INVALID; + } + + _mali_osk_memcpy(mem->block_array, blocks, sizeof(ump_dd_physical_block) * num_blocks); + + /* And setup the rest of the ump_dd_mem struct */ + _mali_osk_atomic_init(&mem->ref_count, 1); + mem->secure_id = (ump_secure_id)map_id; + mem->size_bytes = size_total; + mem->nr_blocks = num_blocks; + mem->backend_info = NULL; + mem->ctx = NULL; + mem->release_func = phys_blocks_release; + /* For now UMP handles created by ump_dd_handle_create_from_phys_blocks() is forced to be Uncached */ + mem->is_cached = 0; + mem->hw_device = _UMP_UK_USED_BY_CPU; + mem->lock_usage = UMP_NOT_LOCKED; + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(3, ("UMP memory created. ID: %u, size: %lu\n", mem->secure_id, mem->size_bytes)); + + return (ump_dd_handle)mem; +} + +static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor) +{ + _mali_osk_free(descriptor->block_array); + descriptor->block_array = NULL; +} + +_mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction ) +{ + ump_session_data * session_data = NULL; + ump_dd_mem *new_allocation = NULL; + ump_session_memory_list_element * session_memory_element = NULL; + int map_id; + + DEBUG_ASSERT_POINTER( user_interaction ); + DEBUG_ASSERT_POINTER( user_interaction->ctx ); + + session_data = (ump_session_data *) user_interaction->ctx; + + session_memory_element = _mali_osk_calloc( 1, sizeof(ump_session_memory_list_element)); + if (NULL == session_memory_element) + { + DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n")); + return _MALI_OSK_ERR_NOMEM; + } + + + new_allocation = _mali_osk_calloc( 1, sizeof(ump_dd_mem)); + if (NULL==new_allocation) + { + _mali_osk_free(session_memory_element); + DBG_MSG(1, ("Failed to allocate ump_dd_mem in _ump_ukk_allocate()\n")); + return _MALI_OSK_ERR_NOMEM; + } + + /* Create a secure ID for this allocation */ + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*)new_allocation); + + if (map_id < 0) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_free(session_memory_element); + _mali_osk_free(new_allocation); + DBG_MSG(1, ("Failed to allocate secure ID in ump_ioctl_allocate()\n")); + return - _MALI_OSK_ERR_INVALID_FUNC; + } + + /* Initialize the part of the new_allocation that we know so for */ + new_allocation->secure_id = (ump_secure_id)map_id; + _mali_osk_atomic_init(&new_allocation->ref_count,1); + if ( 0==(UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE & user_interaction->constraints) ) + new_allocation->is_cached = 0; + else new_allocation->is_cached = 1; + + /* special case a size of 0, we should try to emulate what malloc does in this case, which is to return a valid pointer that must be freed, but can't be dereferences */ + if (0 == user_interaction->size) + { + user_interaction->size = 1; /* emulate by actually allocating the minimum block size */ + } + + new_allocation->size_bytes = UMP_SIZE_ALIGN(user_interaction->size); /* Page align the size */ + new_allocation->lock_usage = UMP_NOT_LOCKED; + + /* Now, ask the active memory backend to do the actual memory allocation */ + if (!device.backend->allocate( device.backend->ctx, new_allocation ) ) + { + DBG_MSG(3, ("OOM: No more UMP memory left. Failed to allocate memory in ump_ioctl_allocate(). Size: %lu, requested size: %lu\n", new_allocation->size_bytes, (unsigned long)user_interaction->size)); + ump_descriptor_mapping_free(device.secure_id_map, map_id); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_free(new_allocation); + _mali_osk_free(session_memory_element); + return _MALI_OSK_ERR_INVALID_FUNC; + } + new_allocation->hw_device = _UMP_UK_USED_BY_CPU; + new_allocation->ctx = device.backend->ctx; + new_allocation->release_func = device.backend->release; + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + /* Initialize the session_memory_element, and add it to the session object */ + session_memory_element->mem = new_allocation; + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_add(&(session_memory_element->list), &(session_data->list_head_session_memory_list)); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + + user_interaction->secure_id = new_allocation->secure_id; + user_interaction->size = new_allocation->size_bytes; + DBG_MSG(3, ("UMP memory allocated. ID: %u, size: %lu\n", new_allocation->secure_id, new_allocation->size_bytes)); + + return _MALI_OSK_ERR_OK; +} + +/* MALI_SEC */ +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args) +{ + ump_dd_mem * mem; + ump_secure_id secure_id; + + DEBUG_ASSERT_POINTER(memh); + + secure_id = ump_dd_secure_id_get(memh); + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + device.backend->set(mem, args); + } + else + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_set(). ID: %u\n", (ump_secure_id)secure_id)); + return UMP_DD_INVALID; + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return UMP_DD_SUCCESS; +} + +UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args) +{ + ump_dd_mem * mem; + void *result; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + result = device.backend->get(mem, args); + } + else + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_get(). ID: %u\n", (ump_secure_id)secure_id)); + return UMP_DD_HANDLE_INVALID; + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return result; +} + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr) +{ + ump_dd_mem * mem; + + DBG_MSG(5, ("Getting handle from Virtual address. vaddr: %u\n", vaddr)); + + _ump_osk_mem_mapregion_get(&mem, vaddr); + + DBG_MSG(1, ("Getting handle's Handle : 0x%8lx\n", mem)); + + return (ump_dd_handle)mem; +} diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_types.h b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_types.h new file mode 100644 index 0000000..19a9755 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_types.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __UMP_KERNEL_TYPES_H__ +#define __UMP_KERNEL_TYPES_H__ + +#include "ump_kernel_interface.h" +#include "mali_osk.h" + + +typedef enum +{ + UMP_USED_BY_CPU = 0, + UMP_USED_BY_MALI = 1, + UMP_USED_BY_UNKNOWN_DEVICE= 100, +} ump_hw_usage; + +typedef enum +{ + UMP_NOT_LOCKED = 0, + UMP_READ = 1, + UMP_READ_WRITE = 3, +} ump_lock_usage; + + +/* + * This struct is what is "behind" a ump_dd_handle + */ +typedef struct ump_dd_mem +{ + ump_secure_id secure_id; + _mali_osk_atomic_t ref_count; + unsigned long size_bytes; + unsigned long nr_blocks; + ump_dd_physical_block * block_array; + void (*release_func)(void * ctx, struct ump_dd_mem * descriptor); + void * ctx; + void * backend_info; + int is_cached; + ump_hw_usage hw_device; + ump_lock_usage lock_usage; +} ump_dd_mem; + + + +#endif /* __UMP_KERNEL_TYPES_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_osk.h b/drivers/gpu/mali400/r3p2/ump/common/ump_osk.h new file mode 100644 index 0000000..d9d182a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_osk.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_osk.h + * Defines the OS abstraction layer for the UMP kernel device driver (OSK) + */ + +#ifndef __UMP_OSK_H__ +#define __UMP_OSK_H__ + +#include +#include +#include "ump_uk_types.h" +#include "ump_kernel_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +_mali_osk_errcode_t _ump_osk_init( void ); + +_mali_osk_errcode_t _ump_osk_term( void ); + +int _ump_osk_atomic_inc_and_read( _mali_osk_atomic_t *atom ); + +int _ump_osk_atomic_dec_and_read( _mali_osk_atomic_t *atom ); + +_mali_osk_errcode_t _ump_osk_mem_mapregion_init( ump_memory_allocation *descriptor ); + +_mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descriptor, u32 offset, u32 * phys_addr, unsigned long size ); + +void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor ); + +void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data ); + +/* MALI_SEC */ +void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_ukk.h b/drivers/gpu/mali400/r3p2/ump/common/ump_ukk.h new file mode 100644 index 0000000..56e4be3 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_ukk.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_ukk.h + * Defines the kernel-side interface of the user-kernel interface + */ + +#ifndef __UMP_UKK_H__ +#define __UMP_UKK_H__ + +#include "mali_osk.h" +#include "ump_uk_types.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +_mali_osk_errcode_t _ump_ukk_open( void** context ); + +_mali_osk_errcode_t _ump_ukk_close( void** context ); + +_mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction ); + +_mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info ); + +_mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction ); + +_mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ); + +_mali_osk_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args ); + +void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args ); + +void _ump_ukk_msync( _ump_uk_msync_s *args ); + +void _ump_ukk_cache_operations_control(_ump_uk_cache_operations_control_s* args); + +void _ump_ukk_switch_hw_usage(_ump_uk_switch_hw_usage_s *args ); + +void _ump_ukk_lock(_ump_uk_lock_s *args ); + +void _ump_ukk_unlock(_ump_uk_unlock_s *args ); + +u32 _ump_ukk_report_memory_usage( void ); + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_UKK_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface.h b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface.h new file mode 100644 index 0000000..042c8b1 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface.h @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_interface.h + * + * This file contains the kernel space part of the UMP API. + */ + +#ifndef __UMP_KERNEL_INTERFACE_H__ +#define __UMP_KERNEL_INTERFACE_H__ + + +/** @defgroup ump_kernel_space_api UMP Kernel Space API + * @{ */ + + +#include "ump_kernel_platform.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** + * External representation of a UMP handle in kernel space. + */ +typedef void * ump_dd_handle; + +/** + * Typedef for a secure ID, a system wide identificator for UMP memory buffers. + */ +typedef unsigned int ump_secure_id; + + +/** + * Value to indicate an invalid UMP memory handle. + */ +#define UMP_DD_HANDLE_INVALID ((ump_dd_handle)0) + + +/** + * Value to indicate an invalid secure Id. + */ +#define UMP_INVALID_SECURE_ID ((ump_secure_id)-1) + + +/** + * UMP error codes for kernel space. + */ +typedef enum +{ + UMP_DD_SUCCESS, /**< indicates success */ + UMP_DD_INVALID, /**< indicates failure */ +} ump_dd_status_code; + + +/** + * Struct used to describe a physical block used by UMP memory + */ +typedef struct ump_dd_physical_block +{ + unsigned long addr; /**< The physical address of the block */ + unsigned long size; /**< The length of the block, typically page aligned */ +} ump_dd_physical_block; + + +/** + * Retrieves the secure ID for the specified UMP memory. + * + * This identificator is unique across the entire system, and uniquely identifies + * the specified UMP memory. This identificator can later be used through the + * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id" or + * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" + * functions in order to access this UMP memory, for instance from another process. + * + * @note There is a user space equivalent function called @ref ump_secure_id_get "ump_secure_id_get" + * + * @see ump_dd_handle_create_from_secure_id + * @see ump_handle_create_from_secure_id + * @see ump_secure_id_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the secure ID for the specified UMP memory. + */ +UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(ump_dd_handle mem); + + +/** + * Retrieves a handle to allocated UMP memory. + * + * The usage of UMP memory is reference counted, so this will increment the reference + * count by one for the specified UMP memory. + * Use @ref ump_dd_reference_release "ump_dd_reference_release" when there is no longer any + * use for the retrieved handle. + * + * @note There is a user space equivalent function called @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" + * + * @see ump_dd_reference_release + * @see ump_handle_create_from_secure_id + * + * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function. + * + * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id); + + +/** + * Retrieves the number of physical blocks used by the specified UMP memory. + * + * This function retrieves the number of @ref ump_dd_physical_block "ump_dd_physical_block" structs needed + * to describe the physical memory layout of the given UMP memory. This can later be used when calling + * the functions @ref ump_dd_phys_blocks_get "ump_dd_phys_blocks_get" and + * @ref ump_dd_phys_block_get "ump_dd_phys_block_get". + * + * @see ump_dd_phys_blocks_get + * @see ump_dd_phys_block_get + * + * @param mem Handle to UMP memory. + * + * @return The number of ump_dd_physical_block structs required to describe the physical memory layout of the specified UMP memory. + */ +UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle mem); + + +/** + * Retrieves all physical memory block information for specified UMP memory. + * + * This function can be used by other device drivers in order to create MMU tables. + * + * @note This function will fail if the num_blocks parameter is either to large or to small. + * + * @see ump_dd_phys_block_get + * + * @param mem Handle to UMP memory. + * @param blocks An array of @ref ump_dd_physical_block "ump_dd_physical_block" structs that will receive the physical description. + * @param num_blocks The number of blocks to return in the blocks array. Use the function + * @ref ump_dd_phys_block_count_get "ump_dd_phys_block_count_get" first to determine the number of blocks required. + * + * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. + */ +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle mem, ump_dd_physical_block * blocks, unsigned long num_blocks); + + +/** + * Retrieves the physical memory block information for specified block for the specified UMP memory. + * + * This function can be used by other device drivers in order to create MMU tables. + * + * @note This function will return UMP_DD_INVALID if the specified index is out of range. + * + * @see ump_dd_phys_blocks_get + * + * @param mem Handle to UMP memory. + * @param index Which physical info block to retrieve. + * @param block Pointer to a @ref ump_dd_physical_block "ump_dd_physical_block" struct which will receive the requested information. + * + * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. + */ +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle mem, unsigned long index, ump_dd_physical_block * block); + + +/** + * Retrieves the actual size of the specified UMP memory. + * + * The size is reported in bytes, and is typically page aligned. + * + * @note There is a user space equivalent function called @ref ump_size_get "ump_size_get" + * + * @see ump_size_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the allocated size of the specified UMP memory, in bytes. + */ +UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle mem); + + +/** + * Adds an extra reference to the specified UMP memory. + * + * This function adds an extra reference to the specified UMP memory. This function should + * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_dd_handle + * variable. The function @ref ump_dd_reference_release "ump_dd_reference_release" must then be used + * to release each copy of the UMP memory handle. + * + * @note You are not required to call @ref ump_dd_reference_add "ump_dd_reference_add" + * for UMP handles returned from + * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id", + * because these handles are already reference counted by this function. + * + * @note There is a user space equivalent function called @ref ump_reference_add "ump_reference_add" + * + * @see ump_reference_add + * + * @param mem Handle to UMP memory. + */ +UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle mem); + + +/** + * Releases a reference from the specified UMP memory. + * + * This function should be called once for every reference to the UMP memory handle. + * When the last reference is released, all resources associated with this UMP memory + * handle are freed. + * + * @note There is a user space equivalent function called @ref ump_reference_release "ump_reference_release" + * + * @see ump_reference_release + * + * @param mem Handle to UMP memory. + */ +UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle mem); + + +#ifdef __cplusplus +} +#endif + + +/** @} */ /* end group ump_kernel_space_api */ + + +#endif /* __UMP_KERNEL_INTERFACE_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface_ref_drv.h b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface_ref_drv.h new file mode 100644 index 0000000..b253de5 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface_ref_drv.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_interface.h + */ + +#ifndef __UMP_KERNEL_INTERFACE_REF_DRV_H__ +#define __UMP_KERNEL_INTERFACE_REF_DRV_H__ + +#include "ump_kernel_interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Turn specified physical memory into UMP memory. */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks); +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id); +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args); +UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args); +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr); + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_KERNEL_INTERFACE_REF_DRV_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_platform.h b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_platform.h new file mode 100644 index 0000000..4349605 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_platform.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_platform.h + * + * This file should define UMP_KERNEL_API_EXPORT, + * which dictates how the UMP kernel API should be exported/imported. + * Modify this file, if needed, to match your platform setup. + */ + +#ifndef __UMP_KERNEL_PLATFORM_H__ +#define __UMP_KERNEL_PLATFORM_H__ + +/** @addtogroup ump_kernel_space_api + * @{ */ + +/** + * A define which controls how UMP kernel space API functions are imported and exported. + * This define should be set by the implementor of the UMP API. + */ + +#if defined(_WIN32) + +#if defined(UMP_BUILDING_UMP_LIBRARY) +#define UMP_KERNEL_API_EXPORT __declspec(dllexport) +#else +#define UMP_KERNEL_API_EXPORT __declspec(dllimport) +#endif + +#else + +#define UMP_KERNEL_API_EXPORT + +#endif + + +/** @} */ /* end group ump_kernel_space_api */ + + +#endif /* __UMP_KERNEL_PLATFORM_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/include/ump_uk_types.h b/drivers/gpu/mali400/r3p2/ump/include/ump_uk_types.h new file mode 100644 index 0000000..2f87272 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/include/ump_uk_types.h @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_uk_types.h + * Defines the types and constants used in the user-kernel interface + */ + +#ifndef __UMP_UK_TYPES_H__ +#define __UMP_UK_TYPES_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Helpers for API version handling */ +#define MAKE_VERSION_ID(x) (((x) << 16UL) | (x)) +#define IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF)) +#define GET_VERSION(x) (((x) >> 16UL) & 0xFFFF) +#define IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y)))) + +/** + * API version define. + * Indicates the version of the kernel API + * The version is a 16bit integer incremented on each API change. + * The 16bit integer is stored twice in a 32bit integer + * So for version 1 the value would be 0x00010001 + */ +#define UMP_IOCTL_API_VERSION MAKE_VERSION_ID(2) + +typedef enum +{ + _UMP_IOC_QUERY_API_VERSION = 1, + _UMP_IOC_ALLOCATE, + _UMP_IOC_RELEASE, + _UMP_IOC_SIZE_GET, + _UMP_IOC_MAP_MEM, /* not used in Linux */ + _UMP_IOC_UNMAP_MEM, /* not used in Linux */ + _UMP_IOC_MSYNC, + _UMP_IOC_CACHE_OPERATIONS_CONTROL, + _UMP_IOC_SWITCH_HW_USAGE, + _UMP_IOC_LOCK, + _UMP_IOC_UNLOCK, + _UMP_IOC_ION_IMPORT, +}_ump_uk_functions; + +typedef enum +{ + UMP_REF_DRV_UK_CONSTRAINT_NONE = 0, + UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR = 1, + UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE = 128, +} ump_uk_alloc_constraints; + +typedef enum +{ + _UMP_UK_MSYNC_CLEAN = 0, + _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE = 1, + _UMP_UK_MSYNC_INVALIDATE = 2, + _UMP_UK_MSYNC_FLUSH_L1 = 3, + _UMP_UK_MSYNC_READOUT_CACHE_ENABLED = 128, +} ump_uk_msync_op; + +typedef enum +{ + _UMP_UK_CACHE_OP_START = 0, + _UMP_UK_CACHE_OP_FINISH = 1, +} ump_uk_cache_op_control; + +typedef enum +{ + _UMP_UK_READ = 1, + _UMP_UK_READ_WRITE = 3, +} ump_uk_lock_usage; + +typedef enum +{ + _UMP_UK_USED_BY_CPU = 0, + _UMP_UK_USED_BY_MALI = 1, + _UMP_UK_USED_BY_UNKNOWN_DEVICE= 100, +} ump_uk_user; + +/** + * Get API version ([in,out] u32 api_version, [out] u32 compatible) + */ +typedef struct _ump_uk_api_version_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 version; /**< Set to the user space version on entry, stores the device driver version on exit */ + u32 compatible; /**< Non-null if the device is compatible with the client */ +} _ump_uk_api_version_s; + +/** + * ALLOCATE ([out] u32 secure_id, [in,out] u32 size, [in] contraints) + */ +typedef struct _ump_uk_allocate_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< Return value from DD to Userdriver */ + u32 size; /**< Input and output. Requested size; input. Returned size; output */ + ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ +} _ump_uk_allocate_s; + +typedef struct _ump_uk_ion_import_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + int ion_fd; /**< ion_fd */ + u32 secure_id; /**< Return value from DD to Userdriver */ + u32 size; /**< Input and output. Requested size; input. Returned size; output */ + ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ +} _ump_uk_ion_import_s; + +/** + * SIZE_GET ([in] u32 secure_id, [out]size ) + */ +typedef struct _ump_uk_size_get_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< Input to DD */ + u32 size; /**< Returned size; output */ +} _ump_uk_size_get_s; + +/** + * Release ([in] u32 secure_id) + */ +typedef struct _ump_uk_release_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< Input to DD */ +} _ump_uk_release_s; + +typedef struct _ump_uk_map_mem_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *mapping; /**< [out] Returns user-space virtual address for the mapping */ + void *phys_addr; /**< [in] physical address */ + unsigned long size; /**< [in] size */ + u32 secure_id; /**< [in] secure_id to assign to mapping */ + void * _ukk_private; /**< Only used inside linux port between kernel frontend and common part to store vma */ + u32 cookie; + u32 is_cached; /**< [in,out] caching of CPU mappings */ +} _ump_uk_map_mem_s; + +typedef struct _ump_uk_unmap_mem_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *mapping; + u32 size; + void * _ukk_private; + u32 cookie; +} _ump_uk_unmap_mem_s; + +typedef struct _ump_uk_msync_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *mapping; /**< [in] mapping addr */ + void *address; /**< [in] flush start addr */ + u32 size; /**< [in] size to flush */ + ump_uk_msync_op op; /**< [in] flush operation */ + u32 cookie; /**< [in] cookie stored with reference to the kernel mapping internals */ + u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ + u32 is_cached; /**< [out] caching of CPU mappings */ +} _ump_uk_msync_s; + +typedef struct _ump_uk_cache_operations_control_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + ump_uk_cache_op_control op; /**< [in] cache operations start/stop */ +} _ump_uk_cache_operations_control_s; + + +typedef struct _ump_uk_switch_hw_usage_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ + ump_uk_user new_user; /**< [in] cookie stored with reference to the kernel mapping internals */ + +} _ump_uk_switch_hw_usage_s; + +typedef struct _ump_uk_lock_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ + ump_uk_lock_usage lock_usage; +} _ump_uk_lock_s; + +typedef struct _ump_uk_unlock_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ +} _ump_uk_unlock_s; + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_UK_TYPES_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/linux/license/gpl/ump_kernel_license.h b/drivers/gpu/mali400/r3p2/ump/linux/license/gpl/ump_kernel_license.h new file mode 100644 index 0000000..187e33b --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/license/gpl/ump_kernel_license.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_license.h + * Defines for the macro MODULE_LICENSE. + */ + +#ifndef __UMP_KERNEL_LICENSE_H__ +#define __UMP_KERNEL_LICENSE_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define UMP_KERNEL_LINUX_LICENSE "GPL" +#define UMP_LICENSE_IS_GPL 1 + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_KERNEL_LICENSE_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_ioctl.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_ioctl.h new file mode 100644 index 0000000..dcc343a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_ioctl.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __UMP_IOCTL_H__ +#define __UMP_IOCTL_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#include + +#ifndef __user +#define __user +#endif + + +/** + * @file UMP_ioctl.h + * This file describes the interface needed to use the Linux device driver. + * The interface is used by the userpace UMP driver. + */ + +#define UMP_IOCTL_NR 0x90 + + +#define UMP_IOC_QUERY_API_VERSION _IOR(UMP_IOCTL_NR, _UMP_IOC_QUERY_API_VERSION, _ump_uk_api_version_s) +#define UMP_IOC_ALLOCATE _IOWR(UMP_IOCTL_NR, _UMP_IOC_ALLOCATE, _ump_uk_allocate_s) +#define UMP_IOC_RELEASE _IOR(UMP_IOCTL_NR, _UMP_IOC_RELEASE, _ump_uk_release_s) +#define UMP_IOC_SIZE_GET _IOWR(UMP_IOCTL_NR, _UMP_IOC_SIZE_GET, _ump_uk_size_get_s) +#define UMP_IOC_MSYNC _IOW(UMP_IOCTL_NR, _UMP_IOC_MSYNC, _ump_uk_msync_s) +/* MALI_SEC */ +#define UMP_IOC_ION_IMPORT _IOW(UMP_IOCTL_NR, _UMP_IOC_ION_IMPORT, _ump_uk_ion_import_s) +/* MALI_SEC */ +#define UMP_IOC_DMABUF_IMPORT _IOW(UMP_IOCTL_NR, _UMP_IOC_DMABUF_IMPORT,\ + struct ump_uk_dmabuf) + +#define UMP_IOC_CACHE_OPERATIONS_CONTROL _IOW(UMP_IOCTL_NR, _UMP_IOC_CACHE_OPERATIONS_CONTROL, _ump_uk_cache_operations_control_s) +#define UMP_IOC_SWITCH_HW_USAGE _IOW(UMP_IOCTL_NR, _UMP_IOC_SWITCH_HW_USAGE, _ump_uk_switch_hw_usage_s) +#define UMP_IOC_LOCK _IOW(UMP_IOCTL_NR, _UMP_IOC_LOCK, _ump_uk_lock_s) +#define UMP_IOC_UNLOCK _IOW(UMP_IOCTL_NR, _UMP_IOC_UNLOCK, _ump_uk_unlock_s) + + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_IOCTL_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.c new file mode 100644 index 0000000..b509f43 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.c @@ -0,0 +1,500 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include /* kernel module definitions */ +#include /* file system operations */ +#include /* character device definitions */ +#include /* request_mem_region */ +#include /* memory management functions and types */ +#include /* user space access */ +#include +#include +#include + +#include "arch/config.h" /* Configuration for current platform. The symlinc for arch is set by Makefile */ +#include "ump_ioctl.h" +#include "ump_kernel_common.h" +#include "ump_kernel_interface.h" +#include "ump_kernel_interface_ref_drv.h" +#include "ump_kernel_descriptor_mapping.h" +#include "ump_kernel_memory_backend.h" +#include "ump_kernel_memory_backend_os.h" +#include "ump_kernel_memory_backend_dedicated.h" +#include "ump_kernel_license.h" + +#include "ump_osk.h" +#include "ump_ukk.h" +#include "ump_uk_types.h" +#include "ump_ukk_wrappers.h" +#include "ump_ukk_ref_wrappers.h" + +/* MALI_SEC */ +#ifdef CONFIG_ION_EXYNOS +#include +extern struct ion_device *ion_exynos; +struct ion_client *ion_client_ump = NULL; +#endif + +/* MALI_SEC */ +#if defined(CONFIG_MALI400) +extern int map_errcode( _mali_osk_errcode_t err ); +#endif + +/* Module parameter to control log level */ +int ump_debug_level = 2; +module_param(ump_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(ump_debug_level, "Higher number, more dmesg output"); + +/* By default the module uses any available major, but it's possible to set it at load time to a specific number */ +int ump_major = 0; +module_param(ump_major, int, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_major, "Device major number"); + +/* Name of the UMP device driver */ +static char ump_dev_name[] = "ump"; /* should be const, but the functions we call requires non-cost */ + + +#if UMP_LICENSE_IS_GPL +static struct dentry *ump_debugfs_dir = NULL; +#endif + +/* + * The data which we attached to each virtual memory mapping request we get. + * Each memory mapping has a reference to the UMP memory it maps. + * We release this reference when the last memory mapping is unmapped. + */ +typedef struct ump_vma_usage_tracker +{ + int references; + ump_dd_handle handle; +} ump_vma_usage_tracker; + +struct ump_device +{ + struct cdev cdev; +#if UMP_LICENSE_IS_GPL + struct class * ump_class; +#endif +}; + +/* The global variable containing the global device data */ +static struct ump_device ump_device; + + +/* Forward declare static functions */ +static int ump_file_open(struct inode *inode, struct file *filp); +static int ump_file_release(struct inode *inode, struct file *filp); +#ifdef HAVE_UNLOCKED_IOCTL +static long ump_file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#endif +static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma); + + +/* This variable defines the file operations this UMP device driver offer */ +static struct file_operations ump_fops = +{ + .owner = THIS_MODULE, + .open = ump_file_open, + .release = ump_file_release, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = ump_file_ioctl, +#else + .ioctl = ump_file_ioctl, +#endif + .mmap = ump_file_mmap +}; + + +/* This function is called by Linux to initialize this module. + * All we do is initialize the UMP device driver. + */ +static int ump_initialize_module(void) +{ + _mali_osk_errcode_t err; + + DBG_MSG(2, ("Inserting UMP device driver. Compiled: %s, time: %s\n", __DATE__, __TIME__)); + + err = ump_kernel_constructor(); + if (_MALI_OSK_ERR_OK != err) + { + MSG_ERR(("UMP device driver init failed\n")); + return map_errcode(err); + } + + MSG(("UMP device driver %s loaded\n", SVN_REV_STRING)); + return 0; +} + + + +/* + * This function is called by Linux to unload/terminate/exit/cleanup this module. + * All we do is terminate the UMP device driver. + */ +static void ump_cleanup_module(void) +{ +/* MALI_SEC */ +#ifdef CONFIG_ION_EXYNOS + if (ion_client_ump) + ion_client_destroy(ion_client_ump); +#endif + + DBG_MSG(2, ("Unloading UMP device driver\n")); + ump_kernel_destructor(); + DBG_MSG(2, ("Module unloaded\n")); +} + + + +static ssize_t ump_memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 mem = _ump_ukk_report_memory_usage(); + + r = snprintf(buf, 64, "%u\n", mem); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static const struct file_operations ump_memory_usage_fops = { + .owner = THIS_MODULE, + .read = ump_memory_used_read, +}; + +/* + * Initialize the UMP device driver. + */ +int ump_kernel_device_initialize(void) +{ + int err; + dev_t dev = 0; +#if UMP_LICENSE_IS_GPL + ump_debugfs_dir = debugfs_create_dir(ump_dev_name, NULL); + if (ERR_PTR(-ENODEV) == ump_debugfs_dir) + { + ump_debugfs_dir = NULL; + } + else + { + debugfs_create_file("memory_usage", 0400, ump_debugfs_dir, NULL, &ump_memory_usage_fops); + } +#endif + + if (0 == ump_major) + { + /* auto select a major */ + err = alloc_chrdev_region(&dev, 0, 1, ump_dev_name); + ump_major = MAJOR(dev); + } + else + { + /* use load time defined major number */ + dev = MKDEV(ump_major, 0); + err = register_chrdev_region(dev, 1, ump_dev_name); + } + + if (0 == err) + { + memset(&ump_device, 0, sizeof(ump_device)); + + /* initialize our char dev data */ + cdev_init(&ump_device.cdev, &ump_fops); + ump_device.cdev.owner = THIS_MODULE; + ump_device.cdev.ops = &ump_fops; + + /* register char dev with the kernel */ + err = cdev_add(&ump_device.cdev, dev, 1/*count*/); + if (0 == err) + { + +#if UMP_LICENSE_IS_GPL + ump_device.ump_class = class_create(THIS_MODULE, ump_dev_name); + if (IS_ERR(ump_device.ump_class)) + { + err = PTR_ERR(ump_device.ump_class); + } + else + { + struct device * mdev; + mdev = device_create(ump_device.ump_class, NULL, dev, NULL, ump_dev_name); + if (!IS_ERR(mdev)) + { + return 0; + } + + err = PTR_ERR(mdev); + } + cdev_del(&ump_device.cdev); +#else + return 0; +#endif + } + + unregister_chrdev_region(dev, 1); + } + + return err; +} + + + +/* + * Terminate the UMP device driver + */ +void ump_kernel_device_terminate(void) +{ + dev_t dev = MKDEV(ump_major, 0); + +#if UMP_LICENSE_IS_GPL + device_destroy(ump_device.ump_class, dev); + class_destroy(ump_device.ump_class); +#endif + + /* unregister char device */ + cdev_del(&ump_device.cdev); + + /* free major */ + unregister_chrdev_region(dev, 1); + +#if UMP_LICENSE_IS_GPL + if(ump_debugfs_dir) + debugfs_remove_recursive(ump_debugfs_dir); +#endif +} + +/* + * Open a new session. User space has called open() on us. + */ +static int ump_file_open(struct inode *inode, struct file *filp) +{ + struct ump_session_data * session_data; + _mali_osk_errcode_t err; + + /* input validation */ + if (0 != MINOR(inode->i_rdev)) + { + MSG_ERR(("Minor not zero in ump_file_open()\n")); + return -ENODEV; + } + + /* Call the OS-Independent UMP Open function */ + err = _ump_ukk_open((void**) &session_data ); + if( _MALI_OSK_ERR_OK != err ) + { + MSG_ERR(("Ump failed to open a new session\n")); + return map_errcode( err ); + } + + filp->private_data = (void*)session_data; + filp->f_pos = 0; + + return 0; /* success */ +} + + + +/* + * Close a session. User space has called close() or crashed/terminated. + */ +static int ump_file_release(struct inode *inode, struct file *filp) +{ + _mali_osk_errcode_t err; + + err = _ump_ukk_close((void**) &filp->private_data ); + if( _MALI_OSK_ERR_OK != err ) + { + return map_errcode( err ); + } + + return 0; /* success */ +} + + + +/* + * Handle IOCTL requests. + */ +#ifdef HAVE_UNLOCKED_IOCTL +static long ump_file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +#else +static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +#endif +{ + int err = -ENOTTY; + void __user * argument; + struct ump_session_data * session_data; + +#ifndef HAVE_UNLOCKED_IOCTL + (void)inode; /* inode not used */ +#endif + + session_data = (struct ump_session_data *)filp->private_data; + if (NULL == session_data) + { + MSG_ERR(("No session data attached to file object\n")); + return -ENOTTY; + } + + /* interpret the argument as a user pointer to something */ + argument = (void __user *)arg; + + switch (cmd) + { + case UMP_IOC_QUERY_API_VERSION: + err = ump_get_api_version_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_ALLOCATE : + err = ump_allocate_wrapper((u32 __user *)argument, session_data); + break; +/* MALI_SEC */ +#ifdef CONFIG_ION_EXYNOS + case UMP_IOC_ION_IMPORT: + err = ump_ion_import_wrapper((u32 __user *)argument, session_data); + break; +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER + case UMP_IOC_DMABUF_IMPORT: + err = ump_dmabuf_import_wrapper((u32 __user *)argument, + session_data); + break; +#endif + case UMP_IOC_RELEASE: + err = ump_release_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_SIZE_GET: + err = ump_size_get_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_MSYNC: + err = ump_msync_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_CACHE_OPERATIONS_CONTROL: + err = ump_cache_operations_control_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_SWITCH_HW_USAGE: + err = ump_switch_hw_usage_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_LOCK: + err = ump_lock_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_UNLOCK: + err = ump_unlock_wrapper((u32 __user *)argument, session_data); + break; + + default: + DBG_MSG(1, ("No handler for IOCTL. cmd: 0x%08x, arg: 0x%08lx\n", cmd, arg)); + err = -EFAULT; + break; + } + + return err; +} + +/* MALI_SEC */ +#if !defined(CONFIG_MALI400) +int map_errcode( _mali_osk_errcode_t err ) +{ + switch(err) + { + case _MALI_OSK_ERR_OK : return 0; + case _MALI_OSK_ERR_FAULT: return -EFAULT; + case _MALI_OSK_ERR_INVALID_FUNC: return -ENOTTY; + case _MALI_OSK_ERR_INVALID_ARGS: return -EINVAL; + case _MALI_OSK_ERR_NOMEM: return -ENOMEM; + case _MALI_OSK_ERR_TIMEOUT: return -ETIMEDOUT; + case _MALI_OSK_ERR_RESTARTSYSCALL: return -ERESTARTSYS; + case _MALI_OSK_ERR_ITEM_NOT_FOUND: return -ENOENT; + default: return -EFAULT; + } +} +#endif + +/* + * Handle from OS to map specified virtual memory to specified UMP memory. + */ +static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma) +{ + _ump_uk_map_mem_s args; + _mali_osk_errcode_t err; + struct ump_session_data * session_data; + + /* Validate the session data */ + session_data = (struct ump_session_data *)filp->private_data; + /* MALI_SEC */ + // original : if (NULL == session_data) + if (NULL == session_data || NULL == session_data->cookies_map->table->mappings) + { + MSG_ERR(("mmap() called without any session data available\n")); + return -EFAULT; + } + + /* Re-pack the arguments that mmap() packed for us */ + args.ctx = session_data; + args.phys_addr = 0; + args.size = vma->vm_end - vma->vm_start; + args._ukk_private = vma; + args.secure_id = vma->vm_pgoff; + args.is_cached = 0; + + if (!(vma->vm_flags & VM_SHARED)) + { + args.is_cached = 1; + vma->vm_flags = vma->vm_flags | VM_SHARED | VM_MAYSHARE ; + DBG_MSG(3, ("UMP Map function: Forcing the CPU to use cache\n")); + } + /* By setting this flag, during a process fork; the child process will not have the parent UMP mappings */ + vma->vm_flags |= VM_DONTCOPY; + + DBG_MSG(4, ("UMP vma->flags: %x\n", vma->vm_flags )); + + /* Call the common mmap handler */ + err = _ump_ukk_map_mem( &args ); + if ( _MALI_OSK_ERR_OK != err) + { + MSG_ERR(("_ump_ukk_map_mem() failed in function ump_file_mmap()")); + return map_errcode( err ); + } + + return 0; /* success */ +} + +/* Export UMP kernel space API functions */ +EXPORT_SYMBOL(ump_dd_secure_id_get); +EXPORT_SYMBOL(ump_dd_handle_create_from_secure_id); +EXPORT_SYMBOL(ump_dd_phys_block_count_get); +EXPORT_SYMBOL(ump_dd_phys_block_get); +EXPORT_SYMBOL(ump_dd_phys_blocks_get); +EXPORT_SYMBOL(ump_dd_size_get); +EXPORT_SYMBOL(ump_dd_reference_add); +EXPORT_SYMBOL(ump_dd_reference_release); +/* MALI_SEC */ +EXPORT_SYMBOL(ump_dd_meminfo_get); +EXPORT_SYMBOL(ump_dd_meminfo_set); +EXPORT_SYMBOL(ump_dd_handle_get_from_vaddr); + +/* Export our own extended kernel space allocator */ +EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks); + +/* Setup init and exit functions for this module */ +module_init(ump_initialize_module); +module_exit(ump_cleanup_module); + +/* And some module informatio */ +MODULE_LICENSE(UMP_KERNEL_LINUX_LICENSE); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION(SVN_REV_STRING); diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.h new file mode 100644 index 0000000..4985bb7 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __UMP_KERNEL_LINUX_H__ +#define __UMP_KERNEL_LINUX_H__ + +int ump_kernel_device_initialize(void); +void ump_kernel_device_terminate(void); + + +#endif /* __UMP_KERNEL_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.c new file mode 100644 index 0000000..f42a320 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.c @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* needed to detect kernel version specific code */ +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else /* pre 2.6.26 the file was in the arch specific location */ +#include +#endif + +#include +#include +#include +#include +#include "ump_kernel_common.h" +#include "ump_kernel_memory_backend.h" + + + +#define UMP_BLOCK_SIZE (256UL * 1024UL) /* 256kB, remember to keep the ()s */ + + + +typedef struct block_info +{ + struct block_info * next; +} block_info; + + + +typedef struct block_allocator +{ + struct semaphore mutex; + block_info * all_blocks; + block_info * first_free; + u32 base; + u32 num_blocks; + u32 num_free; +} block_allocator; + + +static void block_allocator_shutdown(ump_memory_backend * backend); +static int block_allocator_allocate(void* ctx, ump_dd_mem * mem); +static void block_allocator_release(void * ctx, ump_dd_mem * handle); +static inline u32 get_phys(block_allocator * allocator, block_info * block); +static u32 block_allocator_stat(struct ump_memory_backend *backend); + + + +/* + * Create dedicated memory backend + */ +ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size) +{ + ump_memory_backend * backend; + block_allocator * allocator; + u32 usable_size; + u32 num_blocks; + + usable_size = (size + UMP_BLOCK_SIZE - 1) & ~(UMP_BLOCK_SIZE - 1); + num_blocks = usable_size / UMP_BLOCK_SIZE; + + if (0 == usable_size) + { + DBG_MSG(1, ("Memory block of size %u is unusable\n", size)); + return NULL; + } + + DBG_MSG(5, ("Creating dedicated UMP memory backend. Base address: 0x%08x, size: 0x%08x\n", base_address, size)); + DBG_MSG(6, ("%u usable bytes which becomes %u blocks\n", usable_size, num_blocks)); + + backend = kzalloc(sizeof(ump_memory_backend), GFP_KERNEL); + if (NULL != backend) + { + allocator = kmalloc(sizeof(block_allocator), GFP_KERNEL); + if (NULL != allocator) + { + allocator->all_blocks = kmalloc(sizeof(block_allocator) * num_blocks, GFP_KERNEL); + if (NULL != allocator->all_blocks) + { + int i; + + allocator->first_free = NULL; + allocator->num_blocks = num_blocks; + allocator->num_free = num_blocks; + allocator->base = base_address; + sema_init(&allocator->mutex, 1); + + for (i = 0; i < num_blocks; i++) + { + allocator->all_blocks[i].next = allocator->first_free; + allocator->first_free = &allocator->all_blocks[i]; + } + + backend->ctx = allocator; + backend->allocate = block_allocator_allocate; + backend->release = block_allocator_release; + backend->shutdown = block_allocator_shutdown; + backend->stat = block_allocator_stat; + backend->pre_allocate_physical_check = NULL; + backend->adjust_to_mali_phys = NULL; + /* MALI_SEC */ + backend->get = NULL; + backend->set = NULL; + + return backend; + } + kfree(allocator); + } + kfree(backend); + } + + return NULL; +} + + + +/* + * Destroy specified dedicated memory backend + */ +static void block_allocator_shutdown(ump_memory_backend * backend) +{ + block_allocator * allocator; + + BUG_ON(!backend); + BUG_ON(!backend->ctx); + + allocator = (block_allocator*)backend->ctx; + + DBG_MSG_IF(1, allocator->num_free != allocator->num_blocks, ("%u blocks still in use during shutdown\n", allocator->num_blocks - allocator->num_free)); + + kfree(allocator->all_blocks); + kfree(allocator); + kfree(backend); +} + + + +static int block_allocator_allocate(void* ctx, ump_dd_mem * mem) +{ + block_allocator * allocator; + u32 left; + block_info * last_allocated = NULL; + int i = 0; + + BUG_ON(!ctx); + BUG_ON(!mem); + + allocator = (block_allocator*)ctx; + left = mem->size_bytes; + + BUG_ON(!left); + BUG_ON(!&allocator->mutex); + + mem->nr_blocks = ((left + UMP_BLOCK_SIZE - 1) & ~(UMP_BLOCK_SIZE - 1)) / UMP_BLOCK_SIZE; + mem->block_array = (ump_dd_physical_block*)vmalloc(sizeof(ump_dd_physical_block) * mem->nr_blocks); + if (NULL == mem->block_array) + { + MSG_ERR(("Failed to allocate block array\n")); + return 0; + } + + if (down_interruptible(&allocator->mutex)) + { + MSG_ERR(("Could not get mutex to do block_allocate\n")); + return 0; + } + + mem->size_bytes = 0; + + while ((left > 0) && (allocator->first_free)) + { + block_info * block; + + block = allocator->first_free; + allocator->first_free = allocator->first_free->next; + block->next = last_allocated; + last_allocated = block; + allocator->num_free--; + + mem->block_array[i].addr = get_phys(allocator, block); + mem->block_array[i].size = UMP_BLOCK_SIZE; + mem->size_bytes += UMP_BLOCK_SIZE; + + i++; + + if (left < UMP_BLOCK_SIZE) left = 0; + else left -= UMP_BLOCK_SIZE; + } + + if (left) + { + block_info * block; + /* release all memory back to the pool */ + while (last_allocated) + { + block = last_allocated->next; + last_allocated->next = allocator->first_free; + allocator->first_free = last_allocated; + last_allocated = block; + allocator->num_free++; + } + + vfree(mem->block_array); + mem->backend_info = NULL; + mem->block_array = NULL; + + DBG_MSG(4, ("Could not find a mem-block for the allocation.\n")); + up(&allocator->mutex); + + return 0; + } + + mem->backend_info = last_allocated; + + up(&allocator->mutex); + mem->is_cached=0; + + return 1; +} + + + +static void block_allocator_release(void * ctx, ump_dd_mem * handle) +{ + block_allocator * allocator; + block_info * block, * next; + + BUG_ON(!ctx); + BUG_ON(!handle); + + allocator = (block_allocator*)ctx; + block = (block_info*)handle->backend_info; + BUG_ON(!block); + + if (down_interruptible(&allocator->mutex)) + { + MSG_ERR(("Allocator release: Failed to get mutex - memory leak\n")); + return; + } + + while (block) + { + next = block->next; + + BUG_ON( (block < allocator->all_blocks) || (block > (allocator->all_blocks + allocator->num_blocks))); + + block->next = allocator->first_free; + allocator->first_free = block; + allocator->num_free++; + + block = next; + } + DBG_MSG(3, ("%d blocks free after release call\n", allocator->num_free)); + up(&allocator->mutex); + + vfree(handle->block_array); + handle->block_array = NULL; +} + + + +/* + * Helper function for calculating the physical base adderss of a memory block + */ +static inline u32 get_phys(block_allocator * allocator, block_info * block) +{ + return allocator->base + ((block - allocator->all_blocks) * UMP_BLOCK_SIZE); +} + +static u32 block_allocator_stat(struct ump_memory_backend *backend) +{ + block_allocator *allocator; + BUG_ON(!backend); + allocator = (block_allocator*)backend->ctx; + BUG_ON(!allocator); + + return (allocator->num_blocks - allocator->num_free)* UMP_BLOCK_SIZE; +} diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.h new file mode 100644 index 0000000..fa4bdcc --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_memory_backend_dedicated.h + */ + +#ifndef __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ +#define __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ + +#include "ump_kernel_memory_backend.h" + +ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size); + +#endif /* __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ */ + diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c new file mode 100644 index 0000000..0cee2c8 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* needed to detect kernel version specific code */ +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else /* pre 2.6.26 the file was in the arch specific location */ +#include +#endif + +#include +#include +#include +#include +#include +#include +#include "ump_kernel_common.h" +#include "ump_kernel_memory_backend.h" + + + +typedef struct os_allocator +{ + struct semaphore mutex; + u32 num_pages_max; /**< Maximum number of pages to allocate from the OS */ + u32 num_pages_allocated; /**< Number of pages allocated from the OS */ +} os_allocator; + + + +static void os_free(void* ctx, ump_dd_mem * descriptor); +static int os_allocate(void* ctx, ump_dd_mem * descriptor); +static void os_memory_backend_destroy(ump_memory_backend * backend); +static u32 os_stat(struct ump_memory_backend *backend); + + + +/* + * Create OS memory backend + */ +ump_memory_backend * ump_os_memory_backend_create(const int max_allocation) +{ + ump_memory_backend * backend; + os_allocator * info; + + info = kmalloc(sizeof(os_allocator), GFP_KERNEL); + if (NULL == info) + { + return NULL; + } + + info->num_pages_max = max_allocation >> PAGE_SHIFT; + info->num_pages_allocated = 0; + + sema_init(&info->mutex, 1); + + backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL); + if (NULL == backend) + { + kfree(info); + return NULL; + } + + backend->ctx = info; + backend->allocate = os_allocate; + backend->release = os_free; + backend->shutdown = os_memory_backend_destroy; + backend->stat = os_stat; + backend->pre_allocate_physical_check = NULL; + backend->adjust_to_mali_phys = NULL; + /* MALI_SEC */ + backend->get = NULL; + backend->set = NULL; + + return backend; +} + + + +/* + * Destroy specified OS memory backend + */ +static void os_memory_backend_destroy(ump_memory_backend * backend) +{ + os_allocator * info = (os_allocator*)backend->ctx; + + DBG_MSG_IF(1, 0 != info->num_pages_allocated, ("%d pages still in use during shutdown\n", info->num_pages_allocated)); + + kfree(info); + kfree(backend); +} + + + +/* + * Allocate UMP memory + */ +static int os_allocate(void* ctx, ump_dd_mem * descriptor) +{ + u32 left; + os_allocator * info; + int pages_allocated = 0; + int is_cached; + + BUG_ON(!descriptor); + BUG_ON(!ctx); + + info = (os_allocator*)ctx; + left = descriptor->size_bytes; + is_cached = descriptor->is_cached; + + if (down_interruptible(&info->mutex)) + { + DBG_MSG(1, ("Failed to get mutex in os_free\n")); + return 0; /* failure */ + } + + descriptor->backend_info = NULL; + descriptor->nr_blocks = ((left + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) >> PAGE_SHIFT; + + DBG_MSG(5, ("Allocating page array. Size: %lu\n", descriptor->nr_blocks * sizeof(ump_dd_physical_block))); + + descriptor->block_array = (ump_dd_physical_block *)vmalloc(sizeof(ump_dd_physical_block) * descriptor->nr_blocks); + if (NULL == descriptor->block_array) + { + up(&info->mutex); + DBG_MSG(1, ("Block array could not be allocated\n")); + return 0; /* failure */ + } + + while (left > 0 && ((info->num_pages_allocated + pages_allocated) < info->num_pages_max)) + { + struct page * new_page; + + if (is_cached) + { + new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN); + } else + { + new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD); + } + if (NULL == new_page) + { + /* MALI_SEC */ + DBG_MSG(1, ("UMP memory allocated: Out of Memory !!\n")); + break; + } + + /* Ensure page caches are flushed. */ + if ( is_cached ) + { + descriptor->block_array[pages_allocated].addr = page_to_phys(new_page); + descriptor->block_array[pages_allocated].size = PAGE_SIZE; + } else + { + descriptor->block_array[pages_allocated].addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL ); + descriptor->block_array[pages_allocated].size = PAGE_SIZE; + } + + DBG_MSG(5, ("Allocated page 0x%08lx cached: %d\n", descriptor->block_array[pages_allocated].addr, is_cached)); + + if (left < PAGE_SIZE) + { + left = 0; + } + else + { + left -= PAGE_SIZE; + } + + pages_allocated++; + } + + DBG_MSG(5, ("Alloce for ID:%2d got %d pages, cached: %d\n", descriptor->secure_id, pages_allocated)); + + if (left) + { + DBG_MSG(1, ("Failed to allocate needed pages\n")); + /* MALI_SEC */ + DBG_MSG(1, ("UMP memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", + (pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); + + while(pages_allocated) + { + pages_allocated--; + if ( !is_cached ) + { + dma_unmap_page(NULL, descriptor->block_array[pages_allocated].addr, PAGE_SIZE, DMA_BIDIRECTIONAL); + } + __free_page(pfn_to_page(descriptor->block_array[pages_allocated].addr >> PAGE_SHIFT) ); + } + + up(&info->mutex); + + return 0; /* failure */ + } + + info->num_pages_allocated += pages_allocated; + + DBG_MSG(6, ("%d out of %d pages now allocated\n", info->num_pages_allocated, info->num_pages_max)); + + up(&info->mutex); + + return 1; /* success*/ +} + + +/* + * Free specified UMP memory + */ +static void os_free(void* ctx, ump_dd_mem * descriptor) +{ + os_allocator * info; + int i; + + BUG_ON(!ctx); + BUG_ON(!descriptor); + + info = (os_allocator*)ctx; + + BUG_ON(descriptor->nr_blocks > info->num_pages_allocated); + + if (down_interruptible(&info->mutex)) + { + DBG_MSG(1, ("Failed to get mutex in os_free\n")); + return; + } + + DBG_MSG(5, ("Releasing %lu OS pages\n", descriptor->nr_blocks)); + + info->num_pages_allocated -= descriptor->nr_blocks; + + up(&info->mutex); + + for ( i = 0; i < descriptor->nr_blocks; i++) + { + DBG_MSG(6, ("Freeing physical page. Address: 0x%08lx\n", descriptor->block_array[i].addr)); + if ( ! descriptor->is_cached) + { + dma_unmap_page(NULL, descriptor->block_array[i].addr, PAGE_SIZE, DMA_BIDIRECTIONAL); + } + __free_page(pfn_to_page(descriptor->block_array[i].addr>>PAGE_SHIFT) ); + } + + vfree(descriptor->block_array); +} + + +static u32 os_stat(struct ump_memory_backend *backend) +{ + os_allocator *info; + info = (os_allocator*)backend->ctx; + return info->num_pages_allocated * _MALI_OSK_MALI_PAGE_SIZE; +} diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.h new file mode 100644 index 0000000..f924705 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_memory_backend_os.h + */ + +#ifndef __UMP_KERNEL_MEMORY_BACKEND_OS_H__ +#define __UMP_KERNEL_MEMORY_BACKEND_OS_H__ + +#include "ump_kernel_memory_backend.h" + +ump_memory_backend * ump_os_memory_backend_create(const int max_allocation); + +#endif /* __UMP_KERNEL_MEMORY_BACKEND_OS_H__ */ + diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_memory_backend.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_memory_backend.c new file mode 100644 index 0000000..fd1f555 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_memory_backend.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include /* kernel module definitions */ +#include /* request_mem_region */ + +#include "arch/config.h" /* Configuration for current platform. The symlink for arch is set by Makefile */ + +#include "ump_osk.h" +#include "ump_kernel_common.h" +#include "ump_kernel_memory_backend_os.h" +#include "ump_kernel_memory_backend_dedicated.h" + +/* Configure which dynamic memory allocator to use */ +int ump_backend = ARCH_UMP_BACKEND_DEFAULT; +module_param(ump_backend, int, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_backend, "0 = dedicated memory backend (default), 1 = OS memory backend"); + +/* The base address of the memory block for the dedicated memory backend */ +unsigned int ump_memory_address = ARCH_UMP_MEMORY_ADDRESS_DEFAULT; +module_param(ump_memory_address, uint, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_memory_address, "The physical address to map for the dedicated memory backend"); + +/* The size of the memory block for the dedicated memory backend */ +unsigned int ump_memory_size = ARCH_UMP_MEMORY_SIZE_DEFAULT; +module_param(ump_memory_size, uint, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_memory_size, "The size of fixed memory to map in the dedicated memory backend"); + +ump_memory_backend* ump_memory_backend_create ( void ) +{ + ump_memory_backend * backend = NULL; + + /* Create the dynamic memory allocator backend */ + if (0 == ump_backend) + { + DBG_MSG(2, ("Using dedicated memory backend\n")); + + DBG_MSG(2, ("Requesting dedicated memory: 0x%08x, size: %u\n", ump_memory_address, ump_memory_size)); + /* Ask the OS if we can use the specified physical memory */ + if (NULL == request_mem_region(ump_memory_address, ump_memory_size, "UMP Memory")) + { + MSG_ERR(("Failed to request memory region (0x%08X - 0x%08X). Is Mali DD already loaded?\n", ump_memory_address, ump_memory_address + ump_memory_size - 1)); + return NULL; + } + backend = ump_block_allocator_create(ump_memory_address, ump_memory_size); + } + else if (1 == ump_backend) + { + DBG_MSG(2, ("Using OS memory backend, allocation limit: %d\n", ump_memory_size)); + backend = ump_os_memory_backend_create(ump_memory_size); + } +/* MALI_SEC */ +#ifdef CONFIG_UMP_VCM_ALLOC + else if (2 == ump_backend) + { + DBG_MSG(2, ("Using VCM memory backend, allocation limit: %d\n", ump_memory_size)); + backend = ump_vcm_memory_backend_create(ump_memory_size); + } +#endif + + return backend; +} + +void ump_memory_backend_destroy( void ) +{ + if (0 == ump_backend) + { + DBG_MSG(2, ("Releasing dedicated memory: 0x%08x\n", ump_memory_address)); + release_mem_region(ump_memory_address, ump_memory_size); + } +} diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_atomics.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_atomics.c new file mode 100644 index 0000000..ef1902e --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_atomics.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_osk_atomics.c + * Implementation of the OS abstraction layer for the UMP kernel device driver + */ + +#include "ump_osk.h" +#include + +int _ump_osk_atomic_dec_and_read( _mali_osk_atomic_t *atom ) +{ + return atomic_dec_return((atomic_t *)&atom->u.val); +} + +int _ump_osk_atomic_inc_and_read( _mali_osk_atomic_t *atom ) +{ + return atomic_inc_return((atomic_t *)&atom->u.val); +} diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_low_level_mem.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_low_level_mem.c new file mode 100644 index 0000000..5fd85a6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_low_level_mem.c @@ -0,0 +1,507 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_osk_memory.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +/* needed to detect kernel version specific code */ +#include + +#include "ump_osk.h" +#include "ump_uk_types.h" +#include "ump_ukk.h" +#include "ump_kernel_common.h" +#include /* kernel module definitions */ +#include +#include +/* MALI_SEC */ +#include +#include + +#include +#include /* to verify pointers from user space */ +#include +#include + +typedef struct ump_vma_usage_tracker +{ + atomic_t references; + ump_memory_allocation *descriptor; +} ump_vma_usage_tracker; + +static void ump_vma_open(struct vm_area_struct * vma); +static void ump_vma_close(struct vm_area_struct * vma); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +static int ump_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf); +#else +static unsigned long ump_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address); +#endif + +static struct vm_operations_struct ump_vm_ops = +{ + .open = ump_vma_open, + .close = ump_vma_close, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + .fault = ump_cpu_page_fault_handler +#else + .nopfn = ump_cpu_page_fault_handler +#endif +}; + +/* + * Page fault for VMA region + * This should never happen since we always map in the entire virtual memory range. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +static int ump_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf) +#else +static unsigned long ump_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + void __user * address; + address = vmf->virtual_address; +#endif + MSG_ERR(("Page-fault in UMP memory region caused by the CPU\n")); + MSG_ERR(("VMA: 0x%08lx, virtual address: 0x%08lx\n", (unsigned long)vma, address)); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + return VM_FAULT_SIGBUS; +#else + return NOPFN_SIGBUS; +#endif +} + +static void ump_vma_open(struct vm_area_struct * vma) +{ + ump_vma_usage_tracker * vma_usage_tracker; + int new_val; + + vma_usage_tracker = (ump_vma_usage_tracker*)vma->vm_private_data; + BUG_ON(NULL == vma_usage_tracker); + + new_val = atomic_inc_return(&vma_usage_tracker->references); + + DBG_MSG(4, ("VMA open, VMA reference count incremented. VMA: 0x%08lx, reference count: %d\n", (unsigned long)vma, new_val)); +} + +static void ump_vma_close(struct vm_area_struct * vma) +{ + ump_vma_usage_tracker * vma_usage_tracker; + _ump_uk_unmap_mem_s args; + int new_val; + + vma_usage_tracker = (ump_vma_usage_tracker*)vma->vm_private_data; + BUG_ON(NULL == vma_usage_tracker); + + new_val = atomic_dec_return(&vma_usage_tracker->references); + + DBG_MSG(4, ("VMA close, VMA reference count decremented. VMA: 0x%08lx, reference count: %d\n", (unsigned long)vma, new_val)); + + if (0 == new_val) + { + ump_memory_allocation * descriptor; + + descriptor = vma_usage_tracker->descriptor; + + args.ctx = descriptor->ump_session; + args.cookie = descriptor->cookie; + args.mapping = descriptor->mapping; + args.size = descriptor->size; + + args._ukk_private = NULL; /** @note unused */ + + DBG_MSG(4, ("No more VMA references left, releasing UMP memory\n")); + _ump_ukk_unmap_mem( & args ); + + /* vma_usage_tracker is free()d by _ump_osk_mem_mapregion_term() */ + } +} + +_mali_osk_errcode_t _ump_osk_mem_mapregion_init( ump_memory_allocation * descriptor ) +{ + ump_vma_usage_tracker * vma_usage_tracker; + struct vm_area_struct *vma; + + if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; + + vma_usage_tracker = kmalloc(sizeof(ump_vma_usage_tracker), GFP_KERNEL); + if (NULL == vma_usage_tracker) + { + DBG_MSG(1, ("Failed to allocate memory for ump_vma_usage_tracker in _mali_osk_mem_mapregion_init\n")); + return -_MALI_OSK_ERR_FAULT; + } + + vma = (struct vm_area_struct*)descriptor->process_mapping_info; + if (NULL == vma ) + { + kfree(vma_usage_tracker); + return _MALI_OSK_ERR_FAULT; + } + + vma->vm_private_data = vma_usage_tracker; + vma->vm_flags |= VM_IO; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + vma->vm_flags |= VM_RESERVED; +#else + vma->vm_flags |= VM_DONTDUMP; + vma->vm_flags |= VM_DONTEXPAND; + vma->vm_flags |= VM_PFNMAP; +#endif + + + if (0==descriptor->is_cached) + { + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + } + DBG_MSG(3, ("Mapping with page_prot: 0x%x\n", vma->vm_page_prot )); + + /* Setup the functions which handle further VMA handling */ + vma->vm_ops = &ump_vm_ops; + + /* Do the va range allocation - in this case, it was done earlier, so we copy in that information */ + descriptor->mapping = (void __user*)vma->vm_start; + + atomic_set(&vma_usage_tracker->references, 1); /*this can later be increased if process is forked, see ump_vma_open() */ + vma_usage_tracker->descriptor = descriptor; + + return _MALI_OSK_ERR_OK; +} + +void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor ) +{ + struct vm_area_struct* vma; + ump_vma_usage_tracker * vma_usage_tracker; + + if (NULL == descriptor) return; + + /* Linux does the right thing as part of munmap to remove the mapping + * All that remains is that we remove the vma_usage_tracker setup in init() */ + vma = (struct vm_area_struct*)descriptor->process_mapping_info; + + vma_usage_tracker = vma->vm_private_data; + + /* We only get called if mem_mapregion_init succeeded */ + kfree(vma_usage_tracker); + return; +} + +_mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descriptor, u32 offset, u32 * phys_addr, unsigned long size ) +{ + struct vm_area_struct *vma; + _mali_osk_errcode_t retval; + + if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; + + vma = (struct vm_area_struct*)descriptor->process_mapping_info; + + if (NULL == vma ) return _MALI_OSK_ERR_FAULT; + + retval = remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, (*phys_addr) >> PAGE_SHIFT, size, vma->vm_page_prot) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK;; + + DBG_MSG(4, ("Mapping virtual to physical memory. ID: %u, vma: 0x%08lx, virtual addr:0x%08lx, physical addr: 0x%08lx, size:%lu, prot:0x%x, vm_flags:0x%x RETVAL: 0x%x\n", + ump_dd_secure_id_get(descriptor->handle), + (unsigned long)vma, + (unsigned long)(vma->vm_start + offset), + (unsigned long)*phys_addr, + size, + (unsigned int)vma->vm_page_prot, vma->vm_flags, retval)); + + return retval; +} + +/* MALI_SEC */ +static u32 _ump_osk_virt_to_phys_start(ump_dd_mem * mem, u32 start, u32 address, int *index) +{ + int i; + u32 offset = address - start; + ump_dd_physical_block *block; + u32 sum = 0; + + for (i=0; inr_blocks; i++) { + block = &mem->block_array[i]; + sum += block->size; + if (sum > offset) { + *index = i; + DBG_MSG(3, ("_ump_osk_virt_to_phys : index : %d, virtual 0x%x, phys 0x%x\n", i, address, (u32)block->addr + offset - (sum -block->size))); + return (u32)block->addr + offset - (sum -block->size); + } + } + + return _MALI_OSK_ERR_FAULT; +} + +/* MALI_SEC */ +static u32 _ump_osk_virt_to_phys_end(ump_dd_mem * mem, u32 start, u32 address, int *index) +{ + int i; + u32 offset = address - start; + ump_dd_physical_block *block; + u32 sum = 0; + + for (i=0; inr_blocks; i++) { + block = &mem->block_array[i]; + sum += block->size; + if (sum >= offset) { + *index = i; + DBG_MSG(3, ("_ump_osk_virt_to_phys : index : %d, virtual 0x%x, phys 0x%x\n", i, address, (u32)block->addr + offset - (sum -block->size))); + return (u32)block->addr + offset - (sum -block->size); + } + } + + return _MALI_OSK_ERR_FAULT; +} + +/* MALI_SEC */ +static void _ump_osk_msync_with_virt(ump_dd_mem * mem, ump_uk_msync_op op, u32 start, u32 address, u32 size) +{ + int start_index, end_index; + u32 start_p, end_p; + + DBG_MSG(3, ("Cache flush with user virtual address. start : 0x%x, end : 0x%x, address 0x%x, size 0x%x\n", start, start+mem->size_bytes, address, size)); + + start_p = _ump_osk_virt_to_phys_start(mem, start, address, &start_index); + end_p = _ump_osk_virt_to_phys_end(mem, start, address+size, &end_index); + + if (start_index==end_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) + outer_flush_range(start_p, end_p); + else + outer_clean_range(start_p, end_p); + } else { + ump_dd_physical_block *block; + int i; + + for (i=start_index; i<=end_index; i++) { + block = &mem->block_array[i]; + + if (i == start_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(start_p, block->addr+block->size); + } else { + outer_clean_range(start_p, block->addr+block->size); + } + } + else if (i == end_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(block->addr, end_p); + } else { + outer_clean_range(block->addr, end_p); + } + break; + } + else { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(block->addr, block->addr+block->size); + } else { + outer_clean_range(block->addr, block->addr+block->size); + } + } + } + } + return; +} +/* The end of MALI_SEC */ + +static void level1_cache_flush_all(void) +{ + DBG_MSG(4, ("UMP[xx] Flushing complete L1 cache\n")); + __cpuc_flush_kern_all(); +} + +void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data ) +{ + int i; + /* MALI_SEC */ + const void *start_v, *end_v; + + /* Flush L1 using virtual address, the entire range in one go. + * Only flush if user space process has a valid write mapping on given address. */ + if( (mem) && (virt!=NULL) && (access_ok(VERIFY_WRITE, virt, size)) ) + { + /* MALI_SEC */ + start_v = (void *)virt; + end_v = (void *)(start_v + size - 1); + /* There is no dmac_clean_range, so the L1 is always flushed, + * also for UMP_MSYNC_CLEAN. */ + if (size >= SZ_64K) + flush_all_cpu_caches(); + else + dmac_flush_range(start_v, end_v); + + /* MALI ORIGINAL CODE */ + //__cpuc_flush_dcache_area(virt, size); + + DBG_MSG(3, ("UMP[%02u] Flushing CPU L1 Cache. Cpu address: %x-%x\n", mem->secure_id, start_v,end_v)); + } + else + { + if (session_data) + { + if (op == _UMP_UK_MSYNC_FLUSH_L1 ) + { + DBG_MSG(4, ("UMP Pending L1 cache flushes: %d\n", session_data->has_pending_level1_cache_flush)); + session_data->has_pending_level1_cache_flush = 0; + level1_cache_flush_all(); + return; + } + else + { + if (session_data->cache_operations_ongoing) + { + session_data->has_pending_level1_cache_flush++; + DBG_MSG(4, ("UMP[%02u] Defering the L1 flush. Nr pending:%d\n", mem->secure_id, session_data->has_pending_level1_cache_flush) ); + } + else + { + /* Flushing the L1 cache for each switch_user() if ump_cache_operations_control(START) is not called */ + level1_cache_flush_all(); + } + } + } + else + { + DBG_MSG(4, ("Unkown state %s %d\n", __FUNCTION__, __LINE__)); + level1_cache_flush_all(); + } + } + + if ( NULL == mem ) return; + + if ( mem->size_bytes==size) + { + DBG_MSG(3, ("UMP[%02u] Flushing CPU L2 Cache\n",mem->secure_id)); + } + else + { + DBG_MSG(3, ("UMP[%02u] Flushing CPU L2 Cache. Blocks:%u, TotalSize:%u. FlushSize:%u Offset:0x%x FirstPaddr:0x%08x\n", + mem->secure_id, mem->nr_blocks, mem->size_bytes, size, offset, mem->block_array[0].addr)); + } + + + /* Flush L2 using physical addresses, block for block. */ + /* MALI_SEC */ + if ((virt!=NULL) && (mem->size_bytes >= SZ_1M)) { + if (op == _UMP_UK_MSYNC_CLEAN) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) + outer_clean_all(); +#else + outer_sync(); +#endif + else if ((op == _UMP_UK_MSYNC_INVALIDATE) || (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE)) + outer_flush_all(); + return; + } + + for (i=0 ; i < mem->nr_blocks; i++) + { + u32 start_p, end_p; + ump_dd_physical_block *block; + block = &mem->block_array[i]; + + if(offset >= block->size) + { + offset -= block->size; + continue; + } + + if(offset) + { + start_p = (u32)block->addr + offset; + /* We'll zero the offset later, after using it to calculate end_p. */ + } + else + { + start_p = (u32)block->addr; + } + + if(size < block->size - offset) + { + end_p = start_p + size - 1; + size = 0; + } + else + { + if(offset) + { + end_p = start_p + (block->size - offset - 1); + size -= block->size - offset; + offset = 0; + } + else + { + end_p = start_p + block->size - 1; + size -= block->size; + } + } + + switch(op) + { + case _UMP_UK_MSYNC_CLEAN: + outer_clean_range(start_p, end_p); + break; + case _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE: + outer_flush_range(start_p, end_p); + break; + case _UMP_UK_MSYNC_INVALIDATE: + outer_inv_range(start_p, end_p); + break; + default: + break; + } + + if(0 == size) + { + /* Nothing left to flush. */ + break; + } + } + + return; +} + +/* MALI_SEC */ +void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + ump_vma_usage_tracker * vma_usage_tracker; + ump_memory_allocation *descriptor; + ump_dd_handle handle; + + DBG_MSG(3, ("_ump_osk_mem_mapregion_get: vaddr 0x%08lx\n", vaddr)); + + down_read(&mm->mmap_sem); + vma = find_vma(mm, vaddr); + up_read(&mm->mmap_sem); + if(!vma) + { + DBG_MSG(3, ("Not found VMA\n")); + *mem = NULL; + return; + } + DBG_MSG(4, ("Get vma: 0x%08lx vma->vm_start: 0x%08lx\n", (unsigned long)vma, vma->vm_start)); + + vma_usage_tracker = (struct ump_vma_usage_tracker*)vma->vm_private_data; + if(vma_usage_tracker == NULL) + { + DBG_MSG(3, ("Not found vma_usage_tracker\n")); + *mem = NULL; + return; + } + + descriptor = (struct ump_memory_allocation*)vma_usage_tracker->descriptor; + handle = (ump_dd_handle)descriptor->handle; + + DBG_MSG(3, ("Get handle: 0x%08lx\n", handle)); + *mem = (ump_dd_mem*)handle; +} diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_misc.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_misc.c new file mode 100644 index 0000000..12066eb --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_misc.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_osk_misc.c + * Implementation of the OS abstraction layer for the UMP kernel device driver + */ + + +#include "ump_osk.h" + +#include +#include "ump_kernel_linux.h" + +/* is called from ump_kernel_constructor in common code */ +_mali_osk_errcode_t _ump_osk_init( void ) +{ + if (0 != ump_kernel_device_initialize()) + { + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _ump_osk_term( void ) +{ + ump_kernel_device_terminate(); + return _MALI_OSK_ERR_OK; +} diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.c new file mode 100644 index 0000000..977db9a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.c @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_ukk_wrappers.c + * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls for the reference implementation + */ + + +#include /* user space access */ + +#include "ump_osk.h" +#include "ump_uk_types.h" +#include "ump_ukk.h" +#include "ump_kernel_common.h" + +/* MALI_SEC */ +#if defined(CONFIG_ION_EXYNOS) || defined(CONFIG_DMA_SHARED_BUFFER) +#include +#include "ump_kernel_interface_ref_drv.h" +#include "mali_osk_list.h" +#ifdef CONFIG_ION_EXYNOS +#include +#include "../../../../gpu/ion/ion_priv.h" +extern struct ion_device *ion_exynos; +extern struct ion_client *ion_client_ump; +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER +#include +#endif +#endif + +/* + * IOCTL operation; Allocate UMP memory + */ +int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_allocate_s user_interaction; + _mali_osk_errcode_t err; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_allocate()\n")); + return -ENOTTY; + } + + /* Copy the user space memory to kernel space (so we safely can read it) */ + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_allocate()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + err = _ump_ukk_allocate( &user_interaction ); + if( _MALI_OSK_ERR_OK != err ) + { + DBG_MSG(1, ("_ump_ukk_allocate() failed in ump_ioctl_allocate()\n")); + return map_errcode(err); + } + user_interaction.ctx = NULL; + + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + /* If the copy fails then we should release the memory. We can use the IOCTL release to accomplish this */ + _ump_uk_release_s release_args; + + MSG_ERR(("copy_to_user() failed in ump_ioctl_allocate()\n")); + + release_args.ctx = (void *) session_data; + release_args.secure_id = user_interaction.secure_id; + + err = _ump_ukk_release( &release_args ); + if(_MALI_OSK_ERR_OK != err) + { + MSG_ERR(("_ump_ukk_release() also failed when trying to release newly allocated memory in ump_ioctl_allocate()\n")); + } + + return -EFAULT; + } + + return 0; /* success */ +} + +/* MALI_SEC */ +#ifdef CONFIG_ION_EXYNOS +/* + * IOCTL operation; Import fd to UMP memory + */ +int ump_ion_import_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_ion_import_s user_interaction; + ump_dd_handle *ump_handle; + ump_dd_physical_block * blocks; + unsigned long num_blocks; + struct ion_handle *ion_hnd; + struct scatterlist *sg; + struct scatterlist *sg_ion; + unsigned long i = 0; + + ump_session_memory_list_element * session_memory_element = NULL; + if (ion_client_ump==NULL) + ion_client_ump = ion_client_create(ion_exynos, -1, "ump"); + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_allocate()\n")); + return -ENOTTY; + } + + /* Copy the user space memory to kernel space (so we safely can read it) */ + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_allocate()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + /* translate fd to secure ID*/ + ion_hnd = ion_import_fd(ion_client_ump, user_interaction.ion_fd); + sg_ion = ion_map_dma(ion_client_ump,ion_hnd); + + blocks = (ump_dd_physical_block*)_mali_osk_malloc(sizeof(ump_dd_physical_block)*1024); + + if (NULL == blocks) { + MSG_ERR(("Failed to allocate blocks in ump_ioctl_allocate()\n")); + return -ENOMEM; + } + + sg = sg_ion; + do { + blocks[i].addr = sg_phys(sg); + blocks[i].size = sg_dma_len(sg); + i++; + if (i>=1024) { + _mali_osk_free(blocks); + MSG_ERR(("ion_import fail() in ump_ioctl_allocate()\n")); + return -EFAULT; + } + sg = sg_next(sg); + } while(sg); + + num_blocks = i; + + /* Initialize the session_memory_element, and add it to the session object */ + session_memory_element = _mali_osk_calloc( 1, sizeof(ump_session_memory_list_element)); + + if (NULL == session_memory_element) + { + _mali_osk_free(blocks); + DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n")); + return -EFAULT; + } + + ump_handle = ump_dd_handle_create_from_phys_blocks(blocks, num_blocks); + if (UMP_DD_HANDLE_INVALID == ump_handle) + { + _mali_osk_free(session_memory_element); + _mali_osk_free(blocks); + DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n")); + return -EFAULT; + } + + session_memory_element->mem = (ump_dd_mem*)ump_handle; + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_add(&(session_memory_element->list), &(session_data->list_head_session_memory_list)); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + ion_unmap_dma(ion_client_ump,ion_hnd); + ion_free(ion_client_ump, ion_hnd); + + _mali_osk_free(blocks); + + user_interaction.secure_id = ump_dd_secure_id_get(ump_handle); + user_interaction.size = ump_dd_size_get(ump_handle); + user_interaction.ctx = NULL; + + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + /* If the copy fails then we should release the memory. We can use the IOCTL release to accomplish this */ + + MSG_ERR(("copy_to_user() failed in ump_ioctl_allocate()\n")); + + return -EFAULT; + } + return 0; /* success */ +} +#endif + +#ifdef CONFIG_DMA_SHARED_BUFFER +int ump_dmabuf_import_wrapper(u32 __user *argument, + struct ump_session_data *session_data) +{ + ump_session_memory_list_element *session = NULL; + struct ump_uk_dmabuf ump_dmabuf; + ump_dd_handle *ump_handle; + ump_dd_physical_block *blocks; + struct dma_buf_attachment *attach; + struct dma_buf *dma_buf; + struct sg_table *sgt; + struct scatterlist *sgl; + unsigned long block_size; + /* FIXME */ + struct device dev; + unsigned int i = 0, npages; + int ret; + + /* Sanity check input parameters */ + if (!argument || !session_data) { + MSG_ERR(("NULL parameter.\n")); + return -EINVAL; + } + + if (copy_from_user(&ump_dmabuf, argument, + sizeof(struct ump_uk_dmabuf))) { + MSG_ERR(("copy_from_user() failed.\n")); + return -EFAULT; + } + + dma_buf = dma_buf_get(ump_dmabuf.fd); + if (IS_ERR(dma_buf)) + return PTR_ERR(dma_buf); + + /* + * check whether dma_buf imported already exists or not. + * + * TODO + * if already imported then dma_buf_put() should be called + * and then just return dma_buf imported. + */ + + attach = dma_buf_attach(dma_buf, &dev); + if (IS_ERR(attach)) { + ret = PTR_ERR(attach); + goto err_dma_buf_put; + } + + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); + goto err_dma_buf_detach; + } + + npages = sgt->nents; + + /* really need? */ + ump_dmabuf.ctx = (void *)session_data; + + block_size = sizeof(ump_dd_physical_block) * npages; + + blocks = (ump_dd_physical_block *)_mali_osk_malloc(block_size); + + if (NULL == blocks) { + MSG_ERR(("Failed to allocate blocks\n")); + ret = -ENOMEM; + goto err_dmu_buf_unmap; + } + + sgl = sgt->sgl; + + while (i < npages) { + blocks[i].addr = sg_phys(sgl); + blocks[i].size = sg_dma_len(sgl); + sgl = sg_next(sgl); + i++; + } + + /* + * Initialize the session memory list element, and add it + * to the session object + */ + session = _mali_osk_calloc(1, sizeof(*session)); + if (!session) { + DBG_MSG(1, ("Failed to allocate session.\n")); + ret = -EFAULT; + goto err_free_block; + } + + ump_handle = ump_dd_handle_create_from_phys_blocks(blocks, i); + if (UMP_DD_HANDLE_INVALID == ump_handle) { + DBG_MSG(1, ("Failed to create ump handle.\n")); + ret = -EFAULT; + goto err_free_session; + } + + session->mem = (ump_dd_mem *)ump_handle; + + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_add(&(session->list), + &(session_data->list_head_session_memory_list)); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_free(blocks); + + ump_dmabuf.ump_handle = (uint32_t)ump_handle; + ump_dmabuf.size = ump_dd_size_get(ump_handle); + + if (copy_to_user(argument, &ump_dmabuf, + sizeof(struct ump_uk_dmabuf))) { + MSG_ERR(("copy_to_user() failed.\n")); + ret = -EFAULT; + goto err_release_ump_handle; + } + + return 0; + +err_release_ump_handle: + ump_dd_reference_release(ump_handle); +err_free_session: + _mali_osk_free(session); +err_free_block: + _mali_osk_free(blocks); +err_dmu_buf_unmap: + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); +err_dma_buf_detach: + dma_buf_detach(dma_buf, attach); +err_dma_buf_put: + dma_buf_put(dma_buf); + return ret; +} +#endif diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.h new file mode 100644 index 0000000..63ee98c --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_ukk_wrappers.h + * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls for the reference implementation + */ + +#ifndef __UMP_UKK_REF_WRAPPERS_H__ +#define __UMP_UKK_REF_WRAPPERS_H__ + +#include +#include "ump_kernel_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data * session_data); + +/* MALI_SEC */ +#ifdef CONFIG_ION_EXYNOS +int ump_ion_import_wrapper(u32 __user * argument, struct ump_session_data * session_data); +#endif +/* MALI_SEC */ +#ifdef CONFIG_DMA_SHARED_BUFFER +int ump_dmabuf_import_wrapper(u32 __user *argument, + struct ump_session_data *session_data); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_UKK_REF_WRAPPERS_H__ */ diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.c new file mode 100644 index 0000000..780f311 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.c @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_ukk_wrappers.c + * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls + */ + +#include /* user space access */ + +#include "ump_osk.h" +#include "ump_uk_types.h" +#include "ump_ukk.h" +#include "ump_kernel_common.h" + +/* + * IOCTL operation; Negotiate version of IOCTL API + */ +int ump_get_api_version_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_api_version_s version_info; + _mali_osk_errcode_t err; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_get_api_version()\n")); + return -ENOTTY; + } + + /* Copy the user space memory to kernel space (so we safely can read it) */ + if (0 != copy_from_user(&version_info, argument, sizeof(version_info))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_get_api_version()\n")); + return -EFAULT; + } + + version_info.ctx = (void*) session_data; + err = _ump_uku_get_api_version( &version_info ); + if( _MALI_OSK_ERR_OK != err ) + { + MSG_ERR(("_ump_uku_get_api_version() failed in ump_ioctl_get_api_version()\n")); + return map_errcode(err); + } + + version_info.ctx = NULL; + + /* Copy ouput data back to user space */ + if (0 != copy_to_user(argument, &version_info, sizeof(version_info))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_get_api_version()\n")); + return -EFAULT; + } + + return 0; /* success */ +} + + +/* + * IOCTL operation; Release reference to specified UMP memory. + */ +int ump_release_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_release_s release_args; + _mali_osk_errcode_t err; + + /* Sanity check input parameters */ + if (NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_release()\n")); + return -ENOTTY; + } + + /* Copy the user space memory to kernel space (so we safely can read it) */ + if (0 != copy_from_user(&release_args, argument, sizeof(release_args))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_get_api_version()\n")); + return -EFAULT; + } + + release_args.ctx = (void*) session_data; + err = _ump_ukk_release( &release_args ); + if( _MALI_OSK_ERR_OK != err ) + { + MSG_ERR(("_ump_ukk_release() failed in ump_ioctl_release()\n")); + return map_errcode(err); + } + + + return 0; /* success */ +} + +/* + * IOCTL operation; Return size for specified UMP memory. + */ +int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_size_get_s user_interaction; + _mali_osk_errcode_t err; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_size_get()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + err = _ump_ukk_size_get( &user_interaction ); + if( _MALI_OSK_ERR_OK != err ) + { + MSG_ERR(("_ump_ukk_size_get() failed in ump_ioctl_size_get()\n")); + return map_errcode(err); + } + + user_interaction.ctx = NULL; + + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_size_get()\n")); + return -EFAULT; + } + + return 0; /* success */ +} + +/* + * IOCTL operation; Do cache maintenance on specified UMP memory. + */ +int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_msync_s user_interaction; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_msync()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + _ump_ukk_msync( &user_interaction ); + + user_interaction.ctx = NULL; + + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_msync()\n")); + return -EFAULT; + } + + return 0; /* success */ +} +int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_cache_operations_control_s user_interaction; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_cache_operations_control()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + _ump_ukk_cache_operations_control((_ump_uk_cache_operations_control_s*) &user_interaction ); + + user_interaction.ctx = NULL; + +#if 0 /* No data to copy back */ + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_cache_operations_control()\n")); + return -EFAULT; + } +#endif + return 0; /* success */ +} + +int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_switch_hw_usage_s user_interaction; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + _ump_ukk_switch_hw_usage( &user_interaction ); + + user_interaction.ctx = NULL; + +#if 0 /* No data to copy back */ + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } +#endif + return 0; /* success */ +} + +int ump_lock_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_lock_s user_interaction; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + _ump_ukk_lock( &user_interaction ); + + user_interaction.ctx = NULL; + +#if 0 /* No data to copy back */ + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } +#endif + + return 0; /* success */ +} + +int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_unlock_s user_interaction; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + _ump_ukk_unlock( &user_interaction ); + + user_interaction.ctx = NULL; + +#if 0 /* No data to copy back */ + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } +#endif + + return 0; /* success */ +} diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.h new file mode 100644 index 0000000..e87a903 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_ukk_wrappers.h + * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls + */ + +#ifndef __UMP_UKK_WRAPPERS_H__ +#define __UMP_UKK_WRAPPERS_H__ + +#include +#include "ump_kernel_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + + +int ump_get_api_version_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_release_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_lock_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data * session_data); + + + + +#ifdef __cplusplus +} +#endif + + + +#endif /* __UMP_UKK_WRAPPERS_H__ */ diff --git a/drivers/media/video/samsung/Kconfig b/drivers/media/video/samsung/Kconfig index 7ae9e6a..4824144 100644 --- a/drivers/media/video/samsung/Kconfig +++ b/drivers/media/video/samsung/Kconfig @@ -17,8 +17,6 @@ if CPU_EXYNOS4210 || CPU_EXYNOS4212 || CPU_EXYNOS4412 source "drivers/media/video/samsung/fimc/Kconfig" source "drivers/media/video/samsung/tvout/Kconfig" source "drivers/media/video/samsung/mfc5x/Kconfig" - source "drivers/media/video/samsung/mali/Kconfig" - source "drivers/media/video/samsung/ump/Kconfig" endif config VIDEO_FIMG2D diff --git a/drivers/media/video/samsung/Makefile b/drivers/media/video/samsung/Makefile index e9905d2..5a46253 100644 --- a/drivers/media/video/samsung/Makefile +++ b/drivers/media/video/samsung/Makefile @@ -12,8 +12,6 @@ obj-$(CONFIG_VIDEO_FIMG2D3X) += fimg2d3x/ obj-$(CONFIG_VIDEO_FIMG2D4X) += fimg2d4x/ endif -obj-$(CONFIG_VIDEO_UMP) += ump/ obj-$(CONFIG_VIDEO_TSI) += tsi/ -obj-$(CONFIG_VIDEO_MALI400MP) += mali/ EXTRA_CFLAGS += -Idrivers/media/video diff --git a/drivers/media/video/samsung/mali/Kbuild_module b/drivers/media/video/samsung/mali/Kbuild_module deleted file mode 100644 index e865954..0000000 --- a/drivers/media/video/samsung/mali/Kbuild_module +++ /dev/null @@ -1,295 +0,0 @@ -# -# Copyright (C) 2010-2011 ARM Limited. All rights reserved. -# -# This program is free software and is provided to you under the terms of the GNU General Public License version 2 -# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. -# -# A copy of the licence is included with the program, and can also be obtained from Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# - -# This file is called by the Linux build system. - -OSKOS=linux - -# set up defaults if not defined by the user -USING_UMP ?= 0 -USING_OS_MEMORY ?= 0 -USING_MALI_PMM_TESTSUITE ?= 0 -OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 -USING_PROFILING ?= 1 -USING_INTERNAL_PROFILING ?= 0 -DISABLE_PP0 ?= 0 -DISABLE_PP1 ?= 0 -DISABLE_PP2 ?= 0 -DISABLE_PP3 ?= 0 -PROFILING_SKIP_PP_JOBS ?= 0 -PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 -PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH ?= 0 -TIMESTAMP ?= default -BUILD ?= debug -TARGET_PLATFORM ?= default -KERNEL_RUNTIME_PM_ENABLED ?= 0 -CONFIG ?= pb-virtex5-m200 -MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0 -MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 -MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 - -DEFINES := $(EXTRA_DEFINES) - -# Get path to driver source from Linux build system -DRIVER_DIR=$(src) - -# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: -# The ARM proprietary product will only include the license/proprietary directory -# The GPL product will only include the license/gpl directory - -ifeq ($(wildcard $(DRIVER_DIR)/linux/license/gpl/*),) -ccflags-y += -I$(DRIVER_DIR)/linux/license/proprietary -# Disable profiling for proprietary -override USING_PROFILING := 0 -$(warning "USING_PROFILING not supported, disabling.") -else -ccflags-y += -I$(DRIVER_DIR)/linux/license/gpl -endif - - -ifeq ($(USING_PROFILING),1) -ifeq ($(USING_INTERNAL_PROFILING),0) -ifndef CONFIG_TRACEPOINTS -# Should default to gator profiling, but we dont have the kernel feature required, so disable profiling -override USING_PROFILING = 0 -$(warning "CONFIG_TRACEPOINTS required for USING_PROFILING") -endif -endif -endif - -ifeq ($(USING_PROFILING),0) -# make sure user hasnt selected incompatible flags -override USING_INTERNAL_PROFILING = 0 -endif - -MALI_RELEASE_NAME=$(shell cat $(DRIVER_DIR)/.version 2> /dev/null) - -# Check if a Mali Core sub module should be enabled, true or false returned -submodule_enabled = $(shell gcc $(DEFINES) -E $1/arch/config.h | grep type | grep -c $(2)) - -OSKFILES = \ - $(OSKOS)/mali_osk_atomics.c \ - $(OSKOS)/mali_osk_irq.c \ - $(OSKOS)/mali_osk_locks.c \ - $(OSKOS)/mali_osk_wait_queue.c \ - $(OSKOS)/mali_osk_low_level_mem.c \ - $(OSKOS)/mali_osk_math.c \ - $(OSKOS)/mali_osk_memory.c \ - $(OSKOS)/mali_osk_misc.c \ - $(OSKOS)/mali_osk_mali.c \ - $(OSKOS)/mali_osk_notification.c \ - $(OSKOS)/mali_osk_time.c \ - $(OSKOS)/mali_osk_timers.c - -UKKFILES = \ - $(OSKOS)/mali_ukk_mem.c \ - $(OSKOS)/mali_ukk_gp.c \ - $(OSKOS)/mali_ukk_pp.c \ - $(OSKOS)/mali_ukk_core.c - -ifeq ($(USING_PROFILING),1) -UKKFILES += \ - $(OSKOS)/mali_ukk_profiling.c -endif - -ifeq ($(MALI_PLATFORM_FILE),) -MALI_PLATFORM_FILE = platform/default/mali_platform.c -endif - -# Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available -SVN_REV := $(shell (cd $(DRIVER_DIR); (svnversion | grep -E "^[0-9]+" && svnversion) || git svn info | grep '^Revision: '| sed -e 's/^Revision: //' ) 2>/dev/null ) -ifeq ($(SVN_REV),) -SVN_REV := $(MALI_RELEASE_NAME) -else -SVN_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV) -endif - -# Validate selected config -ifneq ($(shell [ -d $(DRIVER_DIR)/arch-$(CONFIG) ] && [ -f $(DRIVER_DIR)/arch-$(CONFIG)/config.h ] && echo "OK"), OK) -$(warning Current directory is $(shell pwd)) -$(error No configuration found for config $(CONFIG). Check that arch-$(CONFIG)/config.h exists) -else -# Link arch to the selected arch-config directory -$(shell [ -L $(DRIVER_DIR)/arch ] && rm $(DRIVER_DIR)/arch) -$(shell ln -sf arch-$(CONFIG) $(DRIVER_DIR)/arch) -$(shell touch $(DRIVER_DIR)/arch/config.h) -endif - -# Set up our defines, which will be passed to gcc -DEFINES += -DUSING_OS_MEMORY=$(USING_OS_MEMORY) -DEFINES += -DUSING_MMU=1 -DEFINES += -DUSING_UMP=$(USING_UMP) -DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP -DEFINES += -DMALI_INTERNAL_TIMELINE_PROFILING_ENABLED=$(USING_INTERNAL_PROFILING) -DEFINES += -DDISABLE_PP0=$(DISABLE_PP0) -DEFINES += -DDISABLE_PP1=$(DISABLE_PP1) -DEFINES += -DDISABLE_PP2=$(DISABLE_PP2) -DEFINES += -DDISABLE_PP3=$(DISABLE_PP3) -DEFINES += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS) -DEFINES += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS) -DEFINES += -DPROFILING_PRINT_L2_HITRATE_ON_GP_FINISH=$(PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH) - -DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) -DEFINES += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) -DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) -DEFINES += -DMALI_TIMELINE_PROFILING_ENABLED=$(USING_PROFILING) -DEFINES += -DMALI_POWER_MGMT_TEST_SUITE=$(USING_MALI_PMM_TESTSUITE) -ifeq ($(shell test $(SUBLEVEL) -gt 32 -a $(PATCHLEVEL) = 6 -a $(VERSION) = 2 -o $(VERSION) -gt 2 && echo "OK"),OK) -# MALI_STATE_TRACKING is only supported on Linux kernels from version 2.6.32. -DEFINES += -DMALI_STATE_TRACKING=1 -else -DEFINES += -DMALI_STATE_TRACKING=0 -endif -DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) - -MALI_PLATFORM_FILE = platform/$(TARGET_PLATFORM)/mali_platform.c - - -ifdef CONFIG_PM -ifdef CONFIG_PM_RUNTIME - KERNEL_RUNTIME_PM_ENABLED = 1 -endif -endif - -DEFINES += -DMALI_PMM_RUNTIME_JOB_CONTROL_ON=$(KERNEL_RUNTIME_PM_ENABLED) - -ifeq ($(BUILD), debug) -DEFINES += -DDEBUG -endif -DEFINES += -DSVN_REV=$(SVN_REV) -DEFINES += -DSVN_REV_STRING=\"$(SVN_REV)\" - -# Linux has its own mmap cleanup handlers (see mali_kernel_memory.c) -DEFINES += -DMALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP - -ifeq ($(USING_UMP),1) - DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=1 - ccflags-y += -I$(DRIVER_DIR)/../../ump/include/ump -else - DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=0 -endif - -# Use our defines when compiling -ccflags-y += $(DEFINES) -I$(DRIVER_DIR) -I$(DRIVER_DIR)/include -I$(DRIVER_DIR)/common -I$(DRIVER_DIR)/linux -I$(DRIVER_DIR)/platform - -# Source files which always are included in a build -SRC = \ - common/mali_kernel_core.c \ - linux/mali_kernel_linux.c \ - common/mali_kernel_descriptor_mapping.c \ - common/mali_session.c \ - common/mali_device_pause_resume.c \ - common/mali_kernel_vsync.c \ - linux/mali_ukk_vsync.c \ - linux/mali_kernel_sysfs.c \ - common/mali_mmu.c \ - common/mali_mmu_page_directory.c \ - common/mali_memory.c \ - common/mali_kernel_memory_engine.c \ - common/mali_block_allocator.c \ - common/mali_kernel_mem_os.c \ - common/mali_mem_validation.c \ - common/mali_hw_core.c \ - common/mali_gp.c \ - common/mali_pp.c \ - common/mali_pp_job.c \ - common/mali_gp_job.c \ - common/mali_scheduler.c \ - common/mali_gp_scheduler.c \ - common/mali_pp_scheduler.c \ - common/mali_cluster.c \ - common/mali_group.c \ - common/mali_dlbu.c \ - common/mali_pm.c \ - common/mali_pmu.c \ - common/mali_user_settings_db.c \ - $(OSKOS)/mali_osk_pm.c \ - linux/mali_kernel_pm.c \ - linux/mali_pmu_power_up_down.c \ - $(MALI_PLATFORM_FILE) \ - $(OSKFILES) \ - $(UKKFILES) \ - __malidrv_build_info.c - -# Selecting files to compile by parsing the config file - -ifeq ($(USING_INTERNAL_PROFILING),1) -PROFILING_BACKEND_SOURCES = \ - linux/mali_osk_profiling_internal.c \ - timestamp-$(TIMESTAMP)/mali_timestamp.c -ccflags-y += -I$(DRIVER_DIR)/timestamp-$(TIMESTAMP) -else -ifeq ($(USING_PROFILING),1) -PROFILING_BACKEND_SOURCES = \ - linux/mali_osk_profiling_gator.c -endif -endif - -# Add the profiling sources -SRC += $(PROFILING_BACKEND_SOURCES) - -ifeq ($(USING_MALI_PMM_TESTSUITE),1) -ccflags-y += -I$(DRIVER_DIR)/platform/mali_pmu_testing -endif - -mali-$(CONFIG_MALI400_GPU_UTILIZATION) += common/mali_kernel_utilization.o -mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_dma_buf.o - -ifneq ($(call submodule_enabled, $(DRIVER_DIR), MALI400PP),0) - # Mali-400 PP in use - ccflags-y += -DUSING_MALI400 -endif - -ifneq ($(call submodule_enabled, $(DRIVER_DIR), MALI300PP),0) - # Mali-400 PP in use - ccflags-y += -DUSING_MALI400 -endif - -ifneq ($(call submodule_enabled, $(DRIVER_DIR), MALI200),0) - # Mali200 in use - ccflags-y += -DUSING_MALI200 -endif - -# Always build in support for Mali L2 cache -SRC += common/mali_l2_cache.c - -# Tell the Linux build system to enable building of our .c files -mali-y += $(SRC:.c=.o) -# Tell the Linux build system from which .o file to create the kernel module -obj-$(CONFIG_MALI400) := mali.o - - -VERSION_STRINGS := -VERSION_STRINGS += CONFIG=$(CONFIG) -VERSION_STRINGS += USING_OS_MEMORY=$(USING_OS_MEMORY) -VERSION_STRINGS += API_VERSION=$(shell cd $(DRIVER_DIR); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) -VERSION_STRINGS += REPO_URL=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'URL: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^URL: ' | cut -d: -f2- | cut -b2-) -VERSION_STRINGS += REVISION=$(SVN_REV) -VERSION_STRINGS += CHANGED_REVISION=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'Last Changed Rev: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-) -VERSION_STRINGS += CHANGE_DATE=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'Last Changed Date: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-) -VERSION_STRINGS += BUILD_DATE=$(shell date) - -VERSION_STRINGS += BUILD=$(shell echo $(BUILD) | tr a-z A-Z) -VERSION_STRINGS += CPU=$(CPU) -VERSION_STRINGS += USING_UMP=$(USING_UMP) -VERSION_STRINGS += USING_MALI200=$(call submodule_enabled, $(DRIVER_DIR), MALI200) -VERSION_STRINGS += USING_MALI400=$(call submodule_enabled, $(DRIVER_DIR), MALI400) -VERSION_STRINGS += USING_MALI400_L2_CACHE=$(call submodule_enabled, $(DRIVER_DIR), MALI400L2) -VERSION_STRINGS += USING_GP2=$(call submodule_enabled, $(DRIVER_DIR), MALIGP2) -VERSION_STRINGS += KDIR=$(KDIR) -VERSION_STRINGS += MALI_PLATFORM_FILE=$(MALI_PLATFORM_FILE) -VERSION_STRINGS += OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) -VERSION_STRINGS += USING_PROFILING=$(USING_PROFILING) -VERSION_STRINGS += USING_INTERNAL_PROFILING=$(USING_INTERNAL_PROFILING) -VERSION_STRINGS += USING_GPU_UTILIZATION=$(CONFIG_MALI400_GPU_UTILIZATION) - -# Create file with Mali driver configuration -$(DRIVER_DIR)/__malidrv_build_info.c: - @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(DRIVER_DIR)/__malidrv_build_info.c diff --git a/drivers/media/video/samsung/mali/Kconfig b/drivers/media/video/samsung/mali/Kconfig deleted file mode 100644 index 1736eed..0000000 --- a/drivers/media/video/samsung/mali/Kconfig +++ /dev/null @@ -1,63 +0,0 @@ -# -## S3C Multimedia Mali configuration -## -# -# For Mali -config VIDEO_MALI400MP - bool "Enable MALI integration" - depends on VIDEO_SAMSUNG - default y - ---help--- - This enables MALI integration in the multimedia device driver - -choice -depends on VIDEO_MALI400MP -prompt "MALI MEMORY OPTION" -default MALI_OSMEM_ONLY -config MALI_DED_ONLY - bool "mali dedicated memory only" - ---help--- - This enables MALI dedicated memory only option -config MALI_DED_MMU - bool "mali dedicated memory with mmu enable" - ---help--- - This enables MALI dedicated memory with mmu enable option -config MALI_OSMEM_ONLY - bool "mali OS memory only" - ---help--- - This enables MALI OS memory only option -config MALI_DED_OSMEM - bool "mali dedicated memory and OS memory" - ---help--- - This enables MALI dedicated memory and OS memory option - -endchoice -config MALI_MEM_SIZE -int "Dedicated Memory Size" - depends on VIDEO_MALI400MP && (MALI_DED_ONLY || MALI_DED_MMU || MALI_DED_OSMEM) - default "128" - ---help--- - This value is dedicated memory size of Mali GPU(unit is MByte). - -config MALI_R3P1_LSI - bool "Uses the R3P1 as a kernel module" - depends on VIDEO_MALI400MP - default n - ---help--- - This uses the r3p1 as a MALI kernel module - - -# For DEBUG -config VIDEO_MALI400MP_DEBUG - bool "Enables debug messages" - depends on VIDEO_MALI400MP - default n - help - This enables Mali driver debug messages. - -config VIDEO_MALI400MP_DVFS - bool "Enables DVFS" - depends on VIDEO_MALI400MP && PM - default y - help - This enables Mali driver DVFS. diff --git a/drivers/media/video/samsung/mali/Kconfig_module b/drivers/media/video/samsung/mali/Kconfig_module deleted file mode 100644 index dabb36e..0000000 --- a/drivers/media/video/samsung/mali/Kconfig_module +++ /dev/null @@ -1,30 +0,0 @@ -config MALI400 - tristate "Mali-300/400/450 support" - depends on ARM - select FB - ---help--- - This enables support for the Mali-300, Mali-400, and Mali-450 GPUs. - - To compile this driver as a module, choose M here: the module will be - called mali. - -config MALI400_DEBUG - bool "Enable debug in Mali driver" - depends on MALI400 - ---help--- - This enabled extra debug checks and messages in the Mali-300/400/450 - driver. - -config MALI400_PROFILING - bool "Enable Mali profiling" - depends on MALI400 && TRACEPOINTS - ---help--- - This enables gator profiling of Mali GPU events. - -config MALI400_GPU_UTILIZATION - bool "Enable Mali GPU utilization tracking" - depends on MALI400 - ---help--- - This enables gathering and processing of the utilization of Mali GPU. - This data can be used as a basis to change GPU operating frequency. - diff --git a/drivers/media/video/samsung/mali/Makefile b/drivers/media/video/samsung/mali/Makefile deleted file mode 100644 index 3e25b61..0000000 --- a/drivers/media/video/samsung/mali/Makefile +++ /dev/null @@ -1,337 +0,0 @@ -# -# Copyright (C) 2010-2012 ARM Limited. All rights reserved. -# -# This program is free software and is provided to you under the terms of the GNU General Public License version 2 -# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. -# -# A copy of the licence is included with the program, and can also be obtained from Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# - -OSKOS :=linux -FILES_PREFIX= -MALI_INCLUDE_PREFIX := drivers/media/video/samsung/mali/ -KBUILDROOT = - -ifeq ($(CONFIG_MALI_DED_ONLY),y) -USING_OS_MEMORY=0 -USING_MMU=0 -USING_DED=1 -endif - -ifeq ($(CONFIG_MALI_DED_MMU),y) -USING_OS_MEMORY=0 -USING_MMU=1 -USING_DED=1 -endif - -ifeq ($(CONFIG_MALI_OSMEM_ONLY),y) -USING_MMU=1 -USING_DED=0 -USING_OS_MEMORY=1 -endif - -ifeq ($(CONFIG_MALI_DED_OSMEM),y) -USING_MMU=1 -USING_DED=1 -USING_OS_MEMORY=1 -endif - -ifeq ($(CONFIG_PM),y) - USING_PMM = 1 -ifeq ($(CONFIG_PM_RUNTIME),y) - KERNEL_RUNTIME_PM_ENABLED = 1 -endif -endif - -ifeq ($(CONFIG_VIDEO_MALI400MP_DVFS),y) -USING_GPU_UTILIZATION=1 -USING_MALI_DVFS_ENABLED=1 -endif - -ifeq ($(CONFIG_VIDEO_UMP_DEBUG),y) -BUILD=debug -endif - -ifeq ($(CONFIG_VIDEO_MALI400MP_STREAMLINE_PROFILING),y) -USING_PROFILING=1 -USING_TRACEPOINTS=1 -endif - -# set up defaults if not defined by the user -USE_UMPV2 ?= 0 -PANIC_ON_WATCHDOG_TIMEOUT ?= 1 -USING_MALI400 ?= 1 -USING_MMU ?= 1 -USING_DED ?= 0 -USING_UMP ?= 0 -ONLY_ZBT ?= 0 -USING_ZBT ?= 0 -USING_OS_MEMORY ?= 1 -USING_PMM ?= 0 -USING_MALI_RUN_TIME_PM ?= 0 -USING_MALI_PMM_TESTSUITE ?= 0 -USING_MALI_PMU ?= 0 -USING_GPU_UTILIZATION ?= 0 -OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 -USING_PROFILING ?= 0 -USING_INTERNAL_PROFILING ?= 0 -USING_TRACEPOINTS ?= 0 -USING_MALI_MAJOR_PREDEFINE = 1 -USING_MALI_DVFS_ENABLED ?= 1 -USING_MALI_PMM_EARLYSUSPEND ?= 0 -#USING_KERNEL_WITH_DMA_ALLOC_PHYS_PAGE ?= 0 -#CONFIG_MALI_MEM_SIZE ?= 512 -DISABLE_PP0 ?= 0 -DISABLE_PP1 ?= 0 -DISABLE_PP2 ?= 0 -DISABLE_PP3 ?= 0 -PROFILING_SKIP_PP_JOBS ?= 0 -PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 -PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH ?= 0 -TIMESTAMP ?= default -BUILD ?= release -TARGET_PLATFORM ?= default -KERNEL_RUNTIME_PM_ENABLED ?= 0 -MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0 -MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 -MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 - -# Get path to driver source from Linux build system -ifeq ($(USING_PROFILING),1) -ifeq ($(USING_INTERNAL_PROFILING),0) -ifndef CONFIG_TRACEPOINTS -# Should default to gator profiling, but we dont have the kernel feature required, so disable profiling -override USING_PROFILING = 0 -$(warning "CONFIG_TRACEPOINTS required for USING_PROFILING") -endif -endif -endif - -ifeq ($(USING_PROFILING),0) -# make sure user hasnt selected incompatible flags -override USING_INTERNAL_PROFILING = 0 -endif - -USING_MALI_SLP_GLOBAL_LOCK ?= 0 - -#config validtion check -ifeq ($(USING_OS_MEMORY),1) - USING_MMU = 1 -endif - -# Check if a Mali Core sub module should be enabled, true or false returned -#submodule_enabled = $(shell gcc $(DEFINES) -E $(FILES_PREFIX)/arch/config.h | grep type | grep -c $(2)) - -# Inside the kernel build system - -# This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak --include ../../../arm_internal.mak - -# Set up our defines, which will be passed to gcc -DEFINES += -DONLY_ZBT=$(ONLY_ZBT) -DEFINES += -DUSING_ZBT=$(USING_ZBT) -DEFINES += -DUSING_MMU=$(USING_MMU) -DEFINES += -DUSING_OS_MEMORY=$(USING_OS_MEMORY) -DEFINES += -DUSING_DED=$(USING_DED) -DEFINES += -DUSING_UMP=$(USING_UMP) -DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP -DEFINES += -DUSING_MALI_PMU=$(USING_MALI_PMU) -DEFINES += -DMALI_PMM_RUNTIME_JOB_CONTROL_ON=$(KERNEL_RUNTIME_PM_ENABLED) -DEFINES += -DUSING_MALI_PMM=$(USING_PMM) -DEFINES += -DMALI_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) -DEFINES += -DCONFIG_MALI_MEM_SIZE=$(CONFIG_MALI_MEM_SIZE) -DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP -DEFINES += -DMALI_INTERNAL_TIMELINE_PROFILING_ENABLED=$(USING_INTERNAL_PROFILING) -DEFINES += -DMALI_MAJOR_PREDEFINE=$(USING_MALI_MAJOR_PREDEFINE) -DEFINES += -DMALI_DVFS_ENABLED=$(USING_MALI_DVFS_ENABLED) -DEFINES += -DUSING_MALI_PMM_EARLYSUSPEND=$(USING_MALI_PMM_EARLYSUSPEND) -DEFINES += -DMALI_STATE_TRACKING=0 -DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) -DEFINES += -DMALI_TRACEPOINTS_ENABLED=$(USING_TRACEPOINTS) -DEFINES += -DDISABLE_PP0=$(DISABLE_PP0) -DEFINES += -DDISABLE_PP1=$(DISABLE_PP1) -DEFINES += -DDISABLE_PP2=$(DISABLE_PP2) -DEFINES += -DDISABLE_PP3=$(DISABLE_PP3) -DEFINES += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS) -DEFINES += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS) -DEFINES += -DPROFILING_PRINT_L2_HITRATE_ON_GP_FINISH=$(PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH) -DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) -DEFINES += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) -DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) -DEFINES += -DMALI_TIMELINE_PROFILING_ENABLED=$(USING_PROFILING) -DEFINES += -DMALI_POWER_MGMT_TEST_SUITE=$(USING_MALI_PMM_TESTSUITE) -DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) - -ifeq ($(BUILD),debug) -DEFINES += -DDEBUG -endif - -# Linux has its own mmap cleanup handlers (see mali_kernel_mem_mmu.o) -DEFINES += -DMALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP - -# UMP -ifeq ($(CONFIG_VIDEO_UMP),y) - DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=1 - EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)../ump/include -else - DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=0 -endif - -# Target build file -obj-$(CONFIG_VIDEO_UMP) += mali.o - -# Use our defines when compiling -# MALI -INCLUDES = \ - -I$(MALI_INCLUDE_PREFIX)\ - -I$(MALI_INCLUDE_PREFIX)include \ - -I$(MALI_INCLUDE_PREFIX)common \ - -I$(MALI_INCLUDE_PREFIX)linux \ - -I$(MALI_INCLUDE_PREFIX)platform\ - -I$(MALI_INCLUDE_PREFIX)regs - -EXTRA_CFLAGS += $(INCLUDES)\ - $(DEFINES) - -EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)linux/license/gpl -EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)common/pmm - -# Source files which always are included in a build -ifeq ($(CONFIG_VIDEO_UMP),y) -OSKFILES=\ - $(FILES_PREFIX)$(OSKOS)/mali_osk_irq.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_wait_queue.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_low_level_mem.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_mali.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_notification.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_time.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_timers.o -else -OSKFILES=\ - $(FILES_PREFIX)$(OSKOS)/mali_osk_atomics.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_irq.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_locks.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_wait_queue.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_low_level_mem.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_math.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_memory.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_misc.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_mali.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_notification.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_time.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_timers.o -endif #($(CONFIG_VIDEO_UMP),y) - -ifeq ($(CONFIG_CPU_EXYNOS4210),y) - MALI_PLATFORM_DIR = platform/orion-m400 -else - MALI_PLATFORM_DIR = platform/pegasus-m400 -endif #($(CONFIG_CPU_EXYNOS4210),y) - -MALI_PLATFORM_FILE=$(MALI_PLATFORM_DIR)/mali_platform.o -UKKFILES=\ - $(FILES_PREFIX)$(OSKOS)/mali_ukk_mem.o \ - $(FILES_PREFIX)$(OSKOS)/mali_ukk_gp.o \ - $(FILES_PREFIX)$(OSKOS)/mali_ukk_pp.o \ - $(FILES_PREFIX)$(OSKOS)/mali_ukk_core.o - -ifeq ($(USING_PROFILING),1) -UKKFILES += \ - $(FILES_PREFIX)$(OSKOS)/mali_ukk_profiling.o -endif - -mali-y := \ - common/mali_kernel_core.o \ - linux/mali_kernel_linux.o \ - common/mali_kernel_descriptor_mapping.o \ - common/mali_session.o \ - common/mali_device_pause_resume.o \ - common/mali_kernel_vsync.o \ - linux/mali_ukk_vsync.o \ - linux/mali_kernel_sysfs.o \ - common/mali_mmu.o \ - common/mali_mmu_page_directory.o \ - common/mali_memory.o \ - common/mali_kernel_memory_engine.o \ - common/mali_block_allocator.o \ - common/mali_kernel_mem_os.o \ - common/mali_mem_validation.o \ - common/mali_hw_core.o \ - common/mali_gp.o \ - common/mali_pp.o \ - common/mali_pp_job.o \ - common/mali_gp_job.o \ - common/mali_scheduler.o \ - common/mali_gp_scheduler.o \ - common/mali_pp_scheduler.o \ - common/mali_cluster.o \ - common/mali_group.o \ - common/mali_dlbu.o \ - common/mali_pm.o \ - common/mali_pmu.o \ - common/mali_user_settings_db.o \ - $(OSKOS)/mali_osk_pm.o \ - linux/mali_kernel_pm.o \ - linux/mali_pmu_power_up_down.o \ - $(MALI_PLATFORM_FILE) \ - $(OSKFILES) \ - $(UKKFILES) -# __malidrv_build_info.c - -# Selecting files to compile by parsing the config file - -ifeq ($(USING_INTERNAL_PROFILING),1) -PROFILING_BACKEND_SOURCES = \ - linux/mali_osk_profiling_internal.o \ - timestamp-$(TIMESTAMP)/mali_timestamp.o -EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)timestamp-$(TIMESTAMP) -else -ifeq ($(USING_PROFILING),1) -PROFILING_BACKEND_SOURCES = \ - linux/mali_osk_profiling_gator.o -endif -endif - -# Add the profiling sources -mali-y += $(PROFILING_BACKEND_SOURCES) - -# Mali-400 PP in use -ifeq ($(USING_MALI_PMM_TESTSUITE),1) -EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)platform/mali_pmu_testing -endif - -ifeq ($(USING_GPU_UTILIZATION),1) -EXTRA_CFLAGS += -DCONFIG_MALI400_GPU_UTILIZATION=1 - -mali-y += \ - common/mali_kernel_utilization.o -endif - -ifeq ($(USING_MALI_DVFS_ENABLED),1) -mali-y += $(MALI_PLATFORM_DIR)/mali_platform_dvfs.o -endif #($(USING_MALI_DVFS_ENABLED),1) - -EXTRA_CFLAGS += -DUSING_MALI400 - -# Mali Level2 cache in use -EXTRA_CFLAGS += -DUSING_MALI400_L2_CACHE -mali-y += common/mali_l2_cache.o - -# Mali SLP Global lock feature -ifeq ($(USING_MALI_SLP_GLOBAL_LOCK),1) -mali-y += \ - linux/mali_slp_global_lock.o -endif - - -ifeq ($(PANIC_ON_WATCHDOG_TIMEOUT),1) - EXTRA_CFLAGS += -DUSING_KERNEL_PANIC -endif - -# Get subversion revision number, fall back to 0000 if no svn info is available -SVN_REV:=$(shell ((svnversion | grep -E "^[0-9]+" && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') - -EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV) -EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\" - diff --git a/drivers/media/video/samsung/mali/Makefile_module b/drivers/media/video/samsung/mali/Makefile_module deleted file mode 100644 index 361ce08..0000000 --- a/drivers/media/video/samsung/mali/Makefile_module +++ /dev/null @@ -1,97 +0,0 @@ -# -# Copyright (C) 2010-2012 ARM Limited. All rights reserved. -# -# This program is free software and is provided to you under the terms of the GNU General Public License version 2 -# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. -# -# A copy of the licence is included with the program, and can also be obtained from Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# - -USE_UMPV2=0 - -# The Makefile sets up "arch" based on the CONFIG, creates the version info -# string and the __malidrv_build_info.c file, and then call the Linux build -# system to actually build the driver. After that point the Kbuild file takes -# over. - -# set up defaults if not defined by the user -ARCH ?= arm - -OSKOS=linux -FILES_PREFIX= - -check_cc2 = \ - $(shell if $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \ - then \ - echo "$(2)"; \ - else \ - echo "$(3)"; \ - fi ;) - -# This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak --include ../../../arm_internal.mak - -# Check that required parameters are supplied. -ifeq ($(CONFIG),) -$(error "CONFIG must be specified.") -endif -ifeq ($(CPU)$(KDIR),) -$(error "KDIR or CPU must be specified.") -endif - -ifeq ($(USING_UMP),1) -ifeq ($(USE_UMPV2),1) -UMP_SYMVERS_FILE ?= ../umpv2/Module.symvers -else -UMP_SYMVERS_FILE ?= ../ump/Module.symvers -endif -KBUILD_EXTRA_SYMBOLS = $(realpath $(UMP_SYMVERS_FILE)) -$(warning $(KBUILD_EXTRA_SYMBOLS)) -endif - -# Get any user defined KDIR- or maybe even a hardcoded KDIR --include KDIR_CONFIGURATION - -# Define host system directory -KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build - -ifeq ($(ARCH), arm) -# when compiling for ARM we're cross compiling -export CROSS_COMPILE ?= $(call check_cc2, arm-linux-gnueabi-gcc, arm-linux-gnueabi-, arm-none-linux-gnueabi-) -endif - -# look up KDIR based om CPU selection -KDIR ?= $(KDIR-$(CPU)) - -# validate lookup result -ifeq ($(KDIR),) -$(error No KDIR found for platform $(CPU)) -endif - -# report detected/selected settings -ifdef ARM_INTERNAL_BUILD -$(warning Config $(CONFIG)) -$(warning Host CPU $(CPU)) -$(warning OS_MEMORY $(USING_OS_MEMORY)) -endif - -# Set up build config -export CONFIG_MALI400=m - -ifeq ($(USING_GPU_UTILIZATION),1) -export EXTRA_DEFINES += -DCONFIG_MALI400_GPU_UTILIZATION=1 -export CONFIG_MALI400_GPU_UTILIZATION := y -endif - -all: $(UMP_SYMVERS_FILE) - $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) modules - @rm $(FILES_PREFIX)__malidrv_build_info.c $(FILES_PREFIX)__malidrv_build_info.o - -clean: - $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean - -kernelrelease: - $(MAKE) ARCH=$(ARCH) -C $(KDIR) kernelrelease - -export CONFIG KBUILD_EXTRA_SYMBOLS diff --git a/drivers/media/video/samsung/mali/arch b/drivers/media/video/samsung/mali/arch deleted file mode 120000 index 58ffbe7..0000000 --- a/drivers/media/video/samsung/mali/arch +++ /dev/null @@ -1 +0,0 @@ -arch-release \ No newline at end of file diff --git a/drivers/media/video/samsung/mali/arch-debug b/drivers/media/video/samsung/mali/arch-debug deleted file mode 120000 index 0ed0909..0000000 --- a/drivers/media/video/samsung/mali/arch-debug +++ /dev/null @@ -1 +0,0 @@ -arch-pegasus-m400/ \ No newline at end of file diff --git a/drivers/media/video/samsung/mali/arch-orion-m400/config.h b/drivers/media/video/samsung/mali/arch-orion-m400/config.h deleted file mode 100644 index 73502a2..0000000 --- a/drivers/media/video/samsung/mali/arch-orion-m400/config.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2010 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the EB platform with ZBT memory enabled */ -/*zepplin added 2010.08.17 for orion configuration*/ -#define MALI_BASE_ADDR 0x13000000 -#define GP_ADDR MALI_BASE_ADDR -#define L2_ADDR MALI_BASE_ADDR+0x1000 -#define PMU_ADDR MALI_BASE_ADDR+0x2000 -#define GP_MMU_ADDR MALI_BASE_ADDR+0x3000 -#define PP0_MMU_ADDR MALI_BASE_ADDR+0x4000 -#define PP1_MMU_ADDR MALI_BASE_ADDR+0x5000 -#define PP2_MMU_ADDR MALI_BASE_ADDR+0x6000 -#define PP3_MMU_ADDR MALI_BASE_ADDR+0x7000 -#define PP0_ADDR MALI_BASE_ADDR+0x8000 -#define PP1_ADDR MALI_BASE_ADDR+0xA000 -#define PP2_ADDR MALI_BASE_ADDR+0xC000 -#define PP3_ADDR MALI_BASE_ADDR+0xE000 - -/*for mmu and os memory*/ -#define MEM_BASE_ADDR 0x40000000 -#define MEM_TOTAL_SIZE 0x40000000 -#define MEM_MALI_OS_SIZE 0x40000000 - -/*for dedicated memory*/ -//#define MEM_MALI_BASE 0x58000000 -//#define MEM_MALI_SIZE 0x08000000 -#define MEM_MALI_SIZE CONFIG_MALI_MEM_SIZE*1024*1024 -#define MEM_MALI_BASE 0x80000000 - MEM_MALI_SIZE - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = GP_ADDR, - .irq = IRQ_GP_3D, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = PP0_ADDR, - .irq = IRQ_PP0_3D, - .description = "Mali-400 PP 0", - .mmu_id = 2 - }, - { - .type = MALI400PP, - .base = PP1_ADDR, - .irq = IRQ_PP1_3D, - .description = "Mali-400 PP 1", - .mmu_id = 3 - }, - { - .type = MALI400PP, - .base = PP2_ADDR, - .irq = IRQ_PP2_3D, - .description = "Mali-400 PP 2", - .mmu_id = 4 - }, - { - .type = MALI400PP, - .base = PP3_ADDR, - .irq = IRQ_PP3_3D, - .description = "Mali-400 PP 3", - .mmu_id = 5 - }, -#if USING_MMU - { - .type = MMU, - .base = GP_MMU_ADDR, - .irq = IRQ_GPMMU_3D, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = PP0_MMU_ADDR, - .irq = IRQ_PPMMU0_3D, - .description = "Mali-400 MMU for PP 0", - .mmu_id = 2 - }, - { - .type = MMU, - .base = PP1_MMU_ADDR, - .irq = IRQ_PPMMU1_3D, - .description = "Mali-400 MMU for PP 1", - .mmu_id = 3 - }, - { - .type = MMU, - .base = PP2_MMU_ADDR, - .irq = IRQ_PPMMU2_3D, - .description = "Mali-400 MMU for PP 2", - .mmu_id = 4 - }, - { - .type = MMU, - .base = PP3_MMU_ADDR, - .irq = IRQ_PPMMU3_3D, - .description = "Mali-400 MMU for PP 3", - .mmu_id = 5 - }, -#if USING_OS_MEMORY - { - .type = OS_MEMORY, - .description = "System Memory", - .size = MEM_MALI_OS_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, -#endif -#if USING_DED /* Dedicated Memory */ - { - .type = MEMORY, - .description = "Dedicated Memory", - .base = MEM_MALI_BASE, - .size = MEM_MALI_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#endif/* if USING_OS_MEMORY*/ - { - .type = MEM_VALIDATION, - .description = "Framebuffer Memory", - .base = MEM_BASE_ADDR, - .size = MEM_TOTAL_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#else /* Not using MMU */ - { - .type = MEMORY, - .description = "Dedicated Memory", - .base = MEM_MALI_BASE, - .size = MEM_MALI_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#endif - { - .type = MALI400L2, - .base = L2_ADDR, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h deleted file mode 100644 index e579526..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = PMU, - .description = "Mali-300 PMU", - .base = 0xC0002000, - .irq = -1, - .mmu_id = 0 - - }, - { - .type = MALI300GP, - .description = "Mali-300 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI300PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-300 PP", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = -1, - .description = "Mali-300 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = -1, - .description = "Mali-300 MMU for PP", - .mmu_id = 2 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI300L2, - .base = 0xC0001000, - .description = "Mali-300 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h deleted file mode 100644 index 3893d72..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - - { - .type = PMU, - .description = "Mali-400 PMU", - .base = 0xC0002000, - .irq = -1, - .mmu_id = 0 - }, - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = -1, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = -1, - .description = "Mali-400 MMU for PP", - .mmu_id = 2 - }, - { - .type = OS_MEMORY, - .description = "OS Memory", - .alloc_order = 10, /* Lowest preference for this memory */ - .size = 96 * 1024 * 1024, /* 96 MB */ - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = 0, - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0x80000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h deleted file mode 100644 index 6d84ab1..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = PMU, - .description = "Mali-400 PMU", - .base = 0xC0002000, - .irq = -1, - .mmu_id = 0 - - }, - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = -1, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = -1, - .description = "Mali-400 MMU for PP", - .mmu_id = 2 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h deleted file mode 100644 index 568ac0a..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = -1, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = -1, - .description = "Mali-400 MMU for PP", - .mmu_id = 2 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h deleted file mode 100644 index 98b8059..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP 0", - .mmu_id = 2 - }, - { - .type = MALI400PP, - .base = 0xc000A000, - .irq = -1, - .description = "Mali-400 PP 1", - .mmu_id = 3 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = -1, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = -1, - .description = "Mali-400 MMU for PP 0", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0005000, - .irq = -1, - .description = "Mali-400 MMU for PP 1", - .mmu_id = 3 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h deleted file mode 100644 index 7b10925..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP 0", - .mmu_id = 2 - }, - { - .type = MALI400PP, - .base = 0xc000A000, - .irq = -1, - .description = "Mali-400 PP 1", - .mmu_id = 3 - }, - { - .type = MALI400PP, - .base = 0xc000C000, - .irq = -1, - .description = "Mali-400 PP 2", - .mmu_id = 4 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = 102, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = 102, - .description = "Mali-400 MMU for PP 0", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0005000, - .irq = 102, - .description = "Mali-400 MMU for PP 1", - .mmu_id = 3 - }, - { - .type = MMU, - .base = 0xC0006000, - .irq = 102, - .description = "Mali-400 MMU for PP 2", - .mmu_id = 4 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h deleted file mode 100644 index a15a6bd..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the EB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP 0", - .mmu_id = 2 - }, - { - .type = MALI400PP, - .base = 0xc000A000, - .irq = -1, - .description = "Mali-400 PP 1", - .mmu_id = 3 - }, - { - .type = MALI400PP, - .base = 0xc000C000, - .irq = -1, - .description = "Mali-400 PP 2", - .mmu_id = 4 - }, - { - .type = MALI400PP, - .base = 0xc000E000, - .irq = -1, - .description = "Mali-400 PP 3", - .mmu_id = 5 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = 102, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = 102, - .description = "Mali-400 MMU for PP 0", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0005000, - .irq = 102, - .description = "Mali-400 MMU for PP 1", - .mmu_id = 3 - }, - { - .type = MMU, - .base = 0xC0006000, - .irq = 102, - .description = "Mali-400 MMU for PP 2", - .mmu_id = 4 - }, - { - .type = MMU, - .base = 0xC0007000, - .irq = 102, - .description = "Mali-400 MMU for PP 3", - .mmu_id = 5 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h b/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h deleted file mode 100644 index d5196c3..0000000 --- a/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the EB platform with ZBT memory enabled */ -/*zepplin added 2010.08.17 for orion configuration*/ -#define MALI_BASE_ADDR 0x13000000 -#define GP_ADDR MALI_BASE_ADDR -#define L2_ADDR MALI_BASE_ADDR+0x1000 -#define PMU_ADDR MALI_BASE_ADDR+0x2000 -#define GP_MMU_ADDR MALI_BASE_ADDR+0x3000 -#define PP0_MMU_ADDR MALI_BASE_ADDR+0x4000 -#define PP1_MMU_ADDR MALI_BASE_ADDR+0x5000 -#define PP2_MMU_ADDR MALI_BASE_ADDR+0x6000 -#define PP3_MMU_ADDR MALI_BASE_ADDR+0x7000 -#define PP0_ADDR MALI_BASE_ADDR+0x8000 -#define PP1_ADDR MALI_BASE_ADDR+0xA000 -#define PP2_ADDR MALI_BASE_ADDR+0xC000 -#define PP3_ADDR MALI_BASE_ADDR+0xE000 - -/*for mmu and os memory*/ -#define MEM_BASE_ADDR 0x40000000 -#define MEM_TOTAL_SIZE 0x40000000 -#define MEM_MALI_OS_SIZE 0x40000000 - -/*for dedicated memory*/ -//#define MEM_MALI_BASE 0x58000000 -//#define MEM_MALI_SIZE 0x08000000 -#define MEM_MALI_SIZE CONFIG_MALI_MEM_SIZE*1024*1024 -#define MEM_MALI_BASE 0x80000000 - MEM_MALI_SIZE - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = GP_ADDR, - .irq = IRQ_GP_3D, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = PP0_ADDR, - .irq = IRQ_PP0_3D, - .description = "Mali-400 PP 0", - .mmu_id = 2 - }, - { - .type = MALI400PP, - .base = PP1_ADDR, - .irq = IRQ_PP1_3D, - .description = "Mali-400 PP 1", - .mmu_id = 3 - }, - { - .type = MALI400PP, - .base = PP2_ADDR, - .irq = IRQ_PP2_3D, - .description = "Mali-400 PP 2", - .mmu_id = 4 - }, - { - .type = MALI400PP, - .base = PP3_ADDR, - .irq = IRQ_PP3_3D, - .description = "Mali-400 PP 3", - .mmu_id = 5 - }, -#if USING_MMU - { - .type = MMU, - .base = GP_MMU_ADDR, - .irq = IRQ_GPMMU_3D, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = PP0_MMU_ADDR, - .irq = IRQ_PPMMU0_3D, - .description = "Mali-400 MMU for PP 0", - .mmu_id = 2 - }, - { - .type = MMU, - .base = PP1_MMU_ADDR, - .irq = IRQ_PPMMU1_3D, - .description = "Mali-400 MMU for PP 1", - .mmu_id = 3 - }, - { - .type = MMU, - .base = PP2_MMU_ADDR, - .irq = IRQ_PPMMU2_3D, - .description = "Mali-400 MMU for PP 2", - .mmu_id = 4 - }, - { - .type = MMU, - .base = PP3_MMU_ADDR, - .irq = IRQ_PPMMU3_3D, - .description = "Mali-400 MMU for PP 3", - .mmu_id = 5 - }, -#if USING_OS_MEMORY - { - .type = OS_MEMORY, - .description = "System Memory", - .size = MEM_MALI_OS_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, -#endif -#if USING_DED /* Dedicated Memory */ - { - .type = MEMORY, - .description = "Dedicated Memory", - .base = MEM_MALI_BASE, - .size = MEM_MALI_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#endif/* if USING_OS_MEMORY*/ - { - .type = MEM_VALIDATION, - .description = "memory validation", - .base = MEM_BASE_ADDR, - .size = MEM_TOTAL_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#else /* Not using MMU */ - { - .type = MEMORY, - .description = "Dedicated Memory", - .base = MEM_MALI_BASE, - .size = MEM_MALI_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#endif - { - .type = MALI400L2, - .base = L2_ADDR, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-release b/drivers/media/video/samsung/mali/arch-release deleted file mode 120000 index 0ed0909..0000000 --- a/drivers/media/video/samsung/mali/arch-release +++ /dev/null @@ -1 +0,0 @@ -arch-pegasus-m400/ \ No newline at end of file diff --git a/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h b/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h deleted file mode 100644 index eb5da50..0000000 --- a/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the Versatile Express platform */ - -#define MALI_BASE_ADDRESS 0xFC040000 - -static _mali_osk_resource_t arch_configuration [] = -{ - /* PMU */ - { - .type = PMU, - .base = MALI_BASE_ADDRESS + 0x02000, - .description = "MALI PMU" - }, - /* GP cluster */ - { - .type = MALI400L2, - .base = MALI_BASE_ADDRESS + 0x10000, - .description = "Mali-450 L2 cache for GP" - }, - { - .type = MALI400GP, - .description = "Mali-450 GP", - .base = MALI_BASE_ADDRESS, - .irq = -1, - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x3000, - .irq = 70, - .description = "Mali-450 MMU for GP", - }, - - /* PP0-3 cluster */ - { - .type = MALI400L2, - .base = MALI_BASE_ADDRESS + 0x1000, - .description = "Mali-450 L2 cache for PP0-3" - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0x8000, - .irq = 70, - .description = "Mali-450 PP0", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x4000, - .irq = 70, - .description = "Mali-450 MMU for PP0", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0xA000, - .irq = 70, - .description = "Mali-450 PP1", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x5000, - .irq = 70, - .description = "Mali-450 MMU for PP1", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0xC000, - .irq = 70, - .description = "Mali-450 PP2", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x6000, - .irq = 70, - .description = "Mali-450 MMU for PP2", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0xE000, - .irq = 70, - .description = "Mali-450 PP3", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x7000, - .irq = 70, - .description = "Mali-450 MMU for PP3", - }, - - /* PP4-7 cluster */ - { - .type = MALI400L2, - .base = MALI_BASE_ADDRESS + 0x11000, - .description = "Mali-450 L2 cache for PP4-7" - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0x28000, - .irq = 70, - .description = "Mali-450 PP4", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x1C000, - .irq = 70, - .description = "Mali-450 MMU for PP4", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0x2A000, - .irq = 70, - .description = "Mali-450 PP5", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x1D000, - .irq = 70, - .description = "Mali-450 MMU for PP5", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0x2C000, - .irq = 70, - .description = "Mali-450 PP6", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x1E000, - .irq = 70, - .description = "Mali-450 MMU for PP6", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0x2E000, - .irq = 70, - .description = "Mali-450 PP7", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x1F000, - .irq = 70, - .description = "Mali-450 MMU for PP7", - }, - - /* Memory */ - { - .type = OS_MEMORY, - .description = "Mali OS memory", - .cpu_usage_adjust = 0, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0x0, - .size = 256 * 1024 * 1024, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_block_allocator.c b/drivers/media/video/samsung/mali/common/mali_block_allocator.c deleted file mode 100644 index 269e662..0000000 --- a/drivers/media/video/samsung/mali/common/mali_block_allocator.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include "mali_kernel_common.h" -#include "mali_kernel_core.h" -#include "mali_kernel_memory_engine.h" -#include "mali_block_allocator.h" -#include "mali_osk.h" - -#define MALI_BLOCK_SIZE (256UL * 1024UL) /* 256 kB, remember to keep the ()s */ - -typedef struct block_info -{ - struct block_info * next; -} block_info; - -/* The structure used as the handle produced by block_allocator_allocate, - * and removed by block_allocator_release */ -typedef struct block_allocator_allocation -{ - /* The list will be released in reverse order */ - block_info *last_allocated; - mali_allocation_engine * engine; - mali_memory_allocation * descriptor; - u32 start_offset; - u32 mapping_length; -} block_allocator_allocation; - - -typedef struct block_allocator -{ - _mali_osk_lock_t *mutex; - block_info * all_blocks; - block_info * first_free; - u32 base; - u32 cpu_usage_adjust; - u32 num_blocks; -} block_allocator; - -MALI_STATIC_INLINE u32 get_phys(block_allocator * info, block_info * block); -static mali_physical_memory_allocation_result block_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); -static void block_allocator_release(void * ctx, void * handle); -static mali_physical_memory_allocation_result block_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block); -static void block_allocator_release_page_table_block( mali_page_table_block *page_table_block ); -static void block_allocator_destroy(mali_physical_memory_allocator * allocator); -static u32 block_allocator_stat(mali_physical_memory_allocator * allocator); - -mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size, const char *name) -{ - mali_physical_memory_allocator * allocator; - block_allocator * info; - u32 usable_size; - u32 num_blocks; - - usable_size = size & ~(MALI_BLOCK_SIZE - 1); - MALI_DEBUG_PRINT(3, ("Mali block allocator create for region starting at 0x%08X length 0x%08X\n", base_address, size)); - MALI_DEBUG_PRINT(4, ("%d usable bytes\n", usable_size)); - num_blocks = usable_size / MALI_BLOCK_SIZE; - MALI_DEBUG_PRINT(4, ("which becomes %d blocks\n", num_blocks)); - - if (usable_size == 0) - { - MALI_DEBUG_PRINT(1, ("Memory block of size %d is unusable\n", size)); - return NULL; - } - - allocator = _mali_osk_malloc(sizeof(mali_physical_memory_allocator)); - if (NULL != allocator) - { - info = _mali_osk_malloc(sizeof(block_allocator)); - if (NULL != info) - { - info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_MEM_INFO); - if (NULL != info->mutex) - { - info->all_blocks = _mali_osk_malloc(sizeof(block_info) * num_blocks); - if (NULL != info->all_blocks) - { - u32 i; - info->first_free = NULL; - info->num_blocks = num_blocks; - - info->base = base_address; - info->cpu_usage_adjust = cpu_usage_adjust; - - for ( i = 0; i < num_blocks; i++) - { - info->all_blocks[i].next = info->first_free; - info->first_free = &info->all_blocks[i]; - } - - allocator->allocate = block_allocator_allocate; - allocator->allocate_page_table_block = block_allocator_allocate_page_table_block; - allocator->destroy = block_allocator_destroy; - allocator->stat = block_allocator_stat; - allocator->ctx = info; - allocator->name = name; - - return allocator; - } - _mali_osk_lock_term(info->mutex); - } - _mali_osk_free(info); - } - _mali_osk_free(allocator); - } - - return NULL; -} - -static void block_allocator_destroy(mali_physical_memory_allocator * allocator) -{ - block_allocator * info; - MALI_DEBUG_ASSERT_POINTER(allocator); - MALI_DEBUG_ASSERT_POINTER(allocator->ctx); - info = (block_allocator*)allocator->ctx; - - _mali_osk_free(info->all_blocks); - _mali_osk_lock_term(info->mutex); - _mali_osk_free(info); - _mali_osk_free(allocator); -} - -MALI_STATIC_INLINE u32 get_phys(block_allocator * info, block_info * block) -{ - return info->base + ((block - info->all_blocks) * MALI_BLOCK_SIZE); -} - -static mali_physical_memory_allocation_result block_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) -{ - block_allocator * info; - u32 left; - block_info * last_allocated = NULL; - mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_NONE; - block_allocator_allocation *ret_allocation; - - MALI_DEBUG_ASSERT_POINTER(ctx); - MALI_DEBUG_ASSERT_POINTER(descriptor); - MALI_DEBUG_ASSERT_POINTER(offset); - MALI_DEBUG_ASSERT_POINTER(alloc_info); - - info = (block_allocator*)ctx; - left = descriptor->size - *offset; - MALI_DEBUG_ASSERT(0 != left); - - if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; - - ret_allocation = _mali_osk_malloc( sizeof(block_allocator_allocation) ); - - if ( NULL == ret_allocation ) - { - /* Failure; try another allocator by returning MALI_MEM_ALLOC_NONE */ - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - return result; - } - - ret_allocation->start_offset = *offset; - ret_allocation->mapping_length = 0; - - while ((left > 0) && (info->first_free)) - { - block_info * block; - u32 phys_addr; - u32 padding; - u32 current_mapping_size; - - block = info->first_free; - info->first_free = info->first_free->next; - block->next = last_allocated; - last_allocated = block; - - phys_addr = get_phys(info, block); - - padding = *offset & (MALI_BLOCK_SIZE-1); - - if (MALI_BLOCK_SIZE - padding < left) - { - current_mapping_size = MALI_BLOCK_SIZE - padding; - } - else - { - current_mapping_size = left; - } - - if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, phys_addr + padding, info->cpu_usage_adjust, current_mapping_size)) - { - MALI_DEBUG_PRINT(1, ("Mapping of physical memory failed\n")); - result = MALI_MEM_ALLOC_INTERNAL_FAILURE; - mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->start_offset, ret_allocation->mapping_length, (_mali_osk_mem_mapregion_flags_t)0); - - /* release all memory back to the pool */ - while (last_allocated) - { - /* This relinks every block we've just allocated back into the free-list */ - block = last_allocated->next; - last_allocated->next = info->first_free; - info->first_free = last_allocated; - last_allocated = block; - } - - break; - } - - *offset += current_mapping_size; - left -= current_mapping_size; - ret_allocation->mapping_length += current_mapping_size; - } - - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - - if (last_allocated) - { - if (left) result = MALI_MEM_ALLOC_PARTIAL; - else result = MALI_MEM_ALLOC_FINISHED; - - /* Record all the information about this allocation */ - ret_allocation->last_allocated = last_allocated; - ret_allocation->engine = engine; - ret_allocation->descriptor = descriptor; - - alloc_info->ctx = info; - alloc_info->handle = ret_allocation; - alloc_info->release = block_allocator_release; - } - else - { - /* Free the allocation information - nothing to be passed back */ - _mali_osk_free( ret_allocation ); - } - - return result; -} - -static void block_allocator_release(void * ctx, void * handle) -{ - block_allocator * info; - block_info * block, * next; - block_allocator_allocation *allocation; - - MALI_DEBUG_ASSERT_POINTER(ctx); - MALI_DEBUG_ASSERT_POINTER(handle); - - info = (block_allocator*)ctx; - allocation = (block_allocator_allocation*)handle; - block = allocation->last_allocated; - - MALI_DEBUG_ASSERT_POINTER(block); - - if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) - { - MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); - return; - } - - /* unmap */ - mali_allocation_engine_unmap_physical(allocation->engine, allocation->descriptor, allocation->start_offset, allocation->mapping_length, (_mali_osk_mem_mapregion_flags_t)0); - - while (block) - { - MALI_DEBUG_ASSERT(!((block < info->all_blocks) || (block > (info->all_blocks + info->num_blocks)))); - - next = block->next; - - /* relink into free-list */ - block->next = info->first_free; - info->first_free = block; - - /* advance the loop */ - block = next; - } - - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - - _mali_osk_free( allocation ); -} - - -static mali_physical_memory_allocation_result block_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) -{ - block_allocator * info; - mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_INTERNAL_FAILURE; - - MALI_DEBUG_ASSERT_POINTER(ctx); - MALI_DEBUG_ASSERT_POINTER(block); - info = (block_allocator*)ctx; - - if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; - - if (NULL != info->first_free) - { - void * virt; - u32 phys; - u32 size; - block_info * alloc; - alloc = info->first_free; - - phys = get_phys(info, alloc); /* Does not modify info or alloc */ - size = MALI_BLOCK_SIZE; /* Must be multiple of MALI_MMU_PAGE_SIZE */ - virt = _mali_osk_mem_mapioregion( phys, size, "Mali block allocator page tables" ); - - /* Failure of _mali_osk_mem_mapioregion will result in MALI_MEM_ALLOC_INTERNAL_FAILURE, - * because it's unlikely another allocator will be able to map in. */ - - if ( NULL != virt ) - { - block->ctx = info; /* same as incoming ctx */ - block->handle = alloc; - block->phys_base = phys; - block->size = size; - block->release = block_allocator_release_page_table_block; - block->mapping = virt; - - info->first_free = alloc->next; - - alloc->next = NULL; /* Could potentially link many blocks together instead */ - - result = MALI_MEM_ALLOC_FINISHED; - } - } - else result = MALI_MEM_ALLOC_NONE; - - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - - return result; -} - - -static void block_allocator_release_page_table_block( mali_page_table_block *page_table_block ) -{ - block_allocator * info; - block_info * block, * next; - - MALI_DEBUG_ASSERT_POINTER( page_table_block ); - - info = (block_allocator*)page_table_block->ctx; - block = (block_info*)page_table_block->handle; - - MALI_DEBUG_ASSERT_POINTER(info); - MALI_DEBUG_ASSERT_POINTER(block); - - - if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) - { - MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); - return; - } - - /* Unmap all the physical memory at once */ - _mali_osk_mem_unmapioregion( page_table_block->phys_base, page_table_block->size, page_table_block->mapping ); - - /** @note This loop handles the case where more than one block_info was linked. - * Probably unnecessary for page table block releasing. */ - while (block) - { - next = block->next; - - MALI_DEBUG_ASSERT(!((block < info->all_blocks) || (block > (info->all_blocks + info->num_blocks)))); - - block->next = info->first_free; - info->first_free = block; - - block = next; - } - - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); -} - -static u32 block_allocator_stat(mali_physical_memory_allocator * allocator) -{ - block_allocator * info; - block_info *block; - u32 free_blocks = 0; - - MALI_DEBUG_ASSERT_POINTER(allocator); - - info = (block_allocator*)allocator->ctx; - block = info->first_free; - - while(block) - { - free_blocks++; - block = block->next; - } - return (info->num_blocks - free_blocks) * MALI_BLOCK_SIZE; -} diff --git a/drivers/media/video/samsung/mali/common/mali_block_allocator.h b/drivers/media/video/samsung/mali/common/mali_block_allocator.h deleted file mode 100644 index 6c6f13e..0000000 --- a/drivers/media/video/samsung/mali/common/mali_block_allocator.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_BLOCK_ALLOCATOR_H__ -#define __MALI_BLOCK_ALLOCATOR_H__ - -#include "mali_kernel_memory_engine.h" - -mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size, const char *name); - -#endif /* __MALI_BLOCK_ALLOCATOR_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_cluster.c b/drivers/media/video/samsung/mali/common/mali_cluster.c deleted file mode 100644 index f0fb2b6..0000000 --- a/drivers/media/video/samsung/mali/common/mali_cluster.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_cluster.h" -#include "mali_osk.h" -#include "mali_group.h" -#include "mali_l2_cache.h" -#include "mali_scheduler.h" - -static struct mali_cluster *mali_global_clusters[MALI_MAX_NUMBER_OF_CLUSTERS] = { NULL, NULL, NULL }; -static u32 mali_global_num_clusters = 0; - -/** - * The structure represents a render cluster - * A render cluster is defined by all the cores that share the same Mali L2 cache - */ -struct mali_cluster -{ - struct mali_l2_cache_core *l2; - u32 number_of_groups; - struct mali_group* groups[MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER]; - u32 last_invalidated_id; - mali_bool power_is_enabled; -}; - -struct mali_cluster *mali_cluster_create(struct mali_l2_cache_core *l2_cache) -{ - struct mali_cluster *cluster = NULL; - - if (mali_global_num_clusters >= MALI_MAX_NUMBER_OF_CLUSTERS) - { - MALI_PRINT_ERROR(("Mali cluster: Too many cluster objects created\n")); - return NULL; - } - - cluster = _mali_osk_malloc(sizeof(struct mali_cluster)); - if (NULL != cluster) - { - _mali_osk_memset(cluster, 0, sizeof(struct mali_cluster)); - cluster->l2 = l2_cache; /* This cluster now owns this L2 cache object */ - cluster->last_invalidated_id = 0; - cluster->power_is_enabled = MALI_TRUE; - - mali_global_clusters[mali_global_num_clusters] = cluster; - mali_global_num_clusters++; - - return cluster; - } - - return NULL; -} - -void mali_cluster_power_is_enabled_set(struct mali_cluster * cluster, mali_bool power_is_enabled) -{ - cluster->power_is_enabled = power_is_enabled; -} - -mali_bool mali_cluster_power_is_enabled_get(struct mali_cluster * cluster) -{ - return cluster->power_is_enabled; -} - - -void mali_cluster_add_group(struct mali_cluster *cluster, struct mali_group *group) -{ - MALI_DEBUG_ASSERT_POINTER(cluster); - - if (cluster->number_of_groups < MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER) - { - /* This cluster now owns the group object */ - cluster->groups[cluster->number_of_groups] = group; - cluster->number_of_groups++; - } -} - -void mali_cluster_delete(struct mali_cluster *cluster) -{ - u32 i; - - MALI_DEBUG_ASSERT_POINTER(cluster); - - /* Free all the resources we own */ - for (i = 0; i < cluster->number_of_groups; i++) - { - mali_group_delete(cluster->groups[i]); - } - - if (NULL != cluster->l2) - { - mali_l2_cache_delete(cluster->l2); - } - - for (i = 0; i < mali_global_num_clusters; i++) - { - if (mali_global_clusters[i] == cluster) - { - mali_global_clusters[i] = NULL; - mali_global_num_clusters--; - break; - } - } - - _mali_osk_free(cluster); -} - -void mali_cluster_reset(struct mali_cluster *cluster) -{ - u32 i; - - MALI_DEBUG_ASSERT_POINTER(cluster); - - /* Free all the resources we own */ - for (i = 0; i < cluster->number_of_groups; i++) - { - struct mali_group *group = cluster->groups[i]; - - mali_group_reset(group); - } - - if (NULL != cluster->l2) - { - mali_l2_cache_reset(cluster->l2); - } -} - -struct mali_l2_cache_core* mali_cluster_get_l2_cache_core(struct mali_cluster *cluster) -{ - MALI_DEBUG_ASSERT_POINTER(cluster); - return cluster->l2; -} - -struct mali_group *mali_cluster_get_group(struct mali_cluster *cluster, u32 index) -{ - MALI_DEBUG_ASSERT_POINTER(cluster); - - if (index < cluster->number_of_groups) - { - return cluster->groups[index]; - } - - return NULL; -} - -struct mali_cluster *mali_cluster_get_global_cluster(u32 index) -{ - if (MALI_MAX_NUMBER_OF_CLUSTERS > index) - { - return mali_global_clusters[index]; - } - - return NULL; -} - -u32 mali_cluster_get_glob_num_clusters(void) -{ - return mali_global_num_clusters; -} - -mali_bool mali_cluster_l2_cache_invalidate_all(struct mali_cluster *cluster, u32 id) -{ - MALI_DEBUG_ASSERT_POINTER(cluster); - - if (NULL != cluster->l2) - { - /* If the last cache invalidation was done by a job with a higher id we - * don't have to flush. Since user space will store jobs w/ their - * corresponding memory in sequence (first job #0, then job #1, ...), - * we don't have to flush for job n-1 if job n has already invalidated - * the cache since we know for sure that job n-1's memory was already - * written when job n was started. */ - if (((s32)id) <= ((s32)cluster->last_invalidated_id)) - { - return MALI_FALSE; - } - else - { - cluster->last_invalidated_id = mali_scheduler_get_new_id(); - } - - mali_l2_cache_invalidate_all(cluster->l2); - } - return MALI_TRUE; -} - -void mali_cluster_l2_cache_invalidate_all_force(struct mali_cluster *cluster) -{ - MALI_DEBUG_ASSERT_POINTER(cluster); - - if (NULL != cluster->l2) - { - cluster->last_invalidated_id = mali_scheduler_get_new_id(); - mali_l2_cache_invalidate_all(cluster->l2); - } -} - -void mali_cluster_invalidate_pages(u32 *pages, u32 num_pages) -{ - u32 i; - - for (i = 0; i < mali_global_num_clusters; i++) - { - /*additional check for cluster*/ - if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_clusters[i]->l2)) - { - mali_l2_cache_invalidate_pages(mali_global_clusters[i]->l2, pages, num_pages); - } - mali_l2_cache_unlock_power_state(mali_global_clusters[i]->l2); - /*check for failed power locking???*/ - } -} diff --git a/drivers/media/video/samsung/mali/common/mali_cluster.h b/drivers/media/video/samsung/mali/common/mali_cluster.h deleted file mode 100644 index 33debdb..0000000 --- a/drivers/media/video/samsung/mali/common/mali_cluster.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_CLUSTER_H__ -#define __MALI_CLUSTER_H__ - -#include "mali_osk.h" -#include "mali_l2_cache.h" - -/* Maximum 1 GP and 4 PP for a cluster (Mali-400 Quad-core) */ -#define MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER 5 -#define MALI_MAX_NUMBER_OF_CLUSTERS 3 - -struct mali_cluster; -struct mali_group; - -struct mali_cluster *mali_cluster_create(struct mali_l2_cache_core *l2_cache); -void mali_cluster_add_group(struct mali_cluster *cluster, struct mali_group *group); -void mali_cluster_delete(struct mali_cluster *cluster); - -void mali_cluster_power_is_enabled_set(struct mali_cluster * cluster, mali_bool power_is_enabled); -mali_bool mali_cluster_power_is_enabled_get(struct mali_cluster * cluster); - -void mali_cluster_reset(struct mali_cluster *cluster); - -struct mali_l2_cache_core* mali_cluster_get_l2_cache_core(struct mali_cluster *cluster); -struct mali_group *mali_cluster_get_group(struct mali_cluster *cluster, u32 index); - -struct mali_cluster *mali_cluster_get_global_cluster(u32 index); -u32 mali_cluster_get_glob_num_clusters(void); - -/* Returns MALI_TRUE if it did the flush */ -mali_bool mali_cluster_l2_cache_invalidate_all(struct mali_cluster *cluster, u32 id); -void mali_cluster_l2_cache_invalidate_all_force(struct mali_cluster *cluster); -void mali_cluster_invalidate_pages(u32 *pages, u32 num_pages); - -#endif /* __MALI_CLUSTER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c deleted file mode 100644 index 6af1279..0000000 --- a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_device_pause_resume.c - * Implementation of the Mali pause/resume functionality - */ - -#include "mali_gp_scheduler.h" -#include "mali_pp_scheduler.h" -#include "mali_pm.h" - -void mali_dev_pause(mali_bool *power_is_on) -{ - mali_gp_scheduler_suspend(); - mali_pp_scheduler_suspend(); - - /* - * Take and hold the PM lock to be sure we don't change power state as well. - * (it might be unsafe to for instance change frequency if Mali GPU is powered off) - */ - mali_pm_execute_state_change_lock(); - if (NULL != power_is_on) - { - *power_is_on = mali_pm_is_powered_on(); - } -} - -void mali_dev_resume(void) -{ - mali_pm_execute_state_change_unlock(); - mali_gp_scheduler_resume(); - mali_pp_scheduler_resume(); -} - -/* -EXPORT_SYMBOL(mali_dev_pause); -EXPORT_SYMBOL(mali_dev_resume); -*/ diff --git a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h deleted file mode 100644 index 6be75b0..0000000 --- a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_DEVICE_PAUSE_RESUME_H__ -#define __MALI_DEVICE_PAUSE_RESUME_H__ - -#include "mali_osk.h" - -/** - * Pause the scheduling and power state changes of Mali device driver. - * mali_dev_resume() must always be called as soon as possible after this function - * in order to resume normal operation of the Mali driver. - * - * @param power_is_on Receives the power current status of Mali GPU. MALI_TRUE if GPU is powered on - */ -void mali_dev_pause(mali_bool *power_is_on); - -/** - * Resume scheduling and allow power changes in Mali device driver. - * This must always be called after mali_dev_pause(). - */ -void mali_dev_resume(void); - -#endif /* __MALI_DEVICE_PAUSE_RESUME_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_dlbu.c b/drivers/media/video/samsung/mali/common/mali_dlbu.c deleted file mode 100644 index fcc51fa..0000000 --- a/drivers/media/video/samsung/mali/common/mali_dlbu.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_dlbu.h" -#include "mali_memory.h" -#include "mali_pp.h" -#include "mali_group.h" -#include "mali_osk.h" -#include "mali_hw_core.h" - -/** - * Size of DLBU registers in bytes - */ -#define MALI_DLBU_SIZE 0x400 - -u32 mali_dlbu_phys_addr = 0; -static mali_io_address mali_dlbu_cpu_addr = 0; - -static u32 mali_dlbu_tile_position; - -/** - * DLBU register numbers - * Used in the register read/write routines. - * See the hardware documentation for more information about each register - */ -typedef enum mali_dlbu_register { - MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR = 0x0000, /**< Master tile list physical base address; - 31:12 Physical address to the page used for the DLBU - 0 DLBU enable - set this bit to 1 enables the AXI bus - between PPs and L2s, setting to 0 disables the router and - no further transactions are sent to DLBU */ - MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR = 0x0004, /**< Master tile list virtual base address; - 31:12 Virtual address to the page used for the DLBU */ - MALI_DLBU_REGISTER_TLLIST_VBASEADDR = 0x0008, /**< Tile list virtual base address; - 31:12 Virtual address to the tile list. This address is used when - calculating the call address sent to PP.*/ - MALI_DLBU_REGISTER_FB_DIM = 0x000C, /**< Framebuffer dimension; - 23:16 Number of tiles in Y direction-1 - 7:0 Number of tiles in X direction-1 */ - MALI_DLBU_REGISTER_TLLIST_CONF = 0x0010, /**< Tile list configuration; - 29:28 select the size of each allocated block: 0=128 bytes, 1=256, 2=512, 3=1024 - 21:16 2^n number of tiles to be binned to one tile list in Y direction - 5:0 2^n number of tiles to be binned to one tile list in X direction */ - MALI_DLBU_REGISTER_START_TILE_POS = 0x0014, /**< Start tile positions; - 31:24 start position in Y direction for group 1 - 23:16 start position in X direction for group 1 - 15:8 start position in Y direction for group 0 - 7:0 start position in X direction for group 0 */ - MALI_DLBU_REGISTER_PP_ENABLE_MASK = 0x0018, /**< PP enable mask; - 7 enable PP7 for load balancing - 6 enable PP6 for load balancing - 5 enable PP5 for load balancing - 4 enable PP4 for load balancing - 3 enable PP3 for load balancing - 2 enable PP2 for load balancing - 1 enable PP1 for load balancing - 0 enable PP0 for load balancing */ -} mali_dlbu_register; - -typedef enum -{ - PP0ENABLE = 0, - PP1ENABLE, - PP2ENABLE, - PP3ENABLE, - PP4ENABLE, - PP5ENABLE, - PP6ENABLE, - PP7ENABLE -} mali_dlbu_pp_enable; - -struct mali_dlbu_core -{ - struct mali_hw_core hw_core; /**< Common for all HW cores */ - u32 pp_cores_mask; /**< This is a mask for the PP cores whose operation will be controlled by LBU - see MALI_DLBU_REGISTER_PP_ENABLE_MASK register */ -}; - -_mali_osk_errcode_t mali_dlbu_initialize(void) -{ - - MALI_DEBUG_PRINT(2, ("Dynamic Load Balancing Unit initializing\n")); - - if (_MALI_OSK_ERR_OK == mali_mmu_get_table_page(&mali_dlbu_phys_addr, &mali_dlbu_cpu_addr)) - { - MALI_SUCCESS; - } - - return _MALI_OSK_ERR_FAULT; -} - -void mali_dlbu_terminate(void) -{ - MALI_DEBUG_PRINT(3, ("Mali DLBU: terminating\n")); - - mali_mmu_release_table_page(mali_dlbu_phys_addr); -} - -struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource) -{ - struct mali_dlbu_core *core = NULL; - - MALI_DEBUG_PRINT(2, ("Mali DLBU: Creating Mali dynamic load balancing unit: %s\n", resource->description)); - - core = _mali_osk_malloc(sizeof(struct mali_dlbu_core)); - if (NULL != core) - { - if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI_DLBU_SIZE)) - { - if (_MALI_OSK_ERR_OK == mali_dlbu_reset(core)) - { - mali_hw_core_register_write(&core->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR, MALI_DLB_VIRT_ADDR); - - return core; - } - MALI_PRINT_ERROR(("Failed to reset DLBU %s\n", core->hw_core.description)); - mali_hw_core_delete(&core->hw_core); - } - - _mali_osk_free(core); - } - else - { - MALI_PRINT_ERROR(("Mali DLBU: Failed to allocate memory for DLBU core\n")); - } - - return NULL; -} - -void mali_dlbu_delete(struct mali_dlbu_core *dlbu) -{ - mali_dlbu_reset(dlbu); - mali_hw_core_delete(&dlbu->hw_core); - _mali_osk_free(dlbu); -} - -void mali_dlbu_enable(struct mali_dlbu_core *dlbu) -{ - u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR); - - wval |= 0x1; - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, wval); -} - -void mali_dlbu_disable(struct mali_dlbu_core *dlbu) -{ - u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR); - - wval |= (wval & 0xFFFFFFFE); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, wval); -} - -_mali_osk_errcode_t mali_dlbu_enable_pp_core(struct mali_dlbu_core *dlbu, u32 pp_core_enable, u32 val) -{ - u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK); - - if((pp_core_enable < mali_pp_get_glob_num_pp_cores()) && ((0 == val) || (1 == val))) /* check for valid input parameters */ - { - if (val == 1) - { - val = (wval | (pp_core_enable <<= 0x1)); - } - if (val == 0) - { - val = (wval & ~(pp_core_enable << 0x1)); - } - wval |= val; - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, wval); - dlbu->pp_cores_mask = wval; - - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -void mali_dlbu_enable_all_pp_cores(struct mali_dlbu_core *dlbu) -{ - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask); -} - -void mali_dlbu_disable_all_pp_cores(struct mali_dlbu_core *dlbu) -{ - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, 0x0); -} - -void mali_dlbu_setup(struct mali_dlbu_core *dlbu, u8 fb_xdim, u8 fb_ydim, u8 xtilesize, u8 ytilesize, u8 blocksize, u8 xgr0, u8 ygr0, u8 xgr1, u8 ygr1) -{ - u32 wval = 0x0; - - /* write the framebuffer dimensions */ - wval = (16 << (u32)fb_ydim) | (u32)fb_xdim; - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_FB_DIM, wval); - - /* write the tile list configuration */ - wval = 0x0; - wval = (28 << (u32)blocksize) | (16 << (u32)ytilesize) | ((u32)xtilesize); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_CONF, wval); - - /* write the start tile position */ - wval = 0x0; - wval = (24 << (u32)ygr1 | (16 << (u32)xgr1) | 8 << (u32)ygr0) | (u32)xgr0; - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, wval); -} - -_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; - MALI_DEBUG_ASSERT_POINTER(dlbu); - - MALI_DEBUG_PRINT(4, ("Mali DLBU: mali_dlbu_reset: %s\n", dlbu->hw_core.description)); - - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, mali_dlbu_phys_addr); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, 0x00); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_FB_DIM, 0x00); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_CONF, 0x00); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, 0x00); - - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask); - - err = _MALI_OSK_ERR_OK; - - return err; -} - -_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; - u32 wval, rval; - struct mali_pp_core *pp_core = mali_group_get_pp_core(group); - - /* find the core id and set the mask */ - - if (NULL != pp_core) - { - wval = mali_pp_core_get_id(pp_core); - rval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, (wval << 0x1) | rval); - err = _MALI_OSK_ERR_OK; - } - - return err; -} - -void mali_dlbu_set_tllist_base_address(struct mali_dlbu_core *dlbu, u32 val) -{ - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, val); -} - -void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu) -{ - /* this function to implement (see documentation): - * 1) clear all bits in the enable register - * 2) wait until all PPs have finished - mali_pp_scheduler.c code - this done in interrupts call? - * 3) read the current tile position registers to get current tile positions - - * note that current tile position register is the same as start tile position - perhaps the name should be changed!!! */ - - /* 1) */ - mali_dlbu_disable_all_pp_cores(dlbu); - - /* 3) */ - mali_dlbu_tile_position = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS); -} - -void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu) -{ - /* this function to implement (see the document): - * 1) configure the dynamic load balancing unit as normal - * 2) set the current tile position registers as read when stopping the job - * 3) configure the PPs to start the job as normal - done by another part of the system - scheduler */ - - /* 1) */ - mali_dlbu_reset(dlbu); - /* ++ setup the needed values - see this */ - - /* 2) */ - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, mali_dlbu_tile_position); -} diff --git a/drivers/media/video/samsung/mali/common/mali_dlbu.h b/drivers/media/video/samsung/mali/common/mali_dlbu.h deleted file mode 100644 index e3c3b9d..0000000 --- a/drivers/media/video/samsung/mali/common/mali_dlbu.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_DLBU_H__ -#define __MALI_DLBU_H__ - -#include "mali_osk.h" -#include "mali_group.h" - -#define MALI_DLB_VIRT_ADDR 0xFFF00000 /* master tile virtual address fixed at this value and mapped into every session */ - -extern u32 mali_dlbu_phys_addr; - -struct mali_dlbu_core; - -_mali_osk_errcode_t mali_dlbu_initialize(void); -void mali_dlbu_terminate(void); - -struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource); -void mali_dlbu_delete(struct mali_dlbu_core *dlbu); - -void mali_dlbu_enable(struct mali_dlbu_core *dlbu); -void mali_dlbu_disable(struct mali_dlbu_core *dlbu); - -_mali_osk_errcode_t mali_dlbu_enable_pp_core(struct mali_dlbu_core *dlbu, u32 pp_core_enable, u32 val); -void mali_dlbu_enable_all_pp_cores(struct mali_dlbu_core *dlbu); -void mali_dlbu_disable_all_pp_cores(struct mali_dlbu_core *dlbu); - -_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu); -void mali_dlbu_setup(struct mali_dlbu_core *dlbu, u8 fb_xdim, u8 fb_ydim, u8 xtilesize, u8 ytilesize, u8 blocksize, u8 xgr0, u8 ygr0, u8 xgr1, u8 ygr1); - -_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group); -void mali_dlbu_set_tllist_base_address(struct mali_dlbu_core *dlbu, u32 val); - -void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu); -void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu); - -#endif /* __MALI_DLBU_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_gp.c b/drivers/media/video/samsung/mali/common/mali_gp.c deleted file mode 100644 index 1624e46..0000000 --- a/drivers/media/video/samsung/mali/common/mali_gp.c +++ /dev/null @@ -1,746 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_gp.h" -#include "mali_hw_core.h" -#include "mali_group.h" -#include "mali_osk.h" -#include "regs/mali_gp_regs.h" -#include "mali_kernel_common.h" -#include "mali_kernel_core.h" -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_osk_profiling.h" -#endif - -/** - * Definition of the GP core struct - * Used to track a GP core in the system. - */ -struct mali_gp_core -{ - struct mali_hw_core hw_core; /**< Common for all HW cores */ - struct mali_group *group; /**< Parent group for this core */ - _mali_osk_irq_t *irq; /**< IRQ handler */ - struct mali_gp_job *running_job; /**< Current running job */ - _mali_osk_timer_t *timeout_timer; /**< timeout timer for this core */ - u32 timeout_job_id; /**< job id for the timed out job - relevant only if gp_core_timed_out == MALI_TRUE */ - mali_bool core_timed_out; /**< if MALI_TRUE, this gp core has timed out; if MALI_FALSE, no timeout on this gp core */ - u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ - u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ - u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */ - u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */ -}; - -static struct mali_gp_core *mali_global_gp_core = NULL; - -/* Interrupt handlers */ -static _mali_osk_errcode_t mali_gp_upper_half(void *data); -static void mali_gp_bottom_half(void *data); -static void mali_gp_irq_probe_trigger(void *data); -static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data); -static void mali_gp_post_process_job(struct mali_gp_core *core, mali_bool suspend); -static void mali_gp_timeout(void *data); - -struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group) -{ - struct mali_gp_core* core = NULL; - - MALI_DEBUG_ASSERT(NULL == mali_global_gp_core); - MALI_DEBUG_PRINT(2, ("Mali GP: Creating Mali GP core: %s\n", resource->description)); - - core = _mali_osk_malloc(sizeof(struct mali_gp_core)); - if (NULL != core) - { - core->group = group; - core->running_job = NULL; - core->counter_src0 = MALI_HW_CORE_NO_COUNTER; - core->counter_src1 = MALI_HW_CORE_NO_COUNTER; - core->counter_src0_used = MALI_HW_CORE_NO_COUNTER; - core->counter_src1_used = MALI_HW_CORE_NO_COUNTER; - if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALIGP2_REGISTER_ADDRESS_SPACE_SIZE)) - { - _mali_osk_errcode_t ret; - - mali_group_lock(group); - ret = mali_gp_reset(core); - mali_group_unlock(group); - - if (_MALI_OSK_ERR_OK == ret) - { - /* Setup IRQ handlers (which will do IRQ probing if needed) */ - core->irq = _mali_osk_irq_init(resource->irq, - mali_gp_upper_half, - mali_gp_bottom_half, - mali_gp_irq_probe_trigger, - mali_gp_irq_probe_ack, - core, - "mali_gp_irq_handlers"); - if (NULL != core->irq) - { - /* Initialise the timeout timer */ - core->timeout_timer = _mali_osk_timer_init(); - if(NULL != core->timeout_timer) - { - _mali_osk_timer_setcallback(core->timeout_timer, mali_gp_timeout, (void *)core); - MALI_DEBUG_PRINT(4, ("Mali GP: set global gp core from 0x%08X to 0x%08X\n", mali_global_gp_core, core)); - mali_global_gp_core = core; - - return core; - } - else - { - MALI_PRINT_ERROR(("Failed to setup timeout timer for GP core %s\n", core->hw_core.description)); - /* Release IRQ handlers */ - _mali_osk_irq_term(core->irq); - } - } - else - { - MALI_PRINT_ERROR(("Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description)); - } - } - mali_hw_core_delete(&core->hw_core); - } - - _mali_osk_free(core); - } - else - { - MALI_PRINT_ERROR(("Failed to allocate memory for GP core\n")); - } - - return NULL; -} - -void mali_gp_delete(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - _mali_osk_timer_term(core->timeout_timer); - _mali_osk_irq_term(core->irq); - mali_hw_core_delete(&core->hw_core); - mali_global_gp_core = NULL; - _mali_osk_free(core); -} - -void mali_gp_stop_bus(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS); -} - -_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core) -{ - int i; - const int request_loop_count = 20; - - MALI_DEBUG_ASSERT_POINTER(core); - - /* Send the stop bus command. */ - mali_gp_stop_bus(core); - - /* Wait for bus to be stopped */ - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_PRINT_ERROR(("Mali GP: Failed to stop bus on %s\n", core->hw_core.description)); - return _MALI_OSK_ERR_FAULT; - } - return _MALI_OSK_ERR_OK; -} - -void mali_gp_hard_reset(struct mali_gp_core *core) -{ - const int reset_finished_loop_count = 15; - const u32 reset_wait_target_register = MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW; - const u32 reset_invalid_value = 0xC0FFE000; - const u32 reset_check_value = 0xC01A0000; - const u32 reset_default_value = 0; - int i; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_DEBUG_PRINT(4, ("Mali GP: Hard reset of core %s\n", core->hw_core.description)); - MALI_ASSERT_GROUP_LOCKED(core->group); - - mali_gp_post_process_job(core, MALI_FALSE); - - mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_invalid_value); - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_RESET); - - for (i = 0; i < reset_finished_loop_count; i++) - { - mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_check_value); - if (reset_check_value == mali_hw_core_register_read(&core->hw_core, reset_wait_target_register)) - { - break; - } - } - - if (i == reset_finished_loop_count) - { - MALI_PRINT_ERROR(("Mali GP: The hard reset loop didn't work, unable to recover\n")); - } - - mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_default_value); /* set it back to the default */ - /* Re-enable interrupts */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); - -} - -_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core) -{ - int i; - const int request_loop_count = 20; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_DEBUG_PRINT(4, ("Mali GP: Reset of core %s\n", core->hw_core.description)); - MALI_ASSERT_GROUP_LOCKED(core->group); - - mali_gp_post_process_job(core, MALI_FALSE); - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ - -#if defined(USING_MALI200) - - /* On Mali-200, stop the bus, then do a hard reset of the core */ - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS); - - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_PRINT_ERROR(("Mali GP: Failed to stop bus for core %s, unable to recover\n", core->hw_core.description)); - return _MALI_OSK_ERR_FAULT; - } - - /* the bus was stopped OK, do the hard reset */ - mali_gp_hard_reset(core); - -#elif defined(USING_MALI400) - - /* Mali-300 and Mali-400 have a safe reset command which we use */ - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET); - - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, unable to recover\n", core->hw_core.description)); - return _MALI_OSK_ERR_FAULT; - } -#else -#error "no supported mali core defined" -#endif - - /* Re-enable interrupts */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); - - return _MALI_OSK_ERR_OK; -} - -void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job) -{ - u32 startcmd = 0; - u32 *frame_registers = mali_gp_job_get_frame_registers(job); - core->counter_src0_used = core->counter_src0; - core->counter_src1_used = core->counter_src1; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_ASSERT_GROUP_LOCKED(core->group); - - if (mali_gp_job_has_vs_job(job)) - { - startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS; - } - - if (mali_gp_job_has_plbu_job(job)) - { - startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU; - } - - MALI_DEBUG_ASSERT(0 != startcmd); - - mali_hw_core_register_write_array_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR, frame_registers, MALIGP2_NUM_REGS_FRAME); - -#if PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH - { - /* Read hits and Read misses*/ - mali_l2_cache_core_set_counter_src0(mali_l2_cache_core_get_glob_l2_core(0), 20); - mali_l2_cache_core_set_counter_src1(mali_l2_cache_core_get_glob_l2_core(0), 21); - } -#endif - - /* This selects which performance counters we are reading */ - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) - { - /* global_config has enabled HW counters, this will override anything specified by user space */ - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) - { - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); - } - if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) - { - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); - } - } - else - { - /* Use HW counters from job object, if any */ - u32 perf_counter_flag = mali_gp_job_get_perf_counter_flag(job); - if (0 != perf_counter_flag) - { - if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) - { - core->counter_src0_used = mali_gp_job_get_perf_counter_src0(job); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); - } - - if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) - { - core->counter_src1_used = mali_gp_job_get_perf_counter_src1(job); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); - } - } - } - - MALI_DEBUG_PRINT(3, ("Mali GP: Starting job (0x%08x) on core %s with command 0x%08X\n", job, core->hw_core.description, startcmd)); - - /* Barrier to make sure the previous register write is finished */ - _mali_osk_write_mem_barrier(); - - /* This is the command that starts the core. */ - mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, startcmd); - - /* Barrier to make sure the previous register write is finished */ - _mali_osk_write_mem_barrier(); - - /* Setup the timeout timer value and save the job id for the job running on the gp core */ - - _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); - core->timeout_job_id = mali_gp_job_get_id(job); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, - job->frame_builder_id, job->flush_id, 0, 0, 0); - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), job->pid, job->tid, 0, 0, 0); -#endif - - core->running_job = job; -} - -void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr) -{ - u32 irq_readout; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_ASSERT_GROUP_LOCKED(core->group); - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT); - - if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) - { - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG)); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* re-enable interrupts */ - mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, start_addr); - mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, end_addr); - - MALI_DEBUG_PRINT(3, ("Mali GP: Resuming job\n")); - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC); - _mali_osk_write_mem_barrier(); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0); -#endif - } - /* - * else: core has been reset between PLBU_OUT_OF_MEM interrupt and this new heap response. - * A timeout or a page fault on Mali-200 PP core can cause this behaviour. - */ -} - -void mali_gp_abort_job(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - MALI_ASSERT_GROUP_LOCKED(core->group); - - if (_MALI_OSK_ERR_FAULT != mali_gp_reset(core)) - { - _mali_osk_timer_del(core->timeout_timer); - } -} - -u32 mali_gp_core_get_version(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VERSION); -} - -mali_bool mali_gp_core_set_counter_src0(struct mali_gp_core *core, u32 counter) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - core->counter_src0 = counter; - return MALI_TRUE; -} - -mali_bool mali_gp_core_set_counter_src1(struct mali_gp_core *core, u32 counter) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - core->counter_src1 = counter; - return MALI_TRUE; -} - -u32 mali_gp_core_get_counter_src0(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return core->counter_src0; -} - -u32 mali_gp_core_get_counter_src1(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return core->counter_src1; -} - -struct mali_gp_core *mali_gp_get_global_gp_core(void) -{ - return mali_global_gp_core; -} - -/* ------------- interrupt handling below ------------------ */ -static _mali_osk_errcode_t mali_gp_upper_half(void *data) -{ - struct mali_gp_core *core = (struct mali_gp_core *)data; - u32 irq_readout; - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); - if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout) - { - /* Mask out all IRQs from this core until IRQ is handled */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); -#endif - - /* We do need to handle this in a bottom half */ - _mali_osk_irq_schedulework(core->irq); - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -static void mali_gp_bottom_half(void *data) -{ - struct mali_gp_core *core = (struct mali_gp_core *)data; - u32 irq_readout; - u32 irq_errors; - -#if MALI_TIMELINE_PROFILING_ENABLED -#if 0 /* Bottom half TLP logging is currently not supported */ - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0); -#endif -#endif - - mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */ - - if ( MALI_FALSE == mali_group_power_is_on(core->group) ) - { - MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description)); - mali_group_unlock(core->group); - return; - } - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED; - MALI_DEBUG_PRINT(4, ("Mali GP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description)); - - if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST)) - { - u32 core_status = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS); - if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE)) - { - mali_gp_post_process_job(core, MALI_FALSE); - MALI_DEBUG_PRINT(4, ("Mali GP: Job completed, calling group handler\n")); - mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_COMPLETED); /* Will release group lock */ - return; - } - } - - /* - * Now lets look at the possible error cases (IRQ indicating error or timeout) - * END_CMD_LST, HANG and PLBU_OOM interrupts are not considered error. - */ - irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM); - if (0 != irq_errors) - { - mali_gp_post_process_job(core, MALI_FALSE); - MALI_PRINT_ERROR(("Mali GP: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, core->hw_core.description)); - mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_FAILED); /* Will release group lock */ - return; - } - else if (MALI_TRUE == core->core_timed_out) /* SW timeout */ - { - if (core->timeout_job_id == mali_gp_job_get_id(core->running_job)) - { - mali_gp_post_process_job(core, MALI_FALSE); - MALI_DEBUG_PRINT(2, ("Mali GP: Job %d timed out\n", mali_gp_job_get_id(core->running_job))); - mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_TIMED_OUT); - } - core->core_timed_out = MALI_FALSE; - return; - } - else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) - { - /* GP wants more memory in order to continue. - * - * This must be handled prior to HANG because this actually can - * generate a HANG while waiting for more memory. - * And it must be handled before the completion interrupts, - * since the PLBU can run out of memory after VS is complete; - * in which case the OOM must be handled before to complete the - * PLBU work. - */ - mali_gp_post_process_job(core, MALI_TRUE); - MALI_DEBUG_PRINT(3, ("Mali GP: PLBU needs more heap memory\n")); - mali_group_bottom_half(core->group, GROUP_EVENT_GP_OOM); /* Will release group lock */ - return; - } - else if (irq_readout & MALIGP2_REG_VAL_IRQ_HANG) - { - /* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_HANG); - } - - /* - * The only way to get here is if we got a HANG interrupt, which we ignore, or only one of two needed END_CMD_LST interrupts. - * Re-enable interrupts and let core continue to run. - */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); - mali_group_unlock(core->group); - -#if MALI_TIMELINE_PROFILING_ENABLED -#if 0 /* Bottom half TLP logging is currently not supported */ - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0); -#endif -#endif -} - -static void mali_gp_irq_probe_trigger(void *data) -{ - struct mali_gp_core *core = (struct mali_gp_core *)data; - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* @@@@ This should not be needed */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG); - _mali_osk_mem_barrier(); -} - -static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data) -{ - struct mali_gp_core *core = (struct mali_gp_core *)data; - u32 irq_readout; - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); - if (MALIGP2_REG_VAL_IRQ_FORCE_HANG & irq_readout) - { - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_FORCE_HANG); - _mali_osk_mem_barrier(); - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -/* ------ local helper functions below --------- */ - -static void mali_gp_post_process_job(struct mali_gp_core *core, mali_bool suspend) -{ - MALI_ASSERT_GROUP_LOCKED(core->group); - - if (NULL != core->running_job) - { - u32 val0 = 0; - u32 val1 = 0; -#if MALI_TIMELINE_PROFILING_ENABLED - u32 event_id; -#endif - -#if PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH - { - u32 src0, value0, src1, value1, sum, per_thousand, per_thousand_now, diff0, diff1; - static u32 print_nr=0; - static u32 prev0=0; - static u32 prev1=0; - if ( !(++print_nr&511) ) - { - mali_l2_cache_core_get_counter_values(mali_l2_cache_core_get_glob_l2_core(0), &src0, &value0, &src1, &value1); - MALI_DEBUG_ASSERT( src0==20 ); /* Read hits */ - MALI_DEBUG_ASSERT( src1==21 ); /* Read misses */ - - sum = value0+value1; - if ( sum > 1000000 ) - { - per_thousand = value0 / (sum/1000); - } - else - { - per_thousand = (value0*1000) / (sum); - } - diff0 = value0-prev0; - diff1 = value1-prev1; - - sum = diff0 + diff1 ; - if ( sum > 1000000 ) - { - per_thousand_now = diff0 / (sum/1000); - } - else - { - per_thousand_now = (diff0*1000) / (sum); - } - - prev0=value0; - prev1=value1; - if (per_thousand_now<=1000) - { - MALI_DEBUG_PRINT(2, ("Mali L2: Read hits/misses: %d/%d = %d thousand_parts total, since previous: %d\n", value0, value1, per_thousand, per_thousand_now)); - } - - } - } -#endif - - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) - { - val0 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE); - if (mali_gp_job_get_perf_counter_flag(core->running_job) && - _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_gp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used) - { - /* We retrieved the counter that user space asked for, so return the value through the job object */ - mali_gp_job_set_perf_counter_value0(core->running_job, val0); - } - else - { - /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ - mali_gp_job_set_perf_counter_value0(core->running_job, MALI_HW_CORE_INVALID_VALUE); - } - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, val0); -#endif - - } - - if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) - { - val1 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE); - if (mali_gp_job_get_perf_counter_flag(core->running_job) && - _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_gp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used) - { - /* We retrieved the counter that user space asked for, so return the value through the job object */ - mali_gp_job_set_perf_counter_value1(core->running_job, val1); - } - else - { - /* User space asked for a counter, but this is not what we retrieved (overridden by counter src set on core) */ - mali_gp_job_set_perf_counter_value1(core->running_job, MALI_HW_CORE_INVALID_VALUE); - } - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, val1); -#endif - } - -#if MALI_TIMELINE_PROFILING_ENABLED - if (MALI_TRUE == suspend) - { - event_id = MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0); - } - else - { - event_id = MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0); - } - _mali_osk_profiling_add_event(event_id, val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0); -#endif - - mali_gp_job_set_current_heap_addr(core->running_job, - mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR)); - - if (MALI_TRUE != suspend) - { - /* We are no longer running a job... */ - core->running_job = NULL; - _mali_osk_timer_del(core->timeout_timer); - } - } -} - -/* callback function for gp core timeout */ -static void mali_gp_timeout(void *data) -{ - struct mali_gp_core * core = ((struct mali_gp_core *)data); - - MALI_DEBUG_PRINT(3, ("Mali GP: TIMEOUT callback \n")); - core->core_timed_out = MALI_TRUE; - _mali_osk_irq_schedulework(core->irq); -} - -#if 0 -void mali_gp_print_state(struct mali_gp_core *core) -{ - MALI_DEBUG_PRINT(2, ("Mali GP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) )); -} -#endif - -#if MALI_STATE_TRACKING -u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size) -{ - int n = 0; - - n += _mali_osk_snprintf(buf + n, size - n, "\tGP: %s\n", core->hw_core.description); - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_gp.h b/drivers/media/video/samsung/mali/common/mali_gp.h deleted file mode 100644 index 3175b75..0000000 --- a/drivers/media/video/samsung/mali/common/mali_gp.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_GP_H__ -#define __MALI_GP_H__ - -#include "mali_osk.h" -#include "mali_gp_job.h" - -struct mali_gp_core; -struct mali_group; - -_mali_osk_errcode_t mali_gp_initialize(void); -void mali_gp_terminate(void); - -struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group); -void mali_gp_delete(struct mali_gp_core *core); - -void mali_gp_stop_bus(struct mali_gp_core *core); -_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core); -void mali_gp_hard_reset(struct mali_gp_core *core); -_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core); - -void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job); -void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr); - -void mali_gp_abort_job(struct mali_gp_core *core); - -u32 mali_gp_core_get_version(struct mali_gp_core *core); - -mali_bool mali_gp_core_set_counter_src0(struct mali_gp_core *core, u32 counter); -mali_bool mali_gp_core_set_counter_src1(struct mali_gp_core *core, u32 counter); -u32 mali_gp_core_get_counter_src0(struct mali_gp_core *core); -u32 mali_gp_core_get_counter_src1(struct mali_gp_core *core); -struct mali_gp_core *mali_gp_get_global_gp_core(void); - -u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size); - -#endif /* __MALI_GP_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_gp_job.c b/drivers/media/video/samsung/mali/common/mali_gp_job.c deleted file mode 100644 index abe1d93..0000000 --- a/drivers/media/video/samsung/mali/common/mali_gp_job.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_gp_job.h" -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_uk_types.h" - -struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id) -{ - struct mali_gp_job *job; - - job = _mali_osk_malloc(sizeof(struct mali_gp_job)); - if (NULL != job) - { - _mali_osk_list_init(&job->list); - job->session = session; - job->id = id; - job->user_id = args->user_job_ptr; - _mali_osk_memcpy(job->frame_registers, args->frame_registers, sizeof(job->frame_registers)); - job->heap_current_addr = args->frame_registers[4]; - job->perf_counter_flag = args->perf_counter_flag; - job->perf_counter_src0 = args->perf_counter_src0; - job->perf_counter_src1 = args->perf_counter_src1; - job->perf_counter_value0 = 0; - job->perf_counter_value1 = 0; - - job->pid = _mali_osk_get_pid(); - job->tid = _mali_osk_get_tid(); - job->frame_builder_id = args->frame_builder_id; - job->flush_id = args->flush_id; - - return job; - } - - return NULL; -} - -void mali_gp_job_delete(struct mali_gp_job *job) -{ - _mali_osk_free(job); -} diff --git a/drivers/media/video/samsung/mali/common/mali_gp_job.h b/drivers/media/video/samsung/mali/common/mali_gp_job.h deleted file mode 100644 index 9c29f1c..0000000 --- a/drivers/media/video/samsung/mali/common/mali_gp_job.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_GP_JOB_H__ -#define __MALI_GP_JOB_H__ - -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_uk_types.h" -#include "mali_session.h" - -/** - * The structure represends a GP job, including all sub-jobs - * (This struct unfortunatly needs to be public because of how the _mali_osk_list_* - * mechanism works) - */ -struct mali_gp_job -{ - _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */ - struct mali_session_data *session; /**< Session which submitted this job */ - u32 id; /**< identifier for this job in kernel space (sequential numbering) */ - u32 user_id; /**< identifier for the job in user space */ - u32 frame_registers[MALIGP2_NUM_REGS_FRAME]; /**< core specific registers associated with this job, see ARM DDI0415A */ - u32 heap_current_addr; /**< Holds the current HEAP address when the job has completed */ - u32 perf_counter_flag; /**< bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ - u32 perf_counter_src0; /**< source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ - u32 perf_counter_src1; /**< source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ - u32 perf_counter_value0; /**< Value of performance counter 0 (to be returned to user space) */ - u32 perf_counter_value1; /**< Value of performance counter 1 (to be returned to user space) */ - u32 pid; /**< Process ID of submitting process */ - u32 tid; /**< Thread ID of submitting thread */ - u32 frame_builder_id; /**< id of the originating frame builder */ - u32 flush_id; /**< flush id within the originating frame builder */ -}; - -struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id); -void mali_gp_job_delete(struct mali_gp_job *job); - -MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job) -{ - return (NULL == job) ? 0 : job->id; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_user_id(struct mali_gp_job *job) -{ - return job->user_id; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_frame_builder_id(struct mali_gp_job *job) -{ - return job->frame_builder_id; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_flush_id(struct mali_gp_job *job) -{ - return job->flush_id; -} - -MALI_STATIC_INLINE u32* mali_gp_job_get_frame_registers(struct mali_gp_job *job) -{ - return job->frame_registers; -} - -MALI_STATIC_INLINE struct mali_session_data *mali_gp_job_get_session(struct mali_gp_job *job) -{ - return job->session; -} - -MALI_STATIC_INLINE mali_bool mali_gp_job_has_vs_job(struct mali_gp_job *job) -{ - return (job->frame_registers[0] != job->frame_registers[1]) ? MALI_TRUE : MALI_FALSE; -} - -MALI_STATIC_INLINE mali_bool mali_gp_job_has_plbu_job(struct mali_gp_job *job) -{ - return (job->frame_registers[2] != job->frame_registers[3]) ? MALI_TRUE : MALI_FALSE; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_current_heap_addr(struct mali_gp_job *job) -{ - return job->heap_current_addr; -} - -MALI_STATIC_INLINE void mali_gp_job_set_current_heap_addr(struct mali_gp_job *job, u32 heap_addr) -{ - job->heap_current_addr = heap_addr; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_flag(struct mali_gp_job *job) -{ - return job->perf_counter_flag; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src0(struct mali_gp_job *job) -{ - return job->perf_counter_src0; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src1(struct mali_gp_job *job) -{ - return job->perf_counter_src1; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value0(struct mali_gp_job *job) -{ - return job->perf_counter_value0; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value1(struct mali_gp_job *job) -{ - return job->perf_counter_value1; -} - -MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value0(struct mali_gp_job *job, u32 value) -{ - job->perf_counter_value0 = value; -} - -MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value1(struct mali_gp_job *job, u32 value) -{ - job->perf_counter_value1 = value; -} - -#endif /* __MALI_GP_JOB_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c deleted file mode 100644 index f06d899..0000000 --- a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_gp_scheduler.h" -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_scheduler.h" -#include "mali_gp.h" -#include "mali_gp_job.h" -#include "mali_group.h" -#include "mali_cluster.h" - -enum mali_gp_slot_state -{ - MALI_GP_SLOT_STATE_IDLE, - MALI_GP_SLOT_STATE_WORKING, -}; - -/* A render slot is an entity which jobs can be scheduled onto */ -struct mali_gp_slot -{ - struct mali_group *group; - /* - * We keep track of the state here as well as in the group object - * so we don't need to take the group lock so often (and also avoid clutter with the working lock) - */ - enum mali_gp_slot_state state; - u32 returned_cookie; -}; - -static u32 gp_version = 0; -static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */ -static struct mali_gp_slot slot; - -/* Variables to allow safe pausing of the scheduler */ -static _mali_osk_wait_queue_t *gp_scheduler_working_wait_queue = NULL; -static u32 pause_count = 0; - -static mali_bool mali_gp_scheduler_is_suspended(void); - -static _mali_osk_lock_t *gp_scheduler_lock = NULL; -/* Contains tid of thread that locked the scheduler or 0, if not locked */ - -_mali_osk_errcode_t mali_gp_scheduler_initialize(void) -{ - u32 i; - - _MALI_OSK_INIT_LIST_HEAD(&job_queue); - - gp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); - if (NULL == gp_scheduler_lock) - { - return _MALI_OSK_ERR_NOMEM; - } - - gp_scheduler_working_wait_queue = _mali_osk_wait_queue_init(); - if (NULL == gp_scheduler_working_wait_queue) - { - _mali_osk_lock_term(gp_scheduler_lock); - return _MALI_OSK_ERR_NOMEM; - } - - /* Find all the available GP cores */ - for (i = 0; i < mali_cluster_get_glob_num_clusters(); i++) - { - u32 group_id = 0; - struct mali_cluster *curr_cluster = mali_cluster_get_global_cluster(i); - struct mali_group *group = mali_cluster_get_group(curr_cluster, group_id); - while (NULL != group) - { - struct mali_gp_core *gp_core = mali_group_get_gp_core(group); - if (NULL != gp_core) - { - if (0 == gp_version) - { - /* Retrieve GP version */ - gp_version = mali_gp_core_get_version(gp_core); - } - slot.group = group; - slot.state = MALI_GP_SLOT_STATE_IDLE; - break; /* There are only one GP, no point in looking for more */ - } - group_id++; - group = mali_cluster_get_group(curr_cluster, group_id); - } - } - - return _MALI_OSK_ERR_OK; -} - -void mali_gp_scheduler_terminate(void) -{ - _mali_osk_wait_queue_term(gp_scheduler_working_wait_queue); - _mali_osk_lock_term(gp_scheduler_lock); -} - -MALI_STATIC_INLINE void mali_gp_scheduler_lock(void) -{ - if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW)) - { - /* Non-interruptable lock failed: this should never happen. */ - MALI_DEBUG_ASSERT(0); - } - MALI_DEBUG_PRINT(5, ("Mali GP scheduler: GP scheduler lock taken\n")); -} - -MALI_STATIC_INLINE void mali_gp_scheduler_unlock(void) -{ - MALI_DEBUG_PRINT(5, ("Mali GP scheduler: Releasing GP scheduler lock\n")); - _mali_osk_lock_signal(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW); -} - -#ifdef DEBUG -MALI_STATIC_INLINE void mali_gp_scheduler_assert_locked(void) -{ - MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock); -} -#define MALI_ASSERT_GP_SCHEDULER_LOCKED() mali_gp_scheduler_assert_locked() -#else -#define MALI_ASSERT_GP_SCHEDULER_LOCKED() -#endif - -static void mali_gp_scheduler_schedule(void) -{ - struct mali_gp_job *job; - - MALI_ASSERT_GP_SCHEDULER_LOCKED(); - - if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue)) - { - MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", - pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0)); - return; /* Nothing to do, so early out */ - } - - job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list); - - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job)); - if (_MALI_OSK_ERR_OK == mali_group_start_gp_job(slot.group, job)) - { - /* Mark slot as busy */ - slot.state = MALI_GP_SLOT_STATE_WORKING; - - /* Remove from queue of unscheduled jobs */ - _mali_osk_list_del(&job->list); - } - else - { - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Failed to start GP job\n")); - } -} - -static void mali_gp_scheduler_return_job_to_user(struct mali_gp_job *job, mali_bool success) -{ - _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s)); - if (NULL != notobj) - { - _mali_uk_gp_job_finished_s *jobres = notobj->result_buffer; - _mali_osk_memset(jobres, 0, sizeof(_mali_uk_gp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ - jobres->user_job_ptr = mali_gp_job_get_user_id(job); - if (MALI_TRUE == success) - { - jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; - } - else - { - jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; - } - - jobres->heap_current_addr = mali_gp_job_get_current_heap_addr(job); - jobres->perf_counter0 = mali_gp_job_get_perf_counter_value0(job); - jobres->perf_counter1 = mali_gp_job_get_perf_counter_value1(job); - - mali_session_send_notification(mali_gp_job_get_session(job), notobj); - } - else - { - MALI_PRINT_ERROR(("Mali GP scheduler: Unable to allocate notification object\n")); - } - - mali_gp_job_delete(job); -} - - -void mali_gp_scheduler_do_schedule(void) -{ - mali_gp_scheduler_lock(); - - mali_gp_scheduler_schedule(); - - mali_gp_scheduler_unlock(); -} - -void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success) -{ - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) completed (%s)\n", mali_gp_job_get_id(job), job, success ? "success" : "failure")); - - mali_gp_scheduler_lock(); - - /* Mark slot as idle again */ - slot.state = MALI_GP_SLOT_STATE_IDLE; - - /* If paused, then this was the last job, so wake up sleeping workers */ - if (pause_count > 0) - { - _mali_osk_wait_queue_wake_up(gp_scheduler_working_wait_queue); - } - else - { - mali_gp_scheduler_schedule(); - } - - mali_gp_scheduler_unlock(); - - mali_gp_scheduler_return_job_to_user(job, success); -} - -void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job) -{ - _mali_osk_notification_t *notobj; - - notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); - - if (NULL != notobj) - { - _mali_uk_gp_job_suspended_s * jobres; - - mali_gp_scheduler_lock(); - - jobres = (_mali_uk_gp_job_suspended_s *)notobj->result_buffer; - - jobres->user_job_ptr = mali_gp_job_get_user_id(job); - jobres->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY; - jobres->cookie = mali_gp_job_get_id(job); - slot.returned_cookie = jobres->cookie; - - mali_session_send_notification(mali_gp_job_get_session(job), notobj); - - mali_gp_scheduler_unlock(); - } - - /* - * If this function failed, then we could return the job to user space right away, - * but there is a job timer anyway that will do that eventually. - * This is not exactly a common case anyway. - */ -} - -void mali_gp_scheduler_suspend(void) -{ - mali_gp_scheduler_lock(); - pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ - mali_gp_scheduler_unlock(); - - _mali_osk_wait_queue_wait_event(gp_scheduler_working_wait_queue, mali_gp_scheduler_is_suspended); -} - -void mali_gp_scheduler_resume(void) -{ - mali_gp_scheduler_lock(); - pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */ - if (0 == pause_count) - { - mali_gp_scheduler_schedule(); - } - mali_gp_scheduler_unlock(); -} - -_mali_osk_errcode_t _mali_ukk_gp_start_job(_mali_uk_gp_start_job_s *args) -{ - struct mali_session_data *session; - struct mali_gp_job *job; - - MALI_DEBUG_ASSERT_POINTER(args); - - if (NULL == args->ctx) - { - return _MALI_OSK_ERR_INVALID_ARGS; - } - - session = (struct mali_session_data*)args->ctx; - if (NULL == session) - { - return _MALI_OSK_ERR_FAULT; - } - - job = mali_gp_job_create(session, args, mali_scheduler_get_new_id()); - if (NULL == job) - { - return _MALI_OSK_ERR_NOMEM; - } - -#if PROFILING_SKIP_PP_AND_GP_JOBS -#warning GP jobs will not be executed - mali_gp_scheduler_return_job_to_user(job, MALI_TRUE); - return _MALI_OSK_ERR_OK; -#endif - - mali_gp_scheduler_lock(); - - _mali_osk_list_addtail(&job->list, &job_queue); - - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job)); - - mali_gp_scheduler_schedule(); - - mali_gp_scheduler_unlock(); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores(_mali_uk_get_gp_number_of_cores_s *args) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - args->number_of_cores = 1; - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_get_gp_core_version(_mali_uk_get_gp_core_version_s *args) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - args->version = gp_version; - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s *args) -{ - struct mali_session_data *session; - _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT; - - MALI_DEBUG_ASSERT_POINTER(args); - - if (NULL == args->ctx) - { - return _MALI_OSK_ERR_INVALID_ARGS; - } - - session = (struct mali_session_data*)args->ctx; - if (NULL == session) - { - return _MALI_OSK_ERR_FAULT; - } - - mali_gp_scheduler_lock(); - - /* Make sure that the cookie returned by user space is the same as we provided in the first place */ - if (args->cookie != slot.returned_cookie) - { - MALI_DEBUG_PRINT(2, ("Mali GP scheduler: Got an illegal cookie from user space, expected %u but got %u (job id)\n", slot.returned_cookie, args->cookie)) ; - mali_gp_scheduler_unlock(); - return _MALI_OSK_ERR_FAULT; - } - - mali_gp_scheduler_unlock(); - - switch (args->code) - { - case _MALIGP_JOB_RESUME_WITH_NEW_HEAP: - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Resuming job %u with new heap; 0x%08X - 0x%08X\n", args->cookie, args->arguments[0], args->arguments[1])); - mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]); - ret = _MALI_OSK_ERR_OK; - break; - - case _MALIGP_JOB_ABORT: - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting job %u, no new heap provided\n", args->cookie)); - mali_group_abort_gp_job(slot.group, args->cookie); - ret = _MALI_OSK_ERR_OK; - break; - - default: - MALI_PRINT_ERROR(("Mali GP scheduler: Wrong suspend response from user space\n")); - ret = _MALI_OSK_ERR_FAULT; - break; - } - - return ret; - -} - -void mali_gp_scheduler_abort_session(struct mali_session_data *session) -{ - struct mali_gp_job *job, *tmp; - - mali_gp_scheduler_lock(); - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting all jobs from session 0x%08x\n", session)); - - /* Check queue for jobs and remove */ - _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_gp_job, list) - { - if (mali_gp_job_get_session(job) == session) - { - MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Removing GP job 0x%08x from queue\n", job)); - _mali_osk_list_del(&(job->list)); - mali_gp_job_delete(job); - } - } - - mali_gp_scheduler_unlock(); - - /* Abort running jobs from this session. It is safe to do this outside - * the scheduler lock as there is only one GP core, and the queue has - * already been emptied, as long as there are no new jobs coming in - * from user space. */ - mali_group_abort_session(slot.group, session); -} - -static mali_bool mali_gp_scheduler_is_suspended(void) -{ - mali_bool ret; - - mali_gp_scheduler_lock(); - ret = pause_count > 0 && slot.state == MALI_GP_SLOT_STATE_IDLE; - mali_gp_scheduler_unlock(); - - return ret; -} - - -#if MALI_STATE_TRACKING -u32 mali_gp_scheduler_dump_state(char *buf, u32 size) -{ - int n = 0; - - n += _mali_osk_snprintf(buf + n, size - n, "GP\n"); - n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty"); - - n += mali_group_dump_state(slot.group, buf + n, size - n); - n += _mali_osk_snprintf(buf + n, size - n, "\t\tState: %d\n", mali_group_gp_state(slot.group)); - n += _mali_osk_snprintf(buf + n, size - n, "\n"); - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h deleted file mode 100644 index ef58509..0000000 --- a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_GP_SCHEDULER_H__ -#define __MALI_GP_SCHEDULER_H__ - -#include "mali_osk.h" -#include "mali_cluster.h" -#include "mali_gp_job.h" - -_mali_osk_errcode_t mali_gp_scheduler_initialize(void); -void mali_gp_scheduler_terminate(void); - -void mali_gp_scheduler_do_schedule(void); -void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success); -void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job); -void mali_gp_scheduler_abort_session(struct mali_session_data *session); -u32 mali_gp_scheduler_dump_state(char *buf, u32 size); - -void mali_gp_scheduler_suspend(void); -void mali_gp_scheduler_resume(void); - -#endif /* __MALI_GP_SCHEDULER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_group.c b/drivers/media/video/samsung/mali/common/mali_group.c deleted file mode 100644 index 94bf774..0000000 --- a/drivers/media/video/samsung/mali/common/mali_group.c +++ /dev/null @@ -1,841 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_group.h" -#include "mali_osk.h" -#include "mali_cluster.h" -#include "mali_gp.h" -#include "mali_pp.h" -#include "mali_mmu.h" -#include "mali_gp_scheduler.h" -#include "mali_pp_scheduler.h" -#include "mali_pm.h" - -/* - * The group object is the most important object in the device driver, - * and acts as the center of many HW operations. - * The reason for this is that operations on the MMU will affect all - * cores connected to this MMU (a group is defined by the MMU and the - * cores which are connected to this). - * The group lock is thus the most important lock, followed by the - * GP and PP scheduler locks. They must be taken in the following - * order: - * GP/PP lock first, then group lock(s). - */ - -/** - * The structure represents a render group - * A render group is defined by all the cores that share the same Mali MMU - */ - -struct mali_group -{ - struct mali_cluster *cluster; - - struct mali_mmu_core *mmu; - struct mali_session_data *session; - int page_dir_ref_count; - mali_bool power_is_on; -#if defined(USING_MALI200) - mali_bool pagedir_activation_failed; -#endif - - struct mali_gp_core *gp_core; - enum mali_group_core_state gp_state; - struct mali_gp_job *gp_running_job; - - struct mali_pp_core *pp_core; - enum mali_group_core_state pp_state; - struct mali_pp_job *pp_running_job; - u32 pp_running_sub_job; - - _mali_osk_lock_t *lock; -}; - -static struct mali_group *mali_global_groups[MALI_MAX_NUMBER_OF_GROUPS]; -static u32 mali_global_num_groups = 0; - -enum mali_group_activate_pd_status -{ - MALI_GROUP_ACTIVATE_PD_STATUS_FAILED, - MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD, - MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD, -}; - -/* local helper functions */ -static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session); -static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session); -static void mali_group_recovery_reset(struct mali_group *group); -static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success); - -void mali_group_lock(struct mali_group *group) -{ - if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(group->lock, _MALI_OSK_LOCKMODE_RW)) - { - /* Non-interruptable lock failed: this should never happen. */ - MALI_DEBUG_ASSERT(0); - } - MALI_DEBUG_PRINT(5, ("Mali group: Group lock taken 0x%08X\n", group)); -} - -void mali_group_unlock(struct mali_group *group) -{ - MALI_DEBUG_PRINT(5, ("Mali group: Releasing group lock 0x%08X\n", group)); - _mali_osk_lock_signal(group->lock, _MALI_OSK_LOCKMODE_RW); -} - -#ifdef DEBUG -void mali_group_assert_locked(struct mali_group *group) -{ - MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); -} -#endif - - -struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_mmu_core *mmu) -{ - struct mali_group *group = NULL; - - if (mali_global_num_groups >= MALI_MAX_NUMBER_OF_GROUPS) - { - MALI_PRINT_ERROR(("Mali group: Too many group objects created\n")); - return NULL; - } - - group = _mali_osk_malloc(sizeof(struct mali_group)); - if (NULL != group) - { - _mali_osk_memset(group, 0, sizeof(struct mali_group)); - group->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_GROUP); - if (NULL != group->lock) - { - group->cluster = cluster; - group->mmu = mmu; /* This group object now owns the MMU object */ - group->session = NULL; - group->page_dir_ref_count = 0; - group->power_is_on = MALI_TRUE; - - group->gp_state = MALI_GROUP_CORE_STATE_IDLE; - group->pp_state = MALI_GROUP_CORE_STATE_IDLE; -#if defined(USING_MALI200) - group->pagedir_activation_failed = MALI_FALSE; -#endif - mali_global_groups[mali_global_num_groups] = group; - mali_global_num_groups++; - - return group; - } - _mali_osk_free(group); - } - - return NULL; -} - -void mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core) -{ - /* This group object now owns the GP core object */ - group->gp_core = gp_core; -} - -void mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core) -{ - /* This group object now owns the PP core object */ - group->pp_core = pp_core; -} - -void mali_group_delete(struct mali_group *group) -{ - u32 i; - - /* Delete the resources that this group owns */ - if (NULL != group->gp_core) - { - mali_gp_delete(group->gp_core); - } - - if (NULL != group->pp_core) - { - mali_pp_delete(group->pp_core); - } - - if (NULL != group->mmu) - { - mali_mmu_delete(group->mmu); - } - - for (i = 0; i < mali_global_num_groups; i++) - { - if (mali_global_groups[i] == group) - { - mali_global_groups[i] = NULL; - mali_global_num_groups--; - break; - } - } - - _mali_osk_lock_term(group->lock); - - _mali_osk_free(group); -} - -/* Called from mali_cluster_reset() when the system is re-turned on */ -void mali_group_reset(struct mali_group *group) -{ - mali_group_lock(group); - - group->session = NULL; - - if (NULL != group->mmu) - { - mali_mmu_reset(group->mmu); - } - - if (NULL != group->gp_core) - { - mali_gp_reset(group->gp_core); - } - - if (NULL != group->pp_core) - { - mali_pp_reset(group->pp_core); - } - - mali_group_unlock(group); -} - -struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group) -{ - return group->gp_core; -} - -struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group) -{ - return group->pp_core; -} - -_mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job) -{ - struct mali_session_data *session; - enum mali_group_activate_pd_status activate_status; - - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); - - mali_pm_core_event(MALI_CORE_EVENT_GP_START); - - session = mali_gp_job_get_session(job); - - mali_group_lock(group); - - mali_cluster_l2_cache_invalidate_all(group->cluster, mali_gp_job_get_id(job)); - - activate_status = mali_group_activate_page_directory(group, session); - if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) - { - /* if session is NOT kept Zapping is done as part of session switch */ - if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) - { - mali_mmu_zap_tlb_without_stall(group->mmu); - } - mali_gp_job_start(group->gp_core, job); - group->gp_running_job = job; - group->gp_state = MALI_GROUP_CORE_STATE_WORKING; - - mali_group_unlock(group); - - return _MALI_OSK_ERR_OK; - } - -#if defined(USING_MALI200) - group->pagedir_activation_failed = MALI_TRUE; -#endif - - mali_group_unlock(group); - - mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_GP_START */ - return _MALI_OSK_ERR_FAULT; -} - -_mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job) -{ - struct mali_session_data *session; - enum mali_group_activate_pd_status activate_status; - - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); - - mali_pm_core_event(MALI_CORE_EVENT_PP_START); - - session = mali_pp_job_get_session(job); - - mali_group_lock(group); - - mali_cluster_l2_cache_invalidate_all(group->cluster, mali_pp_job_get_id(job)); - - activate_status = mali_group_activate_page_directory(group, session); - if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) - { - /* if session is NOT kept Zapping is done as part of session switch */ - if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) - { - MALI_DEBUG_PRINT(3, ("PP starting job PD_Switch 0 Flush 1 Zap 1\n")); - mali_mmu_zap_tlb_without_stall(group->mmu); - } - mali_pp_job_start(group->pp_core, job, sub_job); - group->pp_running_job = job; - group->pp_running_sub_job = sub_job; - group->pp_state = MALI_GROUP_CORE_STATE_WORKING; - - mali_group_unlock(group); - - return _MALI_OSK_ERR_OK; - } - -#if defined(USING_MALI200) - group->pagedir_activation_failed = MALI_TRUE; -#endif - - mali_group_unlock(group); - - mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_PP_START */ - return _MALI_OSK_ERR_FAULT; -} - -void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr) -{ - mali_group_lock(group); - - if (group->gp_state != MALI_GROUP_CORE_STATE_OOM || - mali_gp_job_get_id(group->gp_running_job) != job_id) - { - mali_group_unlock(group); - return; /* Illegal request or job has already been aborted */ - } - - mali_cluster_l2_cache_invalidate_all_force(group->cluster); - mali_mmu_zap_tlb_without_stall(group->mmu); - - mali_gp_resume_with_new_heap(group->gp_core, start_addr, end_addr); - group->gp_state = MALI_GROUP_CORE_STATE_WORKING; - - mali_group_unlock(group); -} - -void mali_group_abort_gp_job(struct mali_group *group, u32 job_id) -{ - mali_group_lock(group); - - if (group->gp_state == MALI_GROUP_CORE_STATE_IDLE || - mali_gp_job_get_id(group->gp_running_job) != job_id) - { - mali_group_unlock(group); - return; /* No need to cancel or job has already been aborted or completed */ - } - - mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* Will release group lock */ -} - -void mali_group_abort_pp_job(struct mali_group *group, u32 job_id) -{ - mali_group_lock(group); - - if (group->pp_state == MALI_GROUP_CORE_STATE_IDLE || - mali_pp_job_get_id(group->pp_running_job) != job_id) - { - mali_group_unlock(group); - return; /* No need to cancel or job has already been aborted or completed */ - } - - mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* Will release group lock */ -} - -void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session) -{ - struct mali_gp_job *gp_job; - struct mali_pp_job *pp_job; - u32 gp_job_id = 0; - u32 pp_job_id = 0; - mali_bool abort_pp = MALI_FALSE; - mali_bool abort_gp = MALI_FALSE; - - mali_group_lock(group); - - gp_job = group->gp_running_job; - pp_job = group->pp_running_job; - - if (gp_job && mali_gp_job_get_session(gp_job) == session) - { - MALI_DEBUG_PRINT(4, ("Aborting GP job 0x%08x from session 0x%08x\n", gp_job, session)); - - gp_job_id = mali_gp_job_get_id(gp_job); - abort_gp = MALI_TRUE; - } - - if (pp_job && mali_pp_job_get_session(pp_job) == session) - { - MALI_DEBUG_PRINT(4, ("Mali group: Aborting PP job 0x%08x from session 0x%08x\n", pp_job, session)); - - pp_job_id = mali_pp_job_get_id(pp_job); - abort_pp = MALI_TRUE; - } - - mali_group_unlock(group); - - /* These functions takes and releases the group lock */ - if (0 != abort_gp) - { - mali_group_abort_gp_job(group, gp_job_id); - } - if (0 != abort_pp) - { - mali_group_abort_pp_job(group, pp_job_id); - } - - mali_group_lock(group); - mali_group_remove_session_if_unused(group, session); - mali_group_unlock(group); -} - -enum mali_group_core_state mali_group_gp_state(struct mali_group *group) -{ - return group->gp_state; -} - -enum mali_group_core_state mali_group_pp_state(struct mali_group *group) -{ - return group->pp_state; -} - -/* group lock need to be taken before calling mali_group_bottom_half */ -void mali_group_bottom_half(struct mali_group *group, enum mali_group_event_t event) -{ - MALI_ASSERT_GROUP_LOCKED(group); - - switch (event) - { - case GROUP_EVENT_PP_JOB_COMPLETED: - mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_TRUE); /* PP job SUCCESS */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_PP_JOB_FAILED: - mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* PP job FAIL */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_PP_JOB_TIMED_OUT: - mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* PP job TIMEOUT */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_GP_JOB_COMPLETED: - mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_TRUE); /* GP job SUCCESS */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_GP_JOB_FAILED: - mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* GP job FAIL */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_GP_JOB_TIMED_OUT: - mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* GP job TIMEOUT */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_GP_OOM: - group->gp_state = MALI_GROUP_CORE_STATE_OOM; - mali_group_unlock(group); /* Nothing to do on the HW side, so just release group lock right away */ - mali_gp_scheduler_oom(group, group->gp_running_job); - break; - case GROUP_EVENT_MMU_PAGE_FAULT: - mali_group_complete_jobs(group, MALI_TRUE, MALI_TRUE, MALI_FALSE); /* GP and PP job FAIL */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - default: - break; - } -} - -struct mali_mmu_core *mali_group_get_mmu(struct mali_group *group) -{ - return group->mmu; -} - -struct mali_session_data *mali_group_get_session(struct mali_group *group) -{ - return group->session; -} - -struct mali_group *mali_group_get_glob_group(u32 index) -{ - if(mali_global_num_groups > index) - { - return mali_global_groups[index]; - } - - return NULL; -} - -u32 mali_group_get_glob_num_groups(void) -{ - return mali_global_num_groups; -} - -/* Used to check if scheduler for the other core type needs to be called on job completion. - * - * Used only for Mali-200, where job start may fail if the only MMU is busy - * with another session's address space. - */ -static inline mali_bool mali_group_other_reschedule_needed(struct mali_group *group) -{ - MALI_ASSERT_GROUP_LOCKED(group); - -#if defined(USING_MALI200) - if (group->pagedir_activation_failed) - { - group->pagedir_activation_failed = MALI_FALSE; - return MALI_TRUE; - } - else -#endif - { - return MALI_FALSE; - } -} - -static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session) -{ - enum mali_group_activate_pd_status retval; - MALI_ASSERT_GROUP_LOCKED(group); - - MALI_DEBUG_PRINT(5, ("Mali group: Activating page directory 0x%08X from session 0x%08X on group 0x%08X\n", mali_session_get_page_directory(session), session, group)); - MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count); - - if (0 != group->page_dir_ref_count) - { - if (group->session != session) - { - MALI_DEBUG_PRINT(4, ("Mali group: Activating session FAILED: 0x%08x on group 0x%08X. Existing session: 0x%08x\n", session, group, group->session)); - return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED; - } - else - { - MALI_DEBUG_PRINT(4, ("Mali group: Activating session already activated: 0x%08x on group 0x%08X. New Ref: %d\n", session, group, 1+group->page_dir_ref_count)); - retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD; - - } - } - else - { - /* There might be another session here, but it is ok to overwrite it since group->page_dir_ref_count==0 */ - if (group->session != session) - { - mali_bool activate_success; - MALI_DEBUG_PRINT(5, ("Mali group: Activate session: %08x previous: %08x on group 0x%08X. Ref: %d\n", session, group->session, group, 1+group->page_dir_ref_count)); - - activate_success = mali_mmu_activate_page_directory(group->mmu, mali_session_get_page_directory(session)); - MALI_DEBUG_ASSERT(activate_success); - if ( MALI_FALSE== activate_success ) return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED; - group->session = session; - retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD; - } - else - { - MALI_DEBUG_PRINT(4, ("Mali group: Activate existing session 0x%08X on group 0x%08X. Ref: %d\n", session->page_directory, group, 1+group->page_dir_ref_count)); - retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD; - } - } - - group->page_dir_ref_count++; - return retval; -} - -static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session) -{ - MALI_ASSERT_GROUP_LOCKED(group); - - MALI_DEBUG_ASSERT(0 < group->page_dir_ref_count); - MALI_DEBUG_ASSERT(session == group->session); - - group->page_dir_ref_count--; - - /* As an optimization, the MMU still points to the group->session even if (0 == group->page_dir_ref_count), - and we do not call mali_mmu_activate_empty_page_directory(group->mmu); */ - MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count); -} - -void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session) -{ - MALI_ASSERT_GROUP_LOCKED(group); - - if (0 == group->page_dir_ref_count) - { - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); - - if (group->session == session) - { - MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on); - MALI_DEBUG_PRINT(3, ("Mali group: Deactivating unused session 0x%08X on group %08X\n", session, group)); - mali_mmu_activate_empty_page_directory(group->mmu); - group->session = NULL; - } - } -} - -void mali_group_power_on(void) -{ - int i; - for (i = 0; i < mali_global_num_groups; i++) - { - struct mali_group *group = mali_global_groups[i]; - mali_group_lock(group); - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); - MALI_DEBUG_ASSERT_POINTER(group->cluster); - group->power_is_on = MALI_TRUE; - mali_cluster_power_is_enabled_set(group->cluster, MALI_TRUE); - mali_group_unlock(group); - } - MALI_DEBUG_PRINT(3,("group: POWER ON\n")); -} - -mali_bool mali_group_power_is_on(struct mali_group *group) -{ - MALI_ASSERT_GROUP_LOCKED(group); - return group->power_is_on; -} - -void mali_group_power_off(void) -{ - int i; - /* It is necessary to set group->session = NULL; so that the powered off MMU is not written to on map /unmap */ - /* It is necessary to set group->power_is_on=MALI_FALSE so that pending bottom_halves does not access powered off cores. */ - for (i = 0; i < mali_global_num_groups; i++) - { - struct mali_group *group = mali_global_groups[i]; - mali_group_lock(group); - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); - MALI_DEBUG_ASSERT_POINTER(group->cluster); - group->session = NULL; - MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on); - group->power_is_on = MALI_FALSE; - mali_cluster_power_is_enabled_set(group->cluster, MALI_FALSE); - mali_group_unlock(group); - } - MALI_DEBUG_PRINT(3,("group: POWER OFF\n")); -} - - -static void mali_group_recovery_reset(struct mali_group *group) -{ - MALI_ASSERT_GROUP_LOCKED(group); - - /* Stop cores, bus stop */ - if (NULL != group->pp_core) - { - mali_pp_stop_bus(group->pp_core); - } - if (NULL != group->gp_core) - { - mali_gp_stop_bus(group->gp_core); - } - - /* Flush MMU */ - mali_mmu_activate_fault_flush_page_directory(group->mmu); - mali_mmu_page_fault_done(group->mmu); - - /* Wait for cores to stop bus */ - if (NULL != group->pp_core) - { - mali_pp_stop_bus_wait(group->pp_core); - } - if (NULL != group->gp_core) - { - mali_gp_stop_bus_wait(group->gp_core); - } - - /* Reset cores */ - if (NULL != group->pp_core) - { - mali_pp_hard_reset(group->pp_core); - } - if (NULL != group->gp_core) - { - mali_gp_hard_reset(group->gp_core); - } - - /* Reset MMU */ - mali_mmu_reset(group->mmu); - group->session = NULL; -} - -/* Group lock need to be taken before calling mali_group_complete_jobs. Will release the lock here. */ -static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success) -{ - mali_bool need_group_reset = MALI_FALSE; - mali_bool gp_success = success; - mali_bool pp_success = success; - - MALI_ASSERT_GROUP_LOCKED(group); - - if (complete_gp && !complete_pp) - { - MALI_DEBUG_ASSERT_POINTER(group->gp_core); - if (_MALI_OSK_ERR_OK == mali_gp_reset(group->gp_core)) - { - struct mali_gp_job *gp_job_to_return = group->gp_running_job; - group->gp_state = MALI_GROUP_CORE_STATE_IDLE; - group->gp_running_job = NULL; - - MALI_DEBUG_ASSERT_POINTER(gp_job_to_return); - - mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return)); - - if(mali_group_other_reschedule_needed(group)) - { - mali_group_unlock(group); - mali_pp_scheduler_do_schedule(); - } - else - { - mali_group_unlock(group); - } - - mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success); - mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ - - return; - } - else - { - need_group_reset = MALI_TRUE; - MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset GP, need to reset entire group\n")); - pp_success = MALI_FALSE; /* This might kill PP as well, so this should fail */ - } - } - if (complete_pp && !complete_gp) - { - MALI_DEBUG_ASSERT_POINTER(group->pp_core); - if (_MALI_OSK_ERR_OK == mali_pp_reset(group->pp_core)) - { - struct mali_pp_job *pp_job_to_return = group->pp_running_job; - u32 pp_sub_job_to_return = group->pp_running_sub_job; - group->pp_state = MALI_GROUP_CORE_STATE_IDLE; - group->pp_running_job = NULL; - - MALI_DEBUG_ASSERT_POINTER(pp_job_to_return); - - mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return)); - - if(mali_group_other_reschedule_needed(group)) - { - mali_group_unlock(group); - mali_gp_scheduler_do_schedule(); - } - else - { - mali_group_unlock(group); - } - - mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success); - mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ - - return; - } - else - { - need_group_reset = MALI_TRUE; - MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n")); - gp_success = MALI_FALSE; /* This might kill GP as well, so this should fail */ - } - } - else if (complete_gp && complete_pp) - { - need_group_reset = MALI_TRUE; - } - - if (MALI_TRUE == need_group_reset) - { - struct mali_gp_job *gp_job_to_return = group->gp_running_job; - struct mali_pp_job *pp_job_to_return = group->pp_running_job; - u32 pp_sub_job_to_return = group->pp_running_sub_job; - mali_bool schedule_other = MALI_FALSE; - - MALI_DEBUG_PRINT(3, ("Mali group: Resetting entire group\n")); - - group->gp_state = MALI_GROUP_CORE_STATE_IDLE; - group->gp_running_job = NULL; - if (NULL != gp_job_to_return) - { - mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return)); - } - - group->pp_state = MALI_GROUP_CORE_STATE_IDLE; - group->pp_running_job = NULL; - if (NULL != pp_job_to_return) - { - mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return)); - } - - /* The reset has to be done after mali_group_deactivate_page_directory() */ - mali_group_recovery_reset(group); - - if (mali_group_other_reschedule_needed(group) && (NULL == gp_job_to_return || NULL == pp_job_to_return)) - { - schedule_other = MALI_TRUE; - } - - mali_group_unlock(group); - - if (NULL != gp_job_to_return) - { - mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success); - mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ - } - else if (schedule_other) - { - mali_pp_scheduler_do_schedule(); - } - - if (NULL != pp_job_to_return) - { - mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success); - mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ - } - else if (schedule_other) - { - mali_gp_scheduler_do_schedule(); - } - - return; - } - - mali_group_unlock(group); -} - -#if MALI_STATE_TRACKING -u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size) -{ - int n = 0; - - n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group); - if (group->gp_core) - { - n += mali_gp_dump_state(group->gp_core, buf + n, size - n); - n += _mali_osk_snprintf(buf + n, size - n, "\tGP state: %d\n", group->gp_state); - n += _mali_osk_snprintf(buf + n, size - n, "\tGP job: %p\n", group->gp_running_job); - } - if (group->pp_core) - { - n += mali_pp_dump_state(group->pp_core, buf + n, size - n); - n += _mali_osk_snprintf(buf + n, size - n, "\tPP state: %d\n", group->pp_state); - n += _mali_osk_snprintf(buf + n, size - n, "\tPP job: %p, subjob %d \n", - group->pp_running_job, group->pp_running_sub_job); - } - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_group.h b/drivers/media/video/samsung/mali/common/mali_group.h deleted file mode 100644 index 3533d13..0000000 --- a/drivers/media/video/samsung/mali/common/mali_group.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_GROUP_H__ -#define __MALI_GROUP_H__ - -#include "linux/jiffies.h" -#include "mali_osk.h" -#include "mali_cluster.h" -#include "mali_mmu.h" -#include "mali_gp.h" -#include "mali_pp.h" -#include "mali_session.h" - -/* max runtime [ms] for a core job - used by timeout timers */ -#define MAX_RUNTIME 5000 -/** @brief A mali group object represents a MMU and a PP and/or a GP core. - * - */ -#define MALI_MAX_NUMBER_OF_GROUPS 9 - -struct mali_group; - -enum mali_group_event_t -{ - GROUP_EVENT_PP_JOB_COMPLETED, /**< PP job completed successfully */ - GROUP_EVENT_PP_JOB_FAILED, /**< PP job completed with failure */ - GROUP_EVENT_PP_JOB_TIMED_OUT, /**< PP job reached max runtime */ - GROUP_EVENT_GP_JOB_COMPLETED, /**< GP job completed successfully */ - GROUP_EVENT_GP_JOB_FAILED, /**< GP job completed with failure */ - GROUP_EVENT_GP_JOB_TIMED_OUT, /**< GP job reached max runtime */ - GROUP_EVENT_GP_OOM, /**< GP job ran out of heap memory */ - GROUP_EVENT_MMU_PAGE_FAULT, /**< MMU page fault */ -}; - -enum mali_group_core_state -{ - MALI_GROUP_CORE_STATE_IDLE, - MALI_GROUP_CORE_STATE_WORKING, - MALI_GROUP_CORE_STATE_OOM -}; - -/** @brief Create a new Mali group object - * - * @param cluster Pointer to the cluster to which the group is connected. - * @param mmu Pointer to the MMU that defines this group - * @return A pointer to a new group object - */ -struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_mmu_core *mmu); -void mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core); -void mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core); -void mali_group_delete(struct mali_group *group); - -/** @brief Reset group - * - * This function will reset the entire group, including all the cores present in the group. - * - * @param group Pointer to the group to reset - */ -void mali_group_reset(struct mali_group *group); - -/** @brief Get pointer to GP core object - */ -struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group); - -/** @brief Get pointer to PP core object - */ -struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group); - -/** @brief Lock group object - * - * Most group functions will lock the group object themselves. The expection is - * the group_bottom_half which requires the group to be locked on entry. - * - * @param group Pointer to group to lock - */ -void mali_group_lock(struct mali_group *group); - -/** @brief Unlock group object - * - * @param group Pointer to group to unlock - */ -void mali_group_unlock(struct mali_group *group); -#ifdef DEBUG -void mali_group_assert_locked(struct mali_group *group); -#define MALI_ASSERT_GROUP_LOCKED(group) mali_group_assert_locked(group) -#else -#define MALI_ASSERT_GROUP_LOCKED(group) -#endif - -/** @brief Start GP job - */ -_mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job); -/** @brief Start fragment of PP job - */ -_mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job); - -/** @brief Resume GP job that suspended waiting for more heap memory - */ -void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr); -/** @brief Abort GP job - * - * Used to abort suspended OOM jobs when user space failed to allocte more memory. - */ -void mali_group_abort_gp_job(struct mali_group *group, u32 job_id); -/** @brief Abort all GP jobs from \a session - * - * Used on session close when terminating all running and queued jobs from \a session. - */ -void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session); - -enum mali_group_core_state mali_group_gp_state(struct mali_group *group); -enum mali_group_core_state mali_group_pp_state(struct mali_group *group); - -/** @brief The common group bottom half interrupt handler - * - * This is only called from the GP and PP bottom halves. - * - * The action taken is dictated by the \a event. - * - * @param event The event code - */ -void mali_group_bottom_half(struct mali_group *group, enum mali_group_event_t event); - -struct mali_mmu_core *mali_group_get_mmu(struct mali_group *group); -struct mali_session_data *mali_group_get_session(struct mali_group *group); - -void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session_data); - -void mali_group_power_on(void); -void mali_group_power_off(void); -mali_bool mali_group_power_is_on(struct mali_group *group); - -struct mali_group *mali_group_get_glob_group(u32 index); -u32 mali_group_get_glob_num_groups(void); - -u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size); - -#endif /* __MALI_GROUP_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_hw_core.c b/drivers/media/video/samsung/mali/common/mali_hw_core.c deleted file mode 100644 index 0b08622..0000000 --- a/drivers/media/video/samsung/mali/common/mali_hw_core.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_hw_core.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" - -_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size) -{ - core->phys_addr = resource->base; - core->description = resource->description; - core->size = reg_size; - if (_MALI_OSK_ERR_OK == _mali_osk_mem_reqregion(core->phys_addr, core->size, core->description)) - { - core->mapped_registers = _mali_osk_mem_mapioregion(core->phys_addr, core->size, core->description); - if (NULL != core->mapped_registers) - { - return _MALI_OSK_ERR_OK; - } - else - { - MALI_PRINT_ERROR(("Failed to map memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr)); - } - _mali_osk_mem_unreqregion(core->phys_addr, core->size); - } - else - { - MALI_PRINT_ERROR(("Failed to request memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr)); - } - - return _MALI_OSK_ERR_FAULT; -} - -void mali_hw_core_delete(struct mali_hw_core *core) -{ - _mali_osk_mem_unmapioregion(core->phys_addr, core->size, core->mapped_registers); - core->mapped_registers = NULL; - _mali_osk_mem_unreqregion(core->phys_addr, core->size); -} diff --git a/drivers/media/video/samsung/mali/common/mali_hw_core.h b/drivers/media/video/samsung/mali/common/mali_hw_core.h deleted file mode 100644 index c797804..0000000 --- a/drivers/media/video/samsung/mali/common/mali_hw_core.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_HW_CORE_H__ -#define __MALI_HW_CORE_H__ - -#include "mali_osk.h" -#include "mali_kernel_common.h" - -/** - * The common parts for all Mali HW cores (GP, PP, MMU, L2 and PMU) - * This struct is embedded inside all core specific structs. - */ -struct mali_hw_core -{ - u32 phys_addr; /**< Physical address of the registers */ - u32 size; /**< Size of registers */ - mali_io_address mapped_registers; /**< Virtual mapping of the registers */ - const char* description; /**< Name of unit (as specified in device configuration) */ -}; - -#define MALI_HW_CORE_NO_COUNTER ((u32)-1) -#define MALI_HW_CORE_INVALID_VALUE ((u32)-1) - -_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size); -void mali_hw_core_delete(struct mali_hw_core *core); - -MALI_STATIC_INLINE u32 mali_hw_core_register_read(struct mali_hw_core *core, u32 relative_address) -{ - u32 read_val; - read_val = _mali_osk_mem_ioread32(core->mapped_registers, relative_address); - MALI_DEBUG_PRINT(6, ("register_read for core %s, relative addr=0x%04X, val=0x%08X\n", - core->description, relative_address, read_val)); - return read_val; -} - -MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed(struct mali_hw_core *core, u32 relative_address, u32 new_val) -{ - MALI_DEBUG_PRINT(6, ("register_write_relaxed for core %s, relative addr=0x%04X, val=0x%08X\n", - core->description, relative_address, new_val)); - _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val); -} - -MALI_STATIC_INLINE void mali_hw_core_register_write(struct mali_hw_core *core, u32 relative_address, u32 new_val) -{ - MALI_DEBUG_PRINT(6, ("register_write for core %s, relative addr=0x%04X, val=0x%08X\n", - core->description, relative_address, new_val)); - _mali_osk_mem_iowrite32(core->mapped_registers, relative_address, new_val); -} - -MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed(struct mali_hw_core *core, u32 relative_address, u32 *write_array, u32 nr_of_regs) -{ - u32 i; - MALI_DEBUG_PRINT(6, ("register_write_array: for core %s, relative addr=0x%04X, nr of regs=%u\n", - core->description,relative_address, nr_of_regs)); - - /* Do not use burst writes against the registers */ - for (i = 0; i< nr_of_regs; i++) - { - mali_hw_core_register_write_relaxed(core, relative_address + i*4, write_array[i]); - } -} - -#endif /* __MALI_HW_CORE_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_common.h b/drivers/media/video/samsung/mali/common/mali_kernel_common.h deleted file mode 100644 index b354f92..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_common.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_KERNEL_COMMON_H__ -#define __MALI_KERNEL_COMMON_H__ - -/* Make sure debug is defined when it should be */ -#ifndef DEBUG - #if defined(_DEBUG) - #define DEBUG - #endif -#endif - -/* Macro for generating a kernel panic. - * Turned on off by compile-time Makefile settings - */ -#if defined(USING_KERNEL_PANIC) -#include - #define MALI_PANIC(fmt, args...) panic( fmt, ## args ); -#else - #define MALI_PANIC(fmt, args...) -#endif - -/* The file include several useful macros for error checking, debugging and printing. - * - MALI_PRINTF(...) Do not use this function: Will be included in Release builds. - * - MALI_DEBUG_PRINT(nr, (X) ) Prints the second argument if nr<=MALI_DEBUG_LEVEL. - * - MALI_DEBUG_ERROR( (X) ) Prints an errortext, a source trace, and the given error message. - * - MALI_DEBUG_ASSERT(exp,(X)) If the asserted expr is false, the program will exit. - * - MALI_DEBUG_ASSERT_POINTER(pointer) Triggers if the pointer is a zero pointer. - * - MALI_DEBUG_CODE( X ) The code inside the macro is only compiled in Debug builds. - * - * The (X) means that you must add an extra parenthesis around the argumentlist. - * - * The printf function: MALI_PRINTF(...) is routed to _mali_osk_debugmsg - * - * Suggested range for the DEBUG-LEVEL is [1:6] where - * [1:2] Is messages with highest priority, indicate possible errors. - * [3:4] Is messages with medium priority, output important variables. - * [5:6] Is messages with low priority, used during extensive debugging. - */ - - /** - * Fundamental error macro. Reports an error code. This is abstracted to allow us to - * easily switch to a different error reporting method if we want, and also to allow - * us to search for error returns easily. - * - * Note no closing semicolon - this is supplied in typical usage: - * - * MALI_ERROR(MALI_ERROR_OUT_OF_MEMORY); - */ -#define MALI_ERROR(error_code) return (error_code) - -/** - * Basic error macro, to indicate success. - * Note no closing semicolon - this is supplied in typical usage: - * - * MALI_SUCCESS; - */ -#define MALI_SUCCESS MALI_ERROR(_MALI_OSK_ERR_OK) - -/** - * Basic error macro. This checks whether the given condition is true, and if not returns - * from this function with the supplied error code. This is a macro so that we can override it - * for stress testing. - * - * Note that this uses the do-while-0 wrapping to ensure that we don't get problems with dangling - * else clauses. Note also no closing semicolon - this is supplied in typical usage: - * - * MALI_CHECK((p!=NULL), ERROR_NO_OBJECT); - */ -#define MALI_CHECK(condition, error_code) do { if(!(condition)) MALI_ERROR(error_code); } while(0) - -/** - * Error propagation macro. If the expression given is anything other than _MALI_OSK_NO_ERROR, - * then the value is returned from the enclosing function as an error code. This effectively - * acts as a guard clause, and propagates error values up the call stack. This uses a - * temporary value to ensure that the error expression is not evaluated twice. - * If the counter for forcing a failure has been set using _mali_force_error, this error will be - * returned without evaluating the expression in MALI_CHECK_NO_ERROR - */ -#define MALI_CHECK_NO_ERROR(expression) \ - do { _mali_osk_errcode_t _check_no_error_result=(expression); \ - if(_check_no_error_result != _MALI_OSK_ERR_OK) \ - MALI_ERROR(_check_no_error_result); \ - } while(0) - -/** - * Pointer check macro. Checks non-null pointer. - */ -#define MALI_CHECK_NON_NULL(pointer, error_code) MALI_CHECK( ((pointer)!=NULL), (error_code) ) - -/** - * Error macro with goto. This checks whether the given condition is true, and if not jumps - * to the specified label using a goto. The label must therefore be local to the function in - * which this macro appears. This is most usually used to execute some clean-up code before - * exiting with a call to ERROR. - * - * Like the other macros, this is a macro to allow us to override the condition if we wish, - * e.g. to force an error during stress testing. - */ -#define MALI_CHECK_GOTO(condition, label) do { if(!(condition)) goto label; } while(0) - -/** - * Explicitly ignore a parameter passed into a function, to suppress compiler warnings. - * Should only be used with parameter names. - */ -#define MALI_IGNORE(x) x=x - -#define MALI_PRINTF(args) _mali_osk_dbgmsg args; - -#define MALI_PRINT_ERROR(args) do{ \ - MALI_PRINTF(("Mali: ERR: %s\n" ,__FILE__)); \ - MALI_PRINTF((" %s()%4d\n ", __FUNCTION__, __LINE__)) ; \ - MALI_PRINTF(args); \ - MALI_PRINTF(("\n")); \ - } while(0) - -#define MALI_PRINT(args) do{ \ - MALI_PRINTF(("Mali: ")); \ - MALI_PRINTF(args); \ - } while (0) - -#ifdef DEBUG -#ifndef mali_debug_level -extern int mali_debug_level; -#endif - -#define MALI_DEBUG_CODE(code) code -#define MALI_DEBUG_PRINT(level, args) do { \ - if((level) <= mali_debug_level)\ - {MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); } \ - } while (0) - -#define MALI_DEBUG_PRINT_ERROR(args) MALI_PRINT_ERROR(args) - -#define MALI_DEBUG_PRINT_IF(level,condition,args) \ - if((condition)&&((level) <= mali_debug_level))\ - {MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); } - -#define MALI_DEBUG_PRINT_ELSE(level, args)\ - else if((level) <= mali_debug_level)\ - { MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); } - -/** - * @note these variants of DEBUG ASSERTS will cause a debugger breakpoint - * to be entered (see _mali_osk_break() ). An alternative would be to call - * _mali_osk_abort(), on OSs that support it. - */ -#define MALI_DEBUG_PRINT_ASSERT(condition, args) do {if( !(condition)) { MALI_PRINT_ERROR(args); _mali_osk_break(); } } while(0) -#define MALI_DEBUG_ASSERT_POINTER(pointer) do {if( (pointer)== NULL) {MALI_PRINT_ERROR(("NULL pointer " #pointer)); _mali_osk_break();} } while(0) -#define MALI_DEBUG_ASSERT(condition) do {if( !(condition)) {MALI_PRINT_ERROR(("ASSERT failed: " #condition )); _mali_osk_break();} } while(0) - -#else /* DEBUG */ - -#define MALI_DEBUG_CODE(code) -#define MALI_DEBUG_PRINT(string,args) do {} while(0) -#define MALI_DEBUG_PRINT_ERROR(args) do {} while(0) -#define MALI_DEBUG_PRINT_IF(level,condition,args) do {} while(0) -#define MALI_DEBUG_PRINT_ELSE(level,condition,args) do {} while(0) -#define MALI_DEBUG_PRINT_ASSERT(condition,args) do {} while(0) -#define MALI_DEBUG_ASSERT_POINTER(pointer) do {} while(0) -#define MALI_DEBUG_ASSERT(condition) do {} while(0) - -#endif /* DEBUG */ - -/** - * variables from user space cannot be dereferenced from kernel space; tagging them - * with __user allows the GCC compiler to generate a warning. Other compilers may - * not support this so we define it here as an empty macro if the compiler doesn't - * define it. - */ -#ifndef __user -#define __user -#endif - -#endif /* __MALI_KERNEL_COMMON_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.c b/drivers/media/video/samsung/mali/common/mali_kernel_core.c deleted file mode 100644 index 45e86d2..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_core.c +++ /dev/null @@ -1,980 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_osk.h" -#include "mali_osk_mali.h" -#include "mali_ukk.h" -#include "mali_kernel_core.h" -#include "mali_memory.h" -#include "mali_mem_validation.h" -#include "mali_mmu.h" -#include "mali_mmu_page_directory.h" -#include "mali_dlbu.h" -#include "mali_gp.h" -#include "mali_pp.h" -#include "mali_gp_scheduler.h" -#include "mali_pp_scheduler.h" -#include "mali_cluster.h" -#include "mali_group.h" -#include "mali_pm.h" -#include "mali_pmu.h" -#include "mali_scheduler.h" -#ifdef CONFIG_MALI400_GPU_UTILIZATION -#include "mali_kernel_utilization.h" -#endif -#include "mali_l2_cache.h" -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_osk_profiling.h" -#endif - -/** Pointer to table of resource definitions available to the Mali driver. - * _mali_osk_resources_init() sets up the pointer to this table. - */ -static _mali_osk_resource_t *arch_configuration = NULL; - -/** Start profiling from module load? */ -int mali_boot_profiling = 0; - -/** Number of resources initialized by _mali_osk_resources_init() */ -static u32 num_resources; - -static _mali_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN; -static u32 global_gpu_base_address = 0; -static u32 global_gpu_major_version = 0; -static u32 global_gpu_minor_version = 0; - -static u32 first_pp_offset = 0; - -#define HANG_CHECK_MSECS_DEFAULT 500 /* 500 ms */ -#define WATCHDOG_MSECS_DEFAULT 4000 /* 4 s */ - -/* timer related */ -int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT; -int mali_hang_check_interval = HANG_CHECK_MSECS_DEFAULT; - -static _mali_osk_resource_t *mali_find_resource(_mali_osk_resource_type_t type, u32 offset) -{ - int i; - u32 addr = global_gpu_base_address + offset; - - for (i = 0; i < num_resources; i++) - { - if (type == arch_configuration[i].type && arch_configuration[i].base == addr) - { - return &(arch_configuration[i]); - } - } - - return NULL; -} - -static u32 mali_count_resources(_mali_osk_resource_type_t type) -{ - int i; - u32 retval = 0; - - for (i = 0; i < num_resources; i++) - { - if (type == arch_configuration[i].type) - { - retval++; - } - } - - return retval; -} - - -static _mali_osk_errcode_t mali_parse_gpu_base_and_first_pp_offset_address(void) -{ - int i; - _mali_osk_resource_t *first_gp_resource = NULL; - _mali_osk_resource_t *first_pp_resource = NULL; - - for (i = 0; i < num_resources; i++) - { - if (MALI_GP == arch_configuration[i].type) - { - if (NULL == first_gp_resource || first_gp_resource->base > arch_configuration[i].base) - { - first_gp_resource = &(arch_configuration[i]); - } - } - if (MALI_PP == arch_configuration[i].type) - { - if (NULL == first_pp_resource || first_pp_resource->base > arch_configuration[i].base) - { - first_pp_resource = &(arch_configuration[i]); - } - } - } - - if (NULL == first_gp_resource || NULL == first_pp_resource) - { - MALI_PRINT_ERROR(("No GP+PP core specified in config file\n")); - return _MALI_OSK_ERR_FAULT; - } - - if (first_gp_resource->base < first_pp_resource->base) - { - /* GP is first, so we are dealing with Mali-300, Mali-400 or Mali-450 */ - global_gpu_base_address = first_gp_resource->base; - first_pp_offset = 0x8000; - } - else - { - /* PP is first, so we are dealing with Mali-200 */ - global_gpu_base_address = first_pp_resource->base; - first_pp_offset = 0x0; - } - MALI_SUCCESS; -} - -static _mali_osk_errcode_t mali_parse_product_info(void) -{ - _mali_osk_resource_t *first_pp_resource = NULL; - - /* Find the first PP core */ - first_pp_resource = mali_find_resource(MALI_PP, first_pp_offset); - if (NULL != first_pp_resource) - { - /* Create a dummy PP object for this core so that we can read the version register */ - struct mali_group *group = mali_group_create(NULL, NULL); - if (NULL != group) - { - /*struct mali_pp_core *pp_core = mali_pp_create(first_pp_resource, group, 0);*/ - struct mali_pp_core *pp_core = mali_pp_create(first_pp_resource, group); - if (NULL != pp_core) - { - u32 pp_version = mali_pp_core_get_version(pp_core); - mali_pp_delete(pp_core); - mali_group_delete(group); - - global_gpu_major_version = (pp_version >> 8) & 0xFF; - global_gpu_minor_version = pp_version & 0xFF; - - switch (pp_version >> 16) - { - case MALI200_PP_PRODUCT_ID: - global_product_id = _MALI_PRODUCT_ID_MALI200; - MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-200 r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); - break; - case MALI300_PP_PRODUCT_ID: - global_product_id = _MALI_PRODUCT_ID_MALI300; - MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-300 r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); - break; - case MALI400_PP_PRODUCT_ID: - global_product_id = _MALI_PRODUCT_ID_MALI400; - MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-400 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); - break; - case MALI450_PP_PRODUCT_ID: - global_product_id = _MALI_PRODUCT_ID_MALI450; - MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-450 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); - break; - default: - MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version)); - return _MALI_OSK_ERR_FAULT; - } - - return _MALI_OSK_ERR_OK; - } - else - { - MALI_PRINT_ERROR(("Failed to create initial PP object\n")); - } - } - else - { - MALI_PRINT_ERROR(("Failed to create initial group object\n")); - } - } - else - { - MALI_PRINT_ERROR(("First PP core not specified in config file\n")); - } - - return _MALI_OSK_ERR_FAULT; -} - -static void mali_delete_clusters(void) -{ - u32 i; - u32 number_of_clusters = mali_cluster_get_glob_num_clusters(); - - for (i = 0; i < number_of_clusters; i++) - { - mali_cluster_delete(mali_cluster_get_global_cluster(i)); - } -} - -static _mali_osk_errcode_t mali_create_cluster(_mali_osk_resource_t *resource) -{ - if (NULL != resource) - { - struct mali_l2_cache_core *l2_cache; - - if (mali_l2_cache_core_get_glob_num_l2_cores() >= mali_l2_cache_core_get_max_num_l2_cores()) - { - MALI_PRINT_ERROR(("Found too many L2 cache core objects, max %u is supported\n", mali_l2_cache_core_get_max_num_l2_cores())); - return _MALI_OSK_ERR_FAULT; - } - - MALI_DEBUG_PRINT(3, ("Found L2 cache %s, starting new cluster\n", resource->description)); - - /*l2_cache = mali_l2_cache_create(resource, global_num_l2_cache_cores);*/ - l2_cache = mali_l2_cache_create(resource); - if (NULL == l2_cache) - { - MALI_PRINT_ERROR(("Failed to create L2 cache object\n")); - return _MALI_OSK_ERR_FAULT; - } - - if (NULL == mali_cluster_create(l2_cache)) - { - MALI_PRINT_ERROR(("Failed to create cluster object\n")); - mali_l2_cache_delete(l2_cache); - return _MALI_OSK_ERR_FAULT; - } - } - else - { - mali_cluster_create(NULL); - if (NULL == mali_cluster_get_global_cluster(0)) - { - MALI_PRINT_ERROR(("Failed to create cluster object\n")); - return _MALI_OSK_ERR_FAULT; - } - } - - MALI_DEBUG_PRINT(3, ("Created cluster object\n")); - return _MALI_OSK_ERR_OK; -} - -static _mali_osk_errcode_t mali_parse_config_cluster(void) -{ - if (_MALI_PRODUCT_ID_MALI200 == global_product_id) - { - /* Create dummy cluster without L2 cache */ - return mali_create_cluster(NULL); - } - else if (_MALI_PRODUCT_ID_MALI300 == global_product_id || _MALI_PRODUCT_ID_MALI400 == global_product_id) - { - _mali_osk_resource_t *l2_resource = mali_find_resource(MALI_L2, 0x1000); - if (NULL == l2_resource) - { - MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n")); - return _MALI_OSK_ERR_FAULT; - } - - return mali_create_cluster(l2_resource); - } - else if (_MALI_PRODUCT_ID_MALI450 == global_product_id) - { - /* - * L2 for GP at 0x10000 - * L2 for PP0-3 at 0x01000 - * L2 for PP4-7 at 0x11000 (optional) - */ - - _mali_osk_resource_t *l2_gp_resource; - _mali_osk_resource_t *l2_pp_grp0_resource; - _mali_osk_resource_t *l2_pp_grp1_resource; - - /* Make cluster for GP's L2 */ - l2_gp_resource = mali_find_resource(MALI_L2, 0x10000); - if (NULL != l2_gp_resource) - { - _mali_osk_errcode_t ret; - MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for GP\n")); - ret = mali_create_cluster(l2_gp_resource); - if (_MALI_OSK_ERR_OK != ret) - { - return ret; - } - } - else - { - MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n")); - return _MALI_OSK_ERR_FAULT; - } - - /* Make cluster for first PP core group */ - l2_pp_grp0_resource = mali_find_resource(MALI_L2, 0x1000); - if (NULL != l2_pp_grp0_resource) - { - _mali_osk_errcode_t ret; - MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for PP group 0\n")); - ret = mali_create_cluster(l2_pp_grp0_resource); - if (_MALI_OSK_ERR_OK != ret) - { - return ret; - } - } - else - { - MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for PP group 0 in config file\n")); - return _MALI_OSK_ERR_FAULT; - } - - /* Second PP core group is optional, don't fail if we don't find it */ - l2_pp_grp1_resource = mali_find_resource(MALI_L2, 0x11000); - if (NULL != l2_pp_grp1_resource) - { - _mali_osk_errcode_t ret; - MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for PP group 0\n")); - ret = mali_create_cluster(l2_pp_grp1_resource); - if (_MALI_OSK_ERR_OK != ret) - { - return ret; - } - } - } - - return _MALI_OSK_ERR_OK; -} - -static _mali_osk_errcode_t mali_create_group(struct mali_cluster *cluster, - _mali_osk_resource_t *resource_mmu, - _mali_osk_resource_t *resource_gp, - _mali_osk_resource_t *resource_pp) -{ - struct mali_mmu_core *mmu; - struct mali_group *group; - struct mali_pp_core *pp; - - MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description)); - - /* Create the MMU object */ - mmu = mali_mmu_create(resource_mmu); - if (NULL == mmu) - { - MALI_PRINT_ERROR(("Failed to create MMU object\n")); - return _MALI_OSK_ERR_FAULT; - } - - /* Create the group object */ - group = mali_group_create(cluster, mmu); - if (NULL == group) - { - MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description)); - mali_mmu_delete(mmu); - return _MALI_OSK_ERR_FAULT; - } - - /* Set pointer back to group in mmu.*/ - mali_mmu_set_group(mmu, group); - - /* Add this group to current cluster */ - mali_cluster_add_group(cluster, group); - - if (NULL != resource_gp) - { - /* Create the GP core object inside this group */ - /* global_gp_core = mali_gp_create(resource_gp, group); */ - if (NULL == mali_gp_create(resource_gp, group)) - { - /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ - MALI_PRINT_ERROR(("Failed to create GP object\n")); - return _MALI_OSK_ERR_FAULT; - } - - /* Add GP object to this group */ - MALI_DEBUG_PRINT(3, ("Adding GP %s to group\n", resource_gp->description)); - mali_group_add_gp_core(group, mali_gp_get_global_gp_core()); - } - - if (NULL != resource_pp) - { - /* Create the PP core object inside this group */ - pp = mali_pp_create(resource_pp, group); - - if (NULL == pp) - { - /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ - MALI_PRINT_ERROR(("Failed to create PP object\n")); - return _MALI_OSK_ERR_FAULT; - } - - /* Add PP object to this group */ - MALI_DEBUG_PRINT(3, ("Adding PP %s to group\n", resource_pp->description)); - mali_group_add_pp_core(group, pp); - } - - return _MALI_OSK_ERR_OK; -} - -static _mali_osk_errcode_t mali_parse_config_groups(void) -{ - if (_MALI_PRODUCT_ID_MALI200 == global_product_id) - { - _mali_osk_resource_t *resource_gp; - _mali_osk_resource_t *resource_pp; - _mali_osk_resource_t *resource_mmu; - - MALI_DEBUG_ASSERT(1 == mali_cluster_get_glob_num_clusters()); - - resource_gp = mali_find_resource(MALI_GP, 0x02000); - resource_pp = mali_find_resource(MALI_PP, 0x00000); - resource_mmu = mali_find_resource(MMU, 0x03000); - - if (NULL == resource_mmu || NULL == resource_gp || NULL == resource_pp) - { - /* Missing mandatory core(s) */ - return _MALI_OSK_ERR_FAULT; - } - - /*return mali_create_group(global_clusters[0], resource_mmu, resource_gp, resource_pp);*/ - return mali_create_group(mali_cluster_get_global_cluster(0), resource_mmu, resource_gp, resource_pp); - } - else if (_MALI_PRODUCT_ID_MALI300 == global_product_id || - _MALI_PRODUCT_ID_MALI400 == global_product_id || - _MALI_PRODUCT_ID_MALI450 == global_product_id) - { - _mali_osk_errcode_t err; - int cluster_id_gp = 0; - int cluster_id_pp_grp0 = 0; - int cluster_id_pp_grp1 = 0; - int i; - _mali_osk_resource_t *resource_gp; - _mali_osk_resource_t *resource_gp_mmu; - _mali_osk_resource_t *resource_pp[mali_pp_get_max_num_pp_cores()]; - _mali_osk_resource_t *resource_pp_mmu[mali_pp_get_max_num_pp_cores()]; - u32 max_num_pp_cores = mali_pp_get_max_num_pp_cores(); - - if (_MALI_PRODUCT_ID_MALI450 == global_product_id) - { - /* Mali-450 has separate L2s for GP, and PP core group(s) */ - cluster_id_pp_grp0 = 1; - cluster_id_pp_grp1 = 2; - } - - resource_gp = mali_find_resource(MALI_GP, 0x00000); - resource_gp_mmu = mali_find_resource(MMU, 0x03000); - resource_pp[0] = mali_find_resource(MALI_PP, 0x08000); - resource_pp[1] = mali_find_resource(MALI_PP, 0x0A000); - resource_pp[2] = mali_find_resource(MALI_PP, 0x0C000); - resource_pp[3] = mali_find_resource(MALI_PP, 0x0E000); - resource_pp[4] = mali_find_resource(MALI_PP, 0x28000); - resource_pp[5] = mali_find_resource(MALI_PP, 0x2A000); - resource_pp[6] = mali_find_resource(MALI_PP, 0x2C000); - resource_pp[7] = mali_find_resource(MALI_PP, 0x2E000); - resource_pp_mmu[0] = mali_find_resource(MMU, 0x04000); - resource_pp_mmu[1] = mali_find_resource(MMU, 0x05000); - resource_pp_mmu[2] = mali_find_resource(MMU, 0x06000); - resource_pp_mmu[3] = mali_find_resource(MMU, 0x07000); - resource_pp_mmu[4] = mali_find_resource(MMU, 0x1C000); - resource_pp_mmu[5] = mali_find_resource(MMU, 0x1D000); - resource_pp_mmu[6] = mali_find_resource(MMU, 0x1E000); - resource_pp_mmu[7] = mali_find_resource(MMU, 0x1F000); - - if (NULL == resource_gp || NULL == resource_gp_mmu || NULL == resource_pp[0] || NULL == resource_pp_mmu[0]) - { - /* Missing mandatory core(s) */ - MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU (0x%08X, 0x%08X, 0x%08X, 0x%08X)\n", - resource_gp, resource_gp_mmu, resource_pp[0], resource_pp_mmu[0])); - return _MALI_OSK_ERR_FAULT; - } - - MALI_DEBUG_ASSERT(1 <= mali_cluster_get_glob_num_clusters()); - err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_gp), resource_gp_mmu, resource_gp, NULL); - if (err != _MALI_OSK_ERR_OK) - { - return err; - } - - /* Create group for first (and mandatory) PP core */ - MALI_DEBUG_ASSERT(mali_cluster_get_glob_num_clusters() >= (cluster_id_pp_grp0 + 1)); /* >= 1 on Mali-300 and Mali-400, >= 2 on Mali-450 */ - err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp0), resource_pp_mmu[0], NULL, resource_pp[0]); - if (err != _MALI_OSK_ERR_OK) - { - return err; - } - - /* Create groups for rest of the cores in the first PP core group */ - for (i = 1; i < 4; i++) /* First half of the PP cores belong to first core group */ - { - if (NULL != resource_pp[i]) - { - err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp0), resource_pp_mmu[i], NULL, resource_pp[i]); - if (err != _MALI_OSK_ERR_OK) - { - return err; - } - } - } - - /* Create groups for cores in the second PP core group */ - for (i = 4; i < max_num_pp_cores; i++) /* Second half of the PP cores belong to second core group */ - { - if (NULL != resource_pp[i]) - { - MALI_DEBUG_ASSERT(mali_cluster_get_glob_num_clusters() >= 2); /* Only Mali-450 have more than 4 PPs, and these cores belong to second core group */ - err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp1), resource_pp_mmu[i], NULL, resource_pp[i]); - if (err != _MALI_OSK_ERR_OK) - { - return err; - } - } - } - } - - return _MALI_OSK_ERR_OK; -} - -static _mali_osk_errcode_t mali_parse_config_pmu(void) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; - _mali_osk_resource_t *resource_pmu; - u32 number_of_pp_cores; - u32 number_of_l2_caches; - - resource_pmu = mali_find_resource(PMU, 0x02000); - number_of_pp_cores = mali_count_resources(MALI_PP); - number_of_l2_caches = mali_count_resources(MALI_L2); - - if (NULL != resource_pmu) - { - if (NULL == mali_pmu_create(resource_pmu, number_of_pp_cores, number_of_l2_caches)) - { - err = _MALI_OSK_ERR_FAULT; - } - } - return err; -} - -static _mali_osk_errcode_t mali_parse_config_memory(void) -{ - int i; - _mali_osk_errcode_t ret; - - for(i = 0; i < num_resources; i++) - { - switch(arch_configuration[i].type) - { - case OS_MEMORY: - ret = mali_memory_core_resource_os_memory(&arch_configuration[i]); - if (_MALI_OSK_ERR_OK != ret) - { - MALI_PRINT_ERROR(("Failed to register OS_MEMORY\n")); - mali_memory_terminate(); - return ret; - } - break; - case MEMORY: - ret = mali_memory_core_resource_dedicated_memory(&arch_configuration[i]); - if (_MALI_OSK_ERR_OK != ret) - { - MALI_PRINT_ERROR(("Failed to register MEMORY\n")); - mali_memory_terminate(); - return ret; - } - break; - case MEM_VALIDATION: - ret = mali_mem_validation_add_range(&arch_configuration[i]); - if (_MALI_OSK_ERR_OK != ret) - { - MALI_PRINT_ERROR(("Failed to register MEM_VALIDATION\n")); - mali_memory_terminate(); - return ret; - } - break; - default: - break; - } - } - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_initialize_subsystems(void) -{ - _mali_osk_errcode_t err; - mali_bool is_pmu_enabled; - - err = mali_session_initialize(); - if (_MALI_OSK_ERR_OK != err) goto session_init_failed; - -#if MALI_TIMELINE_PROFILING_ENABLED - err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE); - if (_MALI_OSK_ERR_OK != err) - { - /* No biggie if we wheren't able to initialize the profiling */ - MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n")); - } -#endif - - /* Get data from config.h */ - err = _mali_osk_resources_init(&arch_configuration, &num_resources); - if (_MALI_OSK_ERR_OK != err) goto osk_resources_init_failed; - - /* Initialize driver subsystems */ - err = mali_memory_initialize(); - if (_MALI_OSK_ERR_OK != err) goto memory_init_failed; - - /* Configure memory early. Memory allocation needed for mali_mmu_initialize. */ - err = mali_parse_config_memory(); - if (_MALI_OSK_ERR_OK != err) goto parse_memory_config_failed; - - /* Parsing the GPU base address and first pp offset */ - err = mali_parse_gpu_base_and_first_pp_offset_address(); - if (_MALI_OSK_ERR_OK != err) goto parse_gpu_base_address_failed; - - /* Initialize the MALI PMU */ - err = mali_parse_config_pmu(); - if (_MALI_OSK_ERR_OK != err) goto parse_pmu_config_failed; - - is_pmu_enabled = mali_pmu_get_global_pmu_core() != NULL ? MALI_TRUE : MALI_FALSE; - - /* Initialize the power management module */ - err = mali_pm_initialize(); - if (_MALI_OSK_ERR_OK != err) goto pm_init_failed; - - /* Make sure the power stays on for the rest of this function */ - mali_pm_always_on(MALI_TRUE); - - /* Detect which Mali GPU we are dealing with */ - err = mali_parse_product_info(); - if (_MALI_OSK_ERR_OK != err) goto product_info_parsing_failed; - - /* The global_product_id is now populated with the correct Mali GPU */ - - /* Initialize MMU module */ - err = mali_mmu_initialize(); - if (_MALI_OSK_ERR_OK != err) goto mmu_init_failed; - - /* Initialize the DLBU module for Mali-450 */ - if (_MALI_PRODUCT_ID_MALI450 == global_product_id) - { - err = mali_dlbu_initialize(); - if (_MALI_OSK_ERR_OK != err) goto dlbu_init_failed; - } - - /* Start configuring the actual Mali hardware. */ - err = mali_parse_config_cluster(); - if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed; - err = mali_parse_config_groups(); - if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed; - - /* Initialize the schedulers */ - err = mali_scheduler_initialize(); - if (_MALI_OSK_ERR_OK != err) goto scheduler_init_failed; - err = mali_gp_scheduler_initialize(); - if (_MALI_OSK_ERR_OK != err) goto gp_scheduler_init_failed; - err = mali_pp_scheduler_initialize(); - if (_MALI_OSK_ERR_OK != err) goto pp_scheduler_init_failed; - -#ifdef CONFIG_MALI400_GPU_UTILIZATION - /* Initialize the GPU utilization tracking */ - err = mali_utilization_init(); - if (_MALI_OSK_ERR_OK != err) goto utilization_init_failed; -#endif - - /* We no longer need to stay */ - mali_pm_always_on(MALI_FALSE); - MALI_SUCCESS; /* all ok */ - - /* Error handling */ -#ifdef CONFIG_MALI400_GPU_UTILIZATION -utilization_init_failed: - mali_pp_scheduler_terminate(); -#endif -pp_scheduler_init_failed: - mali_gp_scheduler_terminate(); -gp_scheduler_init_failed: - mali_scheduler_terminate(); -scheduler_init_failed: -config_parsing_failed: - mali_delete_clusters(); /* Delete clusters even if config parsing failed. */ - if (_MALI_PRODUCT_ID_MALI450 == global_product_id) - { - mali_dlbu_terminate(); - } -dlbu_init_failed: - mali_mmu_terminate(); -mmu_init_failed: - /* Nothing to roll back */ -product_info_parsing_failed: - mali_pm_terminate(); -pm_init_failed: - if (is_pmu_enabled) - { - mali_pmu_delete(mali_pmu_get_global_pmu_core()); - } -parse_pmu_config_failed: -parse_gpu_base_address_failed: -parse_memory_config_failed: - mali_memory_terminate(); -memory_init_failed: - _mali_osk_resources_term(&arch_configuration, num_resources); -osk_resources_init_failed: -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_term(); -#endif - mali_session_terminate(); -session_init_failed: - return err; -} - -void mali_terminate_subsystems(void) -{ - struct mali_pmu_core *pmu; - - MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n")); - - /* shut down subsystems in reverse order from startup */ - - mali_pm_always_on(MALI_TRUE); /* Mali will be powered off once PM subsystem terminates */ - -#ifdef CONFIG_MALI400_GPU_UTILIZATION - mali_utilization_term(); -#endif - - mali_pp_scheduler_terminate(); - mali_gp_scheduler_terminate(); - mali_scheduler_terminate(); - - mali_delete_clusters(); /* Delete clusters even if config parsing failed. */ - - if (_MALI_PRODUCT_ID_MALI450 == global_product_id) - { - mali_dlbu_terminate(); - } - - mali_mmu_terminate(); - - pmu = mali_pmu_get_global_pmu_core(); - if (NULL != pmu) - { - mali_pmu_delete(pmu); - } - - mali_pm_terminate(); - - mali_memory_terminate(); - - _mali_osk_resources_term(&arch_configuration, num_resources); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_term(); -#endif - - mali_session_terminate(); -} - -_mali_product_id_t mali_kernel_core_get_product_id(void) -{ - return global_product_id; -} - -void mali_kernel_core_wakeup(void) -{ - u32 i; - u32 glob_num_clusters = mali_cluster_get_glob_num_clusters(); - struct mali_cluster *cluster; - - for (i = 0; i < glob_num_clusters; i++) - { - cluster = mali_cluster_get_global_cluster(i); - mali_cluster_reset(cluster); - } -} - -_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args ) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - /* check compatability */ - if ( args->version == _MALI_UK_API_VERSION ) - { - args->compatible = 1; - } - else - { - args->compatible = 0; - } - - args->version = _MALI_UK_API_VERSION; /* report our version */ - - /* success regardless of being compatible or not */ - MALI_SUCCESS; -} - -_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args ) -{ - _mali_osk_errcode_t err; - _mali_osk_notification_t *notification; - _mali_osk_notification_queue_t *queue; - - /* check input */ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - queue = ((struct mali_session_data *)args->ctx)->ioctl_queue; - - /* if the queue does not exist we're currently shutting down */ - if (NULL == queue) - { - MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); - args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS; - MALI_SUCCESS; - } - - /* receive a notification, might sleep */ - err = _mali_osk_notification_queue_receive(queue, ¬ification); - if (_MALI_OSK_ERR_OK != err) - { - MALI_ERROR(err); /* errcode returned, pass on to caller */ - } - - /* copy the buffer to the user */ - args->type = (_mali_uk_notification_type)notification->notification_type; - _mali_osk_memcpy(&args->data, notification->result_buffer, notification->result_buffer_size); - - /* finished with the notification */ - _mali_osk_notification_delete( notification ); - - MALI_SUCCESS; /* all ok */ -} - -_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args ) -{ - _mali_osk_notification_t * notification; - _mali_osk_notification_queue_t *queue; - - /* check input */ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - queue = ((struct mali_session_data *)args->ctx)->ioctl_queue; - - /* if the queue does not exist we're currently shutting down */ - if (NULL == queue) - { - MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); - MALI_SUCCESS; - } - - notification = _mali_osk_notification_create(args->type, 0); - if ( NULL == notification) - { - MALI_PRINT_ERROR( ("Failed to create notification object\n")); - return _MALI_OSK_ERR_NOMEM; - } - - _mali_osk_notification_queue_send(queue, notification); - - MALI_SUCCESS; /* all ok */ -} - -_mali_osk_errcode_t _mali_ukk_open(void **context) -{ - struct mali_session_data *session_data; - - /* allocated struct to track this session */ - session_data = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data)); - MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_NOMEM); - - MALI_DEBUG_PRINT(2, ("Session starting\n")); - - /* create a response queue for this session */ - session_data->ioctl_queue = _mali_osk_notification_queue_init(); - if (NULL == session_data->ioctl_queue) - { - _mali_osk_free(session_data); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - session_data->page_directory = mali_mmu_pagedir_alloc(); - if (NULL == session_data->page_directory) - { - _mali_osk_notification_queue_term(session_data->ioctl_queue); - _mali_osk_free(session_data); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session_data->page_directory, MALI_DLB_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE)) - { - MALI_PRINT_ERROR(("Failed to map DLB page into session\n")); - _mali_osk_notification_queue_term(session_data->ioctl_queue); - _mali_osk_free(session_data); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - if (0 != mali_dlbu_phys_addr) - { - mali_mmu_pagedir_update(session_data->page_directory, MALI_DLB_VIRT_ADDR, mali_dlbu_phys_addr, _MALI_OSK_MALI_PAGE_SIZE, MALI_CACHE_STANDARD); - } - - if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session_data)) - { - mali_mmu_pagedir_free(session_data->page_directory); - _mali_osk_notification_queue_term(session_data->ioctl_queue); - _mali_osk_free(session_data); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - *context = (void*)session_data; - - /* Add session to the list of all sessions. */ - mali_session_add(session_data); - - MALI_DEBUG_PRINT(3, ("Session started\n")); - MALI_SUCCESS; -} - -_mali_osk_errcode_t _mali_ukk_close(void **context) -{ - struct mali_session_data *session; - MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS); - session = (struct mali_session_data *)*context; - - MALI_DEBUG_PRINT(3, ("Session ending\n")); - - /* Remove session from list of all sessions. */ - mali_session_remove(session); - - /* Abort queued and running jobs */ - mali_gp_scheduler_abort_session(session); - mali_pp_scheduler_abort_session(session); - - /* Flush pending work. - * Needed to make sure all bottom half processing related to this - * session has been completed, before we free internal data structures. - */ - _mali_osk_flush_workqueue(NULL); - - /* Free remaining memory allocated to this session */ - mali_memory_session_end(session); - - /* Free session data structures */ - mali_mmu_pagedir_free(session->page_directory); - _mali_osk_notification_queue_term(session->ioctl_queue); - _mali_osk_free(session); - - *context = NULL; - - MALI_DEBUG_PRINT(2, ("Session has ended\n")); - - MALI_SUCCESS; -} - -#if MALI_STATE_TRACKING -u32 _mali_kernel_core_dump_state(char* buf, u32 size) -{ - int n = 0; /* Number of bytes written to buf */ - - n += mali_gp_scheduler_dump_state(buf + n, size - n); - n += mali_pp_scheduler_dump_state(buf + n, size - n); - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.h b/drivers/media/video/samsung/mali/common/mali_kernel_core.h deleted file mode 100644 index d424c48..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_core.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_KERNEL_CORE_H__ -#define __MALI_KERNEL_CORE_H__ - -#include "mali_osk.h" - -extern int mali_hang_check_interval; -extern int mali_max_job_runtime; - -typedef enum -{ - _MALI_PRODUCT_ID_UNKNOWN, - _MALI_PRODUCT_ID_MALI200, - _MALI_PRODUCT_ID_MALI300, - _MALI_PRODUCT_ID_MALI400, - _MALI_PRODUCT_ID_MALI450, -} _mali_product_id_t; - -_mali_osk_errcode_t mali_initialize_subsystems(void); - -void mali_terminate_subsystems(void); - -void mali_kernel_core_wakeup(void); - -_mali_product_id_t mali_kernel_core_get_product_id(void); - -u32 _mali_kernel_core_dump_state(char* buf, u32 size); - -#endif /* __MALI_KERNEL_CORE_H__ */ - diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c deleted file mode 100644 index b9f05ca..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_kernel_descriptor_mapping.h" -#include "mali_osk.h" -#include "mali_osk_bitops.h" - -#define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1)) - -/** - * Allocate a descriptor table capable of holding 'count' mappings - * @param count Number of mappings in the table - * @return Pointer to a new table, NULL on error - */ -static mali_descriptor_table * descriptor_table_alloc(int count); - -/** - * Free a descriptor table - * @param table The table to free - */ -static void descriptor_table_free(mali_descriptor_table * table); - -mali_descriptor_mapping * mali_descriptor_mapping_create(int init_entries, int max_entries) -{ - mali_descriptor_mapping * map = _mali_osk_calloc(1, sizeof(mali_descriptor_mapping)); - - init_entries = MALI_PAD_INT(init_entries); - max_entries = MALI_PAD_INT(max_entries); - - if (NULL != map) - { - map->table = descriptor_table_alloc(init_entries); - if (NULL != map->table) - { - map->lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP); - if (NULL != map->lock) - { - _mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */ - map->max_nr_mappings_allowed = max_entries; - map->current_nr_mappings = init_entries; - return map; - } - descriptor_table_free(map->table); - } - _mali_osk_free(map); - } - return NULL; -} - -void mali_descriptor_mapping_destroy(mali_descriptor_mapping * map) -{ - descriptor_table_free(map->table); - _mali_osk_lock_term(map->lock); - _mali_osk_free(map); -} - -_mali_osk_errcode_t mali_descriptor_mapping_allocate_mapping(mali_descriptor_mapping * map, void * target, int *odescriptor) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; - int new_descriptor; - - MALI_DEBUG_ASSERT_POINTER(map); - MALI_DEBUG_ASSERT_POINTER(odescriptor); - - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); - new_descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); - if (new_descriptor == map->current_nr_mappings) - { - /* no free descriptor, try to expand the table */ - mali_descriptor_table * new_table, * old_table; - if (map->current_nr_mappings >= map->max_nr_mappings_allowed) goto unlock_and_exit; - - map->current_nr_mappings += BITS_PER_LONG; - new_table = descriptor_table_alloc(map->current_nr_mappings); - if (NULL == new_table) goto unlock_and_exit; - - old_table = map->table; - _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); - _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); - map->table = new_table; - descriptor_table_free(old_table); - } - - /* we have found a valid descriptor, set the value and usage bit */ - _mali_osk_set_nonatomic_bit(new_descriptor, map->table->usage); - map->table->mappings[new_descriptor] = target; - *odescriptor = new_descriptor; - err = _MALI_OSK_ERR_OK; - -unlock_and_exit: - _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); - MALI_ERROR(err); -} - -void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping * map, void (*callback)(int, void*)) -{ - int i; - - MALI_DEBUG_ASSERT_POINTER(map); - MALI_DEBUG_ASSERT_POINTER(callback); - - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - /* id 0 is skipped as it's an reserved ID not mapping to anything */ - for (i = 1; i < map->current_nr_mappings; ++i) - { - if (_mali_osk_test_bit(i, map->table->usage)) - { - callback(i, map->table->mappings[i]); - } - } - _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); -} - -_mali_osk_errcode_t mali_descriptor_mapping_get(mali_descriptor_mapping * map, int descriptor, void** target) -{ - _mali_osk_errcode_t result = _MALI_OSK_ERR_FAULT; - MALI_DEBUG_ASSERT_POINTER(map); - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) - { - *target = map->table->mappings[descriptor]; - result = _MALI_OSK_ERR_OK; - } - else *target = NULL; - _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); - MALI_ERROR(result); -} - -_mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping * map, int descriptor, void * target) -{ - _mali_osk_errcode_t result = _MALI_OSK_ERR_FAULT; - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) - { - map->table->mappings[descriptor] = target; - result = _MALI_OSK_ERR_OK; - } - _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); - MALI_ERROR(result); -} - -void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor) -{ - void *old_value = NULL; - - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) - { - old_value = map->table->mappings[descriptor]; - map->table->mappings[descriptor] = NULL; - _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage); - } - _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); - - return old_value; -} - -static mali_descriptor_table * descriptor_table_alloc(int count) -{ - mali_descriptor_table * table; - - table = _mali_osk_calloc(1, sizeof(mali_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count)); - - if (NULL != table) - { - table->usage = (u32*)((u8*)table + sizeof(mali_descriptor_table)); - table->mappings = (void**)((u8*)table + sizeof(mali_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG)); - } - - return table; -} - -static void descriptor_table_free(mali_descriptor_table * table) -{ - _mali_osk_free(table); -} diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h deleted file mode 100644 index 82ed94d..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_kernel_descriptor_mapping.h - */ - -#ifndef __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ -#define __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ - -#include "mali_osk.h" - -/** - * The actual descriptor mapping table, never directly accessed by clients - */ -typedef struct mali_descriptor_table -{ - u32 * usage; /**< Pointer to bitpattern indicating if a descriptor is valid/used or not */ - void** mappings; /**< Array of the pointers the descriptors map to */ -} mali_descriptor_table; - -/** - * The descriptor mapping object - * Provides a separate namespace where we can map an integer to a pointer - */ -typedef struct mali_descriptor_mapping -{ - _mali_osk_lock_t *lock; /**< Lock protecting access to the mapping object */ - int max_nr_mappings_allowed; /**< Max number of mappings to support in this namespace */ - int current_nr_mappings; /**< Current number of possible mappings */ - mali_descriptor_table * table; /**< Pointer to the current mapping table */ -} mali_descriptor_mapping; - -/** - * Create a descriptor mapping object - * Create a descriptor mapping capable of holding init_entries growable to max_entries - * @param init_entries Number of entries to preallocate memory for - * @param max_entries Number of entries to max support - * @return Pointer to a descriptor mapping object, NULL on failure - */ -mali_descriptor_mapping * mali_descriptor_mapping_create(int init_entries, int max_entries); - -/** - * Destroy a descriptor mapping object - * @param map The map to free - */ -void mali_descriptor_mapping_destroy(mali_descriptor_mapping * map); - -/** - * Allocate a new mapping entry (descriptor ID) - * Allocates a new entry in the map. - * @param map The map to allocate a new entry in - * @param target The value to map to - * @return The descriptor allocated, a negative value on error - */ -_mali_osk_errcode_t mali_descriptor_mapping_allocate_mapping(mali_descriptor_mapping * map, void * target, int *descriptor); - -/** - * Get the value mapped to by a descriptor ID - * @param map The map to lookup the descriptor id in - * @param descriptor The descriptor ID to lookup - * @param target Pointer to a pointer which will receive the stored value - * @return 0 on successful lookup, negative on error - */ -_mali_osk_errcode_t mali_descriptor_mapping_get(mali_descriptor_mapping * map, int descriptor, void** target); - -/** - * Set the value mapped to by a descriptor ID - * @param map The map to lookup the descriptor id in - * @param descriptor The descriptor ID to lookup - * @param target Pointer to replace the current value with - * @return 0 on successful lookup, negative on error - */ -_mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping * map, int descriptor, void * target); - -/** - * Call the specified callback function for each descriptor in map. - * Entire function is mutex protected. - * @param map The map to do callbacks for - * @param callback A callback function which will be calle for each entry in map - */ -void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping * map, void (*callback)(int, void*)); - -/** - * Free the descriptor ID - * For the descriptor to be reused it has to be freed - * @param map The map to free the descriptor from - * @param descriptor The descriptor ID to free - * - * @return old value of descriptor mapping - */ -void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor); - -#endif /* __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c deleted file mode 100644 index 8ff3d37..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_kernel_core.h" -#include "mali_kernel_memory_engine.h" -#include "mali_osk.h" - -typedef struct os_allocation -{ - u32 num_pages; - u32 offset_start; - mali_allocation_engine * engine; - mali_memory_allocation * descriptor; -} os_allocation; - -typedef struct os_allocator -{ - _mali_osk_lock_t *mutex; - - /** - * Maximum number of pages to allocate from the OS - */ - u32 num_pages_max; - - /** - * Number of pages allocated from the OS - */ - u32 num_pages_allocated; - - /** CPU Usage adjustment (add to mali physical address to get cpu physical address) */ - u32 cpu_usage_adjust; -} os_allocator; - -static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); -static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block); -static void os_allocator_release(void * ctx, void * handle); -static void os_allocator_page_table_block_release( mali_page_table_block *page_table_block ); -static void os_allocator_destroy(mali_physical_memory_allocator * allocator); -static u32 os_allocator_stat(mali_physical_memory_allocator * allocator); - -mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u32 cpu_usage_adjust, const char *name) -{ - mali_physical_memory_allocator * allocator; - os_allocator * info; - - max_allocation = (max_allocation + _MALI_OSK_CPU_PAGE_SIZE-1) & ~(_MALI_OSK_CPU_PAGE_SIZE-1); - - MALI_DEBUG_PRINT(2, ("Mali OS memory allocator created with max allocation size of 0x%X bytes, cpu_usage_adjust 0x%08X\n", max_allocation, cpu_usage_adjust)); - - allocator = _mali_osk_malloc(sizeof(mali_physical_memory_allocator)); - if (NULL != allocator) - { - info = _mali_osk_malloc(sizeof(os_allocator)); - if (NULL != info) - { - info->num_pages_max = max_allocation / _MALI_OSK_CPU_PAGE_SIZE; - info->num_pages_allocated = 0; - info->cpu_usage_adjust = cpu_usage_adjust; - - info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_MEM_INFO); - if (NULL != info->mutex) - { - allocator->allocate = os_allocator_allocate; - allocator->allocate_page_table_block = os_allocator_allocate_page_table_block; - allocator->destroy = os_allocator_destroy; - allocator->stat = os_allocator_stat; - allocator->ctx = info; - allocator->name = name; - - return allocator; - } - _mali_osk_free(info); - } - _mali_osk_free(allocator); - } - - return NULL; -} - -static u32 os_allocator_stat(mali_physical_memory_allocator * allocator) -{ - os_allocator * info; - info = (os_allocator*)allocator->ctx; - return info->num_pages_allocated * _MALI_OSK_MALI_PAGE_SIZE; -} - -static void os_allocator_destroy(mali_physical_memory_allocator * allocator) -{ - os_allocator * info; - MALI_DEBUG_ASSERT_POINTER(allocator); - MALI_DEBUG_ASSERT_POINTER(allocator->ctx); - info = (os_allocator*)allocator->ctx; - _mali_osk_lock_term(info->mutex); - _mali_osk_free(info); - _mali_osk_free(allocator); -} - -static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) -{ - mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_NONE; - u32 left; - os_allocator * info; - os_allocation * allocation; - int pages_allocated = 0; - _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; - - MALI_DEBUG_ASSERT_POINTER(ctx); - MALI_DEBUG_ASSERT_POINTER(engine); - MALI_DEBUG_ASSERT_POINTER(descriptor); - MALI_DEBUG_ASSERT_POINTER(offset); - MALI_DEBUG_ASSERT_POINTER(alloc_info); - - info = (os_allocator*)ctx; - left = descriptor->size - *offset; - - if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; - - /** @note this code may not work on Linux, or may require a more complex Linux implementation */ - allocation = _mali_osk_malloc(sizeof(os_allocation)); - if (NULL != allocation) - { - u32 os_mem_max_usage = info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE; - allocation->offset_start = *offset; - allocation->num_pages = ((left + _MALI_OSK_CPU_PAGE_SIZE - 1) & ~(_MALI_OSK_CPU_PAGE_SIZE - 1)) >> _MALI_OSK_CPU_PAGE_ORDER; - MALI_DEBUG_PRINT(6, ("Allocating page array of size %d bytes\n", allocation->num_pages * sizeof(struct page*))); - - while (left > 0) - { - err = mali_allocation_engine_map_physical(engine, descriptor, *offset, MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, info->cpu_usage_adjust, _MALI_OSK_CPU_PAGE_SIZE); - if ( _MALI_OSK_ERR_OK != err) - { - if ( _MALI_OSK_ERR_NOMEM == err) - { - /* 'Partial' allocation (or, out-of-memory on first page) */ - break; - } - - MALI_DEBUG_PRINT(1, ("Mapping of physical memory failed\n")); - - /* Fatal error, cleanup any previous pages allocated. */ - if ( pages_allocated > 0 ) - { - mali_allocation_engine_unmap_physical( engine, descriptor, allocation->offset_start, _MALI_OSK_CPU_PAGE_SIZE*pages_allocated, _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR ); - /* (*offset) doesn't need to be restored; it will not be used by the caller on failure */ - } - - pages_allocated = 0; - - result = MALI_MEM_ALLOC_INTERNAL_FAILURE; - break; - } - - /* Loop iteration */ - if (left < _MALI_OSK_CPU_PAGE_SIZE) left = 0; - else left -= _MALI_OSK_CPU_PAGE_SIZE; - - pages_allocated++; - - *offset += _MALI_OSK_CPU_PAGE_SIZE; - } - - if (left) MALI_PRINT(("Out of memory. Mali memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", - (info->num_pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); - - /* Loop termination; decide on result */ - if (pages_allocated) - { - MALI_DEBUG_PRINT(6, ("Allocated %d pages\n", pages_allocated)); - if (left) result = MALI_MEM_ALLOC_PARTIAL; - else result = MALI_MEM_ALLOC_FINISHED; - - /* Some OS do not perform a full cache flush (including all outer caches) for uncached mapped memory. - * They zero the memory through a cached mapping, then flush the inner caches but not the outer caches. - * This is required for MALI to have the correct view of the memory. - */ - _mali_osk_cache_ensure_uncached_range_flushed( (void *)descriptor, allocation->offset_start, pages_allocated *_MALI_OSK_CPU_PAGE_SIZE ); - allocation->num_pages = pages_allocated; - allocation->engine = engine; /* Necessary to make the engine's unmap call */ - allocation->descriptor = descriptor; /* Necessary to make the engine's unmap call */ - info->num_pages_allocated += pages_allocated; - - MALI_DEBUG_PRINT(6, ("%d out of %d pages now allocated\n", info->num_pages_allocated, info->num_pages_max)); - - alloc_info->ctx = info; - alloc_info->handle = allocation; - alloc_info->release = os_allocator_release; - } - else - { - MALI_DEBUG_PRINT(6, ("Releasing pages array due to no pages allocated\n")); - _mali_osk_free( allocation ); - } - } - - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - - return result; -} - -static void os_allocator_release(void * ctx, void * handle) -{ - os_allocator * info; - os_allocation * allocation; - mali_allocation_engine * engine; - mali_memory_allocation * descriptor; - - MALI_DEBUG_ASSERT_POINTER(ctx); - MALI_DEBUG_ASSERT_POINTER(handle); - - info = (os_allocator*)ctx; - allocation = (os_allocation*)handle; - engine = allocation->engine; - descriptor = allocation->descriptor; - - MALI_DEBUG_ASSERT_POINTER( engine ); - MALI_DEBUG_ASSERT_POINTER( descriptor ); - - if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) - { - MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); - return; - } - - MALI_DEBUG_PRINT(6, ("Releasing %d os pages\n", allocation->num_pages)); - - MALI_DEBUG_ASSERT( allocation->num_pages <= info->num_pages_allocated); - info->num_pages_allocated -= allocation->num_pages; - - mali_allocation_engine_unmap_physical( engine, descriptor, allocation->offset_start, _MALI_OSK_CPU_PAGE_SIZE*allocation->num_pages, _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR ); - - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - - _mali_osk_free(allocation); -} - -static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) -{ -#if defined(CONFIG_MACH_KONA) -#ifndef CONFIG_FORCE_MAX_ZONEORDER - int allocation_order = 10; -#else - int allocation_order = CONFIG_FORCE_MAX_ZONEORDER - 1; -#endif -#else - int allocation_order = 11; /* _MALI_OSK_CPU_PAGE_SIZE << 6 */ -#endif - void *virt = NULL; - u32 size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; - os_allocator * info; - - u32 cpu_phys_base; - - MALI_DEBUG_ASSERT_POINTER(ctx); - info = (os_allocator*)ctx; - - /* Ensure we don't allocate more than we're supposed to from the ctx */ - if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; - - /* if the number of pages to be requested lead to exceeding the memory - * limit in info->num_pages_max, reduce the size that is to be requested. */ - while ( (info->num_pages_allocated + (1 << allocation_order) > info->num_pages_max) - && _mali_osk_mem_check_allocated(info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE) ) - { - if ( allocation_order > 0 ) { - --allocation_order; - } else { - /* return OOM */ - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - return MALI_MEM_ALLOC_NONE; - } - } - - /* try to allocate 2^(allocation_order) pages, if that fails, try - * allocation_order-1 to allocation_order 0 (inclusive) */ - while ( allocation_order >= 0 ) - { - size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; - virt = _mali_osk_mem_allocioregion( &cpu_phys_base, size ); - - if (NULL != virt) break; - - --allocation_order; - } - - if ( NULL == virt ) - { - MALI_DEBUG_PRINT(1, ("Failed to allocate consistent memory. Is CONSISTENT_DMA_SIZE set too low?\n")); - /* return OOM */ - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - return MALI_MEM_ALLOC_NONE; - } - - MALI_DEBUG_PRINT(5, ("os_allocator_allocate_page_table_block: Allocation of order %i succeeded\n", - allocation_order)); - - /* we now know the size of the allocation since we know for what - * allocation_order the allocation succeeded */ - size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; - - - block->release = os_allocator_page_table_block_release; - block->ctx = ctx; - block->handle = (void*)allocation_order; - block->size = size; - block->phys_base = cpu_phys_base - info->cpu_usage_adjust; - block->mapping = virt; - - info->num_pages_allocated += (1 << allocation_order); - - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - - return MALI_MEM_ALLOC_FINISHED; -} - -static void os_allocator_page_table_block_release( mali_page_table_block *page_table_block ) -{ - os_allocator * info; - u32 allocation_order; - u32 pages_allocated; - - MALI_DEBUG_ASSERT_POINTER( page_table_block ); - - info = (os_allocator*)page_table_block->ctx; - - MALI_DEBUG_ASSERT_POINTER( info ); - - allocation_order = (u32)page_table_block->handle; - - pages_allocated = 1 << allocation_order; - - MALI_DEBUG_ASSERT( pages_allocated * _MALI_OSK_CPU_PAGE_SIZE == page_table_block->size ); - - if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) - { - MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); - return; - } - - MALI_DEBUG_ASSERT( pages_allocated <= info->num_pages_allocated); - info->num_pages_allocated -= pages_allocated; - - /* Adjust phys_base from mali physical address to CPU physical address */ - _mali_osk_mem_freeioregion( page_table_block->phys_base + info->cpu_usage_adjust, page_table_block->size, page_table_block->mapping ); - - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); -} diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.h b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.h deleted file mode 100644 index 59e6494..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_KERNEL_MEM_OS_H__ -#define __MALI_KERNEL_MEM_OS_H__ - -/** - * @brief Creates an object that manages allocating OS memory - * - * Creates an object that provides an interface to allocate OS memory and - * have it mapped into the Mali virtual memory space. - * - * The object exposes pointers to - * - allocate OS memory - * - allocate Mali page tables in OS memory - * - destroy the object - * - * Allocations from OS memory are of type mali_physical_memory_allocation - * which provides a function to release the allocation. - * - * @param max_allocation max. number of bytes that can be allocated from OS memory - * @param cpu_usage_adjust value to add to mali physical addresses to obtain CPU physical addresses - * @param name description of the allocator - * @return pointer to mali_physical_memory_allocator object. NULL on failure. - **/ -mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u32 cpu_usage_adjust, const char *name); - -#endif /* __MALI_KERNEL_MEM_OS_H__ */ - - diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c deleted file mode 100644 index d770e3e..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_kernel_core.h" -#include "mali_kernel_memory_engine.h" -#include "mali_osk.h" -#include "mali_osk_list.h" - -typedef struct memory_engine -{ - mali_kernel_mem_address_manager * mali_address; - mali_kernel_mem_address_manager * process_address; -} memory_engine; - -mali_allocation_engine mali_allocation_engine_create(mali_kernel_mem_address_manager * mali_address_manager, mali_kernel_mem_address_manager * process_address_manager) -{ - memory_engine * engine; - - /* Mali Address Manager need not support unmap_physical */ - MALI_DEBUG_ASSERT_POINTER(mali_address_manager); - MALI_DEBUG_ASSERT_POINTER(mali_address_manager->allocate); - MALI_DEBUG_ASSERT_POINTER(mali_address_manager->release); - MALI_DEBUG_ASSERT_POINTER(mali_address_manager->map_physical); - - /* Process Address Manager must support unmap_physical for OS allocation - * error path handling */ - MALI_DEBUG_ASSERT_POINTER(process_address_manager); - MALI_DEBUG_ASSERT_POINTER(process_address_manager->allocate); - MALI_DEBUG_ASSERT_POINTER(process_address_manager->release); - MALI_DEBUG_ASSERT_POINTER(process_address_manager->map_physical); - MALI_DEBUG_ASSERT_POINTER(process_address_manager->unmap_physical); - - - engine = (memory_engine*)_mali_osk_malloc(sizeof(memory_engine)); - if (NULL == engine) return NULL; - - engine->mali_address = mali_address_manager; - engine->process_address = process_address_manager; - - return (mali_allocation_engine)engine; -} - -void mali_allocation_engine_destroy(mali_allocation_engine engine) -{ - MALI_DEBUG_ASSERT_POINTER(engine); - _mali_osk_free(engine); -} - -_mali_osk_errcode_t mali_allocation_engine_allocate_memory(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, mali_physical_memory_allocator * physical_allocators, _mali_osk_list_t *tracking_list ) -{ - memory_engine * engine = (memory_engine*)mem_engine; - - MALI_DEBUG_ASSERT_POINTER(engine); - MALI_DEBUG_ASSERT_POINTER(descriptor); - MALI_DEBUG_ASSERT_POINTER(physical_allocators); - /* ASSERT that the list member has been initialized, even if it won't be - * used for tracking. We need it to be initialized to see if we need to - * delete it from a list in the release function. */ - MALI_DEBUG_ASSERT( NULL != descriptor->list.next && NULL != descriptor->list.prev ); - - if (_MALI_OSK_ERR_OK == engine->mali_address->allocate(descriptor)) - { - _mali_osk_errcode_t res = _MALI_OSK_ERR_OK; - if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) - { - res = engine->process_address->allocate(descriptor); - } - if ( _MALI_OSK_ERR_OK == res ) - { - /* address space setup OK, commit physical memory to the allocation */ - mali_physical_memory_allocator * active_allocator = physical_allocators; - struct mali_physical_memory_allocation * active_allocation_tracker = &descriptor->physical_allocation; - u32 offset = 0; - - while ( NULL != active_allocator ) - { - switch (active_allocator->allocate(active_allocator->ctx, mem_engine, descriptor, &offset, active_allocation_tracker)) - { - case MALI_MEM_ALLOC_FINISHED: - if ( NULL != tracking_list ) - { - /* Insert into the memory session list */ - /* ASSERT that it is not already part of a list */ - MALI_DEBUG_ASSERT( _mali_osk_list_empty( &descriptor->list ) ); - _mali_osk_list_add( &descriptor->list, tracking_list ); - } - - MALI_SUCCESS; /* all done */ - case MALI_MEM_ALLOC_NONE: - /* reuse current active_allocation_tracker */ - MALI_DEBUG_PRINT( 4, ("Memory Engine Allocate: No allocation on %s, resorting to %s\n", - ( active_allocator->name ) ? active_allocator->name : "UNNAMED", - ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") ); - active_allocator = active_allocator->next; - break; - case MALI_MEM_ALLOC_PARTIAL: - if (NULL != active_allocator->next) - { - /* need a new allocation tracker */ - active_allocation_tracker->next = _mali_osk_calloc(1, sizeof(mali_physical_memory_allocation)); - if (NULL != active_allocation_tracker->next) - { - active_allocation_tracker = active_allocation_tracker->next; - MALI_DEBUG_PRINT( 2, ("Memory Engine Allocate: Partial allocation on %s, resorting to %s\n", - ( active_allocator->name ) ? active_allocator->name : "UNNAMED", - ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") ); - active_allocator = active_allocator->next; - break; - } - } - /* FALL THROUGH */ - case MALI_MEM_ALLOC_INTERNAL_FAILURE: - active_allocator = NULL; /* end the while loop */ - break; - } - } - - MALI_PRINT(("Memory allocate failed, could not allocate size %d kB.\n", descriptor->size/1024)); - - /* allocation failure, start cleanup */ - /* loop over any potential partial allocations */ - active_allocation_tracker = &descriptor->physical_allocation; - while (NULL != active_allocation_tracker) - { - /* handle blank trackers which will show up during failure */ - if (NULL != active_allocation_tracker->release) - { - active_allocation_tracker->release(active_allocation_tracker->ctx, active_allocation_tracker->handle); - } - active_allocation_tracker = active_allocation_tracker->next; - } - - /* free the allocation tracker objects themselves, skipping the tracker stored inside the descriptor itself */ - for ( active_allocation_tracker = descriptor->physical_allocation.next; active_allocation_tracker != NULL; ) - { - void * buf = active_allocation_tracker; - active_allocation_tracker = active_allocation_tracker->next; - _mali_osk_free(buf); - } - - /* release the address spaces */ - - if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) - { - engine->process_address->release(descriptor); - } - } - engine->mali_address->release(descriptor); - } - - MALI_ERROR(_MALI_OSK_ERR_FAULT); -} - -void mali_allocation_engine_release_memory(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor) -{ - mali_allocation_engine_release_pt1_mali_pagetables_unmap(mem_engine, descriptor); - mali_allocation_engine_release_pt2_physical_memory_free(mem_engine, descriptor); -} - -void mali_allocation_engine_release_pt1_mali_pagetables_unmap(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor) -{ - memory_engine * engine = (memory_engine*)mem_engine; - - MALI_DEBUG_ASSERT_POINTER(engine); - MALI_DEBUG_ASSERT_POINTER(descriptor); - - /* Calling: mali_address_manager_release() */ - /* This function is allowed to be called several times, and it only does the release on the first call. */ - engine->mali_address->release(descriptor); -} - -void mali_allocation_engine_release_pt2_physical_memory_free(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor) -{ - memory_engine * engine = (memory_engine*)mem_engine; - mali_physical_memory_allocation * active_allocation_tracker; - - /* Remove this from a tracking list in session_data->memory_head */ - if ( ! _mali_osk_list_empty( &descriptor->list ) ) - { - _mali_osk_list_del( &descriptor->list ); - /* Clear the list for debug mode, catch use-after-free */ - MALI_DEBUG_CODE( descriptor->list.next = descriptor->list.prev = NULL; ) - } - - active_allocation_tracker = &descriptor->physical_allocation; - while (NULL != active_allocation_tracker) - { - MALI_DEBUG_ASSERT_POINTER(active_allocation_tracker->release); - active_allocation_tracker->release(active_allocation_tracker->ctx, active_allocation_tracker->handle); - active_allocation_tracker = active_allocation_tracker->next; - } - - /* free the allocation tracker objects themselves, skipping the tracker stored inside the descriptor itself */ - for ( active_allocation_tracker = descriptor->physical_allocation.next; active_allocation_tracker != NULL; ) - { - void * buf = active_allocation_tracker; - active_allocation_tracker = active_allocation_tracker->next; - _mali_osk_free(buf); - } - - if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) - { - engine->process_address->release(descriptor); - } -} - -_mali_osk_errcode_t mali_allocation_engine_map_physical(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, u32 offset, u32 phys, u32 cpu_usage_adjust, u32 size) -{ - _mali_osk_errcode_t err; - memory_engine * engine = (memory_engine*)mem_engine; - _mali_osk_mem_mapregion_flags_t unmap_flags = (_mali_osk_mem_mapregion_flags_t)0; - - MALI_DEBUG_ASSERT_POINTER(engine); - MALI_DEBUG_ASSERT_POINTER(descriptor); - - MALI_DEBUG_PRINT(7, ("Mapping phys 0x%08X length 0x%08X at offset 0x%08X\n", phys, size, offset)); - - MALI_DEBUG_ASSERT_POINTER(engine->mali_address); - MALI_DEBUG_ASSERT_POINTER(engine->mali_address->map_physical); - - /* Handle process address manager first, because we may need them to - * allocate the physical page */ - if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) - { - /* Handle OS-allocated specially, since an adjustment may be required */ - if ( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC == phys ) - { - MALI_DEBUG_ASSERT( _MALI_OSK_CPU_PAGE_SIZE == size ); - - /* Set flags to use on error path */ - unmap_flags |= _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR; - - err = engine->process_address->map_physical(descriptor, offset, &phys, size); - /* Adjust for cpu physical address to mali physical address */ - phys -= cpu_usage_adjust; - } - else - { - u32 cpu_phys; - /* Adjust mali physical address to cpu physical address */ - cpu_phys = phys + cpu_usage_adjust; - err = engine->process_address->map_physical(descriptor, offset, &cpu_phys, size); - } - - if ( _MALI_OSK_ERR_OK != err ) - { - MALI_DEBUG_PRINT(2, ("Map failed: %s %d\n", __FUNCTION__, __LINE__)); - MALI_ERROR( err ); - } - } - - MALI_DEBUG_PRINT(7, ("Mapping phys 0x%08X length 0x%08X at offset 0x%08X to CPUVA 0x%08X\n", phys, size, offset, (u32)(descriptor->mapping) + offset)); - - /* Mali address manager must use the physical address - no point in asking - * it to allocate another one for us */ - MALI_DEBUG_ASSERT( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC != phys ); - - err = engine->mali_address->map_physical(descriptor, offset, &phys, size); - - if ( _MALI_OSK_ERR_OK != err ) - { - if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) - { - MALI_DEBUG_PRINT( 2, ("Process address manager succeeded, but Mali Address manager failed for phys=0x%08X size=0x%08X, offset=0x%08X. Will unmap.\n", phys, size, offset)); - engine->process_address->unmap_physical(descriptor, offset, size, unmap_flags); - } - MALI_DEBUG_PRINT(2, ("Map mali failed: %s %d\n", __FUNCTION__, __LINE__)); - MALI_ERROR( err ); - } - - MALI_SUCCESS; -} - -void mali_allocation_engine_unmap_physical(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t unmap_flags ) -{ - memory_engine * engine = (memory_engine*)mem_engine; - - MALI_DEBUG_ASSERT_POINTER(engine); - MALI_DEBUG_ASSERT_POINTER(descriptor); - - MALI_DEBUG_PRINT(7, ("UnMapping length 0x%08X at offset 0x%08X\n", size, offset)); - - MALI_DEBUG_ASSERT_POINTER(engine->mali_address); - MALI_DEBUG_ASSERT_POINTER(engine->process_address); - - if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) - { - /* Mandetory for process_address manager to have an unmap function*/ - engine->process_address->unmap_physical( descriptor, offset, size, unmap_flags ); - } - - /* Optional for mali_address manager to have an unmap function*/ - if ( NULL != engine->mali_address->unmap_physical ) - { - engine->mali_address->unmap_physical( descriptor, offset, size, unmap_flags ); - } -} - - -_mali_osk_errcode_t mali_allocation_engine_allocate_page_tables(mali_allocation_engine engine, mali_page_table_block * descriptor, mali_physical_memory_allocator * physical_provider) -{ - mali_physical_memory_allocator * active_allocator = physical_provider; - - MALI_DEBUG_ASSERT_POINTER(descriptor); - MALI_DEBUG_ASSERT_POINTER(physical_provider); - - while ( NULL != active_allocator ) - { - switch (active_allocator->allocate_page_table_block(active_allocator->ctx, descriptor)) - { - case MALI_MEM_ALLOC_FINISHED: - MALI_SUCCESS; /* all done */ - case MALI_MEM_ALLOC_NONE: - /* try next */ - MALI_DEBUG_PRINT( 2, ("Memory Engine Allocate PageTables: No allocation on %s, resorting to %s\n", - ( active_allocator->name ) ? active_allocator->name : "UNNAMED", - ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") ); - active_allocator = active_allocator->next; - break; - case MALI_MEM_ALLOC_PARTIAL: - MALI_DEBUG_PRINT(1, ("Invalid return value from allocate_page_table_block call: MALI_MEM_ALLOC_PARTIAL\n")); - /* FALL THROUGH */ - case MALI_MEM_ALLOC_INTERNAL_FAILURE: - MALI_DEBUG_PRINT(1, ("Aborting due to allocation failure\n")); - active_allocator = NULL; /* end the while loop */ - break; - } - } - - MALI_ERROR(_MALI_OSK_ERR_FAULT); -} - - -void mali_allocation_engine_report_allocators( mali_physical_memory_allocator * physical_provider ) -{ - mali_physical_memory_allocator * active_allocator = physical_provider; - MALI_DEBUG_ASSERT_POINTER(physical_provider); - - MALI_DEBUG_PRINT( 1, ("Mali memory allocators will be used in this order of preference (lowest numbered first) :\n")); - while ( NULL != active_allocator ) - { - if ( NULL != active_allocator->name ) - { - MALI_DEBUG_PRINT( 1, ("\t%d: %s\n", active_allocator->alloc_order, active_allocator->name) ); - } - else - { - MALI_DEBUG_PRINT( 1, ("\t%d: (UNNAMED ALLOCATOR)\n", active_allocator->alloc_order) ); - } - active_allocator = active_allocator->next; - } - -} - -u32 mali_allocation_engine_memory_usage(mali_physical_memory_allocator *allocator) -{ - u32 sum = 0; - while(NULL != allocator) - { - /* Only count allocators that have set up a stat function. */ - if(allocator->stat) - sum += allocator->stat(allocator); - - allocator = allocator->next; - } - - return sum; -} diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h deleted file mode 100644 index 3b41cee..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_KERNEL_MEMORY_ENGINE_H__ -#define __MALI_KERNEL_MEMORY_ENGINE_H__ - -typedef void * mali_allocation_engine; - -typedef enum { MALI_MEM_ALLOC_FINISHED, MALI_MEM_ALLOC_PARTIAL, MALI_MEM_ALLOC_NONE, MALI_MEM_ALLOC_INTERNAL_FAILURE } mali_physical_memory_allocation_result; - -typedef struct mali_physical_memory_allocation -{ - void (*release)(void * ctx, void * handle); /**< Function to call on to release the physical memory */ - void * ctx; - void * handle; - struct mali_physical_memory_allocation * next; -} mali_physical_memory_allocation; - -struct mali_page_table_block; - -typedef struct mali_page_table_block -{ - void (*release)(struct mali_page_table_block *page_table_block); - void * ctx; - void * handle; - u32 size; /**< In bytes, should be a multiple of MALI_MMU_PAGE_SIZE to avoid internal fragementation */ - u32 phys_base; /**< Mali physical address */ - mali_io_address mapping; -} mali_page_table_block; - - -/** @addtogroup _mali_osk_low_level_memory - * @{ */ - -typedef enum -{ - MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE = 0x1, - MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE = 0x2, -} mali_memory_allocation_flag; - -/** - * Supplying this 'magic' physical address requests that the OS allocate the - * physical address at page commit time, rather than committing a specific page - */ -#define MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC ((u32)(-1)) - -typedef struct mali_memory_allocation -{ - /* Information about the allocation */ - void * mapping; /**< CPU virtual address where the memory is mapped at */ - u32 mali_address; /**< The Mali seen address of the memory allocation */ - u32 size; /**< Size of the allocation */ - u32 permission; /**< Permission settings */ - mali_memory_allocation_flag flags; - u32 cache_settings; /* type: mali_memory_cache_settings, found in Ump DD breaks if we include it...*/ - - _mali_osk_lock_t * lock; - - /* Manager specific information pointers */ - void * mali_addr_mapping_info; /**< Mali address allocation specific info */ - void * process_addr_mapping_info; /**< Mapping manager specific info */ - - mali_physical_memory_allocation physical_allocation; - - _mali_osk_list_t list; /**< List for linking together memory allocations into the session's memory head */ -} mali_memory_allocation; -/** @} */ /* end group _mali_osk_low_level_memory */ - - -typedef struct mali_physical_memory_allocator -{ - mali_physical_memory_allocation_result (*allocate)(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); - mali_physical_memory_allocation_result (*allocate_page_table_block)(void * ctx, mali_page_table_block * block); /* MALI_MEM_ALLOC_PARTIAL not allowed */ - void (*destroy)(struct mali_physical_memory_allocator * allocator); - u32 (*stat)(struct mali_physical_memory_allocator * allocator); - void * ctx; - const char * name; /**< Descriptive name for use in mali_allocation_engine_report_allocators, or NULL */ - u32 alloc_order; /**< Order in which the allocations should happen */ - struct mali_physical_memory_allocator * next; -} mali_physical_memory_allocator; - -typedef struct mali_kernel_mem_address_manager -{ - _mali_osk_errcode_t (*allocate)(mali_memory_allocation *); /**< Function to call to reserve an address */ - void (*release)(mali_memory_allocation *); /**< Function to call to free the address allocated */ - - /** - * Function called for each physical sub allocation. - * Called for each physical block allocated by the physical memory manager. - * @param[in] descriptor The memory descriptor in question - * @param[in] off Offset from the start of range - * @param[in,out] phys_addr A pointer to the physical address of the start of the - * physical block. When *phys_addr == MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC - * is used, this requests the function to allocate the physical page - * itself, and return it through the pointer provided. - * @param[in] size Length in bytes of the physical block - * @return _MALI_OSK_ERR_OK on success. - * A value of type _mali_osk_errcode_t other than _MALI_OSK_ERR_OK indicates failure. - * Specifically, _MALI_OSK_ERR_UNSUPPORTED indicates that the function - * does not support allocating physical pages itself. - */ - _mali_osk_errcode_t (*map_physical)(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size); - - /** - * Function called to remove a physical sub allocation. - * Called on error paths where one of the address managers fails. - * - * @note this is optional. For address managers where this is not - * implemented, the value of this member is NULL. The memory engine - * currently does not require the mali address manager to be able to - * unmap individual pages, but the process address manager must have this - * capability. - * - * @param[in] descriptor The memory descriptor in question - * @param[in] off Offset from the start of range - * @param[in] size Length in bytes of the physical block - * @param[in] flags flags to use on a per-page basis. For OS-allocated - * physical pages, this must include _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR. - * @return _MALI_OSK_ERR_OK on success. - * A value of type _mali_osk_errcode_t other than _MALI_OSK_ERR_OK indicates failure. - */ - void (*unmap_physical)(mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags); - -} mali_kernel_mem_address_manager; - -mali_allocation_engine mali_allocation_engine_create(mali_kernel_mem_address_manager * mali_address_manager, mali_kernel_mem_address_manager * process_address_manager); - -void mali_allocation_engine_destroy(mali_allocation_engine engine); - -int mali_allocation_engine_allocate_memory(mali_allocation_engine engine, mali_memory_allocation * descriptor, mali_physical_memory_allocator * physical_provider, _mali_osk_list_t *tracking_list ); -void mali_allocation_engine_release_memory(mali_allocation_engine engine, mali_memory_allocation * descriptor); - -void mali_allocation_engine_release_pt1_mali_pagetables_unmap(mali_allocation_engine engine, mali_memory_allocation * descriptor); -void mali_allocation_engine_release_pt2_physical_memory_free(mali_allocation_engine engine, mali_memory_allocation * descriptor); - -int mali_allocation_engine_map_physical(mali_allocation_engine engine, mali_memory_allocation * descriptor, u32 offset, u32 phys, u32 cpu_usage_adjust, u32 size); -void mali_allocation_engine_unmap_physical(mali_allocation_engine engine, mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t unmap_flags); - -int mali_allocation_engine_allocate_page_tables(mali_allocation_engine, mali_page_table_block * descriptor, mali_physical_memory_allocator * physical_provider); - -void mali_allocation_engine_report_allocators(mali_physical_memory_allocator * physical_provider); - -u32 mali_allocation_engine_memory_usage(mali_physical_memory_allocator *allocator); - -#endif /* __MALI_KERNEL_MEMORY_ENGINE_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c deleted file mode 100644 index a374dbf..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_utilization.h" -#include "mali_osk.h" -#include "mali_platform.h" - -/* Define how often to calculate and report GPU utilization, in milliseconds */ -#define MALI_GPU_UTILIZATION_TIMEOUT 1000 - -static _mali_osk_lock_t *time_data_lock; - -static _mali_osk_atomic_t num_running_cores; - -static u64 period_start_time = 0; -static u64 work_start_time = 0; -static u64 accumulated_work_time = 0; - -static _mali_osk_timer_t *utilization_timer = NULL; -static mali_bool timer_running = MALI_FALSE; - - -static void calculate_gpu_utilization(void* arg) -{ - u64 time_now; - u64 time_period; - u32 leading_zeroes; - u32 shift_val; - u32 work_normalized; - u32 period_normalized; - u32 utilization; - - _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - if (accumulated_work_time == 0 && work_start_time == 0) - { - /* Don't reschedule timer, this will be started if new work arrives */ - timer_running = MALI_FALSE; - - _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - /* No work done for this period, report zero usage */ - mali_gpu_utilization_handler(0); - - return; - } - - time_now = _mali_osk_time_get_ns(); - time_period = time_now - period_start_time; - - /* If we are currently busy, update working period up to now */ - if (work_start_time != 0) - { - accumulated_work_time += (time_now - work_start_time); - work_start_time = time_now; - } - - /* - * We have two 64-bit values, a dividend and a divisor. - * To avoid dependencies to a 64-bit divider, we shift down the two values - * equally first. - * We shift the dividend up and possibly the divisor down, making the result X in 256. - */ - - /* Shift the 64-bit values down so they fit inside a 32-bit integer */ - leading_zeroes = _mali_osk_clz((u32)(time_period >> 32)); - shift_val = 32 - leading_zeroes; - work_normalized = (u32)(accumulated_work_time >> shift_val); - period_normalized = (u32)(time_period >> shift_val); - - /* - * Now, we should report the usage in parts of 256 - * this means we must shift up the dividend or down the divisor by 8 - * (we could do a combination, but we just use one for simplicity, - * but the end result should be good enough anyway) - */ - if (period_normalized > 0x00FFFFFF) - { - /* The divisor is so big that it is safe to shift it down */ - period_normalized >>= 8; - } - else - { - /* - * The divisor is so small that we can shift up the dividend, without loosing any data. - * (dividend is always smaller than the divisor) - */ - work_normalized <<= 8; - } - - utilization = work_normalized / period_normalized; - - accumulated_work_time = 0; - period_start_time = time_now; /* starting a new period */ - - _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT)); - - - mali_gpu_utilization_handler(utilization); -} - -_mali_osk_errcode_t mali_utilization_init(void) -{ - time_data_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | - _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_UTILIZATION); - - if (NULL == time_data_lock) - { - return _MALI_OSK_ERR_FAULT; - } - - _mali_osk_atomic_init(&num_running_cores, 0); - - utilization_timer = _mali_osk_timer_init(); - if (NULL == utilization_timer) - { - _mali_osk_lock_term(time_data_lock); - return _MALI_OSK_ERR_FAULT; - } - _mali_osk_timer_setcallback(utilization_timer, calculate_gpu_utilization, NULL); - - return _MALI_OSK_ERR_OK; -} - -void mali_utilization_suspend(void) -{ - if (NULL != utilization_timer) - { - _mali_osk_timer_del(utilization_timer); - timer_running = MALI_FALSE; - } -} - -void mali_utilization_term(void) -{ - if (NULL != utilization_timer) - { - _mali_osk_timer_del(utilization_timer); - timer_running = MALI_FALSE; - _mali_osk_timer_term(utilization_timer); - utilization_timer = NULL; - } - - _mali_osk_atomic_term(&num_running_cores); - - _mali_osk_lock_term(time_data_lock); -} - -void mali_utilization_core_start(u64 time_now) -{ - if (_mali_osk_atomic_inc_return(&num_running_cores) == 1) - { - /* - * We went from zero cores working, to one core working, - * we now consider the entire GPU for being busy - */ - - _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - if (time_now < period_start_time) - { - /* - * This might happen if the calculate_gpu_utilization() was able - * to run between the sampling of time_now and us grabbing the lock above - */ - time_now = period_start_time; - } - - work_start_time = time_now; - if (timer_running != MALI_TRUE) - { - timer_running = MALI_TRUE; - period_start_time = work_start_time; /* starting a new period */ - - _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT)); - } - else - { - _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); - } - } -} - -void mali_utilization_core_end(u64 time_now) -{ - if (_mali_osk_atomic_dec_return(&num_running_cores) == 0) - { - /* - * No more cores are working, so accumulate the time we was busy. - */ - _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - if (time_now < work_start_time) - { - /* - * This might happen if the calculate_gpu_utilization() was able - * to run between the sampling of time_now and us grabbing the lock above - */ - time_now = work_start_time; - } - - accumulated_work_time += (time_now - work_start_time); - work_start_time = 0; - - _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); - } -} diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h deleted file mode 100644 index 1f60517..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_KERNEL_UTILIZATION_H__ -#define __MALI_KERNEL_UTILIZATION_H__ - -#include "mali_osk.h" - -/** - * Initialize/start the Mali GPU utilization metrics reporting. - * - * @return _MALI_OSK_ERR_OK on success, otherwise failure. - */ -_mali_osk_errcode_t mali_utilization_init(void); - -/** - * Terminate the Mali GPU utilization metrics reporting - */ -void mali_utilization_term(void); - -/** - * Should be called when a job is about to execute a job - */ -void mali_utilization_core_start(u64 time_now); - -/** - * Should be called to stop the utilization timer during system suspend - */ -void mali_utilization_suspend(void); - -/** - * Should be called when a job has completed executing a job - */ -void mali_utilization_core_end(u64 time_now); - - -#endif /* __MALI_KERNEL_UTILIZATION_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c b/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c deleted file mode 100644 index 63c9f5b..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_ukk.h" - -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_osk_profiling.h" -#endif - -_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args) -{ - _mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event; - MALI_IGNORE(event); /* event is not used for release code, and that is OK */ - -#if MALI_TIMELINE_PROFILING_ENABLED - /* - * Manually generate user space events in kernel space. - * This saves user space from calling kernel space twice in this case. - * We just need to remember to add pid and tid manually. - */ - if ( event==_MALI_UK_VSYNC_EVENT_BEGIN_WAIT) - { - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC, - _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); - } - - if (event==_MALI_UK_VSYNC_EVENT_END_WAIT) - { - - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC, - _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); - } -#endif - - MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event)); - MALI_SUCCESS; -} - diff --git a/drivers/media/video/samsung/mali/common/mali_l2_cache.c b/drivers/media/video/samsung/mali/common/mali_l2_cache.c deleted file mode 100644 index b7267f1..0000000 --- a/drivers/media/video/samsung/mali/common/mali_l2_cache.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include "mali_kernel_common.h" -#include "mali_osk.h" - -#include "mali_l2_cache.h" -#include "mali_hw_core.h" -#include "mali_pm.h" - -/** - * Size of the Mali L2 cache registers in bytes - */ -#define MALI400_L2_CACHE_REGISTERS_SIZE 0x30 - -#define MALI_MAX_NUMBER_OF_L2_CACHE_CORES 3 - -/** - * Mali L2 cache register numbers - * Used in the register read/write routines. - * See the hardware documentation for more information about each register - */ -typedef enum mali_l2_cache_register { - MALI400_L2_CACHE_REGISTER_STATUS = 0x0008, - /*unused = 0x000C */ - MALI400_L2_CACHE_REGISTER_COMMAND = 0x0010, /**< Misc cache commands, e.g. clear */ - MALI400_L2_CACHE_REGISTER_CLEAR_PAGE = 0x0014, - MALI400_L2_CACHE_REGISTER_MAX_READS = 0x0018, /**< Limit of outstanding read requests */ - MALI400_L2_CACHE_REGISTER_ENABLE = 0x001C, /**< Enable misc cache features */ - MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0 = 0x0020, - MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0 = 0x0024, - MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1 = 0x0028, - MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1 = 0x002C, -} mali_l2_cache_register; - -/** - * Mali L2 cache commands - * These are the commands that can be sent to the Mali L2 cache unit - */ -typedef enum mali_l2_cache_command -{ - MALI400_L2_CACHE_COMMAND_CLEAR_ALL = 0x01, /**< Clear the entire cache */ - /* Read HW TRM carefully before adding/using other commands than the clear above */ -} mali_l2_cache_command; - -/** - * Mali L2 cache commands - * These are the commands that can be sent to the Mali L2 cache unit - */ -typedef enum mali_l2_cache_enable -{ - MALI400_L2_CACHE_ENABLE_DEFAULT = 0x0, /**< Default state of enable register */ - MALI400_L2_CACHE_ENABLE_ACCESS = 0x01, /**< Permit cacheable accesses */ - MALI400_L2_CACHE_ENABLE_READ_ALLOCATE = 0x02, /**< Permit cache read allocate */ -} mali_l2_cache_enable; - -/** - * Mali L2 cache status bits - */ -typedef enum mali_l2_cache_status -{ - MALI400_L2_CACHE_STATUS_COMMAND_BUSY = 0x01, /**< Command handler of L2 cache is busy */ - MALI400_L2_CACHE_STATUS_DATA_BUSY = 0x02, /**< L2 cache is busy handling data requests */ -} mali_l2_cache_status; - -/** - * Definition of the L2 cache core struct - * Used to track a L2 cache unit in the system. - * Contains information about the mapping of the registers - */ -struct mali_l2_cache_core -{ - struct mali_hw_core hw_core; /**< Common for all HW cores */ - u32 core_id; /**< Unique core ID */ - _mali_osk_lock_t *command_lock; /**< Serialize all L2 cache commands */ - _mali_osk_lock_t *counter_lock; /**< Synchronize L2 cache counter access */ - u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ - u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ -}; - -#define MALI400_L2_MAX_READS_DEFAULT 0x1C - -static struct mali_l2_cache_core *mali_global_l2_cache_cores[MALI_MAX_NUMBER_OF_L2_CACHE_CORES]; -static u32 mali_global_num_l2_cache_cores = 0; - -int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT; - -/* Local helper functions */ -static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val); - - -struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource) -{ - struct mali_l2_cache_core *cache = NULL; - - MALI_DEBUG_PRINT(2, ("Mali L2 cache: Creating Mali L2 cache: %s\n", resource->description)); - - if (mali_global_num_l2_cache_cores >= MALI_MAX_NUMBER_OF_L2_CACHE_CORES) - { - MALI_PRINT_ERROR(("Mali L2 cache: Too many L2 cache core objects created\n")); - return NULL; - } - - cache = _mali_osk_malloc(sizeof(struct mali_l2_cache_core)); - if (NULL != cache) - { - cache->core_id = mali_global_num_l2_cache_cores; - cache->counter_src0 = MALI_HW_CORE_NO_COUNTER; - cache->counter_src1 = MALI_HW_CORE_NO_COUNTER; - if (_MALI_OSK_ERR_OK == mali_hw_core_create(&cache->hw_core, resource, MALI400_L2_CACHE_REGISTERS_SIZE)) - { - cache->command_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, - 0, _MALI_OSK_LOCK_ORDER_L2_COMMAND); - if (NULL != cache->command_lock) - { - cache->counter_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, - 0, _MALI_OSK_LOCK_ORDER_L2_COUNTER); - if (NULL != cache->counter_lock) - { - if (_MALI_OSK_ERR_OK == mali_l2_cache_reset(cache)) - { - mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = cache; - mali_global_num_l2_cache_cores++; - - return cache; - } - else - { - MALI_PRINT_ERROR(("Mali L2 cache: Failed to reset L2 cache core %s\n", cache->hw_core.description)); - } - - _mali_osk_lock_term(cache->counter_lock); - } - else - { - MALI_PRINT_ERROR(("Mali L2 cache: Failed to create counter lock for L2 cache core %s\n", cache->hw_core.description)); - } - - _mali_osk_lock_term(cache->command_lock); - } - else - { - MALI_PRINT_ERROR(("Mali L2 cache: Failed to create command lock for L2 cache core %s\n", cache->hw_core.description)); - } - - mali_hw_core_delete(&cache->hw_core); - } - - _mali_osk_free(cache); - } - else - { - MALI_PRINT_ERROR(("Mali L2 cache: Failed to allocate memory for L2 cache core\n")); - } - - return NULL; -} - -void mali_l2_cache_delete(struct mali_l2_cache_core *cache) -{ - u32 i; - - /* reset to defaults */ - mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)MALI400_L2_MAX_READS_DEFAULT); - mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_DEFAULT); - - _mali_osk_lock_term(cache->counter_lock); - _mali_osk_lock_term(cache->command_lock); - mali_hw_core_delete(&cache->hw_core); - - for (i = 0; i < mali_global_num_l2_cache_cores; i++) - { - if (mali_global_l2_cache_cores[i] == cache) - { - mali_global_l2_cache_cores[i] = NULL; - mali_global_num_l2_cache_cores--; - } - } - - _mali_osk_free(cache); -} - -u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache) -{ - return cache->core_id; -} - -mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter) -{ - u32 value = 0; /* disabled src */ - mali_bool core_is_on; - - MALI_DEBUG_ASSERT_POINTER(cache); - - core_is_on = mali_l2_cache_lock_power_state(cache); - - _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); - - cache->counter_src0 = counter; - - if (MALI_HW_CORE_NO_COUNTER != counter) - { - value = counter; - } - - if (MALI_TRUE == core_is_on) - { - mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, value); - } - - _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); - - mali_l2_cache_unlock_power_state(cache); - - return MALI_TRUE; -} - -mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter) -{ - u32 value = 0; /* disabled src */ - mali_bool core_is_on; - - MALI_DEBUG_ASSERT_POINTER(cache); - - core_is_on = mali_l2_cache_lock_power_state(cache); - - _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); - - cache->counter_src1 = counter; - - if (MALI_HW_CORE_NO_COUNTER != counter) - { - value = counter; - } - - if (MALI_TRUE == core_is_on) - { - mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, value); - } - - _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); - - mali_l2_cache_unlock_power_state(cache); - - return MALI_TRUE; -} - -u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache) -{ - return cache->counter_src0; -} - -u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache) -{ - return cache->counter_src1; -} - -void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1) -{ - MALI_DEBUG_ASSERT(NULL != src0); - MALI_DEBUG_ASSERT(NULL != value0); - MALI_DEBUG_ASSERT(NULL != src1); - MALI_DEBUG_ASSERT(NULL != value1); - - /* Caller must hold the PM lock and know that we are powered on */ - - _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); - - *src0 = cache->counter_src0; - *src1 = cache->counter_src1; - - if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) - { - *value0 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0); - } - - if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) - { - *value1 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1); - } - - _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); -} - -struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index) -{ - if (MALI_MAX_NUMBER_OF_L2_CACHE_CORES > index) - { - return mali_global_l2_cache_cores[index]; - } - - return NULL; -} - -u32 mali_l2_cache_core_get_glob_num_l2_cores(void) -{ - return mali_global_num_l2_cache_cores; -} - -u32 mali_l2_cache_core_get_max_num_l2_cores(void) -{ - return MALI_MAX_NUMBER_OF_L2_CACHE_CORES; -} - -_mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache) -{ - /* Invalidate cache (just to keep it in a known state at startup) */ - mali_l2_cache_invalidate_all(cache); - - /* Enable cache */ - mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_ACCESS | (u32)MALI400_L2_CACHE_ENABLE_READ_ALLOCATE); - mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)mali_l2_max_reads); - - /* Restart any performance counters (if enabled) */ - _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); - - if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) - { - mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, cache->counter_src0); - } - - if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER) - { - mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, cache->counter_src1); - } - - _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache) -{ - return mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); -} - -_mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages) -{ - u32 i; - _mali_osk_errcode_t ret1, ret = _MALI_OSK_ERR_OK; - - for (i = 0; i < num_pages; i++) - { - ret1 = mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, pages[i]); - if (_MALI_OSK_ERR_OK != ret1) - { - ret = ret1; - } - } - - return ret; -} - -mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache) -{ - /* - * Take PM lock and check power state. - * Returns MALI_TRUE if module is powered on. - * Power state will not change until mali_l2_cache_unlock_power_state() is called. - */ - mali_pm_lock(); - return mali_pm_is_powered_on(); -} - -void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache) -{ - /* Release PM lock */ - mali_pm_unlock(); -} - -/* -------- local helper functions below -------- */ - - -static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val) -{ - int i = 0; - const int loop_count = 100000; - - /* - * Grab lock in order to send commands to the L2 cache in a serialized fashion. - * The L2 cache will ignore commands if it is busy. - */ - _mali_osk_lock_wait(cache->command_lock, _MALI_OSK_LOCKMODE_RW); - - /* First, wait for L2 cache command handler to go idle */ - - for (i = 0; i < loop_count; i++) - { - if (!(mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_STATUS) & (u32)MALI400_L2_CACHE_STATUS_COMMAND_BUSY)) - { - break; - } - } - - if (i == loop_count) - { - _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW); - MALI_DEBUG_PRINT(1, ( "Mali L2 cache: aborting wait for command interface to go idle\n")); - MALI_ERROR( _MALI_OSK_ERR_FAULT ); - } - - /* then issue the command */ - mali_hw_core_register_write(&cache->hw_core, reg, val); - - _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW); - - MALI_SUCCESS; -} diff --git a/drivers/media/video/samsung/mali/common/mali_l2_cache.h b/drivers/media/video/samsung/mali/common/mali_l2_cache.h deleted file mode 100644 index 5a8e4da..0000000 --- a/drivers/media/video/samsung/mali/common/mali_l2_cache.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_KERNEL_L2_CACHE_H__ -#define __MALI_KERNEL_L2_CACHE_H__ - -#include "mali_osk.h" - -struct mali_l2_cache_core; - -_mali_osk_errcode_t mali_l2_cache_initialize(void); -void mali_l2_cache_terminate(void); - -struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t * resource); -void mali_l2_cache_delete(struct mali_l2_cache_core *cache); - -u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache); - -mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter); -mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter); -u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache); -u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache); -void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1); -struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index); -u32 mali_l2_cache_core_get_glob_num_l2_cores(void); -u32 mali_l2_cache_core_get_max_num_l2_cores(void); - -_mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache); - -_mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache); -_mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages); - -mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache); -void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache); - -#endif /* __MALI_KERNEL_L2_CACHE_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_mem_validation.c b/drivers/media/video/samsung/mali/common/mali_mem_validation.c deleted file mode 100644 index ea9c428..0000000 --- a/drivers/media/video/samsung/mali/common/mali_mem_validation.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_mem_validation.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" - -#define MALI_INVALID_MEM_ADDR 0xFFFFFFFF - -typedef struct -{ - u32 phys_base; /**< Mali physical base of the memory, page aligned */ - u32 size; /**< size in bytes of the memory, multiple of page size */ -} _mali_mem_validation_t; - -static _mali_mem_validation_t mali_mem_validator = { MALI_INVALID_MEM_ADDR, MALI_INVALID_MEM_ADDR }; - -_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t *resource) -{ - /* Check that no other MEM_VALIDATION resources exist */ - if (MALI_INVALID_MEM_ADDR != mali_mem_validator.phys_base) - { - MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; another range is already specified\n", resource->description)); - return _MALI_OSK_ERR_FAULT; - } - - /* Check restrictions on page alignment */ - if ((0 != (resource->base & (~_MALI_OSK_CPU_PAGE_MASK))) || - (0 != (resource->size & (~_MALI_OSK_CPU_PAGE_MASK)))) - { - MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; incorrect alignment\n", resource->description)); - return _MALI_OSK_ERR_FAULT; - } - - mali_mem_validator.phys_base = resource->base; - mali_mem_validator.size = resource->size; - MALI_DEBUG_PRINT(2, ("Memory Validator '%s' installed for Mali physical address base=0x%08X, size=0x%08X\n", - resource->description, mali_mem_validator.phys_base, mali_mem_validator.size)); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size) -{ - if (phys_addr < (phys_addr + size)) /* Don't allow overflow (or zero size) */ - { - if ((0 == ( phys_addr & (~_MALI_OSK_CPU_PAGE_MASK))) && - (0 == ( size & (~_MALI_OSK_CPU_PAGE_MASK)))) - { - if ((phys_addr >= mali_mem_validator.phys_base) && - ((phys_addr + (size - 1)) >= mali_mem_validator.phys_base) && - (phys_addr <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) && - ((phys_addr + (size - 1)) <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) ) - { - MALI_DEBUG_PRINT(3, ("Accepted range 0x%08X + size 0x%08X (= 0x%08X)\n", phys_addr, size, (phys_addr + size - 1))); - return _MALI_OSK_ERR_OK; - } - } - } - - MALI_PRINT_ERROR(("MALI PHYSICAL RANGE VALIDATION ERROR: The range supplied was: phys_base=0x%08X, size=0x%08X\n", phys_addr, size)); - - return _MALI_OSK_ERR_FAULT; -} diff --git a/drivers/media/video/samsung/mali/common/mali_mem_validation.h b/drivers/media/video/samsung/mali/common/mali_mem_validation.h deleted file mode 100644 index 2043b44..0000000 --- a/drivers/media/video/samsung/mali/common/mali_mem_validation.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_MEM_VALIDATION_H__ -#define __MALI_MEM_VALIDATION_H__ - -#include "mali_osk.h" - -_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t * resource); -_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size); - -#endif /* __MALI_MEM_VALIDATION_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_memory.c b/drivers/media/video/samsung/mali/common/mali_memory.c deleted file mode 100644 index 75506ed..0000000 --- a/drivers/media/video/samsung/mali/common/mali_memory.c +++ /dev/null @@ -1,1319 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_kernel_descriptor_mapping.h" -#include "mali_mem_validation.h" -#include "mali_memory.h" -#include "mali_mmu_page_directory.h" -#include "mali_kernel_memory_engine.h" -#include "mali_block_allocator.h" -#include "mali_kernel_mem_os.h" -#include "mali_session.h" -#include "mali_l2_cache.h" -#include "mali_cluster.h" -#include "mali_group.h" -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 -#include "ump_kernel_interface.h" -#endif - -/* kernel side OS functions and user-kernel interface */ -#include "mali_osk.h" -#include "mali_osk_mali.h" -#include "mali_ukk.h" -#include "mali_osk_list.h" -#include "mali_osk_bitops.h" - -/** - * Per-session memory descriptor mapping table sizes - */ -#define MALI_MEM_DESCRIPTORS_INIT 64 -#define MALI_MEM_DESCRIPTORS_MAX 65536 - -typedef struct dedicated_memory_info -{ - u32 base; - u32 size; - struct dedicated_memory_info * next; -} dedicated_memory_info; - -/* types used for external_memory and ump_memory physical memory allocators, which are using the mali_allocation_engine */ -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 -typedef struct ump_mem_allocation -{ - mali_allocation_engine * engine; - mali_memory_allocation * descriptor; - u32 initial_offset; - u32 size_allocated; - ump_dd_handle ump_mem; -} ump_mem_allocation ; -#endif - -typedef struct external_mem_allocation -{ - mali_allocation_engine * engine; - mali_memory_allocation * descriptor; - u32 initial_offset; - u32 size; -} external_mem_allocation; - -/** - * @brief Internal function for unmapping memory - * - * Worker function for unmapping memory from a user-process. We assume that the - * session/descriptor's lock was obtained before entry. For example, the - * wrapper _mali_ukk_mem_munmap() will lock the descriptor, then call this - * function to do the actual unmapping. mali_memory_core_session_end() could - * also call this directly (depending on compilation options), having locked - * the descriptor. - * - * This function will fail if it is unable to put the MMU in stall mode (which - * might be the case if a page fault is also being processed). - * - * @param args see _mali_uk_mem_munmap_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ); - -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 -static void ump_memory_release(void * ctx, void * handle); -static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); -#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0*/ - - -static void external_memory_release(void * ctx, void * handle); -static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); - - -/* nop functions */ - -/* mali address manager needs to allocate page tables on allocate, write to page table(s) on map, write to page table(s) and release page tables on release */ -static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor); /* validates the range, allocates memory for the page tables if needed */ -static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size); -static void mali_address_manager_release(mali_memory_allocation * descriptor); - -/* MMU variables */ - -typedef struct mali_mmu_page_table_allocation -{ - _mali_osk_list_t list; - u32 * usage_map; - u32 usage_count; - u32 num_pages; - mali_page_table_block pages; -} mali_mmu_page_table_allocation; - -typedef struct mali_mmu_page_table_allocations -{ - _mali_osk_lock_t *lock; - _mali_osk_list_t partial; - _mali_osk_list_t full; - /* we never hold on to a empty allocation */ -} mali_mmu_page_table_allocations; - -static mali_kernel_mem_address_manager mali_address_manager = -{ - mali_address_manager_allocate, /* allocate */ - mali_address_manager_release, /* release */ - mali_address_manager_map, /* map_physical */ - NULL /* unmap_physical not present*/ -}; - -/* the mmu page table cache */ -static struct mali_mmu_page_table_allocations page_table_cache; - - -static mali_kernel_mem_address_manager process_address_manager = -{ - _mali_osk_mem_mapregion_init, /* allocate */ - _mali_osk_mem_mapregion_term, /* release */ - _mali_osk_mem_mapregion_map, /* map_physical */ - _mali_osk_mem_mapregion_unmap /* unmap_physical */ -}; - -static _mali_osk_errcode_t mali_mmu_page_table_cache_create(void); -static void mali_mmu_page_table_cache_destroy(void); - -static mali_allocation_engine memory_engine = NULL; -static mali_physical_memory_allocator * physical_memory_allocators = NULL; - -static dedicated_memory_info * mem_region_registrations = NULL; - -mali_allocation_engine mali_mem_get_memory_engine(void) -{ - return memory_engine; -} - -/* called during module init */ -_mali_osk_errcode_t mali_memory_initialize(void) -{ - _mali_osk_errcode_t err; - - MALI_DEBUG_PRINT(2, ("Memory system initializing\n")); - - err = mali_mmu_page_table_cache_create(); - if(_MALI_OSK_ERR_OK != err) - { - MALI_ERROR(err); - } - - memory_engine = mali_allocation_engine_create(&mali_address_manager, &process_address_manager); - MALI_CHECK_NON_NULL( memory_engine, _MALI_OSK_ERR_FAULT); - - MALI_SUCCESS; -} - -/* called if/when our module is unloaded */ -void mali_memory_terminate(void) -{ - MALI_DEBUG_PRINT(2, ("Memory system terminating\n")); - - mali_mmu_page_table_cache_destroy(); - - while ( NULL != mem_region_registrations) - { - dedicated_memory_info * m; - m = mem_region_registrations; - mem_region_registrations = m->next; - _mali_osk_mem_unreqregion(m->base, m->size); - _mali_osk_free(m); - } - - while ( NULL != physical_memory_allocators) - { - mali_physical_memory_allocator * m; - m = physical_memory_allocators; - physical_memory_allocators = m->next; - m->destroy(m); - } - - if (NULL != memory_engine) - { - mali_allocation_engine_destroy(memory_engine); - memory_engine = NULL; - } -} - -_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data * session_data) -{ - MALI_DEBUG_PRINT(5, ("Memory session begin\n")); - - /* create descriptor mapping table */ - session_data->descriptor_mapping = mali_descriptor_mapping_create(MALI_MEM_DESCRIPTORS_INIT, MALI_MEM_DESCRIPTORS_MAX); - - if (NULL == session_data->descriptor_mapping) - { - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - session_data->memory_lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK - | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_SESSION); - if (NULL == session_data->memory_lock) - { - mali_descriptor_mapping_destroy(session_data->descriptor_mapping); - _mali_osk_free(session_data); - MALI_ERROR(_MALI_OSK_ERR_FAULT); - } - - /* Init the session's memory allocation list */ - _MALI_OSK_INIT_LIST_HEAD( &session_data->memory_head ); - - MALI_DEBUG_PRINT(5, ("MMU session begin: success\n")); - MALI_SUCCESS; -} - -static void descriptor_table_cleanup_callback(int descriptor_id, void* map_target) -{ - mali_memory_allocation * descriptor; - - descriptor = (mali_memory_allocation*)map_target; - - MALI_DEBUG_PRINT(3, ("Cleanup of descriptor %d mapping to 0x%x in descriptor table\n", descriptor_id, map_target)); - MALI_DEBUG_ASSERT(descriptor); - - mali_allocation_engine_release_memory(memory_engine, descriptor); - _mali_osk_free(descriptor); -} - -void mali_memory_session_end(struct mali_session_data *session_data) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_BUSY; - - MALI_DEBUG_PRINT(3, ("MMU session end\n")); - - if (NULL == session_data) - { - MALI_DEBUG_PRINT(1, ("No session data found during session end\n")); - return; - } - - while (err == _MALI_OSK_ERR_BUSY) - { - /* Lock the session so we can modify the memory list */ - _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); - err = _MALI_OSK_ERR_OK; - - /* Free all memory engine allocations */ - if (0 == _mali_osk_list_empty(&session_data->memory_head)) - { - mali_memory_allocation *descriptor; - mali_memory_allocation *temp; - _mali_uk_mem_munmap_s unmap_args; - - MALI_DEBUG_PRINT(1, ("Memory found on session usage list during session termination\n")); - - unmap_args.ctx = session_data; - - /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */ - _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->memory_head, mali_memory_allocation, list) - { - MALI_DEBUG_PRINT(4, ("Freeing block with mali address 0x%x size %d mapped in user space at 0x%x\n", - descriptor->mali_address, descriptor->size, descriptor->size, descriptor->mapping) - ); - /* ASSERT that the descriptor's lock references the correct thing */ - MALI_DEBUG_ASSERT( descriptor->lock == session_data->memory_lock ); - /* Therefore, we have already locked the descriptor */ - - unmap_args.size = descriptor->size; - unmap_args.mapping = descriptor->mapping; - unmap_args.cookie = (u32)descriptor; - - /* - * This removes the descriptor from the list, and frees the descriptor - * - * Does not handle the _MALI_OSK_SPECIFIC_INDIRECT_MMAP case, since - * the only OS we are aware of that requires indirect MMAP also has - * implicit mmap cleanup. - */ - err = _mali_ukk_mem_munmap_internal( &unmap_args ); - - if (err == _MALI_OSK_ERR_BUSY) - { - _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); - /* - * Reason for this; - * We where unable to stall the MMU, probably because we are in page fault handling. - * Sleep for a while with the session lock released, then try again. - * Abnormal termination of programs with running Mali jobs is a normal reason for this. - */ - _mali_osk_time_ubusydelay(10); - break; /* Will jump back into: "while (err == _MALI_OSK_ERR_BUSY)" */ - } - } - } - } - /* Assert that we really did free everything */ - MALI_DEBUG_ASSERT( _mali_osk_list_empty(&session_data->memory_head) ); - - if (NULL != session_data->descriptor_mapping) - { - mali_descriptor_mapping_call_for_each(session_data->descriptor_mapping, descriptor_table_cleanup_callback); - mali_descriptor_mapping_destroy(session_data->descriptor_mapping); - session_data->descriptor_mapping = NULL; - } - - _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - /** - * @note Could the VMA close handler mean that we use the session data after it was freed? - * In which case, would need to refcount the session data, and free on VMA close - */ - - /* Free the lock */ - _mali_osk_lock_term( session_data->memory_lock ); - - return; -} - -_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource) -{ - mali_physical_memory_allocator * allocator; - mali_physical_memory_allocator ** next_allocator_list; - - u32 alloc_order = resource->alloc_order; - - allocator = mali_os_allocator_create(resource->size, resource->cpu_usage_adjust, resource->description); - if (NULL == allocator) - { - MALI_DEBUG_PRINT(1, ("Failed to create OS memory allocator\n")); - MALI_ERROR(_MALI_OSK_ERR_FAULT); - } - - allocator->alloc_order = alloc_order; - - /* link in the allocator: insertion into ordered list - * resources of the same alloc_order will be Last-in-first */ - next_allocator_list = &physical_memory_allocators; - - while (NULL != *next_allocator_list && - (*next_allocator_list)->alloc_order < alloc_order ) - { - next_allocator_list = &((*next_allocator_list)->next); - } - - allocator->next = (*next_allocator_list); - (*next_allocator_list) = allocator; - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource) -{ - mali_physical_memory_allocator * allocator; - mali_physical_memory_allocator ** next_allocator_list; - dedicated_memory_info * cleanup_data; - - u32 alloc_order = resource->alloc_order; - - /* do the low level linux operation first */ - - /* Request ownership of the memory */ - if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(resource->base, resource->size, resource->description)) - { - MALI_DEBUG_PRINT(1, ("Failed to request memory region %s (0x%08X - 0x%08X)\n", resource->description, resource->base, resource->base + resource->size - 1)); - MALI_ERROR(_MALI_OSK_ERR_FAULT); - } - - /* create generic block allocator object to handle it */ - allocator = mali_block_allocator_create(resource->base, resource->cpu_usage_adjust, resource->size, resource->description ); - - if (NULL == allocator) - { - MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n")); - _mali_osk_mem_unreqregion(resource->base, resource->size); - MALI_ERROR(_MALI_OSK_ERR_FAULT); - } - - /* save low level cleanup info */ - allocator->alloc_order = alloc_order; - - cleanup_data = _mali_osk_malloc(sizeof(dedicated_memory_info)); - - if (NULL == cleanup_data) - { - _mali_osk_mem_unreqregion(resource->base, resource->size); - allocator->destroy(allocator); - MALI_ERROR(_MALI_OSK_ERR_FAULT); - } - - cleanup_data->base = resource->base; - cleanup_data->size = resource->size; - - cleanup_data->next = mem_region_registrations; - mem_region_registrations = cleanup_data; - - /* link in the allocator: insertion into ordered list - * resources of the same alloc_order will be Last-in-first */ - next_allocator_list = &physical_memory_allocators; - - while ( NULL != *next_allocator_list && - (*next_allocator_list)->alloc_order < alloc_order ) - { - next_allocator_list = &((*next_allocator_list)->next); - } - - allocator->next = (*next_allocator_list); - (*next_allocator_list) = allocator; - - MALI_SUCCESS; -} - -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 -static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) -{ - ump_dd_handle ump_mem; - u32 nr_blocks; - u32 i; - ump_dd_physical_block * ump_blocks; - ump_mem_allocation *ret_allocation; - - MALI_DEBUG_ASSERT_POINTER(ctx); - MALI_DEBUG_ASSERT_POINTER(engine); - MALI_DEBUG_ASSERT_POINTER(descriptor); - MALI_DEBUG_ASSERT_POINTER(alloc_info); - - ret_allocation = _mali_osk_malloc( sizeof( ump_mem_allocation ) ); - if ( NULL==ret_allocation ) return MALI_MEM_ALLOC_INTERNAL_FAILURE; - - ump_mem = (ump_dd_handle)ctx; - - MALI_DEBUG_PRINT(4, ("In ump_memory_commit\n")); - - nr_blocks = ump_dd_phys_block_count_get(ump_mem); - - MALI_DEBUG_PRINT(4, ("Have %d blocks\n", nr_blocks)); - - if (nr_blocks == 0) - { - MALI_DEBUG_PRINT(1, ("No block count\n")); - _mali_osk_free( ret_allocation ); - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - - ump_blocks = _mali_osk_malloc(sizeof(*ump_blocks)*nr_blocks ); - if ( NULL==ump_blocks ) - { - _mali_osk_free( ret_allocation ); - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - - if (UMP_DD_INVALID == ump_dd_phys_blocks_get(ump_mem, ump_blocks, nr_blocks)) - { - _mali_osk_free(ump_blocks); - _mali_osk_free( ret_allocation ); - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - - /* Store away the initial offset for unmapping purposes */ - ret_allocation->initial_offset = *offset; - - for(i=0; iinitial_offset; - MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n")); - - /* unmap all previous blocks (if any) */ - mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 ); - - _mali_osk_free(ump_blocks); - _mali_osk_free(ret_allocation); - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - *offset += ump_blocks[i].size; - } - - if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) - { - /* Map in an extra virtual guard page at the end of the VMA */ - MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n")); - if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[0].addr , 0, _MALI_OSK_MALI_PAGE_SIZE )) - { - u32 size_allocated = *offset - ret_allocation->initial_offset; - MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n")); - - /* unmap all previous blocks (if any) */ - mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 ); - - _mali_osk_free(ump_blocks); - _mali_osk_free(ret_allocation); - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - *offset += _MALI_OSK_MALI_PAGE_SIZE; - } - - _mali_osk_free( ump_blocks ); - - ret_allocation->engine = engine; - ret_allocation->descriptor = descriptor; - ret_allocation->ump_mem = ump_mem; - ret_allocation->size_allocated = *offset - ret_allocation->initial_offset; - - alloc_info->ctx = NULL; - alloc_info->handle = ret_allocation; - alloc_info->next = NULL; - alloc_info->release = ump_memory_release; - - return MALI_MEM_ALLOC_FINISHED; -} - -static void ump_memory_release(void * ctx, void * handle) -{ - ump_dd_handle ump_mem; - ump_mem_allocation *allocation; - - allocation = (ump_mem_allocation *)handle; - - MALI_DEBUG_ASSERT_POINTER( allocation ); - - ump_mem = allocation->ump_mem; - - MALI_DEBUG_ASSERT(UMP_DD_HANDLE_INVALID!=ump_mem); - - /* At present, this is a no-op. But, it allows the mali_address_manager to - * do unmapping of a subrange in future. */ - mali_allocation_engine_unmap_physical( allocation->engine, - allocation->descriptor, - allocation->initial_offset, - allocation->size_allocated, - (_mali_osk_mem_mapregion_flags_t)0 - ); - _mali_osk_free( allocation ); - - - ump_dd_reference_release(ump_mem) ; - return; -} - -_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args ) -{ - ump_dd_handle ump_mem; - mali_physical_memory_allocator external_memory_allocator; - struct mali_session_data *session_data; - mali_memory_allocation * descriptor; - int md; - - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - session_data = (struct mali_session_data *)args->ctx; - MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); - - /* check arguments */ - /* NULL might be a valid Mali address */ - if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); - - /* size must be a multiple of the system page size */ - if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); - - MALI_DEBUG_PRINT(3, - ("Requested to map ump memory with secure id %d into virtual memory 0x%08X, size 0x%08X\n", - args->secure_id, args->mali_address, args->size)); - - ump_mem = ump_dd_handle_create_from_secure_id( (int)args->secure_id ) ; - - if ( UMP_DD_HANDLE_INVALID==ump_mem ) MALI_ERROR(_MALI_OSK_ERR_FAULT); - - descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); - if (NULL == descriptor) - { - ump_dd_reference_release(ump_mem); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - descriptor->size = args->size; - descriptor->mapping = NULL; - descriptor->mali_address = args->mali_address; - descriptor->mali_addr_mapping_info = (void*)session_data; - descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ - descriptor->cache_settings = (u32) MALI_CACHE_STANDARD; - descriptor->lock = session_data->memory_lock; - - if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) - { - descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; - } - _mali_osk_list_init( &descriptor->list ); - - if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md)) - { - ump_dd_reference_release(ump_mem); - _mali_osk_free(descriptor); - MALI_ERROR(_MALI_OSK_ERR_FAULT); - } - - external_memory_allocator.allocate = ump_memory_commit; - external_memory_allocator.allocate_page_table_block = NULL; - external_memory_allocator.ctx = ump_mem; - external_memory_allocator.name = "UMP Memory"; - external_memory_allocator.next = NULL; - - _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); - - if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL)) - { - _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); - mali_descriptor_mapping_free(session_data->descriptor_mapping, md); - ump_dd_reference_release(ump_mem); - _mali_osk_free(descriptor); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); - - args->cookie = md; - - MALI_DEBUG_PRINT(5,("Returning from UMP attach\n")); - - /* All OK */ - MALI_SUCCESS; -} - - -_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args ) -{ - mali_memory_allocation * descriptor; - struct mali_session_data *session_data; - - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - session_data = (struct mali_session_data *)args->ctx; - MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); - - if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor)) - { - MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release ump memory\n", args->cookie)); - MALI_ERROR(_MALI_OSK_ERR_FAULT); - } - - descriptor = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie); - - if (NULL != descriptor) - { - _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - mali_allocation_engine_release_memory(memory_engine, descriptor); - - _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - _mali_osk_free(descriptor); - } - - MALI_SUCCESS; - -} -#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 */ - - -static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) -{ - u32 * data; - external_mem_allocation * ret_allocation; - - MALI_DEBUG_ASSERT_POINTER(ctx); - MALI_DEBUG_ASSERT_POINTER(engine); - MALI_DEBUG_ASSERT_POINTER(descriptor); - MALI_DEBUG_ASSERT_POINTER(alloc_info); - - ret_allocation = _mali_osk_malloc( sizeof(external_mem_allocation) ); - - if ( NULL == ret_allocation ) - { - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - - data = (u32*)ctx; - - ret_allocation->engine = engine; - ret_allocation->descriptor = descriptor; - ret_allocation->initial_offset = *offset; - - alloc_info->ctx = NULL; - alloc_info->handle = ret_allocation; - alloc_info->next = NULL; - alloc_info->release = external_memory_release; - - MALI_DEBUG_PRINT(5, ("External map: mapping phys 0x%08X at mali virtual address 0x%08X staring at offset 0x%08X length 0x%08X\n", data[0], descriptor->mali_address, *offset, data[1])); - - if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, data[1])) - { - MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n")); - _mali_osk_free(ret_allocation); - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - *offset += data[1]; - - if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) - { - /* Map in an extra virtual guard page at the end of the VMA */ - MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n")); - if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, _MALI_OSK_MALI_PAGE_SIZE)) - { - u32 size_allocated = *offset - ret_allocation->initial_offset; - MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n")); - - /* unmap what we previously mapped */ - mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 ); - _mali_osk_free(ret_allocation); - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - *offset += _MALI_OSK_MALI_PAGE_SIZE; - } - - ret_allocation->size = *offset - ret_allocation->initial_offset; - - return MALI_MEM_ALLOC_FINISHED; -} - -static void external_memory_release(void * ctx, void * handle) -{ - external_mem_allocation * allocation; - - allocation = (external_mem_allocation *) handle; - MALI_DEBUG_ASSERT_POINTER( allocation ); - - /* At present, this is a no-op. But, it allows the mali_address_manager to - * do unmapping of a subrange in future. */ - - mali_allocation_engine_unmap_physical( allocation->engine, - allocation->descriptor, - allocation->initial_offset, - allocation->size, - (_mali_osk_mem_mapregion_flags_t)0 - ); - - _mali_osk_free( allocation ); - - return; -} - -_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args ) -{ - mali_physical_memory_allocator external_memory_allocator; - struct mali_session_data *session_data; - u32 info[2]; - mali_memory_allocation * descriptor; - int md; - - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - session_data = (struct mali_session_data *)args->ctx; - MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); - - external_memory_allocator.allocate = external_memory_commit; - external_memory_allocator.allocate_page_table_block = NULL; - external_memory_allocator.ctx = &info[0]; - external_memory_allocator.name = "External Memory"; - external_memory_allocator.next = NULL; - - /* check arguments */ - /* NULL might be a valid Mali address */ - if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); - - /* size must be a multiple of the system page size */ - if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); - - MALI_DEBUG_PRINT(3, - ("Requested to map physical memory 0x%x-0x%x into virtual memory 0x%x\n", - (void*)args->phys_addr, - (void*)(args->phys_addr + args->size -1), - (void*)args->mali_address) - ); - - /* Validate the mali physical range */ - if (_MALI_OSK_ERR_OK != mali_mem_validation_check(args->phys_addr, args->size)) - { - return _MALI_OSK_ERR_FAULT; - } - - info[0] = args->phys_addr; - info[1] = args->size; - - descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); - if (NULL == descriptor) MALI_ERROR(_MALI_OSK_ERR_NOMEM); - - descriptor->size = args->size; - descriptor->mapping = NULL; - descriptor->mali_address = args->mali_address; - descriptor->mali_addr_mapping_info = (void*)session_data; - descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ - descriptor->cache_settings = (u32)MALI_CACHE_STANDARD; - descriptor->lock = session_data->memory_lock; - if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) - { - descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; - } - _mali_osk_list_init( &descriptor->list ); - - _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); - - if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL)) - { - _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_free(descriptor); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); - - if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md)) - { - mali_allocation_engine_release_memory(memory_engine, descriptor); - _mali_osk_free(descriptor); - MALI_ERROR(_MALI_OSK_ERR_FAULT); - } - - args->cookie = md; - - MALI_DEBUG_PRINT(5,("Returning from range_map_external_memory\n")); - - /* All OK */ - MALI_SUCCESS; -} - - -_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args ) -{ - mali_memory_allocation * descriptor; - void* old_value; - struct mali_session_data *session_data; - - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - session_data = (struct mali_session_data *)args->ctx; - MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); - - if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor)) - { - MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to unmap external memory\n", args->cookie)); - MALI_ERROR(_MALI_OSK_ERR_FAULT); - } - - old_value = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie); - - if (NULL != old_value) - { - _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - mali_allocation_engine_release_memory(memory_engine, descriptor); - - _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - _mali_osk_free(descriptor); - } - - MALI_SUCCESS; -} - -_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args ) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - args->memory_size = 2 * 1024 * 1024 * 1024UL; /* 2GB address space */ - args->mali_address_base = 1 * 1024 * 1024 * 1024UL; /* staring at 1GB, causing this layout: (0-1GB unused)(1GB-3G usage by Mali)(3G-4G unused) */ - MALI_SUCCESS; -} - -_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args ) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - MALI_SUCCESS; -} - -static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor) -{ - struct mali_session_data *session_data; - u32 actual_size; - - MALI_DEBUG_ASSERT_POINTER(descriptor); - - session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; - - actual_size = descriptor->size; - - if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) - { - actual_size += _MALI_OSK_MALI_PAGE_SIZE; - } - - return mali_mmu_pagedir_map(session_data->page_directory, descriptor->mali_address, actual_size); -} - -static void mali_address_manager_release(mali_memory_allocation * descriptor) -{ - const u32 illegal_mali_address = 0xffffffff; - struct mali_session_data *session_data; - MALI_DEBUG_ASSERT_POINTER(descriptor); - - /* It is allowed to call this function several times on the same descriptor. - When memory is released we set the illegal_mali_address so we can early out here. */ - if ( illegal_mali_address == descriptor->mali_address) return; - - session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; - mali_mmu_pagedir_unmap(session_data->page_directory, descriptor->mali_address, descriptor->size); - - descriptor->mali_address = illegal_mali_address ; -} - -static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size) -{ - struct mali_session_data *session_data; - u32 mali_address; - - MALI_DEBUG_ASSERT_POINTER(descriptor); - MALI_DEBUG_ASSERT_POINTER(phys_addr); - - session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; - MALI_DEBUG_ASSERT_POINTER(session_data); - - mali_address = descriptor->mali_address + offset; - - MALI_DEBUG_PRINT(7, ("Mali map: mapping 0x%08X to Mali address 0x%08X length 0x%08X\n", *phys_addr, mali_address, size)); - - mali_mmu_pagedir_update(session_data->page_directory, mali_address, *phys_addr, size, descriptor->cache_settings); - - MALI_SUCCESS; -} - -/* This handler registered to mali_mmap for MMU builds */ -_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args ) -{ - struct mali_session_data *session_data; - mali_memory_allocation * descriptor; - - /* validate input */ - if (NULL == args) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: args was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); } - - /* Unpack arguments */ - session_data = (struct mali_session_data *)args->ctx; - - /* validate input */ - if (NULL == session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_FAULT); } - - descriptor = (mali_memory_allocation*) _mali_osk_calloc( 1, sizeof(mali_memory_allocation) ); - if (NULL == descriptor) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: descriptor was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_NOMEM); } - - descriptor->size = args->size; - descriptor->mali_address = args->phys_addr; - descriptor->mali_addr_mapping_info = (void*)session_data; - - descriptor->process_addr_mapping_info = args->ukk_private; /* save to be used during physical manager callback */ - descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE; - descriptor->cache_settings = (u32) args->cache_settings ; - descriptor->lock = session_data->memory_lock; - _mali_osk_list_init( &descriptor->list ); - - _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); - - if (0 == mali_allocation_engine_allocate_memory(memory_engine, descriptor, physical_memory_allocators, &session_data->memory_head)) - { - /* We do not FLUSH nor TLB_ZAP on MMAP, since we do both of those on job start*/ - _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); - - args->mapping = descriptor->mapping; - args->cookie = (u32)descriptor; - - MALI_DEBUG_PRINT(7, ("MMAP OK\n")); - MALI_SUCCESS; - } - else - { - _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); - /* OOM, but not a fatal error */ - MALI_DEBUG_PRINT(4, ("Memory allocation failure, OOM\n")); - _mali_osk_free(descriptor); - /* Linux will free the CPU address allocation, userspace client the Mali address allocation */ - MALI_ERROR(_MALI_OSK_ERR_FAULT); - } -} - -static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ) -{ - struct mali_session_data *session_data; - mali_memory_allocation * descriptor; - - u32 num_groups = mali_group_get_glob_num_groups(); - struct mali_group *group; - u32 i; - - descriptor = (mali_memory_allocation *)args->cookie; - MALI_DEBUG_ASSERT_POINTER(descriptor); - - /** @note args->context unused; we use the memory_session from the cookie */ - /* args->mapping and args->size are also discarded. They are only necessary - for certain do_munmap implementations. However, they could be used to check the - descriptor at this point. */ - - session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; - MALI_DEBUG_ASSERT_POINTER(session_data); - - /* Unmapping the memory from the mali virtual address space. - It is allowed to call this function severeal times, which might happen if zapping below fails. */ - mali_allocation_engine_release_pt1_mali_pagetables_unmap(memory_engine, descriptor); - -#ifdef MALI_UNMAP_FLUSH_ALL_MALI_L2 - { - u32 number_of_clusters = mali_cluster_get_glob_num_clusters(); - for (i = 0; i < number_of_clusters; i++) - { - struct mali_cluster *cluster; - cluster = mali_cluster_get_global_cluster(i); - if( mali_cluster_power_is_enabled_get(cluster) ) - { - mali_cluster_l2_cache_invalidate_all_force(cluster); - } - } - } -#endif - - for (i = 0; i < num_groups; i++) - { - group = mali_group_get_glob_group(i); - mali_group_lock(group); - mali_group_remove_session_if_unused(group, session_data); - if (mali_group_get_session(group) == session_data) - { - /* The Zap also does the stall and disable_stall */ - mali_bool zap_success = mali_mmu_zap_tlb(mali_group_get_mmu(group)); - if (MALI_TRUE != zap_success) - { - MALI_DEBUG_PRINT(2, ("Mali memory unmap failed. Doing pagefault handling.\n")); - mali_group_bottom_half(group, GROUP_EVENT_MMU_PAGE_FAULT); - /* The bottom half will also do the unlock */ - continue; - } - } - mali_group_unlock(group); - } - - /* Removes the descriptor from the session's memory list, releases physical memory, releases descriptor */ - mali_allocation_engine_release_pt2_physical_memory_free(memory_engine, descriptor); - - _mali_osk_free(descriptor); - - return _MALI_OSK_ERR_OK; -} - -/* Handler for unmapping memory for MMU builds */ -_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args ) -{ - mali_memory_allocation * descriptor; - _mali_osk_lock_t *descriptor_lock; - _mali_osk_errcode_t err; - - descriptor = (mali_memory_allocation *)args->cookie; - MALI_DEBUG_ASSERT_POINTER(descriptor); - - /** @note args->context unused; we use the memory_session from the cookie */ - /* args->mapping and args->size are also discarded. They are only necessary - for certain do_munmap implementations. However, they could be used to check the - descriptor at this point. */ - - MALI_DEBUG_ASSERT_POINTER((struct mali_session_data *)descriptor->mali_addr_mapping_info); - - descriptor_lock = descriptor->lock; /* should point to the session data lock... */ - - err = _MALI_OSK_ERR_BUSY; - while (err == _MALI_OSK_ERR_BUSY) - { - if (descriptor_lock) - { - _mali_osk_lock_wait( descriptor_lock, _MALI_OSK_LOCKMODE_RW ); - } - - err = _mali_ukk_mem_munmap_internal( args ); - - if (descriptor_lock) - { - _mali_osk_lock_signal( descriptor_lock, _MALI_OSK_LOCKMODE_RW ); - } - - if (err == _MALI_OSK_ERR_BUSY) - { - /* - * Reason for this; - * We where unable to stall the MMU, probably because we are in page fault handling. - * Sleep for a while with the session lock released, then try again. - * Abnormal termination of programs with running Mali jobs is a normal reason for this. - */ - _mali_osk_time_ubusydelay(10); - } - } - - return err; -} - -u32 _mali_ukk_report_memory_usage(void) -{ - return mali_allocation_engine_memory_usage(physical_memory_allocators); -} - -_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping) -{ - _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); - - if (0 == _mali_osk_list_empty(&page_table_cache.partial)) - { - mali_mmu_page_table_allocation * alloc = _MALI_OSK_LIST_ENTRY(page_table_cache.partial.next, mali_mmu_page_table_allocation, list); - int page_number = _mali_osk_find_first_zero_bit(alloc->usage_map, alloc->num_pages); - MALI_DEBUG_PRINT(6, ("Partial page table allocation found, using page offset %d\n", page_number)); - _mali_osk_set_nonatomic_bit(page_number, alloc->usage_map); - alloc->usage_count++; - if (alloc->num_pages == alloc->usage_count) - { - /* full, move alloc to full list*/ - _mali_osk_list_move(&alloc->list, &page_table_cache.full); - } - _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); - - *table_page = (MALI_MMU_PAGE_SIZE * page_number) + alloc->pages.phys_base; - *mapping = (mali_io_address)((MALI_MMU_PAGE_SIZE * page_number) + (u32)alloc->pages.mapping); - MALI_DEBUG_PRINT(4, ("Page table allocated for VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page )); - MALI_SUCCESS; - } - else - { - mali_mmu_page_table_allocation * alloc; - /* no free pages, allocate a new one */ - - alloc = (mali_mmu_page_table_allocation *)_mali_osk_calloc(1, sizeof(mali_mmu_page_table_allocation)); - if (NULL == alloc) - { - _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); - *table_page = MALI_INVALID_PAGE; - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - _MALI_OSK_INIT_LIST_HEAD(&alloc->list); - - if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_page_tables(memory_engine, &alloc->pages, physical_memory_allocators)) - { - MALI_DEBUG_PRINT(1, ("No more memory for page tables\n")); - _mali_osk_free(alloc); - _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); - *table_page = MALI_INVALID_PAGE; - *mapping = NULL; - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - /* create the usage map */ - alloc->num_pages = alloc->pages.size / MALI_MMU_PAGE_SIZE; - alloc->usage_count = 1; - MALI_DEBUG_PRINT(3, ("New page table cache expansion, %d pages in new cache allocation\n", alloc->num_pages)); - alloc->usage_map = _mali_osk_calloc(1, ((alloc->num_pages + BITS_PER_LONG - 1) & ~(BITS_PER_LONG-1) / BITS_PER_LONG) * sizeof(unsigned long)); - if (NULL == alloc->usage_map) - { - MALI_DEBUG_PRINT(1, ("Failed to allocate memory to describe MMU page table cache usage\n")); - alloc->pages.release(&alloc->pages); - _mali_osk_free(alloc); - _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); - *table_page = MALI_INVALID_PAGE; - *mapping = NULL; - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - _mali_osk_set_nonatomic_bit(0, alloc->usage_map); - - if (alloc->num_pages > 1) - { - _mali_osk_list_add(&alloc->list, &page_table_cache.partial); - } - else - { - _mali_osk_list_add(&alloc->list, &page_table_cache.full); - } - - _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); - *table_page = alloc->pages.phys_base; /* return the first page */ - *mapping = alloc->pages.mapping; /* Mapping for first page */ - MALI_DEBUG_PRINT(4, ("Page table allocated: VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page )); - MALI_SUCCESS; - } -} - -void mali_mmu_release_table_page(u32 pa) -{ - mali_mmu_page_table_allocation * alloc, * temp_alloc; - - MALI_DEBUG_PRINT_IF(1, pa & 4095, ("Bad page address 0x%x given to mali_mmu_release_table_page\n", (void*)pa)); - - MALI_DEBUG_PRINT(4, ("Releasing table page 0x%08X to the cache\n", pa)); - - _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); - - /* find the entry this address belongs to */ - /* first check the partial list */ - _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.partial, mali_mmu_page_table_allocation, list) - { - u32 start = alloc->pages.phys_base; - u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE; - if (pa >= start && pa <= last) - { - MALI_DEBUG_ASSERT(0 != _mali_osk_test_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map)); - _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map); - alloc->usage_count--; - - _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE); - - if (0 == alloc->usage_count) - { - /* empty, release whole page alloc */ - _mali_osk_list_del(&alloc->list); - alloc->pages.release(&alloc->pages); - _mali_osk_free(alloc->usage_map); - _mali_osk_free(alloc); - } - _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); - MALI_DEBUG_PRINT(4, ("(partial list)Released table page 0x%08X to the cache\n", pa)); - return; - } - } - - /* the check the full list */ - _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.full, mali_mmu_page_table_allocation, list) - { - u32 start = alloc->pages.phys_base; - u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE; - if (pa >= start && pa <= last) - { - _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map); - alloc->usage_count--; - - _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE); - - - if (0 == alloc->usage_count) - { - /* empty, release whole page alloc */ - _mali_osk_list_del(&alloc->list); - alloc->pages.release(&alloc->pages); - _mali_osk_free(alloc->usage_map); - _mali_osk_free(alloc); - } - else - { - /* transfer to partial list */ - _mali_osk_list_move(&alloc->list, &page_table_cache.partial); - } - - _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); - MALI_DEBUG_PRINT(4, ("(full list)Released table page 0x%08X to the cache\n", pa)); - return; - } - } - - MALI_DEBUG_PRINT(1, ("pa 0x%x not found in the page table cache\n", (void*)pa)); - - _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); -} - -static _mali_osk_errcode_t mali_mmu_page_table_cache_create(void) -{ - page_table_cache.lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK - | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE); - MALI_CHECK_NON_NULL( page_table_cache.lock, _MALI_OSK_ERR_FAULT ); - _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.partial); - _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.full); - MALI_SUCCESS; -} - -static void mali_mmu_page_table_cache_destroy(void) -{ - mali_mmu_page_table_allocation * alloc, *temp; - - _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.partial, mali_mmu_page_table_allocation, list) - { - MALI_DEBUG_PRINT_IF(1, 0 != alloc->usage_count, ("Destroying page table cache while pages are tagged as in use. %d allocations still marked as in use.\n", alloc->usage_count)); - _mali_osk_list_del(&alloc->list); - alloc->pages.release(&alloc->pages); - _mali_osk_free(alloc->usage_map); - _mali_osk_free(alloc); - } - - MALI_DEBUG_PRINT_IF(1, 0 == _mali_osk_list_empty(&page_table_cache.full), ("Page table cache full list contains one or more elements \n")); - - _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.full, mali_mmu_page_table_allocation, list) - { - MALI_DEBUG_PRINT(1, ("Destroy alloc 0x%08X with usage count %d\n", (u32)alloc, alloc->usage_count)); - _mali_osk_list_del(&alloc->list); - alloc->pages.release(&alloc->pages); - _mali_osk_free(alloc->usage_map); - _mali_osk_free(alloc); - } - - _mali_osk_lock_term(page_table_cache.lock); -} diff --git a/drivers/media/video/samsung/mali/common/mali_memory.h b/drivers/media/video/samsung/mali/common/mali_memory.h deleted file mode 100644 index 78e2945..0000000 --- a/drivers/media/video/samsung/mali/common/mali_memory.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_MEMORY_H__ -#define __MALI_MEMORY_H__ - -#include "mali_osk.h" -#include "mali_session.h" - -struct mali_cluster; -struct mali_group; - -/** @brief Initialize Mali memory subsystem - * - * Allocate and initialize internal data structures. Must be called before - * allocating Mali memory. - * - * @return On success _MALI_OSK_ERR_OK, othervise some error code describing the error. - */ -_mali_osk_errcode_t mali_memory_initialize(void); - -/** @brief Terminate Mali memory system - * - * Clean up and release internal data structures. - */ -void mali_memory_terminate(void); - -/** @brief Start new Mali memory session - * - * Allocate and prepare session specific memory allocation data data. The - * session page directory, lock, and descriptor map is set up. - * - * @param mali_session_data pointer to the session data structure - */ -_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data *mali_session_data); - -/** @brief Close a Mali memory session - * - * Release session specific memory allocation related data. - * - * @param mali_session_data pointer to the session data structure - */ -void mali_memory_session_end(struct mali_session_data *mali_session_data); - -/** @brief Allocate a page table page - * - * Allocate a page for use as a page directory or page table. The page is - * mapped into kernel space. - * - * @return _MALI_OSK_ERR_OK on success, othervise an error code - * @param table_page GPU pointer to the allocated page - * @param mapping CPU pointer to the mapping of the allocated page - */ -_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping); - -/** @brief Release a page table page - * - * Release a page table page allocated through \a mali_mmu_get_table_page - * - * @param pa the GPU address of the page to release - */ -void mali_mmu_release_table_page(u32 pa); - - -/** @brief Parse resource and prepare the OS memory allocator - */ -_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource); - -/** @brief Parse resource and prepare the dedicated memory allocator - */ -_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource); - -mali_allocation_engine mali_mem_get_memory_engine(void); - -#endif /* __MALI_MEMORY_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_mmu.c b/drivers/media/video/samsung/mali/common/mali_mmu.c deleted file mode 100644 index 2f2fa4d..0000000 --- a/drivers/media/video/samsung/mali/common/mali_mmu.c +++ /dev/null @@ -1,619 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_bitops.h" -#include "mali_osk_list.h" -#include "mali_ukk.h" - -#include "mali_mmu.h" -#include "mali_hw_core.h" -#include "mali_group.h" -#include "mali_mmu_page_directory.h" - -/** - * Size of the MMU registers in bytes - */ -#define MALI_MMU_REGISTERS_SIZE 0x24 - -/** - * MMU register numbers - * Used in the register read/write routines. - * See the hardware documentation for more information about each register - */ -typedef enum mali_mmu_register { - MALI_MMU_REGISTER_DTE_ADDR = 0x0000, /**< Current Page Directory Pointer */ - MALI_MMU_REGISTER_STATUS = 0x0004, /**< Status of the MMU */ - MALI_MMU_REGISTER_COMMAND = 0x0008, /**< Command register, used to control the MMU */ - MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x000C, /**< Logical address of the last page fault */ - MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x010, /**< Used to invalidate the mapping of a single page from the MMU */ - MALI_MMU_REGISTER_INT_RAWSTAT = 0x0014, /**< Raw interrupt status, all interrupts visible */ - MALI_MMU_REGISTER_INT_CLEAR = 0x0018, /**< Indicate to the MMU that the interrupt has been received */ - MALI_MMU_REGISTER_INT_MASK = 0x001C, /**< Enable/disable types of interrupts */ - MALI_MMU_REGISTER_INT_STATUS = 0x0020 /**< Interrupt status based on the mask */ -} mali_mmu_register; - -/** - * MMU interrupt register bits - * Each cause of the interrupt is reported - * through the (raw) interrupt status registers. - * Multiple interrupts can be pending, so multiple bits - * can be set at once. - */ -typedef enum mali_mmu_interrupt -{ - MALI_MMU_INTERRUPT_PAGE_FAULT = 0x01, /**< A page fault occured */ - MALI_MMU_INTERRUPT_READ_BUS_ERROR = 0x02 /**< A bus read error occured */ -} mali_mmu_interrupt; - -/** - * MMU commands - * These are the commands that can be sent - * to the MMU unit. - */ -typedef enum mali_mmu_command -{ - MALI_MMU_COMMAND_ENABLE_PAGING = 0x00, /**< Enable paging (memory translation) */ - MALI_MMU_COMMAND_DISABLE_PAGING = 0x01, /**< Disable paging (memory translation) */ - MALI_MMU_COMMAND_ENABLE_STALL = 0x02, /**< Enable stall on page fault */ - MALI_MMU_COMMAND_DISABLE_STALL = 0x03, /**< Disable stall on page fault */ - MALI_MMU_COMMAND_ZAP_CACHE = 0x04, /**< Zap the entire page table cache */ - MALI_MMU_COMMAND_PAGE_FAULT_DONE = 0x05, /**< Page fault processed */ - MALI_MMU_COMMAND_HARD_RESET = 0x06 /**< Reset the MMU back to power-on settings */ -} mali_mmu_command; - -typedef enum mali_mmu_status_bits -{ - MALI_MMU_STATUS_BIT_PAGING_ENABLED = 1 << 0, - MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE = 1 << 1, - MALI_MMU_STATUS_BIT_STALL_ACTIVE = 1 << 2, - MALI_MMU_STATUS_BIT_IDLE = 1 << 3, - MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY = 1 << 4, - MALI_MMU_STATUS_BIT_PAGE_FAULT_IS_WRITE = 1 << 5, -} mali_mmu_status_bits; - -/** - * Definition of the MMU struct - * Used to track a MMU unit in the system. - * Contains information about the mapping of the registers - */ -struct mali_mmu_core -{ - struct mali_hw_core hw_core; /**< Common for all HW cores */ - struct mali_group *group; /**< Parent core group */ - _mali_osk_irq_t *irq; /**< IRQ handler */ -}; - -/** - * The MMU interrupt handler - * Upper half of the MMU interrupt processing. - * Called by the kernel when the MMU has triggered an interrupt. - * The interrupt function supports IRQ sharing. So it'll probe the MMU in question - * @param irq The irq number (not used) - * @param dev_id Points to the MMU object being handled - * @param regs Registers of interrupted process (not used) - * @return Standard Linux interrupt result. - * Subset used by the driver is IRQ_HANDLED processed - * IRQ_NONE Not processed - */ -static _mali_osk_errcode_t mali_mmu_upper_half(void * data); - -/** - * The MMU reset hander - * Bottom half of the MMU interrupt processing for page faults and bus errors - * @param work The item to operate on, NULL in our case - */ -static void mali_mmu_bottom_half(void *data); - -static void mali_mmu_probe_trigger(void *data); -static _mali_osk_errcode_t mali_mmu_probe_ack(void *data); - -MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu); - -/* page fault queue flush helper pages - * note that the mapping pointers are currently unused outside of the initialization functions */ -static u32 mali_page_fault_flush_page_directory = MALI_INVALID_PAGE; -static u32 mali_page_fault_flush_page_table = MALI_INVALID_PAGE; -static u32 mali_page_fault_flush_data_page = MALI_INVALID_PAGE; - -/* an empty page directory (no address valid) which is active on any MMU not currently marked as in use */ -static u32 mali_empty_page_directory = MALI_INVALID_PAGE; - -_mali_osk_errcode_t mali_mmu_initialize(void) -{ - /* allocate the helper pages */ - mali_empty_page_directory = mali_allocate_empty_page(); - if(0 == mali_empty_page_directory) - { - mali_empty_page_directory = MALI_INVALID_PAGE; - return _MALI_OSK_ERR_NOMEM; - } - - if (_MALI_OSK_ERR_OK != mali_create_fault_flush_pages(&mali_page_fault_flush_page_directory, - &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page)) - { - mali_free_empty_page(mali_empty_page_directory); - return _MALI_OSK_ERR_FAULT; - } - - return _MALI_OSK_ERR_OK; -} - -void mali_mmu_terminate(void) -{ - MALI_DEBUG_PRINT(3, ("Mali MMU: terminating\n")); - - /* Free global helper pages */ - mali_free_empty_page(mali_empty_page_directory); - - /* Free the page fault flush pages */ - mali_destroy_fault_flush_pages(&mali_page_fault_flush_page_directory, - &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page); -} - -struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource) -{ - struct mali_mmu_core* mmu = NULL; - - MALI_DEBUG_ASSERT_POINTER(resource); - - MALI_DEBUG_PRINT(2, ("Mali MMU: Creating Mali MMU: %s\n", resource->description)); - - mmu = _mali_osk_calloc(1,sizeof(struct mali_mmu_core)); - if (NULL != mmu) - { - if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE)) - { - if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu)) - { - /* Setup IRQ handlers (which will do IRQ probing if needed) */ - mmu->irq = _mali_osk_irq_init(resource->irq, - mali_mmu_upper_half, - mali_mmu_bottom_half, - mali_mmu_probe_trigger, - mali_mmu_probe_ack, - mmu, - "mali_mmu_irq_handlers"); - if (NULL != mmu->irq) - { - return mmu; - } - else - { - MALI_PRINT_ERROR(("Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description)); - } - } - mali_hw_core_delete(&mmu->hw_core); - } - - _mali_osk_free(mmu); - } - else - { - MALI_PRINT_ERROR(("Failed to allocate memory for MMU\n")); - } - - return NULL; -} - -void mali_mmu_delete(struct mali_mmu_core *mmu) -{ - _mali_osk_irq_term(mmu->irq); - mali_hw_core_delete(&mmu->hw_core); - _mali_osk_free(mmu); -} - -void mali_mmu_set_group(struct mali_mmu_core *mmu, struct mali_group *group) -{ - mmu->group = group; -} - -static void mali_mmu_enable_paging(struct mali_mmu_core *mmu) -{ - const int max_loop_count = 100; - const int delay_in_usecs = 1; - int i; - - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING); - - for (i = 0; i < max_loop_count; ++i) - { - if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED) - { - break; - } - _mali_osk_time_ubusydelay(delay_in_usecs); - } - if (max_loop_count == i) - { - MALI_PRINT_ERROR(("Enable paging request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); - } -} - -mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu) -{ - const int max_loop_count = 100; - const int delay_in_usecs = 999; - int i; - u32 mmu_status; - - /* There are no group when it is called from mali_mmu_create */ - if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group); - - mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); - - if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) ) - { - MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enebled.\n")); - return MALI_TRUE; - } - - if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) - { - MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it is in pagefault state.\n")); - return MALI_FALSE; - } - - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL); - - for (i = 0; i < max_loop_count; ++i) - { - mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); - if ( mmu_status & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) - { - break; - } - if ( 0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED ))) - { - break; - } - _mali_osk_time_ubusydelay(delay_in_usecs); - } - if (max_loop_count == i) - { - MALI_PRINT_ERROR(("Enable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); - return MALI_FALSE; - } - - if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) - { - MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it has a pagefault.\n")); - return MALI_FALSE; - } - - return MALI_TRUE; -} - -void mali_mmu_disable_stall(struct mali_mmu_core *mmu) -{ - const int max_loop_count = 100; - const int delay_in_usecs = 1; - int i; - u32 mmu_status; - /* There are no group when it is called from mali_mmu_create */ - if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group); - - mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); - - if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) - { - MALI_DEBUG_PRINT(3, ("MMU disable skipped since it was not enabled.\n")); - return; - } - if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) - { - MALI_DEBUG_PRINT(2, ("Aborting MMU disable stall request since it is in pagefault state.\n")); - return; - } - - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL); - - for (i = 0; i < max_loop_count; ++i) - { - u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); - if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) ) - { - break; - } - if ( status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) - { - break; - } - if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) - { - break; - } - _mali_osk_time_ubusydelay(delay_in_usecs); - } - if (max_loop_count == i) MALI_DEBUG_PRINT(1,("Disable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); -} - -void mali_mmu_page_fault_done(struct mali_mmu_core *mmu) -{ - MALI_ASSERT_GROUP_LOCKED(mmu->group); - MALI_DEBUG_PRINT(4, ("Mali MMU: %s: Leaving page fault mode\n", mmu->hw_core.description)); - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE); -} - -MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu) -{ - const int max_loop_count = 100; - const int delay_in_usecs = 1; - int i; - /* The _if_ is neccessary when called from mali_mmu_create and NULL==group */ - if (mmu->group)MALI_ASSERT_GROUP_LOCKED(mmu->group); - - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE); - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_HARD_RESET); - - for (i = 0; i < max_loop_count; ++i) - { - if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR) == 0) - { - break; - } - _mali_osk_time_ubusydelay(delay_in_usecs); - } - if (max_loop_count == i) - { - MALI_PRINT_ERROR(("Reset request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); - return _MALI_OSK_ERR_FAULT; - } - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; - mali_bool stall_success; - MALI_DEBUG_ASSERT_POINTER(mmu); - /* The _if_ is neccessary when called from mali_mmu_create and NULL==group */ - if (mmu->group) - { - MALI_ASSERT_GROUP_LOCKED(mmu->group); - } - - stall_success = mali_mmu_enable_stall(mmu); - - /* The stall can not fail in current hw-state */ - MALI_DEBUG_ASSERT(stall_success); - - MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description)); - - if (_MALI_OSK_ERR_OK == mali_mmu_raw_reset(mmu)) - { - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR); - /* no session is active, so just activate the empty page directory */ - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory); - mali_mmu_enable_paging(mmu); - err = _MALI_OSK_ERR_OK; - } - mali_mmu_disable_stall(mmu); - - return err; -} - - -/* ------------- interrupt handling below ------------------ */ - -static _mali_osk_errcode_t mali_mmu_upper_half(void * data) -{ - struct mali_mmu_core *mmu = (struct mali_mmu_core *)data; - u32 int_stat; - - MALI_DEBUG_ASSERT_POINTER(mmu); - - /* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */ - int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS); - if (0 != int_stat) - { - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, 0); - mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); - - if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT) - { - _mali_osk_irq_schedulework(mmu->irq); - } - - if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR) - { - /* clear interrupt flag */ - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR); - /* reenable it */ - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, - mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK) | MALI_MMU_INTERRUPT_READ_BUS_ERROR); - MALI_PRINT_ERROR(("Mali MMU: Read bus error\n")); - } - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -static void mali_mmu_bottom_half(void * data) -{ - struct mali_mmu_core *mmu = (struct mali_mmu_core*)data; - u32 raw, status, fault_address; - - MALI_DEBUG_ASSERT_POINTER(mmu); - - MALI_DEBUG_PRINT(3, ("Mali MMU: Page fault bottom half: Locking subsystems\n")); - - mali_group_lock(mmu->group); /* Unlocked in mali_group_bottom_half */ - - if ( MALI_FALSE == mali_group_power_is_on(mmu->group) ) - { - MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.",mmu->hw_core.description)); - mali_group_unlock(mmu->group); - return; - } - - raw = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT); - status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); - - if ( (0==(raw & MALI_MMU_INTERRUPT_PAGE_FAULT)) && (0==(status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) ) - { - MALI_DEBUG_PRINT(2, ("Mali MMU: Page fault bottom half: No Irq found.\n")); - mali_group_unlock(mmu->group); - /* MALI_DEBUG_ASSERT(0); */ - return; - } - - /* An actual page fault has occurred. */ - - fault_address = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_PAGE_FAULT_ADDR); - - MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n", - (void*)fault_address, - (status >> 6) & 0x1F, - (status & 32) ? "write" : "read", - mmu->hw_core.description)); - - mali_group_bottom_half(mmu->group, GROUP_EVENT_MMU_PAGE_FAULT); /* Unlocks the group lock */ -} - -mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu) -{ - mali_bool stall_success; - MALI_ASSERT_GROUP_LOCKED(mmu->group); - - stall_success = mali_mmu_enable_stall(mmu); - - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); - - if (MALI_FALSE == stall_success) - { - /* False means that it is in Pagefault state. Not possible to disable_stall then */ - return MALI_FALSE; - } - - mali_mmu_disable_stall(mmu); - return MALI_TRUE; -} - -void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu) -{ - MALI_ASSERT_GROUP_LOCKED(mmu->group); - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); -} - - -void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address) -{ - MALI_ASSERT_GROUP_LOCKED(mmu->group); - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_ZAP_ONE_LINE, MALI_MMU_PDE_ENTRY(mali_address)); -} - -static void mali_mmu_activate_address_space(struct mali_mmu_core *mmu, u32 page_directory) -{ - MALI_ASSERT_GROUP_LOCKED(mmu->group); - /* The MMU must be in stalled or page fault mode, for this writing to work */ - MALI_DEBUG_ASSERT( 0 != ( mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) - & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) ); - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, page_directory); - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); - -} - -mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mali_page_directory *pagedir) -{ - mali_bool stall_success; - MALI_DEBUG_ASSERT_POINTER(mmu); - MALI_ASSERT_GROUP_LOCKED(mmu->group); - - MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description)); - stall_success = mali_mmu_enable_stall(mmu); - - if ( MALI_FALSE==stall_success ) return MALI_FALSE; - mali_mmu_activate_address_space(mmu, pagedir->page_directory); - mali_mmu_disable_stall(mmu); - return MALI_TRUE; -} - -void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu) -{ - mali_bool stall_success; - MALI_DEBUG_ASSERT_POINTER(mmu); - MALI_ASSERT_GROUP_LOCKED(mmu->group); - MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description)); - - stall_success = mali_mmu_enable_stall(mmu); - /* This function can only be called when the core is idle, so it could not fail. */ - MALI_DEBUG_ASSERT( stall_success ); - mali_mmu_activate_address_space(mmu, mali_empty_page_directory); - mali_mmu_disable_stall(mmu); -} - -void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu) -{ - mali_bool stall_success; - MALI_DEBUG_ASSERT_POINTER(mmu); - MALI_ASSERT_GROUP_LOCKED(mmu->group); - - MALI_DEBUG_PRINT(3, ("Activating the page fault flush page directory on MMU %s\n", mmu->hw_core.description)); - stall_success = mali_mmu_enable_stall(mmu); - /* This function is expect to fail the stalling, since it might be in PageFault mode when it is called */ - mali_mmu_activate_address_space(mmu, mali_page_fault_flush_page_directory); - if ( MALI_TRUE==stall_success ) mali_mmu_disable_stall(mmu); -} - -/* Is called when we want the mmu to give an interrupt */ -static void mali_mmu_probe_trigger(void *data) -{ - struct mali_mmu_core *mmu = (struct mali_mmu_core *)data; - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT, MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR); -} - -/* Is called when the irq probe wants the mmu to acknowledge an interrupt from the hw */ -static _mali_osk_errcode_t mali_mmu_probe_ack(void *data) -{ - struct mali_mmu_core *mmu = (struct mali_mmu_core *)data; - u32 int_stat; - - int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS); - - MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_acknowledge: intstat 0x%x\n", int_stat)); - if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT) - { - MALI_DEBUG_PRINT(2, ("Probe: Page fault detect: PASSED\n")); - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT); - } - else - { - MALI_DEBUG_PRINT(1, ("Probe: Page fault detect: FAILED\n")); - } - - if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR) - { - MALI_DEBUG_PRINT(2, ("Probe: Bus read error detect: PASSED\n")); - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR); - } - else - { - MALI_DEBUG_PRINT(1, ("Probe: Bus read error detect: FAILED\n")); - } - - if ( (int_stat & (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) == - (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) - { - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -#if 0 -void mali_mmu_print_state(struct mali_mmu_core *mmu) -{ - MALI_DEBUG_PRINT(2, ("MMU: State of %s is 0x%08x\n", mmu->hw_core.description, mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_mmu.h b/drivers/media/video/samsung/mali/common/mali_mmu.h deleted file mode 100644 index c7274b8..0000000 --- a/drivers/media/video/samsung/mali/common/mali_mmu.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_MMU_H__ -#define __MALI_MMU_H__ - -#include "mali_osk.h" -#include "mali_mmu_page_directory.h" - -/* Forward declaration from mali_group.h */ -struct mali_group; - -struct mali_mmu_core; - -_mali_osk_errcode_t mali_mmu_initialize(void); - -void mali_mmu_terminate(void); - -struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource); -void mali_mmu_set_group(struct mali_mmu_core *mmu, struct mali_group *group); -void mali_mmu_delete(struct mali_mmu_core *mmu); - -_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu); -mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu); -void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu); -void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address); - -mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core* mmu, struct mali_page_directory *pagedir); -void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu); -void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu); - -/** - * Issues the enable stall command to the MMU and waits for HW to complete the request - * @param mmu The MMU to enable paging for - * @return MALI_TRUE if HW stall was successfully engaged, otherwise MALI_FALSE (req timed out) - */ -mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu); - -/** - * Issues the disable stall command to the MMU and waits for HW to complete the request - * @param mmu The MMU to enable paging for - */ -void mali_mmu_disable_stall(struct mali_mmu_core *mmu); - -void mali_mmu_page_fault_done(struct mali_mmu_core *mmu); - - -#endif /* __MALI_MMU_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c deleted file mode 100644 index cc91ae9..0000000 --- a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_kernel_core.h" -#include "mali_osk.h" -#include "mali_uk_types.h" -#include "mali_mmu_page_directory.h" -#include "mali_memory.h" - -#include "mali_cluster.h" -#include "mali_group.h" - -static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data); - -u32 mali_allocate_empty_page(void) -{ - _mali_osk_errcode_t err; - mali_io_address mapping; - u32 address; - - if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&address, &mapping)) - { - /* Allocation failed */ - return 0; - } - - MALI_DEBUG_ASSERT_POINTER( mapping ); - - err = fill_page(mapping, 0); - if (_MALI_OSK_ERR_OK != err) - { - mali_mmu_release_table_page(address); - } - return address; -} - -void mali_free_empty_page(u32 address) -{ - if (MALI_INVALID_PAGE != address) - { - mali_mmu_release_table_page(address); - } -} - -_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page) -{ - _mali_osk_errcode_t err; - mali_io_address page_directory_mapping; - mali_io_address page_table_mapping; - mali_io_address data_page_mapping; - - err = mali_mmu_get_table_page(data_page, &data_page_mapping); - if (_MALI_OSK_ERR_OK == err) - { - err = mali_mmu_get_table_page(page_table, &page_table_mapping); - if (_MALI_OSK_ERR_OK == err) - { - err = mali_mmu_get_table_page(page_directory, &page_directory_mapping); - if (_MALI_OSK_ERR_OK == err) - { - fill_page(data_page_mapping, 0); - fill_page(page_table_mapping, *data_page | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT); - fill_page(page_directory_mapping, *page_table | MALI_MMU_FLAGS_PRESENT); - MALI_SUCCESS; - } - mali_mmu_release_table_page(*page_table); - *page_table = MALI_INVALID_PAGE; - } - mali_mmu_release_table_page(*data_page); - *data_page = MALI_INVALID_PAGE; - } - return err; -} - -void mali_destroy_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page) -{ - if (MALI_INVALID_PAGE != *page_directory) - { - mali_mmu_release_table_page(*page_directory); - *page_directory = MALI_INVALID_PAGE; - } - - if (MALI_INVALID_PAGE != *page_table) - { - mali_mmu_release_table_page(*page_table); - *page_table = MALI_INVALID_PAGE; - } - - if (MALI_INVALID_PAGE != *data_page) - { - mali_mmu_release_table_page(*data_page); - *data_page = MALI_INVALID_PAGE; - } -} - -static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data) -{ - int i; - MALI_DEBUG_ASSERT_POINTER( mapping ); - - for(i = 0; i < MALI_MMU_PAGE_SIZE/4; i++) - { - _mali_osk_mem_iowrite32_relaxed( mapping, i * sizeof(u32), data); - } - _mali_osk_mem_barrier(); - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size) -{ - const int first_pde = MALI_MMU_PDE_ENTRY(mali_address); - const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1); - _mali_osk_errcode_t err; - mali_io_address pde_mapping; - u32 pde_phys; - int i; - - for(i = first_pde; i <= last_pde; i++) - { - if(0 == (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & MALI_MMU_FLAGS_PRESENT)) - { - /* Page table not present */ - MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]); - MALI_DEBUG_ASSERT(NULL == pagedir->page_entries_mapped[i]); - - err = mali_mmu_get_table_page(&pde_phys, &pde_mapping); - if(_MALI_OSK_ERR_OK != err) - { - MALI_PRINT_ERROR(("Failed to allocate page table page.\n")); - return err; - } - pagedir->page_entries_mapped[i] = pde_mapping; - - /* Update PDE, mark as present */ - _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32), - pde_phys | MALI_MMU_FLAGS_PRESENT); - - MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]); - pagedir->page_entries_usage_count[i] = 1; - } - else - { - pagedir->page_entries_usage_count[i]++; - } - } - _mali_osk_write_mem_barrier(); - - MALI_SUCCESS; -} - -MALI_STATIC_INLINE void mali_mmu_zero_pte(mali_io_address page_table, u32 mali_address, u32 size) -{ - int i; - const int first_pte = MALI_MMU_PTE_ENTRY(mali_address); - const int last_pte = MALI_MMU_PTE_ENTRY(mali_address + size - 1); - - for (i = first_pte; i <= last_pte; i++) - { - _mali_osk_mem_iowrite32_relaxed(page_table, i * sizeof(u32), 0); - } -} - -_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size) -{ - const int first_pde = MALI_MMU_PDE_ENTRY(mali_address); - const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1); - u32 left = size; - int i; -#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 - mali_bool pd_changed = MALI_FALSE; - u32 pages_to_invalidate[3]; /* hard-coded to 3: max two pages from the PT level plus max one page from PD level */ - u32 num_pages_inv = 0; -#endif - - /* For all page directory entries in range. */ - for (i = first_pde; i <= last_pde; i++) - { - u32 size_in_pde, offset; - - MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[i]); - MALI_DEBUG_ASSERT(0 != pagedir->page_entries_usage_count[i]); - - /* Offset into page table, 0 if mali_address is 4MiB aligned */ - offset = (mali_address & (MALI_MMU_VIRTUAL_PAGE_SIZE - 1)); - if (left < MALI_MMU_VIRTUAL_PAGE_SIZE - offset) - { - size_in_pde = left; - } - else - { - size_in_pde = MALI_MMU_VIRTUAL_PAGE_SIZE - offset; - } - - pagedir->page_entries_usage_count[i]--; - - /* If entire page table is unused, free it */ - if (0 == pagedir->page_entries_usage_count[i]) - { - u32 page_address; - MALI_DEBUG_PRINT(4, ("Releasing page table as this is the last reference\n")); - /* last reference removed, no need to zero out each PTE */ - - page_address = MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32))); - pagedir->page_entries_mapped[i] = NULL; - _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32), 0); - - mali_mmu_release_table_page(page_address); -#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 - pd_changed = MALI_TRUE; -#endif - } - else - { -#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 - pages_to_invalidate[num_pages_inv] = mali_page_directory_get_phys_address(pagedir, i); - num_pages_inv++; - MALI_DEBUG_ASSERT(num_pages_inv<3); -#endif - - /* If part of the page table is still in use, zero the relevant PTEs */ - mali_mmu_zero_pte(pagedir->page_entries_mapped[i], mali_address, size_in_pde); - } - - left -= size_in_pde; - mali_address += size_in_pde; - } - _mali_osk_write_mem_barrier(); - -#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 - /* L2 pages invalidation */ - if (MALI_TRUE == pd_changed) - { - pages_to_invalidate[num_pages_inv] = pagedir->page_directory; - num_pages_inv++; - MALI_DEBUG_ASSERT(num_pages_inv<3); - } - - if (_MALI_PRODUCT_ID_MALI200 != mali_kernel_core_get_product_id()) - { - mali_cluster_invalidate_pages(pages_to_invalidate, num_pages_inv); - } -#endif - - MALI_SUCCESS; -} - -struct mali_page_directory *mali_mmu_pagedir_alloc(void) -{ - struct mali_page_directory *pagedir; - - pagedir = _mali_osk_calloc(1, sizeof(struct mali_page_directory)); - if(NULL == pagedir) - { - return NULL; - } - - if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&pagedir->page_directory, &pagedir->page_directory_mapped)) - { - _mali_osk_free(pagedir); - return NULL; - } - - /* Zero page directory */ - fill_page(pagedir->page_directory_mapped, 0); - - return pagedir; -} - -void mali_mmu_pagedir_free(struct mali_page_directory *pagedir) -{ - const int num_page_table_entries = sizeof(pagedir->page_entries_mapped) / sizeof(pagedir->page_entries_mapped[0]); - int i; - - /* Free referenced page tables and zero PDEs. */ - for (i = 0; i < num_page_table_entries; i++) - { - if (pagedir->page_directory_mapped && (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, sizeof(u32)*i) & MALI_MMU_FLAGS_PRESENT)) - { - mali_mmu_release_table_page( _mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK); - _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i * sizeof(u32), 0); - } - } - _mali_osk_write_mem_barrier(); - - /* Free the page directory page. */ - mali_mmu_release_table_page(pagedir->page_directory); - - _mali_osk_free(pagedir); -} - - -void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size, mali_memory_cache_settings cache_settings) -{ - u32 end_address = mali_address + size; - u32 permission_bits; - - switch ( cache_settings ) - { - case MALI_CACHE_GP_READ_ALLOCATE: - MALI_DEBUG_PRINT(3, ("Map L2 GP_Read_allocate\n")); - permission_bits = MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE; - break; - - case MALI_CACHE_STANDARD: - MALI_DEBUG_PRINT(3, ("Map L2 Standard\n")); - /*falltrough */ - default: - if ( MALI_CACHE_STANDARD != cache_settings) MALI_PRINT_ERROR(("Wrong cache settings\n")); - permission_bits = MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT; - } - - /* Map physical pages into MMU page tables */ - for ( ; mali_address < end_address; mali_address += MALI_MMU_PAGE_SIZE, phys_address += MALI_MMU_PAGE_SIZE) - { - MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)]); - _mali_osk_mem_iowrite32_relaxed(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)], - MALI_MMU_PTE_ENTRY(mali_address) * sizeof(u32), - phys_address | permission_bits); - } - _mali_osk_write_mem_barrier(); -} - -u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index) -{ - return (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, index*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK); -} - -/* For instrumented */ -struct dump_info -{ - u32 buffer_left; - u32 register_writes_size; - u32 page_table_dump_size; - u32 *buffer; -}; - -static _mali_osk_errcode_t writereg(u32 where, u32 what, const char *comment, struct dump_info *info) -{ - if (NULL != info) - { - info->register_writes_size += sizeof(u32)*2; /* two 32-bit words */ - - if (NULL != info->buffer) - { - /* check that we have enough space */ - if (info->buffer_left < sizeof(u32)*2) MALI_ERROR(_MALI_OSK_ERR_NOMEM); - - *info->buffer = where; - info->buffer++; - - *info->buffer = what; - info->buffer++; - - info->buffer_left -= sizeof(u32)*2; - } - } - - MALI_SUCCESS; -} - -static _mali_osk_errcode_t dump_page(mali_io_address page, u32 phys_addr, struct dump_info * info) -{ - if (NULL != info) - { - /* 4096 for the page and 4 bytes for the address */ - const u32 page_size_in_elements = MALI_MMU_PAGE_SIZE / 4; - const u32 page_size_in_bytes = MALI_MMU_PAGE_SIZE; - const u32 dump_size_in_bytes = MALI_MMU_PAGE_SIZE + 4; - - info->page_table_dump_size += dump_size_in_bytes; - - if (NULL != info->buffer) - { - if (info->buffer_left < dump_size_in_bytes) MALI_ERROR(_MALI_OSK_ERR_NOMEM); - - *info->buffer = phys_addr; - info->buffer++; - - _mali_osk_memcpy(info->buffer, page, page_size_in_bytes); - info->buffer += page_size_in_elements; - - info->buffer_left -= dump_size_in_bytes; - } - } - - MALI_SUCCESS; -} - -static _mali_osk_errcode_t dump_mmu_page_table(struct mali_page_directory *pagedir, struct dump_info * info) -{ - MALI_DEBUG_ASSERT_POINTER(pagedir); - MALI_DEBUG_ASSERT_POINTER(info); - - if (NULL != pagedir->page_directory_mapped) - { - int i; - - MALI_CHECK_NO_ERROR( - dump_page(pagedir->page_directory_mapped, pagedir->page_directory, info) - ); - - for (i = 0; i < 1024; i++) - { - if (NULL != pagedir->page_entries_mapped[i]) - { - MALI_CHECK_NO_ERROR( - dump_page(pagedir->page_entries_mapped[i], - _mali_osk_mem_ioread32(pagedir->page_directory_mapped, - i * sizeof(u32)) & ~MALI_MMU_FLAGS_MASK, info) - ); - } - } - } - - MALI_SUCCESS; -} - -static _mali_osk_errcode_t dump_mmu_registers(struct mali_page_directory *pagedir, struct dump_info * info) -{ - MALI_CHECK_NO_ERROR(writereg(0x00000000, pagedir->page_directory, - "set the page directory address", info)); - MALI_CHECK_NO_ERROR(writereg(0x00000008, 4, "zap???", info)); - MALI_CHECK_NO_ERROR(writereg(0x00000008, 0, "enable paging", info)); - MALI_SUCCESS; -} - -_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args ) -{ - struct dump_info info = { 0, 0, 0, NULL }; - struct mali_session_data * session_data; - - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - session_data = (struct mali_session_data *)(args->ctx); - - MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info)); - MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info)); - args->size = info.register_writes_size + info.page_table_dump_size; - MALI_SUCCESS; -} - -_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args ) -{ - struct dump_info info = { 0, 0, 0, NULL }; - struct mali_session_data * session_data; - - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - MALI_CHECK_NON_NULL(args->buffer, _MALI_OSK_ERR_INVALID_ARGS); - - session_data = (struct mali_session_data *)(args->ctx); - - info.buffer_left = args->size; - info.buffer = args->buffer; - - args->register_writes = info.buffer; - MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info)); - - args->page_table_dump = info.buffer; - MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info)); - - args->register_writes_size = info.register_writes_size; - args->page_table_dump_size = info.page_table_dump_size; - - MALI_SUCCESS; -} diff --git a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h deleted file mode 100644 index 628833a..0000000 --- a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_MMU_PAGE_DIRECTORY_H__ -#define __MALI_MMU_PAGE_DIRECTORY_H__ - -#include "mali_osk.h" - -/** - * Size of an MMU page in bytes - */ -#define MALI_MMU_PAGE_SIZE 0x1000 - -/* - * Size of the address space referenced by a page table page - */ -#define MALI_MMU_VIRTUAL_PAGE_SIZE 0x400000 /* 4 MiB */ - -/** - * Page directory index from address - * Calculates the page directory index from the given address - */ -#define MALI_MMU_PDE_ENTRY(address) (((address)>>22) & 0x03FF) - -/** - * Page table index from address - * Calculates the page table index from the given address - */ -#define MALI_MMU_PTE_ENTRY(address) (((address)>>12) & 0x03FF) - -/** - * Extract the memory address from an PDE/PTE entry - */ -#define MALI_MMU_ENTRY_ADDRESS(value) ((value) & 0xFFFFFC00) - -#define MALI_INVALID_PAGE ((u32)(~0)) - -/** - * - */ -typedef enum mali_mmu_entry_flags -{ - MALI_MMU_FLAGS_PRESENT = 0x01, - MALI_MMU_FLAGS_READ_PERMISSION = 0x02, - MALI_MMU_FLAGS_WRITE_PERMISSION = 0x04, - MALI_MMU_FLAGS_OVERRIDE_CACHE = 0x8, - MALI_MMU_FLAGS_WRITE_CACHEABLE = 0x10, - MALI_MMU_FLAGS_WRITE_ALLOCATE = 0x20, - MALI_MMU_FLAGS_WRITE_BUFFERABLE = 0x40, - MALI_MMU_FLAGS_READ_CACHEABLE = 0x80, - MALI_MMU_FLAGS_READ_ALLOCATE = 0x100, - MALI_MMU_FLAGS_MASK = 0x1FF, -} mali_mmu_entry_flags; - - -#define MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE ( \ -MALI_MMU_FLAGS_PRESENT | \ - MALI_MMU_FLAGS_READ_PERMISSION | \ - MALI_MMU_FLAGS_WRITE_PERMISSION | \ - MALI_MMU_FLAGS_OVERRIDE_CACHE | \ - MALI_MMU_FLAGS_WRITE_CACHEABLE | \ - MALI_MMU_FLAGS_WRITE_BUFFERABLE | \ - MALI_MMU_FLAGS_READ_CACHEABLE | \ - MALI_MMU_FLAGS_READ_ALLOCATE ) - - -struct mali_page_directory -{ - u32 page_directory; /**< Physical address of the memory session's page directory */ - mali_io_address page_directory_mapped; /**< Pointer to the mapped version of the page directory into the kernel's address space */ - - mali_io_address page_entries_mapped[1024]; /**< Pointers to the page tables which exists in the page directory mapped into the kernel's address space */ - u32 page_entries_usage_count[1024]; /**< Tracks usage count of the page table pages, so they can be releases on the last reference */ -}; - -/* Map Mali virtual address space (i.e. ensure page tables exist for the virtual range) */ -_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size); -_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size); - -/* Back virtual address space with actual pages. Assumes input is contiguous and 4k aligned. */ -void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size, u32 cache_settings); - -u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index); - -u32 mali_allocate_empty_page(void); -void mali_free_empty_page(u32 address); -_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page); -void mali_destroy_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page); - -struct mali_page_directory *mali_mmu_pagedir_alloc(void); -void mali_mmu_pagedir_free(struct mali_page_directory *pagedir); - -#endif /* __MALI_MMU_PAGE_DIRECTORY_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk.h b/drivers/media/video/samsung/mali/common/mali_osk.h deleted file mode 100644 index e32d15d..0000000 --- a/drivers/media/video/samsung/mali/common/mali_osk.h +++ /dev/null @@ -1,1798 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk.h - * Defines the OS abstraction layer for the kernel device driver (OSK) - */ - -#ifndef __MALI_OSK_H__ -#define __MALI_OSK_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * @addtogroup uddapi Unified Device Driver (UDD) APIs - * - * @{ - */ - -/** - * @addtogroup oskapi UDD OS Abstraction for Kernel-side (OSK) APIs - * - * @{ - */ - -/** @defgroup _mali_osk_miscellaneous OSK Miscellaneous functions, constants and types - * @{ */ - -/* Define integer types used by OSK. Note: these currently clash with Linux so we only define them if not defined already */ -#ifndef __KERNEL__ - typedef unsigned char u8; - typedef signed char s8; - typedef unsigned short u16; - typedef signed short s16; - typedef unsigned int u32; - typedef signed int s32; - typedef unsigned long long u64; - #define BITS_PER_LONG (sizeof(long)*8) -#else - /* Ensure Linux types u32, etc. are defined */ - #include -#endif - -/** @brief Mali Boolean type which uses MALI_TRUE and MALI_FALSE - */ - typedef unsigned long mali_bool; - -#ifndef MALI_TRUE - #define MALI_TRUE ((mali_bool)1) -#endif - -#ifndef MALI_FALSE - #define MALI_FALSE ((mali_bool)0) -#endif - -/** - * @brief OSK Error codes - * - * Each OS may use its own set of error codes, and may require that the - * User/Kernel interface take certain error code. This means that the common - * error codes need to be sufficiently rich to pass the correct error code - * thorugh from the OSK to U/K layer, across all OSs. - * - * The result is that some error codes will appear redundant on some OSs. - * Under all OSs, the OSK layer must translate native OS error codes to - * _mali_osk_errcode_t codes. Similarly, the U/K layer must translate from - * _mali_osk_errcode_t codes to native OS error codes. - */ -typedef enum -{ - _MALI_OSK_ERR_OK = 0, /**< Success. */ - _MALI_OSK_ERR_FAULT = -1, /**< General non-success */ - _MALI_OSK_ERR_INVALID_FUNC = -2, /**< Invalid function requested through User/Kernel interface (e.g. bad IOCTL number) */ - _MALI_OSK_ERR_INVALID_ARGS = -3, /**< Invalid arguments passed through User/Kernel interface */ - _MALI_OSK_ERR_NOMEM = -4, /**< Insufficient memory */ - _MALI_OSK_ERR_TIMEOUT = -5, /**< Timeout occurred */ - _MALI_OSK_ERR_RESTARTSYSCALL = -6, /**< Special: On certain OSs, must report when an interruptable mutex is interrupted. Ignore otherwise. */ - _MALI_OSK_ERR_ITEM_NOT_FOUND = -7, /**< Table Lookup failed */ - _MALI_OSK_ERR_BUSY = -8, /**< Device/operation is busy. Try again later */ - _MALI_OSK_ERR_UNSUPPORTED = -9, /**< Optional part of the interface used, and is unsupported */ -} _mali_osk_errcode_t; - -/** @} */ /* end group _mali_osk_miscellaneous */ - - -/** @defgroup _mali_osk_irq OSK IRQ handling - * @{ */ - -/** @brief Private type for IRQ handling objects */ -typedef struct _mali_osk_irq_t_struct _mali_osk_irq_t; - -/** @brief Optional function to trigger an irq from a resource - * - * This function is implemented by the common layer to allow probing of a resource's IRQ. - * @param arg resource-specific data */ -typedef void (*_mali_osk_irq_trigger_t)( void * arg ); - -/** @brief Optional function to acknowledge an irq from a resource - * - * This function is implemented by the common layer to allow probing of a resource's IRQ. - * @param arg resource-specific data - * @return _MALI_OSK_ERR_OK if the IRQ was successful, or a suitable _mali_osk_errcode_t on failure. */ -typedef _mali_osk_errcode_t (*_mali_osk_irq_ack_t)( void * arg ); - -/** @brief IRQ 'upper-half' handler callback. - * - * This function is implemented by the common layer to do the initial handling of a - * resource's IRQ. This maps on to the concept of an ISR that does the minimum - * work necessary before handing off to an IST. - * - * The communication of the resource-specific data from the ISR to the IST is - * handled by the OSK implementation. - * - * On most systems, the IRQ upper-half handler executes in IRQ context. - * Therefore, the system may have restrictions about what can be done in this - * context - * - * If an IRQ upper-half handler requires more work to be done than can be - * acheived in an IRQ context, then it may defer the work with - * _mali_osk_irq_schedulework(). Refer to \ref _mali_osk_irq_schedulework() for - * more information. - * - * @param arg resource-specific data - * @return _MALI_OSK_ERR_OK if the IRQ was correctly handled, or a suitable - * _mali_osk_errcode_t otherwise. - */ -typedef _mali_osk_errcode_t (*_mali_osk_irq_uhandler_t)( void * arg ); - -/** @brief IRQ 'bottom-half' handler callback. - * - * This function is implemented by the common layer to do the deferred handling - * of a resource's IRQ. Usually, this work cannot be carried out in IRQ context - * by the IRQ upper-half handler. - * - * The IRQ bottom-half handler maps on to the concept of an IST that may - * execute some time after the actual IRQ has fired. - * - * All OSK-registered IRQ bottom-half handlers will be serialized, across all - * CPU-cores in the system. - * - * Refer to \ref _mali_osk_irq_schedulework() for more information on the - * IRQ work-queue, and the calling of the IRQ bottom-half handler. - * - * @param arg resource-specific data - */ -typedef void (*_mali_osk_irq_bhandler_t)( void * arg ); -/** @} */ /* end group _mali_osk_irq */ - - -/** @defgroup _mali_osk_atomic OSK Atomic counters - * @{ */ - -/** @brief Public type of atomic counters - * - * This is public for allocation on stack. On systems that support it, this is just a single 32-bit value. - * On others, it could be encapsulating an object stored elsewhere. - * - * Regardless of implementation, the \ref _mali_osk_atomic functions \b must be used - * for all accesses to the variable's value, even if atomicity is not required. - * Do not access u.val or u.obj directly. - */ -typedef struct -{ - union - { - u32 val; - void *obj; - } u; -} _mali_osk_atomic_t; -/** @} */ /* end group _mali_osk_atomic */ - - -/** @defgroup _mali_osk_lock OSK Mutual Exclusion Locks - * @{ */ - - -/** @brief OSK Mutual Exclusion Lock ordered list - * - * This lists the various types of locks in the system and is used to check - * that locks are taken in the correct order. - * - * Holding more than one lock of the same order at the same time is not - * allowed. - * - */ -typedef enum -{ - _MALI_OSK_LOCK_ORDER_LAST = 0, - - _MALI_OSK_LOCK_ORDER_PM_EXECUTE, - _MALI_OSK_LOCK_ORDER_UTILIZATION, - _MALI_OSK_LOCK_ORDER_L2_COUNTER, - _MALI_OSK_LOCK_ORDER_PROFILING, - _MALI_OSK_LOCK_ORDER_L2_COMMAND, - _MALI_OSK_LOCK_ORDER_PM_CORE_STATE, - _MALI_OSK_LOCK_ORDER_GROUP, - _MALI_OSK_LOCK_ORDER_SCHEDULER, - - _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP, - _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE, - _MALI_OSK_LOCK_ORDER_MEM_INFO, - _MALI_OSK_LOCK_ORDER_MEM_SESSION, - - _MALI_OSK_LOCK_ORDER_SESSIONS, - - _MALI_OSK_LOCK_ORDER_FIRST -} _mali_osk_lock_order_t; - - -/** @brief OSK Mutual Exclusion Lock flags type - * - * Flags are supplied at the point where the Lock is initialized. Each flag can - * be combined with others using bitwise OR, '|'. - * - * The flags must be sufficiently rich to cope with all our OSs. This means - * that on some OSs, certain flags can be completely ignored. We define a - * number of terms that are significant across all OSs: - * - * - Sleeping/non-sleeping mutexs. Sleeping mutexs can block on waiting, and so - * schedule out the current thread. This is significant on OSs where there are - * situations in which the current thread must not be put to sleep. On OSs - * without this restriction, sleeping and non-sleeping mutexes can be treated - * as the same (if that is required). - * - Interruptable/non-interruptable mutexes. For sleeping mutexes, it may be - * possible for the sleep to be interrupted for a reason other than the thread - * being able to obtain the lock. OSs behaving in this way may provide a - * mechanism to control whether sleeping mutexes can be interrupted. On OSs - * that do not support the concept of interruption, \b or they do not support - * control of mutex interruption, then interruptable mutexes may be treated - * as non-interruptable. - * - * Some constrains apply to the lock type flags: - * - * - Spinlocks are by nature, non-interruptable. Hence, they must always be - * combined with the NONINTERRUPTABLE flag, because it is meaningless to ask - * for a spinlock that is interruptable (and this highlights its - * non-interruptable-ness). For example, on certain OSs they should be used when - * you must not sleep. - * - Reader/writer is an optimization hint, and any type of lock can be - * reader/writer. Since this is an optimization hint, the implementation need - * not respect this for any/all types of lock. For example, on certain OSs, - * there's no interruptable reader/writer mutex. If such a thing were requested - * on that OS, the fact that interruptable was requested takes priority over the - * reader/writer-ness, because reader/writer-ness is not necessary for correct - * operation. - * - Any lock can use the order parameter. - * - A onelock is an optimization hint specific to certain OSs. It can be - * specified when it is known that only one lock will be held by the thread, - * and so can provide faster mutual exclusion. This can be safely ignored if - * such optimization is not required/present. - * - * The absence of any flags (the value 0) results in a sleeping-mutex, which is interruptable. - */ -typedef enum -{ - _MALI_OSK_LOCKFLAG_SPINLOCK = 0x1, /**< Specifically, don't sleep on those architectures that require it */ - _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE = 0x2, /**< The mutex cannot be interrupted, e.g. delivery of signals on those architectures where this is required */ - _MALI_OSK_LOCKFLAG_READERWRITER = 0x4, /**< Optimise for readers/writers */ - _MALI_OSK_LOCKFLAG_ORDERED = 0x8, /**< Use the order parameter; otherwise use automatic ordering */ - _MALI_OSK_LOCKFLAG_ONELOCK = 0x10, /**< Each thread can only hold one lock at a time */ - _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ = 0x20, /**< IRQ version of spinlock */ - /** @enum _mali_osk_lock_flags_t - * - * Flags from 0x10000--0x80000000 are RESERVED for User-mode */ - -} _mali_osk_lock_flags_t; - -/** @brief Mutual Exclusion Lock Mode Optimization hint - * - * The lock mode is used to implement the read/write locking of locks specified - * as _MALI_OSK_LOCKFLAG_READERWRITER. In this case, the RO mode can be used - * to allow multiple concurrent readers, but no writers. The RW mode is used for - * writers, and so will wait for all readers to release the lock (if any present). - * Further readers and writers will wait until the writer releases the lock. - * - * The mode is purely an optimization hint: for example, it is permissible for - * all locks to behave in RW mode, regardless of that supplied. - * - * It is an error to attempt to use locks in anything other that RW mode when - * _MALI_OSK_LOCKFLAG_READERWRITER is not supplied. - * - */ -typedef enum -{ - _MALI_OSK_LOCKMODE_UNDEF = -1, /**< Undefined lock mode. For internal use only */ - _MALI_OSK_LOCKMODE_RW = 0x0, /**< Read-write mode, default. All readers and writers are mutually-exclusive */ - _MALI_OSK_LOCKMODE_RO, /**< Read-only mode, to support multiple concurrent readers, but mutual exclusion in the presence of writers. */ - /** @enum _mali_osk_lock_mode_t - * - * Lock modes 0x40--0x7F are RESERVED for User-mode */ -} _mali_osk_lock_mode_t; - -/** @brief Private type for Mutual Exclusion lock objects */ -typedef struct _mali_osk_lock_t_struct _mali_osk_lock_t; - -#ifdef DEBUG -/** @brief Macro for asserting that the current thread holds a given lock - */ -#define MALI_DEBUG_ASSERT_LOCK_HELD(l) MALI_DEBUG_ASSERT(_mali_osk_lock_get_owner(l) == _mali_osk_get_tid()); - -/** @brief returns a lock's owner (thread id) if debugging is enabled - */ -u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock ); -#endif - -/** @} */ /* end group _mali_osk_lock */ - -/** @defgroup _mali_osk_low_level_memory OSK Low-level Memory Operations - * @{ */ - -/** - * @brief Private data type for use in IO accesses to/from devices. - * - * This represents some range that is accessible from the device. Examples - * include: - * - Device Registers, which could be readable and/or writeable. - * - Memory that the device has access to, for storing configuration structures. - * - * Access to this range must be made through the _mali_osk_mem_ioread32() and - * _mali_osk_mem_iowrite32() functions. - */ -typedef struct _mali_io_address * mali_io_address; - -/** @defgroup _MALI_OSK_CPU_PAGE CPU Physical page size macros. - * - * The order of the page size is supplied for - * ease of use by algorithms that might require it, since it is easier to know - * it ahead of time rather than calculating it. - * - * The Mali Page Mask macro masks off the lower bits of a physical address to - * give the start address of the page for that physical address. - * - * @note The Mali device driver code is designed for systems with 4KB page size. - * Changing these macros will not make the entire Mali device driver work with - * page sizes other than 4KB. - * - * @note The CPU Physical Page Size has been assumed to be the same as the Mali - * Physical Page Size. - * - * @{ - */ - -/** CPU Page Order, as log to base 2 of the Page size. @see _MALI_OSK_CPU_PAGE_SIZE */ -#define _MALI_OSK_CPU_PAGE_ORDER ((u32)12) -/** CPU Page Size, in bytes. */ -#define _MALI_OSK_CPU_PAGE_SIZE (((u32)1) << (_MALI_OSK_CPU_PAGE_ORDER)) -/** CPU Page Mask, which masks off the offset within a page */ -#define _MALI_OSK_CPU_PAGE_MASK (~((((u32)1) << (_MALI_OSK_CPU_PAGE_ORDER)) - ((u32)1))) -/** @} */ /* end of group _MALI_OSK_CPU_PAGE */ - -/** @defgroup _MALI_OSK_MALI_PAGE Mali Physical Page size macros - * - * Mali Physical page size macros. The order of the page size is supplied for - * ease of use by algorithms that might require it, since it is easier to know - * it ahead of time rather than calculating it. - * - * The Mali Page Mask macro masks off the lower bits of a physical address to - * give the start address of the page for that physical address. - * - * @note The Mali device driver code is designed for systems with 4KB page size. - * Changing these macros will not make the entire Mali device driver work with - * page sizes other than 4KB. - * - * @note The Mali Physical Page Size has been assumed to be the same as the CPU - * Physical Page Size. - * - * @{ - */ - -/** Mali Page Order, as log to base 2 of the Page size. @see _MALI_OSK_MALI_PAGE_SIZE */ -#define _MALI_OSK_MALI_PAGE_ORDER ((u32)12) -/** Mali Page Size, in bytes. */ -#define _MALI_OSK_MALI_PAGE_SIZE (((u32)1) << (_MALI_OSK_MALI_PAGE_ORDER)) -/** Mali Page Mask, which masks off the offset within a page */ -#define _MALI_OSK_MALI_PAGE_MASK (~((((u32)1) << (_MALI_OSK_MALI_PAGE_ORDER)) - ((u32)1))) -/** @} */ /* end of group _MALI_OSK_MALI_PAGE*/ - -/** @brief flags for mapping a user-accessible memory range - * - * Where a function with prefix '_mali_osk_mem_mapregion' accepts flags as one - * of the function parameters, it will use one of these. These allow per-page - * control over mappings. Compare with the mali_memory_allocation_flag type, - * which acts over an entire range - * - * These may be OR'd together with bitwise OR (|), but must be cast back into - * the type after OR'ing. - */ -typedef enum -{ - _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR = 0x1, /**< Physical address is OS Allocated */ -} _mali_osk_mem_mapregion_flags_t; -/** @} */ /* end group _mali_osk_low_level_memory */ - -/** @defgroup _mali_osk_notification OSK Notification Queues - * @{ */ - -/** @brief Private type for notification queue objects */ -typedef struct _mali_osk_notification_queue_t_struct _mali_osk_notification_queue_t; - -/** @brief Public notification data object type */ -typedef struct _mali_osk_notification_t_struct -{ - u32 notification_type; /**< The notification type */ - u32 result_buffer_size; /**< Size of the result buffer to copy to user space */ - void * result_buffer; /**< Buffer containing any type specific data */ -} _mali_osk_notification_t; - -/** @} */ /* end group _mali_osk_notification */ - - -/** @defgroup _mali_osk_timer OSK Timer Callbacks - * @{ */ - -/** @brief Function to call when a timer expires - * - * When a timer expires, this function is called. Note that on many systems, - * a timer callback will be executed in IRQ context. Therefore, restrictions - * may apply on what can be done inside the timer callback. - * - * If a timer requires more work to be done than can be acheived in an IRQ - * context, then it may defer the work with a work-queue. For example, it may - * use \ref _mali_osk_irq_schedulework() to make use of the IRQ bottom-half handler - * to carry out the remaining work. - * - * Stopping the timer with \ref _mali_osk_timer_del() blocks on compeletion of - * the callback. Therefore, the callback may not obtain any mutexes also held - * by any callers of _mali_osk_timer_del(). Otherwise, a deadlock may occur. - * - * @param arg Function-specific data */ -typedef void (*_mali_osk_timer_callback_t)(void * arg ); - -/** @brief Private type for Timer Callback Objects */ -typedef struct _mali_osk_timer_t_struct _mali_osk_timer_t; -/** @} */ /* end group _mali_osk_timer */ - - -/** @addtogroup _mali_osk_list OSK Doubly-Linked Circular Lists - * @{ */ - -/** @brief Public List objects. - * - * To use, add a _mali_osk_list_t member to the structure that may become part - * of a list. When traversing the _mali_osk_list_t objects, use the - * _MALI_OSK_CONTAINER_OF() macro to recover the structure from its - *_mali_osk_list_t member - * - * Each structure may have multiple _mali_osk_list_t members, so that the - * structure is part of multiple lists. When traversing lists, ensure that the - * correct _mali_osk_list_t member is used, because type-checking will be - * lost by the compiler. - */ -typedef struct _mali_osk_list_s -{ - struct _mali_osk_list_s *next; - struct _mali_osk_list_s *prev; -} _mali_osk_list_t; - -/** @brief Initialize a list to be a head of an empty list - * @param exp the list to initialize. */ -#define _MALI_OSK_INIT_LIST_HEAD(exp) _mali_osk_list_init(exp) - -/** @brief Define a list variable, which is uninitialized. - * @param exp the name of the variable that the list will be defined as. */ -#define _MALI_OSK_LIST_HEAD(exp) _mali_osk_list_t exp - -/** @brief Find the containing structure of another structure - * - * This is the reverse of the operation 'offsetof'. This means that the - * following condition is satisfied: - * - * ptr == _MALI_OSK_CONTAINER_OF( &ptr->member, type, member ) - * - * When ptr is of type 'type'. - * - * Its purpose it to recover a larger structure that has wrapped a smaller one. - * - * @note no type or memory checking occurs to ensure that a wrapper structure - * does in fact exist, and that it is being recovered with respect to the - * correct member. - * - * @param ptr the pointer to the member that is contained within the larger - * structure - * @param type the type of the structure that contains the member - * @param member the name of the member in the structure that ptr points to. - * @return a pointer to a \a type object which contains \a member, as pointed - * to by \a ptr. - */ -#define _MALI_OSK_CONTAINER_OF(ptr, type, member) \ - ((type *)( ((char *)ptr) - offsetof(type,member) )) - -/** @brief Find the containing structure of a list - * - * When traversing a list, this is used to recover the containing structure, - * given that is contains a _mali_osk_list_t member. - * - * Each list must be of structures of one type, and must link the same members - * together, otherwise it will not be possible to correctly recover the - * sturctures that the lists link. - * - * @note no type or memory checking occurs to ensure that a structure does in - * fact exist for the list entry, and that it is being recovered with respect - * to the correct list member. - * - * @param ptr the pointer to the _mali_osk_list_t member in this structure - * @param type the type of the structure that contains the member - * @param member the member of the structure that ptr points to. - * @return a pointer to a \a type object which contains the _mali_osk_list_t - * \a member, as pointed to by the _mali_osk_list_t \a *ptr. - */ -#define _MALI_OSK_LIST_ENTRY(ptr, type, member) \ - _MALI_OSK_CONTAINER_OF(ptr, type, member) - -/** @brief Enumerate a list safely - * - * With this macro, lists can be enumerated in a 'safe' manner. That is, - * entries can be deleted from the list without causing an error during - * enumeration. To achieve this, a 'temporary' pointer is required, which must - * be provided to the macro. - * - * Use it like a 'for()', 'while()' or 'do()' construct, and so it must be - * followed by a statement or compound-statement which will be executed for - * each list entry. - * - * Upon loop completion, providing that an early out was not taken in the - * loop body, then it is guaranteed that ptr->member == list, even if the loop - * body never executed. - * - * @param ptr a pointer to an object of type 'type', which points to the - * structure that contains the currently enumerated list entry. - * @param tmp a pointer to an object of type 'type', which must not be used - * inside the list-execution statement. - * @param list a pointer to a _mali_osk_list_t, from which enumeration will - * begin - * @param type the type of the structure that contains the _mali_osk_list_t - * member that is part of the list to be enumerated. - * @param member the _mali_osk_list_t member of the structure that is part of - * the list to be enumerated. - */ -#define _MALI_OSK_LIST_FOREACHENTRY(ptr, tmp, list, type, member) \ - for (ptr = _MALI_OSK_LIST_ENTRY((list)->next, type, member), \ - tmp = _MALI_OSK_LIST_ENTRY(ptr->member.next, type, member); \ - &ptr->member != (list); \ - ptr = tmp, tmp = _MALI_OSK_LIST_ENTRY(tmp->member.next, type, member)) -/** @} */ /* end group _mali_osk_list */ - - -/** @addtogroup _mali_osk_miscellaneous - * @{ */ - -/** @brief The known resource types - * - * @note \b IMPORTANT: these must remain fixed, and only be extended. This is - * because not all systems use a header file for reading in their resources. - * The resources may instead come from a data file where these resources are - * 'hard-coded' in, because there's no easy way of transferring the enum values - * into such data files. E.g. the C-Pre-processor does \em not process enums. - */ -typedef enum _mali_osk_resource_type -{ - RESOURCE_TYPE_FIRST =0, /**< Duplicate resource marker for the first resource*/ - - MEMORY =0, /**< Physically contiguous memory block, not managed by the OS */ - OS_MEMORY =1, /**< Memory managed by and shared with the OS */ - - MALI_PP =2, /**< Mali Pixel Processor core */ - MALI450PP =2, /**< Compatibility option */ - MALI400PP =2, /**< Compatibility option */ - MALI300PP =2, /**< Compatibility option */ - MALI200 =2, /**< Compatibility option */ - - MALI_GP =3, /**< Mali Geometry Processor core */ - MALI450GP =3, /**< Compatibility option */ - MALI400GP =3, /**< Compatibility option */ - MALI300GP =3, /**< Compatibility option */ - MALIGP2 =3, /**< Compatibility option */ - - MMU =4, /**< Mali MMU (Memory Management Unit) */ - - FPGA_FRAMEWORK =5, /**< Mali registers specific to FPGA implementations */ - - MALI_L2 =6, /**< Mali Level 2 cache core */ - MALI450L2 =6, /**< Compatibility option */ - MALI400L2 =6, /**< Compatibility option */ - MALI300L2 =6, /**< Compatibility option */ - - MEM_VALIDATION =7, /**< External Memory Validator */ - - PMU =8, /**< Power Manangement Unit */ - - RESOURCE_TYPE_COUNT /**< The total number of known resources */ -} _mali_osk_resource_type_t; - -/** @brief resource description struct - * - * _mali_osk_resources_init() will enumerate objects of this type. Not all - * members have a valid meaning across all types. - * - * The mmu_id is used to group resources to a certain MMU, since there may be - * more than one MMU in the system, and each resource may be using a different - * MMU: - * - For MMU resources, the setting of mmu_id is a uniquely identifying number. - * - For Other resources, the setting of mmu_id determines which MMU the - * resource uses. - */ -typedef struct _mali_osk_resource -{ - _mali_osk_resource_type_t type; /**< type of the resource */ - const char * description; /**< short description of the resource */ - u32 base; /**< Physical base address of the resource, as seen by Mali resources. */ - s32 cpu_usage_adjust; /**< Offset added to the base address of the resource to arrive at the CPU physical address of the resource (if different from the Mali physical address) */ - u32 size; /**< Size in bytes of the resource - either the size of its register range, or the size of the memory block. */ - u32 irq; /**< IRQ number delivered to the CPU, or -1 to tell the driver to probe for it (if possible) */ - u32 flags; /**< Resources-specific flags. */ - u32 mmu_id; /**< Identifier for Mali MMU resources. */ - u32 alloc_order; /**< Order in which MEMORY/OS_MEMORY resources are used */ -} _mali_osk_resource_t; -/** @} */ /* end group _mali_osk_miscellaneous */ - - -#include "mali_kernel_memory_engine.h" /* include for mali_memory_allocation and mali_physical_memory_allocation type */ - -/** @addtogroup _mali_osk_irq - * @{ */ - -/** @brief Fake IRQ number for testing purposes - */ -#define _MALI_OSK_IRQ_NUMBER_FAKE ((u32)0xFFFFFFF1) - -/** @addtogroup _mali_osk_irq - * @{ */ - -/** @brief PMM Virtual IRQ number - */ -#define _MALI_OSK_IRQ_NUMBER_PMM ((u32)0xFFFFFFF2) - - -/** @brief Initialize IRQ handling for a resource - * - * The _mali_osk_irq_t returned must be written into the resource-specific data - * pointed to by data. This is so that the upper and lower handlers can call - * _mali_osk_irq_schedulework(). - * - * @note The caller must ensure that the resource does not generate an - * interrupt after _mali_osk_irq_init() finishes, and before the - * _mali_osk_irq_t is written into the resource-specific data. Otherwise, - * the upper-half handler will fail to call _mali_osk_irq_schedulework(). - * - * @param irqnum The IRQ number that the resource uses, as seen by the CPU. - * The value -1 has a special meaning which indicates the use of probing, and trigger_func and ack_func must be - * non-NULL. - * @param uhandler The upper-half handler, corresponding to a ISR handler for - * the resource - * @param bhandler The lower-half handler, corresponding to an IST handler for - * the resource - * @param trigger_func Optional: a function to trigger the resource's irq, to - * probe for the interrupt. Use NULL if irqnum != -1. - * @param ack_func Optional: a function to acknowledge the resource's irq, to - * probe for the interrupt. Use NULL if irqnum != -1. - * @param data resource-specific data, which will be passed to uhandler, - * bhandler and (if present) trigger_func and ack_funnc - * @param description textual description of the IRQ resource. - * @return on success, a pointer to a _mali_osk_irq_t object, which represents - * the IRQ handling on this resource. NULL on failure. - */ -_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, _mali_osk_irq_bhandler_t bhandler, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *data, const char *description ); - -/** @brief Cause a queued, deferred call of the IRQ bottom-half. - * - * _mali_osk_irq_schedulework provides a mechanism for enqueuing deferred calls - * to the IRQ bottom-half handler. The queue is known as the IRQ work-queue. - * After calling _mali_osk_irq_schedulework(), the IRQ bottom-half handler will - * be scheduled to run at some point in the future. - * - * This is called by the IRQ upper-half to defer further processing of - * IRQ-related work to the IRQ bottom-half handler. This is necessary for work - * that cannot be done in an IRQ context by the IRQ upper-half handler. Timer - * callbacks also use this mechanism, because they are treated as though they - * operate in an IRQ context. Refer to \ref _mali_osk_timer_t for more - * information. - * - * Code that operates in a kernel-process context (with no IRQ context - * restrictions) may also enqueue deferred calls to the IRQ bottom-half. The - * advantage over direct calling is that deferred calling allows the caller and - * IRQ bottom half to hold the same mutex, with a guarantee that they will not - * deadlock just by using this mechanism. - * - * _mali_osk_irq_schedulework() places deferred call requests on a queue, to - * allow for more than one thread to make a deferred call. Therfore, if it is - * called 'K' times, then the IRQ bottom-half will be scheduled 'K' times too. - * 'K' is a number that is implementation-specific. - * - * _mali_osk_irq_schedulework() is guaranteed to not block on: - * - enqueuing a deferred call request. - * - the completion of the IRQ bottom-half handler. - * - * This is to prevent deadlock. For example, if _mali_osk_irq_schedulework() - * blocked, then it would cause a deadlock when the following two conditions - * hold: - * - The IRQ bottom-half callback (of type _mali_osk_irq_bhandler_t) locks - * a mutex - * - And, at the same time, the caller of _mali_osk_irq_schedulework() also - * holds the same mutex - * - * @note care must be taken to not overflow the queue that - * _mali_osk_irq_schedulework() operates on. Code must be structured to - * ensure that the number of requests made to the queue is bounded. Otherwise, - * IRQs will be lost. - * - * The queue that _mali_osk_irq_schedulework implements is a FIFO of N-writer, - * 1-reader type. The writers are the callers of _mali_osk_irq_schedulework - * (all OSK-registered IRQ upper-half handlers in the system, watchdog timers, - * callers from a Kernel-process context). The reader is a single thread that - * handles all OSK-registered IRQs. - * - * The consequence of the queue being a 1-reader type is that calling - * _mali_osk_irq_schedulework() on different _mali_osk_irq_t objects causes - * their IRQ bottom-halves to be serialized, across all CPU-cores in the - * system. - * - * @param irq a pointer to the _mali_osk_irq_t object corresponding to the - * resource whose IRQ bottom-half must begin processing. - */ -void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq ); - -/** @brief Terminate IRQ handling on a resource. - * - * This will disable the interrupt from the device, and then waits for the - * IRQ work-queue to finish the work that is currently in the queue. That is, - * for every deferred call currently in the IRQ work-queue, it waits for each - * of those to be processed by their respective IRQ bottom-half handler. - * - * This function is used to ensure that the bottom-half handler of the supplied - * IRQ object will not be running at the completion of this function call. - * However, the caller must ensure that no other sources could call the - * _mali_osk_irq_schedulework() on the same IRQ object. For example, the - * relevant timers must be stopped. - * - * @note While this function is being called, other OSK-registered IRQs in the - * system may enqueue work for their respective bottom-half handlers. This - * function will not wait for those entries in the work-queue to be flushed. - * - * Since this blocks on the completion of work in the IRQ work-queue, the - * caller of this function \b must \b not hold any mutexes that are taken by - * any OSK-registered IRQ bottom-half handler. To do so may cause a deadlock. - * - * @param irq a pointer to the _mali_osk_irq_t object corresponding to the - * resource whose IRQ handling is to be terminated. - */ -void _mali_osk_irq_term( _mali_osk_irq_t *irq ); - -/** @brief flushing workqueue. - * - * This will flush the workqueue. - * - * @param irq a pointer to the _mali_osk_irq_t object corresponding to the - * resource whose IRQ handling is to be terminated. - */ -void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq ); - -/** @} */ /* end group _mali_osk_irq */ - - -/** @addtogroup _mali_osk_atomic - * @{ */ - -/** @brief Decrement an atomic counter - * - * @note It is an error to decrement the counter beyond -(1<<23) - * - * @param atom pointer to an atomic counter */ -void _mali_osk_atomic_dec( _mali_osk_atomic_t *atom ); - -/** @brief Decrement an atomic counter, return new value - * - * @param atom pointer to an atomic counter - * @return The new value, after decrement */ -u32 _mali_osk_atomic_dec_return( _mali_osk_atomic_t *atom ); - -/** @brief Increment an atomic counter - * - * @note It is an error to increment the counter beyond (1<<23)-1 - * - * @param atom pointer to an atomic counter */ -void _mali_osk_atomic_inc( _mali_osk_atomic_t *atom ); - -/** @brief Increment an atomic counter, return new value - * - * @param atom pointer to an atomic counter */ -u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom ); - -/** @brief Initialize an atomic counter - * - * @note the parameter required is a u32, and so signed integers should be - * cast to u32. - * - * @param atom pointer to an atomic counter - * @param val the value to initialize the atomic counter. - * @return _MALI_OSK_ERR_OK on success, otherwise, a suitable - * _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_osk_atomic_init( _mali_osk_atomic_t *atom, u32 val ); - -/** @brief Read a value from an atomic counter - * - * This can only be safely used to determine the value of the counter when it - * is guaranteed that other threads will not be modifying the counter. This - * makes its usefulness limited. - * - * @param atom pointer to an atomic counter - */ -u32 _mali_osk_atomic_read( _mali_osk_atomic_t *atom ); - -/** @brief Terminate an atomic counter - * - * @param atom pointer to an atomic counter - */ -void _mali_osk_atomic_term( _mali_osk_atomic_t *atom ); -/** @} */ /* end group _mali_osk_atomic */ - - -/** @defgroup _mali_osk_memory OSK Memory Allocation - * @{ */ - -/** @brief Allocate zero-initialized memory. - * - * Returns a buffer capable of containing at least \a n elements of \a size - * bytes each. The buffer is initialized to zero. - * - * If there is a need for a bigger block of memory (16KB or bigger), then - * consider to use _mali_osk_vmalloc() instead, as this function might - * map down to a OS function with size limitations. - * - * The buffer is suitably aligned for storage and subsequent access of every - * type that the compiler supports. Therefore, the pointer to the start of the - * buffer may be cast into any pointer type, and be subsequently accessed from - * such a pointer, without loss of information. - * - * When the buffer is no longer in use, it must be freed with _mali_osk_free(). - * Failure to do so will cause a memory leak. - * - * @note Most toolchains supply memory allocation functions that meet the - * compiler's alignment requirements. - * - * @param n Number of elements to allocate - * @param size Size of each element - * @return On success, the zero-initialized buffer allocated. NULL on failure - */ -void *_mali_osk_calloc( u32 n, u32 size ); - -/** @brief Allocate memory. - * - * Returns a buffer capable of containing at least \a size bytes. The - * contents of the buffer are undefined. - * - * If there is a need for a bigger block of memory (16KB or bigger), then - * consider to use _mali_osk_vmalloc() instead, as this function might - * map down to a OS function with size limitations. - * - * The buffer is suitably aligned for storage and subsequent access of every - * type that the compiler supports. Therefore, the pointer to the start of the - * buffer may be cast into any pointer type, and be subsequently accessed from - * such a pointer, without loss of information. - * - * When the buffer is no longer in use, it must be freed with _mali_osk_free(). - * Failure to do so will cause a memory leak. - * - * @note Most toolchains supply memory allocation functions that meet the - * compiler's alignment requirements. - * - * Remember to free memory using _mali_osk_free(). - * @param size Number of bytes to allocate - * @return On success, the buffer allocated. NULL on failure. - */ -void *_mali_osk_malloc( u32 size ); - -/** @brief Free memory. - * - * Reclaims the buffer pointed to by the parameter \a ptr for the system. - * All memory returned from _mali_osk_malloc() and _mali_osk_calloc() - * must be freed before the application exits. Otherwise, - * a memory leak will occur. - * - * Memory must be freed once. It is an error to free the same non-NULL pointer - * more than once. - * - * It is legal to free the NULL pointer. - * - * @param ptr Pointer to buffer to free - */ -void _mali_osk_free( void *ptr ); - -/** @brief Allocate memory. - * - * Returns a buffer capable of containing at least \a size bytes. The - * contents of the buffer are undefined. - * - * This function is potentially slower than _mali_osk_malloc() and _mali_osk_calloc(), - * but do support bigger sizes. - * - * The buffer is suitably aligned for storage and subsequent access of every - * type that the compiler supports. Therefore, the pointer to the start of the - * buffer may be cast into any pointer type, and be subsequently accessed from - * such a pointer, without loss of information. - * - * When the buffer is no longer in use, it must be freed with _mali_osk_free(). - * Failure to do so will cause a memory leak. - * - * @note Most toolchains supply memory allocation functions that meet the - * compiler's alignment requirements. - * - * Remember to free memory using _mali_osk_free(). - * @param size Number of bytes to allocate - * @return On success, the buffer allocated. NULL on failure. - */ -void *_mali_osk_valloc( u32 size ); - -/** @brief Free memory. - * - * Reclaims the buffer pointed to by the parameter \a ptr for the system. - * All memory returned from _mali_osk_valloc() must be freed before the - * application exits. Otherwise a memory leak will occur. - * - * Memory must be freed once. It is an error to free the same non-NULL pointer - * more than once. - * - * It is legal to free the NULL pointer. - * - * @param ptr Pointer to buffer to free - */ -void _mali_osk_vfree( void *ptr ); - -/** @brief Copies memory. - * - * Copies the \a len bytes from the buffer pointed by the parameter \a src - * directly to the buffer pointed by \a dst. - * - * It is an error for \a src to overlap \a dst anywhere in \a len bytes. - * - * @param dst Pointer to the destination array where the content is to be - * copied. - * @param src Pointer to the source of data to be copied. - * @param len Number of bytes to copy. - * @return \a dst is always passed through unmodified. - */ -void *_mali_osk_memcpy( void *dst, const void *src, u32 len ); - -/** @brief Fills memory. - * - * Sets the first \a n bytes of the block of memory pointed to by \a s to - * the specified value - * @param s Pointer to the block of memory to fill. - * @param c Value to be set, passed as u32. Only the 8 Least Significant Bits (LSB) - * are used. - * @param n Number of bytes to be set to the value. - * @return \a s is always passed through unmodified - */ -void *_mali_osk_memset( void *s, u32 c, u32 n ); -/** @} */ /* end group _mali_osk_memory */ - - -/** @brief Checks the amount of memory allocated - * - * Checks that not more than \a max_allocated bytes are allocated. - * - * Some OS bring up an interactive out of memory dialogue when the - * system runs out of memory. This can stall non-interactive - * apps (e.g. automated test runs). This function can be used to - * not trigger the OOM dialogue by keeping allocations - * within a certain limit. - * - * @return MALI_TRUE when \a max_allocated bytes are not in use yet. MALI_FALSE - * when at least \a max_allocated bytes are in use. - */ -mali_bool _mali_osk_mem_check_allocated( u32 max_allocated ); - -/** @addtogroup _mali_osk_lock - * @{ */ - -/** @brief Initialize a Mutual Exclusion Lock - * - * Locks are created in the signalled (unlocked) state. - * - * initial must be zero, since there is currently no means of expressing - * whether a reader/writer lock should be initially locked as a reader or - * writer. This would require some encoding to be used. - * - * 'Automatic' ordering means that locks must be obtained in the order that - * they were created. For all locks that can be held at the same time, they must - * either all provide the order parameter, or they all must use 'automatic' - * ordering - because there is no way of mixing 'automatic' and 'manual' - * ordering. - * - * @param flags flags combined with bitwise OR ('|'), or zero. There are - * restrictions on which flags can be combined, @see _mali_osk_lock_flags_t. - * @param initial For future expansion into semaphores. SBZ. - * @param order The locking order of the mutex. That is, locks obtained by the - * same thread must have been created with an increasing order parameter, for - * deadlock prevention. Setting to zero causes 'automatic' ordering to be used. - * @return On success, a pointer to a _mali_osk_lock_t object. NULL on failure. - */ -_mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial, u32 order ); - -/** @brief Wait for a lock to be signalled (obtained) - - * After a thread has successfully waited on the lock, the lock is obtained by - * the thread, and is marked as unsignalled. The thread releases the lock by - * signalling it. - * - * In the case of Reader/Writer locks, multiple readers can obtain a lock in - * the absence of writers, which is a performance optimization (providing that - * the readers never write to the protected resource). - * - * To prevent deadlock, locks must always be obtained in the same order. - * - * For locks marked as _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, it is a - * programming error for the function to exit without obtaining the lock. This - * means that the error code must only be checked for interruptible locks. - * - * @param lock the lock to wait upon (obtain). - * @param mode the mode in which the lock should be obtained. Unless the lock - * was created with _MALI_OSK_LOCKFLAG_READERWRITER, this must be - * _MALI_OSK_LOCKMODE_RW. - * @return On success, _MALI_OSK_ERR_OK. For interruptible locks, a suitable - * _mali_osk_errcode_t will be returned on failure, and the lock will not be - * obtained. In this case, the error code must be propagated up to the U/K - * interface. - */ -_mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode); - - -/** @brief Signal (release) a lock - * - * Locks may only be signalled by the thread that originally waited upon the - * lock. - * - * @note In the OSU, a flag exists to allow any thread to signal a - * lock. Such functionality is not present in the OSK. - * - * @param lock the lock to signal (release). - * @param mode the mode in which the lock should be obtained. This must match - * the mode in which the lock was waited upon. - */ -void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ); - -/** @brief Terminate a lock - * - * This terminates a lock and frees all associated resources. - * - * It is a programming error to terminate the lock when it is held (unsignalled) - * by a thread. - * - * @param lock the lock to terminate. - */ -void _mali_osk_lock_term( _mali_osk_lock_t *lock ); -/** @} */ /* end group _mali_osk_lock */ - - -/** @addtogroup _mali_osk_low_level_memory - * @{ */ - -/** @brief Issue a memory barrier - * - * This defines an arbitrary memory barrier operation, which forces an ordering constraint - * on memory read and write operations. - */ -void _mali_osk_mem_barrier( void ); - -/** @brief Issue a write memory barrier - * - * This defines an write memory barrier operation which forces an ordering constraint - * on memory write operations. - */ -void _mali_osk_write_mem_barrier( void ); - -/** @brief Map a physically contiguous region into kernel space - * - * This is primarily used for mapping in registers from resources, and Mali-MMU - * page tables. The mapping is only visable from kernel-space. - * - * Access has to go through _mali_osk_mem_ioread32 and _mali_osk_mem_iowrite32 - * - * @param phys CPU-physical base address of the memory to map in. This must - * be aligned to the system's page size, which is assumed to be 4K. - * @param size the number of bytes of physically contiguous address space to - * map in - * @param description A textual description of the memory being mapped in. - * @return On success, a Mali IO address through which the mapped-in - * memory/registers can be accessed. NULL on failure. - */ -mali_io_address _mali_osk_mem_mapioregion( u32 phys, u32 size, const char *description ); - -/** @brief Unmap a physically contiguous address range from kernel space. - * - * The address range should be one previously mapped in through - * _mali_osk_mem_mapioregion. - * - * It is a programming error to do (but not limited to) the following: - * - attempt an unmap twice - * - unmap only part of a range obtained through _mali_osk_mem_mapioregion - * - unmap more than the range obtained through _mali_osk_mem_mapioregion - * - unmap an address range that was not successfully mapped using - * _mali_osk_mem_mapioregion - * - provide a mapping that does not map to phys. - * - * @param phys CPU-physical base address of the memory that was originally - * mapped in. This must be aligned to the system's page size, which is assumed - * to be 4K - * @param size The number of bytes that were originally mapped in. - * @param mapping The Mali IO address through which the mapping is - * accessed. - */ -void _mali_osk_mem_unmapioregion( u32 phys, u32 size, mali_io_address mapping ); - -/** @brief Allocate and Map a physically contiguous region into kernel space - * - * This is used for allocating physically contiguous regions (such as Mali-MMU - * page tables) and mapping them into kernel space. The mapping is only - * visible from kernel-space. - * - * The alignment of the returned memory is guaranteed to be at least - * _MALI_OSK_CPU_PAGE_SIZE. - * - * Access must go through _mali_osk_mem_ioread32 and _mali_osk_mem_iowrite32 - * - * @note This function is primarily to provide support for OSs that are - * incapable of separating the tasks 'allocate physically contiguous memory' - * and 'map it into kernel space' - * - * @param[out] phys CPU-physical base address of memory that was allocated. - * (*phys) will be guaranteed to be aligned to at least - * _MALI_OSK_CPU_PAGE_SIZE on success. - * - * @param[in] size the number of bytes of physically contiguous memory to - * allocate. This must be a multiple of _MALI_OSK_CPU_PAGE_SIZE. - * - * @return On success, a Mali IO address through which the mapped-in - * memory/registers can be accessed. NULL on failure, and (*phys) is unmodified. - */ -mali_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 size ); - -/** @brief Free a physically contiguous address range from kernel space. - * - * The address range should be one previously mapped in through - * _mali_osk_mem_allocioregion. - * - * It is a programming error to do (but not limited to) the following: - * - attempt a free twice on the same ioregion - * - free only part of a range obtained through _mali_osk_mem_allocioregion - * - free more than the range obtained through _mali_osk_mem_allocioregion - * - free an address range that was not successfully mapped using - * _mali_osk_mem_allocioregion - * - provide a mapping that does not map to phys. - * - * @param phys CPU-physical base address of the memory that was originally - * mapped in, which was aligned to _MALI_OSK_CPU_PAGE_SIZE. - * @param size The number of bytes that were originally mapped in, which was - * a multiple of _MALI_OSK_CPU_PAGE_SIZE. - * @param mapping The Mali IO address through which the mapping is - * accessed. - */ -void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address mapping ); - -/** @brief Request a region of physically contiguous memory - * - * This is used to ensure exclusive access to a region of physically contigous - * memory. - * - * It is acceptable to implement this as a stub. However, it is then the job - * of the System Integrator to ensure that no other device driver will be using - * the physical address ranges used by Mali, while the Mali device driver is - * loaded. - * - * @param phys CPU-physical base address of the memory to request. This must - * be aligned to the system's page size, which is assumed to be 4K. - * @param size the number of bytes of physically contiguous address space to - * request. - * @param description A textual description of the memory being requested. - * @return _MALI_OSK_ERR_OK on success. Otherwise, a suitable - * _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description ); - -/** @brief Un-request a region of physically contiguous memory - * - * This is used to release a regious of physically contiguous memory previously - * requested through _mali_osk_mem_reqregion, so that other device drivers may - * use it. This will be called at time of Mali device driver termination. - * - * It is a programming error to attempt to: - * - unrequest a region twice - * - unrequest only part of a range obtained through _mali_osk_mem_reqregion - * - unrequest more than the range obtained through _mali_osk_mem_reqregion - * - unrequest an address range that was not successfully requested using - * _mali_osk_mem_reqregion - * - * @param phys CPU-physical base address of the memory to un-request. This must - * be aligned to the system's page size, which is assumed to be 4K - * @param size the number of bytes of physically contiguous address space to - * un-request. - */ -void _mali_osk_mem_unreqregion( u32 phys, u32 size ); - -/** @brief Read from a location currently mapped in through - * _mali_osk_mem_mapioregion - * - * This reads a 32-bit word from a 32-bit aligned location. It is a programming - * error to provide unaligned locations, or to read from memory that is not - * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or - * _mali_osk_mem_allocioregion(). - * - * @param mapping Mali IO address to read from - * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4 - * @return the 32-bit word from the specified location. - */ -u32 _mali_osk_mem_ioread32( volatile mali_io_address mapping, u32 offset ); - -/** @brief Write to a location currently mapped in through - * _mali_osk_mem_mapioregion without memory barriers - * - * This write a 32-bit word to a 32-bit aligned location without using memory barrier. - * It is a programming error to provide unaligned locations, or to write to memory that is not - * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or - * _mali_osk_mem_allocioregion(). - * - * @param mapping Mali IO address to write to - * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4 - * @param val the 32-bit word to write. - */ -void _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val ); - -/** @brief Write to a location currently mapped in through - * _mali_osk_mem_mapioregion with write memory barrier - * - * This write a 32-bit word to a 32-bit aligned location. It is a programming - * error to provide unaligned locations, or to write to memory that is not - * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or - * _mali_osk_mem_allocioregion(). - * - * @param mapping Mali IO address to write to - * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4 - * @param val the 32-bit word to write. - */ -void _mali_osk_mem_iowrite32( volatile mali_io_address mapping, u32 offset, u32 val ); - -/** @brief Flush all CPU caches - * - * This should only be implemented if flushing of the cache is required for - * memory mapped in through _mali_osk_mem_mapregion. - */ -void _mali_osk_cache_flushall( void ); - -/** @brief Flush any caches necessary for the CPU and MALI to have the same view of a range of uncached mapped memory - * - * This should only be implemented if your OS doesn't do a full cache flush (inner & outer) - * after allocating uncached mapped memory. - * - * Some OS do not perform a full cache flush (including all outer caches) for uncached mapped memory. - * They zero the memory through a cached mapping, then flush the inner caches but not the outer caches. - * This is required for MALI to have the correct view of the memory. - */ -void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size ); - -/** @} */ /* end group _mali_osk_low_level_memory */ - - -/** @addtogroup _mali_osk_notification - * - * User space notification framework - * - * Communication with user space of asynchronous events is performed through a - * synchronous call to the \ref u_k_api. - * - * Since the events are asynchronous, the events have to be queued until a - * synchronous U/K API call can be made by user-space. A U/K API call might also - * be received before any event has happened. Therefore the notifications the - * different subsystems wants to send to user space has to be queued for later - * reception, or a U/K API call has to be blocked until an event has occured. - * - * Typical uses of notifications are after running of jobs on the hardware or - * when changes to the system is detected that needs to be relayed to user - * space. - * - * After an event has occured user space has to be notified using some kind of - * message. The notification framework supports sending messages to waiting - * threads or queueing of messages until a U/K API call is made. - * - * The notification queue is a FIFO. There are no restrictions on the numbers - * of readers or writers in the queue. - * - * A message contains what user space needs to identifiy how to handle an - * event. This includes a type field and a possible type specific payload. - * - * A notification to user space is represented by a - * \ref _mali_osk_notification_t object. A sender gets hold of such an object - * using _mali_osk_notification_create(). The buffer given by the - * _mali_osk_notification_t::result_buffer field in the object is used to store - * any type specific data. The other fields are internal to the queue system - * and should not be touched. - * - * @{ */ - -/** @brief Create a notification object - * - * Returns a notification object which can be added to the queue of - * notifications pending for user space transfer. - * - * The implementation will initialize all members of the - * \ref _mali_osk_notification_t object. In particular, the - * _mali_osk_notification_t::result_buffer member will be initialized to point - * to \a size bytes of storage, and that storage will be suitably aligned for - * storage of any structure. That is, the created buffer meets the same - * requirements as _mali_osk_malloc(). - * - * The notification object must be deleted when not in use. Use - * _mali_osk_notification_delete() for deleting it. - * - * @note You \b must \b not call _mali_osk_free() on a \ref _mali_osk_notification_t, - * object, or on a _mali_osk_notification_t::result_buffer. You must only use - * _mali_osk_notification_delete() to free the resources assocaited with a - * \ref _mali_osk_notification_t object. - * - * @param type The notification type - * @param size The size of the type specific buffer to send - * @return Pointer to a notification object with a suitable buffer, or NULL on error. - */ -_mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ); - -/** @brief Delete a notification object - * - * This must be called to reclaim the resources of a notification object. This - * includes: - * - The _mali_osk_notification_t::result_buffer - * - The \ref _mali_osk_notification_t itself. - * - * A notification object \b must \b not be used after it has been deleted by - * _mali_osk_notification_delete(). - * - * In addition, the notification object may not be deleted while it is in a - * queue. That is, if it has been placed on a queue with - * _mali_osk_notification_queue_send(), then it must not be deleted until - * it has been received by a call to _mali_osk_notification_queue_receive(). - * Otherwise, the queue may be corrupted. - * - * @param object the notification object to delete. - */ -void _mali_osk_notification_delete( _mali_osk_notification_t *object ); - -/** @brief Create a notification queue - * - * Creates a notification queue which can be used to queue messages for user - * delivery and get queued messages from - * - * The queue is a FIFO, and has no restrictions on the numbers of readers or - * writers. - * - * When the queue is no longer in use, it must be terminated with - * \ref _mali_osk_notification_queue_term(). Failure to do so will result in a - * memory leak. - * - * @return Pointer to a new notification queue or NULL on error. - */ -_mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void ); - -/** @brief Destroy a notification queue - * - * Destroys a notification queue and frees associated resources from the queue. - * - * A notification queue \b must \b not be destroyed in the following cases: - * - while there are \ref _mali_osk_notification_t objects in the queue. - * - while there are writers currently acting upon the queue. That is, while - * a thread is currently calling \ref _mali_osk_notification_queue_send() on - * the queue, or while a thread may call - * \ref _mali_osk_notification_queue_send() on the queue in the future. - * - while there are readers currently waiting upon the queue. That is, while - * a thread is currently calling \ref _mali_osk_notification_queue_receive() on - * the queue, or while a thread may call - * \ref _mali_osk_notification_queue_receive() on the queue in the future. - * - * Therefore, all \ref _mali_osk_notification_t objects must be flushed and - * deleted by the code that makes use of the notification queues, since only - * they know the structure of the _mali_osk_notification_t::result_buffer - * (even if it may only be a flat sturcture). - * - * @note Since the queue is a FIFO, the code using notification queues may - * create its own 'flush' type of notification, to assist in flushing the - * queue. - * - * Once the queue has been destroyed, it must not be used again. - * - * @param queue The queue to destroy - */ -void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue ); - -/** @brief Schedule notification for delivery - * - * When a \ref _mali_osk_notification_t object has been created successfully - * and set up, it may be added to the queue of objects waiting for user space - * transfer. - * - * The sending will not block if the queue is full. - * - * A \ref _mali_osk_notification_t object \b must \b not be put on two different - * queues at the same time, or enqueued twice onto a single queue before - * reception. However, it is acceptable for it to be requeued \em after reception - * from a call to _mali_osk_notification_queue_receive(), even onto the same queue. - * - * Again, requeuing must also not enqueue onto two different queues at the same - * time, or enqueue onto the same queue twice before reception. - * - * @param queue The notification queue to add this notification to - * @param object The entry to add - */ -void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object ); - -#if MALI_STATE_TRACKING -/** @brief Receive a notification from a queue - * - * Check if a notification queue is empty. - * - * @param queue The queue to check. - * @return MALI_TRUE if queue is empty, otherwise MALI_FALSE. - */ -mali_bool _mali_osk_notification_queue_is_empty( _mali_osk_notification_queue_t *queue ); -#endif - -/** @brief Receive a notification from a queue - * - * Receives a single notification from the given queue. - * - * If no notifciations are ready the thread will sleep until one becomes ready. - * Therefore, notifications may not be received into an - * IRQ or 'atomic' context (that is, a context where sleeping is disallowed). - * - * @param queue The queue to receive from - * @param result Pointer to storage of a pointer of type - * \ref _mali_osk_notification_t*. \a result will be written to such that the - * expression \a (*result) will evaluate to a pointer to a valid - * \ref _mali_osk_notification_t object, or NULL if none were received. - * @return _MALI_OSK_ERR_OK on success. _MALI_OSK_ERR_RESTARTSYSCALL if the sleep was interrupted. - */ -_mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ); - -/** @brief Dequeues a notification from a queue - * - * Receives a single notification from the given queue. - * - * If no notifciations are ready the function call will return an error code. - * - * @param queue The queue to receive from - * @param result Pointer to storage of a pointer of type - * \ref _mali_osk_notification_t*. \a result will be written to such that the - * expression \a (*result) will evaluate to a pointer to a valid - * \ref _mali_osk_notification_t object, or NULL if none were received. - * @return _MALI_OSK_ERR_OK on success, _MALI_OSK_ERR_ITEM_NOT_FOUND if queue was empty. - */ -_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ); - -/** @} */ /* end group _mali_osk_notification */ - - -/** @addtogroup _mali_osk_timer - * - * Timers use the OS's representation of time, which are 'ticks'. This is to - * prevent aliasing problems between the internal timer time, and the time - * asked for. - * - * @{ */ - -/** @brief Initialize a timer - * - * Allocates resources for a new timer, and initializes them. This does not - * start the timer. - * - * @return a pointer to the allocated timer object, or NULL on failure. - */ -_mali_osk_timer_t *_mali_osk_timer_init(void); - -/** @brief Start a timer - * - * It is an error to start a timer without setting the callback via - * _mali_osk_timer_setcallback(). - * - * It is an error to use this to start an already started timer. - * - * The timer will expire in \a ticks_to_expire ticks, at which point, the - * callback function will be invoked with the callback-specific data, - * as registered by _mali_osk_timer_setcallback(). - * - * @param tim the timer to start - * @param ticks_to_expire the amount of time in ticks for the timer to run - * before triggering. - */ -void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire ); - -/** @brief Modify a timer - * - * Set the absolute time at which a timer will expire, and start it if it is - * stopped. If \a expiry_tick is in the past (determined by - * _mali_osk_time_after() ), the timer fires immediately. - * - * It is an error to modify a timer without setting the callback via - * _mali_osk_timer_setcallback(). - * - * The timer will expire at absolute time \a expiry_tick, at which point, the - * callback function will be invoked with the callback-specific data, as set - * by _mali_osk_timer_setcallback(). - * - * @param tim the timer to modify, and start if necessary - * @param expiry_tick the \em absolute time in ticks at which this timer should - * trigger. - * - */ -void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick); - -/** @brief Stop a timer, and block on its completion. - * - * Stop the timer. When the function returns, it is guaranteed that the timer's - * callback will not be running on any CPU core. - * - * Since stoping the timer blocks on compeletion of the callback, the callback - * may not obtain any mutexes that the caller holds. Otherwise, a deadlock will - * occur. - * - * @note While the callback itself is guaranteed to not be running, work - * enqueued on the IRQ work-queue by the timer (with - * \ref _mali_osk_irq_schedulework()) may still run. The timer callback and IRQ - * bottom-half handler must take this into account. - * - * It is legal to stop an already stopped timer. - * - * @param tim the timer to stop. - * - */ -void _mali_osk_timer_del( _mali_osk_timer_t *tim ); - -/** @brief Set a timer's callback parameters. - * - * This must be called at least once before a timer is started/modified. - * - * After a timer has been stopped or expires, the callback remains set. This - * means that restarting the timer will call the same function with the same - * parameters on expiry. - * - * @param tim the timer to set callback on. - * @param callback Function to call when timer expires - * @param data Function-specific data to supply to the function on expiry. - */ -void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data ); - -/** @brief Terminate a timer, and deallocate resources. - * - * The timer must first be stopped by calling _mali_osk_timer_del(). - * - * It is a programming error for _mali_osk_timer_term() to be called on: - * - timer that is currently running - * - a timer that is currently executing its callback. - * - * @param tim the timer to deallocate. - */ -void _mali_osk_timer_term( _mali_osk_timer_t *tim ); -/** @} */ /* end group _mali_osk_timer */ - - -/** @defgroup _mali_osk_time OSK Time functions - * - * \ref _mali_osk_time use the OS's representation of time, which are - * 'ticks'. This is to prevent aliasing problems between the internal timer - * time, and the time asked for. - * - * OS tick time is measured as a u32. The time stored in a u32 may either be - * an absolute time, or a time delta between two events. Whilst it is valid to - * use math opeartors to \em change the tick value represented as a u32, it - * is often only meaningful to do such operations on time deltas, rather than - * on absolute time. However, it is meaningful to add/subtract time deltas to - * absolute times. - * - * Conversion between tick time and milliseconds (ms) may not be loss-less, - * and are \em implementation \em depenedant. - * - * Code use OS time must take this into account, since: - * - a small OS time may (or may not) be rounded - * - a large time may (or may not) overflow - * - * @{ */ - -/** @brief Return whether ticka occurs after tickb - * - * Some OSs handle tick 'rollover' specially, and so can be more robust against - * tick counters rolling-over. This function must therefore be called to - * determine if a time (in ticks) really occurs after another time (in ticks). - * - * @param ticka ticka - * @param tickb tickb - * @return non-zero if ticka represents a time that occurs after tickb. - * Zero otherwise. - */ -int _mali_osk_time_after( u32 ticka, u32 tickb ); - -/** @brief Convert milliseconds to OS 'ticks' - * - * @param ms time interval in milliseconds - * @return the corresponding time interval in OS ticks. - */ -u32 _mali_osk_time_mstoticks( u32 ms ); - -/** @brief Convert OS 'ticks' to milliseconds - * - * @param ticks time interval in OS ticks. - * @return the corresponding time interval in milliseconds - */ -u32 _mali_osk_time_tickstoms( u32 ticks ); - - -/** @brief Get the current time in OS 'ticks'. - * @return the current time in OS 'ticks'. - */ -u32 _mali_osk_time_tickcount( void ); - -/** @brief Cause a microsecond delay - * - * The delay will have microsecond resolution, and is necessary for correct - * operation of the driver. At worst, the delay will be \b at least \a usecs - * microseconds, and so may be (significantly) more. - * - * This function may be implemented as a busy-wait, which is the most sensible - * implementation. On OSs where there are situations in which a thread must not - * sleep, this is definitely implemented as a busy-wait. - * - * @param usecs the number of microseconds to wait for. - */ -void _mali_osk_time_ubusydelay( u32 usecs ); - -/** @brief Return time in nano seconds, since any given reference. - * - * @return Time in nano seconds - */ -u64 _mali_osk_time_get_ns( void ); - - -/** @} */ /* end group _mali_osk_time */ - -/** @defgroup _mali_osk_math OSK Math - * @{ */ - -/** @brief Count Leading Zeros (Little-endian) - * - * @note This function must be implemented to support the reference - * implementation of _mali_osk_find_first_zero_bit, as defined in - * mali_osk_bitops.h. - * - * @param val 32-bit words to count leading zeros on - * @return the number of leading zeros. - */ -u32 _mali_osk_clz( u32 val ); -/** @} */ /* end group _mali_osk_math */ - -/** @defgroup _mali_osk_wait_queue OSK Wait Queue functionality - * @{ */ -/** @brief Private type for wait queue objects */ -typedef struct _mali_osk_wait_queue_t_struct _mali_osk_wait_queue_t; - -/** @brief Initialize an empty Wait Queue */ -_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void ); - -/** @brief Sleep if condition is false - * - * @param queue the queue to use - * @param condition function pointer to a boolean function - * - * Put thread to sleep if the given \a codition function returns false. When - * being asked to wake up again, the condition will be re-checked and the - * thread only woken up if the condition is now true. - */ -void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void) ); - -/** @brief Wake up all threads in wait queue if their respective conditions are - * true - * - * @param queue the queue whose threads should be woken up - * - * Wake up all threads in wait queue \a queue whose condition is now true. - */ -void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue ); - -/** @brief terminate a wait queue - * - * @param queue the queue to terminate. - */ -void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue ); -/** @} */ /* end group _mali_osk_wait_queue */ - - -/** @addtogroup _mali_osk_miscellaneous - * @{ */ - -/** @brief Output a device driver debug message. - * - * The interpretation of \a fmt is the same as the \c format parameter in - * _mali_osu_vsnprintf(). - * - * @param fmt a _mali_osu_vsnprintf() style format string - * @param ... a variable-number of parameters suitable for \a fmt - */ -void _mali_osk_dbgmsg( const char *fmt, ... ); - -/** @brief Print fmt into buf. - * - * The interpretation of \a fmt is the same as the \c format parameter in - * _mali_osu_vsnprintf(). - * - * @param buf a pointer to the result buffer - * @param size the total number of bytes allowed to write to \a buf - * @param fmt a _mali_osu_vsnprintf() style format string - * @param ... a variable-number of parameters suitable for \a fmt - * @return The number of bytes written to \a buf - */ -u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... ); - -/** @brief Abnormal process abort. - * - * Terminates the caller-process if this function is called. - * - * This function will be called from Debug assert-macros in mali_kernel_common.h. - * - * This function will never return - because to continue from a Debug assert - * could cause even more problems, and hinder debugging of the initial problem. - * - * This function is only used in Debug builds, and is not used in Release builds. - */ -void _mali_osk_abort(void); - -/** @brief Sets breakpoint at point where function is called. - * - * This function will be called from Debug assert-macros in mali_kernel_common.h, - * to assist in debugging. If debugging at this level is not required, then this - * function may be implemented as a stub. - * - * This function is only used in Debug builds, and is not used in Release builds. - */ -void _mali_osk_break(void); - -/** @brief Return an identificator for calling process. - * - * @return Identificator for calling process. - */ -u32 _mali_osk_get_pid(void); - -/** @brief Return an identificator for calling thread. - * - * @return Identificator for calling thread. - */ -u32 _mali_osk_get_tid(void); - -/** @brief Enable OS controlled runtime power management - */ -void _mali_osk_pm_dev_enable(void); - -/** @brief Tells the OS that device is now idle - */ -_mali_osk_errcode_t _mali_osk_pm_dev_idle(void); - -/** @brief Tells the OS that the device is about to become active - */ -_mali_osk_errcode_t _mali_osk_pm_dev_activate(void); - -/** @} */ /* end group _mali_osk_miscellaneous */ - -/** @} */ /* end group osuapi */ - -/** @} */ /* end group uddapi */ - - -#ifdef __cplusplus -} -#endif - -#include "mali_osk_specific.h" /* include any per-os specifics */ - -/* Check standard inlines */ -#ifndef MALI_STATIC_INLINE - #error MALI_STATIC_INLINE not defined on your OS -#endif - -#ifndef MALI_NON_STATIC_INLINE - #error MALI_NON_STATIC_INLINE not defined on your OS -#endif - -#endif /* __MALI_OSK_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk_bitops.h b/drivers/media/video/samsung/mali/common/mali_osk_bitops.h deleted file mode 100644 index ada1488..0000000 --- a/drivers/media/video/samsung/mali/common/mali_osk_bitops.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_bitops.h - * Implementation of the OS abstraction layer for the kernel device driver - */ - -#ifndef __MALI_OSK_BITOPS_H__ -#define __MALI_OSK_BITOPS_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -MALI_STATIC_INLINE void _mali_internal_clear_bit( u32 bit, u32 *addr ) -{ - MALI_DEBUG_ASSERT( bit < 32 ); - MALI_DEBUG_ASSERT( NULL != addr ); - - (*addr) &= ~(1 << bit); -} - -MALI_STATIC_INLINE void _mali_internal_set_bit( u32 bit, u32 *addr ) -{ - MALI_DEBUG_ASSERT( bit < 32 ); - MALI_DEBUG_ASSERT( NULL != addr ); - - (*addr) |= (1 << bit); -} - -MALI_STATIC_INLINE u32 _mali_internal_test_bit( u32 bit, u32 value ) -{ - MALI_DEBUG_ASSERT( bit < 32 ); - return value & (1 << bit); -} - -MALI_STATIC_INLINE int _mali_internal_find_first_zero_bit( u32 value ) -{ - u32 inverted; - u32 negated; - u32 isolated; - u32 leading_zeros; - - /* Begin with xxx...x0yyy...y, where ys are 1, number of ys is in range 0..31 */ - inverted = ~value; /* zzz...z1000...0 */ - /* Using count_trailing_zeros on inverted value - - * See ARM System Developers Guide for details of count_trailing_zeros */ - - /* Isolate the zero: it is preceeded by a run of 1s, so add 1 to it */ - negated = (u32)-inverted ; /* -a == ~a + 1 (mod 2^n) for n-bit numbers */ - /* negated = xxx...x1000...0 */ - - isolated = negated & inverted ; /* xxx...x1000...0 & zzz...z1000...0, zs are ~xs */ - /* And so the first zero bit is in the same position as the 1 == number of 1s that preceeded it - * Note that the output is zero if value was all 1s */ - - leading_zeros = _mali_osk_clz( isolated ); - - return 31 - leading_zeros; -} - - -/** @defgroup _mali_osk_bitops OSK Non-atomic Bit-operations - * @{ */ - -/** - * These bit-operations do not work atomically, and so locks must be used if - * atomicity is required. - * - * Reference implementations for Little Endian are provided, and so it should - * not normally be necessary to re-implement these. Efficient bit-twiddling - * techniques are used where possible, implemented in portable C. - * - * Note that these reference implementations rely on _mali_osk_clz() being - * implemented. - */ - -/** @brief Clear a bit in a sequence of 32-bit words - * @param nr bit number to clear, starting from the (Little-endian) least - * significant bit - * @param addr starting point for counting. - */ -MALI_STATIC_INLINE void _mali_osk_clear_nonatomic_bit( u32 nr, u32 *addr ) -{ - addr += nr >> 5; /* find the correct word */ - nr = nr & ((1 << 5)-1); /* The bit number within the word */ - - _mali_internal_clear_bit( nr, addr ); -} - -/** @brief Set a bit in a sequence of 32-bit words - * @param nr bit number to set, starting from the (Little-endian) least - * significant bit - * @param addr starting point for counting. - */ -MALI_STATIC_INLINE void _mali_osk_set_nonatomic_bit( u32 nr, u32 *addr ) -{ - addr += nr >> 5; /* find the correct word */ - nr = nr & ((1 << 5)-1); /* The bit number within the word */ - - _mali_internal_set_bit( nr, addr ); -} - -/** @brief Test a bit in a sequence of 32-bit words - * @param nr bit number to test, starting from the (Little-endian) least - * significant bit - * @param addr starting point for counting. - * @return zero if bit was clear, non-zero if set. Do not rely on the return - * value being related to the actual word under test. - */ -MALI_STATIC_INLINE u32 _mali_osk_test_bit( u32 nr, u32 *addr ) -{ - addr += nr >> 5; /* find the correct word */ - nr = nr & ((1 << 5)-1); /* The bit number within the word */ - - return _mali_internal_test_bit( nr, *addr ); -} - -/* Return maxbit if not found */ -/** @brief Find the first zero bit in a sequence of 32-bit words - * @param addr starting point for search. - * @param maxbit the maximum number of bits to search - * @return the number of the first zero bit found, or maxbit if none were found - * in the specified range. - */ -MALI_STATIC_INLINE u32 _mali_osk_find_first_zero_bit( const u32 *addr, u32 maxbit ) -{ - u32 total; - - for ( total = 0; total < maxbit; total += 32, ++addr ) - { - int result; - result = _mali_internal_find_first_zero_bit( *addr ); - - /* non-negative signifies the bit was found */ - if ( result >= 0 ) - { - total += (u32)result; - break; - } - } - - /* Now check if we reached maxbit or above */ - if ( total >= maxbit ) - { - total = maxbit; - } - - return total; /* either the found bit nr, or maxbit if not found */ -} -/** @} */ /* end group _mali_osk_bitops */ - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_OSK_BITOPS_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk_list.h b/drivers/media/video/samsung/mali/common/mali_osk_list.h deleted file mode 100644 index 5987b0a..0000000 --- a/drivers/media/video/samsung/mali/common/mali_osk_list.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_list.h - * Implementation of the OS abstraction layer for the kernel device driver - */ - -#ifndef __MALI_OSK_LIST_H__ -#define __MALI_OSK_LIST_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -MALI_STATIC_INLINE void __mali_osk_list_add(_mali_osk_list_t *new_entry, _mali_osk_list_t *prev, _mali_osk_list_t *next) -{ - next->prev = new_entry; - new_entry->next = next; - new_entry->prev = prev; - prev->next = new_entry; -} - -MALI_STATIC_INLINE void __mali_osk_list_del(_mali_osk_list_t *prev, _mali_osk_list_t *next) -{ - next->prev = prev; - prev->next = next; -} - -/** @addtogroup _mali_osk_list - * @{ */ - -/** Reference implementations of Doubly-linked Circular Lists are provided. - * There is often no need to re-implement these. - * - * @note The implementation may differ subtly from any lists the OS provides. - * For this reason, these lists should not be mixed with OS-specific lists - * inside the OSK/UKK implementation. */ - -/** @brief Initialize a list element. - * - * All list elements must be initialized before use. - * - * Do not use on any list element that is present in a list without using - * _mali_osk_list_del first, otherwise this will break the list. - * - * @param list the list element to initialize - */ -MALI_STATIC_INLINE void _mali_osk_list_init( _mali_osk_list_t *list ) -{ - list->next = list; - list->prev = list; -} - -/** @brief Insert a single list element after an entry in a list - * - * As an example, if this is inserted to the head of a list, then this becomes - * the first element of the list. - * - * Do not use to move list elements from one list to another, as it will break - * the originating list. - * - * - * @param newlist the list element to insert - * @param list the list in which to insert. The new element will be the next - * entry in this list - */ -MALI_STATIC_INLINE void _mali_osk_list_add( _mali_osk_list_t *new_entry, _mali_osk_list_t *list ) -{ - __mali_osk_list_add(new_entry, list, list->next); -} - -/** @brief Insert a single list element before an entry in a list - * - * As an example, if this is inserted to the head of a list, then this becomes - * the last element of the list. - * - * Do not use to move list elements from one list to another, as it will break - * the originating list. - * - * @param newlist the list element to insert - * @param list the list in which to insert. The new element will be the previous - * entry in this list - */ -MALI_STATIC_INLINE void _mali_osk_list_addtail( _mali_osk_list_t *new_entry, _mali_osk_list_t *list ) -{ - __mali_osk_list_add(new_entry, list->prev, list); -} - -/** @brief Remove a single element from a list - * - * The element will no longer be present in the list. The removed list element - * will be uninitialized, and so should not be traversed. It must be - * initialized before further use. - * - * @param list the list element to remove. - */ -MALI_STATIC_INLINE void _mali_osk_list_del( _mali_osk_list_t *list ) -{ - __mali_osk_list_del(list->prev, list->next); -} - -/** @brief Remove a single element from a list, and re-initialize it - * - * The element will no longer be present in the list. The removed list element - * will initialized, and so can be used as normal. - * - * @param list the list element to remove and initialize. - */ -MALI_STATIC_INLINE void _mali_osk_list_delinit( _mali_osk_list_t *list ) -{ - __mali_osk_list_del(list->prev, list->next); - _mali_osk_list_init(list); -} - -/** @brief Determine whether a list is empty. - * - * An empty list is one that contains a single element that points to itself. - * - * @param list the list to check. - * @return non-zero if the list is empty, and zero otherwise. - */ -MALI_STATIC_INLINE int _mali_osk_list_empty( _mali_osk_list_t *list ) -{ - return list->next == list; -} - -/** @brief Move a list element from one list to another. - * - * The list element must be initialized. - * - * As an example, moving a list item to the head of a new list causes this item - * to be the first element in the new list. - * - * @param move the list element to move - * @param list the new list into which the element will be inserted, as the next - * element in the list. - */ -MALI_STATIC_INLINE void _mali_osk_list_move( _mali_osk_list_t *move_entry, _mali_osk_list_t *list ) -{ - __mali_osk_list_del(move_entry->prev, move_entry->next); - _mali_osk_list_add(move_entry, list); -} - -/** @brief Join two lists - * - * The list element must be initialized. - * - * Allows you to join a list into another list at a specific location - * - * @param list the new list to add - * @param at the location in a list to add the new list into - */ -MALI_STATIC_INLINE void _mali_osk_list_splice( _mali_osk_list_t *list, _mali_osk_list_t *at ) -{ - if (!_mali_osk_list_empty(list)) - { - /* insert all items from 'list' after 'at' */ - _mali_osk_list_t *first = list->next; - _mali_osk_list_t *last = list->prev; - _mali_osk_list_t *split = at->next; - - first->prev = at; - at->next = first; - - last->next = split; - split->prev = last; - } -} -/** @} */ /* end group _mali_osk_list */ - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_OSK_LIST_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk_mali.h b/drivers/media/video/samsung/mali/common/mali_osk_mali.h deleted file mode 100644 index 427fcc8..0000000 --- a/drivers/media/video/samsung/mali/common/mali_osk_mali.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_mali.h - * Defines the OS abstraction layer which is specific for the Mali kernel device driver (OSK) - */ - -#ifndef __MALI_OSK_MALI_H__ -#define __MALI_OSK_MALI_H__ - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** @addtogroup _mali_osk_miscellaneous - * @{ */ - -/** @brief Read the Mali Resource configuration - * - * Populates a _mali_arch_resource_t array from configuration settings, which - * are stored in an OS-specific way. - * - * For example, these may be compiled in to a static structure, or read from - * the filesystem at startup. - * - * On failure, do not call _mali_osk_resources_term. - * - * @param arch_config a pointer to the store the pointer to the resources - * @param num_resources the number of resources read - * @return _MALI_OSK_ERR_OK on success. _MALI_OSK_ERR_NOMEM on allocation - * error. For other failures, a suitable _mali_osk_errcode_t is returned. - */ -_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources ); - -/** @brief Free resources allocated by _mali_osk_resources_init. - * - * Frees the _mali_arch_resource_t array allocated by _mali_osk_resources_init - * - * @param arch_config a pointer to the stored the pointer to the resources - * @param num_resources the number of resources in the array - */ -void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources); -/** @} */ /* end group _mali_osk_miscellaneous */ - -/** @addtogroup _mali_osk_low_level_memory - * @{ */ - -/** @brief Initialize a user-space accessible memory range - * - * This initializes a virtual address range such that it is reserved for the - * current process, but does not map any physical pages into this range. - * - * This function may initialize or adjust any members of the - * mali_memory_allocation \a descriptor supplied, before the physical pages are - * mapped in with _mali_osk_mem_mapregion_map(). - * - * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE - * set in \a descriptor->flags. It is an error to call this function without - * setting this flag. Otherwise, \a descriptor->flags bits are reserved for - * future expansion - * - * The \a descriptor's process_addr_mapping_info member can be modified to - * allocate OS-specific information. Note that on input, this will be a - * ukk_private word from the U/K inteface, as inserted by _mali_ukk_mem_mmap(). - * This is used to pass information from the U/K interface to the OSK interface, - * if necessary. The precise usage of the process_addr_mapping_info member - * depends on the U/K implementation of _mali_ukk_mem_mmap(). - * - * Therefore, the U/K implementation of _mali_ukk_mem_mmap() and the OSK - * implementation of _mali_osk_mem_mapregion_init() must agree on the meaning and - * usage of the ukk_private word and process_addr_mapping_info member. - * - * Refer to \ref u_k_api for more information on the U/K interface. - * - * On successful return, \a descriptor's mapping member will be correct for - * use with _mali_osk_mem_mapregion_term() and _mali_osk_mem_mapregion_map(). - * - * @param descriptor the mali_memory_allocation to initialize. - */ -_mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descriptor ); - -/** @brief Terminate a user-space accessible memory range - * - * This terminates a virtual address range reserved in the current user process, - * where none, some or all of the virtual address ranges have mappings to - * physical pages. - * - * It will unmap any physical pages that had been mapped into a reserved - * virtual address range for the current process, and then releases the virtual - * address range. Any extra book-keeping information or resources allocated - * during _mali_osk_mem_mapregion_init() will also be released. - * - * The \a descriptor itself is not freed - this must be handled by the caller of - * _mali_osk_mem_mapregion_term(). - * - * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE - * set in descriptor->flags. It is an error to call this function without - * setting this flag. Otherwise, descriptor->flags bits are reserved for - * future expansion - * - * @param descriptor the mali_memory_allocation to terminate. - */ -void _mali_osk_mem_mapregion_term( mali_memory_allocation * descriptor ); - -/** @brief Map physical pages into a user process's virtual address range - * - * This is used to map a number of physically contigous pages into a - * user-process's virtual address range, which was previously reserved by a - * call to _mali_osk_mem_mapregion_init(). - * - * This need not provide a mapping for the entire virtual address range - * reserved for \a descriptor - it may be used to map single pages per call. - * - * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE - * set in \a descriptor->flags. It is an error to call this function without - * setting this flag. Otherwise, \a descriptor->flags bits are reserved for - * future expansion - * - * The function may supply \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC. - * In this case, \a size must be set to \ref _MALI_OSK_CPU_PAGE_SIZE, and the function - * will allocate the physical page itself. The physical address of the - * allocated page will be returned through \a phys_addr. - * - * It is an error to set \a size != \ref _MALI_OSK_CPU_PAGE_SIZE while - * \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, - * since it is not always possible for OSs to support such a setting through this - * interface. - * - * @note \b IMPORTANT: This code must validate the input parameters. If the - * range defined by \a offset and \a size is outside the range allocated in - * \a descriptor, then this function \b MUST not attempt any mapping, and must - * instead return a suitable \ref _mali_osk_errcode_t \b failure code. - * - * @param[in,out] descriptor the mali_memory_allocation representing the - * user-process's virtual address range to map into. - * - * @param[in] offset the offset into the virtual address range. This is only added - * to the mapping member of the \a descriptor, and not the \a phys_addr parameter. - * It must be a multiple of \ref _MALI_OSK_CPU_PAGE_SIZE. - * - * @param[in,out] phys_addr a pointer to the physical base address to begin the - * mapping from. If \a size == \ref _MALI_OSK_CPU_PAGE_SIZE and - * \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, then this - * function will allocate the physical page itself, and return the - * physical address of the page through \a phys_addr, which will be aligned to - * \ref _MALI_OSK_CPU_PAGE_SIZE. Otherwise, \a *phys_addr must be aligned to - * \ref _MALI_OSK_CPU_PAGE_SIZE, and is unmodified after the call. - * \a phys_addr is unaffected by the \a offset parameter. - * - * @param[in] size the number of bytes to map in. This must be a multiple of - * \ref _MALI_OSK_CPU_PAGE_SIZE. - * - * @return _MALI_OSK_ERR_OK on sucess, otherwise a _mali_osk_errcode_t value - * on failure - * - * @note could expand to use _mali_osk_mem_mapregion_flags_t instead of - * \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, but note that we must - * also modify the mali process address manager in the mmu/memory engine code. - */ -_mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size ); - - -/** @brief Unmap physical pages from a user process's virtual address range - * - * This is used to unmap a number of physically contigous pages from a - * user-process's virtual address range, which were previously mapped by a - * call to _mali_osk_mem_mapregion_map(). If the range specified was allocated - * from OS memory, then that memory will be returned to the OS. Whilst pages - * will be mapped out, the Virtual address range remains reserved, and at the - * same base address. - * - * When this function is used to unmap pages from OS memory - * (_mali_osk_mem_mapregion_map() was called with *phys_addr == - * \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC), then the \a flags must - * include \ref _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR. This is because - * it is not always easy for an OS implementation to discover whether the - * memory was OS allocated or not (and so, how it should release the memory). - * - * For this reason, only a range of pages of the same allocation type (all OS - * allocated, or none OS allocacted) may be unmapped in one call. Multiple - * calls must be made if allocations of these different types exist across the - * entire region described by the \a descriptor. - * - * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE - * set in \a descriptor->flags. It is an error to call this function without - * setting this flag. Otherwise, \a descriptor->flags bits are reserved for - * future expansion - * - * @param[in,out] descriptor the mali_memory_allocation representing the - * user-process's virtual address range to map into. - * - * @param[in] offset the offset into the virtual address range. This is only added - * to the mapping member of the \a descriptor. \a offset must be a multiple of - * \ref _MALI_OSK_CPU_PAGE_SIZE. - * - * @param[in] size the number of bytes to unmap. This must be a multiple of - * \ref _MALI_OSK_CPU_PAGE_SIZE. - * - * @param[in] flags specifies how the memory should be unmapped. For a range - * of pages that were originally OS allocated, this must have - * \ref _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR set. - */ -void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags ); -/** @} */ /* end group _mali_osk_low_level_memory */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_OSK_MALI_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk_profiling.h b/drivers/media/video/samsung/mali/common/mali_osk_profiling.h deleted file mode 100644 index fd9a8fb..0000000 --- a/drivers/media/video/samsung/mali/common/mali_osk_profiling.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_OSK_PROFILING_H__ -#define __MALI_OSK_PROFILING_H__ - -#if MALI_TIMELINE_PROFILING_ENABLED - -#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED -#include "mali_linux_trace.h" -#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */ - -#include "mali_profiling_events.h" - -#define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576 - -#define MALI_PROFILING_NO_HW_COUNTER = ((u32)-1) - -/** @defgroup _mali_osk_profiling External profiling connectivity - * @{ */ - -/** - * Initialize the profiling module. - * @return _MALI_OSK_ERR_OK on success, otherwise failure. - */ -_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start); - -/* - * Terminate the profiling module. - */ -void _mali_osk_profiling_term(void); - -/** - * Start recording profiling data - * - * The specified limit will determine how large the capture buffer is. - * MALI_PROFILING_MAX_BUFFER_ENTRIES determines the maximum size allowed by the device driver. - * - * @param limit The desired maximum number of events to record on input, the actual maximum on output. - * @return _MALI_OSK_ERR_OK on success, otherwise failure. - */ -_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit); - -/** - * Add an profiling event - * - * @param event_id The event identificator. - * @param data0 First data parameter, depending on event_id specified. - * @param data1 Second data parameter, depending on event_id specified. - * @param data2 Third data parameter, depending on event_id specified. - * @param data3 Fourth data parameter, depending on event_id specified. - * @param data4 Fifth data parameter, depending on event_id specified. - * @return _MALI_OSK_ERR_OK on success, otherwise failure. - */ -#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED -/* Call Linux tracepoint directly */ -#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) trace_mali_timeline_event((event_id), (data0), (data1), (data2), (data3), (data4)) -#else -/* Internal profiling is handled like a plain function call */ -void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4); -#endif - -/** - * Report a hardware counter event. - * - * @param counter_id The ID of the counter. - * @param value The value of the counter. - */ - -#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED -/* Call Linux tracepoint directly */ -#define _mali_osk_profiling_report_hw_counter(counter_id, value) trace_mali_hw_counter(counter_id, value) -#else -/* Internal profiling is handled like a plain function call */ -void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value); -#endif - -/** - * Report SW counters - * - * @param counters array of counter values - */ -void _mali_osk_profiling_report_sw_counters(u32 *counters); - -/** - * Stop recording profiling data - * - * @param count Returns the number of recorded events. - * @return _MALI_OSK_ERR_OK on success, otherwise failure. - */ -_mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count); - -/** - * Retrieves the number of events that can be retrieved - * - * @return The number of recorded events that can be retrieved. - */ -u32 _mali_osk_profiling_get_count(void); - -/** - * Retrieve an event - * - * @param index Event index (start with 0 and continue until this function fails to retrieve all events) - * @param timestamp The timestamp for the retrieved event will be stored here. - * @param event_id The event ID for the retrieved event will be stored here. - * @param data The 5 data values for the retrieved event will be stored here. - * @return _MALI_OSK_ERR_OK on success, otherwise failure. - */ -_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]); - -/** - * Clear the recorded buffer. - * - * This is needed in order to start another recording. - * - * @return _MALI_OSK_ERR_OK on success, otherwise failure. - */ -_mali_osk_errcode_t _mali_osk_profiling_clear(void); - -/** - * Checks if a recording of profiling data is in progress - * - * @return MALI_TRUE if recording of profiling data is in progress, MALI_FALSE if not - */ -mali_bool _mali_osk_profiling_is_recording(void); - -/** - * Checks if profiling data is available for retrival - * - * @return MALI_TRUE if profiling data is avaiable, MALI_FALSE if not - */ -mali_bool _mali_osk_profiling_have_recording(void); - -/** @} */ /* end group _mali_osk_profiling */ - -#endif /* MALI_TIMELINE_PROFILING_ENABLED */ - -#endif /* __MALI_OSK_PROFILING_H__ */ - - diff --git a/drivers/media/video/samsung/mali/common/mali_pm.c b/drivers/media/video/samsung/mali/common/mali_pm.c deleted file mode 100644 index 933e54e..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pm.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_pm.h" -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_gp_scheduler.h" -#include "mali_pp_scheduler.h" -#include "mali_platform.h" -#include "mali_kernel_utilization.h" -#include "mali_kernel_core.h" -#include "mali_group.h" - -#define MALI_PM_LIGHT_SLEEP_TIMEOUT 1000 - -enum mali_pm_scheme -{ - MALI_PM_SCHEME_DYNAMIC, - MALI_PM_SCHEME_OS_SUSPENDED, - MALI_PM_SCHEME_ALWAYS_ON -}; - -enum mali_pm_level -{ - MALI_PM_LEVEL_1_ON, - MALI_PM_LEVEL_2_STANDBY, - MALI_PM_LEVEL_3_LIGHT_SLEEP, - MALI_PM_LEVEL_4_DEEP_SLEEP -}; -static _mali_osk_lock_t *mali_pm_lock_set_next_state; -static _mali_osk_lock_t *mali_pm_lock_set_core_states; -static _mali_osk_lock_t *mali_pm_lock_execute_state_change; -static _mali_osk_irq_t *wq_irq; - -static _mali_osk_timer_t *idle_timer = NULL; -static mali_bool idle_timer_running = MALI_FALSE; -static u32 mali_pm_event_number = 0; - -static u32 num_active_gps = 0; -static u32 num_active_pps = 0; - -static enum mali_pm_scheme current_scheme = MALI_PM_SCHEME_DYNAMIC; -static enum mali_pm_level current_level = MALI_PM_LEVEL_1_ON; -static enum mali_pm_level next_level_dynamic = MALI_PM_LEVEL_2_STANDBY; /* Should be the state we go to when we go out of MALI_PM_SCHEME_ALWAYS_ON during init */ - - - -static _mali_osk_errcode_t mali_pm_upper_half(void *data); -static void mali_pm_bottom_half(void *data); -static void mali_pm_powerup(void); -static void mali_pm_powerdown(mali_power_mode power_mode); - -static void timeout_light_sleep(void* arg); -#if 0 -/* Deep sleep timout not supported */ -static void timeout_deep_sleep(void* arg); -#endif -static u32 mali_pm_event_number_get(void); -static void mali_pm_event(enum mali_pm_event pm_event, mali_bool schedule_work, u32 timer_time ); - -_mali_osk_errcode_t mali_pm_initialize(void) -{ - mali_pm_lock_execute_state_change = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PM_EXECUTE); - - if (NULL != mali_pm_lock_execute_state_change ) - { - mali_pm_lock_set_next_state = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ONELOCK| _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_LAST); - - if (NULL != mali_pm_lock_set_next_state) - { - mali_pm_lock_set_core_states = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PM_CORE_STATE); - - if (NULL != mali_pm_lock_set_core_states) - { - idle_timer = _mali_osk_timer_init(); - if (NULL != idle_timer) - { - wq_irq = _mali_osk_irq_init(_MALI_OSK_IRQ_NUMBER_PMM, - mali_pm_upper_half, - mali_pm_bottom_half, - NULL, - NULL, - (void *)NULL, - "Mali PM deferred work"); - if (NULL != wq_irq) - { - if (_MALI_OSK_ERR_OK == mali_platform_init()) - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - _mali_osk_pm_dev_enable(); - mali_pm_powerup(); -#endif - return _MALI_OSK_ERR_OK; - } - - _mali_osk_irq_term(wq_irq); - } - - _mali_osk_timer_del(idle_timer); - _mali_osk_timer_term(idle_timer); - } - _mali_osk_lock_term(mali_pm_lock_set_core_states); - } - _mali_osk_lock_term(mali_pm_lock_set_next_state); - } - _mali_osk_lock_term(mali_pm_lock_execute_state_change); - } - - return _MALI_OSK_ERR_FAULT; -} - -void mali_pm_terminate(void) -{ - mali_platform_deinit(); - _mali_osk_irq_term(wq_irq); - _mali_osk_timer_del(idle_timer); - _mali_osk_timer_term(idle_timer); - _mali_osk_lock_term(mali_pm_lock_execute_state_change); - _mali_osk_lock_term(mali_pm_lock_set_next_state); - _mali_osk_lock_term(mali_pm_lock_set_core_states); -} - - -inline void mali_pm_lock(void) -{ - _mali_osk_lock_wait(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW); -} - -inline void mali_pm_unlock(void) -{ - _mali_osk_lock_signal(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW); -} - -inline void mali_pm_execute_state_change_lock(void) -{ - _mali_osk_lock_wait(mali_pm_lock_execute_state_change,_MALI_OSK_LOCKMODE_RW); -} - -inline void mali_pm_execute_state_change_unlock(void) -{ - _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW); -} - -static void mali_pm_powerup(void) -{ -#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT(3, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n")); - mali_platform_power_mode_change(MALI_POWER_MODE_ON); -#else - /* Aquire our reference */ - _mali_osk_pm_dev_activate(); -#endif - mali_group_power_on(); -} - -static void mali_pm_powerdown(mali_power_mode power_mode) -{ - if ( (MALI_PM_LEVEL_1_ON == current_level) || (MALI_PM_LEVEL_2_STANDBY == current_level) ) - { - mali_group_power_off(); - } - -#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON - mali_platform_power_mode_change(power_mode); -#else - _mali_osk_pm_dev_idle(); - - if (MALI_POWER_MODE_DEEP_SLEEP == power_mode) - { - mali_platform_power_mode_change(power_mode); - } -#endif -} - -mali_bool mali_pm_is_powered_on(void) -{ - mali_bool is_on = MALI_TRUE; - - if( ! (MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme) ) - { - is_on = MALI_FALSE; - } - else if ( ! (MALI_PM_LEVEL_1_ON == current_level || MALI_PM_LEVEL_2_STANDBY == current_level)) - { - is_on = MALI_FALSE; - } - else if ( ! (MALI_PM_LEVEL_1_ON == next_level_dynamic || MALI_PM_LEVEL_2_STANDBY == next_level_dynamic)) - { - is_on = MALI_FALSE; - } - - return is_on; -} - -MALI_DEBUG_CODE( -static const char *state_as_string(enum mali_pm_level level) -{ - switch(level) - { - case MALI_PM_LEVEL_1_ON: - return "MALI_PM_LEVEL_1_ON"; - case MALI_PM_LEVEL_2_STANDBY: - return "MALI_PM_LEVEL_2_STANDBY"; - case MALI_PM_LEVEL_3_LIGHT_SLEEP: - return "MALI_PM_LEVEL_3_LIGHT_SLEEP"; - case MALI_PM_LEVEL_4_DEEP_SLEEP: - return "MALI_PM_LEVEL_4_DEEP_SLEEP"; - default: - return "UNKNOWN LEVEL"; - } -}); - -/* This could be used from another thread (work queue), if we need that */ -static void mali_pm_process_next(void) -{ - enum mali_pm_level pm_level_to_set; - - _mali_osk_lock_wait(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW); - - pm_level_to_set = current_level; - - if (MALI_PM_SCHEME_DYNAMIC == current_scheme) - { - pm_level_to_set = next_level_dynamic; - - MALI_DEBUG_PRINT(4, ("Mali PM: Dynamic scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(pm_level_to_set))); - - if (current_level == pm_level_to_set) - { - goto end_function; /* early out, no change in power level */ - } - - /* Start timers according to new state, so we get STANDBY -> LIGHT_SLEEP -> DEEP_SLEEP */ - - if (MALI_TRUE == idle_timer_running) - { - /* There is an existing timeout, so delete it */ - _mali_osk_timer_del(idle_timer); - idle_timer_running = MALI_FALSE; - } - - /* Making sure that we turn on through the platform file - Since it was turned OFF directly through the platform file. - This might lead to double turn-on, but the plaform file supports that.*/ - if ( current_level == MALI_PM_LEVEL_4_DEEP_SLEEP) - { - mali_pm_powerup(); - mali_kernel_core_wakeup(); - - } - if (MALI_PM_LEVEL_1_ON == pm_level_to_set) - { - if (MALI_PM_LEVEL_2_STANDBY != current_level) - { - /* We only need to do anything if we came from one of the sleeping states */ - mali_pm_powerup(); - - /* Wake up Mali cores since we came from a sleep state */ - mali_kernel_core_wakeup(); - } - } - else if (MALI_PM_LEVEL_2_STANDBY == pm_level_to_set) - { - /* This is just an internal state, so we don't bother to report it to the platform file */ - idle_timer_running = MALI_TRUE; - _mali_osk_timer_setcallback(idle_timer, timeout_light_sleep, (void*) mali_pm_event_number_get()); - _mali_osk_timer_add(idle_timer, _mali_osk_time_mstoticks(MALI_PM_LIGHT_SLEEP_TIMEOUT)); - } - else if (MALI_PM_LEVEL_3_LIGHT_SLEEP == pm_level_to_set) - { - mali_pm_powerdown(MALI_POWER_MODE_LIGHT_SLEEP); - } - else if (MALI_PM_LEVEL_4_DEEP_SLEEP == pm_level_to_set) - { - MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n")); - mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP); - } - } - else if (MALI_PM_SCHEME_OS_SUSPENDED == current_scheme) - { - MALI_DEBUG_PRINT(4, ("Mali PM: OS scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(MALI_PM_LEVEL_4_DEEP_SLEEP))); - - pm_level_to_set = MALI_PM_LEVEL_4_DEEP_SLEEP; - - if (current_level == pm_level_to_set) - { - goto end_function; /* early out, no change in power level */ - } - - /* Cancel any timers */ - if (MALI_TRUE == idle_timer_running) - { - /* There is an existing timeout, so delete it */ - _mali_osk_timer_del(idle_timer); - idle_timer_running = MALI_FALSE; - } - - MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n")); - mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP); - next_level_dynamic = current_level; - } - else if (MALI_PM_SCHEME_ALWAYS_ON == current_scheme) - { - MALI_DEBUG_PRINT(4, ("Mali PM: Always on scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(MALI_PM_LEVEL_1_ON))); - - pm_level_to_set = MALI_PM_LEVEL_1_ON; - if (current_level == pm_level_to_set) - { - goto end_function; /* early out, no change in power level */ - } - - MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n")); - mali_pm_powerup(); - if (MALI_PM_LEVEL_2_STANDBY != current_level) - { - /* Wake up Mali cores since we came from a sleep state */ - mali_kernel_core_wakeup(); - } - } - else - { - MALI_PRINT_ERROR(("MALI PM: Illegal scheme")); - } - - current_level = pm_level_to_set; - -end_function: - _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW); - -} - -void mali_pm_always_on(mali_bool enable) -{ - if (MALI_TRUE == enable) - { - /* The event is processed in current thread synchronously */ - mali_pm_event(MALI_PM_EVENT_SCHEME_ALWAYS_ON, MALI_FALSE, 0 ); - } - else - { - /* The event is processed in current thread synchronously */ - mali_pm_event(MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL, MALI_FALSE, 0 ); - } -} - -static _mali_osk_errcode_t mali_pm_upper_half(void *data) -{ - /* not used */ - return _MALI_OSK_ERR_OK; -} - -static void mali_pm_bottom_half(void *data) -{ - mali_pm_process_next(); -} - -static u32 mali_pm_event_number_get(void) -{ - u32 retval; - - mali_pm_lock(); /* spinlock: mali_pm_lock_set_next_state */ - retval = ++mali_pm_event_number; - if (0==retval ) retval = ++mali_pm_event_number; - mali_pm_unlock(); - - return retval; -} - -static void mali_pm_event(enum mali_pm_event pm_event, mali_bool schedule_work, u32 timer_time ) -{ - mali_pm_lock(); /* spinlock: mali_pm_lock_set_next_state */ - /* Only timer events should set this variable, all other events must set it to zero. */ - if ( 0 != timer_time ) - { - MALI_DEBUG_ASSERT( (pm_event==MALI_PM_EVENT_TIMER_LIGHT_SLEEP) || (pm_event==MALI_PM_EVENT_TIMER_DEEP_SLEEP) ); - if ( mali_pm_event_number != timer_time ) - { - /* In this case there have been processed newer events since the timer event was set up. - If so we always ignore the timing event */ - mali_pm_unlock(); - return; - } - } - else - { - /* Delete possible ongoing timers - if ( (MALI_PM_LEVEL_2_STANDBY==current_level) || (MALI_PM_LEVEL_3_LIGHT_SLEEP==current_level) ) - { - _mali_osk_timer_del(idle_timer); - } - */ - } - mali_pm_event_number++; - switch (pm_event) - { - case MALI_PM_EVENT_CORES_WORKING: - next_level_dynamic = MALI_PM_LEVEL_1_ON; - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); - break; - case MALI_PM_EVENT_CORES_IDLE: - next_level_dynamic = MALI_PM_LEVEL_2_STANDBY; - /*MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme );*/ - break; - case MALI_PM_EVENT_TIMER_LIGHT_SLEEP: - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme ); - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); - next_level_dynamic = MALI_PM_LEVEL_3_LIGHT_SLEEP; - break; - case MALI_PM_EVENT_TIMER_DEEP_SLEEP: - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme ); - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); - next_level_dynamic = MALI_PM_LEVEL_4_DEEP_SLEEP; - break; - case MALI_PM_EVENT_OS_SUSPEND: - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme ); - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); - current_scheme = MALI_PM_SCHEME_OS_SUSPENDED; - next_level_dynamic = MALI_PM_LEVEL_4_DEEP_SLEEP; /* Dynamic scheme will go into level when we are resumed */ - break; - case MALI_PM_EVENT_OS_RESUME: - MALI_DEBUG_ASSERT(MALI_PM_SCHEME_OS_SUSPENDED == current_scheme ); - current_scheme = MALI_PM_SCHEME_DYNAMIC; - break; - case MALI_PM_EVENT_SCHEME_ALWAYS_ON: - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); - current_scheme = MALI_PM_SCHEME_ALWAYS_ON; - break; - case MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL: - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme ); - current_scheme = MALI_PM_SCHEME_DYNAMIC; - break; - default: - MALI_DEBUG_PRINT_ERROR(("Unknown next state.")); - mali_pm_unlock(); - return; - } - mali_pm_unlock(); - - if (MALI_TRUE == schedule_work) - { - _mali_osk_irq_schedulework(wq_irq); - } - else - { - mali_pm_process_next(); - } -} - -static void timeout_light_sleep(void* arg) -{ - /* State change only if no newer power events have happend from the time in arg. - Actual work will be scheduled on worker thread. */ - mali_pm_event(MALI_PM_EVENT_TIMER_LIGHT_SLEEP, MALI_TRUE, (u32) arg); -} - -void mali_pm_core_event(enum mali_core_event core_event) -{ - mali_bool transition_working = MALI_FALSE; - mali_bool transition_idle = MALI_FALSE; - - _mali_osk_lock_wait(mali_pm_lock_set_core_states, _MALI_OSK_LOCKMODE_RW); - - switch (core_event) - { - case MALI_CORE_EVENT_GP_START: - if (num_active_pps + num_active_gps == 0) - { - transition_working = MALI_TRUE; - } - num_active_gps++; - break; - case MALI_CORE_EVENT_GP_STOP: - if (num_active_pps + num_active_gps == 1) - { - transition_idle = MALI_TRUE; - } - num_active_gps--; - break; - case MALI_CORE_EVENT_PP_START: - if (num_active_pps + num_active_gps == 0) - { - transition_working = MALI_TRUE; - } - num_active_pps++; - break; - case MALI_CORE_EVENT_PP_STOP: - if (num_active_pps + num_active_gps == 1) - { - transition_idle = MALI_TRUE; - } - num_active_pps--; - break; - } - - if (transition_working == MALI_TRUE) - { -#ifdef CONFIG_MALI400_GPU_UTILIZATION - mali_utilization_core_start(_mali_osk_time_get_ns()); -#endif - mali_pm_event(MALI_PM_EVENT_CORES_WORKING, MALI_FALSE, 0); /* process event in same thread */ - } - else if (transition_idle == MALI_TRUE) - { -#ifdef CONFIG_MALI400_GPU_UTILIZATION - mali_utilization_core_end(_mali_osk_time_get_ns()); -#endif - mali_pm_event(MALI_PM_EVENT_CORES_IDLE, MALI_FALSE, 0); /* process event in same thread */ - } - - _mali_osk_lock_signal(mali_pm_lock_set_core_states, _MALI_OSK_LOCKMODE_RW); -} - -void mali_pm_os_suspend(void) -{ - MALI_DEBUG_PRINT(2, ("Mali PM: OS suspending...\n")); - - mali_gp_scheduler_suspend(); - mali_pp_scheduler_suspend(); - mali_pm_event(MALI_PM_EVENT_OS_SUSPEND, MALI_FALSE, 0); /* process event in same thread */ - - MALI_DEBUG_PRINT(2, ("Mali PM: OS suspend completed\n")); -} - -void mali_pm_os_resume(void) -{ - MALI_DEBUG_PRINT(2, ("Mali PM: OS resuming...\n")); - - mali_pm_event(MALI_PM_EVENT_OS_RESUME, MALI_FALSE, 0); /* process event in same thread */ - mali_gp_scheduler_resume(); - mali_pp_scheduler_resume(); - - MALI_DEBUG_PRINT(2, ("Mali PM: OS resume completed\n")); -} - -void mali_pm_runtime_suspend(void) -{ - MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime suspended\n")); - mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP); -} - -void mali_pm_runtime_resume(void) -{ - MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime resumed\n")); - mali_platform_power_mode_change(MALI_POWER_MODE_ON); -} diff --git a/drivers/media/video/samsung/mali/common/mali_pm.h b/drivers/media/video/samsung/mali/common/mali_pm.h deleted file mode 100644 index d4ccfde..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pm.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_PM_H__ -#define __MALI_PM_H__ - -#include "mali_osk.h" - -enum mali_core_event -{ - MALI_CORE_EVENT_GP_START, - MALI_CORE_EVENT_GP_STOP, - MALI_CORE_EVENT_PP_START, - MALI_CORE_EVENT_PP_STOP -}; - -enum mali_pm_event -{ - MALI_PM_EVENT_CORES_WORKING, - MALI_PM_EVENT_CORES_IDLE, - MALI_PM_EVENT_TIMER_LIGHT_SLEEP, - MALI_PM_EVENT_TIMER_DEEP_SLEEP, - MALI_PM_EVENT_OS_SUSPEND, - MALI_PM_EVENT_OS_RESUME, - MALI_PM_EVENT_SCHEME_ALWAYS_ON, - MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL, -}; - -_mali_osk_errcode_t mali_pm_initialize(void); -void mali_pm_terminate(void); -void mali_pm_always_on(mali_bool enable); - -void mali_pm_lock(void); -void mali_pm_unlock(void); -void mali_pm_execute_state_change_lock(void); - -void mali_pm_execute_state_change_unlock(void); - -mali_bool mali_pm_is_powered_on(void); - -void mali_pm_core_event(enum mali_core_event core_event); - -void mali_pm_os_suspend(void); -void mali_pm_os_resume(void); -void mali_pm_runtime_suspend(void); -void mali_pm_runtime_resume(void); - - -#endif /* __MALI_PM_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_pmu.c b/drivers/media/video/samsung/mali/common/mali_pmu.c deleted file mode 100644 index 348b5dc..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pmu.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_pmu.c - * Mali driver functions for Mali 400 PMU hardware - */ -#include "mali_hw_core.h" -#include "mali_pmu.h" -#include "mali_pp.h" -#include "mali_kernel_common.h" -#include "mali_osk.h" - -static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches); - -/** @brief MALI inbuilt PMU hardware info and PMU hardware has knowledge of cores power mask - */ -struct mali_pmu_core -{ - struct mali_hw_core hw_core; - u32 mali_registered_cores_power_mask; -}; - -static struct mali_pmu_core *mali_global_pmu_core = NULL; - -/** @brief Register layout for hardware PMU - */ -typedef enum { - PMU_REG_ADDR_MGMT_POWER_UP = 0x00, /*< Power up register */ - PMU_REG_ADDR_MGMT_POWER_DOWN = 0x04, /*< Power down register */ - PMU_REG_ADDR_MGMT_STATUS = 0x08, /*< Core sleep status register */ - PMU_REG_ADDR_MGMT_INT_MASK = 0x0C, /*< Interrupt mask register */ - PMU_REGISTER_ADDRESS_SPACE_SIZE = 0x10, /*< Size of register space */ -} pmu_reg_addr_mgmt_addr; - -struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches) -{ - struct mali_pmu_core* pmu; - - MALI_DEBUG_ASSERT(NULL == mali_global_pmu_core); - MALI_DEBUG_PRINT(2, ("Mali PMU: Creating Mali PMU core\n")); - - pmu = (struct mali_pmu_core *)_mali_osk_malloc(sizeof(struct mali_pmu_core)); - if (NULL != pmu) - { - pmu->mali_registered_cores_power_mask = mali_pmu_detect_mask(number_of_pp_cores, number_of_l2_caches); - if (_MALI_OSK_ERR_OK == mali_hw_core_create(&pmu->hw_core, resource, PMU_REGISTER_ADDRESS_SPACE_SIZE)) - { - if (_MALI_OSK_ERR_OK == mali_pmu_reset(pmu)) - { - mali_global_pmu_core = pmu; - return pmu; - } - mali_hw_core_delete(&pmu->hw_core); - } - _mali_osk_free(pmu); - } - - return NULL; -} - -void mali_pmu_delete(struct mali_pmu_core *pmu) -{ - MALI_DEBUG_ASSERT_POINTER(pmu); - - mali_hw_core_delete(&pmu->hw_core); - _mali_osk_free(pmu); - pmu = NULL; -} - -_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu) -{ - /* Don't use interrupts - just poll status */ - mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0); - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_pmu_powerdown_all(struct mali_pmu_core *pmu) -{ - u32 stat; - u32 timeout; - - MALI_DEBUG_ASSERT_POINTER(pmu); - MALI_DEBUG_ASSERT( pmu->mali_registered_cores_power_mask != 0 ); - MALI_DEBUG_PRINT( 4, ("Mali PMU: power down (0x%08X)\n", pmu->mali_registered_cores_power_mask) ); - - mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_DOWN, pmu->mali_registered_cores_power_mask); - - /* Wait for cores to be powered down (100 x 100us = 100ms) */ - timeout = 100; - do - { - /* Get status of sleeping cores */ - stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); - stat &= pmu->mali_registered_cores_power_mask; - if( stat == pmu->mali_registered_cores_power_mask ) break; /* All cores we wanted are now asleep */ - _mali_osk_time_ubusydelay(100); - timeout--; - } while( timeout > 0 ); - - if( timeout == 0 ) - { - return _MALI_OSK_ERR_TIMEOUT; - } - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_pmu_powerup_all(struct mali_pmu_core *pmu) -{ - u32 stat; - u32 timeout; - - MALI_DEBUG_ASSERT_POINTER(pmu); - MALI_DEBUG_ASSERT( pmu->mali_registered_cores_power_mask != 0 ); /* Shouldn't be zero */ - MALI_DEBUG_PRINT( 4, ("Mali PMU: power up (0x%08X)\n", pmu->mali_registered_cores_power_mask) ); - - mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_UP, pmu->mali_registered_cores_power_mask); - - /* Wait for cores to be powered up (100 x 100us = 100ms) */ - timeout = 100; - do - { - /* Get status of sleeping cores */ - stat = mali_hw_core_register_read(&pmu->hw_core,PMU_REG_ADDR_MGMT_STATUS); - stat &= pmu->mali_registered_cores_power_mask; - if( stat == 0 ) break; /* All cores we wanted are now awake */ - _mali_osk_time_ubusydelay(100); - timeout--; - } while( timeout > 0 ); - - if( timeout == 0 ) - { - return _MALI_OSK_ERR_TIMEOUT; - } - - return _MALI_OSK_ERR_OK; -} - -struct mali_pmu_core *mali_pmu_get_global_pmu_core(void) -{ - return mali_global_pmu_core; -} - -static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches) -{ - u32 mask = 0; - - if (number_of_l2_caches == 1) - { - /* Mali-300 or Mali-400 */ - u32 i; - - /* GP */ - mask = 0x01; - - /* L2 cache */ - mask |= 0x01<<1; - - /* Set bit for each PP core */ - for (i = 0; i < number_of_pp_cores; i++) - { - mask |= 0x01<<(i+2); - } - } - else if (number_of_l2_caches > 1) - { - /* Mali-450 */ - - /* GP (including its L2 cache) */ - mask = 0x01; - - /* There is always at least one PP (including its L2 cache) */ - mask |= 0x01<<1; - - /* Additional PP cores in same L2 cache */ - if (number_of_pp_cores >= 2) - { - mask |= 0x01<<2; - } - - /* Additional PP cores in a third L2 cache */ - if (number_of_pp_cores >= 5) - { - mask |= 0x01<<3; - } - } - - MALI_DEBUG_PRINT(4, ("Mali PMU: Power mask is 0x%08X (%u + %u)\n", mask, number_of_pp_cores, number_of_l2_caches)); - - return mask; -} diff --git a/drivers/media/video/samsung/mali/common/mali_pmu.h b/drivers/media/video/samsung/mali/common/mali_pmu.h deleted file mode 100644 index fd10c08..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pmu.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_platform.h - * Platform specific Mali driver functions - */ - -#include "mali_osk.h" - -struct mali_pmu_core; - -/** @brief Initialisation of MALI PMU - * - * This is called from entry point of the driver in order to create and intialize the PMU resource - * - * @param resource it will be a pointer to a PMU resource - * @param number_of_pp_cores Number of found PP resources in configuration - * @param number_of_l2_caches Number of found L2 cache resources in configuration - * @return The created PMU object, or NULL in case of failure. - */ -struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches); - -/** @brief It deallocates the PMU resource - * - * This is called on the exit of the driver to terminate the PMU resource - * - * @param pmu Pointer to PMU core object to delete - */ -void mali_pmu_delete(struct mali_pmu_core *pmu); - -/** @brief Reset PMU core - * - * @param pmu Pointer to PMU core object to reset - * @return _MALI_OSK_ERR_OK on success, otherwise failure. - */ -_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu); - -/** @brief MALI GPU power down using MALI in-built PMU - * - * called to power down all cores - * - * @param pmu Pointer to PMU core object to power down - * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. - */ -_mali_osk_errcode_t mali_pmu_powerdown_all(struct mali_pmu_core *pmu); - - -/** @brief MALI GPU power up using MALI in-built PMU - * - * called to power up all cores - * - * @param pmu Pointer to PMU core object to power up - * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. - */ -_mali_osk_errcode_t mali_pmu_powerup_all(struct mali_pmu_core *pmu); - - -/** @brief Retrieves the Mali PMU core object (if any) - * - * @return The Mali PMU object, or NULL if no PMU exists. - */ -struct mali_pmu_core *mali_pmu_get_global_pmu_core(void); diff --git a/drivers/media/video/samsung/mali/common/mali_pp.c b/drivers/media/video/samsung/mali/common/mali_pp.c deleted file mode 100644 index 5549f82..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_pp.h" -#include "mali_hw_core.h" -#include "mali_group.h" -#include "mali_osk.h" -#include "regs/mali_200_regs.h" -#include "mali_kernel_common.h" -#include "mali_kernel_core.h" -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_osk_profiling.h" -#endif - -/* See mali_gp.c file for description on how to handle the interrupt mask. - * This is how to do it on PP: mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); - */ - -#define MALI_MAX_NUMBER_OF_PP_CORES 8 - -/** - * Definition of the PP core struct - * Used to track a PP core in the system. - */ -struct mali_pp_core -{ - struct mali_hw_core hw_core; /**< Common for all HW cores */ - struct mali_group *group; /**< Parent group for this core */ - _mali_osk_irq_t *irq; /**< IRQ handler */ - u32 core_id; /**< Unique core ID */ - struct mali_pp_job *running_job; /**< Current running (super) job */ - u32 running_sub_job; /**< Current running sub job */ - _mali_osk_timer_t *timeout_timer; /**< timeout timer for this core */ - u32 timeout_job_id; /**< job id for the timed out job - relevant only if pp_core_timed_out == MALI_TRUE */ - mali_bool core_timed_out; /**< if MALI_TRUE, this pp core has timed out; if MALI_FALSE, no timeout on this pp core */ - u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ - u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ - u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */ - u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */ -}; - -static struct mali_pp_core* mali_global_pp_cores[MALI_MAX_NUMBER_OF_PP_CORES]; -static u32 mali_global_num_pp_cores = 0; - -/* Interrupt handlers */ -static _mali_osk_errcode_t mali_pp_upper_half(void *data); -static void mali_pp_bottom_half(void *data); -static void mali_pp_irq_probe_trigger(void *data); -static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data); -static void mali_pp_post_process_job(struct mali_pp_core *core); -static void mali_pp_timeout(void *data); - -struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group) -{ - struct mali_pp_core* core = NULL; - - MALI_DEBUG_PRINT(2, ("Mali PP: Creating Mali PP core: %s\n", resource->description)); - MALI_DEBUG_PRINT(2, ("Mali PP: Base address of PP core: 0x%x\n", resource->base)); - - if (mali_global_num_pp_cores >= MALI_MAX_NUMBER_OF_PP_CORES) - { - MALI_PRINT_ERROR(("Mali PP: Too many PP core objects created\n")); - return NULL; - } - - core = _mali_osk_malloc(sizeof(struct mali_pp_core)); - if (NULL != core) - { - core->group = group; - core->core_id = mali_global_num_pp_cores; - core->running_job = NULL; - core->counter_src0 = MALI_HW_CORE_NO_COUNTER; - core->counter_src1 = MALI_HW_CORE_NO_COUNTER; - core->counter_src0_used = MALI_HW_CORE_NO_COUNTER; - core->counter_src1_used = MALI_HW_CORE_NO_COUNTER; - if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI200_REG_SIZEOF_REGISTER_BANK)) - { - _mali_osk_errcode_t ret; - - mali_group_lock(group); - ret = mali_pp_reset(core); - mali_group_unlock(group); - - if (_MALI_OSK_ERR_OK == ret) - { - /* Setup IRQ handlers (which will do IRQ probing if needed) */ - core->irq = _mali_osk_irq_init(resource->irq, - mali_pp_upper_half, - mali_pp_bottom_half, - mali_pp_irq_probe_trigger, - mali_pp_irq_probe_ack, - core, - "mali_pp_irq_handlers"); - if (NULL != core->irq) - { - /* Initialise the timeout timer */ - core->timeout_timer = _mali_osk_timer_init(); - if(NULL != core->timeout_timer) - { - _mali_osk_timer_setcallback(core->timeout_timer, mali_pp_timeout, (void *)core); - - mali_global_pp_cores[mali_global_num_pp_cores] = core; - mali_global_num_pp_cores++; - - return core; - } - else - { - MALI_PRINT_ERROR(("Failed to setup timeout timer for PP core %s\n", core->hw_core.description)); - /* Release IRQ handlers */ - _mali_osk_irq_term(core->irq); - } - } - else - { - MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description)); - } - } - mali_hw_core_delete(&core->hw_core); - } - - _mali_osk_free(core); - } - else - { - MALI_PRINT_ERROR(("Mali PP: Failed to allocate memory for PP core\n")); - } - - return NULL; -} - -void mali_pp_delete(struct mali_pp_core *core) -{ - u32 i; - - MALI_DEBUG_ASSERT_POINTER(core); - - _mali_osk_timer_term(core->timeout_timer); - _mali_osk_irq_term(core->irq); - mali_hw_core_delete(&core->hw_core); - - /* Remove core from global list */ - for (i = 0; i < mali_global_num_pp_cores; i++) - { - if (mali_global_pp_cores[i] == core) - { - mali_global_pp_cores[i] = NULL; - mali_global_num_pp_cores--; - break; - } - } - - _mali_osk_free(core); -} - -void mali_pp_stop_bus(struct mali_pp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - /* Will only send the stop bus command, and not wait for it to complete */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS); -} - -_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core) -{ - int i; - const int request_loop_count = 20; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_ASSERT_GROUP_LOCKED(core->group); - - /* Send the stop bus command. */ - mali_pp_stop_bus(core); - - /* Wait for bus to be stopped */ - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED) - break; - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_PRINT_ERROR(("Mali PP: Failed to stop bus on %s. Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); - return _MALI_OSK_ERR_FAULT; - } - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core) -{ - /* Bus must be stopped before calling this function */ - const int reset_finished_loop_count = 15; - const u32 reset_invalid_value = 0xC0FFE000; - const u32 reset_check_value = 0xC01A0000; - int i; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_DEBUG_PRINT(2, ("Mali PP: Hard reset of core %s\n", core->hw_core.description)); - MALI_ASSERT_GROUP_LOCKED(core->group); - - mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */ - - /* Set register to a bogus value. The register will be used to detect when reset is complete */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value); - - /* Force core to reset */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET); - - /* Wait for reset to be complete */ - for (i = 0; i < reset_finished_loop_count; i++) - { - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_check_value); - if (reset_check_value == mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW)) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (i == reset_finished_loop_count) - { - MALI_PRINT_ERROR(("Mali PP: The hard reset loop didn't work, unable to recover\n")); - } - - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, 0x00000000); /* set it back to the default */ - /* Re-enable interrupts */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core) -{ - int i; - const int request_loop_count = 20; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description)); - MALI_ASSERT_GROUP_LOCKED(core->group); - - mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */ - - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ - -#if defined(USING_MALI200) - - /* On Mali-200, stop the bus, then do a hard reset of the core */ - - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS); - - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_PRINT_ERROR(("Mali PP: Failed to stop bus for core %s, unable to recover\n", core->hw_core.description)); - return _MALI_OSK_ERR_FAULT ; - } - - /* the bus was stopped OK, do the hard reset */ - mali_pp_hard_reset(core); - -#elif defined(USING_MALI400) - - /* Mali-300 and Mali-400 have a safe reset command which we use */ - - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI400PP_REG_VAL_IRQ_RESET_COMPLETED); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET); - - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400PP_REG_VAL_IRQ_RESET_COMPLETED) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_DEBUG_PRINT(2, ("Mali PP: Failed to reset core %s, Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); - return _MALI_OSK_ERR_FAULT; - } -#else -#error "no supported mali core defined" -#endif - - /* Re-enable interrupts */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); - - return _MALI_OSK_ERR_OK; -} - -void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job) -{ - u32 *frame_registers = mali_pp_job_get_frame_registers(job); - u32 *wb0_registers = mali_pp_job_get_wb0_registers(job); - u32 *wb1_registers = mali_pp_job_get_wb1_registers(job); - u32 *wb2_registers = mali_pp_job_get_wb2_registers(job); - core->counter_src0_used = core->counter_src0; - core->counter_src1_used = core->counter_src1; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_ASSERT_GROUP_LOCKED(core->group); - - mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, frame_registers, MALI200_NUM_REGS_FRAME); - if (0 != sub_job) - { - /* - * There are two frame registers which are different for each sub job. - * For the first sub job, these are correctly represented in the frame register array, - * but we need to patch these for all other sub jobs - */ - mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job)); - mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job)); - } - - if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ - { - mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, MALI200_NUM_REGS_WBx); - } - - if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ - { - mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, MALI200_NUM_REGS_WBx); - } - - if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ - { - mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, MALI200_NUM_REGS_WBx); - } - - /* This selects which performance counters we are reading */ - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) - { - /* global_config has enabled HW counters, this will override anything specified by user space */ - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) - { - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); - } - if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) - { - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); - } - } - else - { - /* Use HW counters from job object, if any */ - u32 perf_counter_flag = mali_pp_job_get_perf_counter_flag(job); - if (0 != perf_counter_flag) - { - if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) - { - core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); - } - - if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) - { - core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); - } - } - } - - MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description)); - - /* Adding barrier to make sure all rester writes are finished */ - _mali_osk_write_mem_barrier(); - - /* This is the command that starts the core. */ - mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING); - - /* Adding barrier to make sure previous rester writes is finished */ - _mali_osk_write_mem_barrier(); - - /* Setup the timeout timer value and save the job id for the job running on the pp core */ - _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); - core->timeout_job_id = mali_pp_job_get_id(job); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, job->frame_builder_id, job->flush_id, 0, 0, 0); - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), job->pid, job->tid, 0, 0, 0); -#endif - - core->running_job = job; - core->running_sub_job = sub_job; -} - -u32 mali_pp_core_get_version(struct mali_pp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION); -} - -u32 mali_pp_core_get_id(struct mali_pp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return core->core_id; -} - -mali_bool mali_pp_core_set_counter_src0(struct mali_pp_core *core, u32 counter) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - core->counter_src0 = counter; - return MALI_TRUE; -} - -mali_bool mali_pp_core_set_counter_src1(struct mali_pp_core *core, u32 counter) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - core->counter_src1 = counter; - return MALI_TRUE; -} - -u32 mali_pp_core_get_counter_src0(struct mali_pp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return core->counter_src0; -} - -u32 mali_pp_core_get_counter_src1(struct mali_pp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return core->counter_src1; -} - -struct mali_pp_core* mali_pp_get_global_pp_core(u32 index) -{ - if (MALI_MAX_NUMBER_OF_PP_CORES > index) - { - return mali_global_pp_cores[index]; - } - - return NULL; -} - -u32 mali_pp_get_glob_num_pp_cores(void) -{ - return mali_global_num_pp_cores; -} - -u32 mali_pp_get_max_num_pp_cores(void) -{ - return MALI_MAX_NUMBER_OF_PP_CORES; -} - -/* ------------- interrupt handling below ------------------ */ -static _mali_osk_errcode_t mali_pp_upper_half(void *data) -{ - struct mali_pp_core *core = (struct mali_pp_core *)data; - u32 irq_readout; - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); - if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout) - { - /* Mask out all IRQs from this core until IRQ is handled */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); -#endif - - /* We do need to handle this in a bottom half */ - _mali_osk_irq_schedulework(core->irq); - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -static void mali_pp_bottom_half(void *data) -{ - struct mali_pp_core *core = (struct mali_pp_core *)data; - u32 irq_readout; - u32 irq_errors; - -#if MALI_TIMELINE_PROFILING_ENABLED -#if 0 /* Bottom half TLP logging is currently not supported */ - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); -#endif -#endif - - mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */ - - if ( MALI_FALSE == mali_group_power_is_on(core->group) ) - { - MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description)); - mali_group_unlock(core->group); - return; - } - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED; - - MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description)); - - if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME) - { - mali_pp_post_process_job(core); - MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n")); - mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_COMPLETED); /* Will release group lock */ - return; - } - - /* - * Now lets look at the possible error cases (IRQ indicating error or timeout) - * END_OF_FRAME and HANG interrupts are not considered error. - */ - irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG); - if (0 != irq_errors) - { - mali_pp_post_process_job(core); - MALI_PRINT_ERROR(("Mali PP: Unknown interrupt 0x%08X from core %s, aborting job\n", - irq_readout, core->hw_core.description)); - mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_FAILED); /* Will release group lock */ - return; - } - else if (MALI_TRUE == core->core_timed_out) /* SW timeout */ - { - if (core->timeout_job_id == mali_pp_job_get_id(core->running_job)) - { - mali_pp_post_process_job(core); - MALI_DEBUG_PRINT(2, ("Mali PP: Job %d timed out on core %s\n", - mali_pp_job_get_id(core->running_job), core->hw_core.description)); - mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_TIMED_OUT); /* Will release group lock */ - } - else - { - mali_group_unlock(core->group); - } - core->core_timed_out = MALI_FALSE; - return; - } - else if (irq_readout & MALI200_REG_VAL_IRQ_HANG) - { - /* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_HANG); - } - - /* - * The only way to get here is if we got a HANG interrupt, which we ignore. - * Re-enable interrupts and let core continue to run - */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); - mali_group_unlock(core->group); - -#if MALI_TIMELINE_PROFILING_ENABLED -#if 0 /* Bottom half TLP logging is currently not supported */ - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); -#endif -#endif -} - -static void mali_pp_irq_probe_trigger(void *data) -{ - struct mali_pp_core *core = (struct mali_pp_core *)data; - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); /* @@@@ This should not be needed */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG); - _mali_osk_mem_barrier(); -} - -static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data) -{ - struct mali_pp_core *core = (struct mali_pp_core *)data; - u32 irq_readout; - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); - if (MALI200_REG_VAL_IRQ_FORCE_HANG & irq_readout) - { - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_FORCE_HANG); - _mali_osk_mem_barrier(); - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - - -/* ------ local helper functions below --------- */ -static void mali_pp_post_process_job(struct mali_pp_core *core) -{ - MALI_ASSERT_GROUP_LOCKED(core->group); - - if (NULL != core->running_job) - { - u32 val0 = 0; - u32 val1 = 0; -#if MALI_TIMELINE_PROFILING_ENABLED - int counter_index = COUNTER_FP0_C0 + (2 * core->core_id); -#endif - - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) - { - val0 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE); - if (mali_pp_job_get_perf_counter_flag(core->running_job) && - _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_pp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used) - { - /* We retrieved the counter that user space asked for, so return the value through the job object */ - mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, val0); - } - else - { - /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ - mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); - } - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_report_hw_counter(counter_index, val0); -#endif - } - - if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) - { - val1 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE); - if (mali_pp_job_get_perf_counter_flag(core->running_job) && - _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_pp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used) - { - /* We retrieved the counter that user space asked for, so return the value through the job object */ - mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, val1); - } - else - { - /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ - mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); - } - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_report_hw_counter(counter_index + 1, val1); -#endif - } - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), - val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0); -#endif - - /* We are no longer running a job... */ - core->running_job = NULL; - _mali_osk_timer_del(core->timeout_timer); - } -} - -/* callback function for pp core timeout */ -static void mali_pp_timeout(void *data) -{ - struct mali_pp_core * core = ((struct mali_pp_core *)data); - - MALI_DEBUG_PRINT(3, ("Mali PP: TIMEOUT callback \n")); - core->core_timed_out = MALI_TRUE; - _mali_osk_irq_schedulework(core->irq); -} - -#if 0 -static void mali_pp_print_registers(struct mali_pp_core *core) -{ - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_VERSION = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_MASK = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE))); -} -#endif - -#if 0 -void mali_pp_print_state(struct mali_pp_core *core) -{ - MALI_DEBUG_PRINT(2, ("Mali PP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) )); -} -#endif - -#if MALI_STATE_TRACKING -u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size) -{ - int n = 0; - - n += _mali_osk_snprintf(buf + n, size - n, "\tPP #%d: %s\n", core->core_id, core->hw_core.description); - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_pp.h b/drivers/media/video/samsung/mali/common/mali_pp.h deleted file mode 100644 index 9b425a0..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_PP_H__ -#define __MALI_PP_H__ - -#include "mali_osk.h" -#include "mali_pp_job.h" - -struct mali_pp_core; -struct mali_group; - -_mali_osk_errcode_t mali_pp_initialize(void); -void mali_pp_terminate(void); - -struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group); -void mali_pp_delete(struct mali_pp_core *core); - -void mali_pp_stop_bus(struct mali_pp_core *core); -_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core); -_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core); -_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core); - -void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job); - -u32 mali_pp_core_get_version(struct mali_pp_core *core); - -u32 mali_pp_core_get_id(struct mali_pp_core *core); - -mali_bool mali_pp_core_set_counter_src0(struct mali_pp_core *core, u32 counter); -mali_bool mali_pp_core_set_counter_src1(struct mali_pp_core *core, u32 counter); -u32 mali_pp_core_get_counter_src0(struct mali_pp_core *core); -u32 mali_pp_core_get_counter_src1(struct mali_pp_core *core); -struct mali_pp_core* mali_pp_get_global_pp_core(u32 index); -u32 mali_pp_get_glob_num_pp_cores(void); -u32 mali_pp_get_max_num_pp_cores(void); -/* Debug */ -u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size); - -#endif /* __MALI_PP_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_pp_job.c b/drivers/media/video/samsung/mali/common/mali_pp_job.c deleted file mode 100644 index 47b8a0a..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp_job.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_pp_job.h" -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_kernel_common.h" -#include "mali_uk_types.h" - -struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, u32 id) -{ - struct mali_pp_job *job; - - if (args->num_cores > _MALI_PP_MAX_SUB_JOBS) - { - MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n")); - return NULL; - } - - job = _mali_osk_malloc(sizeof(struct mali_pp_job)); - if (NULL != job) - { - u32 i; - _mali_osk_list_init(&job->list); - job->session = session; - job->id = id; - job->user_id = args->user_job_ptr; - job->barrier = args->flags & _MALI_PP_JOB_FLAG_BARRIER ? MALI_TRUE : MALI_FALSE; - job->active_barrier = job->barrier; - job->no_notification = args->flags & _MALI_PP_JOB_FLAG_NO_NOTIFICATION ? MALI_TRUE : MALI_FALSE; - _mali_osk_memcpy(job->frame_registers, args->frame_registers, sizeof(job->frame_registers)); - _mali_osk_memcpy(job->frame_registers_addr_frame, args->frame_registers_addr_frame, sizeof(job->frame_registers_addr_frame)); - _mali_osk_memcpy(job->frame_registers_addr_stack, args->frame_registers_addr_stack, sizeof(job->frame_registers_addr_stack)); - - /* Only copy write back registers for the units that are enabled */ - job->wb0_registers[0] = 0; - job->wb1_registers[0] = 0; - job->wb2_registers[0] = 0; - if (args->wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ - { - _mali_osk_memcpy(job->wb0_registers, args->wb0_registers, sizeof(job->wb0_registers)); - } - if (args->wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ - { - _mali_osk_memcpy(job->wb1_registers, args->wb1_registers, sizeof(job->wb1_registers)); - } - if (args->wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ - { - _mali_osk_memcpy(job->wb2_registers, args->wb2_registers, sizeof(job->wb2_registers)); - } - - job->perf_counter_flag = args->perf_counter_flag; - job->perf_counter_src0 = args->perf_counter_src0; - job->perf_counter_src1 = args->perf_counter_src1; - for (i = 0; i < args->num_cores; i++) - { - job->perf_counter_value0[i] = 0; - job->perf_counter_value1[i] = 0; - } - job->sub_job_count = args->num_cores; - job->sub_jobs_started = 0; - job->sub_jobs_completed = 0; - job->sub_job_errors = 0; - - job->pid = _mali_osk_get_pid(); - job->tid = _mali_osk_get_tid(); - job->frame_builder_id = args->frame_builder_id; - job->flush_id = args->flush_id; - - return job; - } - - return NULL; -} - -void mali_pp_job_delete(struct mali_pp_job *job) -{ - _mali_osk_free(job); -} - -_mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job) -{ - if ((0 == job->frame_registers[0]) || (0 == job->frame_registers[1])) - { - return _MALI_OSK_ERR_FAULT; - } - return _MALI_OSK_ERR_OK; -} diff --git a/drivers/media/video/samsung/mali/common/mali_pp_job.h b/drivers/media/video/samsung/mali/common/mali_pp_job.h deleted file mode 100644 index 4399c1d..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp_job.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_PP_JOB_H__ -#define __MALI_PP_JOB_H__ - -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_uk_types.h" -#include "mali_session.h" -#include "mali_kernel_common.h" -#include "regs/mali_200_regs.h" - -/** - * The structure represends a PP job, including all sub-jobs - * (This struct unfortunatly needs to be public because of how the _mali_osk_list_* - * mechanism works) - */ -struct mali_pp_job -{ - _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */ - struct mali_session_data *session; /**< Session which submitted this job */ - u32 id; /**< identifier for this job in kernel space (sequencial numbering) */ - u32 user_id; /**< identifier for the job in user space */ - u32 frame_registers[_MALI_PP_MAX_FRAME_REGISTERS]; /**< core specific registers associated with this job, see ARM DDI0415A */ - u32 frame_registers_addr_frame[_MALI_PP_MAX_SUB_JOBS - 1]; /**< ADDR_FRAME registers for sub job 1-7 */ - u32 frame_registers_addr_stack[_MALI_PP_MAX_SUB_JOBS - 1]; /**< ADDR_STACK registers for sub job 1-7 */ - u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 0 registers */ - u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 1 registers */ - u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 2 registers */ - u32 perf_counter_flag; /**< bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ - u32 perf_counter_src0; /**< Source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ - u32 perf_counter_src1; /**< Source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ - u32 perf_counter_value0[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 0 (to be returned to user space), one for each sub job */ - u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 1 (to be returned to user space), one for each sub job */ - u32 sub_job_count; /**< Total number of sub-jobs in this superjob */ - u32 sub_jobs_started; /**< Total number of sub-jobs started (always started in ascending order) */ - u32 sub_jobs_completed; /**< Number of completed sub-jobs in this superjob */ - u32 sub_job_errors; /**< Bitfield with errors (errors for each single sub-job is or'ed together) */ - u32 pid; /**< Process ID of submitting process */ - u32 tid; /**< Thread ID of submitting thread */ - u32 frame_builder_id; /**< id of the originating frame builder */ - u32 flush_id; /**< flush id within the originating frame builder */ - mali_bool barrier; /**< [in] MALI_TRUE means wait for all my previous jobs to complete before scheduling this one */ - mali_bool active_barrier; /**< [in] Changes from MALI_TRUE to MALI_FALSE when barrier has been resolved */ - mali_bool no_notification; /**< [in] MALI_TRUE means do not notify user space when this job has completed */ -}; - -struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, u32 id); -void mali_pp_job_delete(struct mali_pp_job *job); - -_mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job); - -/****************************************************** - * simple utility functions for dealing with pp jobs: - *****************************************************/ - -MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job) -{ - return (NULL == job) ? 0 : job->id; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_user_id(struct mali_pp_job *job) -{ - return job->user_id; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_frame_builder_id(struct mali_pp_job *job) -{ - return job->frame_builder_id; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_flush_id(struct mali_pp_job *job) -{ - return job->flush_id; -} - -MALI_STATIC_INLINE u32* mali_pp_job_get_frame_registers(struct mali_pp_job *job) -{ - return job->frame_registers; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 sub_job) -{ - if (sub_job == 0) - { - return job->frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)]; - } - else if (sub_job < _MALI_PP_MAX_SUB_JOBS) - { - return job->frame_registers_addr_frame[sub_job - 1]; - } - - return 0; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 sub_job) -{ - if (sub_job == 0) - { - return job->frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)]; - } - else if (sub_job < _MALI_PP_MAX_SUB_JOBS) - { - return job->frame_registers_addr_stack[sub_job - 1]; - } - - return 0; -} - -MALI_STATIC_INLINE u32* mali_pp_job_get_wb0_registers(struct mali_pp_job *job) -{ - return job->wb0_registers; -} - -MALI_STATIC_INLINE u32* mali_pp_job_get_wb1_registers(struct mali_pp_job *job) -{ - return job->wb1_registers; -} - -MALI_STATIC_INLINE u32* mali_pp_job_get_wb2_registers(struct mali_pp_job *job) -{ - return job->wb2_registers; -} - -MALI_STATIC_INLINE void mali_pp_job_disable_wb0(struct mali_pp_job *job) -{ - job->wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; -} - -MALI_STATIC_INLINE void mali_pp_job_disable_wb1(struct mali_pp_job *job) -{ - job->wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; -} - -MALI_STATIC_INLINE void mali_pp_job_disable_wb2(struct mali_pp_job *job) -{ - job->wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; -} - -MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali_pp_job *job) -{ - return job->session; -} - -MALI_STATIC_INLINE mali_bool mali_pp_job_has_unstarted_sub_jobs(struct mali_pp_job *job) -{ - return (job->sub_jobs_started < job->sub_job_count) ? MALI_TRUE : MALI_FALSE; -} - -/* Function used when we are terminating a session with jobs. Return TRUE if it has a rendering job. - Makes sure that no new subjobs is started. */ -MALI_STATIC_INLINE mali_bool mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(struct mali_pp_job *job) -{ - /* All can not be started, since then it would not be in the job queue */ - MALI_DEBUG_ASSERT( job->sub_jobs_started != job->sub_job_count ); - - /* If at least one job is started */ - if ( (job->sub_jobs_started > 0) ) - { - /* If at least one job is currently being rendered, and thus assigned to a group and core */ - if (job->sub_jobs_started > job->sub_jobs_completed ) - { - u32 jobs_remaining = job->sub_job_count - job->sub_jobs_started; - job->sub_jobs_started += jobs_remaining; - job->sub_jobs_completed += jobs_remaining; - job->sub_job_errors += jobs_remaining; - /* Returning TRUE indicating that we can not delete this job which is being redered */ - return MALI_TRUE; - } - } - /* The job is not being rendered to at the moment and can then safely be deleted */ - return MALI_FALSE; -} - -MALI_STATIC_INLINE mali_bool mali_pp_job_is_complete(struct mali_pp_job *job) -{ - return (job->sub_job_count == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_job *job) -{ - return job->sub_jobs_started; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_sub_job_count(struct mali_pp_job *job) -{ - return job->sub_job_count; -} - -MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job, u32 sub_job) -{ - /* Assert that we are marking the "first unstarted sub job" as started */ - MALI_DEBUG_ASSERT(job->sub_jobs_started == sub_job); - job->sub_jobs_started++; -} - -MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_completed(struct mali_pp_job *job, mali_bool success) -{ - job->sub_jobs_completed++; - if ( MALI_FALSE == success ) - { - job->sub_job_errors++; - } -} - -MALI_STATIC_INLINE mali_bool mali_pp_job_was_success(struct mali_pp_job *job) -{ - if ( 0 == job->sub_job_errors ) - { - return MALI_TRUE; - } - return MALI_FALSE; -} - -MALI_STATIC_INLINE mali_bool mali_pp_job_has_active_barrier(struct mali_pp_job *job) -{ - return job->active_barrier; -} - -MALI_STATIC_INLINE void mali_pp_job_barrier_enforced(struct mali_pp_job *job) -{ - job->active_barrier = MALI_FALSE; -} - -MALI_STATIC_INLINE mali_bool mali_pp_job_use_no_notification(struct mali_pp_job *job) -{ - return job->no_notification; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_flag(struct mali_pp_job *job) -{ - return job->perf_counter_flag; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src0(struct mali_pp_job *job) -{ - return job->perf_counter_src0; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src1(struct mali_pp_job *job) -{ - return job->perf_counter_src1; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value0(struct mali_pp_job *job, u32 sub_job) -{ - return job->perf_counter_value0[sub_job]; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value1(struct mali_pp_job *job, u32 sub_job) -{ - return job->perf_counter_value1[sub_job]; -} - -MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value0(struct mali_pp_job *job, u32 sub_job, u32 value) -{ - job->perf_counter_value0[sub_job] = value; -} - -MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value1(struct mali_pp_job *job, u32 sub_job, u32 value) -{ - job->perf_counter_value1[sub_job] = value; -} - -#endif /* __MALI_PP_JOB_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c deleted file mode 100644 index a944055..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_pp_scheduler.h" -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_scheduler.h" -#include "mali_pp.h" -#include "mali_pp_job.h" -#include "mali_group.h" -#include "mali_cluster.h" - -/* Maximum of 8 PP cores (a group can only have maximum of 1 PP core) */ -#define MALI_MAX_NUMBER_OF_PP_GROUPS 8 - -static mali_bool mali_pp_scheduler_is_suspended(void); - -enum mali_pp_slot_state -{ - MALI_PP_SLOT_STATE_IDLE, - MALI_PP_SLOT_STATE_WORKING, -}; - -/* A render slot is an entity which jobs can be scheduled onto */ -struct mali_pp_slot -{ - struct mali_group *group; - /* - * We keep track of the state here as well as in the group object - * so we don't need to take the group lock so often (and also avoid clutter with the working lock) - */ - enum mali_pp_slot_state state; - struct mali_session_data *session; -}; - -static u32 pp_version = 0; -static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */ -static struct mali_pp_slot slots[MALI_MAX_NUMBER_OF_PP_GROUPS]; -static u32 num_slots = 0; -static u32 num_slots_idle = 0; - -/* Variables to allow safe pausing of the scheduler */ -static _mali_osk_wait_queue_t *pp_scheduler_working_wait_queue = NULL; -static u32 pause_count = 0; - -static _mali_osk_lock_t *pp_scheduler_lock = NULL; -/* Contains tid of thread that locked the scheduler or 0, if not locked */ -MALI_DEBUG_CODE(static u32 pp_scheduler_lock_owner = 0); - -_mali_osk_errcode_t mali_pp_scheduler_initialize(void) -{ - u32 i; - - _MALI_OSK_INIT_LIST_HEAD(&job_queue); - - pp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); - if (NULL == pp_scheduler_lock) - { - return _MALI_OSK_ERR_NOMEM; - } - - pp_scheduler_working_wait_queue = _mali_osk_wait_queue_init(); - if (NULL == pp_scheduler_working_wait_queue) - { - _mali_osk_lock_term(pp_scheduler_lock); - return _MALI_OSK_ERR_NOMEM; - } - - /* Find all the available PP cores */ - for (i = 0; i < mali_cluster_get_glob_num_clusters(); i++) - { - u32 group_id = 0; - struct mali_cluster *curr_cluster = mali_cluster_get_global_cluster(i); - struct mali_group *group = mali_cluster_get_group(curr_cluster, group_id); - while (NULL != group) - { - struct mali_pp_core *pp_core = mali_group_get_pp_core(group); - if (NULL != pp_core) - { - if (0 == pp_version) - { - /* Retrieve PP version from first avaiable PP core */ - pp_version = mali_pp_core_get_version(pp_core); - } - slots[num_slots].group = group; - slots[num_slots].state = MALI_PP_SLOT_STATE_IDLE; - slots[num_slots].session = NULL; - num_slots++; - num_slots_idle++; - } - group_id++; - group = mali_cluster_get_group(curr_cluster, group_id); - } - } - - return _MALI_OSK_ERR_OK; -} - -void mali_pp_scheduler_terminate(void) -{ - _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); - _mali_osk_lock_term(pp_scheduler_lock); -} - -MALI_STATIC_INLINE void mali_pp_scheduler_lock(void) -{ - if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW)) - { - /* Non-interruptable lock failed: this should never happen. */ - MALI_DEBUG_ASSERT(0); - } - MALI_DEBUG_PRINT(5, ("Mali PP scheduler: PP scheduler lock taken\n")); - MALI_DEBUG_ASSERT(0 == pp_scheduler_lock_owner); - MALI_DEBUG_CODE(pp_scheduler_lock_owner = _mali_osk_get_tid()); -} - -MALI_STATIC_INLINE void mali_pp_scheduler_unlock(void) -{ - MALI_DEBUG_PRINT(5, ("Mali PP scheduler: Releasing PP scheduler lock\n")); - MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner); - MALI_DEBUG_CODE(pp_scheduler_lock_owner = 0); - _mali_osk_lock_signal(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW); -} - -#ifdef DEBUG -MALI_STATIC_INLINE void mali_pp_scheduler_assert_locked(void) -{ - MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner); -} -#define MALI_ASSERT_PP_SCHEDULER_LOCKED() mali_pp_scheduler_assert_locked() -#else -#define MALI_ASSERT_PP_SCHEDULER_LOCKED() -#endif - -static mali_bool mali_pp_scheduler_session_has_running_jobs(struct mali_session_data *session) -{ - u32 i; - - MALI_ASSERT_PP_SCHEDULER_LOCKED(); - - if (num_slots_idle == num_slots) - { - return MALI_FALSE; - } - - for (i = 0; i < num_slots; i++) - { - if (MALI_PP_SLOT_STATE_WORKING == slots[i].state) - { - if (slots[i].session == session) - { - return MALI_TRUE; - } - } - } - - return MALI_FALSE; -} - -static void mali_pp_scheduler_schedule(void) -{ - u32 i; - struct mali_pp_job *job; -#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS - struct mali_session_data * session; -#endif - - MALI_ASSERT_PP_SCHEDULER_LOCKED(); - - if (0 < pause_count || 0 == num_slots_idle || _mali_osk_list_empty(&job_queue)) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", - pause_count, num_slots_idle)); - return; /* Nothing to do, so early out */ - } - - -#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP - if ( num_slots_idle < num_slots ) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started, since only %d/%d cores are available\n", num_slots_idle,num_slots)); - return; - } -#endif - -#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS - /* Finding initial session for the PP cores */ - job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); - session = job->session; - if ( num_slots != num_slots_idle ) - { - for (i = 0; (i < num_slots) ; i++) - { - if ( slots[i].state == MALI_PP_SLOT_STATE_IDLE ) - { - continue; - } - session = mali_group_get_session(slots[i].group); - break; - } - } -#endif - - for (i = 0; (i < num_slots) && (0 < num_slots_idle); i++) - { - u32 sub_job; - - if (_mali_osk_list_empty(&job_queue)) /* move this check down to where we know we have started all sub jobs for this job??? */ - { - break; /* No more jobs to schedule, so early out */ - } - - if (MALI_PP_SLOT_STATE_IDLE != slots[i].state) - { - continue; - } - - job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); - MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); /* All jobs on the job_queue should have unstarted sub jobs */ - - if (MALI_TRUE == mali_pp_job_has_active_barrier(job)) - { - if (MALI_TRUE == mali_pp_scheduler_session_has_running_jobs(mali_pp_job_get_session(job))) - { - /* There is already a running job from this session, so we need to enforce the barrier */ - return; - } - else - { - /* Barrier is now enforced, update job object so we don't delay execution of sub-jobs */ - mali_pp_job_barrier_enforced(job); - } - } - - #if MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED - if ( (0==job->sub_jobs_started) && (num_slots_idle < num_slots) && (job->sub_job_count > num_slots_idle)) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job with %d subjobs not started, since only %d/%d cores are available\n", job->sub_job_count, num_slots_idle,num_slots)); - return; - } - #endif - - #if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS - if ( job->session != session ) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started since existing job is from another application\n")); - return; - } - #endif - - sub_job = mali_pp_job_get_first_unstarted_sub_job(job); - - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Starting job %u (0x%08X) part %u/%u\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job))); - if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(slots[i].group, job, sub_job)) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u started\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job))); - - /* Mark this sub job as started */ - mali_pp_job_mark_sub_job_started(job, sub_job); - - /* Mark slot as busy */ - slots[i].state = MALI_PP_SLOT_STATE_WORKING; - slots[i].session = mali_pp_job_get_session(job); - num_slots_idle--; - - if (!mali_pp_job_has_unstarted_sub_jobs(job)) - { - /* - * All sub jobs have now started for this job, remove this job from the job queue. - * The job will now only be referred to by the slots which are running it. - * The last slot to complete will make sure it is returned to user space. - */ - _mali_osk_list_del(&job->list); -#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP - MALI_DEBUG_PRINT(6, ("Mali PP scheduler: Skip scheduling more jobs when MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP is set.\n")); - return; -#endif - } - } - else - { - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Failed to start PP job\n")); - return; - } - } -} - -static void mali_pp_scheduler_return_job_to_user(struct mali_pp_job *job) -{ - if (MALI_FALSE == mali_pp_job_use_no_notification(job)) - { - _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s)); - if (NULL != notobj) - { - u32 i; - u32 sub_jobs = mali_pp_job_get_sub_job_count(job); - mali_bool success = mali_pp_job_was_success(job); - - _mali_uk_pp_job_finished_s *jobres = notobj->result_buffer; - _mali_osk_memset(jobres, 0, sizeof(_mali_uk_pp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ - jobres->user_job_ptr = mali_pp_job_get_user_id(job); - if (MALI_TRUE == success) - { - jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; - } - else - { - jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; - } - - for (i = 0; i < sub_jobs; i++) - { - jobres->perf_counter0[i] = mali_pp_job_get_perf_counter_value0(job, i); - jobres->perf_counter1[i] = mali_pp_job_get_perf_counter_value1(job, i); - } - - mali_session_send_notification(mali_pp_job_get_session(job), notobj); - } - else - { - MALI_PRINT_ERROR(("Mali PP scheduler: Unable to allocate notification object\n")); - } - } - - mali_pp_job_delete(job); -} - -void mali_pp_scheduler_do_schedule(void) -{ - mali_pp_scheduler_lock(); - - mali_pp_scheduler_schedule(); - - mali_pp_scheduler_unlock(); -} - -void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success) -{ - u32 i; - mali_bool job_is_done; - - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u completed (%s)\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job), success ? "success" : "failure")); - - mali_pp_scheduler_lock(); - - /* Find slot which was running this job */ - for (i = 0; i < num_slots; i++) - { - if (slots[i].group == group) - { - MALI_DEBUG_ASSERT(MALI_PP_SLOT_STATE_WORKING == slots[i].state); - slots[i].state = MALI_PP_SLOT_STATE_IDLE; - slots[i].session = NULL; - num_slots_idle++; - mali_pp_job_mark_sub_job_completed(job, success); - } - } - - /* If paused, then this was the last job, so wake up sleeping workers */ - if (pause_count > 0) - { - /* Wake up sleeping workers. Their wake-up condition is that - * num_slots == num_slots_idle, so unless we are done working, no - * threads will actually be woken up. - */ - _mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue); - } - else - { - mali_pp_scheduler_schedule(); - } - - job_is_done = mali_pp_job_is_complete(job); - - mali_pp_scheduler_unlock(); - - if (job_is_done) - { - /* Send notification back to user space */ - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for job %u (0x%08X)\n", mali_pp_job_get_id(job), job)); - mali_pp_scheduler_return_job_to_user(job); - } -} - -void mali_pp_scheduler_suspend(void) -{ - mali_pp_scheduler_lock(); - pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ - mali_pp_scheduler_unlock(); - - /*mali_pp_scheduler_working_lock();*/ - /* We have now aquired the working lock, which means that we have successfully paused the scheduler */ - /*mali_pp_scheduler_working_unlock();*/ - - /* go to sleep. When woken up again (in mali_pp_scheduler_job_done), the - * mali_pp_scheduler_suspended() function will be called. This will return true - * iff state is idle and pause_count > 0, so if the core is active this - * will not do anything. - */ - _mali_osk_wait_queue_wait_event(pp_scheduler_working_wait_queue, mali_pp_scheduler_is_suspended); -} - -void mali_pp_scheduler_resume(void) -{ - mali_pp_scheduler_lock(); - pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */ - if (0 == pause_count) - { - mali_pp_scheduler_schedule(); - } - mali_pp_scheduler_unlock(); -} - -_mali_osk_errcode_t _mali_ukk_pp_start_job(_mali_uk_pp_start_job_s *args) -{ - struct mali_session_data *session; - struct mali_pp_job *job; - - MALI_DEBUG_ASSERT_POINTER(args); - MALI_DEBUG_ASSERT_POINTER(args->ctx); - - session = (struct mali_session_data*)args->ctx; - - job = mali_pp_job_create(session, args, mali_scheduler_get_new_id()); - if (NULL == job) - { - return _MALI_OSK_ERR_NOMEM; - } - - if (_MALI_OSK_ERR_OK != mali_pp_job_check(job)) - { - /* Not a valid job, return to user immediately */ - mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ - mali_pp_scheduler_return_job_to_user(job); /* This will also delete the job object */ - return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ - } - -#if PROFILING_SKIP_PP_JOBS || PROFILING_SKIP_PP_AND_GP_JOBS -#warning PP jobs will not be executed - mali_pp_scheduler_return_job_to_user(job); - return _MALI_OSK_ERR_OK; -#endif - - mali_pp_scheduler_lock(); - - _mali_osk_list_addtail(&job->list, &job_queue); - - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) with %u parts queued\n", mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job))); - - mali_pp_scheduler_schedule(); - - mali_pp_scheduler_unlock(); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores(_mali_uk_get_pp_number_of_cores_s *args) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_DEBUG_ASSERT_POINTER(args->ctx); - args->number_of_cores = num_slots; - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_get_pp_core_version(_mali_uk_get_pp_core_version_s *args) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_DEBUG_ASSERT_POINTER(args->ctx); - args->version = pp_version; - return _MALI_OSK_ERR_OK; -} - -void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args) -{ - struct mali_session_data *session; - struct mali_pp_job *job; - struct mali_pp_job *tmp; - - MALI_DEBUG_ASSERT_POINTER(args); - MALI_DEBUG_ASSERT_POINTER(args->ctx); - - session = (struct mali_session_data*)args->ctx; - - mali_pp_scheduler_lock(); - - /* Check queue for jobs that match */ - _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list) - { - if (mali_pp_job_get_session(job) == session && - mali_pp_job_get_frame_builder_id(job) == (u32)args->fb_id && - mali_pp_job_get_flush_id(job) == (u32)args->flush_id) - { - if (args->wbx & _MALI_UK_PP_JOB_WB0) - { - mali_pp_job_disable_wb0(job); - } - if (args->wbx & _MALI_UK_PP_JOB_WB1) - { - mali_pp_job_disable_wb1(job); - } - if (args->wbx & _MALI_UK_PP_JOB_WB2) - { - mali_pp_job_disable_wb2(job); - } - break; - } - } - - mali_pp_scheduler_unlock(); -} - -void mali_pp_scheduler_abort_session(struct mali_session_data *session) -{ - struct mali_pp_job *job, *tmp; - int i; - - mali_pp_scheduler_lock(); - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Aborting all jobs from session 0x%08x\n", session)); - - /* Check queue for jobs and remove */ - _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list) - { - if (mali_pp_job_get_session(job) == session) - { - _mali_osk_list_del(&(job->list)); - - if ( mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(job) ) - { - /* The job is in the render pipeline, we can not delete it yet. */ - /* It will be deleted in the mali_group_abort_session() call below */ - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Keeping partially started PP job 0x%08x in queue\n", job)); - continue; - } - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Removing PP job 0x%08x from queue\n", job)); - mali_pp_job_delete(job); - } - } - - mali_pp_scheduler_unlock(); - - /* Abort running jobs from this session */ - for (i = 0; i < num_slots; i++) - { - struct mali_group *group = slots[i].group; - - MALI_DEBUG_PRINT(5, ("PP sched abort: Looking at group 0x%08x\n", group)); - - if (MALI_PP_SLOT_STATE_WORKING == slots[i].state) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Aborting session 0x%08x from group 0x%08x\n", session, group)); - - mali_group_abort_session(group, session); - } - } -} - -static mali_bool mali_pp_scheduler_is_suspended(void) -{ - mali_bool ret; - - mali_pp_scheduler_lock(); - ret = pause_count > 0 && num_slots == num_slots_idle; - mali_pp_scheduler_unlock(); - - return ret; -} - -#if MALI_STATE_TRACKING -u32 mali_pp_scheduler_dump_state(char *buf, u32 size) -{ - int n = 0; - int i; - - n += _mali_osk_snprintf(buf + n, size - n, "PP:\n"); - n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty"); - n += _mali_osk_snprintf(buf + n, size - n, "\n"); - - for (i = 0; i < num_slots; i++) - { - n += mali_group_dump_state(slots[i].group, buf + n, size - n); - n += _mali_osk_snprintf(buf + n, size - n, "\t\tState: %d\n", slots[i].state); - } - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h deleted file mode 100644 index 48eb3bd..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_PP_SCHEDULER_H__ -#define __MALI_PP_SCHEDULER_H__ - -#include "mali_osk.h" -#include "mali_cluster.h" -#include "mali_pp_job.h" - -_mali_osk_errcode_t mali_pp_scheduler_initialize(void); -void mali_pp_scheduler_terminate(void); - -void mali_pp_scheduler_do_schedule(void); -void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success); - -void mali_pp_scheduler_suspend(void); -void mali_pp_scheduler_resume(void); - -/** @brief Abort all PP jobs from session running or queued - * - * This functions aborts all PP jobs from the specified session. Queued jobs are removed from the queue and jobs - * currently running on a core will be aborted. - * - * @param session Pointer to session whose jobs should be aborted - */ -void mali_pp_scheduler_abort_session(struct mali_session_data *session); - -u32 mali_pp_scheduler_dump_state(char *buf, u32 size); - -#endif /* __MALI_PP_SCHEDULER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_scheduler.c b/drivers/media/video/samsung/mali/common/mali_scheduler.c deleted file mode 100644 index f360209..0000000 --- a/drivers/media/video/samsung/mali/common/mali_scheduler.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" - -static _mali_osk_atomic_t mali_job_autonumber; - -_mali_osk_errcode_t mali_scheduler_initialize(void) -{ - if ( _MALI_OSK_ERR_OK != _mali_osk_atomic_init(&mali_job_autonumber, 0)) - { - MALI_DEBUG_PRINT(1, ("Initialization of atomic job id counter failed.\n")); - return _MALI_OSK_ERR_FAULT; - } - - return _MALI_OSK_ERR_OK; -} - -void mali_scheduler_terminate(void) -{ - _mali_osk_atomic_term(&mali_job_autonumber); -} - -u32 mali_scheduler_get_new_id(void) -{ - u32 job_id = _mali_osk_atomic_inc_return(&mali_job_autonumber); - return job_id; -} - diff --git a/drivers/media/video/samsung/mali/common/mali_scheduler.h b/drivers/media/video/samsung/mali/common/mali_scheduler.h deleted file mode 100644 index 74f0947..0000000 --- a/drivers/media/video/samsung/mali/common/mali_scheduler.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_SCHEDULER_H__ -#define __MALI_SCHEDULER_H__ - -#include "mali_osk.h" - -_mali_osk_errcode_t mali_scheduler_initialize(void); -void mali_scheduler_terminate(void); - -u32 mali_scheduler_get_new_id(void); - -#endif /* __MALI_SCHEDULER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_session.c b/drivers/media/video/samsung/mali/common/mali_session.c deleted file mode 100644 index 2394bb9..0000000 --- a/drivers/media/video/samsung/mali/common/mali_session.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_session.h" - -_MALI_OSK_LIST_HEAD(mali_sessions); - -_mali_osk_lock_t *mali_sessions_lock; - -_mali_osk_errcode_t mali_session_initialize(void) -{ - _MALI_OSK_INIT_LIST_HEAD(&mali_sessions); - - mali_sessions_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_SESSIONS); - - if (NULL == mali_sessions_lock) return _MALI_OSK_ERR_NOMEM; - - return _MALI_OSK_ERR_OK; -} - -void mali_session_terminate(void) -{ - _mali_osk_lock_term(mali_sessions_lock); -} - -void mali_session_add(struct mali_session_data *session) -{ - mali_session_lock(); - _mali_osk_list_add(&session->link, &mali_sessions); - mali_session_unlock(); -} - -void mali_session_remove(struct mali_session_data *session) -{ - mali_session_lock(); - _mali_osk_list_delinit(&session->link); - mali_session_unlock(); -} diff --git a/drivers/media/video/samsung/mali/common/mali_session.h b/drivers/media/video/samsung/mali/common/mali_session.h deleted file mode 100644 index c8640b5..0000000 --- a/drivers/media/video/samsung/mali/common/mali_session.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_SESSION_H__ -#define __MALI_SESSION_H__ - -#include "mali_mmu_page_directory.h" -#include "mali_kernel_descriptor_mapping.h" -#include "mali_osk.h" -#include "mali_osk_list.h" - -struct mali_session_data -{ - _mali_osk_notification_queue_t * ioctl_queue; - - _mali_osk_lock_t *memory_lock; /**< Lock protecting the vm manipulation */ - mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */ - _mali_osk_list_t memory_head; /**< Track all the memory allocated in this session, for freeing on abnormal termination */ - - struct mali_page_directory *page_directory; /**< MMU page directory for this session */ - - _MALI_OSK_LIST_HEAD(link); /**< Link for list of all sessions */ -}; - -_mali_osk_errcode_t mali_session_initialize(void); -void mali_session_terminate(void); - -/* List of all sessions. Actual list head in mali_kernel_core.c */ -extern _mali_osk_list_t mali_sessions; -/* Lock to protect modification and access to the mali_sessions list */ -extern _mali_osk_lock_t *mali_sessions_lock; - -MALI_STATIC_INLINE void mali_session_lock(void) -{ - _mali_osk_lock_wait(mali_sessions_lock, _MALI_OSK_LOCKMODE_RW); -} - -MALI_STATIC_INLINE void mali_session_unlock(void) -{ - _mali_osk_lock_signal(mali_sessions_lock, _MALI_OSK_LOCKMODE_RW); -} - -void mali_session_add(struct mali_session_data *session); -void mali_session_remove(struct mali_session_data *session); -#define MALI_SESSION_FOREACH(session, tmp, link) \ - _MALI_OSK_LIST_FOREACHENTRY(session, tmp, &mali_sessions, struct mali_session_data, link) - -MALI_STATIC_INLINE struct mali_page_directory *mali_session_get_page_directory(struct mali_session_data *session) -{ - return session->page_directory; -} - -MALI_STATIC_INLINE void mali_session_send_notification(struct mali_session_data *session, _mali_osk_notification_t *object) -{ - _mali_osk_notification_queue_send(session->ioctl_queue, object); -} - -#endif /* __MALI_SESSION_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_ukk.h b/drivers/media/video/samsung/mali/common/mali_ukk.h deleted file mode 100644 index 6b018d0..0000000 --- a/drivers/media/video/samsung/mali/common/mali_ukk.h +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_ukk.h - * Defines the kernel-side interface of the user-kernel interface - */ - -#ifndef __MALI_UKK_H__ -#define __MALI_UKK_H__ - -#include "mali_osk.h" -#include "mali_uk_types.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * @addtogroup uddapi Unified Device Driver (UDD) APIs - * - * @{ - */ - -/** - * @addtogroup u_k_api UDD User/Kernel Interface (U/K) APIs - * - * - The _mali_uk functions are an abstraction of the interface to the device - * driver. On certain OSs, this would be implemented via the IOCTL interface. - * On other OSs, it could be via extension of some Device Driver Class, or - * direct function call for Bare metal/RTOSs. - * - It is important to note that: - * - The Device Driver has implemented the _mali_ukk set of functions - * - The Base Driver calls the corresponding set of _mali_uku functions. - * - What requires porting is solely the calling mechanism from User-side to - * Kernel-side, and propagating back the results. - * - Each U/K function is associated with a (group, number) pair from - * \ref _mali_uk_functions to make it possible for a common function in the - * Base Driver and Device Driver to route User/Kernel calls from/to the - * correct _mali_uk function. For example, in an IOCTL system, the IOCTL number - * would be formed based on the group and number assigned to the _mali_uk - * function, as listed in \ref _mali_uk_functions. On the user-side, each - * _mali_uku function would just make an IOCTL with the IOCTL-code being an - * encoded form of the (group, number) pair. On the kernel-side, the Device - * Driver's IOCTL handler decodes the IOCTL-code back into a (group, number) - * pair, and uses this to determine which corresponding _mali_ukk should be - * called. - * - Refer to \ref _mali_uk_functions for more information about this - * (group, number) pairing. - * - In a system where there is no distinction between user and kernel-side, - * the U/K interface may be implemented as:@code - * MALI_STATIC_INLINE _mali_osk_errcode_t _mali_uku_examplefunction( _mali_uk_examplefunction_s *args ) - * { - * return mali_ukk_examplefunction( args ); - * } - * @endcode - * - Therefore, all U/K calls behave \em as \em though they were direct - * function calls (but the \b implementation \em need \em not be a direct - * function calls) - * - * @note Naming the _mali_uk functions the same on both User and Kernel sides - * on non-RTOS systems causes debugging issues when setting breakpoints. In - * this case, it is not clear which function the breakpoint is put on. - * Therefore the _mali_uk functions in user space are prefixed with \c _mali_uku - * and in kernel space with \c _mali_ukk. The naming for the argument - * structures is unaffected. - * - * - The _mali_uk functions are synchronous. - * - Arguments to the _mali_uk functions are passed in a structure. The only - * parameter passed to the _mali_uk functions is a pointer to this structure. - * This first member of this structure, ctx, is a pointer to a context returned - * by _mali_uku_open(). For example:@code - * typedef struct - * { - * void *ctx; - * u32 number_of_cores; - * } _mali_uk_get_gp_number_of_cores_s; - * @endcode - * - * - Each _mali_uk function has its own argument structure named after the - * function. The argument is distinguished by the _s suffix. - * - The argument types are defined by the base driver and user-kernel - * interface. - * - All _mali_uk functions return a standard \ref _mali_osk_errcode_t. - * - Only arguments of type input or input/output need be initialized before - * calling a _mali_uk function. - * - Arguments of type output and input/output are only valid when the - * _mali_uk function returns \ref _MALI_OSK_ERR_OK. - * - The \c ctx member is always invalid after it has been used by a - * _mali_uk function, except for the context management functions - * - * - * \b Interface \b restrictions - * - * The requirements of the interface mean that an implementation of the - * User-kernel interface may do no 'real' work. For example, the following are - * illegal in the User-kernel implementation: - * - Calling functions necessary for operation on all systems, which would - * not otherwise get called on RTOS systems. - * - For example, a U/K interface that calls multiple _mali_ukk functions - * during one particular U/K call. This could not be achieved by the same code - * which uses direct function calls for the U/K interface. - * - Writing in values to the args members, when otherwise these members would - * not hold a useful value for a direct function call U/K interface. - * - For example, U/K interface implementation that take NULL members in - * their arguments structure from the user side, but those members are - * replaced with non-NULL values in the kernel-side of the U/K interface - * implementation. A scratch area for writing data is one such example. In this - * case, a direct function call U/K interface would segfault, because no code - * would be present to replace the NULL pointer with a meaningful pointer. - * - Note that we discourage the case where the U/K implementation changes - * a NULL argument member to non-NULL, and then the Device Driver code (outside - * of the U/K layer) re-checks this member for NULL, and corrects it when - * necessary. Whilst such code works even on direct function call U/K - * intefaces, it reduces the testing coverage of the Device Driver code. This - * is because we have no way of testing the NULL == value path on an OS - * implementation. - * - * A number of allowable examples exist where U/K interfaces do 'real' work: - * - The 'pointer switching' technique for \ref _mali_ukk_get_system_info - * - In this case, without the pointer switching on direct function call - * U/K interface, the Device Driver code still sees the same thing: a pointer - * to which it can write memory. This is because such a system has no - * distinction between a user and kernel pointer. - * - Writing an OS-specific value into the ukk_private member for - * _mali_ukk_mem_mmap(). - * - In this case, this value is passed around by Device Driver code, but - * its actual value is never checked. Device Driver code simply passes it from - * the U/K layer to the OSK layer, where it can be acted upon. In this case, - * \em some OS implementations of the U/K (_mali_ukk_mem_mmap()) and OSK - * (_mali_osk_mem_mapregion_init()) functions will collaborate on the - * meaning of ukk_private member. On other OSs, it may be unused by both - * U/K and OSK layers - * - Therefore, on error inside the U/K interface implementation itself, - * it will be as though the _mali_ukk function itself had failed, and cleaned - * up after itself. - * - Compare this to a direct function call U/K implementation, where all - * error cleanup is handled by the _mali_ukk function itself. The direct - * function call U/K interface implementation is automatically atomic. - * - * The last example highlights a consequence of all U/K interface - * implementations: they must be atomic with respect to the Device Driver code. - * And therefore, should Device Driver code succeed but the U/K implementation - * fail afterwards (but before return to user-space), then the U/K - * implementation must cause appropriate cleanup actions to preserve the - * atomicity of the interface. - * - * @{ - */ - - -/** @defgroup _mali_uk_context U/K Context management - * - * These functions allow for initialisation of the user-kernel interface once per process. - * - * Generally the context will store the OS specific object to communicate with the kernel device driver and further - * state information required by the specific implementation. The context is shareable among all threads in the caller process. - * - * On IOCTL systems, this is likely to be a file descriptor as a result of opening the kernel device driver. - * - * On a bare-metal/RTOS system with no distinction between kernel and - * user-space, the U/K interface simply calls the _mali_ukk variant of the - * function by direct function call. In this case, the context returned is the - * mali_session_data from _mali_ukk_open(). - * - * The kernel side implementations of the U/K interface expect the first member of the argument structure to - * be the context created by _mali_uku_open(). On some OS implementations, the meaning of this context - * will be different between user-side and kernel-side. In which case, the kernel-side will need to replace this context - * with the kernel-side equivalent, because user-side will not have access to kernel-side data. The context parameter - * in the argument structure therefore has to be of type input/output. - * - * It should be noted that the caller cannot reuse the \c ctx member of U/K - * argument structure after a U/K call, because it may be overwritten. Instead, - * the context handle must always be stored elsewhere, and copied into - * the appropriate U/K argument structure for each user-side call to - * the U/K interface. This is not usually a problem, since U/K argument - * structures are usually placed on the stack. - * - * @{ */ - -/** @brief Begin a new Mali Device Driver session - * - * This is used to obtain a per-process context handle for all future U/K calls. - * - * @param context pointer to storage to return a (void*)context handle. - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_open( void **context ); - -/** @brief End a Mali Device Driver session - * - * This should be called when the process no longer requires use of the Mali Device Driver. - * - * The context handle must not be used after it has been closed. - * - * @param context pointer to a stored (void*)context handle. - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_close( void **context ); - -/** @} */ /* end group _mali_uk_context */ - - -/** @addtogroup _mali_uk_core U/K Core - * - * The core functions provide the following functionality: - * - verify that the user and kernel API are compatible - * - retrieve information about the cores and memory banks in the system - * - wait for the result of jobs started on a core - * - * @{ */ - -/** @brief Waits for a job notification. - * - * Sleeps until notified or a timeout occurs. Returns information about the notification. - * - * @param args see _mali_uk_wait_for_notification_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args ); - -/** @brief Post a notification to the notification queue of this application. - * - * @param args see _mali_uk_post_notification_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args ); - -/** @brief Verifies if the user and kernel side of this API are compatible. - * - * @param args see _mali_uk_get_api_version_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args ); - -/** @brief Get the user space settings applicable for calling process. - * - * @param args see _mali_uk_get_user_settings_s in "mali_utgard_uk_types.h" - */ -_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args); - -/** @brief Get a user space setting applicable for calling process. - * - * @param args see _mali_uk_get_user_setting_s in "mali_utgard_uk_types.h" - */ -_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args); - -/** @} */ /* end group _mali_uk_core */ - - -/** @addtogroup _mali_uk_memory U/K Memory - * - * The memory functions provide functionality with and without a Mali-MMU present. - * - * For Mali-MMU based systems, the following functionality is provided: - * - Initialize and terminate MALI virtual address space - * - Allocate/deallocate physical memory to a MALI virtual address range and map into/unmap from the - * current process address space - * - Map/unmap external physical memory into the MALI virtual address range - * - * For Mali-nonMMU based systems: - * - Allocate/deallocate MALI memory - * - * @{ */ - -/** - * @brief Initialize the Mali-MMU Memory system - * - * For Mali-MMU builds of the drivers, this function must be called before any - * other functions in the \ref _mali_uk_memory group are called. - * - * @note This function is for Mali-MMU builds \b only. It should not be called - * when the drivers are built without Mali-MMU support. - * - * @param args see \ref _mali_uk_init_mem_s in mali_utgard_uk_types.h - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable - * _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args ); - -/** - * @brief Terminate the MMU Memory system - * - * For Mali-MMU builds of the drivers, this function must be called when - * functions in the \ref _mali_uk_memory group will no longer be called. This - * function must be called before the application terminates. - * - * @note This function is for Mali-MMU builds \b only. It should not be called - * when the drivers are built without Mali-MMU support. - * - * @param args see \ref _mali_uk_term_mem_s in mali_utgard_uk_types.h - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable - * _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args ); - -/** @brief Map Mali Memory into the current user process - * - * Maps Mali memory into the current user process in a generic way. - * - * This function is to be used for Mali-MMU mode. The function is available in both Mali-MMU and Mali-nonMMU modes, - * but should not be called by a user process in Mali-nonMMU mode. - * - * The implementation and operation of _mali_ukk_mem_mmap() is dependant on whether the driver is built for Mali-MMU - * or Mali-nonMMU: - * - In the nonMMU case, _mali_ukk_mem_mmap() requires a physical address to be specified. For this reason, an OS U/K - * implementation should not allow this to be called from user-space. In any case, nonMMU implementations are - * inherently insecure, and so the overall impact is minimal. Mali-MMU mode should be used if security is desired. - * - In the MMU case, _mali_ukk_mem_mmap() the _mali_uk_mem_mmap_s::phys_addr - * member is used for the \em Mali-virtual address desired for the mapping. The - * implementation of _mali_ukk_mem_mmap() will allocate both the CPU-virtual - * and CPU-physical addresses, and can cope with mapping a contiguous virtual - * address range to a sequence of non-contiguous physical pages. In this case, - * the CPU-physical addresses are not communicated back to the user-side, as - * they are unnecsessary; the \em Mali-virtual address range must be used for - * programming Mali structures. - * - * In the second (MMU) case, _mali_ukk_mem_mmap() handles management of - * CPU-virtual and CPU-physical ranges, but the \em caller must manage the - * \em Mali-virtual address range from the user-side. - * - * @note Mali-virtual address ranges are entirely separate between processes. - * It is not possible for a process to accidentally corrupt another process' - * \em Mali-virtual address space. - * - * @param args see _mali_uk_mem_mmap_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args ); - -/** @brief Unmap Mali Memory from the current user process - * - * Unmaps Mali memory from the current user process in a generic way. This only operates on Mali memory supplied - * from _mali_ukk_mem_mmap(). - * - * @param args see _mali_uk_mem_munmap_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args ); - -/** @brief Determine the buffer size necessary for an MMU page table dump. - * @param args see _mali_uk_query_mmu_page_table_dump_size_s in mali_utgard_uk_types.h - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args ); -/** @brief Dump MMU Page tables. - * @param args see _mali_uk_dump_mmu_page_table_s in mali_utgard_uk_types.h - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args ); - -/** @brief Map a physically contiguous range of memory into Mali - * @param args see _mali_uk_map_external_mem_s in mali_utgard_uk_types.h - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args ); - -/** @brief Unmap a physically contiguous range of memory from Mali - * @param args see _mali_uk_unmap_external_mem_s in mali_utgard_uk_types.h - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args ); - -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 -/** @brief Map UMP memory into Mali - * @param args see _mali_uk_attach_ump_mem_s in mali_utgard_uk_types.h - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args ); -/** @brief Unmap UMP memory from Mali - * @param args see _mali_uk_release_ump_mem_s in mali_utgard_uk_types.h - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args ); -#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */ - -/** @brief Determine virtual-to-physical mapping of a contiguous memory range - * (optional) - * - * This allows the user-side to do a virtual-to-physical address translation. - * In conjunction with _mali_uku_map_external_mem, this can be used to do - * direct rendering. - * - * This function will only succeed on a virtual range that is mapped into the - * current process, and that is contigious. - * - * If va is not page-aligned, then it is rounded down to the next page - * boundary. The remainer is added to size, such that ((u32)va)+size before - * rounding is equal to ((u32)va)+size after rounding. The rounded modified - * va and size will be written out into args on success. - * - * If the supplied size is zero, or not a multiple of the system's PAGE_SIZE, - * then size will be rounded up to the next multiple of PAGE_SIZE before - * translation occurs. The rounded up size will be written out into args on - * success. - * - * On most OSs, virtual-to-physical address translation is a priveledged - * function. Therefore, the implementer must validate the range supplied, to - * ensure they are not providing arbitrary virtual-to-physical address - * translations. While it is unlikely such a mechanism could be used to - * compromise the security of a system on its own, it is possible it could be - * combined with another small security risk to cause a much larger security - * risk. - * - * @note This is an optional part of the interface, and is only used by certain - * implementations of libEGL. If the platform layer in your libEGL - * implementation does not require Virtual-to-Physical address translation, - * then this function need not be implemented. A stub implementation should not - * be required either, as it would only be removed by the compiler's dead code - * elimination. - * - * @note if implemented, this function is entirely platform-dependant, and does - * not exist in common code. - * - * @param args see _mali_uk_va_to_mali_pa_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args ); - -/** @} */ /* end group _mali_uk_memory */ - - -/** @addtogroup _mali_uk_pp U/K Fragment Processor - * - * The Fragment Processor (aka PP (Pixel Processor)) functions provide the following functionality: - * - retrieving version of the fragment processors - * - determine number of fragment processors - * - starting a job on a fragment processor - * - * @{ */ - -/** @brief Issue a request to start a new job on a Fragment Processor. - * - * If the request fails args->status is set to _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE and you can - * try to start the job again. - * - * An existing job could be returned for requeueing if the new job has a higher priority than a previously started job - * which the hardware hasn't actually started processing yet. In this case the new job will be started instead and the - * existing one returned, otherwise the new job is started and the status field args->status is set to - * _MALI_UK_START_JOB_STARTED. - * - * Job completion can be awaited with _mali_ukk_wait_for_notification(). - * - * @param args see _mali_uk_pp_start_job_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_pp_start_job( _mali_uk_pp_start_job_s *args ); - -/** @brief Returns the number of Fragment Processors in the system - * - * @param args see _mali_uk_get_pp_number_of_cores_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores( _mali_uk_get_pp_number_of_cores_s *args ); - -/** @brief Returns the version that all Fragment Processor cores are compatible with. - * - * This function may only be called when _mali_ukk_get_pp_number_of_cores() indicated at least one Fragment - * Processor core is available. - * - * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_get_pp_core_version( _mali_uk_get_pp_core_version_s *args ); - -/** @brief Disable Write-back unit(s) on specified job - * - * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h" - */ -void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args); - - -/** @} */ /* end group _mali_uk_pp */ - - -/** @addtogroup _mali_uk_gp U/K Vertex Processor - * - * The Vertex Processor (aka GP (Geometry Processor)) functions provide the following functionality: - * - retrieving version of the Vertex Processors - * - determine number of Vertex Processors available - * - starting a job on a Vertex Processor - * - * @{ */ - -/** @brief Issue a request to start a new job on a Vertex Processor. - * - * If the request fails args->status is set to _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE and you can - * try to start the job again. - * - * An existing job could be returned for requeueing if the new job has a higher priority than a previously started job - * which the hardware hasn't actually started processing yet. In this case the new job will be started and the - * existing one returned, otherwise the new job is started and the status field args->status is set to - * _MALI_UK_START_JOB_STARTED. - * - * Job completion can be awaited with _mali_ukk_wait_for_notification(). - * - * @param args see _mali_uk_gp_start_job_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_gp_start_job( _mali_uk_gp_start_job_s *args ); - -/** @brief Returns the number of Vertex Processors in the system. - * - * @param args see _mali_uk_get_gp_number_of_cores_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores( _mali_uk_get_gp_number_of_cores_s *args ); - -/** @brief Returns the version that all Vertex Processor cores are compatible with. - * - * This function may only be called when _mali_uk_get_gp_number_of_cores() indicated at least one Vertex - * Processor core is available. - * - * @param args see _mali_uk_get_gp_core_version_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_get_gp_core_version( _mali_uk_get_gp_core_version_s *args ); - -/** @brief Resume or abort suspended Vertex Processor jobs. - * - * After receiving notification that a Vertex Processor job was suspended from - * _mali_ukk_wait_for_notification() you can use this function to resume or abort the job. - * - * @param args see _mali_uk_gp_suspend_response_s in "mali_utgard_uk_types.h" - * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. - */ -_mali_osk_errcode_t _mali_ukk_gp_suspend_response( _mali_uk_gp_suspend_response_s *args ); - -/** @} */ /* end group _mali_uk_gp */ - -#if MALI_TIMELINE_PROFILING_ENABLED -/** @addtogroup _mali_uk_profiling U/K Timeline profiling module - * @{ */ - -/** @brief Start recording profiling events. - * - * @param args see _mali_uk_profiling_start_s in "mali_utgard_uk_types.h" - */ -_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args); - -/** @brief Add event to profiling buffer. - * - * @param args see _mali_uk_profiling_add_event_s in "mali_utgard_uk_types.h" - */ -_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args); - -/** @brief Stop recording profiling events. - * - * @param args see _mali_uk_profiling_stop_s in "mali_utgard_uk_types.h" - */ -_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args); - -/** @brief Retrieve a recorded profiling event. - * - * @param args see _mali_uk_profiling_get_event_s in "mali_utgard_uk_types.h" - */ -_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args); - -/** @brief Clear recorded profiling events. - * - * @param args see _mali_uk_profiling_clear_s in "mali_utgard_uk_types.h" - */ -_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args); - -/** @} */ /* end group _mali_uk_profiling */ -#endif - -/** @addtogroup _mali_uk_vsync U/K VSYNC reporting module - * @{ */ - -/** @brief Report events related to vsync. - * - * @note Events should be reported when starting to wait for vsync and when the - * waiting is finished. This information can then be used in kernel space to - * complement the GPU utilization metric. - * - * @param args see _mali_uk_vsync_event_report_s in "mali_utgard_uk_types.h" - */ -_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args); - -/** @} */ /* end group _mali_uk_vsync */ - -/** @addtogroup _mali_sw_counters_report U/K Software counter reporting - * @{ */ - -/** @brief Report software counters. - * - * @param args see _mali_uk_sw_counters_report_s in "mali_uk_types.h" - */ -_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args); - -/** @} */ /* end group _mali_sw_counters_report */ - -/** @} */ /* end group u_k_api */ - -/** @} */ /* end group uddapi */ - -u32 _mali_ukk_report_memory_usage(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_UKK_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_user_settings_db.c b/drivers/media/video/samsung/mali/common/mali_user_settings_db.c deleted file mode 100644 index d3f1e50..0000000 --- a/drivers/media/video/samsung/mali/common/mali_user_settings_db.c +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_uk_types.h" -#include "mali_user_settings_db.h" -#include "mali_session.h" - -static u32 mali_user_settings[_MALI_UK_USER_SETTING_MAX]; -const char *_mali_uk_user_setting_descriptions[] = _MALI_UK_USER_SETTING_DESCRIPTIONS; - -static void mali_user_settings_notify(_mali_uk_user_setting_t setting, u32 value) -{ - struct mali_session_data *session, *tmp; - - mali_session_lock(); - MALI_SESSION_FOREACH(session, tmp, link) - { - _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_SETTINGS_CHANGED, sizeof(_mali_uk_settings_changed_s)); - _mali_uk_settings_changed_s *data = notobj->result_buffer; - data->setting = setting; - data->value = value; - - mali_session_send_notification(session, notobj); - } - mali_session_unlock(); -} - -void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value) -{ - mali_bool notify = MALI_FALSE; - - MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0); - - if (mali_user_settings[setting] != value) - { - notify = MALI_TRUE; - } - - mali_user_settings[setting] = value; - - if (notify) - { - mali_user_settings_notify(setting, value); - } -} - -u32 mali_get_user_setting(_mali_uk_user_setting_t setting) -{ - MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0); - - return mali_user_settings[setting]; -} - -_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args) -{ - _mali_uk_user_setting_t setting; - MALI_DEBUG_ASSERT_POINTER(args); - - setting = args->setting; - - if (0 <= setting && _MALI_UK_USER_SETTING_MAX > setting) - { - args->value = mali_user_settings[setting]; - return _MALI_OSK_ERR_OK; - } - else - { - return _MALI_OSK_ERR_INVALID_ARGS; - } -} - -_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args) -{ - MALI_DEBUG_ASSERT_POINTER(args); - - _mali_osk_memcpy(args->settings, mali_user_settings, sizeof(mali_user_settings)); - - return _MALI_OSK_ERR_OK; -} diff --git a/drivers/media/video/samsung/mali/common/mali_user_settings_db.h b/drivers/media/video/samsung/mali/common/mali_user_settings_db.h deleted file mode 100644 index fbb9415..0000000 --- a/drivers/media/video/samsung/mali/common/mali_user_settings_db.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_USER_SETTINGS_DB_H__ -#define __MALI_USER_SETTINGS_DB_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "mali_uk_types.h" - -/** @brief Set Mali user setting in DB - * - * Update the DB with a new value for \a setting. If the value is different from theprevious set value running sessions will be notified of the change. - * - * @param setting the setting to be changed - * @param value the new value to set - */ -void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value); - -/** @brief Get current Mali user setting value from DB - * - * @param setting the setting to extract - * @return the value of the selected setting - */ -u32 mali_get_user_setting(_mali_uk_user_setting_t setting); - -#ifdef __cplusplus -} -#endif -#endif /* __MALI_KERNEL_USER_SETTING__ */ diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h deleted file mode 100644 index 7c78947..0000000 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_UTGARD_H__ -#define __MALI_UTGARD_H__ - -/** @brief MALI GPU power down using MALI in-built PMU - * - * called to power down all cores - */ -int mali_pmu_powerdown(void); - - -/** @brief MALI GPU power up using MALI in-built PMU - * - * called to power up all cores - */ -int mali_pmu_powerup(void); - -#endif /* __MALI_UTGARD_H__ */ - diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h deleted file mode 100644 index 40822f7..0000000 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _MALI_UTGARD_COUNTERS_H_ -#define _MALI_UTGARD_COUNTERS_H_ - -typedef struct -{ - void *unused; -} mali_cinstr_counter_info; - -typedef enum -{ - MALI_CINSTR_COUNTER_SOURCE_EGL = 0, - MALI_CINSTR_COUNTER_SOURCE_OPENGLES = 1000, - MALI_CINSTR_COUNTER_SOURCE_OPENVG = 2000, - MALI_CINSTR_COUNTER_SOURCE_GP = 3000, - MALI_CINSTR_COUNTER_SOURCE_PP = 4000, -} cinstr_counter_source; - -#define MALI_CINSTR_EGL_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_EGL -#define MALI_CINSTR_EGL_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_EGL + 999) - -#define MALI_CINSTR_GLES_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_OPENGLES -#define MALI_CINSTR_GLES_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 999) - -#define MALI_CINSTR_VG_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_OPENVG -#define MALI_CINSTR_VG_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_OPENVG + 999) - -#define MALI_CINSTR_GP_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_GP -#define MALI_CINSTR_GP_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_GP + 999) - -#define MALI_CINSTR_PP_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_PP -#define MALI_CINSTR_PP_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_PP + 999) - - -typedef enum -{ - /* EGL counters */ - - MALI_CINSTR_EGL_BLIT_TIME = MALI_CINSTR_COUNTER_SOURCE_EGL + 0, - - /* Last counter in the EGL set */ - MALI_CINSTR_EGL_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_EGL + 1, - - /* GLES counters */ - - MALI_CINSTR_GLES_DRAW_ELEMENTS_CALLS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 0, - MALI_CINSTR_GLES_DRAW_ELEMENTS_NUM_INDICES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 1, - MALI_CINSTR_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 2, - MALI_CINSTR_GLES_DRAW_ARRAYS_CALLS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 3, - MALI_CINSTR_GLES_DRAW_ARRAYS_NUM_TRANSFORMED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 4, - MALI_CINSTR_GLES_DRAW_POINTS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 5, - MALI_CINSTR_GLES_DRAW_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 6, - MALI_CINSTR_GLES_DRAW_LINE_LOOP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 7, - MALI_CINSTR_GLES_DRAW_LINE_STRIP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 8, - MALI_CINSTR_GLES_DRAW_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 9, - MALI_CINSTR_GLES_DRAW_TRIANGLE_STRIP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 10, - MALI_CINSTR_GLES_DRAW_TRIANGLE_FAN = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 11, - MALI_CINSTR_GLES_NON_VBO_DATA_COPY_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 12, - MALI_CINSTR_GLES_UNIFORM_BYTES_COPIED_TO_MALI = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 13, - MALI_CINSTR_GLES_UPLOAD_TEXTURE_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 14, - MALI_CINSTR_GLES_UPLOAD_VBO_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 15, - MALI_CINSTR_GLES_NUM_FLUSHES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 16, - MALI_CINSTR_GLES_NUM_VSHADERS_GENERATED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 17, - MALI_CINSTR_GLES_NUM_FSHADERS_GENERATED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 18, - MALI_CINSTR_GLES_VSHADER_GEN_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 19, - MALI_CINSTR_GLES_FSHADER_GEN_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 20, - MALI_CINSTR_GLES_INPUT_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 21, - MALI_CINSTR_GLES_VXCACHE_HIT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 22, - MALI_CINSTR_GLES_VXCACHE_MISS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 23, - MALI_CINSTR_GLES_VXCACHE_COLLISION = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 24, - MALI_CINSTR_GLES_CULLED_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 25, - MALI_CINSTR_GLES_CULLED_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 26, - MALI_CINSTR_GLES_BACKFACE_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 27, - MALI_CINSTR_GLES_GBCLIP_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 28, - MALI_CINSTR_GLES_GBCLIP_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 29, - MALI_CINSTR_GLES_TRIANGLES_DRAWN = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 30, - MALI_CINSTR_GLES_DRAWCALL_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 31, - MALI_CINSTR_GLES_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 32, - MALI_CINSTR_GLES_INDEPENDENT_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 33, - MALI_CINSTR_GLES_STRIP_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 34, - MALI_CINSTR_GLES_FAN_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 35, - MALI_CINSTR_GLES_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 36, - MALI_CINSTR_GLES_INDEPENDENT_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 37, - MALI_CINSTR_GLES_STRIP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 38, - MALI_CINSTR_GLES_LOOP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 39, - MALI_CINSTR_GLES_POINTS_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 40, - - /* Last counter in the GLES set */ - MALI_CINSTR_GLES_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 41, - - /* OpenVG counters */ - - MALI_CINSTR_VG_MASK_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 0, - MALI_CINSTR_VG_CLEAR_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 1, - MALI_CINSTR_VG_APPEND_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 2, - MALI_CINSTR_VG_APPEND_PATH_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 3, - MALI_CINSTR_VG_MODIFY_PATH_COORDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 4, - MALI_CINSTR_VG_TRANSFORM_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 5, - MALI_CINSTR_VG_INTERPOLATE_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 6, - MALI_CINSTR_VG_PATH_LENGTH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 7, - MALI_CINSTR_VG_POINT_ALONG_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 8, - MALI_CINSTR_VG_PATH_BOUNDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 9, - MALI_CINSTR_VG_PATH_TRANSFORMED_BOUNDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 10, - MALI_CINSTR_VG_DRAW_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 11, - MALI_CINSTR_VG_CLEAR_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 12, - MALI_CINSTR_VG_IMAGE_SUB_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 13, - MALI_CINSTR_VG_GET_IMAGE_SUB_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 14, - MALI_CINSTR_VG_COPY_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 15, - MALI_CINSTR_VG_DRAW_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 16, - MALI_CINSTR_VG_SET_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 17, - MALI_CINSTR_VG_WRITE_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 18, - MALI_CINSTR_VG_GET_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 19, - MALI_CINSTR_VG_READ_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 20, - MALI_CINSTR_VG_COPY_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 21, - MALI_CINSTR_VG_COLOR_MATRIX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 22, - MALI_CINSTR_VG_CONVOLVE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 23, - MALI_CINSTR_VG_SEPARABLE_CONVOLVE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 24, - MALI_CINSTR_VG_GAUSSIAN_BLUR_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 25, - MALI_CINSTR_VG_LOOKUP_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 26, - MALI_CINSTR_VG_LOOKUP_SINGLE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 27, - MALI_CINSTR_VG_CONTEXT_CREATE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 28, - MALI_CINSTR_VG_STROKED_CUBICS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 29, - MALI_CINSTR_VG_STROKED_QUADS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 30, - MALI_CINSTR_VG_STROKED_ARCS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 31, - MALI_CINSTR_VG_STROKED_LINES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 32, - MALI_CINSTR_VG_FILLED_CUBICS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 33, - MALI_CINSTR_VG_FILLED_QUADS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 34, - MALI_CINSTR_VG_FILLED_ARCS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 35, - MALI_CINSTR_VG_FILLED_LINES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 36, - MALI_CINSTR_VG_DRAW_PATH_CALLS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 37, - MALI_CINSTR_VG_TRIANGLES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 38, - MALI_CINSTR_VG_VERTICES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 39, - MALI_CINSTR_VG_INDICES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 40, - MALI_CINSTR_VG_FILLED_PATHS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 41, - MALI_CINSTR_VG_STROKED_PATHS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 42, - MALI_CINSTR_VG_FILL_EXTRACT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 43, - MALI_CINSTR_VG_DRAW_FILLED_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 44, - MALI_CINSTR_VG_STROKE_EXTRACT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 45, - MALI_CINSTR_VG_DRAW_STROKED_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 46, - MALI_CINSTR_VG_DRAW_PAINT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 47, - MALI_CINSTR_VG_DATA_STRUCTURES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 48, - MALI_CINSTR_VG_MEM_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 49, - MALI_CINSTR_VG_RSW_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 50, - - /* Last counter in the VG set */ - MALI_CINSTR_VG_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 51, - - /* Mali GP counters */ - - MALI_CINSTR_GP_DEPRECATED_0 = MALI_CINSTR_COUNTER_SOURCE_GP + 0, - MALI_CINSTR_GP_ACTIVE_CYCLES_GP = MALI_CINSTR_COUNTER_SOURCE_GP + 1, - MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_SHADER = MALI_CINSTR_COUNTER_SOURCE_GP + 2, - MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_STORER = MALI_CINSTR_COUNTER_SOURCE_GP + 3, - MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_LOADER = MALI_CINSTR_COUNTER_SOURCE_GP + 4, - MALI_CINSTR_GP_CYCLES_VERTEX_LOADER_WAITING_FOR_VERTEX_SHADER = MALI_CINSTR_COUNTER_SOURCE_GP + 5, - MALI_CINSTR_GP_NUMBER_OF_WORDS_READ = MALI_CINSTR_COUNTER_SOURCE_GP + 6, - MALI_CINSTR_GP_NUMBER_OF_WORDS_WRITTEN = MALI_CINSTR_COUNTER_SOURCE_GP + 7, - MALI_CINSTR_GP_NUMBER_OF_READ_BURSTS = MALI_CINSTR_COUNTER_SOURCE_GP + 8, - MALI_CINSTR_GP_NUMBER_OF_WRITE_BURSTS = MALI_CINSTR_COUNTER_SOURCE_GP + 9, - MALI_CINSTR_GP_NUMBER_OF_VERTICES_PROCESSED = MALI_CINSTR_COUNTER_SOURCE_GP + 10, - MALI_CINSTR_GP_NUMBER_OF_VERTICES_FETCHED = MALI_CINSTR_COUNTER_SOURCE_GP + 11, - MALI_CINSTR_GP_NUMBER_OF_PRIMITIVES_FETCHED = MALI_CINSTR_COUNTER_SOURCE_GP + 12, - MALI_CINSTR_GP_RESERVED_13 = MALI_CINSTR_COUNTER_SOURCE_GP + 13, - MALI_CINSTR_GP_NUMBER_OF_BACKFACE_CULLINGS_DONE = MALI_CINSTR_COUNTER_SOURCE_GP + 14, - MALI_CINSTR_GP_NUMBER_OF_COMMANDS_WRITTEN_TO_TILES = MALI_CINSTR_COUNTER_SOURCE_GP + 15, - MALI_CINSTR_GP_NUMBER_OF_MEMORY_BLOCKS_ALLOCATED = MALI_CINSTR_COUNTER_SOURCE_GP + 16, - MALI_CINSTR_GP_RESERVED_17 = MALI_CINSTR_COUNTER_SOURCE_GP + 17, - MALI_CINSTR_GP_RESERVED_18 = MALI_CINSTR_COUNTER_SOURCE_GP + 18, - MALI_CINSTR_GP_NUMBER_OF_VERTEX_LOADER_CACHE_MISSES = MALI_CINSTR_COUNTER_SOURCE_GP + 19, - MALI_CINSTR_GP_RESERVED_20 = MALI_CINSTR_COUNTER_SOURCE_GP + 20, - MALI_CINSTR_GP_RESERVED_21 = MALI_CINSTR_COUNTER_SOURCE_GP + 21, - MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_SHADER_COMMAND_PROCESSOR = MALI_CINSTR_COUNTER_SOURCE_GP + 22, - MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_COMMAND_PROCESSOR = MALI_CINSTR_COUNTER_SOURCE_GP + 23, - MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_LIST_WRITER = MALI_CINSTR_COUNTER_SOURCE_GP + 24, - MALI_CINSTR_GP_ACTIVE_CYCLES_THROUGH_THE_PREPARE_LIST_COMMANDS = MALI_CINSTR_COUNTER_SOURCE_GP + 25, - MALI_CINSTR_GP_RESERVED_26 = MALI_CINSTR_COUNTER_SOURCE_GP + 26, - MALI_CINSTR_GP_ACTIVE_CYCLES_PRIMITIVE_ASSEMBLY = MALI_CINSTR_COUNTER_SOURCE_GP + 27, - MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_VERTEX_FETCHER = MALI_CINSTR_COUNTER_SOURCE_GP + 28, - MALI_CINSTR_GP_RESERVED_29 = MALI_CINSTR_COUNTER_SOURCE_GP + 29, - MALI_CINSTR_GP_ACTIVE_CYCLES_BOUNDINGBOX_AND_COMMAND_GENERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 30, - MALI_CINSTR_GP_RESERVED_31 = MALI_CINSTR_COUNTER_SOURCE_GP + 31, - MALI_CINSTR_GP_ACTIVE_CYCLES_SCISSOR_TILE_ITERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 32, - MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_TILE_ITERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 33, - MALI_CINSTR_GP_JOB_COUNT = MALI_CINSTR_COUNTER_SOURCE_GP + 900, - - /* Mali PP counters */ - - MALI_CINSTR_PP_ACTIVE_CLOCK_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 0, - MALI_CINSTR_PP_TOTAL_CLOCK_CYCLES_COUNT_REMOVED = MALI_CINSTR_COUNTER_SOURCE_PP + 1, - MALI_CINSTR_PP_TOTAL_BUS_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 2, - MALI_CINSTR_PP_TOTAL_BUS_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 3, - MALI_CINSTR_PP_BUS_READ_REQUEST_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 4, - MALI_CINSTR_PP_BUS_WRITE_REQUEST_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 5, - MALI_CINSTR_PP_BUS_READ_TRANSACTIONS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 6, - MALI_CINSTR_PP_BUS_WRITE_TRANSACTIONS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 7, - MALI_CINSTR_PP_RESERVED_08 = MALI_CINSTR_COUNTER_SOURCE_PP + 8, - MALI_CINSTR_PP_TILE_WRITEBACK_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 9, - MALI_CINSTR_PP_STORE_UNIT_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 10, - MALI_CINSTR_PP_RESERVED_11 = MALI_CINSTR_COUNTER_SOURCE_PP + 11, - MALI_CINSTR_PP_PALETTE_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 12, - MALI_CINSTR_PP_TEXTURE_CACHE_UNCOMPRESSED_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 13, - MALI_CINSTR_PP_POLYGON_LIST_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 14, - MALI_CINSTR_PP_RSW_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 15, - MALI_CINSTR_PP_VERTEX_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 16, - MALI_CINSTR_PP_UNIFORM_REMAPPING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 17, - MALI_CINSTR_PP_PROGRAM_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 19, - MALI_CINSTR_PP_VARYING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 19, - MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 20, - MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_REMAPPING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 21, - MALI_CINSTR_PP_TEXTURE_CACHE_COMPRESSED_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 22, - MALI_CINSTR_PP_LOAD_UNIT_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 23, - MALI_CINSTR_PP_POLYGON_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 24, - MALI_CINSTR_PP_PIXEL_RECTANGLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 25, - MALI_CINSTR_PP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 26, - MALI_CINSTR_PP_POINTS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 27, - MALI_CINSTR_PP_STALL_CYCLES_POLYGON_LIST_READER = MALI_CINSTR_COUNTER_SOURCE_PP + 28, - MALI_CINSTR_PP_STALL_CYCLES_TRIANGLE_SETUP = MALI_CINSTR_COUNTER_SOURCE_PP + 29, - MALI_CINSTR_PP_QUAD_RASTERIZED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 30, - MALI_CINSTR_PP_FRAGMENT_RASTERIZED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 31, - MALI_CINSTR_PP_FRAGMENT_REJECTED_FRAGMENT_KILL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 32, - MALI_CINSTR_PP_FRAGMENT_REJECTED_FWD_FRAGMENT_KILL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 33, - MALI_CINSTR_PP_FRAGMENT_PASSED_ZSTENCIL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 34, - MALI_CINSTR_PP_PATCHES_REJECTED_EARLY_Z_STENCIL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 35, - MALI_CINSTR_PP_PATCHES_EVALUATED = MALI_CINSTR_COUNTER_SOURCE_PP + 36, - MALI_CINSTR_PP_INSTRUCTION_COMPLETED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 37, - MALI_CINSTR_PP_INSTRUCTION_FAILED_RENDEZVOUS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 38, - MALI_CINSTR_PP_INSTRUCTION_FAILED_VARYING_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 39, - MALI_CINSTR_PP_INSTRUCTION_FAILED_TEXTURE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 40, - MALI_CINSTR_PP_INSTRUCTION_FAILED_LOAD_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 41, - MALI_CINSTR_PP_INSTRUCTION_FAILED_TILE_READ_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 42, - MALI_CINSTR_PP_INSTRUCTION_FAILED_STORE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 43, - MALI_CINSTR_PP_RENDEZVOUS_BREAKAGE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 44, - MALI_CINSTR_PP_PIPELINE_BUBBLES_CYCLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 45, - MALI_CINSTR_PP_TEXTURE_MAPPER_MULTIPASS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 46, - MALI_CINSTR_PP_TEXTURE_MAPPER_CYCLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 47, - MALI_CINSTR_PP_VERTEX_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 48, - MALI_CINSTR_PP_VERTEX_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 49, - MALI_CINSTR_PP_VARYING_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 50, - MALI_CINSTR_PP_VARYING_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 51, - MALI_CINSTR_PP_VARYING_CACHE_CONFLICT_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 52, - MALI_CINSTR_PP_TEXTURE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 53, - MALI_CINSTR_PP_TEXTURE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 54, - MALI_CINSTR_PP_TEXTURE_CACHE_CONFLICT_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 55, - MALI_CINSTR_PP_PALETTE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 56, /* Mali 200 only */ - MALI_CINSTR_PP_PALETTE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 57, /* Mali 200 only */ - MALI_CINSTR_PP_COMPRESSED_TEXTURE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 56, /* Mali 400 class only */ - MALI_CINSTR_PP_COMPRESSED_TEXTURE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 57, /* Mali 400 class only */ - MALI_CINSTR_PP_LOAD_STORE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 58, - MALI_CINSTR_PP_LOAD_STORE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 59, - MALI_CINSTR_PP_PROGRAM_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 60, - MALI_CINSTR_PP_PROGRAM_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 61, - MALI_CINSTR_PP_JOB_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 900, -} cinstr_counters_m200_t; - -#endif /*_MALI_UTGARD_COUNTERS_H_*/ diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h deleted file mode 100644 index 7935448..0000000 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_UTGARD_IOCTL_H__ -#define __MALI_UTGARD_IOCTL_H__ - -#include -#include -#include /* file system operations */ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * @file mali_kernel_ioctl.h - * Interface to the Linux device driver. - * This file describes the interface needed to use the Linux device driver. - * Its interface is designed to used by the HAL implementation through a thin arch layer. - */ - -/** - * ioctl commands - */ - -#define MALI_IOC_BASE 0x82 -#define MALI_IOC_CORE_BASE (_MALI_UK_CORE_SUBSYSTEM + MALI_IOC_BASE) -#define MALI_IOC_MEMORY_BASE (_MALI_UK_MEMORY_SUBSYSTEM + MALI_IOC_BASE) -#define MALI_IOC_PP_BASE (_MALI_UK_PP_SUBSYSTEM + MALI_IOC_BASE) -#define MALI_IOC_GP_BASE (_MALI_UK_GP_SUBSYSTEM + MALI_IOC_BASE) -#define MALI_IOC_PROFILING_BASE (_MALI_UK_PROFILING_SUBSYSTEM + MALI_IOC_BASE) -#define MALI_IOC_VSYNC_BASE (_MALI_UK_VSYNC_SUBSYSTEM + MALI_IOC_BASE) - -#define MALI_IOC_WAIT_FOR_NOTIFICATION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_WAIT_FOR_NOTIFICATION, _mali_uk_wait_for_notification_s *) -#define MALI_IOC_GET_API_VERSION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_API_VERSION, _mali_uk_get_api_version_s *) -#define MALI_IOC_POST_NOTIFICATION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_POST_NOTIFICATION, _mali_uk_post_notification_s *) -#define MALI_IOC_GET_USER_SETTING _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTING, _mali_uk_get_user_setting_s *) -#define MALI_IOC_GET_USER_SETTINGS _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTINGS, _mali_uk_get_user_settings_s *) - -#define MALI_IOC_MEM_GET_BIG_BLOCK _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, void *) -#define MALI_IOC_MEM_FREE_BIG_BLOCK _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_FREE_BIG_BLOCK, void *) -#define MALI_IOC_MEM_INIT _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_INIT_MEM, _mali_uk_init_mem_s *) -#define MALI_IOC_MEM_TERM _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_TERM_MEM, _mali_uk_term_mem_s *) -#define MALI_IOC_MEM_MAP_EXT _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MAP_EXT_MEM, _mali_uk_map_external_mem_s *) -#define MALI_IOC_MEM_UNMAP_EXT _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_UNMAP_EXT_MEM, _mali_uk_unmap_external_mem_s *) -#define MALI_IOC_MEM_ATTACH_DMA_BUF _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_ATTACH_DMA_BUF, _mali_uk_attach_dma_buf_s *) -#define MALI_IOC_MEM_RELEASE_DMA_BUF _IOW(MALI_IOC_MEMORY_BASE, _MALI_UK_RELEASE_DMA_BUF, _mali_uk_release_dma_buf_s *) -#define MALI_IOC_MEM_DMA_BUF_GET_SIZE _IOR(MALI_IOC_MEMORY_BASE, _MALI_UK_DMA_BUF_GET_SIZE, _mali_uk_dma_buf_get_size_s *) -#define MALI_IOC_MEM_ATTACH_UMP _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_ATTACH_UMP_MEM, _mali_uk_attach_ump_mem_s *) -#define MALI_IOC_MEM_RELEASE_UMP _IOW(MALI_IOC_MEMORY_BASE, _MALI_UK_RELEASE_UMP_MEM, _mali_uk_release_ump_mem_s *) -#define MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, _mali_uk_query_mmu_page_table_dump_size_s *) -#define MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_DUMP_MMU_PAGE_TABLE, _mali_uk_dump_mmu_page_table_s *) - -#define MALI_IOC_PP_START_JOB _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_START_JOB, _mali_uk_pp_start_job_s *) -#define MALI_IOC_PP_NUMBER_OF_CORES_GET _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_NUMBER_OF_CORES, _mali_uk_get_pp_number_of_cores_s *) -#define MALI_IOC_PP_CORE_VERSION_GET _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_CORE_VERSION, _mali_uk_get_pp_core_version_s * ) -#define MALI_IOC_PP_DISABLE_WB _IOW (MALI_IOC_PP_BASE, _MALI_UK_PP_DISABLE_WB, _mali_uk_pp_disable_wb_s * ) - -#define MALI_IOC_GP2_START_JOB _IOWR(MALI_IOC_GP_BASE, _MALI_UK_GP_START_JOB, _mali_uk_gp_start_job_s *) -#define MALI_IOC_GP2_NUMBER_OF_CORES_GET _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_NUMBER_OF_CORES, _mali_uk_get_gp_number_of_cores_s *) -#define MALI_IOC_GP2_CORE_VERSION_GET _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_CORE_VERSION, _mali_uk_get_gp_core_version_s *) -#define MALI_IOC_GP2_SUSPEND_RESPONSE _IOW (MALI_IOC_GP_BASE, _MALI_UK_GP_SUSPEND_RESPONSE,_mali_uk_gp_suspend_response_s *) - -#define MALI_IOC_PROFILING_START _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_START, _mali_uk_profiling_start_s *) -#define MALI_IOC_PROFILING_ADD_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_ADD_EVENT, _mali_uk_profiling_add_event_s*) -#define MALI_IOC_PROFILING_STOP _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_STOP, _mali_uk_profiling_stop_s *) -#define MALI_IOC_PROFILING_GET_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_EVENT, _mali_uk_profiling_get_event_s *) -#define MALI_IOC_PROFILING_CLEAR _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_CLEAR, _mali_uk_profiling_clear_s *) -#define MALI_IOC_PROFILING_GET_CONFIG _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_CONFIG, _mali_uk_get_user_settings_s *) -#define MALI_IOC_PROFILING_REPORT_SW_COUNTERS _IOW (MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_REPORT_SW_COUNTERS, _mali_uk_sw_counters_report_s *) - -#define MALI_IOC_VSYNC_EVENT_REPORT _IOW (MALI_IOC_VSYNC_BASE, _MALI_UK_VSYNC_EVENT_REPORT, _mali_uk_vsync_event_report_s *) - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_UTGARD_IOCTL_H__ */ diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h deleted file mode 100644 index b96596e..0000000 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _MALI_UTGARD_PROFILING_EVENTS_H_ -#define _MALI_UTGARD_PROFILING_EVENTS_H_ - -/* - * The event ID is a 32 bit value consisting of different fields - * reserved, 4 bits, for future use - * event type, 4 bits, cinstr_profiling_event_type_t - * event channel, 8 bits, the source of the event. - * event data, 16 bit field, data depending on event type - */ - -/** - * Specifies what kind of event this is - */ -typedef enum -{ - MALI_PROFILING_EVENT_TYPE_SINGLE = 0 << 24, - MALI_PROFILING_EVENT_TYPE_START = 1 << 24, - MALI_PROFILING_EVENT_TYPE_STOP = 2 << 24, - MALI_PROFILING_EVENT_TYPE_SUSPEND = 3 << 24, - MALI_PROFILING_EVENT_TYPE_RESUME = 4 << 24, -} cinstr_profiling_event_type_t; - - -/** - * Secifies the channel/source of the event - */ -typedef enum -{ - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE = 0 << 16, - MALI_PROFILING_EVENT_CHANNEL_GP0 = 1 << 16, - MALI_PROFILING_EVENT_CHANNEL_PP0 = 5 << 16, - MALI_PROFILING_EVENT_CHANNEL_PP1 = 6 << 16, - MALI_PROFILING_EVENT_CHANNEL_PP2 = 7 << 16, - MALI_PROFILING_EVENT_CHANNEL_PP3 = 8 << 16, - MALI_PROFILING_EVENT_CHANNEL_PP4 = 9 << 16, - MALI_PROFILING_EVENT_CHANNEL_PP5 = 10 << 16, - MALI_PROFILING_EVENT_CHANNEL_PP6 = 11 << 16, - MALI_PROFILING_EVENT_CHANNEL_PP7 = 12 << 16, - MALI_PROFILING_EVENT_CHANNEL_GPU = 21 << 16, -} cinstr_profiling_event_channel_t; - - -#define MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(num) (((MALI_PROFILING_EVENT_CHANNEL_GP0 >> 16) + (num)) << 16) -#define MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(num) (((MALI_PROFILING_EVENT_CHANNEL_PP0 >> 16) + (num)) << 16) - -/** - * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from software channel - */ -typedef enum -{ - MALI_PROFILING_EVENT_REASON_SINGLE_SW_NONE = 0, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_NEW_FRAME = 1, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_FLUSH = 2, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_SWAP_BUFFERS = 3, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_FB_EVENT = 4, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GP_ENQUEUE = 5, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_PP_ENQUEUE = 6, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_ENTER_API_FUNC = 10, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC = 11, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_TRY_LOCK = 53, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_LOCK = 54, - MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_UNLOCK = 55, -} cinstr_profiling_event_reason_single_sw_t; - -/** - * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel - */ -typedef enum -{ - MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE = 0, - MALI_PROFILING_EVENT_REASON_START_STOP_MALI = 1, -} cinstr_profiling_event_reason_start_stop_sw_t; - -/** - * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SUSPEND/RESUME is used from software channel - */ -typedef enum -{ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_NONE = 0, /* NOT used */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PIPELINE_FULL = 1, /* NOT used */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC = 26, /* used in some build configurations */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_WAIT = 27, /* USED */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_SYNC = 28, /* USED */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_FILTER_CLEANUP = 29, /* used */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_TEXTURE = 30, /* used */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_MIPLEVEL = 31, /* used */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_READPIXELS = 32, /* used */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_WAIT_SWAP_IMMEDIATE= 33, /* NOT used */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_ICS_QUEUE_BUFFER = 34, /* USED */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_ICS_DEQUEUE_BUFFER = 35, /* USED */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_UMP_LOCK = 36, /* Not currently used */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_GLOBAL_LOCK = 37, /* Not currently used */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_SWAP = 38, /* Not currently used */ - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_MALI_EGL_IMAGE_SYNC_WAIT = 39, /* USED */ -} cinstr_profiling_event_reason_suspend_resume_sw_t; - -/** - * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from a HW channel (GPx+PPx) - */ -typedef enum -{ - MALI_PROFILING_EVENT_REASON_SINGLE_HW_NONE = 0, - MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT = 1, - MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH = 2, -} cinstr_profiling_event_reason_single_hw_t; - -/** - * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel - */ -typedef enum -{ - MALI_PROFILING_EVENT_REASON_SINGLE_GPU_NONE = 0, - MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, -} cinstr_profiling_event_reason_single_gpu_t; - -#endif /*_MALI_UTGARD_PROFILING_EVENTS_H_*/ diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h deleted file mode 100644 index b35a715..0000000 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h +++ /dev/null @@ -1,1095 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_uk_types.h - * Defines the types and constants used in the user-kernel interface - */ - -#ifndef __MALI_UTGARD_UK_TYPES_H__ -#define __MALI_UTGARD_UK_TYPES_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * @addtogroup uddapi Unified Device Driver (UDD) APIs - * - * @{ - */ - -/** - * @addtogroup u_k_api UDD User/Kernel Interface (U/K) APIs - * - * @{ - */ - -/** @defgroup _mali_uk_core U/K Core - * @{ */ - -/** Definition of subsystem numbers, to assist in creating a unique identifier - * for each U/K call. - * - * @see _mali_uk_functions */ -typedef enum -{ - _MALI_UK_CORE_SUBSYSTEM, /**< Core Group of U/K calls */ - _MALI_UK_MEMORY_SUBSYSTEM, /**< Memory Group of U/K calls */ - _MALI_UK_PP_SUBSYSTEM, /**< Fragment Processor Group of U/K calls */ - _MALI_UK_GP_SUBSYSTEM, /**< Vertex Processor Group of U/K calls */ - _MALI_UK_PROFILING_SUBSYSTEM, /**< Profiling Group of U/K calls */ - _MALI_UK_PMM_SUBSYSTEM, /**< Power Management Module Group of U/K calls */ - _MALI_UK_VSYNC_SUBSYSTEM, /**< VSYNC Group of U/K calls */ -} _mali_uk_subsystem_t; - -/** Within a function group each function has its unique sequence number - * to assist in creating a unique identifier for each U/K call. - * - * An ordered pair of numbers selected from - * ( \ref _mali_uk_subsystem_t,\ref _mali_uk_functions) will uniquely identify the - * U/K call across all groups of functions, and all functions. */ -typedef enum -{ - /** Core functions */ - - _MALI_UK_OPEN = 0, /**< _mali_ukk_open() */ - _MALI_UK_CLOSE, /**< _mali_ukk_close() */ - _MALI_UK_WAIT_FOR_NOTIFICATION, /**< _mali_ukk_wait_for_notification() */ - _MALI_UK_GET_API_VERSION, /**< _mali_ukk_get_api_version() */ - _MALI_UK_POST_NOTIFICATION, /**< _mali_ukk_post_notification() */ - _MALI_UK_GET_USER_SETTING, /**< _mali_ukk_get_user_setting() *//**< [out] */ - _MALI_UK_GET_USER_SETTINGS, /**< _mali_ukk_get_user_settings() *//**< [out] */ - - /** Memory functions */ - - _MALI_UK_INIT_MEM = 0, /**< _mali_ukk_init_mem() */ - _MALI_UK_TERM_MEM, /**< _mali_ukk_term_mem() */ - _MALI_UK_GET_BIG_BLOCK, /**< _mali_ukk_get_big_block() */ - _MALI_UK_FREE_BIG_BLOCK, /**< _mali_ukk_free_big_block() */ - _MALI_UK_MAP_MEM, /**< _mali_ukk_mem_mmap() */ - _MALI_UK_UNMAP_MEM, /**< _mali_ukk_mem_munmap() */ - _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, /**< _mali_ukk_mem_get_mmu_page_table_dump_size() */ - _MALI_UK_DUMP_MMU_PAGE_TABLE, /**< _mali_ukk_mem_dump_mmu_page_table() */ - _MALI_UK_ATTACH_DMA_BUF, /**< _mali_ukk_attach_dma_buf() */ - _MALI_UK_RELEASE_DMA_BUF, /**< _mali_ukk_release_dma_buf() */ - _MALI_UK_DMA_BUF_GET_SIZE, /**< _mali_ukk_dma_buf_get_size() */ - _MALI_UK_ATTACH_UMP_MEM, /**< _mali_ukk_attach_ump_mem() */ - _MALI_UK_RELEASE_UMP_MEM, /**< _mali_ukk_release_ump_mem() */ - _MALI_UK_MAP_EXT_MEM, /**< _mali_uku_map_external_mem() */ - _MALI_UK_UNMAP_EXT_MEM, /**< _mali_uku_unmap_external_mem() */ - _MALI_UK_VA_TO_MALI_PA, /**< _mali_uku_va_to_mali_pa() */ - - /** Common functions for each core */ - - _MALI_UK_START_JOB = 0, /**< Start a Fragment/Vertex Processor Job on a core */ - _MALI_UK_GET_NUMBER_OF_CORES, /**< Get the number of Fragment/Vertex Processor cores */ - _MALI_UK_GET_CORE_VERSION, /**< Get the Fragment/Vertex Processor version compatible with all cores */ - - /** Fragment Processor Functions */ - - _MALI_UK_PP_START_JOB = _MALI_UK_START_JOB, /**< _mali_ukk_pp_start_job() */ - _MALI_UK_GET_PP_NUMBER_OF_CORES = _MALI_UK_GET_NUMBER_OF_CORES, /**< _mali_ukk_get_pp_number_of_cores() */ - _MALI_UK_GET_PP_CORE_VERSION = _MALI_UK_GET_CORE_VERSION, /**< _mali_ukk_get_pp_core_version() */ - _MALI_UK_PP_DISABLE_WB, /**< _mali_ukk_pp_job_disable_wb() */ - - /** Vertex Processor Functions */ - - _MALI_UK_GP_START_JOB = _MALI_UK_START_JOB, /**< _mali_ukk_gp_start_job() */ - _MALI_UK_GET_GP_NUMBER_OF_CORES = _MALI_UK_GET_NUMBER_OF_CORES, /**< _mali_ukk_get_gp_number_of_cores() */ - _MALI_UK_GET_GP_CORE_VERSION = _MALI_UK_GET_CORE_VERSION, /**< _mali_ukk_get_gp_core_version() */ - _MALI_UK_GP_SUSPEND_RESPONSE, /**< _mali_ukk_gp_suspend_response() */ - - /** Profiling functions */ - - _MALI_UK_PROFILING_START = 0, /**< __mali_uku_profiling_start() */ - _MALI_UK_PROFILING_ADD_EVENT, /**< __mali_uku_profiling_add_event() */ - _MALI_UK_PROFILING_STOP, /**< __mali_uku_profiling_stop() */ - _MALI_UK_PROFILING_GET_EVENT, /**< __mali_uku_profiling_get_event() */ - _MALI_UK_PROFILING_CLEAR, /**< __mali_uku_profiling_clear() */ - _MALI_UK_PROFILING_GET_CONFIG, /**< __mali_uku_profiling_get_config() */ - _MALI_UK_PROFILING_REPORT_SW_COUNTERS,/**< __mali_uku_profiling_report_sw_counters() */ - - /** VSYNC reporting fuctions */ - _MALI_UK_VSYNC_EVENT_REPORT = 0, /**< _mali_ukk_vsync_event_report() */ - -} _mali_uk_functions; - -/** @brief Get the size necessary for system info - * - * @see _mali_ukk_get_system_info_size() - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 size; /**< [out] size of buffer necessary to hold system information data, in bytes */ -} _mali_uk_get_system_info_size_s; - - -/** @defgroup _mali_uk_getsysteminfo U/K Get System Info - * @{ */ - -/** - * Type definition for the core version number. - * Used when returning the version number read from a core - * - * Its format is that of the 32-bit Version register for a particular core. - * Refer to the "Mali200 and MaliGP2 3D Graphics Processor Technical Reference - * Manual", ARM DDI 0415C, for more information. - */ -typedef u32 _mali_core_version; - -/** - * Enum values for the different modes the driver can be put in. - * Normal is the default mode. The driver then uses a job queue and takes job objects from the clients. - * Job completion is reported using the _mali_ukk_wait_for_notification call. - * The driver blocks this io command until a job has completed or failed or a timeout occurs. - * - * The 'raw' mode is reserved for future expansion. - */ -typedef enum _mali_driver_mode -{ - _MALI_DRIVER_MODE_RAW = 1, /**< Reserved for future expansion */ - _MALI_DRIVER_MODE_NORMAL = 2 /**< Normal mode of operation */ -} _mali_driver_mode; - -/** @brief List of possible cores - * - * add new entries to the end of this enum */ -typedef enum _mali_core_type -{ - _MALI_GP2 = 2, /**< MaliGP2 Programmable Vertex Processor */ - _MALI_200 = 5, /**< Mali200 Programmable Fragment Processor */ - _MALI_400_GP = 6, /**< Mali400 Programmable Vertex Processor */ - _MALI_400_PP = 7, /**< Mali400 Programmable Fragment Processor */ - /* insert new core here, do NOT alter the existing values */ -} _mali_core_type; - - -/** @brief Capabilities of Memory Banks - * - * These may be used to restrict memory banks for certain uses. They may be - * used when access is not possible (e.g. Bus does not support access to it) - * or when access is possible but not desired (e.g. Access is slow). - * - * In the case of 'possible but not desired', there is no way of specifying - * the flags as an optimization hint, so that the memory could be used as a - * last resort. - * - * @see _mali_mem_info - */ -typedef enum _mali_bus_usage -{ - - _MALI_PP_READABLE = (1<<0), /** Readable by the Fragment Processor */ - _MALI_PP_WRITEABLE = (1<<1), /** Writeable by the Fragment Processor */ - _MALI_GP_READABLE = (1<<2), /** Readable by the Vertex Processor */ - _MALI_GP_WRITEABLE = (1<<3), /** Writeable by the Vertex Processor */ - _MALI_CPU_READABLE = (1<<4), /** Readable by the CPU */ - _MALI_CPU_WRITEABLE = (1<<5), /** Writeable by the CPU */ - _MALI_GP_L2_ALLOC = (1<<6), /** GP allocate mali L2 cache lines*/ - _MALI_MMU_READABLE = _MALI_PP_READABLE | _MALI_GP_READABLE, /** Readable by the MMU (including all cores behind it) */ - _MALI_MMU_WRITEABLE = _MALI_PP_WRITEABLE | _MALI_GP_WRITEABLE, /** Writeable by the MMU (including all cores behind it) */ -} _mali_bus_usage; - -typedef enum mali_memory_cache_settings -{ - MALI_CACHE_STANDARD = 0, - MALI_CACHE_GP_READ_ALLOCATE = 1, -} mali_memory_cache_settings ; - - -/** @brief Information about the Mali Memory system - * - * Information is stored in a linked list, which is stored entirely in the - * buffer pointed to by the system_info member of the - * _mali_uk_get_system_info_s arguments provided to _mali_ukk_get_system_info() - * - * Each element of the linked list describes a single Mali Memory bank. - * Each allocation can only come from one bank, and will not cross multiple - * banks. - * - * On Mali-MMU systems, there is only one bank, which describes the maximum - * possible address range that could be allocated (which may be much less than - * the available physical memory) - * - * The flags member describes the capabilities of the memory. It is an error - * to attempt to build a job for a particular core (PP or GP) when the memory - * regions used do not have the capabilities for supporting that core. This - * would result in a job abort from the Device Driver. - * - * For example, it is correct to build a PP job where read-only data structures - * are taken from a memory with _MALI_PP_READABLE set and - * _MALI_PP_WRITEABLE clear, and a framebuffer with _MALI_PP_WRITEABLE set and - * _MALI_PP_READABLE clear. However, it would be incorrect to use a framebuffer - * where _MALI_PP_WRITEABLE is clear. - */ -typedef struct _mali_mem_info -{ - u32 size; /**< Size of the memory bank in bytes */ - _mali_bus_usage flags; /**< Capabilitiy flags of the memory */ - u32 maximum_order_supported; /**< log2 supported size */ - u32 identifier; /* mali_memory_cache_settings cache_settings; */ - struct _mali_mem_info * next; /**< Next List Link */ -} _mali_mem_info; - - - -/** @} */ /* end group _mali_uk_core */ - - -/** @defgroup _mali_uk_gp U/K Vertex Processor - * @{ */ - -/** @defgroup _mali_uk_gp_suspend_response_s Vertex Processor Suspend Response - * @{ */ - -/** @brief Arguments for _mali_ukk_gp_suspend_response() - * - * When _mali_wait_for_notification() receives notification that a - * Vertex Processor job was suspended, you need to send a response to indicate - * what needs to happen with this job. You can either abort or resume the job. - * - * - set @c code to indicate response code. This is either @c _MALIGP_JOB_ABORT or - * @c _MALIGP_JOB_RESUME_WITH_NEW_HEAP to indicate you will provide a new heap - * for the job that will resolve the out of memory condition for the job. - * - copy the @c cookie value from the @c _mali_uk_gp_job_suspended_s notification; - * this is an identifier for the suspended job - * - set @c arguments[0] and @c arguments[1] to zero if you abort the job. If - * you resume it, @c argument[0] should specify the Mali start address for the new - * heap and @c argument[1] the Mali end address of the heap. - * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() - * - */ -typedef enum _maligp_job_suspended_response_code -{ - _MALIGP_JOB_ABORT, /**< Abort the Vertex Processor job */ - _MALIGP_JOB_RESUME_WITH_NEW_HEAP /**< Resume the Vertex Processor job with a new heap */ -} _maligp_job_suspended_response_code; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 cookie; /**< [in] cookie from the _mali_uk_gp_job_suspended_s notification */ - _maligp_job_suspended_response_code code; /**< [in] abort or resume response code, see \ref _maligp_job_suspended_response_code */ - u32 arguments[2]; /**< [in] 0 when aborting a job. When resuming a job, the Mali start and end address for a new heap to resume the job with */ -} _mali_uk_gp_suspend_response_s; - -/** @} */ /* end group _mali_uk_gp_suspend_response_s */ - -/** @defgroup _mali_uk_gpstartjob_s Vertex Processor Start Job - * @{ */ - -/** @brief Status indicating the result of starting a Vertex or Fragment processor job */ -typedef enum -{ - _MALI_UK_START_JOB_STARTED, /**< Job started */ - _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE /**< Job could not be started at this time. Try starting the job again */ -} _mali_uk_start_job_status; - -/** @brief Status indicating the result of the execution of a Vertex or Fragment processor job */ - -typedef enum -{ - _MALI_UK_JOB_STATUS_END_SUCCESS = 1<<(16+0), - _MALI_UK_JOB_STATUS_END_OOM = 1<<(16+1), - _MALI_UK_JOB_STATUS_END_ABORT = 1<<(16+2), - _MALI_UK_JOB_STATUS_END_TIMEOUT_SW = 1<<(16+3), - _MALI_UK_JOB_STATUS_END_HANG = 1<<(16+4), - _MALI_UK_JOB_STATUS_END_SEG_FAULT = 1<<(16+5), - _MALI_UK_JOB_STATUS_END_ILLEGAL_JOB = 1<<(16+6), - _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR = 1<<(16+7), - _MALI_UK_JOB_STATUS_END_SHUTDOWN = 1<<(16+8), - _MALI_UK_JOB_STATUS_END_SYSTEM_UNUSABLE = 1<<(16+9) -} _mali_uk_job_status; - -#define MALIGP2_NUM_REGS_FRAME (6) - -/** @brief Arguments for _mali_ukk_gp_start_job() - * - * To start a Vertex Processor job - * - associate the request with a reference to a @c mali_gp_job_info by setting - * user_job_ptr to the address of the @c mali_gp_job_info of the job. - * - set @c priority to the priority of the @c mali_gp_job_info - * - specify a timeout for the job by setting @c watchdog_msecs to the number of - * milliseconds the job is allowed to run. Specifying a value of 0 selects the - * default timeout in use by the device driver. - * - copy the frame registers from the @c mali_gp_job_info into @c frame_registers. - * - set the @c perf_counter_flag, @c perf_counter_src0 and @c perf_counter_src1 to zero - * for a non-instrumented build. For an instrumented build you can use up - * to two performance counters. Set the corresponding bit in @c perf_counter_flag - * to enable them. @c perf_counter_src0 and @c perf_counter_src1 specify - * the source of what needs to get counted (e.g. number of vertex loader - * cache hits). For source id values, see ARM DDI0415A, Table 3-60. - * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() - * - * When @c _mali_ukk_gp_start_job() returns @c _MALI_OSK_ERR_OK, status contains the - * result of the request (see \ref _mali_uk_start_job_status). If the job could - * not get started (@c _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE) it should be - * tried again. - * - * After the job has started, @c _mali_wait_for_notification() will be notified - * that the job finished or got suspended. It may get suspended due to - * resource shortage. If it finished (see _mali_ukk_wait_for_notification()) - * the notification will contain a @c _mali_uk_gp_job_finished_s result. If - * it got suspended the notification will contain a @c _mali_uk_gp_job_suspended_s - * result. - * - * The @c _mali_uk_gp_job_finished_s contains the job status (see \ref _mali_uk_job_status), - * the number of milliseconds the job took to render, and values of core registers - * when the job finished (irq status, performance counters, renderer list - * address). A job has finished succesfully when its status is - * @c _MALI_UK_JOB_STATUS_FINISHED. If the hardware detected a timeout while rendering - * the job, or software detected the job is taking more than watchdog_msecs to - * complete, the status will indicate @c _MALI_UK_JOB_STATUS_HANG. - * If the hardware detected a bus error while accessing memory associated with the - * job, status will indicate @c _MALI_UK_JOB_STATUS_SEG_FAULT. - * status will indicate @c _MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to - * stop the job but the job didn't start on the hardware yet, e.g. when the - * driver shutdown. - * - * In case the job got suspended, @c _mali_uk_gp_job_suspended_s contains - * the @c user_job_ptr identifier used to start the job with, the @c reason - * why the job stalled (see \ref _maligp_job_suspended_reason) and a @c cookie - * to identify the core on which the job stalled. This @c cookie will be needed - * when responding to this nofication by means of _mali_ukk_gp_suspend_response(). - * (see _mali_ukk_gp_suspend_response()). The response is either to abort or - * resume the job. If the job got suspended due to an out of memory condition - * you may be able to resolve this by providing more memory and resuming the job. - * - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 user_job_ptr; /**< [in] identifier for the job in user space, a @c mali_gp_job_info* */ - u32 priority; /**< [in] job priority. A lower number means higher priority */ - u32 frame_registers[MALIGP2_NUM_REGS_FRAME]; /**< [in] core specific registers associated with this job */ - u32 perf_counter_flag; /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ - u32 perf_counter_src0; /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ - u32 perf_counter_src1; /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ - u32 frame_builder_id; /**< [in] id of the originating frame builder */ - u32 flush_id; /**< [in] flush id within the originating frame builder */ -} _mali_uk_gp_start_job_s; - -#define _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE (1<<0) /**< Enable performance counter SRC0 for a job */ -#define _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE (1<<1) /**< Enable performance counter SRC1 for a job */ - -/** @} */ /* end group _mali_uk_gpstartjob_s */ - -typedef struct -{ - u32 user_job_ptr; /**< [out] identifier for the job in user space */ - _mali_uk_job_status status; /**< [out] status of finished job */ - u32 heap_current_addr; /**< [out] value of the GP PLB PL heap start address register */ - u32 perf_counter0; /**< [out] value of perfomance counter 0 (see ARM DDI0415A) */ - u32 perf_counter1; /**< [out] value of perfomance counter 1 (see ARM DDI0415A) */ -} _mali_uk_gp_job_finished_s; - -typedef enum _maligp_job_suspended_reason -{ - _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY /**< Polygon list builder unit (PLBU) has run out of memory */ -} _maligp_job_suspended_reason; - -typedef struct -{ - u32 user_job_ptr; /**< [out] identifier for the job in user space */ - _maligp_job_suspended_reason reason; /**< [out] reason why the job stalled */ - u32 cookie; /**< [out] identifier for the core in kernel space on which the job stalled */ -} _mali_uk_gp_job_suspended_s; - -/** @} */ /* end group _mali_uk_gp */ - - -/** @defgroup _mali_uk_pp U/K Fragment Processor - * @{ */ - -#define _MALI_PP_MAX_SUB_JOBS 8 - -#define _MALI_PP_MAX_FRAME_REGISTERS ((0x058/4)+1) - -#define _MALI_PP_MAX_WB_REGISTERS ((0x02C/4)+1) - -/** Flag for _mali_uk_pp_start_job_s */ -#define _MALI_PP_JOB_FLAG_NO_NOTIFICATION (1<<0) -#define _MALI_PP_JOB_FLAG_BARRIER (1<<1) - -/** @defgroup _mali_uk_ppstartjob_s Fragment Processor Start Job - * @{ */ - -/** @brief Arguments for _mali_ukk_pp_start_job() - * - * To start a Fragment Processor job - * - associate the request with a reference to a mali_pp_job by setting - * @c user_job_ptr to the address of the @c mali_pp_job of the job. - * - set @c priority to the priority of the mali_pp_job - * - specify a timeout for the job by setting @c watchdog_msecs to the number of - * milliseconds the job is allowed to run. Specifying a value of 0 selects the - * default timeout in use by the device driver. - * - copy the frame registers from the @c mali_pp_job into @c frame_registers. - * For MALI200 you also need to copy the write back 0,1 and 2 registers. - * - set the @c perf_counter_flag, @c perf_counter_src0 and @c perf_counter_src1 to zero - * for a non-instrumented build. For an instrumented build you can use up - * to two performance counters. Set the corresponding bit in @c perf_counter_flag - * to enable them. @c perf_counter_src0 and @c perf_counter_src1 specify - * the source of what needs to get counted (e.g. number of vertex loader - * cache hits). For source id values, see ARM DDI0415A, Table 3-60. - * - pass in the user-kernel context in @c ctx that was returned from _mali_ukk_open() - * - * When _mali_ukk_pp_start_job() returns @c _MALI_OSK_ERR_OK, @c status contains the - * result of the request (see \ref _mali_uk_start_job_status). If the job could - * not get started (@c _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE) it should be - * tried again. - * - * After the job has started, _mali_wait_for_notification() will be notified - * when the job finished. The notification will contain a - * @c _mali_uk_pp_job_finished_s result. It contains the @c user_job_ptr - * identifier used to start the job with, the job @c status (see \ref _mali_uk_job_status), - * the number of milliseconds the job took to render, and values of core registers - * when the job finished (irq status, performance counters, renderer list - * address). A job has finished succesfully when its status is - * @c _MALI_UK_JOB_STATUS_FINISHED. If the hardware detected a timeout while rendering - * the job, or software detected the job is taking more than @c watchdog_msecs to - * complete, the status will indicate @c _MALI_UK_JOB_STATUS_HANG. - * If the hardware detected a bus error while accessing memory associated with the - * job, status will indicate @c _MALI_UK_JOB_STATUS_SEG_FAULT. - * status will indicate @c _MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to - * stop the job but the job didn't start on the hardware yet, e.g. when the - * driver shutdown. - * - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 user_job_ptr; /**< [in] identifier for the job in user space */ - u32 priority; /**< [in] job priority. A lower number means higher priority */ - u32 frame_registers[_MALI_PP_MAX_FRAME_REGISTERS]; /**< [in] core specific registers associated with first sub job, see ARM DDI0415A */ - u32 frame_registers_addr_frame[_MALI_PP_MAX_SUB_JOBS - 1]; /**< [in] ADDR_FRAME registers for sub job 1-7 */ - u32 frame_registers_addr_stack[_MALI_PP_MAX_SUB_JOBS - 1]; /**< [in] ADDR_STACK registers for sub job 1-7 */ - u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS]; - u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS]; - u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS]; - u32 num_cores; /**< [in] Number of cores to set up (valid range: 1-4) */ - u32 perf_counter_flag; /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ - u32 perf_counter_src0; /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ - u32 perf_counter_src1; /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ - u32 frame_builder_id; /**< [in] id of the originating frame builder */ - u32 flush_id; /**< [in] flush id within the originating frame builder */ - u32 flags; /**< [in] See _MALI_PP_JOB_FLAG_* for a list of avaiable flags */ -} _mali_uk_pp_start_job_s; -/** @} */ /* end group _mali_uk_ppstartjob_s */ - -typedef struct -{ - u32 user_job_ptr; /**< [out] identifier for the job in user space */ - _mali_uk_job_status status; /**< [out] status of finished job */ - u32 perf_counter0[_MALI_PP_MAX_SUB_JOBS]; /**< [out] value of perfomance counter 0 (see ARM DDI0415A), one for each sub job */ - u32 perf_counter1[_MALI_PP_MAX_SUB_JOBS]; /**< [out] value of perfomance counter 1 (see ARM DDI0415A), one for each sub job */ -} _mali_uk_pp_job_finished_s; - -/** - * Flags to indicate write-back units - */ -typedef enum -{ - _MALI_UK_PP_JOB_WB0 = 1, - _MALI_UK_PP_JOB_WB1 = 2, - _MALI_UK_PP_JOB_WB2 = 4, -} _mali_uk_pp_job_wbx_flag; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 fb_id; /**< [in] Frame builder ID of job to disable WB units for */ - u32 flush_id; /**< [in] Flush ID of job to disable WB units for */ - _mali_uk_pp_job_wbx_flag wbx; /**< [in] write-back units to disable */ -} _mali_uk_pp_disable_wb_s; - - -/** @} */ /* end group _mali_uk_pp */ - - -/** @addtogroup _mali_uk_core U/K Core - * @{ */ - -/** @defgroup _mali_uk_waitfornotification_s Wait For Notification - * @{ */ - -/** @brief Notification type encodings - * - * Each Notification type is an ordered pair of (subsystem,id), and is unique. - * - * The encoding of subsystem,id into a 32-bit word is: - * encoding = (( subsystem << _MALI_NOTIFICATION_SUBSYSTEM_SHIFT ) & _MALI_NOTIFICATION_SUBSYSTEM_MASK) - * | (( id << _MALI_NOTIFICATION_ID_SHIFT ) & _MALI_NOTIFICATION_ID_MASK) - * - * @see _mali_uk_wait_for_notification_s - */ -typedef enum -{ - /** core notifications */ - - _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x20, - _MALI_NOTIFICATION_APPLICATION_QUIT = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x40, - _MALI_NOTIFICATION_SETTINGS_CHANGED = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x80, - - /** Fragment Processor notifications */ - - _MALI_NOTIFICATION_PP_FINISHED = (_MALI_UK_PP_SUBSYSTEM << 16) | 0x10, - - /** Vertex Processor notifications */ - - _MALI_NOTIFICATION_GP_FINISHED = (_MALI_UK_GP_SUBSYSTEM << 16) | 0x10, - _MALI_NOTIFICATION_GP_STALLED = (_MALI_UK_GP_SUBSYSTEM << 16) | 0x20, - -} _mali_uk_notification_type; - -/** to assist in splitting up 32-bit notification value in subsystem and id value */ -#define _MALI_NOTIFICATION_SUBSYSTEM_MASK 0xFFFF0000 -#define _MALI_NOTIFICATION_SUBSYSTEM_SHIFT 16 -#define _MALI_NOTIFICATION_ID_MASK 0x0000FFFF -#define _MALI_NOTIFICATION_ID_SHIFT 0 - - -/** @brief Enumeration of possible settings which match mali_setting_t in user space - * - * - */ -typedef enum -{ - _MALI_UK_USER_SETTING_SW_EVENTS_ENABLE = 0, - _MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, - _MALI_UK_USER_SETTING_DEPTHBUFFER_CAPTURE_ENABLED, - _MALI_UK_USER_SETTING_STENCILBUFFER_CAPTURE_ENABLED, - _MALI_UK_USER_SETTING_PER_TILE_COUNTERS_CAPTURE_ENABLED, - _MALI_UK_USER_SETTING_BUFFER_CAPTURE_COMPOSITOR, - _MALI_UK_USER_SETTING_BUFFER_CAPTURE_WINDOW, - _MALI_UK_USER_SETTING_BUFFER_CAPTURE_OTHER, - _MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, - _MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, - _MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, - _MALI_UK_USER_SETTING_MAX, -} _mali_uk_user_setting_t; - -/* See mali_user_settings_db.c */ -extern const char *_mali_uk_user_setting_descriptions[]; -#define _MALI_UK_USER_SETTING_DESCRIPTIONS \ -{ \ - "sw_events_enable", \ - "colorbuffer_capture_enable", \ - "depthbuffer_capture_enable", \ - "stencilbuffer_capture_enable", \ - "per_tile_counters_enable", \ - "buffer_capture_compositor", \ - "buffer_capture_window", \ - "buffer_capture_other", \ - "buffer_capture_n_frames", \ - "buffer_capture_resize_factor", \ - "sw_counters_enable", \ -}; - -/** @brief struct to hold the value to a particular setting as seen in the kernel space - */ -typedef struct -{ - _mali_uk_user_setting_t setting; - u32 value; -} _mali_uk_settings_changed_s; - -/** @brief Arguments for _mali_ukk_wait_for_notification() - * - * On successful return from _mali_ukk_wait_for_notification(), the members of - * this structure will indicate the reason for notification. - * - * Specifically, the source of the notification can be identified by the - * subsystem and id fields of the mali_uk_notification_type in the code.type - * member. The type member is encoded in a way to divide up the types into a - * subsystem field, and a per-subsystem ID field. See - * _mali_uk_notification_type for more information. - * - * Interpreting the data union member depends on the notification type: - * - * - type == _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS - * - The kernel side is shutting down. No further - * _mali_uk_wait_for_notification() calls should be made. - * - In this case, the value of the data union member is undefined. - * - This is used to indicate to the user space client that it should close - * the connection to the Mali Device Driver. - * - type == _MALI_NOTIFICATION_PP_FINISHED - * - The notification data is of type _mali_uk_pp_job_finished_s. It contains the user_job_ptr - * identifier used to start the job with, the job status, the number of milliseconds the job took to render, - * and values of core registers when the job finished (irq status, performance counters, renderer list - * address). - * - A job has finished succesfully when its status member is _MALI_UK_JOB_STATUS_FINISHED. - * - If the hardware detected a timeout while rendering the job, or software detected the job is - * taking more than watchdog_msecs (see _mali_ukk_pp_start_job()) to complete, the status member will - * indicate _MALI_UK_JOB_STATUS_HANG. - * - If the hardware detected a bus error while accessing memory associated with the job, status will - * indicate _MALI_UK_JOB_STATUS_SEG_FAULT. - * - Status will indicate MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to stop the job but the job - * didn't start the hardware yet, e.g. when the driver closes. - * - type == _MALI_NOTIFICATION_GP_FINISHED - * - The notification data is of type _mali_uk_gp_job_finished_s. The notification is similar to that of - * type == _MALI_NOTIFICATION_PP_FINISHED, except that several other GP core register values are returned. - * The status values have the same meaning for type == _MALI_NOTIFICATION_PP_FINISHED. - * - type == _MALI_NOTIFICATION_GP_STALLED - * - The nofication data is of type _mali_uk_gp_job_suspended_s. It contains the user_job_ptr - * identifier used to start the job with, the reason why the job stalled and a cookie to identify the core on - * which the job stalled. - * - The reason member of gp_job_suspended is set to _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY - * when the polygon list builder unit has run out of memory. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - _mali_uk_notification_type type; /**< [out] Type of notification available */ - union - { - _mali_uk_gp_job_suspended_s gp_job_suspended;/**< [out] Notification data for _MALI_NOTIFICATION_GP_STALLED notification type */ - _mali_uk_gp_job_finished_s gp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_GP_FINISHED notification type */ - _mali_uk_pp_job_finished_s pp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_PP_FINISHED notification type */ - _mali_uk_settings_changed_s setting_changed;/**< [out] Notification data for _MALI_NOTIFICAATION_SETTINGS_CHANGED notification type */ - } data; -} _mali_uk_wait_for_notification_s; - -/** @brief Arguments for _mali_ukk_post_notification() - * - * Posts the specified notification to the notification queue for this application. - * This is used to send a quit message to the callback thread. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - _mali_uk_notification_type type; /**< [in] Type of notification to post */ -} _mali_uk_post_notification_s; - -/** @} */ /* end group _mali_uk_waitfornotification_s */ - -/** @defgroup _mali_uk_getapiversion_s Get API Version - * @{ */ - -/** helpers for Device Driver API version handling */ - -/** @brief Encode a version ID from a 16-bit input - * - * @note the input is assumed to be 16 bits. It must not exceed 16 bits. */ -#define _MAKE_VERSION_ID(x) (((x) << 16UL) | (x)) - -/** @brief Check whether a 32-bit value is likely to be Device Driver API - * version ID. */ -#define _IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF)) - -/** @brief Decode a 16-bit version number from a 32-bit Device Driver API version - * ID */ -#define _GET_VERSION(x) (((x) >> 16UL) & 0xFFFF) - -/** @brief Determine whether two 32-bit encoded version IDs match */ -#define _IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y)))) - -/** - * API version define. - * Indicates the version of the kernel API - * The version is a 16bit integer incremented on each API change. - * The 16bit integer is stored twice in a 32bit integer - * For example, for version 1 the value would be 0x00010001 - */ -#define _MALI_API_VERSION 17 -#define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION) - -/** - * The API version is a 16-bit integer stored in both the lower and upper 16-bits - * of a 32-bit value. The 16-bit API version value is incremented on each API - * change. Version 1 would be 0x00010001. Used in _mali_uk_get_api_version_s. - */ -typedef u32 _mali_uk_api_version; - -/** @brief Arguments for _mali_uk_get_api_version() - * - * The user-side interface version must be written into the version member, - * encoded using _MAKE_VERSION_ID(). It will be compared to the API version of - * the kernel-side interface. - * - * On successful return, the version member will be the API version of the - * kernel-side interface. _MALI_UK_API_VERSION macro defines the current version - * of the API. - * - * The compatible member must be checked to see if the version of the user-side - * interface is compatible with the kernel-side interface, since future versions - * of the interface may be backwards compatible. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - _mali_uk_api_version version; /**< [in,out] API version of user-side interface. */ - int compatible; /**< [out] @c 1 when @version is compatible, @c 0 otherwise */ -} _mali_uk_get_api_version_s; -/** @} */ /* end group _mali_uk_getapiversion_s */ - -/** @defgroup _mali_uk_get_user_settings_s Get user space settings */ - -/** @brief struct to keep the matching values of the user space settings within certain context - * - * Each member of the settings array corresponds to a matching setting in the user space and its value is the value - * of that particular setting. - * - * All settings are given reference to the context pointed to by the ctx pointer. - * - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 settings[_MALI_UK_USER_SETTING_MAX]; /**< [out] The values for all settings */ -} _mali_uk_get_user_settings_s; - -/** @brief struct to hold the value of a particular setting from the user space within a given context - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - _mali_uk_user_setting_t setting; /**< [in] setting to get */ - u32 value; /**< [out] value of setting */ -} _mali_uk_get_user_setting_s; - -/** @} */ /* end group _mali_uk_core */ - - -/** @defgroup _mali_uk_memory U/K Memory - * @{ */ - -/** @brief Arguments for _mali_ukk_init_mem(). */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 mali_address_base; /**< [out] start of MALI address space */ - u32 memory_size; /**< [out] total MALI address space available */ -} _mali_uk_init_mem_s; - -/** @brief Arguments for _mali_ukk_term_mem(). */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ -} _mali_uk_term_mem_s; - -/** Flag for _mali_uk_map_external_mem_s, _mali_uk_attach_ump_mem_s and _mali_uk_attach_dma_buf_s */ -#define _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE (1<<0) - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 phys_addr; /**< [in] physical address */ - u32 size; /**< [in] size */ - u32 mali_address; /**< [in] mali address to map the physical memory to */ - u32 rights; /**< [in] rights necessary for accessing memory */ - u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */ - u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ -} _mali_uk_map_external_mem_s; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ -} _mali_uk_unmap_external_mem_s; - -/** @note This is identical to _mali_uk_map_external_mem_s above, however phys_addr is replaced by memory descriptor */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 mem_fd; /**< [in] Memory descriptor */ - u32 size; /**< [in] size */ - u32 mali_address; /**< [in] mali address to map the physical memory to */ - u32 rights; /**< [in] rights necessary for accessing memory */ - u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */ - u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ -} _mali_uk_attach_dma_buf_s; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 mem_fd; /**< [in] Memory descriptor */ - u32 size; /**< [out] size */ -} _mali_uk_dma_buf_get_size_s; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 cookie; /**< [in] identifier for mapped memory object in kernel space */ -} _mali_uk_release_dma_buf_s; - -/** @note This is identical to _mali_uk_map_external_mem_s above, however phys_addr is replaced by secure_id */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< [in] secure id */ - u32 size; /**< [in] size */ - u32 mali_address; /**< [in] mali address to map the physical memory to */ - u32 rights; /**< [in] rights necessary for accessing memory */ - u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */ - u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ -} _mali_uk_attach_ump_mem_s; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 cookie; /**< [in] identifier for mapped memory object in kernel space */ -} _mali_uk_release_ump_mem_s; - -/** @brief Arguments for _mali_ukk_va_to_mali_pa() - * - * if size is zero or not a multiple of the system's page size, it will be - * rounded up to the next multiple of the page size. This will occur before - * any other use of the size parameter. - * - * if va is not PAGE_SIZE aligned, it will be rounded down to the next page - * boundary. - * - * The range (va) to ((u32)va)+(size-1) inclusive will be checked for physical - * contiguity. - * - * The implementor will check that the entire physical range is allowed to be mapped - * into user-space. - * - * Failure will occur if either of the above are not satisfied. - * - * Otherwise, the physical base address of the range is returned through pa, - * va is updated to be page aligned, and size is updated to be a non-zero - * multiple of the system's pagesize. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *va; /**< [in,out] Virtual address of the start of the range */ - u32 pa; /**< [out] Physical base address of the range */ - u32 size; /**< [in,out] Size of the range, in bytes. */ -} _mali_uk_va_to_mali_pa_s; - - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 size; /**< [out] size of MMU page table information (registers + page tables) */ -} _mali_uk_query_mmu_page_table_dump_size_s; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 size; /**< [in] size of buffer to receive mmu page table information */ - void *buffer; /**< [in,out] buffer to receive mmu page table information */ - u32 register_writes_size; /**< [out] size of MMU register dump */ - u32 *register_writes; /**< [out] pointer within buffer where MMU register dump is stored */ - u32 page_table_dump_size; /**< [out] size of MMU page table dump */ - u32 *page_table_dump; /**< [out] pointer within buffer where MMU page table dump is stored */ -} _mali_uk_dump_mmu_page_table_s; - -/** @} */ /* end group _mali_uk_memory */ - - -/** @addtogroup _mali_uk_pp U/K Fragment Processor - * @{ */ - -/** @brief Arguments for _mali_ukk_get_pp_number_of_cores() - * - * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() - * - Upon successful return from _mali_ukk_get_pp_number_of_cores(), @c number_of_cores - * will contain the number of Fragment Processor cores in the system. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 number_of_cores; /**< [out] number of Fragment Processor cores in the system */ -} _mali_uk_get_pp_number_of_cores_s; - -/** @brief Arguments for _mali_ukk_get_pp_core_version() - * - * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() - * - Upon successful return from _mali_ukk_get_pp_core_version(), @c version contains - * the version that all Fragment Processor cores are compatible with. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - _mali_core_version version; /**< [out] version returned from core, see \ref _mali_core_version */ -} _mali_uk_get_pp_core_version_s; - -/** @} */ /* end group _mali_uk_pp */ - - -/** @addtogroup _mali_uk_gp U/K Vertex Processor - * @{ */ - -/** @brief Arguments for _mali_ukk_get_gp_number_of_cores() - * - * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() - * - Upon successful return from _mali_ukk_get_gp_number_of_cores(), @c number_of_cores - * will contain the number of Vertex Processor cores in the system. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 number_of_cores; /**< [out] number of Vertex Processor cores in the system */ -} _mali_uk_get_gp_number_of_cores_s; - -/** @brief Arguments for _mali_ukk_get_gp_core_version() - * - * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() - * - Upon successful return from _mali_ukk_get_gp_core_version(), @c version contains - * the version that all Vertex Processor cores are compatible with. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - _mali_core_version version; /**< [out] version returned from core, see \ref _mali_core_version */ -} _mali_uk_get_gp_core_version_s; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 limit; /**< [in,out] The desired limit for number of events to record on input, actual limit on output */ -} _mali_uk_profiling_start_s; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 event_id; /**< [in] event id to register (see enum mali_profiling_events for values) */ - u32 data[5]; /**< [in] event specific data */ -} _mali_uk_profiling_add_event_s; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 count; /**< [out] The number of events sampled */ -} _mali_uk_profiling_stop_s; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 index; /**< [in] which index to get (starting at zero) */ - u64 timestamp; /**< [out] timestamp of event */ - u32 event_id; /**< [out] event id of event (see enum mali_profiling_events for values) */ - u32 data[5]; /**< [out] event specific data */ -} _mali_uk_profiling_get_event_s; - -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ -} _mali_uk_profiling_clear_s; - -/** @} */ /* end group _mali_uk_gp */ - - -/** @addtogroup _mali_uk_memory U/K Memory - * @{ */ - -/** @brief Arguments to _mali_ukk_mem_mmap() - * - * Use of the phys_addr member depends on whether the driver is compiled for - * Mali-MMU or nonMMU: - * - in the nonMMU case, this is the physical address of the memory as seen by - * the CPU (which may be a constant offset from that used by Mali) - * - in the MMU case, this is the Mali Virtual base address of the memory to - * allocate, and the particular physical pages used to back the memory are - * entirely determined by _mali_ukk_mem_mmap(). The details of the physical pages - * are not reported to user-space for security reasons. - * - * The cookie member must be stored for use later when freeing the memory by - * calling _mali_ukk_mem_munmap(). In the Mali-MMU case, the cookie is secure. - * - * The ukk_private word must be set to zero when calling from user-space. On - * Kernel-side, the OS implementation of the U/K interface can use it to - * communicate data to the OS implementation of the OSK layer. In particular, - * _mali_ukk_get_big_block() directly calls _mali_ukk_mem_mmap directly, and - * will communicate its own ukk_private word through the ukk_private member - * here. The common code itself will not inspect or modify the ukk_private - * word, and so it may be safely used for whatever purposes necessary to - * integrate Mali Memory handling into the OS. - * - * The uku_private member is currently reserved for use by the user-side - * implementation of the U/K interface. Its value must be zero. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; /**< [out] Returns user-space virtual address for the mapping */ - u32 size; /**< [in] Size of the requested mapping */ - u32 phys_addr; /**< [in] Physical address - could be offset, depending on caller+callee convention */ - u32 cookie; /**< [out] Returns a cookie for use in munmap calls */ - void *uku_private; /**< [in] User-side Private word used by U/K interface */ - void *ukk_private; /**< [in] Kernel-side Private word used by U/K interface */ - mali_memory_cache_settings cache_settings; /**< [in] Option to set special cache flags, tuning L2 efficency */ -} _mali_uk_mem_mmap_s; - -/** @brief Arguments to _mali_ukk_mem_munmap() - * - * The cookie and mapping members must be that returned from the same previous - * call to _mali_ukk_mem_mmap(). The size member must correspond to cookie - * and mapping - that is, it must be the value originally supplied to a call to - * _mali_ukk_mem_mmap that returned the values of mapping and cookie. - * - * An error will be returned if an attempt is made to unmap only part of the - * originally obtained range, or to unmap more than was originally obtained. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; /**< [in] The mapping returned from mmap call */ - u32 size; /**< [in] The size passed to mmap call */ - u32 cookie; /**< [in] Cookie from mmap call */ -} _mali_uk_mem_munmap_s; -/** @} */ /* end group _mali_uk_memory */ - -/** @defgroup _mali_uk_vsync U/K VSYNC Wait Reporting Module - * @{ */ - -/** @brief VSYNC events - * - * These events are reported when DDK starts to wait for vsync and when the - * vsync has occured and the DDK can continue on the next frame. - */ -typedef enum _mali_uk_vsync_event -{ - _MALI_UK_VSYNC_EVENT_BEGIN_WAIT = 0, - _MALI_UK_VSYNC_EVENT_END_WAIT -} _mali_uk_vsync_event; - -/** @brief Arguments to _mali_ukk_vsync_event() - * - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - _mali_uk_vsync_event event; /**< [in] VSYNCH event type */ -} _mali_uk_vsync_event_report_s; - -/** @} */ /* end group _mali_uk_vsync */ - -/** @defgroup _mali_uk_sw_counters_report U/K Software Counter Reporting - * @{ */ - -/** @brief Software counter values - * - * Values recorded for each of the software counters during a single renderpass. - */ -typedef struct -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32* counters; /**< [in] The array of counter values */ - u32 num_counters; /**< [in] The number of elements in counters array */ -} _mali_uk_sw_counters_report_s; - -/** @} */ /* end group _mali_uk_sw_counters_report */ - -/** @} */ /* end group u_k_api */ - -/** @} */ /* end group uddapi */ - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_UTGARD_UK_TYPES_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/license/gpl/mali_kernel_license.h b/drivers/media/video/samsung/mali/linux/license/gpl/mali_kernel_license.h deleted file mode 100644 index 52bb5e0..0000000 --- a/drivers/media/video/samsung/mali/linux/license/gpl/mali_kernel_license.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_kernel_license.h - * Defines for the macro MODULE_LICENSE. - */ - -#ifndef __MALI_KERNEL_LICENSE_H__ -#define __MALI_KERNEL_LICENSE_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define MALI_KERNEL_LINUX_LICENSE "GPL" -#define MALI_LICENSE_IS_GPL 1 - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_KERNEL_LICENSE_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_dma_buf.c b/drivers/media/video/samsung/mali/linux/mali_dma_buf.c deleted file mode 100644 index 4dd711f..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_dma_buf.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include /* file system operations */ -#include /* user space access */ -#include -#include -#include - -#include "mali_ukk.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_kernel_linux.h" - -#include "mali_kernel_memory_engine.h" -#include "mali_memory.h" - -#include "mali_kernel_sysfs.h" - - -struct mali_dma_buf_attachment { - struct dma_buf *buf; - struct dma_buf_attachment *attachment; - struct sg_table *sgt; - _mali_osk_atomic_t ref; - struct rb_node rb_node; -}; - -static struct rb_root mali_dma_bufs = RB_ROOT; -static DEFINE_SPINLOCK(mali_dma_bufs_lock); - -static inline struct mali_dma_buf_attachment *mali_dma_buf_lookup(struct rb_root *root, struct dma_buf *target) -{ - struct rb_node *node = root->rb_node; - struct mali_dma_buf_attachment *res; - - spin_lock(&mali_dma_bufs_lock); - while (node) - { - res = rb_entry(node, struct mali_dma_buf_attachment, rb_node); - - if (target < res->buf) node = node->rb_left; - else if (target > res->buf) node = node->rb_right; - else - { - _mali_osk_atomic_inc(&res->ref); - spin_unlock(&mali_dma_bufs_lock); - return res; - } - } - spin_unlock(&mali_dma_bufs_lock); - - return NULL; -} - -static void mali_dma_buf_add(struct rb_root *root, struct mali_dma_buf_attachment *new) -{ - struct rb_node **node = &root->rb_node; - struct rb_node *parent = NULL; - struct mali_dma_buf_attachment *res; - - spin_lock(&mali_dma_bufs_lock); - while (*node) - { - parent = *node; - res = rb_entry(*node, struct mali_dma_buf_attachment, rb_node); - - if (new->buf < res->buf) node = &(*node)->rb_left; - else node = &(*node)->rb_right; - } - - rb_link_node(&new->rb_node, parent, node); - rb_insert_color(&new->rb_node, &mali_dma_bufs); - - spin_unlock(&mali_dma_bufs_lock); - - return; -} - - -static void mali_dma_buf_release(void *ctx, void *handle) -{ - struct mali_dma_buf_attachment *mem; - u32 ref; - - mem = (struct mali_dma_buf_attachment *)handle; - - MALI_DEBUG_ASSERT_POINTER(mem); - MALI_DEBUG_ASSERT_POINTER(mem->attachment); - MALI_DEBUG_ASSERT_POINTER(mem->buf); - - spin_lock(&mali_dma_bufs_lock); - ref = _mali_osk_atomic_dec_return(&mem->ref); - - MALI_DEBUG_ASSERT(ref >= 0); - - if (0 == ref) - { - rb_erase(&mem->rb_node, &mali_dma_bufs); - spin_unlock(&mali_dma_bufs_lock); - - MALI_DEBUG_ASSERT(0 == _mali_osk_atomic_read(&mem->ref)); - - dma_buf_unmap_attachment(mem->attachment, mem->sgt, DMA_BIDIRECTIONAL); - - dma_buf_detach(mem->buf, mem->attachment); - dma_buf_put(mem->buf); - - _mali_osk_free(mem); - } - else - { - spin_unlock(&mali_dma_bufs_lock); - } -} - -/* Callback from memory engine which will map into Mali virtual address space */ -static mali_physical_memory_allocation_result mali_dma_buf_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) -{ - struct mali_session_data *session; - struct mali_page_directory *pagedir; - struct mali_dma_buf_attachment *mem; - struct scatterlist *sg; - int i; - u32 virt; - - MALI_DEBUG_ASSERT_POINTER(ctx); - MALI_DEBUG_ASSERT_POINTER(engine); - MALI_DEBUG_ASSERT_POINTER(descriptor); - MALI_DEBUG_ASSERT_POINTER(offset); - MALI_DEBUG_ASSERT_POINTER(alloc_info); - - /* Mapping dma-buf with an offset is not supported. */ - MALI_DEBUG_ASSERT(0 == *offset); - - virt = descriptor->mali_address; - session = (struct mali_session_data *)descriptor->mali_addr_mapping_info; - pagedir = mali_session_get_page_directory(session); - - MALI_DEBUG_ASSERT_POINTER(session); - - mem = (struct mali_dma_buf_attachment *)ctx; - - MALI_DEBUG_ASSERT_POINTER(mem); - - mem->sgt = dma_buf_map_attachment(mem->attachment, DMA_BIDIRECTIONAL); - if (IS_ERR_OR_NULL(mem->sgt)) - { - MALI_PRINT_ERROR(("Failed to map dma-buf attachment\n")); - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - - for_each_sg(mem->sgt->sgl, sg, mem->sgt->nents, i) - { - u32 size = sg_dma_len(sg); - dma_addr_t phys = sg_dma_address(sg); - - /* sg must be page aligned. */ - MALI_DEBUG_ASSERT(0 == size % MALI_MMU_PAGE_SIZE); - - mali_mmu_pagedir_update(pagedir, virt, phys, size, MALI_CACHE_STANDARD); - - virt += size; - *offset += size; - } - - if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) - { - u32 guard_phys; - MALI_DEBUG_PRINT(7, ("Mapping in extra guard page\n")); - - guard_phys = sg_dma_address(mem->sgt->sgl); - mali_mmu_pagedir_update(mali_session_get_page_directory(session), virt, guard_phys, MALI_MMU_PAGE_SIZE, MALI_CACHE_STANDARD); - } - - MALI_DEBUG_ASSERT(*offset == descriptor->size); - - alloc_info->ctx = NULL; - alloc_info->handle = mem; - alloc_info->next = NULL; - alloc_info->release = mali_dma_buf_release; - - return MALI_MEM_ALLOC_FINISHED; -} - -int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *user_arg) -{ - mali_physical_memory_allocator external_memory_allocator; - struct dma_buf *buf; - struct mali_dma_buf_attachment *mem; - _mali_uk_attach_dma_buf_s args; - mali_memory_allocation *descriptor; - int md; - int fd; - - /* Get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if (0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_attach_dma_buf_s))) - { - return -EFAULT; - } - - - fd = args.mem_fd; - - buf = dma_buf_get(fd); - if (IS_ERR_OR_NULL(buf)) - { - MALI_DEBUG_PRINT(2, ("Failed to get dma-buf from fd: %d\n", fd)); - return PTR_RET(buf); - } - - /* Currently, mapping of the full buffer are supported. */ - if (args.size != buf->size) - { - MALI_DEBUG_PRINT(2, ("dma-buf size doesn't match mapping size.\n")); - dma_buf_put(buf); - return -EINVAL; - } - - - mem = mali_dma_buf_lookup(&mali_dma_bufs, buf); - if (NULL == mem) - { - /* dma-buf is not already attached to Mali */ - mem = _mali_osk_calloc(1, sizeof(struct mali_dma_buf_attachment)); - if (NULL == mem) - { - MALI_PRINT_ERROR(("Failed to allocate dma-buf tracing struct\n")); - dma_buf_put(mem->buf); - return -ENOMEM; - } - _mali_osk_atomic_init(&mem->ref, 1); - mem->buf = buf; - - mem->attachment = dma_buf_attach(mem->buf, mali_device); - if (NULL == mem->attachment) - { - MALI_DEBUG_PRINT(2, ("Failed to attach to dma-buf %d\n", fd)); - dma_buf_put(mem->buf); - _mali_osk_free(mem); - return -EFAULT; - } - - mali_dma_buf_add(&mali_dma_bufs, mem); - } - else - { - /* dma-buf is already attached to Mali */ - /* Give back the reference we just took, mali_dma_buf_lookup grabbed a new reference for us. */ - dma_buf_put(buf); - } - - /* Map dma-buf into this session's page tables */ - - /* Set up Mali memory descriptor */ - descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); - if (NULL == descriptor) - { - MALI_PRINT_ERROR(("Failed to allocate descriptor dma-buf %d\n", fd)); - mali_dma_buf_release(NULL, mem); - return -ENOMEM; - } - - descriptor->size = args.size; - descriptor->mapping = NULL; - descriptor->mali_address = args.mali_address; - descriptor->mali_addr_mapping_info = (void*)session; - descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ - descriptor->lock = session->memory_lock; - - if (args.flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) - { - descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; - } - _mali_osk_list_init( &descriptor->list ); - - /* Get descriptor mapping for memory. */ - if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &md)) - { - MALI_PRINT_ERROR(("Failed to create descriptor mapping for dma-buf %d\n", fd)); - _mali_osk_free(descriptor); - mali_dma_buf_release(NULL, mem); - return -EFAULT; - } - - external_memory_allocator.allocate = mali_dma_buf_commit; - external_memory_allocator.allocate_page_table_block = NULL; - external_memory_allocator.ctx = mem; - external_memory_allocator.name = "DMA-BUF Memory"; - external_memory_allocator.next = NULL; - - /* Map memory into session's Mali virtual address space. */ - _mali_osk_lock_wait(session->memory_lock, _MALI_OSK_LOCKMODE_RW); - if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(mali_mem_get_memory_engine(), descriptor, &external_memory_allocator, NULL)) - { - _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); - - MALI_PRINT_ERROR(("Failed to map dma-buf %d into Mali address space\n", fd)); - mali_descriptor_mapping_free(session->descriptor_mapping, md); - mali_dma_buf_release(NULL, mem); - return -ENOMEM; - } - _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); - - /* Return stuff to user space */ - if (0 != put_user(md, &user_arg->cookie)) - { - /* Roll back */ - MALI_PRINT_ERROR(("Failed to return descriptor to user space for dma-buf %d\n", fd)); - mali_descriptor_mapping_free(session->descriptor_mapping, md); - mali_dma_buf_release(NULL, mem); - return -EFAULT; - } - - return 0; -} - -int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *user_arg) -{ - _mali_uk_release_dma_buf_s args; - mali_memory_allocation *descriptor; - - /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_release_dma_buf_s)) ) - { - return -EFAULT; - } - - if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session->descriptor_mapping, args.cookie, (void**)&descriptor)) - { - MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release dma-buf\n", args.cookie)); - return -EINVAL; - } - - descriptor = mali_descriptor_mapping_free(session->descriptor_mapping, args.cookie); - - if (NULL != descriptor) - { - _mali_osk_lock_wait( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - /* Will call back to mali_dma_buf_release() which will release the dma-buf attachment. */ - mali_allocation_engine_release_memory(mali_mem_get_memory_engine(), descriptor); - - _mali_osk_lock_signal( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - _mali_osk_free(descriptor); - } - - /* Return the error that _mali_ukk_map_external_ump_mem produced */ - return 0; -} - -int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *user_arg) -{ - _mali_uk_dma_buf_get_size_s args; - int fd; - struct dma_buf *buf; - - /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_dma_buf_get_size_s)) ) - { - return -EFAULT; - } - - /* Do DMA-BUF stuff */ - fd = args.mem_fd; - - buf = dma_buf_get(fd); - if (IS_ERR_OR_NULL(buf)) - { - MALI_DEBUG_PRINT(2, ("Failed to get dma-buf from fd: %d\n", fd)); - return PTR_RET(buf); - } - - if (0 != put_user(buf->size, &user_arg->size)) - { - dma_buf_put(buf); - return -EFAULT; - } - - dma_buf_put(buf); - - return 0; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_dma_buf.h b/drivers/media/video/samsung/mali/linux/mali_dma_buf.h deleted file mode 100644 index ee9a0ed..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_dma_buf.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_DMA_BUF_H__ -#define __MALI_DMA_BUF_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "mali_osk.h" - -int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *arg); -int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *arg); -int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *arg); - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_KERNEL_LINUX_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c deleted file mode 100644 index 233c0ca..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c +++ /dev/null @@ -1,634 +0,0 @@ -/** - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_kernel_linux.c - * Implementation of the Linux device driver entrypoints - */ -#include /* kernel module definitions */ -#include /* file system operations */ -#include /* character device definitions */ -#include /* memory manager definitions */ -#include -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_kernel_core.h" -#include "mali_osk.h" -#include "mali_kernel_linux.h" -#include "mali_ukk.h" -#include "mali_ukk_wrappers.h" -#include "mali_kernel_pm.h" -#include "mali_kernel_sysfs.h" -#include "mali_platform.h" -#include "mali_kernel_license.h" -#include "mali_dma_buf.h" - -/* Streamline support for the Mali driver */ -#if defined(CONFIG_TRACEPOINTS) && MALI_TIMELINE_PROFILING_ENABLED -/* Ask Linux to create the tracepoints */ -#define CREATE_TRACE_POINTS -#include "mali_linux_trace.h" -#endif /* CONFIG_TRACEPOINTS */ - -static _mali_osk_errcode_t initialize_kernel_device(void); -static int initialize_sysfs(void); -static void terminate_kernel_device(void); - - -/* from the __malidrv_build_info.c file that is generated during build */ -extern const char *__malidrv_build_info(void); - -/* Module parameter to control log level */ -int mali_debug_level = 2; -module_param(mali_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(mali_debug_level, "Higher number, more dmesg output"); - -/* By default the module uses any available major, but it's possible to set it at load time to a specific number */ -#if MALI_MAJOR_PREDEFINE -int mali_major = 244; -#else -int mali_major = 0; -#endif -module_param(mali_major, int, S_IRUGO); /* r--r--r-- */ -MODULE_PARM_DESC(mali_major, "Device major number"); - -module_param(mali_hang_check_interval, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); -MODULE_PARM_DESC(mali_hang_check_interval, "Interval at which to check for progress after the hw watchdog has been triggered"); - -module_param(mali_max_job_runtime, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); -MODULE_PARM_DESC(mali_max_job_runtime, "Maximum allowed job runtime in msecs.\nJobs will be killed after this no matter what"); - -extern int mali_l2_max_reads; -module_param(mali_l2_max_reads, int, S_IRUSR | S_IRGRP | S_IROTH); -MODULE_PARM_DESC(mali_l2_max_reads, "Maximum reads for Mali L2 cache"); - -#if MALI_TIMELINE_PROFILING_ENABLED -extern int mali_boot_profiling; -module_param(mali_boot_profiling, int, S_IRUSR | S_IRGRP | S_IROTH); -MODULE_PARM_DESC(mali_boot_profiling, "Start profiling as a part of Mali driver initialization"); -#endif - -/* Export symbols from common code: mali_user_settings.c */ -#include "mali_user_settings_db.h" -EXPORT_SYMBOL(mali_set_user_setting); -EXPORT_SYMBOL(mali_get_user_setting); -#if MALI_DVFS_ENABLED -extern int mali_dvfs_control; -module_param(mali_dvfs_control, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(mali_dvfs_control, "Mali Current DVFS"); -#if defined(CONFIG_CPU_EXYNOS4210) -#else -extern int step0_clk; -module_param(step0_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step0_clk, "Mali Current step0_clk"); -#ifdef DEBUG -extern int step0_vol; -module_param(step0_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step0_vol, "Mali Current step0_vol"); -#endif - -#if (MALI_DVFS_STEPS > 1) -extern int step1_clk; -module_param(step1_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step1_clk, "Mali Current step1_clk"); - -extern int step0_up; -module_param(step0_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step0_up, "Mali Current step0_up"); - -extern int step1_down; -module_param(step1_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step1_down, "Mali Current step1_down"); -#ifdef DEBUG -extern int step1_vol; -module_param(step1_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step1_vol, "Mali Current step1_vol"); -#endif - -#if (MALI_DVFS_STEPS > 2) -extern int step2_clk; -module_param(step2_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step2_clk, "Mali Current step2_clk"); - -extern int step1_up; -module_param(step1_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step1_up, "Mali Current step1_up"); - -extern int step2_down; -module_param(step2_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step2_down, "Mali Current step2_down"); -#ifdef DEBUG -extern int step2_vol; -module_param(step2_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step2_vol, "Mali Current step2_vol"); -#endif - -#if (MALI_DVFS_STEPS > 3) -extern int step3_clk; -module_param(step3_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step3_clk, "Mali Current step3_clk"); - -extern int step2_up; -module_param(step2_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step2_up, "Mali Current step2_up"); - -extern int step3_down; -module_param(step3_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step3_down, "Mali Current step3_down"); -#ifdef DEBUG -extern int step3_vol; -module_param(step3_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step3_vol, "Mali Current step3_vol"); -#endif -#endif -#endif -#endif -#endif - -extern int mali_gpu_clk; -module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ -MODULE_PARM_DESC(mali_gpu_clk, "Mali Current Clock"); - -extern int mali_gpu_vol; -module_param(mali_gpu_vol, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ -MODULE_PARM_DESC(mali_gpu_vol, "Mali Current Voltage"); - -extern int gpu_power_state; -module_param(gpu_power_state, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ -MODULE_PARM_DESC(gpu_power_state, "Mali Power State"); -#endif - - -static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */ - -/* the mali device */ -static struct mali_dev device; - - -static int mali_open(struct inode *inode, struct file *filp); -static int mali_release(struct inode *inode, struct file *filp); -#ifdef HAVE_UNLOCKED_IOCTL -static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -#else -static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -#endif - -static int mali_mmap(struct file * filp, struct vm_area_struct * vma); - -/* Linux char file operations provided by the Mali module */ -struct file_operations mali_fops = -{ - .owner = THIS_MODULE, - .open = mali_open, - .release = mali_release, -#ifdef HAVE_UNLOCKED_IOCTL - .unlocked_ioctl = mali_ioctl, -#else - .ioctl = mali_ioctl, -#endif - .mmap = mali_mmap -}; - - -int mali_driver_init(void) -{ - int ret = 0; - - MALI_DEBUG_PRINT(2, ("\n")); - MALI_DEBUG_PRINT(2, ("Inserting Mali v%d device driver. \n",_MALI_API_VERSION)); - MALI_DEBUG_PRINT(2, ("Compiled: %s, time: %s.\n", __DATE__, __TIME__)); - MALI_DEBUG_PRINT(2, ("Driver revision: %s\n", SVN_REV_STRING)); - - ret = _mali_dev_platform_register(); - if (0 != ret) goto platform_register_failed; - ret = map_errcode(initialize_kernel_device()); - if (0 != ret) goto initialize_kernel_device_failed; - - ret = map_errcode(mali_platform_init()); - if (0 != ret) goto platform_init_failed; - - mali_osk_low_level_mem_init(); - - ret = map_errcode(mali_initialize_subsystems()); - if (0 != ret) goto initialize_subsystems_failed; - - ret = initialize_sysfs(); - if (0 != ret) goto initialize_sysfs_failed; - - MALI_PRINT(("Mali device driver loaded\n")); - - return 0; /* Success */ - - /* Error handling */ -initialize_sysfs_failed: - mali_terminate_subsystems(); -initialize_subsystems_failed: - mali_osk_low_level_mem_term(); - mali_platform_deinit(); -platform_init_failed: - terminate_kernel_device(); -initialize_kernel_device_failed: - _mali_dev_platform_unregister(); -platform_register_failed: - return ret; -} - -void mali_driver_exit(void) -{ - MALI_DEBUG_PRINT(2, ("\n")); - MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n",_MALI_API_VERSION)); - - /* No need to terminate sysfs, this will be done automatically along with device termination */ - - mali_terminate_subsystems(); - - mali_osk_low_level_mem_term(); - - mali_platform_deinit(); - - terminate_kernel_device(); - _mali_dev_platform_unregister(); - -#if MALI_LICENSE_IS_GPL - /* @@@@ clean up the work queues! This should not be terminated here, since it isn't inited in the function above! */ - flush_workqueue(mali_wq); - destroy_workqueue(mali_wq); - mali_wq = NULL; -#endif - - MALI_PRINT(("Mali device driver unloaded\n")); -} - -static int initialize_kernel_device(void) -{ - int err; - dev_t dev = 0; - if (0 == mali_major) - { - /* auto select a major */ - err = alloc_chrdev_region(&dev, 0/*first minor*/, 1/*count*/, mali_dev_name); - mali_major = MAJOR(dev); - } - else - { - /* use load time defined major number */ - dev = MKDEV(mali_major, 0); - err = register_chrdev_region(dev, 1/*count*/, mali_dev_name); - } - - if (err) - { - goto init_chrdev_err; - } - - memset(&device, 0, sizeof(device)); - - /* initialize our char dev data */ - cdev_init(&device.cdev, &mali_fops); - device.cdev.owner = THIS_MODULE; - device.cdev.ops = &mali_fops; - - /* register char dev with the kernel */ - err = cdev_add(&device.cdev, dev, 1/*count*/); - if (err) - { - goto init_cdev_err; - } - - /* Success! */ - return 0; - -init_cdev_err: - unregister_chrdev_region(dev, 1/*count*/); -init_chrdev_err: - return err; -} - -static int initialize_sysfs(void) -{ - dev_t dev = MKDEV(mali_major, 0); - return mali_sysfs_register(&device, dev, mali_dev_name); -} - -static void terminate_kernel_device(void) -{ - dev_t dev = MKDEV(mali_major, 0); - - mali_sysfs_unregister(&device, dev, mali_dev_name); - - /* unregister char device */ - cdev_del(&device.cdev); - /* free major */ - unregister_chrdev_region(dev, 1/*count*/); - return; -} - -/** @note munmap handler is done by vma close handler */ -static int mali_mmap(struct file * filp, struct vm_area_struct * vma) -{ - struct mali_session_data * session_data; - _mali_uk_mem_mmap_s args = {0, }; - - session_data = (struct mali_session_data *)filp->private_data; - if (NULL == session_data) - { - MALI_PRINT_ERROR(("mmap called without any session data available\n")); - return -EFAULT; - } - - MALI_DEBUG_PRINT(4, ("MMap() handler: start=0x%08X, phys=0x%08X, size=0x%08X vma->flags 0x%08x\n", (unsigned int)vma->vm_start, (unsigned int)(vma->vm_pgoff << PAGE_SHIFT), (unsigned int)(vma->vm_end - vma->vm_start), vma->vm_flags)); - - /* Re-pack the arguments that mmap() packed for us */ - args.ctx = session_data; - args.phys_addr = vma->vm_pgoff << PAGE_SHIFT; - args.size = vma->vm_end - vma->vm_start; - args.ukk_private = vma; - - if ( VM_SHARED== (VM_SHARED & vma->vm_flags)) - { - args.cache_settings = MALI_CACHE_STANDARD ; - MALI_DEBUG_PRINT(3,("Allocate - Standard - Size: %d kb\n", args.size/1024)); - } - else - { - args.cache_settings = MALI_CACHE_GP_READ_ALLOCATE; - MALI_DEBUG_PRINT(3,("Allocate - GP Cached - Size: %d kb\n", args.size/1024)); - } - /* Setting it equal to VM_SHARED and not Private, which would have made the later io_remap fail for MALI_CACHE_GP_READ_ALLOCATE */ - vma->vm_flags = 0x000000fb; - - /* Call the common mmap handler */ - MALI_CHECK(_MALI_OSK_ERR_OK ==_mali_ukk_mem_mmap( &args ), -EFAULT); - - return 0; -} - -static int mali_open(struct inode *inode, struct file *filp) -{ - struct mali_session_data * session_data; - _mali_osk_errcode_t err; - - /* input validation */ - if (0 != MINOR(inode->i_rdev)) return -ENODEV; - - /* allocated struct to track this session */ - err = _mali_ukk_open((void **)&session_data); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - /* initialize file pointer */ - filp->f_pos = 0; - - /* link in our session data */ - filp->private_data = (void*)session_data; - - return 0; -} - -static int mali_release(struct inode *inode, struct file *filp) -{ - _mali_osk_errcode_t err; - - /* input validation */ - if (0 != MINOR(inode->i_rdev)) return -ENODEV; - - err = _mali_ukk_close((void **)&filp->private_data); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - return 0; -} - -int map_errcode( _mali_osk_errcode_t err ) -{ - switch(err) - { - case _MALI_OSK_ERR_OK : return 0; - case _MALI_OSK_ERR_FAULT: return -EFAULT; - case _MALI_OSK_ERR_INVALID_FUNC: return -ENOTTY; - case _MALI_OSK_ERR_INVALID_ARGS: return -EINVAL; - case _MALI_OSK_ERR_NOMEM: return -ENOMEM; - case _MALI_OSK_ERR_TIMEOUT: return -ETIMEDOUT; - case _MALI_OSK_ERR_RESTARTSYSCALL: return -ERESTARTSYS; - case _MALI_OSK_ERR_ITEM_NOT_FOUND: return -ENOENT; - default: return -EFAULT; - } -} - -#ifdef HAVE_UNLOCKED_IOCTL -static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -#else -static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -#endif -{ - int err; - struct mali_session_data *session_data; - -#ifndef HAVE_UNLOCKED_IOCTL - /* inode not used */ - (void)inode; -#endif - - MALI_DEBUG_PRINT(7, ("Ioctl received 0x%08X 0x%08lX\n", cmd, arg)); - - session_data = (struct mali_session_data *)filp->private_data; - if (NULL == session_data) - { - MALI_DEBUG_PRINT(7, ("filp->private_data was NULL\n")); - return -ENOTTY; - } - - if (NULL == (void *)arg) - { - MALI_DEBUG_PRINT(7, ("arg was NULL\n")); - return -ENOTTY; - } - - switch(cmd) - { - case MALI_IOC_WAIT_FOR_NOTIFICATION: - err = wait_for_notification_wrapper(session_data, (_mali_uk_wait_for_notification_s __user *)arg); - break; - - case MALI_IOC_GET_API_VERSION: - err = get_api_version_wrapper(session_data, (_mali_uk_get_api_version_s __user *)arg); - break; - - case MALI_IOC_POST_NOTIFICATION: - err = post_notification_wrapper(session_data, (_mali_uk_post_notification_s __user *)arg); - break; - - case MALI_IOC_GET_USER_SETTINGS: - err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg); - break; - -#if MALI_TIMELINE_PROFILING_ENABLED - case MALI_IOC_PROFILING_START: - err = profiling_start_wrapper(session_data, (_mali_uk_profiling_start_s __user *)arg); - break; - - case MALI_IOC_PROFILING_ADD_EVENT: - err = profiling_add_event_wrapper(session_data, (_mali_uk_profiling_add_event_s __user *)arg); - break; - - case MALI_IOC_PROFILING_STOP: - err = profiling_stop_wrapper(session_data, (_mali_uk_profiling_stop_s __user *)arg); - break; - - case MALI_IOC_PROFILING_GET_EVENT: - err = profiling_get_event_wrapper(session_data, (_mali_uk_profiling_get_event_s __user *)arg); - break; - - case MALI_IOC_PROFILING_CLEAR: - err = profiling_clear_wrapper(session_data, (_mali_uk_profiling_clear_s __user *)arg); - break; - - case MALI_IOC_PROFILING_GET_CONFIG: - /* Deprecated: still compatible with get_user_settings */ - err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg); - break; - - case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: - err = profiling_report_sw_counters_wrapper(session_data, (_mali_uk_sw_counters_report_s __user *)arg); - break; - -#else - - case MALI_IOC_PROFILING_START: /* FALL-THROUGH */ - case MALI_IOC_PROFILING_ADD_EVENT: /* FALL-THROUGH */ - case MALI_IOC_PROFILING_STOP: /* FALL-THROUGH */ - case MALI_IOC_PROFILING_GET_EVENT: /* FALL-THROUGH */ - case MALI_IOC_PROFILING_CLEAR: /* FALL-THROUGH */ - case MALI_IOC_PROFILING_GET_CONFIG: /* FALL-THROUGH */ - case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: /* FALL-THROUGH */ - MALI_DEBUG_PRINT(2, ("Profiling not supported\n")); - err = -ENOTTY; - break; - -#endif - - case MALI_IOC_MEM_INIT: - err = mem_init_wrapper(session_data, (_mali_uk_init_mem_s __user *)arg); - break; - - case MALI_IOC_MEM_TERM: - err = mem_term_wrapper(session_data, (_mali_uk_term_mem_s __user *)arg); - break; - - case MALI_IOC_MEM_MAP_EXT: - err = mem_map_ext_wrapper(session_data, (_mali_uk_map_external_mem_s __user *)arg); - break; - - case MALI_IOC_MEM_UNMAP_EXT: - err = mem_unmap_ext_wrapper(session_data, (_mali_uk_unmap_external_mem_s __user *)arg); - break; - - case MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE: - err = mem_query_mmu_page_table_dump_size_wrapper(session_data, (_mali_uk_query_mmu_page_table_dump_size_s __user *)arg); - break; - - case MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE: - err = mem_dump_mmu_page_table_wrapper(session_data, (_mali_uk_dump_mmu_page_table_s __user *)arg); - break; - -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 - - case MALI_IOC_MEM_ATTACH_UMP: - err = mem_attach_ump_wrapper(session_data, (_mali_uk_attach_ump_mem_s __user *)arg); - break; - - case MALI_IOC_MEM_RELEASE_UMP: - err = mem_release_ump_wrapper(session_data, (_mali_uk_release_ump_mem_s __user *)arg); - break; - -#else - - case MALI_IOC_MEM_ATTACH_UMP: - case MALI_IOC_MEM_RELEASE_UMP: /* FALL-THROUGH */ - MALI_DEBUG_PRINT(2, ("UMP not supported\n")); - err = -ENOTTY; - break; -#endif - -#ifdef CONFIG_DMA_SHARED_BUFFER - case MALI_IOC_MEM_ATTACH_DMA_BUF: - err = mali_attach_dma_buf(session_data, (_mali_uk_attach_dma_buf_s __user *)arg); - break; - - case MALI_IOC_MEM_RELEASE_DMA_BUF: - err = mali_release_dma_buf(session_data, (_mali_uk_release_dma_buf_s __user *)arg); - break; - - case MALI_IOC_MEM_DMA_BUF_GET_SIZE: - err = mali_dma_buf_get_size(session_data, (_mali_uk_dma_buf_get_size_s __user *)arg); - break; -#else - - case MALI_IOC_MEM_DMA_BUF_GET_SIZE: /* FALL-THROUGH */ - MALI_DEBUG_PRINT(2, ("DMA-BUF not supported\n")); - err = -ENOTTY; - break; -#endif - - case MALI_IOC_PP_START_JOB: - err = pp_start_job_wrapper(session_data, (_mali_uk_pp_start_job_s __user *)arg); - break; - - case MALI_IOC_PP_NUMBER_OF_CORES_GET: - err = pp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_pp_number_of_cores_s __user *)arg); - break; - - case MALI_IOC_PP_CORE_VERSION_GET: - err = pp_get_core_version_wrapper(session_data, (_mali_uk_get_pp_core_version_s __user *)arg); - break; - - case MALI_IOC_PP_DISABLE_WB: - err = pp_disable_wb_wrapper(session_data, (_mali_uk_pp_disable_wb_s __user *)arg); - break; - - case MALI_IOC_GP2_START_JOB: - err = gp_start_job_wrapper(session_data, (_mali_uk_gp_start_job_s __user *)arg); - break; - - case MALI_IOC_GP2_NUMBER_OF_CORES_GET: - err = gp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_gp_number_of_cores_s __user *)arg); - break; - - case MALI_IOC_GP2_CORE_VERSION_GET: - err = gp_get_core_version_wrapper(session_data, (_mali_uk_get_gp_core_version_s __user *)arg); - break; - - case MALI_IOC_GP2_SUSPEND_RESPONSE: - err = gp_suspend_response_wrapper(session_data, (_mali_uk_gp_suspend_response_s __user *)arg); - break; - - case MALI_IOC_VSYNC_EVENT_REPORT: - err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg); - break; - - case MALI_IOC_MEM_GET_BIG_BLOCK: /* Fallthrough */ - case MALI_IOC_MEM_FREE_BIG_BLOCK: - MALI_PRINT_ERROR(("Non-MMU mode is no longer supported.\n")); - err = -ENOTTY; - break; - - default: - MALI_DEBUG_PRINT(2, ("No handler for ioctl 0x%08X 0x%08lX\n", cmd, arg)); - err = -ENOTTY; - }; - - return err; -} - - -module_init(mali_driver_init); -module_exit(mali_driver_exit); - -MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE); -MODULE_AUTHOR("ARM Ltd."); -MODULE_VERSION(SVN_REV_STRING); diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h deleted file mode 100644 index 22dc9a4..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_KERNEL_LINUX_H__ -#define __MALI_KERNEL_LINUX_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include /* character device definitions */ -#include "mali_kernel_license.h" -#include "mali_osk.h" - -struct mali_dev -{ - struct cdev cdev; -#if MALI_LICENSE_IS_GPL - struct class * mali_class; -#endif -}; - -#if MALI_LICENSE_IS_GPL -/* Defined in mali_osk_irq.h */ -extern struct workqueue_struct * mali_wq; -#endif - -void mali_osk_low_level_mem_init(void); -void mali_osk_low_level_mem_term(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_KERNEL_LINUX_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c deleted file mode 100644 index 4639d55..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c +++ /dev/null @@ -1,268 +0,0 @@ -/** - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_kernel_pm.c - * Linux Power Management integration - */ - -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_PM_RUNTIME -#include -#endif -#include "mali_osk.h" -#include "mali_uk_types.h" -#include "mali_kernel_common.h" -#include "mali_kernel_license.h" -#include "mali_linux_pm.h" -#include "mali_pm.h" -#include "mali_platform.h" - -#if ! MALI_LICENSE_IS_GPL -#undef CONFIG_PM_RUNTIME -#endif - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -extern void set_mali_parent_power_domain(struct platform_device* dev); -#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */ -static int mali_probe(struct platform_device *pdev); -static int mali_remove(struct platform_device *pdev); - -#ifdef CONFIG_PM_RUNTIME -static int mali_runtime_suspend(struct device *dev); -static int mali_runtime_resume(struct device *dev); -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) -static int mali_os_suspend(struct platform_device *pdev, pm_message_t state); -static int mali_os_resume(struct platform_device *pdev); -#else -static int mali_os_suspend(struct device *dev); -static int mali_os_resume(struct device *dev); -#endif - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) -static const struct dev_pm_ops mali_dev_pm_ops = -{ -#ifdef CONFIG_PM_RUNTIME - .runtime_suspend = mali_runtime_suspend, - .runtime_resume = mali_runtime_resume, - .runtime_idle = NULL, -#else - .suspend = mali_os_suspend, - .resume = mali_os_resume, -#endif - .freeze = mali_os_suspend, - .poweroff = mali_os_suspend, - .thaw = mali_os_resume, - .restore = mali_os_resume, -}; -#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) -struct pm_ext_ops mali_ext_pm_operations = -{ - .base = - { - .freeze = mali_os_suspend, - .thaw = mali_os_resume, - .poweroff = mali_os_suspend, - .restore = mali_os_resume, - }, -}; -#endif - - -static struct platform_driver mali_plat_driver = -{ - .probe = mali_probe, - .remove = mali_remove, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) - .suspend = mali_os_suspend, - .resume = mali_os_resume, - .pm = &mali_ext_pm_operations, -#endif - - .driver = - { - .name = "mali_dev", - .owner = THIS_MODULE, -#if MALI_LICENSE_IS_GPL - .bus = &platform_bus_type, -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) - .pm = &mali_dev_pm_ops, -#endif - }, -}; - -#ifdef CONFIG_PM_RUNTIME -static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy); - -static struct notifier_block mali_pwr_notif_block = -{ - .notifier_call = mali_pwr_suspend_notifier -}; -#endif - -/** This function is called when platform device is unregistered. This function - * is necessary when the platform device is unregistered. - */ -static void _mali_release_pm(struct device *device) -{ -} -struct platform_device mali_gpu_device = -{ - .name = "mali_dev", - .id = 0, - .dev.release = _mali_release_pm -}; - -/** This function is called when the device is probed */ -static int mali_probe(struct platform_device *pdev) -{ - return 0; -} - -static int mali_remove(struct platform_device *pdev) -{ -#ifdef CONFIG_PM_RUNTIME - pm_runtime_disable(&pdev->dev); -#endif - return 0; -} - -#ifdef CONFIG_PM_RUNTIME -static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy) -{ - switch (event) - { - case PM_SUSPEND_PREPARE: - MALI_DEBUG_PRINT(2, ("mali_pwr_suspend_notifier(PM_SUSPEND_PREPARE) called\n")); - mali_pm_os_suspend(); - break; - case PM_POST_SUSPEND: - MALI_DEBUG_PRINT(2, ("mali_pwr_suspend_notifier(PM_SUSPEND_PREPARE) called\n")); - mali_pm_os_resume(); - break; - default: - break; - } - return 0; -} -#endif - - -#ifdef CONFIG_PM_RUNTIME - -static int mali_runtime_suspend(struct device *dev) -{ - MALI_DEBUG_PRINT(3, ("mali_runtime_suspend() called\n")); - mali_pm_runtime_suspend(); - return 0; /* all ok */ -} - -static int mali_runtime_resume(struct device *dev) -{ - MALI_DEBUG_PRINT(3, ("mali_runtime_resume() called\n")); - mali_pm_runtime_resume(); - return 0; /* all ok */ -} - -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) - -static int mali_os_suspend(struct platform_device *pdev, pm_message_t state) -{ - MALI_DEBUG_PRINT(3, ("mali_os_suspend(old) called\n")); - mali_pm_os_suspend(); - return 0; /* all ok */ -} - -static int mali_os_resume(struct platform_device *pdev) -{ - MALI_DEBUG_PRINT(3, ("mali_os_resume(old) called\n")); - mali_pm_os_resume(); - return 0; /* all ok */ -} - -#else - -static int mali_os_suspend(struct device *dev) -{ - MALI_DEBUG_PRINT(3, ("mali_os_suspend(new) called\n")); - mali_pm_os_suspend(); - return 0; /* all ok */ -} - -static int mali_os_resume(struct device *dev) -{ - MALI_DEBUG_PRINT(3, ("mali_os_resume(new) called\n")); - mali_pm_os_resume(); - return 0; /* all ok */ -} - -#endif - -/** This function is called when Mali GPU device is initialized - */ -int _mali_dev_platform_register(void) -{ - int err; - -#ifdef CONFIG_PM_RUNTIME - set_mali_parent_power_domain((void *)&mali_gpu_device); -#endif - -#ifdef CONFIG_PM_RUNTIME - err = register_pm_notifier(&mali_pwr_notif_block); - if (err) - { - return err; - } -#endif - -#if MALI_LICENSE_IS_GPL - err = platform_device_register(&mali_gpu_device); - if (!err) - { - err = platform_driver_register(&mali_plat_driver); - if (err) - { -#ifdef CONFIG_PM_RUNTIME - unregister_pm_notifier(&mali_pwr_notif_block); -#endif - platform_device_unregister(&mali_gpu_device); - } - } -#endif - - return err; -} - -/** This function is called when Mali GPU device is unloaded - */ -void _mali_dev_platform_unregister(void) -{ -#ifdef CONFIG_PM_RUNTIME - unregister_pm_notifier(&mali_pwr_notif_block); -#endif - -#if MALI_LICENSE_IS_GPL - platform_driver_unregister(&mali_plat_driver); - platform_device_unregister(&mali_gpu_device); -#endif -} - diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h deleted file mode 100644 index 6ef7270..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_KERNEL_PM_H__ -#define __MALI_KERNEL_PM_H__ - -int _mali_dev_platform_register(void); -void _mali_dev_platform_unregister(void); - -#endif /* __MALI_KERNEL_PM_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c deleted file mode 100644 index e2dc17b..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c +++ /dev/null @@ -1,1280 +0,0 @@ -/** - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -/** - * @file mali_kernel_sysfs.c - * Implementation of some sysfs data exports - */ - -#include -#include -#include -#include -#include "mali_kernel_license.h" -#include "mali_kernel_common.h" -#include "mali_kernel_linux.h" -#include "mali_ukk.h" - -#if MALI_LICENSE_IS_GPL - -#include -#include -#include -#include -#include "mali_kernel_sysfs.h" -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED -#include -#include "mali_osk_profiling.h" -#endif -#include "mali_pm.h" -#include "mali_cluster.h" -#include "mali_group.h" -#include "mali_gp.h" -#include "mali_pp.h" -#include "mali_l2_cache.h" -#include "mali_hw_core.h" -#include "mali_kernel_core.h" -#include "mali_user_settings_db.h" -#include "mali_device_pause_resume.h" - -#define POWER_BUFFER_SIZE 3 - -struct device *mali_device; -static struct dentry *mali_debugfs_dir = NULL; - -typedef enum -{ - _MALI_DEVICE_SUSPEND, - _MALI_DEVICE_RESUME, - _MALI_DEVICE_DVFS_PAUSE, - _MALI_DEVICE_DVFS_RESUME, - _MALI_MAX_EVENTS -} _mali_device_debug_power_events; - -static const char* const mali_power_events[_MALI_MAX_EVENTS] = { - [_MALI_DEVICE_SUSPEND] = "suspend", - [_MALI_DEVICE_RESUME] = "resume", - [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause", - [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume", -}; - -static u32 virtual_power_status_register=0; -static char pwr_buf[POWER_BUFFER_SIZE]; - -static int open_copy_private_data(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - -static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) -{ - char buf[64]; - int r; - u32 val; - struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data; - - if (0 == src_id) - { - val = mali_gp_core_get_counter_src0(gp_core); - } - else - { - val = mali_gp_core_get_counter_src1(gp_core); - } - - if (MALI_HW_CORE_NO_COUNTER == val) - { - r = sprintf(buf, "-1\n"); - } - else - { - r = sprintf(buf, "%u\n", val); - } - return simple_read_from_buffer(ubuf, cnt, gpos, buf, r); -} - -static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) -{ - struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data; - char buf[64]; - long val; - int ret; - - if (cnt >= sizeof(buf)) - { - return -EINVAL; - } - - if (copy_from_user(&buf, ubuf, cnt)) - { - return -EFAULT; - } - - buf[cnt] = 0; - - ret = strict_strtol(buf, 10, &val); - if (ret < 0) - { - return ret; - } - - if (val < 0) - { - /* any negative input will disable counter */ - val = MALI_HW_CORE_NO_COUNTER; - } - - if (0 == src_id) - { - if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val)) - { - return 0; - } - } - else - { - if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val)) - { - return 0; - } - } - - *gpos += cnt; - return cnt; -} - -static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) -{ - char buf[64]; - long val; - int ret; - u32 ci; - struct mali_cluster *cluster; - - if (cnt >= sizeof(buf)) - { - return -EINVAL; - } - - if (copy_from_user(&buf, ubuf, cnt)) - { - return -EFAULT; - } - - buf[cnt] = 0; - - ret = strict_strtol(buf, 10, &val); - if (ret < 0) - { - return ret; - } - - if (val < 0) - { - /* any negative input will disable counter */ - val = MALI_HW_CORE_NO_COUNTER; - } - - ci = 0; - cluster = mali_cluster_get_global_cluster(ci); - while (NULL != cluster) - { - u32 gi = 0; - struct mali_group *group = mali_cluster_get_group(cluster, gi); - while (NULL != group) - { - struct mali_gp_core *gp_core = mali_group_get_gp_core(group); - if (NULL != gp_core) - { - if (0 == src_id) - { - if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val)) - { - return 0; - } - } - else - { - if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val)) - { - return 0; - } - } - } - - /* try next group */ - gi++; - group = mali_cluster_get_group(cluster, gi); - } - - /* try next cluster */ - ci++; - cluster = mali_cluster_get_global_cluster(ci); - } - - *gpos += cnt; - return cnt; -} - -static ssize_t gp_gpx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos) -{ - return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 0); -} - -static ssize_t gp_gpx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos) -{ - return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 1); -} - -static ssize_t gp_gpx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) -{ - return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 0); -} - -static ssize_t gp_gpx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) -{ - return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 1); -} - -static ssize_t gp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) -{ - return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 0); -} - -static ssize_t gp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) -{ - return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 1); -} - -static const struct file_operations gp_gpx_counter_src0_fops = { - .owner = THIS_MODULE, - .open = open_copy_private_data, - .read = gp_gpx_counter_src0_read, - .write = gp_gpx_counter_src0_write, -}; - -static const struct file_operations gp_gpx_counter_src1_fops = { - .owner = THIS_MODULE, - .open = open_copy_private_data, - .read = gp_gpx_counter_src1_read, - .write = gp_gpx_counter_src1_write, -}; - -static const struct file_operations gp_all_counter_src0_fops = { - .owner = THIS_MODULE, - .write = gp_all_counter_src0_write, -}; - -static const struct file_operations gp_all_counter_src1_fops = { - .owner = THIS_MODULE, - .write = gp_all_counter_src1_write, -}; - -static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) -{ - char buf[64]; - int r; - u32 val; - struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data; - - if (0 == src_id) - { - val = mali_pp_core_get_counter_src0(pp_core); - } - else - { - val = mali_pp_core_get_counter_src1(pp_core); - } - - if (MALI_HW_CORE_NO_COUNTER == val) - { - r = sprintf(buf, "-1\n"); - } - else - { - r = sprintf(buf, "%u\n", val); - } - return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); -} - -static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) -{ - struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data; - char buf[64]; - long val; - int ret; - - if (cnt >= sizeof(buf)) - { - return -EINVAL; - } - - if (copy_from_user(&buf, ubuf, cnt)) - { - return -EFAULT; - } - - buf[cnt] = 0; - - ret = strict_strtol(buf, 10, &val); - if (ret < 0) - { - return ret; - } - - if (val < 0) - { - /* any negative input will disable counter */ - val = MALI_HW_CORE_NO_COUNTER; - } - - if (0 == src_id) - { - if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val)) - { - return 0; - } - } - else - { - if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val)) - { - return 0; - } - } - - *ppos += cnt; - return cnt; -} - -static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) -{ - char buf[64]; - long val; - int ret; - u32 ci; - struct mali_cluster *cluster; - - if (cnt >= sizeof(buf)) - { - return -EINVAL; - } - - if (copy_from_user(&buf, ubuf, cnt)) - { - return -EFAULT; - } - - buf[cnt] = 0; - - ret = strict_strtol(buf, 10, &val); - if (ret < 0) - { - return ret; - } - - if (val < 0) - { - /* any negative input will disable counter */ - val = MALI_HW_CORE_NO_COUNTER; - } - - ci = 0; - cluster = mali_cluster_get_global_cluster(ci); - while (NULL != cluster) - { - u32 gi = 0; - struct mali_group *group = mali_cluster_get_group(cluster, gi); - while (NULL != group) - { - struct mali_pp_core *pp_core = mali_group_get_pp_core(group); - if (NULL != pp_core) - { - if (0 == src_id) - { - if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val)) - { - return 0; - } - } - else - { - if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val)) - { - return 0; - } - } - } - - /* try next group */ - gi++; - group = mali_cluster_get_group(cluster, gi); - } - - /* try next cluster */ - ci++; - cluster = mali_cluster_get_global_cluster(ci); - } - - *ppos += cnt; - return cnt; -} - -static ssize_t pp_ppx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 0); -} - -static ssize_t pp_ppx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 1); -} - -static ssize_t pp_ppx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 0); -} - -static ssize_t pp_ppx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 1); -} - -static ssize_t pp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0); -} - -static ssize_t pp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1); -} - -static const struct file_operations pp_ppx_counter_src0_fops = { - .owner = THIS_MODULE, - .open = open_copy_private_data, - .read = pp_ppx_counter_src0_read, - .write = pp_ppx_counter_src0_write, -}; - -static const struct file_operations pp_ppx_counter_src1_fops = { - .owner = THIS_MODULE, - .open = open_copy_private_data, - .read = pp_ppx_counter_src1_read, - .write = pp_ppx_counter_src1_write, -}; - -static const struct file_operations pp_all_counter_src0_fops = { - .owner = THIS_MODULE, - .write = pp_all_counter_src0_write, -}; - -static const struct file_operations pp_all_counter_src1_fops = { - .owner = THIS_MODULE, - .write = pp_all_counter_src1_write, -}; - - - - - - -static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) -{ - char buf[64]; - int r; - u32 val; - struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data; - - if (0 == src_id) - { - val = mali_l2_cache_core_get_counter_src0(l2_core); - } - else - { - val = mali_l2_cache_core_get_counter_src1(l2_core); - } - - if (MALI_HW_CORE_NO_COUNTER == val) - { - r = sprintf(buf, "-1\n"); - } - else - { - r = sprintf(buf, "%u\n", val); - } - return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); -} - -static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) -{ - struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data; - char buf[64]; - long val; - int ret; - - if (cnt >= sizeof(buf)) - { - return -EINVAL; - } - - if (copy_from_user(&buf, ubuf, cnt)) - { - return -EFAULT; - } - - buf[cnt] = 0; - - ret = strict_strtol(buf, 10, &val); - if (ret < 0) - { - return ret; - } - - if (val < 0) - { - /* any negative input will disable counter */ - val = MALI_HW_CORE_NO_COUNTER; - } - - if (0 == src_id) - { - if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_core, (u32)val)) - { - return 0; - } - } - else - { - if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_core, (u32)val)) - { - return 0; - } - } - - *ppos += cnt; - return cnt; -} - -static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) -{ - char buf[64]; - long val; - int ret; - u32 l2_id; - struct mali_l2_cache_core *l2_cache; - - if (cnt >= sizeof(buf)) - { - return -EINVAL; - } - - if (copy_from_user(&buf, ubuf, cnt)) - { - return -EFAULT; - } - - buf[cnt] = 0; - - ret = strict_strtol(buf, 10, &val); - if (ret < 0) - { - return ret; - } - - if (val < 0) - { - /* any negative input will disable counter */ - val = MALI_HW_CORE_NO_COUNTER; - } - - l2_id = 0; - l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); - while (NULL != l2_cache) - { - if (0 == src_id) - { - if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_cache, (u32)val)) - { - return 0; - } - } - else - { - if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_cache, (u32)val)) - { - return 0; - } - } - - /* try next L2 */ - l2_id++; - l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); - } - - *ppos += cnt; - return cnt; -} - -static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0); -} - -static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1); -} - -static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0); -} - -static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1); -} - -static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0); -} - -static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1); -} - -static const struct file_operations l2_l2x_counter_src0_fops = { - .owner = THIS_MODULE, - .open = open_copy_private_data, - .read = l2_l2x_counter_src0_read, - .write = l2_l2x_counter_src0_write, -}; - -static const struct file_operations l2_l2x_counter_src1_fops = { - .owner = THIS_MODULE, - .open = open_copy_private_data, - .read = l2_l2x_counter_src1_read, - .write = l2_l2x_counter_src1_write, -}; - -static const struct file_operations l2_all_counter_src0_fops = { - .owner = THIS_MODULE, - .write = l2_all_counter_src0_write, -}; - -static const struct file_operations l2_all_counter_src1_fops = { - .owner = THIS_MODULE, - .write = l2_all_counter_src1_write, -}; - -static ssize_t power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - - memset(pwr_buf,0,POWER_BUFFER_SIZE); - virtual_power_status_register = 0; - if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND]))) - { - mali_pm_os_suspend(); - /* @@@@ assuming currently suspend is successful later on to tune as per previous*/ - virtual_power_status_register =1; - - } - else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME]))) - { - mali_pm_os_resume(); - - /* @@@@ assuming currently resume is successful later on to tune as per previous */ - virtual_power_status_register = 1; - } - else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE]))) - { - mali_bool power_on; - mali_dev_pause(&power_on); - if (!power_on) - { - virtual_power_status_register = 2; - mali_dev_resume(); - } - else - { - /* @@@@ assuming currently resume is successful later on to tune as per previous */ - virtual_power_status_register =1; - } - } - else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME]))) - { - mali_dev_resume(); - /* @@@@ assuming currently resume is successful later on to tune as per previous */ - virtual_power_status_register = 1; - - } - *ppos += cnt; - sprintf(pwr_buf, "%d",virtual_power_status_register); - return cnt; -} - -static ssize_t power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return simple_read_from_buffer(ubuf, cnt, ppos, pwr_buf, POWER_BUFFER_SIZE); -} - -static loff_t power_events_seek(struct file *file, loff_t offset, int orig) -{ - file->f_pos = offset; - return 0; -} - -static const struct file_operations power_events_fops = { - .owner = THIS_MODULE, - .read = power_events_read, - .write = power_events_write, - .llseek = power_events_seek, -}; - - -#if MALI_STATE_TRACKING -static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v) -{ - u32 len = 0; - u32 size; - char *buf; - - size = seq_get_buf(seq_file, &buf); - - if(!size) - { - return -ENOMEM; - } - - /* Create the internal state dump. */ - len = snprintf(buf+len, size-len, "Mali device driver %s\n", SVN_REV_STRING); - len += snprintf(buf+len, size-len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE); - - len += _mali_kernel_core_dump_state(buf + len, size - len); - - seq_commit(seq_file, len); - - return 0; -} - -static int mali_seq_internal_state_open(struct inode *inode, struct file *file) -{ - return single_open(file, mali_seq_internal_state_show, NULL); -} - -static const struct file_operations mali_seq_internal_state_fops = { - .owner = THIS_MODULE, - .open = mali_seq_internal_state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* MALI_STATE_TRACKING */ - - -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED -static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) -{ - char buf[64]; - int r; - - r = sprintf(buf, "%u\n", _mali_osk_profiling_is_recording() ? 1 : 0); - return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); -} - -static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - char buf[64]; - unsigned long val; - int ret; - - if (cnt >= sizeof(buf)) - { - return -EINVAL; - } - - if (copy_from_user(&buf, ubuf, cnt)) - { - return -EFAULT; - } - - buf[cnt] = 0; - - ret = strict_strtoul(buf, 10, &val); - if (ret < 0) - { - return ret; - } - - if (val != 0) - { - u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */ - - /* check if we are already recording */ - if (MALI_TRUE == _mali_osk_profiling_is_recording()) - { - MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n")); - return -EFAULT; - } - - /* check if we need to clear out an old recording first */ - if (MALI_TRUE == _mali_osk_profiling_have_recording()) - { - if (_MALI_OSK_ERR_OK != _mali_osk_profiling_clear()) - { - MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n")); - return -EFAULT; - } - } - - /* start recording profiling data */ - if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit)) - { - MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n")); - return -EFAULT; - } - - MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit)); - } - else - { - /* stop recording profiling data */ - u32 count = 0; - if (_MALI_OSK_ERR_OK != _mali_osk_profiling_stop(&count)) - { - MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n")); - return -EFAULT; - } - - MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count)); - } - - *ppos += cnt; - return cnt; -} - -static const struct file_operations profiling_record_fops = { - .owner = THIS_MODULE, - .read = profiling_record_read, - .write = profiling_record_write, -}; - -static void *profiling_events_start(struct seq_file *s, loff_t *pos) -{ - loff_t *spos; - - /* check if we have data avaiable */ - if (MALI_TRUE != _mali_osk_profiling_have_recording()) - { - return NULL; - } - - spos = kmalloc(sizeof(loff_t), GFP_KERNEL); - if (NULL == spos) - { - return NULL; - } - - *spos = *pos; - return spos; -} - -static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos) -{ - loff_t *spos = v; - - /* check if we have data avaiable */ - if (MALI_TRUE != _mali_osk_profiling_have_recording()) - { - return NULL; - } - - /* check if the next entry actually is avaiable */ - if (_mali_osk_profiling_get_count() <= (u32)(*spos + 1)) - { - return NULL; - } - - *pos = ++*spos; - return spos; -} - -static void profiling_events_stop(struct seq_file *s, void *v) -{ - kfree(v); -} - -static int profiling_events_show(struct seq_file *seq_file, void *v) -{ - loff_t *spos = v; - u32 index; - u64 timestamp; - u32 event_id; - u32 data[5]; - - index = (u32)*spos; - - /* Retrieve all events */ - if (_MALI_OSK_ERR_OK == _mali_osk_profiling_get_event(index, ×tamp, &event_id, data)) - { - seq_printf(seq_file, "%llu %u %u %u %u %u %u\n", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]); - return 0; - } - - return 0; -} - -static const struct seq_operations profiling_events_seq_ops = { - .start = profiling_events_start, - .next = profiling_events_next, - .stop = profiling_events_stop, - .show = profiling_events_show -}; - -static int profiling_events_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &profiling_events_seq_ops); -} - -static const struct file_operations profiling_events_fops = { - .owner = THIS_MODULE, - .open = profiling_events_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; -#endif - -static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) -{ - char buf[64]; - size_t r; - u32 mem = _mali_ukk_report_memory_usage(); - - r = snprintf(buf, 64, "%u\n", mem); - return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); -} - -static const struct file_operations memory_usage_fops = { - .owner = THIS_MODULE, - .read = memory_used_read, -}; - - -static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - unsigned long val; - int ret; - _mali_uk_user_setting_t setting; - char buf[32]; - - cnt = min(cnt, sizeof(buf) - 1); - if (copy_from_user(buf, ubuf, cnt)) - { - return -EFAULT; - } - buf[cnt] = '\0'; - - ret = strict_strtoul(buf, 10, &val); - if (0 != ret) - { - return ret; - } - - /* Update setting */ - setting = (_mali_uk_user_setting_t)(filp->private_data); - mali_set_user_setting(setting, val); - - *ppos += cnt; - return cnt; -} - -static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) -{ - char buf[64]; - size_t r; - u32 value; - _mali_uk_user_setting_t setting; - - setting = (_mali_uk_user_setting_t)(filp->private_data); - value = mali_get_user_setting(setting); - - r = snprintf(buf, 64, "%u\n", value); - return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); -} - -static const struct file_operations user_settings_fops = { - .owner = THIS_MODULE, - .open = open_copy_private_data, - .read = user_settings_read, - .write = user_settings_write, -}; - -static int mali_sysfs_user_settings_register(void) -{ - struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir); - - if (mali_user_settings_dir != NULL) - { - int i; - for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++) - { - debugfs_create_file(_mali_uk_user_setting_descriptions[i], 0600, mali_user_settings_dir, (void*)i, &user_settings_fops); - } - } - - return 0; -} - -int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name) -{ - int err = 0; - - device->mali_class = class_create(THIS_MODULE, mali_dev_name); - if (IS_ERR(device->mali_class)) - { - err = PTR_ERR(device->mali_class); - goto init_class_err; - } - mali_device = device_create(device->mali_class, NULL, dev, NULL, mali_dev_name); - if (IS_ERR(mali_device)) - { - err = PTR_ERR(mali_device); - goto init_mdev_err; - } - - mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL); - if(ERR_PTR(-ENODEV) == mali_debugfs_dir) - { - /* Debugfs not supported. */ - mali_debugfs_dir = NULL; - } - else - { - if(NULL != mali_debugfs_dir) - { - /* Debugfs directory created successfully; create files now */ - struct dentry *mali_power_dir; - struct dentry *mali_gp_dir; - struct dentry *mali_pp_dir; - struct dentry *mali_l2_dir; -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - struct dentry *mali_profiling_dir; -#endif - - mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir); - if (mali_power_dir != NULL) - { - debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_events_fops); - } - - mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir); - if (mali_gp_dir != NULL) - { - struct dentry *mali_gp_all_dir; - u32 ci; - struct mali_cluster *cluster; - - mali_gp_all_dir = debugfs_create_dir("all", mali_gp_dir); - if (mali_gp_all_dir != NULL) - { - debugfs_create_file("counter_src0", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src0_fops); - debugfs_create_file("counter_src1", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops); - } - - ci = 0; - cluster = mali_cluster_get_global_cluster(ci); - while (NULL != cluster) - { - u32 gi = 0; - struct mali_group *group = mali_cluster_get_group(cluster, gi); - while (NULL != group) - { - struct mali_gp_core *gp_core = mali_group_get_gp_core(group); - if (NULL != gp_core) - { - struct dentry *mali_gp_gpx_dir; - mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir); - if (NULL != mali_gp_gpx_dir) - { - debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops); - debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops); - } - break; /* no need to look for any other GP cores */ - } - - /* try next group */ - gi++; - group = mali_cluster_get_group(cluster, gi); - } - - /* try next cluster */ - ci++; - cluster = mali_cluster_get_global_cluster(ci); - } - } - - mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir); - if (mali_pp_dir != NULL) - { - struct dentry *mali_pp_all_dir; - u32 ci; - struct mali_cluster *cluster; - - mali_pp_all_dir = debugfs_create_dir("all", mali_pp_dir); - if (mali_pp_all_dir != NULL) - { - debugfs_create_file("counter_src0", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src0_fops); - debugfs_create_file("counter_src1", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops); - } - - ci = 0; - cluster = mali_cluster_get_global_cluster(ci); - while (NULL != cluster) - { - u32 gi = 0; - struct mali_group *group = mali_cluster_get_group(cluster, gi); - while (NULL != group) - { - struct mali_pp_core *pp_core = mali_group_get_pp_core(group); - if (NULL != pp_core) - { - char buf[16]; - struct dentry *mali_pp_ppx_dir; - _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core)); - mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir); - if (NULL != mali_pp_ppx_dir) - { - debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops); - debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops); - } - } - - /* try next group */ - gi++; - group = mali_cluster_get_group(cluster, gi); - } - - /* try next cluster */ - ci++; - cluster = mali_cluster_get_global_cluster(ci); - } - } - - mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir); - if (mali_l2_dir != NULL) - { - struct dentry *mali_l2_all_dir; - u32 l2_id; - struct mali_l2_cache_core *l2_cache; - - mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir); - if (mali_l2_all_dir != NULL) - { - debugfs_create_file("counter_src0", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops); - debugfs_create_file("counter_src1", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops); - } - - l2_id = 0; - l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); - while (NULL != l2_cache) - { - char buf[16]; - struct dentry *mali_l2_l2x_dir; - _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id); - mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir); - if (NULL != mali_l2_l2x_dir) - { - debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops); - debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops); - } - - /* try next L2 */ - l2_id++; - l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); - } - } - - debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops); - -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir); - if (mali_profiling_dir != NULL) - { - struct dentry *mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir); - if (mali_profiling_proc_dir != NULL) - { - struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir); - if (mali_profiling_proc_default_dir != NULL) - { - debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void*)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops); - } - } - debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops); - debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops); - } -#endif - -#if MALI_STATE_TRACKING - debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops); -#endif - - if (mali_sysfs_user_settings_register()) - { - /* Failed to create the debugfs entries for the user settings DB. */ - MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n")); - } - } - } - - /* Success! */ - return 0; - - /* Error handling */ -init_mdev_err: - class_destroy(device->mali_class); -init_class_err: - - return err; -} - -int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name) -{ - if(NULL != mali_debugfs_dir) - { - debugfs_remove_recursive(mali_debugfs_dir); - } - device_destroy(device->mali_class, dev); - class_destroy(device->mali_class); - - return 0; -} - -#else - -/* Dummy implementations for non-GPL */ - -int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name) -{ - return 0; -} - -int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name) -{ - return 0; -} - - -#endif diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h deleted file mode 100644 index 24acca9..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_KERNEL_SYSFS_H__ -#define __MALI_KERNEL_SYSFS_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include - -#define MALI_PROC_DIR "driver/mali" - -extern struct device *mali_device; -struct mali_dev; - -int mali_sysfs_register(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name); - -int mali_sysfs_unregister(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name); - - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_KERNEL_LINUX_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_pm.h b/drivers/media/video/samsung/mali/linux/mali_linux_pm.h deleted file mode 100644 index 10f633e..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_linux_pm.h +++ /dev/null @@ -1,50 +0,0 @@ - -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_LINUX_PM_H__ -#define __MALI_LINUX_PM_H__ - -#ifdef CONFIG_PM -/* Number of power states supported for making power up and down */ -typedef enum -{ - _MALI_DEVICE_SUSPEND, /* Suspend */ - _MALI_DEVICE_RESUME, /* Resume */ - _MALI_DEVICE_MAX_POWER_STATES, /* Maximum power states */ -} _mali_device_power_states; - -/* Number of DVFS events */ -typedef enum -{ - _MALI_DVFS_PAUSE_EVENT = _MALI_DEVICE_MAX_POWER_STATES, /* DVFS Pause event */ - _MALI_DVFS_RESUME_EVENT, /* DVFS Resume event */ - _MALI_MAX_DEBUG_OPERATIONS, -} _mali_device_dvfs_events; - -extern _mali_device_power_states mali_device_state; -extern _mali_device_power_states mali_dvfs_device_state; -extern _mali_osk_lock_t *lock; -extern short is_wake_up_needed; -extern int timeout_fired; -extern struct platform_device mali_gpu_device; - -/* dvfs pm thread */ -extern struct task_struct *dvfs_pm_thread; - -/* Power management thread */ -extern struct task_struct *pm_thread; - -int mali_device_suspend(u32 event_id, struct task_struct **pwr_mgmt_thread); -int mali_device_resume(u32 event_id, struct task_struct **pwr_mgmt_thread); -int mali_get_ospmm_thread_state(void); - -#endif /* CONFIG_PM */ -#endif /* __MALI_LINUX_PM_H___ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h b/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h deleted file mode 100644 index 7d811bd..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef __MALI_LINUX_PM_TESTSUITE_H__ -#define __MALI_LINUX_PM_TESTSUITE_H__ - -#if MALI_POWER_MGMT_TEST_SUITE && defined(CONFIG_PM) - -typedef enum -{ - _MALI_DEVICE_PMM_TIMEOUT_EVENT, - _MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS, - _MALI_DEVICE_PMM_REGISTERED_CORES, - _MALI_DEVICE_MAX_PMM_EVENTS - -} _mali_device_pmm_recording_events; - -extern unsigned int mali_timeout_event_recording_on; -extern unsigned int mali_job_scheduling_events_recording_on; -extern unsigned int pwr_mgmt_status_reg; -extern unsigned int is_mali_pmm_testsuite_enabled; -extern unsigned int is_mali_pmu_present; - -#endif /* MALI_POWER_MGMT_TEST_SUITE && defined(CONFIG_PM) */ - -#endif /* __MALI_LINUX_PM_TESTSUITE_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_trace.h b/drivers/media/video/samsung/mali/linux/mali_linux_trace.h deleted file mode 100644 index 5329ba3..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_linux_trace.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if !defined (MALI_LINUX_TRACE_H) || defined (TRACE_HEADER_MULTI_READ) -#define MALI_LINUX_TRACE_H - -#include - -#include -#include - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM mali -#define TRACE_SYSTEM_STRING __stringfy(TRACE_SYSTEM) - -#define TRACE_INCLUDE_PATH . -#define TRACE_INCLUDE_FILE mali_linux_trace - -/** - * Define the tracepoint used to communicate the status of a GPU. Called - * when a GPU turns on or turns off. - * - * @param event_id The type of the event. This parameter is a bitfield - * encoding the type of the event. - * - * @param d0 First data parameter. - * @param d1 Second data parameter. - * @param d2 Third data parameter. - * @param d3 Fourth data parameter. - * @param d4 Fifth data parameter. - */ -TRACE_EVENT(mali_timeline_event, - - TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, - unsigned int d2, unsigned int d3, unsigned int d4), - - TP_ARGS(event_id, d0, d1, d2, d3, d4), - - TP_STRUCT__entry( - __field(unsigned int, event_id) - __field(unsigned int, d0) - __field(unsigned int, d1) - __field(unsigned int, d2) - __field(unsigned int, d3) - __field(unsigned int, d4) - ), - - TP_fast_assign( - __entry->event_id = event_id; - __entry->d0 = d0; - __entry->d1 = d1; - __entry->d2 = d2; - __entry->d3 = d3; - __entry->d4 = d4; - ), - - TP_printk("event=%d", __entry->event_id) -); - -/** - * Define a tracepoint used to regsiter the value of a hardware counter. - * Hardware counters belonging to the vertex or fragment processor are - * reported via this tracepoint each frame, whilst L2 cache hardware - * counters are reported continuously. - * - * @param counter_id The counter ID. - * @param value The value of the counter. - */ -TRACE_EVENT(mali_hw_counter, - - TP_PROTO(unsigned int counter_id, unsigned int value), - - TP_ARGS(counter_id, value), - - TP_STRUCT__entry( - __field(unsigned int, counter_id) - __field(unsigned int, value) - ), - - TP_fast_assign( - __entry->counter_id = counter_id; - ), - - TP_printk("event %d = %d", __entry->counter_id, __entry->value) -); - -/** - * Define a tracepoint used to send a bundle of software counters. - * - * @param counters The bundle of counters. - */ -TRACE_EVENT(mali_sw_counters, - - TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters), - - TP_ARGS(pid, tid, surface_id, counters), - - TP_STRUCT__entry( - __field(pid_t, pid) - __field(pid_t, tid) - __field(void *, surface_id) - __field(unsigned int *, counters) - ), - - TP_fast_assign( - __entry->pid = pid; - __entry->tid = tid; - __entry->surface_id = surface_id; - __entry->counters = counters; - ), - - TP_printk("counters were %s", __entry->counters == NULL? "NULL" : "not NULL") -); - -#endif /* MALI_LINUX_TRACE_H */ - -/* This part must exist outside the header guard. */ -#include - diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_atomics.c b/drivers/media/video/samsung/mali/linux/mali_osk_atomics.c deleted file mode 100644 index 32f8e6b..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_atomics.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_atomics.c - * Implementation of the OS abstraction layer for the kernel device driver - */ - -#include "mali_osk.h" -#include -#include "mali_kernel_common.h" - -void _mali_osk_atomic_dec( _mali_osk_atomic_t *atom ) -{ - atomic_dec((atomic_t *)&atom->u.val); -} - -u32 _mali_osk_atomic_dec_return( _mali_osk_atomic_t *atom ) -{ - return atomic_dec_return((atomic_t *)&atom->u.val); -} - -void _mali_osk_atomic_inc( _mali_osk_atomic_t *atom ) -{ - atomic_inc((atomic_t *)&atom->u.val); -} - -u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom ) -{ - return atomic_inc_return((atomic_t *)&atom->u.val); -} - -_mali_osk_errcode_t _mali_osk_atomic_init( _mali_osk_atomic_t *atom, u32 val ) -{ - MALI_CHECK_NON_NULL(atom, _MALI_OSK_ERR_INVALID_ARGS); - atomic_set((atomic_t *)&atom->u.val, val); - return _MALI_OSK_ERR_OK; -} - -u32 _mali_osk_atomic_read( _mali_osk_atomic_t *atom ) -{ - return atomic_read((atomic_t *)&atom->u.val); -} - -void _mali_osk_atomic_term( _mali_osk_atomic_t *atom ) -{ - MALI_IGNORE(atom); -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_irq.c b/drivers/media/video/samsung/mali/linux/mali_osk_irq.c deleted file mode 100644 index ddfe564..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_irq.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_irq.c - * Implementation of the OS abstraction layer for the kernel device driver - */ - -#include /* For memory allocation */ -#include -#include - -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_kernel_license.h" -#include "mali_kernel_linux.h" -#include "linux/interrupt.h" - -typedef struct _mali_osk_irq_t_struct -{ - u32 irqnum; - void *data; - _mali_osk_irq_uhandler_t uhandler; - _mali_osk_irq_bhandler_t bhandler; - struct work_struct work_queue_irq_handle; /* Workqueue for the bottom half of the IRQ-handling. This job is activated when this core gets an IRQ.*/ -} mali_osk_irq_object_t; - -#if MALI_LICENSE_IS_GPL -static struct workqueue_struct *pmm_wq = NULL; -struct workqueue_struct *mali_wq = NULL; -#endif - -typedef void (*workqueue_func_t)(void *); -typedef irqreturn_t (*irq_handler_func_t)(int, void *, struct pt_regs *); -static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ); /* , struct pt_regs *regs*/ - -#if defined(INIT_DELAYED_WORK) -static void irq_handler_bottom_half ( struct work_struct *work ); -#else -static void irq_handler_bottom_half ( void * input ); -#endif - -/** - * Linux kernel version has marked SA_SHIRQ as deprecated, IRQF_SHARED should be used. - * This is to handle older kernels which haven't done this swap. - */ -#ifndef IRQF_SHARED -#define IRQF_SHARED SA_SHIRQ -#endif /* IRQF_SHARED */ - -_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, _mali_osk_irq_bhandler_t bhandler, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *data, const char *description ) -{ - mali_osk_irq_object_t *irq_object; - - irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL); - if (NULL == irq_object) return NULL; - -#if MALI_LICENSE_IS_GPL - if (NULL == mali_wq) - { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) - mali_wq = alloc_workqueue("mali", WQ_UNBOUND, 0); -#else - mali_wq = create_workqueue("mali"); -#endif - if(NULL == mali_wq) - { - MALI_PRINT_ERROR(("Unable to create Mali workqueue\n")); - kfree(irq_object); - return NULL; - } - } -#endif - - /* workqueue API changed in 2.6.20, support both versions: */ -#if defined(INIT_DELAYED_WORK) - /* New syntax: INIT_WORK( struct work_struct *work, void (*function)(struct work_struct *)) */ - INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half); -#else - /* Old syntax: INIT_WORK( struct work_struct *work, void (*function)(void *), void *data) */ - INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half, irq_object); -#endif /* defined(INIT_DELAYED_WORK) */ - - if (-1 == irqnum) - { - /* Probe for IRQ */ - if ( (NULL != trigger_func) && (NULL != ack_func) ) - { - unsigned long probe_count = 3; - _mali_osk_errcode_t err; - int irq; - - MALI_DEBUG_PRINT(2, ("Probing for irq\n")); - - do - { - unsigned long mask; - - mask = probe_irq_on(); - trigger_func(data); - - _mali_osk_time_ubusydelay(5); - - irq = probe_irq_off(mask); - err = ack_func(data); - } - while (irq < 0 && (err == _MALI_OSK_ERR_OK) && probe_count--); - - if (irq < 0 || (_MALI_OSK_ERR_OK != err)) irqnum = -1; - else irqnum = irq; - } - else irqnum = -1; /* no probe functions, fault */ - - if (-1 != irqnum) - { - /* found an irq */ - MALI_DEBUG_PRINT(2, ("Found irq %d\n", irqnum)); - } - else - { - MALI_DEBUG_PRINT(2, ("Probe for irq failed\n")); - } - } - - irq_object->irqnum = irqnum; - irq_object->uhandler = uhandler; - irq_object->bhandler = bhandler; - irq_object->data = data; - - /* Is this a real IRQ handler we need? */ - if (irqnum != _MALI_OSK_IRQ_NUMBER_FAKE && irqnum != _MALI_OSK_IRQ_NUMBER_PMM) - { - if (-1 == irqnum) - { - MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description)); - kfree(irq_object); - return NULL; - } - - if (0 != request_irq(irqnum, irq_handler_upper_half, IRQF_SHARED, description, irq_object)) - { - MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description)); - kfree(irq_object); - return NULL; - } - } - -#if MALI_LICENSE_IS_GPL - if ( _MALI_OSK_IRQ_NUMBER_PMM == irqnum ) - { - pmm_wq = create_singlethread_workqueue("mali-pmm-wq"); - } -#endif - - return irq_object; -} - -void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq ) -{ - mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq; -#if MALI_LICENSE_IS_GPL - if ( irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM ) - { - queue_work( pmm_wq,&irq_object->work_queue_irq_handle ); - } - else - { - queue_work(mali_wq, &irq_object->work_queue_irq_handle); - } -#else - schedule_work(&irq_object->work_queue_irq_handle); -#endif -} - -void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq ) -{ -#if MALI_LICENSE_IS_GPL - if (NULL != irq) - { - mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq; - if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM ) - { - flush_workqueue(pmm_wq); - } - else - { - flush_workqueue(mali_wq); - } - } - else - { - flush_workqueue(mali_wq); - } -#endif -} - -void _mali_osk_irq_term( _mali_osk_irq_t *irq ) -{ - mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq; - -#if MALI_LICENSE_IS_GPL - if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM ) - { - flush_workqueue(pmm_wq); - destroy_workqueue(pmm_wq); - } -#endif - free_irq(irq_object->irqnum, irq_object); - kfree(irq_object); - flush_scheduled_work(); -} - - -/** This function is called directly in interrupt context from the OS just after - * the CPU get the hw-irq from mali, or other devices on the same IRQ-channel. - * It is registered one of these function for each mali core. When an interrupt - * arrives this function will be called equal times as registered mali cores. - * That means that we only check one mali core in one function call, and the - * core we check for each turn is given by the \a dev_id variable. - * If we detect an pending interrupt on the given core, we mask the interrupt - * out by settging the core's IRQ_MASK register to zero. - * Then we schedule the mali_core_irq_handler_bottom_half to run as high priority - * work queue job. - */ -static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ) /* , struct pt_regs *regs*/ -{ - mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)dev_id; - - if (irq_object->uhandler(irq_object->data) == _MALI_OSK_ERR_OK) - { - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -/* Is executed when an interrupt occur on one core */ -/* workqueue API changed in 2.6.20, support both versions: */ -#if defined(INIT_DELAYED_WORK) -static void irq_handler_bottom_half ( struct work_struct *work ) -#else -static void irq_handler_bottom_half ( void * input ) -#endif -{ - mali_osk_irq_object_t *irq_object; - -#if defined(INIT_DELAYED_WORK) - irq_object = _MALI_OSK_CONTAINER_OF(work, mali_osk_irq_object_t, work_queue_irq_handle); -#else - if ( NULL == input ) - { - MALI_PRINT_ERROR(("IRQ: Null pointer! Illegal!")); - return; /* Error */ - } - irq_object = (mali_osk_irq_object_t *) input; -#endif - - irq_object->bhandler(irq_object->data); -} - diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_locks.c b/drivers/media/video/samsung/mali/linux/mali_osk_locks.c deleted file mode 100644 index ee857d5..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_locks.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_locks.c - * Implemenation of the OS abstraction layer for the kernel device driver - */ - -/* needed to detect kernel version specific code */ -#include - -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#else /* pre 2.6.26 the file was in the arch specific location */ -#include -#endif - -#include -#include "mali_osk.h" -#include "mali_kernel_common.h" - -/* These are all the locks we implement: */ -typedef enum -{ - _MALI_OSK_INTERNAL_LOCKTYPE_SPIN, /* Mutex, implicitly non-interruptable, use spin_lock/spin_unlock */ - _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ, /* Mutex, IRQ version of spinlock, use spin_lock_irqsave/spin_unlock_irqrestore */ - _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX, /* Interruptable, use up()/down_interruptable() */ - _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT, /* Non-Interruptable, use up()/down() */ - _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW, /* Non-interruptable, Reader/Writer, use {up,down}{read,write}() */ - - /* Linux supports, but we do not support: - * Non-Interruptable Reader/Writer spinlock mutexes - RW optimization will be switched off - */ - - /* Linux does not support: - * One-locks, of any sort - no optimization for this fact will be made. - */ - -} _mali_osk_internal_locktype; - -struct _mali_osk_lock_t_struct -{ - _mali_osk_internal_locktype type; - unsigned long flags; - union - { - spinlock_t spinlock; - struct semaphore sema; - struct rw_semaphore rw_sema; - } obj; - MALI_DEBUG_CODE( - /** original flags for debug checking */ - _mali_osk_lock_flags_t orig_flags; - - /* id of the thread currently holding this lock, 0 if no - * threads hold it. */ - u32 owner; - /* number of owners this lock currently has (can be > 1 if - * taken in R/O mode. */ - u32 nOwners; - /* what mode the lock was taken in */ - _mali_osk_lock_mode_t mode; - ); /* MALI_DEBUG_CODE */ -}; - -_mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial, u32 order ) -{ - _mali_osk_lock_t *lock = NULL; - - /* Validate parameters: */ - /* Flags acceptable */ - MALI_DEBUG_ASSERT( 0 == ( flags & ~(_MALI_OSK_LOCKFLAG_SPINLOCK - | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ - | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE - | _MALI_OSK_LOCKFLAG_READERWRITER - | _MALI_OSK_LOCKFLAG_ORDERED - | _MALI_OSK_LOCKFLAG_ONELOCK )) ); - /* Spinlocks are always non-interruptable */ - MALI_DEBUG_ASSERT( (((flags & _MALI_OSK_LOCKFLAG_SPINLOCK) || (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ)) && (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE)) - || !(flags & _MALI_OSK_LOCKFLAG_SPINLOCK)); - /* Parameter initial SBZ - for future expansion */ - MALI_DEBUG_ASSERT( 0 == initial ); - - lock = kmalloc(sizeof(_mali_osk_lock_t), GFP_KERNEL); - - if ( NULL == lock ) - { - return lock; - } - - /* Determine type of mutex: */ - /* defaults to interruptable mutex if no flags are specified */ - - if ( (flags & _MALI_OSK_LOCKFLAG_SPINLOCK) ) - { - /* Non-interruptable Spinlocks override all others */ - lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_SPIN; - spin_lock_init( &lock->obj.spinlock ); - } - else if ( (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ ) ) - { - lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ; - lock->flags = 0; - spin_lock_init( &lock->obj.spinlock ); - } - else if ( (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE) - && (flags & _MALI_OSK_LOCKFLAG_READERWRITER) ) - { - lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW; - init_rwsem( &lock->obj.rw_sema ); - } - else - { - /* Usual mutex types */ - if ( (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE) ) - { - lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT; - } - else - { - lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX; - } - - /* Initially unlocked */ - sema_init( &lock->obj.sema, 1 ); - } - -#ifdef DEBUG - /* Debug tracking of flags */ - lock->orig_flags = flags; - - /* Debug tracking of lock owner */ - lock->owner = 0; - lock->nOwners = 0; -#endif /* DEBUG */ - - return lock; -} - -#ifdef DEBUG -u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock ) -{ - return lock->owner; -} - -u32 _mali_osk_lock_get_number_owners( _mali_osk_lock_t *lock ) -{ - return lock->nOwners; -} - -u32 _mali_osk_lock_get_mode( _mali_osk_lock_t *lock ) -{ - return lock->mode; -} -#endif /* DEBUG */ - -_mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; - - /* Parameter validation */ - MALI_DEBUG_ASSERT_POINTER( lock ); - - MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode - || _MALI_OSK_LOCKMODE_RO == mode ); - - /* Only allow RO locks when the initial object was a Reader/Writer lock - * Since information is lost on the internal locktype, we use the original - * information, which is only stored when built for DEBUG */ - MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode - || (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) ); - - switch ( lock->type ) - { - case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN: - spin_lock(&lock->obj.spinlock); - break; - case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ: - { - unsigned long tmp_flags; - spin_lock_irqsave(&lock->obj.spinlock, tmp_flags); - lock->flags = tmp_flags; - } - break; - - case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX: - if ( down_interruptible(&lock->obj.sema) ) - { - MALI_PRINT_ERROR(("Can not lock mutex\n")); - err = _MALI_OSK_ERR_RESTARTSYSCALL; - } - break; - - case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT: - down(&lock->obj.sema); - break; - - case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW: - if (mode == _MALI_OSK_LOCKMODE_RO) - { - down_read(&lock->obj.rw_sema); - } - else - { - down_write(&lock->obj.rw_sema); - } - break; - - default: - /* Reaching here indicates a programming error, so you will not get here - * on non-DEBUG builds */ - MALI_DEBUG_PRINT_ERROR( ("Invalid internal lock type: %.8X", lock->type ) ); - break; - } - -#ifdef DEBUG - /* This thread is now the owner of this lock */ - if (_MALI_OSK_ERR_OK == err) - { - if (mode == _MALI_OSK_LOCKMODE_RW) - { - /*MALI_DEBUG_ASSERT(0 == lock->owner);*/ - if (0 != lock->owner) - { - printk(KERN_ERR "%d: ERROR: Lock %p already has owner %d\n", _mali_osk_get_tid(), lock, lock->owner); - dump_stack(); - } - lock->owner = _mali_osk_get_tid(); - lock->mode = mode; - ++lock->nOwners; - } - else /* mode == _MALI_OSK_LOCKMODE_RO */ - { - lock->owner |= _mali_osk_get_tid(); - lock->mode = mode; - ++lock->nOwners; - } - } -#endif - - return err; -} - -void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ) -{ - /* Parameter validation */ - MALI_DEBUG_ASSERT_POINTER( lock ); - - MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode - || _MALI_OSK_LOCKMODE_RO == mode ); - - /* Only allow RO locks when the initial object was a Reader/Writer lock - * Since information is lost on the internal locktype, we use the original - * information, which is only stored when built for DEBUG */ - MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode - || (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) ); - -#ifdef DEBUG - /* make sure the thread releasing the lock actually was the owner */ - if (mode == _MALI_OSK_LOCKMODE_RW) - { - /*MALI_DEBUG_ASSERT(_mali_osk_get_tid() == lock->owner);*/ - if (_mali_osk_get_tid() != lock->owner) - { - printk(KERN_ERR "%d: ERROR: Lock %p owner was %d\n", _mali_osk_get_tid(), lock, lock->owner); - dump_stack(); - } - /* This lock now has no owner */ - lock->owner = 0; - --lock->nOwners; - } - else /* mode == _MALI_OSK_LOCKMODE_RO */ - { - if ((_mali_osk_get_tid() & lock->owner) != _mali_osk_get_tid()) - { - printk(KERN_ERR "%d: ERROR: Not an owner of %p lock.\n", _mali_osk_get_tid(), lock); - dump_stack(); - } - - /* if this is the last thread holding this lock in R/O mode, set owner - * back to 0 */ - if (0 == --lock->nOwners) - { - lock->owner = 0; - } - } -#endif /* DEBUG */ - - switch ( lock->type ) - { - case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN: - spin_unlock(&lock->obj.spinlock); - break; - case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ: - spin_unlock_irqrestore(&lock->obj.spinlock, lock->flags); - break; - - case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX: - /* FALLTHROUGH */ - case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT: - up(&lock->obj.sema); - break; - - case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW: - if (mode == _MALI_OSK_LOCKMODE_RO) - { - up_read(&lock->obj.rw_sema); - } - else - { - up_write(&lock->obj.rw_sema); - } - break; - - default: - /* Reaching here indicates a programming error, so you will not get here - * on non-DEBUG builds */ - MALI_DEBUG_PRINT_ERROR( ("Invalid internal lock type: %.8X", lock->type ) ); - break; - } -} - -void _mali_osk_lock_term( _mali_osk_lock_t *lock ) -{ - /* Parameter validation */ - MALI_DEBUG_ASSERT_POINTER( lock ); - - /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */ - kfree(lock); -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c b/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c deleted file mode 100644 index 02558a0..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_low_level_mem.c - * Implementation of the OS abstraction layer for the kernel device driver - */ - -/* needed to detect kernel version specific code */ -#include - -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) -#include -#endif - -#include "mali_osk.h" -#include "mali_ukk.h" /* required to hook in _mali_ukk_mem_mmap handling */ -#include "mali_kernel_common.h" -#include "mali_kernel_linux.h" - -static void mali_kernel_memory_vma_open(struct vm_area_struct * vma); -static void mali_kernel_memory_vma_close(struct vm_area_struct * vma); - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf); -#else -static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address); -#endif - - -typedef struct mali_vma_usage_tracker -{ - int references; - u32 cookie; -} mali_vma_usage_tracker; - - -/* Linked list structure to hold details of all OS allocations in a particular - * mapping - */ -struct AllocationList -{ - struct AllocationList *next; - u32 offset; - u32 physaddr; -}; - -typedef struct AllocationList AllocationList; - -/* Private structure to store details of a mapping region returned - * from _mali_osk_mem_mapregion_init - */ -struct MappingInfo -{ - struct vm_area_struct *vma; - struct AllocationList *list; - struct AllocationList *tail; -}; - -typedef struct MappingInfo MappingInfo; - - -static u32 _kernel_page_allocate(void); -static void _kernel_page_release(u32 physical_address); -static AllocationList * _allocation_list_item_get(void); -static void _allocation_list_item_release(AllocationList * item); - - -/* Variable declarations */ -static DEFINE_SPINLOCK(allocation_list_spinlock); -static AllocationList * pre_allocated_memory = (AllocationList*) NULL ; -static int pre_allocated_memory_size_current = 0; -#ifdef MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB - static int pre_allocated_memory_size_max = MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB * 1024 * 1024; -#else - static int pre_allocated_memory_size_max = 16 * 1024 * 1024; /* 6 MiB */ -#endif - -static struct vm_operations_struct mali_kernel_vm_ops = -{ - .open = mali_kernel_memory_vma_open, - .close = mali_kernel_memory_vma_close, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - .fault = mali_kernel_memory_cpu_page_fault_handler -#else - .nopfn = mali_kernel_memory_cpu_page_fault_handler -#endif -}; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) -static int mali_mem_shrink(int nr_to_scan, gfp_t gfp_mask) - #else -static int mali_mem_shrink(struct shrinker *shrinker, int nr_to_scan, gfp_t gfp_mask) - #endif -#else -static int mali_mem_shrink(struct shrinker *shrinker, struct shrink_control *sc) -#endif -{ - unsigned long flags; - AllocationList *item; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - int nr = nr_to_scan; -#else - int nr = sc->nr_to_scan; -#endif - - if (0 == nr) - { - return pre_allocated_memory_size_current / PAGE_SIZE; - } - - if (0 == pre_allocated_memory_size_current) - { - /* No pages availble */ - return 0; - } - - if (0 == spin_trylock_irqsave(&allocation_list_spinlock, flags)) - { - /* Not able to lock. */ - return -1; - } - - while (pre_allocated_memory && nr > 0) - { - item = pre_allocated_memory; - pre_allocated_memory = item->next; - - _kernel_page_release(item->physaddr); - _mali_osk_free(item); - - pre_allocated_memory_size_current -= PAGE_SIZE; - --nr; - } - spin_unlock_irqrestore(&allocation_list_spinlock,flags); - - return pre_allocated_memory_size_current / PAGE_SIZE; -} - -struct shrinker mali_mem_shrinker = { - .shrink = mali_mem_shrink, - .seeks = DEFAULT_SEEKS, -}; - -void mali_osk_low_level_mem_init(void) -{ - pre_allocated_memory = (AllocationList*) NULL ; - - register_shrinker(&mali_mem_shrinker); -} - -void mali_osk_low_level_mem_term(void) -{ - unregister_shrinker(&mali_mem_shrinker); - - while ( NULL != pre_allocated_memory ) - { - AllocationList *item; - item = pre_allocated_memory; - pre_allocated_memory = item->next; - _kernel_page_release(item->physaddr); - _mali_osk_free( item ); - } - pre_allocated_memory_size_current = 0; -} - -static u32 _kernel_page_allocate(void) -{ - struct page *new_page; - u32 linux_phys_addr; - - new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD); - - if ( NULL == new_page ) - { - return 0; - } - - /* Ensure page is flushed from CPU caches. */ - linux_phys_addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); - - return linux_phys_addr; -} - -static void _kernel_page_release(u32 physical_address) -{ - struct page *unmap_page; - - #if 1 - dma_unmap_page(NULL, physical_address, PAGE_SIZE, DMA_BIDIRECTIONAL); - #endif - - unmap_page = pfn_to_page( physical_address >> PAGE_SHIFT ); - MALI_DEBUG_ASSERT_POINTER( unmap_page ); - __free_page( unmap_page ); -} - -static AllocationList * _allocation_list_item_get(void) -{ - AllocationList *item = NULL; - unsigned long flags; - - spin_lock_irqsave(&allocation_list_spinlock,flags); - if ( pre_allocated_memory ) - { - item = pre_allocated_memory; - pre_allocated_memory = pre_allocated_memory->next; - pre_allocated_memory_size_current -= PAGE_SIZE; - - spin_unlock_irqrestore(&allocation_list_spinlock,flags); - return item; - } - spin_unlock_irqrestore(&allocation_list_spinlock,flags); - - item = _mali_osk_malloc( sizeof(AllocationList) ); - if ( NULL == item) - { - return NULL; - } - - item->physaddr = _kernel_page_allocate(); - if ( 0 == item->physaddr ) - { - /* Non-fatal error condition, out of memory. Upper levels will handle this. */ - _mali_osk_free( item ); - return NULL; - } - return item; -} - -static void _allocation_list_item_release(AllocationList * item) -{ - unsigned long flags; - spin_lock_irqsave(&allocation_list_spinlock,flags); - if ( pre_allocated_memory_size_current < pre_allocated_memory_size_max) - { - item->next = pre_allocated_memory; - pre_allocated_memory = item; - pre_allocated_memory_size_current += PAGE_SIZE; - spin_unlock_irqrestore(&allocation_list_spinlock,flags); - return; - } - spin_unlock_irqrestore(&allocation_list_spinlock,flags); - - _kernel_page_release(item->physaddr); - _mali_osk_free( item ); -} - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf) -#else -static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address) -#endif -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - void __user * address; - address = vmf->virtual_address; -#endif - /* - * We always fail the call since all memory is pre-faulted when assigned to the process. - * Only the Mali cores can use page faults to extend buffers. - */ - - MALI_DEBUG_PRINT(1, ("Page-fault in Mali memory region caused by the CPU.\n")); - MALI_DEBUG_PRINT(1, ("Tried to access %p (process local virtual address) which is not currently mapped to any Mali memory.\n", (void*)address)); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - return VM_FAULT_SIGBUS; -#else - return NOPFN_SIGBUS; -#endif -} - -static void mali_kernel_memory_vma_open(struct vm_area_struct * vma) -{ - mali_vma_usage_tracker * vma_usage_tracker; - MALI_DEBUG_PRINT(4, ("Open called on vma %p\n", vma)); - - vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data; - vma_usage_tracker->references++; - - return; -} - -static void mali_kernel_memory_vma_close(struct vm_area_struct * vma) -{ - _mali_uk_mem_munmap_s args = {0, }; - mali_memory_allocation * descriptor; - mali_vma_usage_tracker * vma_usage_tracker; - MALI_DEBUG_PRINT(3, ("Close called on vma %p\n", vma)); - - vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data; - - BUG_ON(!vma_usage_tracker); - BUG_ON(0 == vma_usage_tracker->references); - - vma_usage_tracker->references--; - - if (0 != vma_usage_tracker->references) - { - MALI_DEBUG_PRINT(3, ("Ignoring this close, %d references still exists\n", vma_usage_tracker->references)); - return; - } - - /** @note args->context unused, initialized to 0. - * Instead, we use the memory_session from the cookie */ - - descriptor = (mali_memory_allocation *)vma_usage_tracker->cookie; - - args.cookie = (u32)descriptor; - args.mapping = descriptor->mapping; - args.size = descriptor->size; - - _mali_ukk_mem_munmap( &args ); - - /* vma_usage_tracker is free()d by _mali_osk_mem_mapregion_term(). - * In the case of the memory engine, it is called as the release function that has been registered with the engine*/ -} - - -void _mali_osk_mem_barrier( void ) -{ - mb(); -} - -void _mali_osk_write_mem_barrier( void ) -{ - wmb(); -} - -mali_io_address _mali_osk_mem_mapioregion( u32 phys, u32 size, const char *description ) -{ - return (mali_io_address)ioremap_nocache(phys, size); -} - -void _mali_osk_mem_unmapioregion( u32 phys, u32 size, mali_io_address virt ) -{ - iounmap((void*)virt); -} - -mali_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 size ) -{ - void * virt; - MALI_DEBUG_ASSERT_POINTER( phys ); - MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) ); - MALI_DEBUG_ASSERT( 0 != size ); - - /* dma_alloc_* uses a limited region of address space. On most arch/marchs - * 2 to 14 MiB is available. This should be enough for the page tables, which - * currently is the only user of this function. */ - virt = dma_alloc_coherent(NULL, size, phys, GFP_KERNEL | GFP_DMA ); - - MALI_DEBUG_PRINT(3, ("Page table virt: 0x%x = dma_alloc_coherent(size:%d, phys:0x%x, )\n", virt, size, phys)); - - if ( NULL == virt ) - { - MALI_DEBUG_PRINT(5, ("allocioregion: Failed to allocate Pagetable memory, size=0x%.8X\n", size )); - return 0; - } - - MALI_DEBUG_ASSERT( 0 == (*phys & ~_MALI_OSK_CPU_PAGE_MASK) ); - - return (mali_io_address)virt; -} - -void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address virt ) -{ - MALI_DEBUG_ASSERT_POINTER( (void*)virt ); - MALI_DEBUG_ASSERT( 0 != size ); - MALI_DEBUG_ASSERT( 0 == (phys & ( (1 << PAGE_SHIFT) - 1 )) ); - - dma_free_coherent(NULL, size, virt, phys); -} - -_mali_osk_errcode_t inline _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description ) -{ - return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK); -} - -void inline _mali_osk_mem_unreqregion( u32 phys, u32 size ) -{ - release_mem_region(phys, size); -} - -void inline _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val ) -{ - __raw_writel(cpu_to_le32(val),((u8*)addr) + offset); -} - -u32 inline _mali_osk_mem_ioread32( volatile mali_io_address addr, u32 offset ) -{ - return ioread32(((u8*)addr) + offset); -} - -void inline _mali_osk_mem_iowrite32( volatile mali_io_address addr, u32 offset, u32 val ) -{ - iowrite32(val, ((u8*)addr) + offset); -} - -void _mali_osk_cache_flushall( void ) -{ - /** @note Cached memory is not currently supported in this implementation */ -} - -void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size ) -{ - _mali_osk_write_mem_barrier(); -} - -_mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descriptor ) -{ - struct vm_area_struct *vma; - mali_vma_usage_tracker * vma_usage_tracker; - MappingInfo *mappingInfo; - - if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; - - MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); - - vma = (struct vm_area_struct*)descriptor->process_addr_mapping_info; - - if (NULL == vma ) return _MALI_OSK_ERR_FAULT; - - /* Re-write the process_addr_mapping_info */ - mappingInfo = _mali_osk_calloc( 1, sizeof(MappingInfo) ); - - if ( NULL == mappingInfo ) return _MALI_OSK_ERR_FAULT; - - vma_usage_tracker = _mali_osk_calloc( 1, sizeof(mali_vma_usage_tracker) ); - - if (NULL == vma_usage_tracker) - { - MALI_DEBUG_PRINT(2, ("Failed to allocate memory to track memory usage\n")); - _mali_osk_free( mappingInfo ); - return _MALI_OSK_ERR_FAULT; - } - - mappingInfo->vma = vma; - descriptor->process_addr_mapping_info = mappingInfo; - - /* Do the va range allocation - in this case, it was done earlier, so we copy in that information */ - descriptor->mapping = (void __user*)vma->vm_start; - /* list member is already NULL */ - - /* - set some bits which indicate that: - The memory is IO memory, meaning that no paging is to be performed and the memory should not be included in crash dumps - The memory is reserved, meaning that it's present and can never be paged out (see also previous entry) - */ - vma->vm_flags |= VM_IO; - vma->vm_flags |= VM_RESERVED; - vma->vm_flags |= VM_DONTCOPY; - - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - vma->vm_ops = &mali_kernel_vm_ops; /* Operations used on any memory system */ - - vma_usage_tracker->references = 1; /* set initial reference count to be 1 as vma_open won't be called for the first mmap call */ - vma_usage_tracker->cookie = (u32)descriptor; /* cookie for munmap */ - - vma->vm_private_data = vma_usage_tracker; - - return _MALI_OSK_ERR_OK; -} - -void _mali_osk_mem_mapregion_term( mali_memory_allocation * descriptor ) -{ - struct vm_area_struct* vma; - mali_vma_usage_tracker * vma_usage_tracker; - MappingInfo *mappingInfo; - - if (NULL == descriptor) return; - - MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); - - mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; - - MALI_DEBUG_ASSERT_POINTER( mappingInfo ); - - /* Linux does the right thing as part of munmap to remove the mapping - * All that remains is that we remove the vma_usage_tracker setup in init() */ - vma = mappingInfo->vma; - - MALI_DEBUG_ASSERT_POINTER( vma ); - - /* ASSERT that there are no allocations on the list. Unmap should've been - * called on all OS allocations. */ - MALI_DEBUG_ASSERT( NULL == mappingInfo->list ); - - vma_usage_tracker = vma->vm_private_data; - - /* We only get called if mem_mapregion_init succeeded */ - _mali_osk_free(vma_usage_tracker); - - _mali_osk_free( mappingInfo ); - return; -} - -_mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size ) -{ - struct vm_area_struct *vma; - MappingInfo *mappingInfo; - - if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; - - MALI_DEBUG_ASSERT_POINTER( phys_addr ); - - MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); - - MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) ); - - MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK)); - - if (NULL == descriptor->mapping) return _MALI_OSK_ERR_INVALID_ARGS; - - if (size > (descriptor->size - offset)) - { - MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_map: virtual memory area not large enough to map physical 0x%x size %x into area 0x%x at offset 0x%xr\n", - *phys_addr, size, descriptor->mapping, offset)); - return _MALI_OSK_ERR_FAULT; - } - - mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; - - MALI_DEBUG_ASSERT_POINTER( mappingInfo ); - - vma = mappingInfo->vma; - - if (NULL == vma ) return _MALI_OSK_ERR_FAULT; - - MALI_DEBUG_PRINT(7, ("Process map: mapping 0x%08X to process address 0x%08lX length 0x%08X\n", *phys_addr, (long unsigned int)(descriptor->mapping + offset), size)); - - if ( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC == *phys_addr ) - { - _mali_osk_errcode_t ret; - AllocationList *alloc_item; - u32 linux_phys_frame_num; - - alloc_item = _allocation_list_item_get(); - if (NULL == alloc_item) - { - MALI_DEBUG_PRINT(1, ("Failed to allocate list item\n")); - return _MALI_OSK_ERR_NOMEM; - } - - linux_phys_frame_num = alloc_item->physaddr >> PAGE_SHIFT; - - ret = ( remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, linux_phys_frame_num, size, vma->vm_page_prot) ) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK; - - if ( ret != _MALI_OSK_ERR_OK) - { - MALI_PRINT_ERROR(("%s %d could not remap_pfn_range()\n", __FUNCTION__, __LINE__)); - _allocation_list_item_release(alloc_item); - return ret; - } - - /* Put our alloc_item into the list of allocations on success */ - if (NULL == mappingInfo->list) - { - mappingInfo->list = alloc_item; - } - else - { - mappingInfo->tail->next = alloc_item; - } - - mappingInfo->tail = alloc_item; - alloc_item->next = NULL; - alloc_item->offset = offset; - - /* Write out new physical address on success */ - *phys_addr = alloc_item->physaddr; - - return ret; - } - - /* Otherwise, Use the supplied physical address */ - - /* ASSERT that supplied phys_addr is page aligned */ - MALI_DEBUG_ASSERT( 0 == ((*phys_addr) & ~_MALI_OSK_CPU_PAGE_MASK) ); - - return ( remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, *phys_addr >> PAGE_SHIFT, size, vma->vm_page_prot) ) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK; - -} - -void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags ) -{ - MappingInfo *mappingInfo; - - if (NULL == descriptor) return; - - MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); - - MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) ); - - MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK) ); - - if (NULL == descriptor->mapping) return; - - if (size > (descriptor->size - offset)) - { - MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_unmap: virtual memory area not large enough to unmap size %x from area 0x%x at offset 0x%x\n", - size, descriptor->mapping, offset)); - return; - } - mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; - - MALI_DEBUG_ASSERT_POINTER( mappingInfo ); - - if ( 0 != (flags & _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR) ) - { - /* This physical RAM was allocated in _mali_osk_mem_mapregion_map and - * so needs to be unmapped - */ - while (size) - { - /* First find the allocation in the list of allocations */ - AllocationList *alloc = mappingInfo->list; - AllocationList **prev = &(mappingInfo->list); - - while (NULL != alloc && alloc->offset != offset) - { - prev = &(alloc->next); - alloc = alloc->next; - } - if (alloc == NULL) { - MALI_DEBUG_PRINT(1, ("Unmapping memory that isn't mapped\n")); - size -= _MALI_OSK_CPU_PAGE_SIZE; - offset += _MALI_OSK_CPU_PAGE_SIZE; - continue; - } - - *prev = alloc->next; - _allocation_list_item_release(alloc); - - /* Move onto the next allocation */ - size -= _MALI_OSK_CPU_PAGE_SIZE; - offset += _MALI_OSK_CPU_PAGE_SIZE; - } - } - - /* Linux does the right thing as part of munmap to remove the mapping */ - - return; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_mali.c b/drivers/media/video/samsung/mali/linux/mali_osk_mali.c deleted file mode 100644 index 06cb215..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_mali.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_mali.c - * Implementation of the OS abstraction layer which is specific for the Mali kernel device driver - */ -#include -#include -#include - -#include "mali_kernel_common.h" /* MALI_xxx macros */ -#include "mali_osk.h" /* kernel side OS functions */ -#include "mali_uk_types.h" -#include "arch/config.h" /* contains the configuration of the arch we are compiling for */ - -_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources ) -{ - *num_resources = sizeof(arch_configuration) / sizeof(arch_configuration[0]); - *arch_config = arch_configuration; - return _MALI_OSK_ERR_OK; -} - -void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources ) -{ - /* Nothing to do */ -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_math.c b/drivers/media/video/samsung/mali/linux/mali_osk_math.c deleted file mode 100644 index bb25e7d..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_math.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_math.c - * Implementation of the OS abstraction layer for the kernel device driver - */ - -#include "mali_osk.h" -#include - -u32 inline _mali_osk_clz( u32 input ) -{ - return 32-fls(input); -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_memory.c b/drivers/media/video/samsung/mali/linux/mali_osk_memory.c deleted file mode 100644 index 5354e85..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_memory.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_memory.c - * Implementation of the OS abstraction layer for the kernel device driver - */ - -#include "mali_osk.h" -#include -#include - -void inline *_mali_osk_calloc( u32 n, u32 size ) -{ - return kcalloc(n, size, GFP_KERNEL); -} - -void inline *_mali_osk_malloc( u32 size ) -{ - return kmalloc(size, GFP_KERNEL); -} - -void inline _mali_osk_free( void *ptr ) -{ - kfree(ptr); -} - -void inline *_mali_osk_valloc( u32 size ) -{ - return vmalloc(size); -} - -void inline _mali_osk_vfree( void *ptr ) -{ - vfree(ptr); -} - -void inline *_mali_osk_memcpy( void *dst, const void *src, u32 len ) -{ - return memcpy(dst, src, len); -} - -void inline *_mali_osk_memset( void *s, u32 c, u32 n ) -{ - return memset(s, c, n); -} - -mali_bool _mali_osk_mem_check_allocated( u32 max_allocated ) -{ - /* No need to prevent an out-of-memory dialogue appearing on Linux, - * so we always return MALI_TRUE. - */ - return MALI_TRUE; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_misc.c b/drivers/media/video/samsung/mali/linux/mali_osk_misc.c deleted file mode 100644 index ad486db..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_misc.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_misc.c - * Implementation of the OS abstraction layer for the kernel device driver - */ -#include -#include -#include -#include -#include -#include "mali_osk.h" - -void _mali_osk_dbgmsg( const char *fmt, ... ) -{ - va_list args; - va_start(args, fmt); - vprintk(fmt, args); - va_end(args); -} - -u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... ) -{ - int res; - va_list args; - va_start(args, fmt); - - res = vscnprintf(buf, (size_t)size, fmt, args); - - va_end(args); - return res; -} - -void _mali_osk_abort(void) -{ - /* make a simple fault by dereferencing a NULL pointer */ - dump_stack(); - *(int *)0 = 0; -} - -void _mali_osk_break(void) -{ - _mali_osk_abort(); -} - -u32 _mali_osk_get_pid(void) -{ - /* Thread group ID is the process ID on Linux */ - return (u32)current->tgid; -} - -u32 _mali_osk_get_tid(void) -{ - /* pid is actually identifying the thread on Linux */ - return (u32)current->pid; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c deleted file mode 100644 index c14c0d5..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_notification.c - * Implementation of the OS abstraction layer for the kernel device driver - */ - -#include "mali_osk.h" -#include "mali_kernel_common.h" - -/* needed to detect kernel version specific code */ -#include - -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#else /* pre 2.6.26 the file was in the arch specific location */ -#include -#endif - -/** - * Declaration of the notification queue object type - * Contains a linked list of notification pending delivery to user space. - * It also contains a wait queue of exclusive waiters blocked in the ioctl - * When a new notification is posted a single thread is resumed. - */ -struct _mali_osk_notification_queue_t_struct -{ - struct semaphore mutex; /**< Mutex protecting the list */ - wait_queue_head_t receive_queue; /**< Threads waiting for new entries to the queue */ - struct list_head head; /**< List of notifications waiting to be picked up */ -}; - -typedef struct _mali_osk_notification_wrapper_t_struct -{ - struct list_head list; /**< Internal linked list variable */ - _mali_osk_notification_t data; /**< Notification data */ -} _mali_osk_notification_wrapper_t; - -_mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void ) -{ - _mali_osk_notification_queue_t * result; - - result = (_mali_osk_notification_queue_t *)kmalloc(sizeof(_mali_osk_notification_queue_t), GFP_KERNEL); - if (NULL == result) return NULL; - - sema_init(&result->mutex, 1); - init_waitqueue_head(&result->receive_queue); - INIT_LIST_HEAD(&result->head); - - return result; -} - -_mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ) -{ - /* OPT Recycling of notification objects */ - _mali_osk_notification_wrapper_t *notification; - - notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size, - GFP_KERNEL | __GFP_HIGH | __GFP_REPEAT); - if (NULL == notification) - { - MALI_DEBUG_PRINT(1, ("Failed to create a notification object\n")); - return NULL; - } - - /* Init the list */ - INIT_LIST_HEAD(¬ification->list); - - if (0 != size) - { - notification->data.result_buffer = ((u8*)notification) + sizeof(_mali_osk_notification_wrapper_t); - } - else - { - notification->data.result_buffer = NULL; - } - - /* set up the non-allocating fields */ - notification->data.notification_type = type; - notification->data.result_buffer_size = size; - - /* all ok */ - return &(notification->data); -} - -void _mali_osk_notification_delete( _mali_osk_notification_t *object ) -{ - _mali_osk_notification_wrapper_t *notification; - MALI_DEBUG_ASSERT_POINTER( object ); - - notification = container_of( object, _mali_osk_notification_wrapper_t, data ); - - /* Free the container */ - kfree(notification); -} - -void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue ) -{ - MALI_DEBUG_ASSERT_POINTER( queue ); - - /* not much to do, just free the memory */ - kfree(queue); -} - -void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object ) -{ - _mali_osk_notification_wrapper_t *notification; - MALI_DEBUG_ASSERT_POINTER( queue ); - MALI_DEBUG_ASSERT_POINTER( object ); - - notification = container_of( object, _mali_osk_notification_wrapper_t, data ); - - /* lock queue access */ - down(&queue->mutex); - /* add to list */ - list_add_tail(¬ification->list, &queue->head); - /* unlock the queue */ - up(&queue->mutex); - - /* and wake up one possible exclusive waiter */ - wake_up(&queue->receive_queue); -} - -static int _mali_notification_queue_is_empty( _mali_osk_notification_queue_t *queue ) -{ - int ret; - - down(&queue->mutex); - ret = list_empty(&queue->head); - up(&queue->mutex); - return ret; -} - -#if MALI_STATE_TRACKING -mali_bool _mali_osk_notification_queue_is_empty( _mali_osk_notification_queue_t *queue ) -{ - return _mali_notification_queue_is_empty(queue) ? MALI_TRUE : MALI_FALSE; -} -#endif - -_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ) -{ - _mali_osk_errcode_t ret = _MALI_OSK_ERR_ITEM_NOT_FOUND; - _mali_osk_notification_wrapper_t *wrapper_object; - - down(&queue->mutex); - - if (!list_empty(&queue->head)) - { - wrapper_object = list_entry(queue->head.next, _mali_osk_notification_wrapper_t, list); - *result = &(wrapper_object->data); - list_del_init(&wrapper_object->list); - ret = _MALI_OSK_ERR_OK; - } - - up(&queue->mutex); - - return ret; -} - -_mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ) -{ - /* check input */ - MALI_DEBUG_ASSERT_POINTER( queue ); - MALI_DEBUG_ASSERT_POINTER( result ); - - /* default result */ - *result = NULL; - - while (_MALI_OSK_ERR_OK != _mali_osk_notification_queue_dequeue(queue, result)) - { - if (wait_event_interruptible(queue->receive_queue, !_mali_notification_queue_is_empty(queue))) - { - return _MALI_OSK_ERR_RESTARTSYSCALL; - } - } - - return _MALI_OSK_ERR_OK; /* all ok */ -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_pm.c b/drivers/media/video/samsung/mali/linux/mali_osk_pm.c deleted file mode 100644 index 491a603..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_pm.c +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_pm.c - * Implementation of the callback functions from common power management - */ - -#include - -#ifdef CONFIG_PM_RUNTIME -#include -#endif /* CONFIG_PM_RUNTIME */ -#include -#include "mali_platform.h" -#include "mali_osk.h" -#include "mali_uk_types.h" -#include "mali_kernel_common.h" -#include "mali_kernel_license.h" -#include "mali_linux_pm.h" -#include "mali_kernel_license.h" - -#if ! MALI_LICENSE_IS_GPL -#undef CONFIG_PM_RUNTIME -#endif - -extern struct platform_device mali_gpu_device; - -#ifdef CONFIG_PM_RUNTIME -static mali_bool have_runtime_reference = MALI_FALSE; -#endif - -void _mali_osk_pm_dev_enable(void) -{ -#ifdef CONFIG_PM_RUNTIME - pm_runtime_enable(&(mali_gpu_device.dev)); -#endif -} - -/* NB: Function is not thread safe */ -_mali_osk_errcode_t _mali_osk_pm_dev_idle(void) -{ -#ifdef CONFIG_PM_RUNTIME - if (MALI_TRUE == have_runtime_reference) - { - int err; - err = pm_runtime_put_sync(&(mali_gpu_device.dev)); - if (0 > err) - { - MALI_PRINT_ERROR(("OSK PM: pm_runtime_put_sync() returned error code %d\n", err)); - return _MALI_OSK_ERR_FAULT; - } - have_runtime_reference = MALI_FALSE; - } -#endif - return _MALI_OSK_ERR_OK; -} - -/* NB: Function is not thread safe */ -_mali_osk_errcode_t _mali_osk_pm_dev_activate(void) -{ -#ifdef CONFIG_PM_RUNTIME - if (MALI_TRUE != have_runtime_reference) - { - int err; - err = pm_runtime_get_sync(&(mali_gpu_device.dev)); - if (0 > err) - { - MALI_PRINT_ERROR(("OSK PM: pm_runtime_get_sync() returned error code %d\n", err)); - return _MALI_OSK_ERR_FAULT; - } - have_runtime_reference = MALI_TRUE; - } -#endif - return _MALI_OSK_ERR_OK; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c deleted file mode 100644 index 95bee53..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_ukk.h" -#include "mali_uk_types.h" -#include "mali_osk_profiling.h" -#include "mali_linux_trace.h" -#include "mali_gp.h" -#include "mali_pp.h" -#include "mali_l2_cache.h" -#include "mali_user_settings_db.h" - -_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start) -{ - if (MALI_TRUE == auto_start) - { - mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); - } - - return _MALI_OSK_ERR_OK; -} - -void _mali_osk_profiling_term(void) -{ - /* Nothing to do */ -} - -_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit) -{ - /* Nothing to do */ - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_osk_profiling_stop(u32 *count) -{ - /* Nothing to do */ - return _MALI_OSK_ERR_OK; -} - -u32 _mali_osk_profiling_get_count(void) -{ - return 0; -} - -_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) -{ - /* Nothing to do */ - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_osk_profiling_clear(void) -{ - /* Nothing to do */ - return _MALI_OSK_ERR_OK; -} - -mali_bool _mali_osk_profiling_is_recording(void) -{ - return MALI_FALSE; -} - -mali_bool _mali_osk_profiling_have_recording(void) -{ - return MALI_FALSE; -} - -void _mali_osk_profiling_report_sw_counters(u32 *counters) -{ - trace_mali_sw_counters(_mali_osk_get_pid(), _mali_osk_get_tid(), NULL, counters); -} - - -_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args) -{ - return _mali_osk_profiling_start(&args->limit); -} - -_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) -{ - /* Always add process and thread identificator in the first two data elements for events from user space */ - _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args) -{ - return _mali_osk_profiling_stop(&args->count); -} - -_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args) -{ - return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data); -} - -_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args) -{ - return _mali_osk_profiling_clear(); -} - -_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args) -{ - _mali_osk_profiling_report_sw_counters(args->counters); - return _MALI_OSK_ERR_OK; -} - -/** - * Called by gator.ko to set HW counters - * - * @param counter_id The counter ID. - * @param event_id Event ID that the counter should count (HW counter value from TRM). - * - * @return 1 on success, 0 on failure. - */ -int _mali_profiling_set_event(u32 counter_id, s32 event_id) -{ - - if (COUNTER_VP_C0 == counter_id) - { - struct mali_gp_core* gp_core = mali_gp_get_global_gp_core(); - if (NULL != gp_core) - { - if (MALI_TRUE == mali_gp_core_set_counter_src0(gp_core, event_id)) - { - return 1; - } - } - } - if (COUNTER_VP_C1 == counter_id) - { - struct mali_gp_core* gp_core = mali_gp_get_global_gp_core(); - if (NULL != gp_core) - { - if (MALI_TRUE == mali_gp_core_set_counter_src1(gp_core, event_id)) - { - return 1; - } - } - } - if (COUNTER_FP0_C0 <= counter_id && COUNTER_FP3_C1 >= counter_id) - { - u32 core_id = (counter_id - COUNTER_FP0_C0) >> 1; - struct mali_pp_core* pp_core = mali_pp_get_global_pp_core(core_id); - if (NULL != pp_core) - { - u32 counter_src = (counter_id - COUNTER_FP0_C0) & 1; - if (0 == counter_src) - { - if (MALI_TRUE == mali_pp_core_set_counter_src0(pp_core, event_id)) - { - return 1; - } - } - else - { - if (MALI_TRUE == mali_pp_core_set_counter_src1(pp_core, event_id)) - { - return 1; - } - } - } - } - if (COUNTER_L2_C0 <= counter_id && COUNTER_L2_C1 >= counter_id) - { - u32 core_id = (counter_id - COUNTER_L2_C0) >> 1; - struct mali_l2_cache_core* l2_cache_core = mali_l2_cache_core_get_glob_l2_core(core_id); - if (NULL != l2_cache_core) - { - u32 counter_src = (counter_id - COUNTER_L2_C0) & 1; - if (0 == counter_src) - { - if (MALI_TRUE == mali_l2_cache_core_set_counter_src0(l2_cache_core, event_id)) - { - return 1; - } - } - else - { - if (MALI_TRUE == mali_l2_cache_core_set_counter_src1(l2_cache_core, event_id)) - { - return 1; - } - } - } - } - - return 0; -} - -/** - * Called by gator.ko to retrieve the L2 cache counter values for the first L2 cache. - * The L2 cache counters are unique in that they are polled by gator, rather than being - * transmitted via the tracepoint mechanism. - * - * @param src0 First L2 cache counter ID. - * @param val0 First L2 cache counter value. - * @param src1 Second L2 cache counter ID. - * @param val1 Second L2 cache counter value. - */ -void _mali_profiling_get_counters(u32 *src0, u32 *val0, u32 *src1, u32 *val1) -{ - struct mali_l2_cache_core *l2_cache = mali_l2_cache_core_get_glob_l2_core(0); - if (NULL != l2_cache) - { - if (MALI_TRUE == mali_l2_cache_lock_power_state(l2_cache)) - { - /* It is now safe to access the L2 cache core in order to retrieve the counters */ - mali_l2_cache_core_get_counter_values(l2_cache, src0, val0, src1, val1); - } - mali_l2_cache_unlock_power_state(l2_cache); - } -} - -/* - * List of possible actions to be controlled by Streamline. - * The following numbers are used by gator to control the frame buffer dumping and s/w counter reporting. - * We cannot use the enums in mali_uk_types.h because they are unknown inside gator. - */ -#define FBDUMP_CONTROL_ENABLE (1) -#define FBDUMP_CONTROL_RATE (2) -#define SW_COUNTER_ENABLE (3) -#define FBDUMP_CONTROL_RESIZE_FACTOR (4) - -/** - * Called by gator to control the production of profiling information at runtime. - */ -void _mali_profiling_control(u32 action, u32 value) -{ - switch(action) - { - case FBDUMP_CONTROL_ENABLE: - mali_set_user_setting(_MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, (value == 0 ? MALI_FALSE : MALI_TRUE)); - break; - case FBDUMP_CONTROL_RATE: - mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, value); - break; - case SW_COUNTER_ENABLE: - mali_set_user_setting(_MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, value); - break; - case FBDUMP_CONTROL_RESIZE_FACTOR: - mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, value); - break; - default: - break; /* Ignore unimplemented actions */ - } -} - -EXPORT_SYMBOL(_mali_profiling_set_event); -EXPORT_SYMBOL(_mali_profiling_get_counters); -EXPORT_SYMBOL(_mali_profiling_control); diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c deleted file mode 100644 index 2df935d..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_mali.h" -#include "mali_ukk.h" -#include "mali_timestamp.h" -#include "mali_osk_profiling.h" -#include "mali_user_settings_db.h" - -typedef struct mali_profiling_entry -{ - u64 timestamp; - u32 event_id; - u32 data[5]; -} mali_profiling_entry; - - -typedef enum mali_profiling_state -{ - MALI_PROFILING_STATE_UNINITIALIZED, - MALI_PROFILING_STATE_IDLE, - MALI_PROFILING_STATE_RUNNING, - MALI_PROFILING_STATE_RETURN, -} mali_profiling_state; - -static _mali_osk_lock_t *lock = NULL; -static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED; -static mali_profiling_entry* profile_entries = NULL; -static u32 profile_entry_count = 0; -static _mali_osk_atomic_t profile_insert_index; -static _mali_osk_atomic_t profile_entries_written; - -_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start) -{ - profile_entries = NULL; - profile_entry_count = 0; - _mali_osk_atomic_init(&profile_insert_index, 0); - _mali_osk_atomic_init(&profile_entries_written, 0); - - lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PROFILING); - if (NULL == lock) - { - return _MALI_OSK_ERR_FAULT; - } - - prof_state = MALI_PROFILING_STATE_IDLE; - - if (MALI_TRUE == auto_start) - { - u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* Use maximum buffer size */ - - mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); - if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit)) - { - return _MALI_OSK_ERR_FAULT; - } - } - - return _MALI_OSK_ERR_OK; -} - -void _mali_osk_profiling_term(void) -{ - prof_state = MALI_PROFILING_STATE_UNINITIALIZED; - - /* wait for all elements to be completely inserted into array */ - while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written)) - { - /* do nothing */; - } - - if (NULL != profile_entries) - { - _mali_osk_vfree(profile_entries); - profile_entries = NULL; - } - - if (NULL != lock) - { - _mali_osk_lock_term(lock); - lock = NULL; - } -} - -inline _mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit) -{ - _mali_osk_errcode_t ret; - - mali_profiling_entry *new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry)); - - if(NULL == new_profile_entries) - { - return _MALI_OSK_ERR_NOMEM; - } - - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (prof_state != MALI_PROFILING_STATE_IDLE) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_vfree(new_profile_entries); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - if (*limit > MALI_PROFILING_MAX_BUFFER_ENTRIES) - { - *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; - } - - profile_entries = new_profile_entries; - profile_entry_count = *limit; - - ret = _mali_timestamp_reset(); - - if (ret == _MALI_OSK_ERR_OK) - { - prof_state = MALI_PROFILING_STATE_RUNNING; - } - else - { - _mali_osk_vfree(profile_entries); - profile_entries = NULL; - } - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return ret; -} - -inline void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4) -{ - if (prof_state == MALI_PROFILING_STATE_RUNNING) - { - u32 cur_index = (_mali_osk_atomic_inc_return(&profile_insert_index) - 1) % profile_entry_count; - - profile_entries[cur_index].timestamp = _mali_timestamp_get(); - profile_entries[cur_index].event_id = event_id; - profile_entries[cur_index].data[0] = data0; - profile_entries[cur_index].data[1] = data1; - profile_entries[cur_index].data[2] = data2; - profile_entries[cur_index].data[3] = data3; - profile_entries[cur_index].data[4] = data4; - - /* If event is "leave API function", add current memory usage to the event - * as data point 4. This is used in timeline profiling to indicate how - * much memory was used when leaving a function. */ - if (event_id == (MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC)) - { - profile_entries[cur_index].data[4] = _mali_ukk_report_memory_usage(); - } - - _mali_osk_atomic_inc(&profile_entries_written); - } -} - -inline void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value) -{ - /* Not implemented */ -} - -void _mali_osk_profiling_report_sw_counters(u32 *counters) -{ - /* Not implemented */ -} - -inline _mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (prof_state != MALI_PROFILING_STATE_RUNNING) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - /* go into return state (user to retreive events), no more events will be added after this */ - prof_state = MALI_PROFILING_STATE_RETURN; - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - - /* wait for all elements to be completely inserted into array */ - while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written)) - { - /* do nothing */; - } - - *count = _mali_osk_atomic_read(&profile_insert_index); - if(*count>profile_entry_count) *count=profile_entry_count; - - return _MALI_OSK_ERR_OK; -} - -inline u32 _mali_osk_profiling_get_count(void) -{ - u32 retval = 0; - - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - if (prof_state == MALI_PROFILING_STATE_RETURN) - { - retval = _mali_osk_atomic_read(&profile_entries_written); - if(retval>profile_entry_count) retval = profile_entry_count; - } - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - - return retval; -} - -inline _mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if(index=profile_entry_count) - { - idx = (index + _mali_osk_atomic_read(&profile_insert_index)) % profile_entry_count; - } - - if (prof_state != MALI_PROFILING_STATE_RETURN) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - if (idx >= _mali_osk_atomic_read(&profile_entries_written)) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_FAULT; - } - - *timestamp = profile_entries[idx].timestamp; - *event_id = profile_entries[idx].event_id; - data[0] = profile_entries[idx].data[0]; - data[1] = profile_entries[idx].data[1]; - data[2] = profile_entries[idx].data[2]; - data[3] = profile_entries[idx].data[3]; - data[4] = profile_entries[idx].data[4]; - } - else - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_FAULT; - } - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_OK; -} - -inline _mali_osk_errcode_t _mali_osk_profiling_clear(void) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (prof_state != MALI_PROFILING_STATE_RETURN) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - prof_state = MALI_PROFILING_STATE_IDLE; - profile_entry_count = 0; - _mali_osk_atomic_init(&profile_insert_index, 0); - _mali_osk_atomic_init(&profile_entries_written, 0); - if (NULL != profile_entries) - { - _mali_osk_vfree(profile_entries); - profile_entries = NULL; - } - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_OK; -} - -mali_bool _mali_osk_profiling_is_recording(void) -{ - return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE; -} - -mali_bool _mali_osk_profiling_have_recording(void) -{ - return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE; -} - -_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args) -{ - return _mali_osk_profiling_start(&args->limit); -} - -_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) -{ - /* Always add process and thread identificator in the first two data elements for events from user space */ - _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args) -{ - return _mali_osk_profiling_stop(&args->count); -} - -_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args) -{ - return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data); -} - -_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args) -{ - return _mali_osk_profiling_clear(); -} - -_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args) -{ - _mali_osk_profiling_report_sw_counters(args->counters); - return _MALI_OSK_ERR_OK; -} - diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_specific.h b/drivers/media/video/samsung/mali/linux/mali_osk_specific.h deleted file mode 100644 index 83ee906..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_specific.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_specific.h - * Defines per-OS Kernel level specifics, such as unusual workarounds for - * certain OSs. - */ - -#ifndef __MALI_OSK_SPECIFIC_H__ -#define __MALI_OSK_SPECIFIC_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define MALI_STATIC_INLINE static inline -#define MALI_NON_STATIC_INLINE inline - -#ifdef __cplusplus -} -#endif - -/** The list of events supported by the Mali DDK. */ -typedef enum -{ - /* Vertex processor activity */ - ACTIVITY_VP = 0, - - /* Fragment processor activity */ - ACTIVITY_FP0, - ACTIVITY_FP1, - ACTIVITY_FP2, - ACTIVITY_FP3, - - /* L2 cache counters */ - COUNTER_L2_C0, - COUNTER_L2_C1, - - /* Vertex processor counters */ - COUNTER_VP_C0, - COUNTER_VP_C1, - - /* Fragment processor counters */ - COUNTER_FP0_C0, - COUNTER_FP0_C1, - COUNTER_FP1_C0, - COUNTER_FP1_C1, - COUNTER_FP2_C0, - COUNTER_FP2_C1, - COUNTER_FP3_C0, - COUNTER_FP3_C1, - - /* - * If more hardware counters are added, the _mali_osk_hw_counter_table - * below should also be updated. - */ - - /* EGL software counters */ - COUNTER_EGL_BLIT_TIME, - - /* GLES software counters */ - COUNTER_GLES_DRAW_ELEMENTS_CALLS, - COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, - COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_ARRAYS_CALLS, - COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_POINTS, - COUNTER_GLES_DRAW_LINES, - COUNTER_GLES_DRAW_LINE_LOOP, - COUNTER_GLES_DRAW_LINE_STRIP, - COUNTER_GLES_DRAW_TRIANGLES, - COUNTER_GLES_DRAW_TRIANGLE_STRIP, - COUNTER_GLES_DRAW_TRIANGLE_FAN, - COUNTER_GLES_NON_VBO_DATA_COPY_TIME, - COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, - COUNTER_GLES_UPLOAD_TEXTURE_TIME, - COUNTER_GLES_UPLOAD_VBO_TIME, - COUNTER_GLES_NUM_FLUSHES, - COUNTER_GLES_NUM_VSHADERS_GENERATED, - COUNTER_GLES_NUM_FSHADERS_GENERATED, - COUNTER_GLES_VSHADER_GEN_TIME, - COUNTER_GLES_FSHADER_GEN_TIME, - COUNTER_GLES_INPUT_TRIANGLES, - COUNTER_GLES_VXCACHE_HIT, - COUNTER_GLES_VXCACHE_MISS, - COUNTER_GLES_VXCACHE_COLLISION, - COUNTER_GLES_CULLED_TRIANGLES, - COUNTER_GLES_CULLED_LINES, - COUNTER_GLES_BACKFACE_TRIANGLES, - COUNTER_GLES_GBCLIP_TRIANGLES, - COUNTER_GLES_GBCLIP_LINES, - COUNTER_GLES_TRIANGLES_DRAWN, - COUNTER_GLES_DRAWCALL_TIME, - COUNTER_GLES_TRIANGLES_COUNT, - COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, - COUNTER_GLES_STRIP_TRIANGLES_COUNT, - COUNTER_GLES_FAN_TRIANGLES_COUNT, - COUNTER_GLES_LINES_COUNT, - COUNTER_GLES_INDEPENDENT_LINES_COUNT, - COUNTER_GLES_STRIP_LINES_COUNT, - COUNTER_GLES_LOOP_LINES_COUNT, - - /* Framebuffer capture pseudo-counter */ - COUNTER_FILMSTRIP, - - NUMBER_OF_EVENTS -} _mali_osk_counter_id; - -#define FIRST_ACTIVITY_EVENT ACTIVITY_VP -#define LAST_ACTIVITY_EVENT ACTIVITY_FP3 - -#define FIRST_HW_COUNTER COUNTER_L2_C0 -#define LAST_HW_COUNTER COUNTER_FP3_C1 - -#define FIRST_SW_COUNTER COUNTER_EGL_BLIT_TIME -#define LAST_SW_COUNTER COUNTER_GLES_LOOP_LINES_COUNT - -#define FIRST_SPECIAL_COUNTER COUNTER_FILMSTRIP -#define LAST_SPECIAL_COUNTER COUNTER_FILMSTRIP - -#endif /* __MALI_OSK_SPECIFIC_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_time.c b/drivers/media/video/samsung/mali/linux/mali_osk_time.c deleted file mode 100644 index b399b87..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_time.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_time.c - * Implementation of the OS abstraction layer for the kernel device driver - */ - -#include "mali_osk.h" -#include -#include -#include - -int _mali_osk_time_after( u32 ticka, u32 tickb ) -{ - return time_after((unsigned long)ticka, (unsigned long)tickb); -} - -u32 _mali_osk_time_mstoticks( u32 ms ) -{ - return msecs_to_jiffies(ms); -} - -u32 _mali_osk_time_tickstoms( u32 ticks ) -{ - return jiffies_to_msecs(ticks); -} - -u32 _mali_osk_time_tickcount( void ) -{ - return jiffies; -} - -void _mali_osk_time_ubusydelay( u32 usecs ) -{ - udelay(usecs); -} - -u64 _mali_osk_time_get_ns( void ) -{ - struct timespec tsval; - getnstimeofday(&tsval); - return (u64)timespec_to_ns(&tsval); -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_timers.c b/drivers/media/video/samsung/mali/linux/mali_osk_timers.c deleted file mode 100644 index e5829a3..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_timers.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_timers.c - * Implementation of the OS abstraction layer for the kernel device driver - */ - -#include -#include -#include "mali_osk.h" -#include "mali_kernel_common.h" - -struct _mali_osk_timer_t_struct -{ - struct timer_list timer; -}; - -typedef void (*timer_timeout_function_t)(unsigned long); - -_mali_osk_timer_t *_mali_osk_timer_init(void) -{ - _mali_osk_timer_t *t = (_mali_osk_timer_t*)kmalloc(sizeof(_mali_osk_timer_t), GFP_KERNEL); - if (NULL != t) init_timer(&t->timer); - return t; -} - -void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire ) -{ - MALI_DEBUG_ASSERT_POINTER(tim); - tim->timer.expires = _mali_osk_time_tickcount() + ticks_to_expire; - add_timer(&(tim->timer)); -} - -void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick) -{ - MALI_DEBUG_ASSERT_POINTER(tim); - mod_timer(&(tim->timer), expiry_tick); -} - -void _mali_osk_timer_del( _mali_osk_timer_t *tim ) -{ - MALI_DEBUG_ASSERT_POINTER(tim); - del_timer_sync(&(tim->timer)); -} - -void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data ) -{ - MALI_DEBUG_ASSERT_POINTER(tim); - tim->timer.data = (unsigned long)data; - tim->timer.function = (timer_timeout_function_t)callback; -} - -void _mali_osk_timer_term( _mali_osk_timer_t *tim ) -{ - MALI_DEBUG_ASSERT_POINTER(tim); - kfree(tim); -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c b/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c deleted file mode 100644 index ce0561d..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_osk_wait_queue.c - * Implemenation of the OS abstraction layer for the kernel device driver - */ - -#include -#include -#include - -#include "mali_osk.h" -#include "mali_kernel_common.h" - -struct _mali_osk_wait_queue_t_struct -{ - wait_queue_head_t wait_queue; -}; - -_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void ) -{ - _mali_osk_wait_queue_t* ret = NULL; - - ret = kmalloc(sizeof(_mali_osk_wait_queue_t), GFP_KERNEL); - - if (NULL == ret) - { - return ret; - } - - init_waitqueue_head(&ret->wait_queue); - MALI_DEBUG_ASSERT(!waitqueue_active(&ret->wait_queue)); - - return ret; -} - -void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void) ) -{ - MALI_DEBUG_ASSERT_POINTER( queue ); - MALI_DEBUG_PRINT(6, ("Adding to wait queue %p\n", queue)); - wait_event(queue->wait_queue, condition()); -} - -void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue ) -{ - MALI_DEBUG_ASSERT_POINTER( queue ); - - /* if queue is empty, don't attempt to wake up its elements */ - if (!waitqueue_active(&queue->wait_queue)) return; - - MALI_DEBUG_PRINT(6, ("Waking up elements in wait queue %p ....\n", queue)); - - wake_up_all(&queue->wait_queue); - - MALI_DEBUG_PRINT(6, ("... elements in wait queue %p woken up\n", queue)); -} - -void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue ) -{ - /* Parameter validation */ - MALI_DEBUG_ASSERT_POINTER( queue ); - - /* Linux requires no explicit termination of wait queues */ - kfree(queue); -} diff --git a/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c b/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c deleted file mode 100644 index f3b0a2c..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_pmu_power_up_down.c - */ - -#include -#include -#include -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_pmu.h" -#include "linux/mali/mali_utgard.h" - -/* Mali PMU power up/down APIs */ - -int mali_pmu_powerup(void) -{ - struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); - - MALI_DEBUG_PRINT(5, ("Mali PMU: Power up\n")); - - if (NULL == pmu) - { - return -ENXIO; - } - - if (_MALI_OSK_ERR_OK != mali_pmu_powerup_all(pmu)) - { - return -EFAULT; - } - - return 0; -} - -EXPORT_SYMBOL(mali_pmu_powerup); - -int mali_pmu_powerdown(void) -{ - struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); - - MALI_DEBUG_PRINT(5, ("Mali PMU: Power down\n")); - - if (NULL == pmu) - { - return -ENXIO; - } - - if (_MALI_OSK_ERR_OK != mali_pmu_powerdown_all(pmu)) - { - return -EFAULT; - } - - return 0; -} - -EXPORT_SYMBOL(mali_pmu_powerdown); diff --git a/drivers/media/video/samsung/mali/linux/mali_profiling_events.h b/drivers/media/video/samsung/mali/linux/mali_profiling_events.h deleted file mode 100644 index 2639a40..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_profiling_events.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_PROFILING_EVENTS_H__ -#define __MALI_PROFILING_EVENTS_H__ - -/* Simple wrapper in order to find the OS specific location of this file */ -#include - -#endif /* __MALI_PROFILING_EVENTS_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_uk_types.h b/drivers/media/video/samsung/mali/linux/mali_uk_types.h deleted file mode 100644 index 1a81246..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_uk_types.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_UK_TYPES_H__ -#define __MALI_UK_TYPES_H__ - -/* Simple wrapper in order to find the OS specific location of this file */ -//#include -#include "../include/linux/mali/mali_utgard_uk_types.h" - -#endif /* __MALI_UK_TYPES_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_core.c b/drivers/media/video/samsung/mali/linux/mali_ukk_core.c deleted file mode 100644 index 22262fe..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_core.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include /* file system operations */ -#include /* memort allocation functions */ -#include /* user space access */ - -#include "mali_ukk.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_ukk_wrappers.h" - -int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs) -{ - _mali_uk_get_api_version_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - if (0 != get_user(kargs.version, &uargs->version)) return -EFAULT; - - kargs.ctx = session_data; - err = _mali_ukk_get_api_version(&kargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT; - if (0 != put_user(kargs.compatible, &uargs->compatible)) return -EFAULT; - - return 0; -} - -int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs) -{ - _mali_uk_wait_for_notification_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - kargs.ctx = session_data; - err = _mali_ukk_wait_for_notification(&kargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - if(_MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS != kargs.type) - { - kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ - if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_wait_for_notification_s))) return -EFAULT; - } - else - { - if (0 != put_user(kargs.type, &uargs->type)) return -EFAULT; - } - - return 0; -} - -int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs) -{ - _mali_uk_post_notification_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - kargs.ctx = session_data; - - if (0 != get_user(kargs.type, &uargs->type)) - { - return -EFAULT; - } - - err = _mali_ukk_post_notification(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - return 0; -} - -int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs) -{ - _mali_uk_get_user_settings_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - kargs.ctx = session_data; - err = _mali_ukk_get_user_settings(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ - if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_get_user_settings_s))) return -EFAULT; - - return 0; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c b/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c deleted file mode 100644 index 7070016..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include /* file system operations */ -#include /* user space access */ - -#include "mali_ukk.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_ukk_wrappers.h" - -int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs) -{ - _mali_uk_gp_start_job_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); - - if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_gp_start_job_s))) - { - return -EFAULT; - } - - if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_start_job_s))) return -EFAULT; - - kargs.ctx = session_data; - err = _mali_ukk_gp_start_job(&kargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ - - if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_gp_start_job_s))) - { - /* - * If this happens, then user space will not know that the job was actually started, - * and if we return a queued job, then user space will still think that one is still queued. - * This will typically lead to a deadlock in user space. - * This could however only happen if user space deliberately passes a user buffer which - * passes the access_ok(VERIFY_WRITE) check, but isn't fully writable at the time of copy_to_user(). - * The official Mali driver will never attempt to do that, and kernel space should not be affected. - * That is why we do not bother to do a complex rollback in this very very very rare case. - */ - return -EFAULT; - } - - return 0; -} - -int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs) -{ - _mali_uk_get_gp_core_version_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); - - kargs.ctx = session_data; - err = _mali_ukk_get_gp_core_version(&kargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - /* no known transactions to roll-back */ - - if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT; - - return 0; -} - -int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs) -{ - _mali_uk_gp_suspend_response_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); - - if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_suspend_response_s))) return -EFAULT; - - kargs.ctx = session_data; - err = _mali_ukk_gp_suspend_response(&kargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - if (0 != put_user(kargs.cookie, &uargs->cookie)) return -EFAULT; - - /* no known transactions to roll-back */ - return 0; -} - -int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs) -{ - _mali_uk_get_gp_number_of_cores_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); - - kargs.ctx = session_data; - err = _mali_ukk_get_gp_number_of_cores(&kargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - /* no known transactions to roll-back */ - - if (0 != put_user(kargs.number_of_cores, &uargs->number_of_cores)) return -EFAULT; - - return 0; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c b/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c deleted file mode 100644 index 260f257..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include /* file system operations */ -#include /* user space access */ - -#include "mali_ukk.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_ukk_wrappers.h" - -int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs) -{ - _mali_uk_init_mem_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - kargs.ctx = session_data; - err = _mali_ukk_init_mem(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - if (0 != put_user(kargs.mali_address_base, &uargs->mali_address_base)) goto mem_init_rollback; - if (0 != put_user(kargs.memory_size, &uargs->memory_size)) goto mem_init_rollback; - - return 0; - -mem_init_rollback: - { - _mali_uk_term_mem_s kargs; - kargs.ctx = session_data; - err = _mali_ukk_term_mem(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_init_mem, as a result of failing put_user(), failed\n")); - } - } - return -EFAULT; -} - -int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs) -{ - _mali_uk_term_mem_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - kargs.ctx = session_data; - err = _mali_ukk_term_mem(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - return 0; -} - -int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument) -{ - _mali_uk_map_external_mem_s uk_args; - _mali_osk_errcode_t err_code; - - /* validate input */ - /* the session_data pointer was validated by caller */ - MALI_CHECK_NON_NULL( argument, -EINVAL); - - /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_map_external_mem_s)) ) - { - return -EFAULT; - } - - uk_args.ctx = session_data; - err_code = _mali_ukk_map_external_mem( &uk_args ); - - if (0 != put_user(uk_args.cookie, &argument->cookie)) - { - if (_MALI_OSK_ERR_OK == err_code) - { - /* Rollback */ - _mali_uk_unmap_external_mem_s uk_args_unmap; - - uk_args_unmap.ctx = session_data; - uk_args_unmap.cookie = uk_args.cookie; - err_code = _mali_ukk_unmap_external_mem( &uk_args_unmap ); - if (_MALI_OSK_ERR_OK != err_code) - { - MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_unmap_external_mem, as a result of failing put_user(), failed\n")); - } - } - return -EFAULT; - } - - /* Return the error that _mali_ukk_free_big_block produced */ - return map_errcode(err_code); -} - -int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument) -{ - _mali_uk_unmap_external_mem_s uk_args; - _mali_osk_errcode_t err_code; - - /* validate input */ - /* the session_data pointer was validated by caller */ - MALI_CHECK_NON_NULL( argument, -EINVAL); - - /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_unmap_external_mem_s)) ) - { - return -EFAULT; - } - - uk_args.ctx = session_data; - err_code = _mali_ukk_unmap_external_mem( &uk_args ); - - /* Return the error that _mali_ukk_free_big_block produced */ - return map_errcode(err_code); -} - -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 -int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument) -{ - _mali_uk_release_ump_mem_s uk_args; - _mali_osk_errcode_t err_code; - - /* validate input */ - /* the session_data pointer was validated by caller */ - MALI_CHECK_NON_NULL( argument, -EINVAL); - - /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_release_ump_mem_s)) ) - { - return -EFAULT; - } - - uk_args.ctx = session_data; - err_code = _mali_ukk_release_ump_mem( &uk_args ); - - /* Return the error that _mali_ukk_free_big_block produced */ - return map_errcode(err_code); -} - -int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument) -{ - _mali_uk_attach_ump_mem_s uk_args; - _mali_osk_errcode_t err_code; - - /* validate input */ - /* the session_data pointer was validated by caller */ - MALI_CHECK_NON_NULL( argument, -EINVAL); - - /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_attach_ump_mem_s)) ) - { - return -EFAULT; - } - - uk_args.ctx = session_data; - err_code = _mali_ukk_attach_ump_mem( &uk_args ); - - if (0 != put_user(uk_args.cookie, &argument->cookie)) - { - if (_MALI_OSK_ERR_OK == err_code) - { - /* Rollback */ - _mali_uk_release_ump_mem_s uk_args_unmap; - - uk_args_unmap.ctx = session_data; - uk_args_unmap.cookie = uk_args.cookie; - err_code = _mali_ukk_release_ump_mem( &uk_args_unmap ); - if (_MALI_OSK_ERR_OK != err_code) - { - MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_attach_mem, as a result of failing put_user(), failed\n")); - } - } - return -EFAULT; - } - - /* Return the error that _mali_ukk_map_external_ump_mem produced */ - return map_errcode(err_code); -} -#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */ - -int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs) -{ - _mali_uk_query_mmu_page_table_dump_size_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); - - kargs.ctx = session_data; - - err = _mali_ukk_query_mmu_page_table_dump_size(&kargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT; - - return 0; -} - -int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs) -{ - _mali_uk_dump_mmu_page_table_s kargs; - _mali_osk_errcode_t err; - void *buffer; - int rc = -EFAULT; - - /* validate input */ - MALI_CHECK_NON_NULL(uargs, -EINVAL); - /* the session_data pointer was validated by caller */ - - kargs.buffer = NULL; - - /* get location of user buffer */ - if (0 != get_user(buffer, &uargs->buffer)) goto err_exit; - /* get size of mmu page table info buffer from user space */ - if ( 0 != get_user(kargs.size, &uargs->size) ) goto err_exit; - /* verify we can access the whole of the user buffer */ - if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit; - - /* allocate temporary buffer (kernel side) to store mmu page table info */ - kargs.buffer = _mali_osk_valloc(kargs.size); - if (NULL == kargs.buffer) - { - rc = -ENOMEM; - goto err_exit; - } - - kargs.ctx = session_data; - err = _mali_ukk_dump_mmu_page_table(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - rc = map_errcode(err); - goto err_exit; - } - - /* copy mmu page table info back to user space and update pointers */ - if (0 != copy_to_user(uargs->buffer, kargs.buffer, kargs.size) ) goto err_exit; - if (0 != put_user((kargs.register_writes - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->register_writes)) goto err_exit; - if (0 != put_user((kargs.page_table_dump - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->page_table_dump)) goto err_exit; - if (0 != put_user(kargs.register_writes_size, &uargs->register_writes_size)) goto err_exit; - if (0 != put_user(kargs.page_table_dump_size, &uargs->page_table_dump_size)) goto err_exit; - rc = 0; - -err_exit: - if (kargs.buffer) _mali_osk_vfree(kargs.buffer); - return rc; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c b/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c deleted file mode 100644 index c11c61b..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include /* file system operations */ -#include /* user space access */ - -#include "mali_ukk.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_ukk_wrappers.h" - -int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs) -{ - _mali_uk_pp_start_job_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); - - if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_pp_start_job_s))) - { - return -EFAULT; - } - - if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_start_job_s))) return -EFAULT; - - kargs.ctx = session_data; - err = _mali_ukk_pp_start_job(&kargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - return 0; -} - -int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs) -{ - _mali_uk_get_pp_number_of_cores_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); - - kargs.ctx = session_data; - err = _mali_ukk_get_pp_number_of_cores(&kargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - if (0 != put_user(kargs.number_of_cores, &uargs->number_of_cores)) return -EFAULT; - - return 0; -} - -int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs) -{ - _mali_uk_get_pp_core_version_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); - - kargs.ctx = session_data; - err = _mali_ukk_get_pp_core_version(&kargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - - if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT; - - return 0; -} - -int pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs) -{ - _mali_uk_pp_disable_wb_s kargs; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); - - if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_disable_wb_s))) return -EFAULT; - - kargs.ctx = session_data; - _mali_ukk_pp_job_disable_wb(&kargs); - - return 0; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c b/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c deleted file mode 100644 index f4e31c9..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include /* file system operations */ -#include /* user space access */ -#include - -#include "mali_ukk.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_ukk_wrappers.h" - -int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs) -{ - _mali_uk_profiling_start_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_start_s))) - { - return -EFAULT; - } - - kargs.ctx = session_data; - err = _mali_ukk_profiling_start(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - if (0 != put_user(kargs.limit, &uargs->limit)) - { - return -EFAULT; - } - - return 0; -} - -int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_add_event_s __user *uargs) -{ - _mali_uk_profiling_add_event_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_add_event_s))) - { - return -EFAULT; - } - - kargs.ctx = session_data; - err = _mali_ukk_profiling_add_event(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - return 0; -} - -int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_stop_s __user *uargs) -{ - _mali_uk_profiling_stop_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - kargs.ctx = session_data; - err = _mali_ukk_profiling_stop(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - if (0 != put_user(kargs.count, &uargs->count)) - { - return -EFAULT; - } - - return 0; -} - -int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs) -{ - _mali_uk_profiling_get_event_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - if (0 != get_user(kargs.index, &uargs->index)) - { - return -EFAULT; - } - - kargs.ctx = session_data; - - err = _mali_ukk_profiling_get_event(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ - if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_profiling_get_event_s))) - { - return -EFAULT; - } - - return 0; -} - -int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs) -{ - _mali_uk_profiling_clear_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - kargs.ctx = session_data; - err = _mali_ukk_profiling_clear(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - return 0; -} - -int profiling_report_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_report_s __user *uargs) -{ - _mali_uk_sw_counters_report_s kargs; - _mali_osk_errcode_t err; - u32 *counter_buffer; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_sw_counters_report_s))) - { - return -EFAULT; - } - - /* make sure that kargs.num_counters is [at least somewhat] sane */ - if (kargs.num_counters > 10000) { - MALI_DEBUG_PRINT(1, ("User space attempted to allocate too many counters.\n")); - return -EINVAL; - } - - counter_buffer = (u32*)kmalloc(sizeof(u32) * kargs.num_counters, GFP_KERNEL); - if (NULL == counter_buffer) - { - return -ENOMEM; - } - - if (0 != copy_from_user(counter_buffer, kargs.counters, sizeof(u32) * kargs.num_counters)) - { - kfree(counter_buffer); - return -EFAULT; - } - - kargs.ctx = session_data; - kargs.counters = counter_buffer; - - err = _mali_ukk_sw_counters_report(&kargs); - - kfree(counter_buffer); - - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - return 0; -} - - diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c b/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c deleted file mode 100644 index f9b5a3e..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2011-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include /* file system operations */ -#include /* user space access */ - -#include "mali_ukk.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_ukk_wrappers.h" - - -int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs) -{ - _mali_uk_vsync_event_report_s kargs; - _mali_osk_errcode_t err; - - MALI_CHECK_NON_NULL(uargs, -EINVAL); - - if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_vsync_event_report_s))) - { - return -EFAULT; - } - - kargs.ctx = session_data; - err = _mali_ukk_vsync_event_report(&kargs); - if (_MALI_OSK_ERR_OK != err) - { - return map_errcode(err); - } - - return 0; -} - diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h b/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h deleted file mode 100644 index 65857fd..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_ukk_wrappers.h - * Defines the wrapper functions for each user-kernel function - */ - -#ifndef __MALI_UKK_WRAPPERS_H__ -#define __MALI_UKK_WRAPPERS_H__ - -#include "mali_uk_types.h" -#include "mali_osk.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs); -int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs); -int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs); -int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs); -int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs); -int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs); -int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument); -int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument); -int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs); -int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs); - -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 -int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument); -int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument); -#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */ - -int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs); -int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs); -int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs); -int pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs); -int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs); -int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs); -int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs); -int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs); - -int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs); -int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_add_event_s __user *uargs); -int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_stop_s __user *uargs); -int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs); -int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs); -int profiling_report_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_report_s __user *uargs); - -int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs); - - -int map_errcode( _mali_osk_errcode_t err ); - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_UKK_WRAPPERS_H__ */ diff --git a/drivers/media/video/samsung/mali/platform/default/mali_platform.c b/drivers/media/video/samsung/mali/platform/default/mali_platform.c deleted file mode 100644 index d966f25..0000000 --- a/drivers/media/video/samsung/mali/platform/default/mali_platform.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_platform.c - * Platform specific Mali driver functions for a default platform - */ -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" - - -_mali_osk_errcode_t mali_platform_init(void) -{ - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_deinit(void) -{ - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) -{ - MALI_SUCCESS; -} - -void mali_gpu_utilization_handler(u32 utilization) -{ -} - -void set_mali_parent_power_domain(void* dev) -{ -} - - diff --git a/drivers/media/video/samsung/mali/platform/mali_platform.h b/drivers/media/video/samsung/mali/platform/mali_platform.h deleted file mode 100644 index 888f57a..0000000 --- a/drivers/media/video/samsung/mali/platform/mali_platform.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_platform.h - * Platform specific Mali driver functions - */ - -#ifndef __MALI_PLATFORM_H__ -#define __MALI_PLATFORM_H__ - -#include "mali_osk.h" - -#ifdef CONFIG_CPU_EXYNOS4210 -#define MALI_DVFS_STEPS 3 -#else -#define MALI_DVFS_STEPS 5 -#endif - -/* @Enable or Disable Mali GPU Bottom Lock feature */ -#define MALI_GPU_BOTTOM_LOCK 1 - -#define MALI_VOLTAGE_LOCK 1 - -/* @Enable or Disable the CPU frequency lock when the GPU clock is 440 Mhz */ -#define CPUFREQ_LOCK_DURING_440 0 - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief description of power change reasons - */ -typedef enum mali_power_mode_tag -{ - MALI_POWER_MODE_ON, /**< Power Mali on */ - MALI_POWER_MODE_LIGHT_SLEEP, /**< Mali has been idle for a short time, or runtime PM suspend */ - MALI_POWER_MODE_DEEP_SLEEP, /**< Mali has been idle for a long time, or OS suspend */ -} mali_power_mode; - -/** @brief Platform specific setup and initialisation of MALI - * - * This is called from the entrypoint of the driver to initialize the platform - * - * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. - */ -_mali_osk_errcode_t mali_platform_init(void); - -/** @brief Platform specific deinitialisation of MALI - * - * This is called on the exit of the driver to terminate the platform - * - * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. - */ -_mali_osk_errcode_t mali_platform_deinit(void); - -/** @brief Platform specific powerdown sequence of MALI - * - * Notification from the Mali device driver stating the new desired power mode. - * MALI_POWER_MODE_ON must be obeyed, while the other modes are optional. - * @param power_mode defines the power modes - * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. - */ -_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode); - - -/** @brief Platform specific handling of GPU utilization data - * - * When GPU utilization data is enabled, this function will be - * periodically called. - * - * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization. - */ -void mali_gpu_utilization_handler(u32 utilization); - -/** @brief Setting the power domain of MALI - * - * This function sets the power domain of MALI if Linux run time power management is enabled - * - * @param dev Reference to struct platform_device (defined in linux) used by MALI GPU - */ -//void set_mali_parent_power_domain(void* dev); -void mali_utilization_suspend(void); - -#ifdef CONFIG_REGULATOR -int mali_regulator_get_usecount(void); -void mali_regulator_disable(void); -void mali_regulator_enable(void); -void mali_regulator_set_voltage(int min_uV, int max_uV); -#endif -mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz); -unsigned long mali_clk_get_rate(void); -void mali_clk_put(mali_bool binc_mali_clk); - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -_mali_osk_errcode_t mali_platform_powerdown(u32 cores); -_mali_osk_errcode_t mali_platform_powerup(u32 cores); -#endif - - -#if USING_MALI_PMM -#if MALI_POWER_MGMT_TEST_SUITE -/** @brief function to get status of individual cores - * - * This function is used by power management test suite to get the status of powered up/down the number - * of cores - * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization. - */ -u32 pmu_get_power_up_down_info(void); -#endif -#endif - -#if MALI_DVFS_ENABLED -mali_bool init_mali_dvfs_status(int step); -void deinit_mali_dvfs_status(void); -mali_bool mali_dvfs_handler(u32 utilization); -int mali_dvfs_is_running(void); -void mali_dvfs_late_resume(void); -int get_mali_dvfs_control_status(void); -mali_bool set_mali_dvfs_current_step(unsigned int step); -void mali_default_step_set(int step, mali_bool boostup); -int change_dvfs_tableset(int change_clk, int change_step); -#ifdef CONFIG_CPU_EXYNOS4210 -#if MALI_GPU_BOTTOM_LOCK -int mali_dvfs_bottom_lock_push(void); -int mali_dvfs_bottom_lock_pop(void); -#endif -#else -int mali_dvfs_bottom_lock_push(int lock_step); -int mali_dvfs_bottom_lock_pop(void); -#endif -#endif - -int mali_dvfs_get_vol(int step); - -#if MALI_VOLTAGE_LOCK -int mali_voltage_lock_push(int lock_vol); -int mali_voltage_lock_pop(void); -int mali_voltage_lock_init(void); -int mali_vol_get_from_table(int vol); -#endif - -#ifdef __cplusplus -} -#endif -#endif diff --git a/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c b/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c deleted file mode 100644 index cb95dc6..0000000 --- a/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_platform.c - * Platform specific Mali driver functions for a default platform - */ -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" -#include "mali_pmu.h" -#include "linux/mali/mali_utgard.h" - -static u32 bPowerOff = 1; - -_mali_osk_errcode_t mali_platform_init(void) -{ - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_deinit(void) -{ - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) -{ - switch (power_mode) - { - case MALI_POWER_MODE_ON: - if (bPowerOff == 1) - { - mali_pmu_powerup(); - bPowerOff = 0; - } - break; - case MALI_POWER_MODE_LIGHT_SLEEP: - case MALI_POWER_MODE_DEEP_SLEEP: - - if (bPowerOff == 0) - { - mali_pmu_powerdown(); - bPowerOff = 1; - } - - break; - } - MALI_SUCCESS; -} - -void mali_gpu_utilization_handler(u32 utilization) -{ -} - -void set_mali_parent_power_domain(void* dev) -{ -} - - diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c deleted file mode 100644 index 119831d..0000000 --- a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_platform.c - * Platform specific Mali driver functions for a default platform - */ -#include -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" -#include "mali_linux_pm.h" - -#if USING_MALI_PMM -#include "mali_pm.h" -#endif - -#include -#include -#include -#include -#include - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#include -#endif - -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_kernel_profiling.h" -#endif - -#include -#include - -#define EXTXTALCLK_NAME "ext_xtal" -#define VPLLSRCCLK_NAME "vpll_src" -#define FOUTVPLLCLK_NAME "fout_vpll" -#define SCLVPLLCLK_NAME "sclk_vpll" -#define GPUMOUT1CLK_NAME "mout_g3d1" - -#define MPLLCLK_NAME "mout_mpll" -#define GPUMOUT0CLK_NAME "mout_g3d0" -#define GPUCLK_NAME "sclk_g3d" -#define CLK_DIV_STAT_G3D 0x1003C62C -#define CLK_DESC "clk-divider-status" - -static struct clk *ext_xtal_clock = 0; -static struct clk *vpll_src_clock = 0; -static struct clk *fout_vpll_clock = 0; -static struct clk *sclk_vpll_clock = 0; - -static struct clk *mpll_clock = 0; -static struct clk *mali_parent_clock = 0; -static struct clk *mali_clock = 0; - -int mali_gpu_clk = 160; -static unsigned int GPU_MHZ = 1000000; -#ifdef CONFIG_S5PV310_ASV -int mali_gpu_vol = 1100000; /* 1.10V for ASV */ -#else -int mali_gpu_vol = 1100000; /* 1.10V */ -#endif - -#if MALI_DVFS_ENABLED -#define MALI_DVFS_DEFAULT_STEP 0 // 134Mhz default -#endif - -int gpu_power_state; -static int bPoweroff; - -#ifdef CONFIG_REGULATOR -struct regulator { - struct device *dev; - struct list_head list; - int uA_load; - int min_uV; - int max_uV; - char *supply_name; - struct device_attribute dev_attr; - struct regulator_dev *rdev; -}; - -struct regulator *g3d_regulator=NULL; -#endif - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) -extern struct platform_device s5pv310_device_pd[]; -#else -extern struct platform_device exynos4_device_pd[]; -#endif -#endif - -mali_io_address clk_register_map=0; - -#if MALI_GPU_BOTTOM_LOCK -_mali_osk_lock_t *mali_dvfs_lock; -#else -static _mali_osk_lock_t *mali_dvfs_lock; -#endif - -#ifdef CONFIG_REGULATOR -int mali_regulator_get_usecount(void) -{ - struct regulator_dev *rdev; - - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_get_usecount : g3d_regulator is null\n")); - return 0; - } - rdev = g3d_regulator->rdev; - return rdev->use_count; -} - -void mali_regulator_disable(void) -{ - bPoweroff = 1; - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n")); - return; - } - regulator_disable(g3d_regulator); - MALI_DEBUG_PRINT(1, ("regulator_disable -> use cnt: %d \n",mali_regulator_get_usecount())); -} - -void mali_regulator_enable(void) -{ - bPoweroff = 0; - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n")); - return; - } - regulator_enable(g3d_regulator); - MALI_DEBUG_PRINT(1, ("regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); -} - -void mali_regulator_set_voltage(int min_uV, int max_uV) -{ - int voltage; - - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n")); - return; - } - MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS, - min_uV, max_uV, 0, 0, 0); -#endif - - regulator_set_voltage(g3d_regulator,min_uV,max_uV); - voltage = regulator_get_voltage(g3d_regulator); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS, - voltage, 0, 1, 0, 0); -#endif - mali_gpu_vol = voltage; - MALI_DEBUG_PRINT(1, ("= regulator_get_voltage: %d \n",mali_gpu_vol)); - - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); -} -#endif - -unsigned long mali_clk_get_rate(void) -{ - return clk_get_rate(mali_clock); -} - -mali_bool mali_clk_get(mali_bool bis_vpll) -{ - if (bis_vpll == MALI_TRUE) - { - if (ext_xtal_clock == NULL) - { - ext_xtal_clock = clk_get(NULL,EXTXTALCLK_NAME); - if (IS_ERR(ext_xtal_clock)) { - MALI_PRINT( ("MALI Error : failed to get source ext_xtal_clock\n")); - return MALI_FALSE; - } - } - - if (vpll_src_clock == NULL) - { - vpll_src_clock = clk_get(NULL,VPLLSRCCLK_NAME); - if (IS_ERR(vpll_src_clock)) { - MALI_PRINT( ("MALI Error : failed to get source vpll_src_clock\n")); - return MALI_FALSE; - } - } - - if (fout_vpll_clock == NULL) - { - fout_vpll_clock = clk_get(NULL,FOUTVPLLCLK_NAME); - if (IS_ERR(fout_vpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source fout_vpll_clock\n")); - return MALI_FALSE; - } - } - - if (sclk_vpll_clock == NULL) - { - sclk_vpll_clock = clk_get(NULL,SCLVPLLCLK_NAME); - if (IS_ERR(sclk_vpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source sclk_vpll_clock\n")); - return MALI_FALSE; - } - } - - if (mali_parent_clock == NULL) - { - mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME); - - if (IS_ERR(mali_parent_clock)) { - MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); - return MALI_FALSE; - } - } - } - else // mpll - { - if (mpll_clock == NULL) - { - mpll_clock = clk_get(NULL,MPLLCLK_NAME); - - if (IS_ERR(mpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source mpll clock\n")); - return MALI_FALSE; - } - } - - if (mali_parent_clock == NULL) - { - mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME); - - if (IS_ERR(mali_parent_clock)) { - MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); - return MALI_FALSE; - } - } - } - - // mali clock get always. - if (mali_clock == NULL) - { - mali_clock = clk_get(NULL, GPUCLK_NAME); - - if (IS_ERR(mali_clock)) { - MALI_PRINT( ("MALI Error : failed to get source mali clock\n")); - return MALI_FALSE; - } - } - - return MALI_TRUE; -} - -void mali_clk_put(mali_bool binc_mali_clock) -{ - if (mali_parent_clock) - { - clk_put(mali_parent_clock); - mali_parent_clock = 0; - } - - if (mpll_clock) - { - clk_put(mpll_clock); - mpll_clock = 0; - } - - if (sclk_vpll_clock) - { - clk_put(sclk_vpll_clock); - sclk_vpll_clock = 0; - } - - if (fout_vpll_clock) - { - clk_put(fout_vpll_clock); - fout_vpll_clock = 0; - } - - if (vpll_src_clock) - { - clk_put(vpll_src_clock); - vpll_src_clock = 0; - } - - if (ext_xtal_clock) - { - clk_put(ext_xtal_clock); - ext_xtal_clock = 0; - } - - if (binc_mali_clock == MALI_TRUE && mali_clock) - { - clk_put(mali_clock); - mali_clock = 0; - } - -} - - -mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz) -{ - unsigned long rate = 0; - mali_bool bis_vpll = MALI_FALSE; - -#ifdef CONFIG_VPLL_USE_FOR_TVENC - bis_vpll = MALI_TRUE; -#endif - - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - if (mali_clk_get(bis_vpll) == MALI_FALSE) - return MALI_FALSE; - - rate = (unsigned long)clk * (unsigned long)mhz; - MALI_DEBUG_PRINT(3,("= clk_set_rate : %d , %d \n",clk, mhz )); - - if (bis_vpll) - { - clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ); - clk_set_parent(vpll_src_clock, ext_xtal_clock); - clk_set_parent(sclk_vpll_clock, fout_vpll_clock); - - clk_set_parent(mali_parent_clock, sclk_vpll_clock); - clk_set_parent(mali_clock, mali_parent_clock); - } - else - { - clk_set_parent(mali_parent_clock, mpll_clock); - clk_set_parent(mali_clock, mali_parent_clock); - } - - if (clk_enable(mali_clock) < 0) - return MALI_FALSE; - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ, - rate, 0, 0, 0, 0); -#endif - - clk_set_rate(mali_clock, rate); - rate = clk_get_rate(mali_clock); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ, - rate, 0, 0, 0, 0); -#endif - - if (bis_vpll) - mali_gpu_clk = (int)(rate / mhz); - else - mali_gpu_clk = (int)((rate + 500000) / mhz); - - GPU_MHZ = mhz; - MALI_DEBUG_PRINT(3,("= clk_get_rate: %d \n",mali_gpu_clk)); - - mali_clk_put(MALI_FALSE); - - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - return MALI_TRUE; -} - -static mali_bool init_mali_clock(void) -{ - mali_bool ret = MALI_TRUE; - - gpu_power_state = 0; - - if (mali_clock != 0) - return ret; // already initialized - - mali_dvfs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE - | _MALI_OSK_LOCKFLAG_ONELOCK, 0, 0); - if (mali_dvfs_lock == NULL) - return _MALI_OSK_ERR_FAULT; - - if (mali_clk_set_rate(mali_gpu_clk, GPU_MHZ) == MALI_FALSE) - { - ret = MALI_FALSE; - goto err_clock_get; - } - - MALI_PRINT(("init_mali_clock mali_clock %p \n", mali_clock)); - - -#ifdef CONFIG_REGULATOR -#if USING_MALI_PMM - g3d_regulator = regulator_get(&mali_gpu_device.dev, "vdd_g3d"); -#else - g3d_regulator = regulator_get(NULL, "vdd_g3d"); -#endif - - if (IS_ERR(g3d_regulator)) - { - MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n")); - ret = MALI_FALSE; - goto err_regulator; - } - - regulator_enable(g3d_regulator); - MALI_DEBUG_PRINT(1, ("= regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); - mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol); -#endif - - MALI_DEBUG_PRINT(2, ("MALI Clock is set at mali driver\n")); - MALI_DEBUG_PRINT(3,("::clk_put:: %s mali_parent_clock - normal\n", __FUNCTION__)); - MALI_DEBUG_PRINT(3,("::clk_put:: %s mpll_clock - normal\n", __FUNCTION__)); - - mali_clk_put(MALI_FALSE); - - return MALI_TRUE; - - -#ifdef CONFIG_REGULATOR -err_regulator: - regulator_put(g3d_regulator); -#endif - -err_clock_get: - mali_clk_put(MALI_TRUE); - - return ret; -} - -static mali_bool deinit_mali_clock(void) -{ - if (mali_clock == 0) - return MALI_TRUE; - -#ifdef CONFIG_REGULATOR - if (g3d_regulator) - { - regulator_put(g3d_regulator); - g3d_regulator=NULL; - } -#endif - - mali_clk_put(MALI_TRUE); - - return MALI_TRUE; -} - - -static _mali_osk_errcode_t enable_mali_clocks(void) -{ - int err; - err = clk_enable(mali_clock); - MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err)); - - // set clock rate - mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); - - MALI_SUCCESS; -} - -static _mali_osk_errcode_t disable_mali_clocks(void) -{ - clk_disable(mali_clock); - MALI_DEBUG_PRINT(3,("disable_mali_clocks mali_clock %p \n", mali_clock)); - - MALI_SUCCESS; -} - -void set_mali_parent_power_domain(struct platform_device* dev) -{ -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) - dev->dev.parent = &s5pv310_device_pd[PD_G3D].dev; -#else - dev->dev.parent = &exynos4_device_pd[PD_G3D].dev; -#endif - -#endif -} - -_mali_osk_errcode_t g3d_power_domain_control(int bpower_on) -{ - if (bpower_on) - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT(3,("_mali_osk_pm_dev_activate \n")); - _mali_osk_pm_dev_activate(); -#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON - void __iomem *status; - u32 timeout; - __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_PMU_G3D_CONF); - status = S5P_PMU_G3D_CONF + 0x4; - - timeout = 10; - while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) - != S5P_INT_LOCAL_PWR_EN) { - if (timeout == 0) { - MALI_PRINTF(("Power domain enable failed.\n")); - return -ETIMEDOUT; - } - timeout--; - _mali_osk_time_ubusydelay(100); - } -#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON - } - else - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT( 4,("_mali_osk_pm_dev_idle\n")); - _mali_osk_pm_dev_idle(); - -#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON - void __iomem *status; - u32 timeout; - __raw_writel(0, S5P_PMU_G3D_CONF); - - status = S5P_PMU_G3D_CONF + 0x4; - /* Wait max 1ms */ - timeout = 10; - while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) - { - if (timeout == 0) { - MALI_PRINTF(("Power domain disable failed.\n" )); - return -ETIMEDOUT; - } - timeout--; - _mali_osk_time_ubusydelay( 100); - } -#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON - } - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_init() -{ - MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT); -#if MALI_DVFS_ENABLED - if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC ); - if(!init_mali_dvfs_status(MALI_DVFS_DEFAULT_STEP)) - MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n")); -#endif - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_deinit() -{ - deinit_mali_clock(); - -#if MALI_DVFS_ENABLED - deinit_mali_dvfs_status(); - if (clk_register_map ) - { - _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map); - clk_register_map=0; - } -#endif - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_powerdown(u32 cores) -{ - MALI_DEBUG_PRINT(3,("power down is called in mali_platform_powerdown state %x core %x \n", gpu_power_state, cores)); - - if (gpu_power_state != 0) // power down after state is 0 - { - gpu_power_state = gpu_power_state & (~cores); - if (gpu_power_state == 0) - { - MALI_DEBUG_PRINT( 3,("disable clock\n")); - disable_mali_clocks(); - } - } - else - { - MALI_PRINT(("mali_platform_powerdown gpu_power_state == 0 and cores %x \n", cores)); - } - - bPoweroff=1; - - - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_powerup(u32 cores) -{ - MALI_DEBUG_PRINT(3,("power up is called in mali_platform_powerup state %x core %x \n", gpu_power_state, cores)); - - if (gpu_power_state == 0) // power up only before state is 0 - { - gpu_power_state = gpu_power_state | cores; - - if (gpu_power_state != 0) - { - MALI_DEBUG_PRINT(4,("enable clock \n")); - enable_mali_clocks(); - } - } - else - { - gpu_power_state = gpu_power_state | cores; - } - - bPoweroff=0; - - - MALI_SUCCESS; -} - -void mali_gpu_utilization_handler(u32 utilization) -{ - if (bPoweroff==0) - { -#if MALI_DVFS_ENABLED - if(!mali_dvfs_handler(utilization)) - MALI_DEBUG_PRINT(1,( "error on mali dvfs status in utilization\n")); -#endif - } -} - -#if MALI_POWER_MGMT_TEST_SUITE -u32 pmu_get_power_up_down_info(void) -{ - return 4095; -} - -#endif -_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) -{ - MALI_SUCCESS; -} - diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c deleted file mode 100644 index 4efa759..0000000 --- a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c +++ /dev/null @@ -1,448 +0,0 @@ -/* * Copyright (C) 2010-2012 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_platform_dvfs.c - * Platform specific Mali driver dvfs functions - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" - -#include -#include -#include -#include - -#include - -#ifdef CONFIG_CPU_FREQ -#include -#include -#define EXYNOS4_ASV_ENABLED -#endif - -#include "mali_device_pause_resume.h" -#include - -#define MALI_DVFS_WATING 10 // msec - -static int bMaliDvfsRun=0; - -#if MALI_GPU_BOTTOM_LOCK -static _mali_osk_atomic_t bottomlock_status; -#endif - -typedef struct mali_dvfs_tableTag{ - unsigned int clock; - unsigned int freq; - unsigned int vol; -}mali_dvfs_table; - -typedef struct mali_dvfs_statusTag{ - unsigned int currentStep; - mali_dvfs_table * pCurrentDvfs; - -}mali_dvfs_currentstatus; - -typedef struct mali_dvfs_thresholdTag{ - unsigned int downthreshold; - unsigned int upthreshold; -}mali_dvfs_threshold_table; - -typedef struct mali_dvfs_staycount{ - unsigned int staycount; -}mali_dvfs_staycount_table; - -mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={ - /*step 0*/{1}, - /*step 1*/{1}, - /*step 2*/{1} }; - -/*dvfs threshold*/ -mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={ - /*step 0*/{((int)((255*0)/100)) ,((int)((255*85)/100))}, - /*step 1*/{((int)((255*75)/100)) ,((int)((255*85)/100))}, - /*step 2*/{((int)((255*75)/100)) ,((int)((255*100)/100))} }; - -/*dvfs status*/ -mali_dvfs_currentstatus maliDvfsStatus; -int mali_dvfs_control=0; - -/*dvfs table*/ -mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ -#ifdef CONFIG_EXYNOS4210_1400MHZ_SUPPORT - /*step 0*/{134 ,1000000 , 950000}, -#else - /*step 0*/{100 ,1000000 , 950000}, -#endif - /*step 1*/{160 ,1000000 , 950000}, - /*step 2*/{267 ,1000000 ,1000000} }; - -#ifdef EXYNOS4_ASV_ENABLED - -#define ASV_8_LEVEL 8 -#define ASV_5_LEVEL 5 - -static unsigned int asv_3d_volt_5_table[ASV_5_LEVEL][MALI_DVFS_STEPS] = { - /* L3 (100/134MHz) L2(160MHz), L1(267MHz) */ - {1000000, 1000000, 1100000}, /* S */ - {1000000, 1000000, 1100000}, /* A */ - { 950000, 950000, 1000000}, /* B */ - { 950000, 950000, 1000000}, /* C */ - { 950000, 950000, 950000}, /* D */ -}; - -static unsigned int asv_3d_volt_8_table[ASV_8_LEVEL][MALI_DVFS_STEPS] = { - /* L3 (100/134MHz) L2(160MHz), L1(267MHz) */ - {1000000, 1000000, 1100000}, /* SS */ - {1000000, 1000000, 1100000}, /* A1 */ - {1000000, 1000000, 1100000}, /* A2 */ - { 950000, 950000, 1000000}, /* B1 */ - { 950000, 950000, 1000000}, /* B2 */ - { 950000, 950000, 1000000}, /* C1 */ - { 950000, 950000, 1000000}, /* C2 */ - { 950000, 950000, 950000}, /* D1 */ -}; -#endif - -static u32 mali_dvfs_utilization = 255; - -static void mali_dvfs_work_handler(struct work_struct *w); - -static struct workqueue_struct *mali_dvfs_wq = 0; -extern mali_io_address clk_register_map; - -#if MALI_GPU_BOTTOM_LOCK -extern _mali_osk_lock_t *mali_dvfs_lock; -#endif - -static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler); - -static unsigned int get_mali_dvfs_status(void) -{ - return maliDvfsStatus.currentStep; -} - -#if MALI_GPU_BOTTOM_LOCK -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -int get_mali_dvfs_control_status(void) -{ - return mali_dvfs_control; -} - -mali_bool set_mali_dvfs_current_step(unsigned int step) -{ - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - maliDvfsStatus.currentStep = step; - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - return MALI_TRUE; -} -#endif -#endif - -static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup) -{ - u32 validatedStep=step; - -#ifdef CONFIG_REGULATOR - if (mali_regulator_get_usecount()==0) { - MALI_DEBUG_PRINT(1, ("regulator use_count is 0 \n")); - return MALI_FALSE; - } -#endif - - if (boostup) { -#ifdef CONFIG_REGULATOR - /*change the voltage*/ - mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); -#endif - /*change the clock*/ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); - } else { - /*change the clock*/ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); -#ifdef CONFIG_REGULATOR - /*change the voltage*/ - mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); -#endif - } - - maliDvfsStatus.currentStep = validatedStep; - /*for future use*/ - maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep]; - - return MALI_TRUE; -} - -static void mali_platform_wating(u32 msec) -{ - /*sample wating - change this in the future with proper check routine. - */ - unsigned int read_val; - while(1) { - read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00); - if ((read_val & 0x8000)==0x0000) break; - - _mali_osk_time_ubusydelay(100); // 1000 -> 100 : 20101218 - } - /* _mali_osk_time_ubusydelay(msec*1000);*/ -} - -static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup ) -{ - - MALI_DEBUG_PRINT(1, ("> change_mali_dvfs_status: %d, %d \n",step, boostup)); - - if (!set_mali_dvfs_status(step, boostup)) { - MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup)); - return MALI_FALSE; - } - - /*wait until clock and voltage is stablized*/ - mali_platform_wating(MALI_DVFS_WATING); /*msec*/ - - return MALI_TRUE; -} - -static unsigned int decideNextStatus(unsigned int utilization) -{ - unsigned int level=0; // 0:stay, 1:up - - if (!mali_dvfs_control) { -#if MALI_GPU_BOTTOM_LOCK - if (_mali_osk_atomic_read(&bottomlock_status) > 0) - level = 1; /* or bigger */ - else -#endif - switch(maliDvfsStatus.currentStep) - { - case 0: - if( utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold) - level=1; - else - level = maliDvfsStatus.currentStep; - break; - case 1: - if( utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold) - level=2; - else if( utilization < - (mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold*mali_dvfs[maliDvfsStatus.currentStep-1].clock)/ - mali_dvfs[maliDvfsStatus.currentStep].clock) - level=0; - else - level = maliDvfsStatus.currentStep; - break; - case 2: - if( utilization < - (mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold*mali_dvfs[maliDvfsStatus.currentStep-1].clock)/ - mali_dvfs[maliDvfsStatus.currentStep].clock) - level=1; - else - level = maliDvfsStatus.currentStep; - break; - } - } - else - { - if((mali_dvfs_control == 1)||(( mali_dvfs_control > 3) && (mali_dvfs_control < mali_dvfs[0].clock+1))) - { - level=0; - } - else if((mali_dvfs_control == 2)||(( mali_dvfs_control > mali_dvfs[0].clock) && (mali_dvfs_control < mali_dvfs[1].clock+1))) - { - level=1; - } - else - { - level=2; - } - } - - return level; -} - -#ifdef EXYNOS4_ASV_ENABLED -static mali_bool mali_dvfs_table_update(void) -{ - unsigned int exynos_result_of_asv_group; - unsigned int target_asv; - unsigned int i; - exynos_result_of_asv_group = exynos_result_of_asv & 0xf; - target_asv = exynos_result_of_asv >> 28; - MALI_PRINT(("exynos_result_of_asv_group = 0x%x, target_asv = 0x%x\n", exynos_result_of_asv_group, target_asv)); - - if (target_asv == 0x8) { //SUPPORT_1400MHZ - for (i = 0; i < MALI_DVFS_STEPS; i++) { - mali_dvfs[i].vol = asv_3d_volt_5_table[exynos_result_of_asv_group][i]; - MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); - } - } else if (target_asv == 0x4){ //SUPPORT_1200MHZ - for (i = 0; i < MALI_DVFS_STEPS; i++) { - mali_dvfs[i].vol = asv_3d_volt_8_table[exynos_result_of_asv_group][i]; - MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); - } - } - - return MALI_TRUE; - -} -#endif - -static mali_bool mali_dvfs_status(u32 utilization) -{ - unsigned int nextStatus = 0; - unsigned int curStatus = 0; - mali_bool boostup = MALI_FALSE; -#ifdef EXYNOS4_ASV_ENABLED - static mali_bool asv_applied = MALI_FALSE; -#endif - static int stay_count = 0; // to prevent frequent switch - - MALI_DEBUG_PRINT(1, ("> mali_dvfs_status: %d \n",utilization)); -#ifdef EXYNOS4_ASV_ENABLED - if (asv_applied == MALI_FALSE) { - mali_dvfs_table_update(); - change_mali_dvfs_status(0,0); - asv_applied = MALI_TRUE; - - return MALI_TRUE; - } -#endif - - /*decide next step*/ - curStatus = get_mali_dvfs_status(); - nextStatus = decideNextStatus(utilization); - - MALI_DEBUG_PRINT(1, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep)); - - /*if next status is same with current status, don't change anything*/ - if ((curStatus!=nextStatus && stay_count==0)) { - /*check if boost up or not*/ - if (nextStatus > maliDvfsStatus.currentStep) - boostup = 1; - - /*change mali dvfs status*/ - if (!change_mali_dvfs_status(nextStatus,boostup)) { - MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n")); - return MALI_FALSE; - } - stay_count = mali_dvfs_staycount[maliDvfsStatus.currentStep].staycount; - } else { - if (stay_count>0) - stay_count--; - } - - return MALI_TRUE; -} - - - -int mali_dvfs_is_running(void) -{ - return bMaliDvfsRun; -} - - - -void mali_dvfs_late_resume(void) -{ - // set the init clock as low when resume - set_mali_dvfs_status(0,0); -} - - -static void mali_dvfs_work_handler(struct work_struct *w) -{ - bMaliDvfsRun=1; - - MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n")); - - if (!mali_dvfs_status(mali_dvfs_utilization)) - MALI_DEBUG_PRINT(1,( "error on mali dvfs status in mali_dvfs_work_handler")); - - bMaliDvfsRun=0; -} - - -mali_bool init_mali_dvfs_status(int step) -{ - /*default status - add here with the right function to get initilization value. - */ - if (!mali_dvfs_wq) - mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs"); - -#if MALI_GPU_BOTTOM_LOCK - _mali_osk_atomic_init(&bottomlock_status, 0); -#endif - - /*add a error handling here*/ - maliDvfsStatus.currentStep = step; - - return MALI_TRUE; -} - -void deinit_mali_dvfs_status(void) -{ -#if MALI_GPU_BOTTOM_LOCK - _mali_osk_atomic_term(&bottomlock_status); -#endif - - if (mali_dvfs_wq) - destroy_workqueue(mali_dvfs_wq); - mali_dvfs_wq = NULL; -} - -mali_bool mali_dvfs_handler(u32 utilization) -{ - mali_dvfs_utilization = utilization; - queue_work_on(0, mali_dvfs_wq,&mali_dvfs_work); - - /*add error handle here*/ - return MALI_TRUE; -} - -void mali_default_step_set(int step, mali_bool boostup) -{ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); - - if (maliDvfsStatus.currentStep == 1) - set_mali_dvfs_status(step, boostup); -} - -#if MALI_GPU_BOTTOM_LOCK -int mali_dvfs_bottom_lock_push(void) -{ - int prev_status = _mali_osk_atomic_read(&bottomlock_status); - - if (prev_status < 0) { - MALI_PRINT(("gpu bottom lock status is not valid for push")); - return -1; - } - - if (prev_status == 0) { - mali_regulator_set_voltage(mali_dvfs[1].vol, mali_dvfs[1].vol); - mali_clk_set_rate(mali_dvfs[1].clock, mali_dvfs[1].freq); - set_mali_dvfs_current_step(1); - } - - return _mali_osk_atomic_inc_return(&bottomlock_status); -} - -int mali_dvfs_bottom_lock_pop(void) -{ - if (_mali_osk_atomic_read(&bottomlock_status) <= 0) { - MALI_PRINT(("gpu bottom lock status is not valid for pop")); - return -1; - } - - return _mali_osk_atomic_dec_return(&bottomlock_status); -} -#endif diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c deleted file mode 100644 index a08bc97..0000000 --- a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c +++ /dev/null @@ -1,801 +0,0 @@ -/* Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_platform.c - * Platform specific Mali driver functions for a default platform - */ -#include -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" -#include "mali_linux_pm.h" - -#if USING_MALI_PMM -#include "mali_pm.h" -#endif - -#include -#include -#include -#include -#include - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#include -#endif - -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED -#include "mali_osk_profiling.h" -unsigned long gFreq = 366; -int gVolt = 5000; -#endif - -#include -#include - -#define EXTXTALCLK_NAME "ext_xtal" -#define VPLLSRCCLK_NAME "vpll_src" -#define FOUTVPLLCLK_NAME "fout_vpll" -#define SCLVPLLCLK_NAME "sclk_vpll" -#define GPUMOUT1CLK_NAME "mout_g3d1" - -#define MPLLCLK_NAME "mout_mpll" -#define GPUMOUT0CLK_NAME "mout_g3d0" -#define GPUCLK_NAME "sclk_g3d" -#define CLK_DIV_STAT_G3D 0x1003C62C -#define CLK_DESC "clk-divider-status" - -#define MALI_BOTTOMLOCK_VOL 900000 - -typedef struct mali_runtime_resumeTag{ - int clk; - int vol; -}mali_runtime_resume_table; - -mali_runtime_resume_table mali_runtime_resume = {266, 900000}; - -/* lock/unlock CPU freq by Mali */ -extern int cpufreq_lock_by_mali(unsigned int freq); -extern void cpufreq_unlock_by_mali(void); - -/* start of modification by skkim */ -extern mali_bool init_mali_dvfs_status(int step); -extern void deinit_mali_dvfs_status(void); -extern mali_bool mali_dvfs_handler(u32 utilization); -extern int get_mali_dvfs_control_status(void); -extern mali_bool set_mali_dvfs_current_step(unsigned int step); -/* end of modification by skkim */ - -static struct clk *ext_xtal_clock = 0; -static struct clk *vpll_src_clock = 0; -static struct clk *fout_vpll_clock = 0; -static struct clk *sclk_vpll_clock = 0; - -static struct clk *mpll_clock = 0; -static struct clk *mali_parent_clock = 0; -static struct clk *mali_clock = 0; - - -static unsigned int GPU_MHZ = 1000000; - -int mali_gpu_clk = 266; -int mali_gpu_vol = 900000; - -#if MALI_DVFS_ENABLED -#define MALI_DVFS_DEFAULT_STEP 1 -#endif -#if MALI_VOLTAGE_LOCK -int mali_lock_vol = 0; -static _mali_osk_atomic_t voltage_lock_status; -static mali_bool mali_vol_lock_flag = 0; -#endif - -int gpu_power_state; -static int bPoweroff; - -#ifdef CONFIG_REGULATOR -struct regulator { - struct device *dev; - struct list_head list; - int uA_load; - int min_uV; - int max_uV; - char *supply_name; - struct device_attribute dev_attr; - struct regulator_dev *rdev; -}; - -struct regulator *g3d_regulator=NULL; -#endif - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) -extern struct platform_device s5pv310_device_pd[]; -#else -extern struct platform_device exynos4_device_pd[]; -#endif -#endif - -mali_io_address clk_register_map=0; - -_mali_osk_lock_t *mali_dvfs_lock = 0; - -#ifdef CONFIG_REGULATOR -int mali_regulator_get_usecount(void) -{ - struct regulator_dev *rdev; - - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_get_usecount : g3d_regulator is null\n")); - return 0; - } - rdev = g3d_regulator->rdev; - return rdev->use_count; -} - -void mali_regulator_disable(void) -{ - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n")); - return; - } - regulator_disable(g3d_regulator); - MALI_DEBUG_PRINT(1, ("regulator_disable -> use cnt: %d \n",mali_regulator_get_usecount())); - bPoweroff = 1; -} - -void mali_regulator_enable(void) -{ - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n")); - return; - } - regulator_enable(g3d_regulator); - MALI_DEBUG_PRINT(1, ("regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); - bPoweroff = 0; -} - -void mali_regulator_set_voltage(int min_uV, int max_uV) -{ - int voltage; -#if !MALI_DVFS_ENABLED - min_uV = mali_gpu_vol; - max_uV = mali_gpu_vol; -#endif -#if MALI_VOLTAGE_LOCK - if (mali_vol_lock_flag == MALI_FALSE) { - if (min_uV < MALI_BOTTOMLOCK_VOL || max_uV < MALI_BOTTOMLOCK_VOL) { - min_uV = MALI_BOTTOMLOCK_VOL; - max_uV = MALI_BOTTOMLOCK_VOL; - } - } else if (_mali_osk_atomic_read(&voltage_lock_status) > 0 ) { - if (min_uV < mali_lock_vol || max_uV < mali_lock_vol) { -#if MALI_DVFS_ENABLED - int mali_vol_get; - mali_vol_get = mali_vol_get_from_table(mali_lock_vol); - if (mali_vol_get) { - min_uV = mali_vol_get; - max_uV = mali_vol_get; - } -#else - min_uV = mali_lock_vol; - max_uV = mali_lock_vol; -#endif - } - } -#endif - - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n")); - return; - } - - MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); - - regulator_set_voltage(g3d_regulator,min_uV,max_uV); - voltage = regulator_get_voltage(g3d_regulator); - -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - gVolt = voltage/1000; - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_GPU | - MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, gFreq, gVolt, - 0, 0, 0); -#endif - - mali_gpu_vol = voltage; - MALI_DEBUG_PRINT(1, ("= regulator_get_voltage: %d \n",mali_gpu_vol)); - - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); -} -#endif - -unsigned long mali_clk_get_rate(void) -{ - return clk_get_rate(mali_clock); -} - -mali_bool mali_clk_get(mali_bool bis_vpll) -{ - if (bis_vpll == MALI_TRUE) - { - if (ext_xtal_clock == NULL) - { - ext_xtal_clock = clk_get(NULL,EXTXTALCLK_NAME); - if (IS_ERR(ext_xtal_clock)) { - MALI_PRINT( ("MALI Error : failed to get source ext_xtal_clock\n")); - return MALI_FALSE; - } - } - - if (vpll_src_clock == NULL) - { - vpll_src_clock = clk_get(NULL,VPLLSRCCLK_NAME); - if (IS_ERR(vpll_src_clock)) { - MALI_PRINT( ("MALI Error : failed to get source vpll_src_clock\n")); - return MALI_FALSE; - } - } - - if (fout_vpll_clock == NULL) - { - fout_vpll_clock = clk_get(NULL,FOUTVPLLCLK_NAME); - if (IS_ERR(fout_vpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source fout_vpll_clock\n")); - return MALI_FALSE; - } - } - - if (sclk_vpll_clock == NULL) - { - sclk_vpll_clock = clk_get(NULL,SCLVPLLCLK_NAME); - if (IS_ERR(sclk_vpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source sclk_vpll_clock\n")); - return MALI_FALSE; - } - } - - if (mali_parent_clock == NULL) - { - mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME); - - if (IS_ERR(mali_parent_clock)) { - MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); - return MALI_FALSE; - } - } - } - else // mpll - { - if (mpll_clock == NULL) - { - mpll_clock = clk_get(NULL,MPLLCLK_NAME); - - if (IS_ERR(mpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source mpll clock\n")); - return MALI_FALSE; - } - } - - if (mali_parent_clock == NULL) - { - mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME); - - if (IS_ERR(mali_parent_clock)) { - MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); - return MALI_FALSE; - } - } - } - - // mali clock get always. - if (mali_clock == NULL) - { - mali_clock = clk_get(NULL, GPUCLK_NAME); - - if (IS_ERR(mali_clock)) { - MALI_PRINT( ("MALI Error : failed to get source mali clock\n")); - return MALI_FALSE; - } - } - - return MALI_TRUE; -} - -void mali_clk_put(mali_bool binc_mali_clock) -{ - if (mali_parent_clock) - { - clk_put(mali_parent_clock); - mali_parent_clock = 0; - } - - if (mpll_clock) - { - clk_put(mpll_clock); - mpll_clock = 0; - } - - if (sclk_vpll_clock) - { - clk_put(sclk_vpll_clock); - sclk_vpll_clock = 0; - } - - if (fout_vpll_clock) - { - clk_put(fout_vpll_clock); - fout_vpll_clock = 0; - } - - if (vpll_src_clock) - { - clk_put(vpll_src_clock); - vpll_src_clock = 0; - } - - if (ext_xtal_clock) - { - clk_put(ext_xtal_clock); - ext_xtal_clock = 0; - } - - if (binc_mali_clock == MALI_TRUE && mali_clock) - { - clk_put(mali_clock); - mali_clock = 0; - } - -} - - -mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz) -{ - unsigned long rate = 0; - mali_bool bis_vpll = MALI_TRUE; - -#ifndef CONFIG_VPLL_USE_FOR_TVENC - bis_vpll = MALI_TRUE; -#endif - -#if !MALI_DVFS_ENABLED - clk = mali_gpu_clk; -#endif - trace_printk("SPI_GPUFREQ_%uMHz\n", mali_gpu_clk); - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - if (mali_clk_get(bis_vpll) == MALI_FALSE) - return MALI_FALSE; - - rate = (unsigned long)clk * (unsigned long)mhz; - MALI_DEBUG_PRINT(3,("= clk_set_rate : %d , %d \n",clk, mhz )); - - if (bis_vpll) - { - clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ); - clk_set_parent(vpll_src_clock, ext_xtal_clock); - clk_set_parent(sclk_vpll_clock, fout_vpll_clock); - - clk_set_parent(mali_parent_clock, sclk_vpll_clock); - clk_set_parent(mali_clock, mali_parent_clock); - } - else - { - clk_set_parent(mali_parent_clock, mpll_clock); - clk_set_parent(mali_clock, mali_parent_clock); - } - - if (clk_enable(mali_clock) < 0) - return MALI_FALSE; - - - clk_set_rate(mali_clock, rate); - rate = clk_get_rate(mali_clock); - -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - gFreq = rate/1000000; - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_GPU | - MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, - gFreq, gVolt, 0, 0, 0); -#endif - - if (bis_vpll) - mali_gpu_clk = (int)(rate / mhz); - else - mali_gpu_clk = (int)((rate + 500000) / mhz); - - GPU_MHZ = mhz; - MALI_DEBUG_PRINT(3,("= clk_get_rate: %d \n",mali_gpu_clk)); - - mali_clk_put(MALI_FALSE); - - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - return MALI_TRUE; -} - -static mali_bool init_mali_clock(void) -{ - mali_bool ret = MALI_TRUE; - - if (mali_clock != 0) - return ret; // already initialized - - mali_dvfs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE - | _MALI_OSK_LOCKFLAG_ONELOCK, 0, 0); - if (mali_dvfs_lock == NULL) - return _MALI_OSK_ERR_FAULT; - - if (mali_clk_set_rate(mali_gpu_clk, GPU_MHZ) == MALI_FALSE) - { - ret = MALI_FALSE; - goto err_clock_get; - } - - MALI_PRINT(("init_mali_clock mali_clock %p \n", mali_clock)); - - -#ifdef CONFIG_REGULATOR -#if USING_MALI_PMM - g3d_regulator = regulator_get(&mali_gpu_device.dev, "vdd_g3d"); -#else - g3d_regulator = regulator_get(NULL, "vdd_g3d"); -#endif - - if (IS_ERR(g3d_regulator)) - { - MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n")); - ret = MALI_FALSE; - goto err_regulator; - } - - regulator_enable(g3d_regulator); - - MALI_DEBUG_PRINT(1, ("= regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); - mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol); -#endif - - MALI_DEBUG_PRINT(2, ("MALI Clock is set at mali driver\n")); - - MALI_DEBUG_PRINT(3,("::clk_put:: %s mali_parent_clock - normal\n", __FUNCTION__)); - MALI_DEBUG_PRINT(3,("::clk_put:: %s mpll_clock - normal\n", __FUNCTION__)); - - mali_clk_put(MALI_FALSE); - - gpu_power_state=0; - bPoweroff=1; - - return MALI_TRUE; -#ifdef CONFIG_REGULATOR -err_regulator: - regulator_put(g3d_regulator); -#endif - -err_clock_get: - mali_clk_put(MALI_TRUE); - - return ret; -} - -static mali_bool deinit_mali_clock(void) -{ - if (mali_clock == 0) - return MALI_TRUE; - -#ifdef CONFIG_REGULATOR - if (g3d_regulator) - { - regulator_put(g3d_regulator); - g3d_regulator=NULL; - } -#endif - - mali_clk_put(MALI_TRUE); - - return MALI_TRUE; -} -static _mali_osk_errcode_t enable_mali_clocks(void) -{ - int err; - err = clk_enable(mali_clock); - MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err)); - - mali_runtime_resume.vol = mali_dvfs_get_vol(MALI_DVFS_DEFAULT_STEP); -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#if MALI_DVFS_ENABLED - // set clock rate - if (get_mali_dvfs_control_status() != 0 || mali_gpu_clk >= mali_runtime_resume.clk) - mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); - else { - mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol); - mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ); - set_mali_dvfs_current_step(MALI_DVFS_DEFAULT_STEP); - } -#if CPUFREQ_LOCK_DURING_440 - /* lock/unlock CPU freq by Mali */ - if (mali_gpu_clk >= 440) - err = cpufreq_lock_by_mali(1200); -#endif -#else - mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol); - mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ); -#endif -#else - mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); -#endif - MALI_SUCCESS; -} - -static _mali_osk_errcode_t disable_mali_clocks(void) -{ - clk_disable(mali_clock); - MALI_DEBUG_PRINT(3,("disable_mali_clocks mali_clock %p \n", mali_clock)); - -#if MALI_DVFS_ENABLED && CPUFREQ_LOCK_DURING_440 - /* lock/unlock CPU freq by Mali */ - cpufreq_unlock_by_mali(); -#endif - MALI_SUCCESS; -} - -void set_mali_parent_power_domain(struct platform_device* dev) -{ -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) - dev->dev.parent = &s5pv310_device_pd[PD_G3D].dev; -#else - dev->dev.parent = &exynos4_device_pd[PD_G3D].dev; -#endif -#endif -} - -_mali_osk_errcode_t g3d_power_domain_control(int bpower_on) -{ - if (bpower_on) - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT(3,("_mali_osk_pmm_dev_activate \n")); - _mali_osk_pm_dev_activate(); -#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON - void __iomem *status; - u32 timeout; - __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_PMU_G3D_CONF); - status = S5P_PMU_G3D_CONF + 0x4; - - timeout = 10; - while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) - != S5P_INT_LOCAL_PWR_EN) { - if (timeout == 0) { - MALI_PRINTF(("Power domain enable failed.\n")); - return -ETIMEDOUT; - } - timeout--; - _mali_osk_time_ubusydelay(100); - } -#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON - } - else - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT( 4,("_mali_osk_pmm_dev_idle\n")); - _mali_osk_pm_dev_idle(); -#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON - void __iomem *status; - u32 timeout; - __raw_writel(0, S5P_PMU_G3D_CONF); - - status = S5P_PMU_G3D_CONF + 0x4; - /* Wait max 1ms */ - timeout = 10; - while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) - { - if (timeout == 0) { - MALI_PRINTF(("Power domain disable failed.\n" )); - return -ETIMEDOUT; - } - timeout--; - _mali_osk_time_ubusydelay( 100); - } -#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON - } - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_init() -{ - MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT); -#if MALI_VOLTAGE_LOCK - _mali_osk_atomic_init(&voltage_lock_status, 0); -#endif -#if MALI_DVFS_ENABLED - if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC ); - if(!init_mali_dvfs_status(MALI_DVFS_DEFAULT_STEP)) - MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n")); -#endif - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_deinit() -{ - deinit_mali_clock(); -#if MALI_VOLTAGE_LOCK - _mali_osk_atomic_term(&voltage_lock_status); -#endif -#if MALI_DVFS_ENABLED - deinit_mali_dvfs_status(); - if (clk_register_map ) - { - _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map); - clk_register_map=0; - } -#endif - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_powerdown(u32 cores) -{ - trace_printk("SPI_GPU_PWR Idle\n"); - MALI_DEBUG_PRINT(3,("power down is called in mali_platform_powerdown state %x core %x \n", gpu_power_state, cores)); - - if (gpu_power_state != 0) // power down after state is 0 - { - gpu_power_state = gpu_power_state & (~cores); - if (gpu_power_state == 0) - { - MALI_DEBUG_PRINT( 3,("disable clock\n")); - disable_mali_clocks(); - } - } - else - { - MALI_PRINT(("mali_platform_powerdown gpu_power_state == 0 and cores %x \n", cores)); - } - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_powerup(u32 cores) -{ - trace_printk("SPI_GPU_PWR Start\n"); - MALI_DEBUG_PRINT(3,("power up is called in mali_platform_powerup state %x core %x \n", gpu_power_state, cores)); - - if (gpu_power_state == 0) // power up only before state is 0 - { - gpu_power_state = gpu_power_state | cores; - - if (gpu_power_state != 0) - { - MALI_DEBUG_PRINT(4,("enable clock \n")); - enable_mali_clocks(); - } - } - else - { - gpu_power_state = gpu_power_state | cores; - } - - MALI_SUCCESS; -} - -void mali_gpu_utilization_handler(u32 utilization) -{ - if (bPoweroff==0) - { -#if MALI_DVFS_ENABLED - if(!mali_dvfs_handler(utilization)) - MALI_DEBUG_PRINT(1,( "error on mali dvfs status in utilization\n")); -#endif - } -} - -#if MALI_POWER_MGMT_TEST_SUITE -u32 pmu_get_power_up_down_info(void) -{ - return 4095; -} - -#endif - -_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) -{ - switch (power_mode) - { - case MALI_POWER_MODE_ON: - MALI_DEBUG_PRINT(1, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n", bPoweroff ? "powering on" : "already on")); - if (bPoweroff == 1) - { - /** If run time power management is used, donot call this function */ -#ifndef CONFIG_PM_RUNTIME - g3d_power_domain_control(1); -#endif - - MALI_DEBUG_PRINT(4,("enable clock \n")); - enable_mali_clocks(); -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| MALI_PROFILING_EVENT_CHANNEL_GPU|MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); -#endif - //MALI_PRINTF(("Mali Platform powered up")); - gpu_power_state=1; - bPoweroff=0; - } - break; - case MALI_POWER_MODE_LIGHT_SLEEP: - case MALI_POWER_MODE_DEEP_SLEEP: - MALI_DEBUG_PRINT(1, ("Mali platform: Got %s event, %s\n", - power_mode == MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" : "MALI_POWER_MODE_DEEP_SLEEP", - bPoweroff ? "already off" : "powering off")); - if (bPoweroff == 0) - { - disable_mali_clocks(); -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| MALI_PROFILING_EVENT_CHANNEL_GPU|MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0); -#endif - -#ifndef CONFIG_PM_RUNTIME - g3d_power_domain_control(0); -#endif - - //MALI_PRINTF(("Mali Platform powered down")); - gpu_power_state=0; - bPoweroff=1; - } - - break; - } - MALI_SUCCESS; -} - -#if MALI_VOLTAGE_LOCK -int mali_voltage_lock_push(int lock_vol) -{ - int prev_status = _mali_osk_atomic_read(&voltage_lock_status); - - if (prev_status < 0) { - MALI_PRINT(("gpu voltage lock status is not valid for push\n")); - return -1; - } - if (prev_status == 0) { - mali_lock_vol = lock_vol; - if (mali_gpu_vol < mali_lock_vol) - mali_regulator_set_voltage(mali_lock_vol, mali_lock_vol); - } else { - MALI_PRINT(("gpu voltage lock status is already pushed, current lock voltage : %d\n", mali_lock_vol)); - return -1; - } - - return _mali_osk_atomic_inc_return(&voltage_lock_status); -} - -int mali_voltage_lock_pop(void) -{ - if (_mali_osk_atomic_read(&voltage_lock_status) <= 0) { - MALI_PRINT(("gpu voltage lock status is not valid for pop\n")); - return -1; - } - return _mali_osk_atomic_dec_return(&voltage_lock_status); -} - -int mali_voltage_lock_init(void) -{ - mali_vol_lock_flag = MALI_TRUE; - - MALI_SUCCESS; -} -#endif diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c deleted file mode 100644 index cc1164e..0000000 --- a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c +++ /dev/null @@ -1,847 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_platform_dvfs.c - * Platform specific Mali driver dvfs functions - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" - -#include -#include -#include -#include - -#include - -#include "mali_device_pause_resume.h" -#include - -#define MAX_MALI_DVFS_STEPS 5 -#define MALI_DVFS_WATING 10 // msec - -#ifdef CONFIG_CPU_FREQ -#include -#define EXYNOS4_ASV_ENABLED -#endif - -#include - -static int bMaliDvfsRun=0; - -static _mali_osk_atomic_t bottomlock_status; -int bottom_lock_step = 0; - -typedef struct mali_dvfs_tableTag{ - unsigned int clock; - unsigned int freq; - unsigned int vol; -}mali_dvfs_table; - -typedef struct mali_dvfs_statusTag{ - unsigned int currentStep; - mali_dvfs_table * pCurrentDvfs; - -}mali_dvfs_currentstatus; - -typedef struct mali_dvfs_thresholdTag{ - unsigned int downthreshold; - unsigned int upthreshold; -}mali_dvfs_threshold_table; - -typedef struct mali_dvfs_staycount{ - unsigned int staycount; -}mali_dvfs_staycount_table; - -typedef struct mali_dvfs_stepTag{ - int clk; - int vol; -}mali_dvfs_step; - -mali_dvfs_step step[MALI_DVFS_STEPS]={ - /*step 0 clk*/ {160, 875000}, -#if (MALI_DVFS_STEPS > 1) - /*step 1 clk*/ {266, 900000}, -#if (MALI_DVFS_STEPS > 2) - /*step 2 clk*/ {350, 950000}, -#if (MALI_DVFS_STEPS > 3) - /*step 3 clk*/ {440, 1025000}, -#if (MALI_DVFS_STEPS > 4) - /*step 4 clk*/ {533, 1075000} -#endif -#endif -#endif -#endif -}; - -mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={ - /*step 0*/{0}, -#if (MALI_DVFS_STEPS > 1) - /*step 1*/{0}, -#if (MALI_DVFS_STEPS > 2) - /*step 2*/{0}, -#if (MALI_DVFS_STEPS > 3) - /*step 3*/{0}, -#if (MALI_DVFS_STEPS > 4) - /*step 4*/{0} -#endif -#endif -#endif -#endif -}; - -/* dvfs information */ -// L0 = 533Mhz, 1.075V -// L1 = 440Mhz, 1.025V -// L2 = 350Mhz, 0.95V -// L3 = 266Mhz, 0.90V -// L4 = 160Mhz, 0.875V - -int step0_clk = 160; -int step0_vol = 875000; -#if (MALI_DVFS_STEPS > 1) -int step1_clk = 266; -int step1_vol = 900000; -int step0_up = 70; -int step1_down = 62; -#if (MALI_DVFS_STEPS > 2) -int step2_clk = 350; -int step2_vol = 950000; -int step1_up = 90; -int step2_down = 85; -#if (MALI_DVFS_STEPS > 3) -int step3_clk = 440; -int step3_vol = 1025000; -int step2_up = 90; -int step3_down = 85; -#if (MALI_DVFS_STEPS > 4) -int step4_clk = 533; -int step4_vol = 1075000; -int step3_up = 90; -int step4_down = 95; -#endif -#endif -#endif -#endif - -mali_dvfs_table mali_dvfs_all[MAX_MALI_DVFS_STEPS]={ - {160 ,1000000 , 875000}, - {266 ,1000000 , 900000}, - {350 ,1000000 , 950000}, - {440 ,1000000 , 1025000}, - {533 ,1000000 , 1075000} }; - -mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ - {160 ,1000000 , 875000}, -#if (MALI_DVFS_STEPS > 1) - {266 ,1000000 , 900000}, -#if (MALI_DVFS_STEPS > 2) - {350 ,1000000 , 950000}, -#if (MALI_DVFS_STEPS > 3) - {440 ,1000000 ,1025000}, -#if (MALI_DVFS_STEPS > 4) - {533 ,1000000 ,1075000} -#endif -#endif -#endif -#endif -}; - -mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={ - {0 , 70}, -#if (MALI_DVFS_STEPS > 1) - {62 , 90}, -#if (MALI_DVFS_STEPS > 2) - {85 , 90}, -#if (MALI_DVFS_STEPS > 3) - {85 ,90}, -#if (MALI_DVFS_STEPS > 4) - {95 ,100} -#endif -#endif -#endif -#endif -}; - -#ifdef EXYNOS4_ASV_ENABLED -#define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */ -#define ASV_LEVEL_PRIME 13 /* ASV0, 1, 12 is reserved */ - -static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = { - { 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000, 900000, 900000, 900000, 875000}, /* L3(160Mhz) */ -#if (MALI_DVFS_STEPS > 1) - { 1000000, 975000, 975000, 975000, 950000, 950000, 950000, 900000, 900000, 900000, 900000, 875000}, /* L2(266Mhz) */ -#if (MALI_DVFS_STEPS > 2) - { 1075000, 1050000, 1050000, 1050000, 1000000, 1000000, 1000000, 975000, 975000, 975000, 975000, 925000}, /* L1(350Mhz) */ -#if (MALI_DVFS_STEPS > 3) - { 1125000, 1100000, 1100000, 1100000, 1075000, 1075000, 1075000, 1025000, 1025000, 1025000, 1025000, 975000}, /* L0(440Mhz) */ -#endif -#endif -#endif -}; - -static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS-1][ASV_LEVEL] = { - { 950000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */ -#if (MALI_DVFS_STEPS > 1) - { 975000, 950000, 925000, 925000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000}, /* L2(266Mhz) */ -#if (MALI_DVFS_STEPS > 2) - { 1050000, 1025000, 1000000, 1000000, 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000}, /* L1(350Mhz) */ -#if (MALI_DVFS_STEPS > 3) - { 1100000, 1075000, 1050000, 1050000, 1050000, 1025000, 1025000, 1000000, 1000000, 1000000, 975000, 950000}, /* L0(440Mhz) */ -#endif -#endif -#endif -}; - -static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL_PRIME] = { - { 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 875000, 862500, 850000, 850000}, /* L4(160Mhz) */ -#if (MALI_DVFS_STEPS > 1) - { 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 900000, 887500, 875000, 862500}, /* L3(266Mhz) */ -#if (MALI_DVFS_STEPS > 2) - { 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 925000, 912500}, /* L2(350Mhz) */ -#if (MALI_DVFS_STEPS > 3) - { 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000}, /* L1(440Mhz) */ -#if (MALI_DVFS_STEPS > 4) - { 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1087500, 1075000, 1062500, 1050000}, /* L0(600Mhz) */ -#endif -#endif -#endif -#endif -}; -#endif /* ASV_LEVEL */ - -/*dvfs status*/ -mali_dvfs_currentstatus maliDvfsStatus; -int mali_dvfs_control=0; - -static u32 mali_dvfs_utilization = 255; - -static void mali_dvfs_work_handler(struct work_struct *w); - -static struct workqueue_struct *mali_dvfs_wq = 0; -extern mali_io_address clk_register_map; -extern _mali_osk_lock_t *mali_dvfs_lock; - -int mali_runtime_resumed = -1; - -static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler); - -/* lock/unlock CPU freq by Mali */ -#include -#include - -atomic_t mali_cpufreq_lock; - -int cpufreq_lock_by_mali(unsigned int freq) -{ -#ifdef CONFIG_EXYNOS4_CPUFREQ -/* #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_ARCH_EXYNOS4) */ - unsigned int level; - - if (atomic_read(&mali_cpufreq_lock) == 0) { - if (exynos_cpufreq_get_level(freq * 1000, &level)) { - printk(KERN_ERR - "Mali: failed to get cpufreq level for %dMHz", - freq); - return -EINVAL; - } - - if (exynos_cpufreq_lock(DVFS_LOCK_ID_G3D, level)) { - printk(KERN_ERR - "Mali: failed to cpufreq lock for L%d", level); - return -EINVAL; - } - - atomic_set(&mali_cpufreq_lock, 1); - printk(KERN_DEBUG "Mali: cpufreq locked on <%d>%dMHz\n", level, - freq); - } -#endif - return 0; -} - -void cpufreq_unlock_by_mali(void) -{ -#ifdef CONFIG_EXYNOS4_CPUFREQ -/* #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_ARCH_EXYNOS4) */ - if (atomic_read(&mali_cpufreq_lock) == 1) { - exynos_cpufreq_lock_free(DVFS_LOCK_ID_G3D); - atomic_set(&mali_cpufreq_lock, 0); - printk(KERN_DEBUG "Mali: cpufreq locked off\n"); - } -#endif -} - -static unsigned int get_mali_dvfs_status(void) -{ - return maliDvfsStatus.currentStep; -} -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -int get_mali_dvfs_control_status(void) -{ - return mali_dvfs_control; -} - -mali_bool set_mali_dvfs_current_step(unsigned int step) -{ - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - maliDvfsStatus.currentStep = step % MAX_MALI_DVFS_STEPS; - if (step >= MAX_MALI_DVFS_STEPS) - mali_runtime_resumed = maliDvfsStatus.currentStep; - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - return MALI_TRUE; -} -#endif -static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup) -{ - u32 validatedStep=step; - int err; - -#ifdef CONFIG_REGULATOR - if (mali_regulator_get_usecount() == 0) { - MALI_DEBUG_PRINT(1, ("regulator use_count is 0 \n")); - return MALI_FALSE; - } -#endif - - if (boostup) { -#ifdef CONFIG_REGULATOR - /*change the voltage*/ - mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); -#endif - /*change the clock*/ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); - } else { - /*change the clock*/ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); -#ifdef CONFIG_REGULATOR - /*change the voltage*/ - mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); -#endif - } - -#ifdef EXYNOS4_ASV_ENABLED - if (samsung_rev() < EXYNOS4412_REV_2_0) { - if (mali_dvfs[step].clock == 160) - exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); - else - exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); - } -#endif - - - set_mali_dvfs_current_step(validatedStep); - /*for future use*/ - maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep]; - -#if CPUFREQ_LOCK_DURING_440 - /* lock/unlock CPU freq by Mali */ - if (mali_dvfs[step].clock == 440) - err = cpufreq_lock_by_mali(1200); - else - cpufreq_unlock_by_mali(); -#endif - - return MALI_TRUE; -} - -static void mali_platform_wating(u32 msec) -{ - /*sample wating - change this in the future with proper check routine. - */ - unsigned int read_val; - while(1) { - read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00); - if ((read_val & 0x8000)==0x0000) break; - _mali_osk_time_ubusydelay(100); // 1000 -> 100 : 20101218 - } - /* _mali_osk_time_ubusydelay(msec*1000);*/ -} - -static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup ) -{ - - MALI_DEBUG_PRINT(1, ("> change_mali_dvfs_status: %d, %d \n",step, boostup)); - - if (!set_mali_dvfs_status(step, boostup)) { - MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup)); - return MALI_FALSE; - } - - /*wait until clock and voltage is stablized*/ - mali_platform_wating(MALI_DVFS_WATING); /*msec*/ - - return MALI_TRUE; -} - -#ifdef EXYNOS4_ASV_ENABLED -extern unsigned int exynos_result_of_asv; - -static mali_bool mali_dvfs_table_update(void) -{ - unsigned int i; - unsigned int step_num = MALI_DVFS_STEPS; - - if(samsung_rev() < EXYNOS4412_REV_2_0) - step_num = MALI_DVFS_STEPS - 1; - - if(soc_is_exynos4412()) { - if (exynos_armclk_max == 1000000) { - MALI_PRINT(("::C::exynos_result_of_asv : %d\n", exynos_result_of_asv)); - for (i = 0; i < step_num; i++) { - mali_dvfs[i].vol = asv_3d_volt_9_table_1ghz_type[i][exynos_result_of_asv]; - MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); - } - } else if(((is_special_flag() >> G3D_LOCK_FLAG) & 0x1) && (samsung_rev() >= EXYNOS4412_REV_2_0)) { - MALI_PRINT(("::L::exynos_result_of_asv : %d\n", exynos_result_of_asv)); - for (i = 0; i < step_num; i++) { - mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv] + 25000; - MALI_PRINT(("mali_dvfs[%d].vol = %d \n ", i, mali_dvfs[i].vol)); - } - } else if (samsung_rev() >= EXYNOS4412_REV_2_0) { - MALI_PRINT(("::P::exynos_result_of_asv : %d\n", exynos_result_of_asv)); - for (i = 0; i < step_num; i++) { - mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv]; - MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); - } - } else { - MALI_PRINT(("::Q::exynos_result_of_asv : %d\n", exynos_result_of_asv)); - for (i = 0; i < step_num; i++) { - mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv]; - MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); - } - } - } - - return MALI_TRUE; -} -#endif - -static unsigned int decideNextStatus(unsigned int utilization) -{ - static unsigned int level = 0; // 0:stay, 1:up - static int mali_dvfs_clk = 0; - - if (mali_runtime_resumed >= 0) { - level = mali_runtime_resumed; - mali_runtime_resumed = -1; - } - - if (mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold - <= mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold) { - MALI_PRINT(("upthreadshold is smaller than downthreshold: %d < %d\n", - mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold, - mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold)); - return level; - } - - if (!mali_dvfs_control && level == maliDvfsStatus.currentStep) { - if (utilization > (int)(255 * mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold / 100) && - level < MALI_DVFS_STEPS - 1) { - level++; - if ((samsung_rev() < EXYNOS4412_REV_2_0) && (maliDvfsStatus.currentStep == 3)) { - level=get_mali_dvfs_status(); - } - } - if (utilization < (int)(255 * mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold / 100) && - level > 0) { - level--; - } - } else if (mali_dvfs_control == 999) { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[i].clock; - } -#ifdef EXYNOS4_ASV_ENABLED - mali_dvfs_table_update(); -#endif - i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - mali_dvfs[i].clock = step[i].clk; - } - mali_dvfs_control = 0; - level = 0; - - step0_clk = step[0].clk; - change_dvfs_tableset(step0_clk, 0); -#if (MALI_DVFS_STEPS > 1) - step1_clk = step[1].clk; - change_dvfs_tableset(step1_clk, 1); -#if (MALI_DVFS_STEPS > 2) - step2_clk = step[2].clk; - change_dvfs_tableset(step2_clk, 2); -#if (MALI_DVFS_STEPS > 3) - step3_clk = step[3].clk; - change_dvfs_tableset(step3_clk, 3); -#if (MALI_DVFS_STEPS > 4) - step4_clk = step[4].clk; - change_dvfs_tableset(step4_clk, 4); -#endif -#endif -#endif -#endif - } else if (mali_dvfs_control != mali_dvfs_clk && mali_dvfs_control != 999) { - if (mali_dvfs_control < mali_dvfs_all[1].clock && mali_dvfs_control > 0) { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[0].clock; - } - maliDvfsStatus.currentStep = 0; - } else if (mali_dvfs_control < mali_dvfs_all[2].clock && mali_dvfs_control >= mali_dvfs_all[1].clock) { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[1].clock; - } - maliDvfsStatus.currentStep = 1; - } else if (mali_dvfs_control < mali_dvfs_all[3].clock && mali_dvfs_control >= mali_dvfs_all[2].clock) { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[2].clock; - } - maliDvfsStatus.currentStep = 2; - } else if (mali_dvfs_control < mali_dvfs_all[4].clock && mali_dvfs_control >= mali_dvfs_all[3].clock) { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[3].clock; - } - maliDvfsStatus.currentStep = 3; - } else { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[4].clock; - } - maliDvfsStatus.currentStep = 4; - } - step0_clk = step[0].clk; - change_dvfs_tableset(step0_clk, 0); -#if (MALI_DVFS_STEPS > 1) - step1_clk = step[1].clk; - change_dvfs_tableset(step1_clk, 1); -#if (MALI_DVFS_STEPS > 2) - step2_clk = step[2].clk; - change_dvfs_tableset(step2_clk, 2); -#if (MALI_DVFS_STEPS > 3) - step3_clk = step[3].clk; - change_dvfs_tableset(step3_clk, 3); -#if (MALI_DVFS_STEPS > 4) - step4_clk = step[4].clk; - change_dvfs_tableset(step4_clk, 4); -#endif -#endif -#endif -#endif - level = maliDvfsStatus.currentStep; - } - - mali_dvfs_clk = mali_dvfs_control; - - if (_mali_osk_atomic_read(&bottomlock_status) > 0) { - if (level < bottom_lock_step) - level = bottom_lock_step; - } - - return level; -} - -static mali_bool mali_dvfs_status(u32 utilization) -{ - unsigned int nextStatus = 0; - unsigned int curStatus = 0; - mali_bool boostup = MALI_FALSE; - static int stay_count = 0; -#ifdef EXYNOS4_ASV_ENABLED - static mali_bool asv_applied = MALI_FALSE; -#endif - - MALI_DEBUG_PRINT(1, ("> mali_dvfs_status: %d \n",utilization)); -#ifdef EXYNOS4_ASV_ENABLED - if (asv_applied == MALI_FALSE) { - mali_dvfs_table_update(); - change_mali_dvfs_status(1, 0); - asv_applied = MALI_TRUE; - - return MALI_TRUE; - } -#endif - - /*decide next step*/ - curStatus = get_mali_dvfs_status(); - nextStatus = decideNextStatus(utilization); - - MALI_DEBUG_PRINT(1, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep)); - - /*if next status is same with current status, don't change anything*/ - if ((curStatus != nextStatus && stay_count == 0)) { - /*check if boost up or not*/ - if (nextStatus > maliDvfsStatus.currentStep) boostup = 1; - - /*change mali dvfs status*/ - if (!change_mali_dvfs_status(nextStatus,boostup)) { - MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n")); - return MALI_FALSE; - } - stay_count = mali_dvfs_staycount[maliDvfsStatus.currentStep].staycount; - } else { - if (stay_count > 0) - stay_count--; - } - - return MALI_TRUE; -} - - - -int mali_dvfs_is_running(void) -{ - return bMaliDvfsRun; - -} - - - -void mali_dvfs_late_resume(void) -{ - // set the init clock as low when resume - set_mali_dvfs_status(0,0); -} - - -static void mali_dvfs_work_handler(struct work_struct *w) -{ - int change_clk = 0; - int change_step = 0; - bMaliDvfsRun=1; - - /* dvfs table change when clock was changed */ - if (step0_clk != mali_dvfs[0].clock) { - MALI_PRINT(("::: step0_clk change to %d Mhz\n", step0_clk)); - change_clk = step0_clk; - change_step = 0; - step0_clk = change_dvfs_tableset(change_clk, change_step); - } -#if (MALI_DVFS_STEPS > 1) - if (step1_clk != mali_dvfs[1].clock) { - MALI_PRINT(("::: step1_clk change to %d Mhz\n", step1_clk)); - change_clk = step1_clk; - change_step = 1; - step1_clk = change_dvfs_tableset(change_clk, change_step); - } - if (step0_up != mali_dvfs_threshold[0].upthreshold) { - MALI_PRINT(("::: step0_up change to %d %\n", step0_up)); - mali_dvfs_threshold[0].upthreshold = step0_up; - } - if (step1_down != mali_dvfs_threshold[1].downthreshold) { - MALI_PRINT((":::step1_down change to %d %\n", step1_down)); - mali_dvfs_threshold[1].downthreshold = step1_down; - } -#if (MALI_DVFS_STEPS > 2) - if (step2_clk != mali_dvfs[2].clock) { - MALI_PRINT(("::: step2_clk change to %d Mhz\n", step2_clk)); - change_clk = step2_clk; - change_step = 2; - step2_clk = change_dvfs_tableset(change_clk, change_step); - } - if (step1_up != mali_dvfs_threshold[1].upthreshold) { - MALI_PRINT((":::step1_up change to %d %\n", step1_up)); - mali_dvfs_threshold[1].upthreshold = step1_up; - } - if (step2_down != mali_dvfs_threshold[2].downthreshold) { - MALI_PRINT((":::step2_down change to %d %\n", step2_down)); - mali_dvfs_threshold[2].downthreshold = step2_down; - } -#if (MALI_DVFS_STEPS > 3) - if (step3_clk != mali_dvfs[3].clock) { - MALI_PRINT(("::: step3_clk change to %d Mhz\n", step3_clk)); - change_clk = step3_clk; - change_step = 3; - step3_clk = change_dvfs_tableset(change_clk, change_step); - } - if (step2_up != mali_dvfs_threshold[2].upthreshold) { - MALI_PRINT((":::step2_up change to %d %\n", step2_up)); - mali_dvfs_threshold[2].upthreshold = step2_up; - } - if (step3_down != mali_dvfs_threshold[3].downthreshold) { - MALI_PRINT((":::step3_down change to %d %\n", step3_down)); - mali_dvfs_threshold[3].downthreshold = step3_down; - } -#if (MALI_DVFS_STEPS > 4) - if (step4_clk != mali_dvfs[4].clock) { - MALI_PRINT(("::: step4_clk change to %d Mhz\n", step4_clk)); - change_clk = step4_clk; - change_step = 4; - step4_clk = change_dvfs_tableset(change_clk, change_step); - } - if (step3_up != mali_dvfs_threshold[3].upthreshold) { - MALI_PRINT((":::step3_up change to %d %\n", step3_up)); - mali_dvfs_threshold[3].upthreshold = step3_up; - } - if (step4_down != mali_dvfs_threshold[4].downthreshold) { - MALI_PRINT((":::step4_down change to %d %\n", step4_down)); - mali_dvfs_threshold[4].downthreshold = step4_down; - } -#endif -#endif -#endif -#endif - - -#ifdef DEBUG - mali_dvfs[0].vol = step0_vol; - mali_dvfs[1].vol = step1_vol; - mali_dvfs[2].vol = step2_vol; - mali_dvfs[3].vol = step3_vol; - mali_dvfs[4].vol = step4_vol; -#endif - MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n")); - - if (!mali_dvfs_status(mali_dvfs_utilization)) - MALI_DEBUG_PRINT(1,( "error on mali dvfs status in mali_dvfs_work_handler")); - - bMaliDvfsRun=0; -} - -mali_bool init_mali_dvfs_status(int step) -{ - /*default status - add here with the right function to get initilization value. - */ - if (!mali_dvfs_wq) - mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs"); - - _mali_osk_atomic_init(&bottomlock_status, 0); - - /*add a error handling here*/ - set_mali_dvfs_current_step(step); - - return MALI_TRUE; -} - -void deinit_mali_dvfs_status(void) -{ - if (mali_dvfs_wq) - destroy_workqueue(mali_dvfs_wq); - - _mali_osk_atomic_term(&bottomlock_status); - - mali_dvfs_wq = NULL; -} - -mali_bool mali_dvfs_handler(u32 utilization) -{ - mali_dvfs_utilization = utilization; - queue_work_on(0, mali_dvfs_wq,&mali_dvfs_work); - - /*add error handle here*/ - return MALI_TRUE; -} - -int change_dvfs_tableset(int change_clk, int change_step) -{ - int err; - - if (change_clk < mali_dvfs_all[1].clock) { - mali_dvfs[change_step].clock = mali_dvfs_all[0].clock; - } else if (change_clk < mali_dvfs_all[2].clock && change_clk >= mali_dvfs_all[1].clock) { - mali_dvfs[change_step].clock = mali_dvfs_all[1].clock; - } else if (change_clk < mali_dvfs_all[3].clock && change_clk >= mali_dvfs_all[2].clock) { - mali_dvfs[change_step].clock = mali_dvfs_all[2].clock; - } else if (change_clk < mali_dvfs_all[4].clock && change_clk >= mali_dvfs_all[3].clock) { - mali_dvfs[change_step].clock = mali_dvfs_all[3].clock; - } else { - mali_dvfs[change_step].clock = mali_dvfs_all[4].clock; - } - - MALI_PRINT((":::mali dvfs step %d clock and voltage = %d Mhz, %d V\n",change_step, mali_dvfs[change_step].clock, mali_dvfs[change_step].vol)); - - if (maliDvfsStatus.currentStep == change_step) { -#ifdef CONFIG_REGULATOR - /*change the voltage*/ - mali_regulator_set_voltage(mali_dvfs[change_step].vol, mali_dvfs[change_step].vol); -#endif - /*change the clock*/ - mali_clk_set_rate(mali_dvfs[change_step].clock, mali_dvfs[change_step].freq); - -#if CPUFREQ_LOCK_DURING_440 - /* lock/unlock CPU freq by Mali */ - if (mali_dvfs[change_step].clock == 440) - err = cpufreq_lock_by_mali(1200); - else - cpufreq_unlock_by_mali(); -#endif - } - - return mali_dvfs[change_step].clock; -} - -void mali_default_step_set(int step, mali_bool boostup) -{ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); - - if (maliDvfsStatus.currentStep == 1) - set_mali_dvfs_status(step, boostup); -} - -int mali_dvfs_bottom_lock_push(int lock_step) -{ - int prev_status = _mali_osk_atomic_read(&bottomlock_status); - - if (prev_status < 0) { - MALI_PRINT(("gpu bottom lock status is not valid for push\n")); - return -1; - } - if (bottom_lock_step < lock_step) { - bottom_lock_step = lock_step; - if (get_mali_dvfs_status() < lock_step) { - mali_regulator_set_voltage(mali_dvfs[lock_step].vol, mali_dvfs[lock_step].vol); - mali_clk_set_rate(mali_dvfs[lock_step].clock, mali_dvfs[lock_step].freq); - set_mali_dvfs_current_step(lock_step); - } - } - return _mali_osk_atomic_inc_return(&bottomlock_status); -} - -int mali_dvfs_bottom_lock_pop(void) -{ - int prev_status = _mali_osk_atomic_read(&bottomlock_status); - if (prev_status <= 0) { - MALI_PRINT(("gpu bottom lock status is not valid for pop\n")); - return -1; - } else if (prev_status == 1) { - bottom_lock_step = 0; - MALI_PRINT(("gpu bottom lock release\n")); - } - - return _mali_osk_atomic_dec_return(&bottomlock_status); -} - -int mali_dvfs_get_vol(int step) -{ - step = step % MAX_MALI_DVFS_STEPS; - MALI_DEBUG_ASSERT(step= vol) - return mali_dvfs[i].vol; - } - MALI_PRINT(("Failed to get voltage from mali_dvfs table, maximum voltage is %d uV\n", mali_dvfs[MALI_DVFS_STEPS-1].vol)); - return 0; -} -#endif diff --git a/drivers/media/video/samsung/mali/regs/mali_200_regs.h b/drivers/media/video/samsung/mali/regs/mali_200_regs.h deleted file mode 100644 index 59e92c8..0000000 --- a/drivers/media/video/samsung/mali/regs/mali_200_regs.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _MALI200_REGS_H_ -#define _MALI200_REGS_H_ - -/** - * Enum for management register addresses. - */ -enum mali200_mgmt_reg -{ - MALI200_REG_ADDR_MGMT_VERSION = 0x1000, - MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x1004, - MALI200_REG_ADDR_MGMT_STATUS = 0x1008, - MALI200_REG_ADDR_MGMT_CTRL_MGMT = 0x100c, - - MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x1020, - MALI200_REG_ADDR_MGMT_INT_CLEAR = 0x1024, - MALI200_REG_ADDR_MGMT_INT_MASK = 0x1028, - MALI200_REG_ADDR_MGMT_INT_STATUS = 0x102c, - - MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW = 0x1044, - - MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x1050, - - MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x1080, - MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x1084, - MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x108c, - - MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x10a0, - MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x10a4, - MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x10ac, - - MALI200_REG_SIZEOF_REGISTER_BANK = 0x10f0 - -}; - -#define MALI200_REG_VAL_PERF_CNT_ENABLE 1 - -enum mali200_mgmt_ctrl_mgmt { - MALI200_REG_VAL_CTRL_MGMT_STOP_BUS = (1<<0), -#if defined(USING_MALI200) - MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES = (1<<3), -#endif - MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET = (1<<5), - MALI200_REG_VAL_CTRL_MGMT_START_RENDERING = (1<<6), -#if defined(USING_MALI400) || defined(USING_MALI450) - MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET = (1<<7), -#endif -}; - -enum mali200_mgmt_irq { - MALI200_REG_VAL_IRQ_END_OF_FRAME = (1<<0), - MALI200_REG_VAL_IRQ_END_OF_TILE = (1<<1), - MALI200_REG_VAL_IRQ_HANG = (1<<2), - MALI200_REG_VAL_IRQ_FORCE_HANG = (1<<3), - MALI200_REG_VAL_IRQ_BUS_ERROR = (1<<4), - MALI200_REG_VAL_IRQ_BUS_STOP = (1<<5), - MALI200_REG_VAL_IRQ_CNT_0_LIMIT = (1<<6), - MALI200_REG_VAL_IRQ_CNT_1_LIMIT = (1<<7), - MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR = (1<<8), - MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND = (1<<9), - MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW = (1<<10), - MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW = (1<<11), - MALI400PP_REG_VAL_IRQ_RESET_COMPLETED = (1<<12), -}; - -#if defined(USING_MALI200) -#define MALI200_REG_VAL_IRQ_MASK_ALL ((enum mali200_mgmt_irq) (\ - MALI200_REG_VAL_IRQ_END_OF_FRAME |\ - MALI200_REG_VAL_IRQ_END_OF_TILE |\ - MALI200_REG_VAL_IRQ_HANG |\ - MALI200_REG_VAL_IRQ_FORCE_HANG |\ - MALI200_REG_VAL_IRQ_BUS_ERROR |\ - MALI200_REG_VAL_IRQ_BUS_STOP |\ - MALI200_REG_VAL_IRQ_CNT_0_LIMIT |\ - MALI200_REG_VAL_IRQ_CNT_1_LIMIT |\ - MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR)) -#elif defined(USING_MALI400) || defined(USING_MALI450) -#define MALI200_REG_VAL_IRQ_MASK_ALL ((enum mali200_mgmt_irq) (\ - MALI200_REG_VAL_IRQ_END_OF_FRAME |\ - MALI200_REG_VAL_IRQ_END_OF_TILE |\ - MALI200_REG_VAL_IRQ_HANG |\ - MALI200_REG_VAL_IRQ_FORCE_HANG |\ - MALI200_REG_VAL_IRQ_BUS_ERROR |\ - MALI200_REG_VAL_IRQ_BUS_STOP |\ - MALI200_REG_VAL_IRQ_CNT_0_LIMIT |\ - MALI200_REG_VAL_IRQ_CNT_1_LIMIT |\ - MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR |\ - MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND |\ - MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW |\ - MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW |\ - MALI400PP_REG_VAL_IRQ_RESET_COMPLETED)) -#else -#error "No supported mali core defined" -#endif - -#if defined(USING_MALI200) -#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\ - MALI200_REG_VAL_IRQ_END_OF_FRAME |\ - MALI200_REG_VAL_IRQ_HANG |\ - MALI200_REG_VAL_IRQ_FORCE_HANG |\ - MALI200_REG_VAL_IRQ_BUS_ERROR |\ - MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR)) -#elif defined(USING_MALI400) || defined(USING_MALI450) -#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\ - MALI200_REG_VAL_IRQ_END_OF_FRAME |\ - MALI200_REG_VAL_IRQ_HANG |\ - MALI200_REG_VAL_IRQ_FORCE_HANG |\ - MALI200_REG_VAL_IRQ_BUS_ERROR |\ - MALI200_REG_VAL_IRQ_BUS_STOP |\ - MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR |\ - MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND |\ - MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW |\ - MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW)) -#else -#error "No supported mali core defined" -#endif - -#define MALI200_REG_VAL_IRQ_MASK_NONE ((enum mali200_mgmt_irq)(0)) - -enum mali200_mgmt_status { - MALI200_REG_VAL_STATUS_RENDERING_ACTIVE = (1<<0), - MALI200_REG_VAL_STATUS_BUS_STOPPED = (1<<4), -}; - -enum mali200_render_unit -{ - MALI200_REG_ADDR_FRAME = 0x0000, - MALI200_REG_ADDR_STACK = 0x0030 -}; - -#if defined(USING_MALI200) -#define MALI200_NUM_REGS_FRAME ((0x04C/4)+1) -#elif defined(USING_MALI400) -#define MALI200_NUM_REGS_FRAME ((0x058/4)+1) -#elif defined(USING_MALI450) -#define MALI200_NUM_REGS_FRAME ((0x058/4)+1) -#else -#error "No supported mali core defined" -#endif - -enum mali200_wb_unit { - MALI200_REG_ADDR_WB0 = 0x0100, - MALI200_REG_ADDR_WB1 = 0x0200, - MALI200_REG_ADDR_WB2 = 0x0300 -}; - -enum mali200_wb_unit_regs { - MALI200_REG_ADDR_WB_SOURCE_SELECT = 0x0000, -}; - -/** The number of registers in one single writeback unit */ -#ifndef MALI200_NUM_REGS_WBx -#define MALI200_NUM_REGS_WBx ((0x02C/4)+1) -#endif - -/* This should be in the top 16 bit of the version register of Mali PP */ -#define MALI200_PP_PRODUCT_ID 0xC807 -#define MALI300_PP_PRODUCT_ID 0xCE07 -#define MALI400_PP_PRODUCT_ID 0xCD07 -#define MALI450_PP_PRODUCT_ID 0xCF07 - - -#endif /* _MALI200_REGS_H_ */ diff --git a/drivers/media/video/samsung/mali/regs/mali_gp_regs.h b/drivers/media/video/samsung/mali/regs/mali_gp_regs.h deleted file mode 100644 index 21c83c0..0000000 --- a/drivers/media/video/samsung/mali/regs/mali_gp_regs.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _MALIGP2_CONROL_REGS_H_ -#define _MALIGP2_CONROL_REGS_H_ - -/** - * These are the different geometry processor control registers. - * Their usage is to control and monitor the operation of the - * Vertex Shader and the Polygon List Builder in the geometry processor. - * Addresses are in 32-bit word relative sizes. - * @see [P0081] "Geometry Processor Data Structures" for details - */ - -typedef enum { - MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR = 0x00, - MALIGP2_REG_ADDR_MGMT_VSCL_END_ADDR = 0x04, - MALIGP2_REG_ADDR_MGMT_PLBUCL_START_ADDR = 0x08, - MALIGP2_REG_ADDR_MGMT_PLBUCL_END_ADDR = 0x0c, - MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR = 0x10, - MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR = 0x14, - MALIGP2_REG_ADDR_MGMT_CMD = 0x20, - MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT = 0x24, - MALIGP2_REG_ADDR_MGMT_INT_CLEAR = 0x28, - MALIGP2_REG_ADDR_MGMT_INT_MASK = 0x2C, - MALIGP2_REG_ADDR_MGMT_INT_STAT = 0x30, - MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW = 0x34, - MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x3C, - MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x40, - MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x44, - MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x48, - MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x4C, - MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x50, - MALIGP2_REG_ADDR_MGMT_STATUS = 0x68, - MALIGP2_REG_ADDR_MGMT_VERSION = 0x6C, - MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR_READ = 0x80, - MALIGP2_REG_ADDR_MGMT_PLBCL_START_ADDR_READ = 0x84, - MALIGP2_CONTR_AXI_BUS_ERROR_STAT = 0x94, - MALIGP2_REGISTER_ADDRESS_SPACE_SIZE = 0x98, -} maligp_reg_addr_mgmt_addr; - -#define MALIGP2_REG_VAL_PERF_CNT_ENABLE 1 - -/** - * Commands to geometry processor. - * @see MALIGP2_CTRL_REG_CMD - */ -typedef enum -{ - MALIGP2_REG_VAL_CMD_START_VS = (1<< 0), - MALIGP2_REG_VAL_CMD_START_PLBU = (1<< 1), - MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC = (1<< 4), - MALIGP2_REG_VAL_CMD_RESET = (1<< 5), - MALIGP2_REG_VAL_CMD_FORCE_HANG = (1<< 6), - MALIGP2_REG_VAL_CMD_STOP_BUS = (1<< 9), -#if defined(USING_MALI400) || defined(USING_MALI450) - MALI400GP_REG_VAL_CMD_SOFT_RESET = (1<<10), -#endif -} mgp_contr_reg_val_cmd; - - -/** @defgroup MALIGP2_IRQ - * Interrupt status of geometry processor. - * @see MALIGP2_CTRL_REG_INT_RAWSTAT, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, - * MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_ADDR_MGMT_INT_STAT - * @{ - */ -#define MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST (1 << 0) -#define MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST (1 << 1) -#define MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM (1 << 2) -#define MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ (1 << 3) -#define MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ (1 << 4) -#define MALIGP2_REG_VAL_IRQ_HANG (1 << 5) -#define MALIGP2_REG_VAL_IRQ_FORCE_HANG (1 << 6) -#define MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT (1 << 7) -#define MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT (1 << 8) -#define MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR (1 << 9) -#define MALIGP2_REG_VAL_IRQ_SYNC_ERROR (1 << 10) -#define MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR (1 << 11) -#if defined(USING_MALI400) || defined(USING_MALI450) -#define MALI400GP_REG_VAL_IRQ_AXI_BUS_STOPPED (1 << 12) -#define MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD (1 << 13) -#define MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD (1 << 14) -#define MALI400GP_REG_VAL_IRQ_RESET_COMPLETED (1 << 19) -#define MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW (1 << 20) -#define MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW (1 << 21) -#define MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS (1 << 22) -#elif !defined USING_MALI200 -#error "No supported mali core defined" -#endif - -/* Mask defining all IRQs in MaliGP2 */ -#if defined(USING_MALI200) -#define MALIGP2_REG_VAL_IRQ_MASK_ALL \ - (\ - MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ - MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ | \ - MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ | \ - MALIGP2_REG_VAL_IRQ_HANG | \ - MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ - MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT | \ - MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT | \ - MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ - MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ - MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR) -#elif defined(USING_MALI400) || defined(USING_MALI450) -#define MALIGP2_REG_VAL_IRQ_MASK_ALL \ - (\ - MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ - MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ | \ - MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ | \ - MALIGP2_REG_VAL_IRQ_HANG | \ - MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ - MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT | \ - MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT | \ - MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ - MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ - MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR | \ - MALI400GP_REG_VAL_IRQ_AXI_BUS_STOPPED | \ - MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD | \ - MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD | \ - MALI400GP_REG_VAL_IRQ_RESET_COMPLETED | \ - MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \ - MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW | \ - MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS) -#else -#error "No supported mali core defined" -#endif - -/* Mask defining the IRQs in MaliGP2 which we use*/ -#if defined(USING_MALI200) -#define MALIGP2_REG_VAL_IRQ_MASK_USED \ - (\ - MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ - MALIGP2_REG_VAL_IRQ_HANG | \ - MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ - MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ - MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ - MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR) -#elif defined(USING_MALI400) || defined(USING_MALI450) -#define MALIGP2_REG_VAL_IRQ_MASK_USED \ - (\ - MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ - MALIGP2_REG_VAL_IRQ_HANG | \ - MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ - MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ - MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ - MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR | \ - MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD | \ - MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD | \ - MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \ - MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW | \ - MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS) -#else -#error "No supported mali core defined" -#endif - -/* Mask defining non IRQs on MaliGP2*/ -#define MALIGP2_REG_VAL_IRQ_MASK_NONE 0 - -/** }@ defgroup MALIGP2_IRQ*/ - -/** @defgroup MALIGP2_STATUS - * The different Status values to the geometry processor. - * @see MALIGP2_CTRL_REG_STATUS - * @{ - */ -#define MALIGP2_REG_VAL_STATUS_VS_ACTIVE 0x0002 -#define MALIGP2_REG_VAL_STATUS_BUS_STOPPED 0x0004 -#define MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE 0x0008 -#define MALIGP2_REG_VAL_STATUS_BUS_ERROR 0x0040 -#define MALIGP2_REG_VAL_STATUS_WRITE_BOUND_ERR 0x0100 -/** }@ defgroup MALIGP2_STATUS*/ - -#define MALIGP2_REG_VAL_STATUS_MASK_ACTIVE (\ - MALIGP2_REG_VAL_STATUS_VS_ACTIVE|\ - MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE) - - -#define MALIGP2_REG_VAL_STATUS_MASK_ERROR (\ - MALIGP2_REG_VAL_STATUS_BUS_ERROR |\ - MALIGP2_REG_VAL_STATUS_WRITE_BOUND_ERR ) - -/* This should be in the top 16 bit of the version register of gp.*/ -#define MALI200_GP_PRODUCT_ID 0xA07 -#define MALI300_GP_PRODUCT_ID 0xC07 -#define MALI400_GP_PRODUCT_ID 0xB07 -#define MALI450_GP_PRODUCT_ID 0xD07 - -/** - * The different sources for instrumented on the geometry processor. - * @see MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC - */ - -enum MALIGP2_cont_reg_perf_cnt_src { - MALIGP2_REG_VAL_PERF_CNT1_SRC_NUMBER_OF_VERTICES_PROCESSED = 0x0a, -}; - -#endif diff --git a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c b/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c deleted file mode 100644 index 2426853..0000000 --- a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_timestamp.h" - -/* This file is intentionally left empty, as all functions are inlined in mali_profiling_sampler.h */ diff --git a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h b/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h deleted file mode 100644 index 0551726..0000000 --- a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_TIMESTAMP_H__ -#define __MALI_TIMESTAMP_H__ - -#include "mali_osk.h" - -MALI_STATIC_INLINE _mali_osk_errcode_t _mali_timestamp_reset(void) -{ - /* - * reset counters and overflow flags - */ - - u32 mask = (1 << 0) | /* enable all three counters */ - (0 << 1) | /* reset both Count Registers to 0x0 */ - (1 << 2) | /* reset the Cycle Counter Register to 0x0 */ - (0 << 3) | /* 1 = Cycle Counter Register counts every 64th processor clock cycle */ - (0 << 4) | /* Count Register 0 interrupt enable */ - (0 << 5) | /* Count Register 1 interrupt enable */ - (0 << 6) | /* Cycle Counter interrupt enable */ - (0 << 8) | /* Count Register 0 overflow flag (clear or write, flag on read) */ - (0 << 9) | /* Count Register 1 overflow flag (clear or write, flag on read) */ - (1 << 10); /* Cycle Counter Register overflow flag (clear or write, flag on read) */ - - __asm__ __volatile__ ("MCR p15, 0, %0, c15, c12, 0" : : "r" (mask) ); - - return _MALI_OSK_ERR_OK; -} - -MALI_STATIC_INLINE u64 _mali_timestamp_get(void) -{ - u32 result; - - /* this is for the clock cycles */ - __asm__ __volatile__ ("MRC p15, 0, %0, c15, c12, 1" : "=r" (result)); - - return (u64)result; -} - -#endif /* __MALI_TIMESTAMP_H__ */ diff --git a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c b/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c deleted file mode 100644 index 2426853..0000000 --- a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_timestamp.h" - -/* This file is intentionally left empty, as all functions are inlined in mali_profiling_sampler.h */ diff --git a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h b/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h deleted file mode 100644 index e6d3f2a..0000000 --- a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_TIMESTAMP_H__ -#define __MALI_TIMESTAMP_H__ - -#include "mali_osk.h" - -MALI_STATIC_INLINE _mali_osk_errcode_t _mali_timestamp_reset(void) -{ - return _MALI_OSK_ERR_OK; -} - -MALI_STATIC_INLINE u64 _mali_timestamp_get(void) -{ - return _mali_osk_time_get_ns(); -} - -#endif /* __MALI_TIMESTAMP_H__ */ diff --git a/drivers/media/video/samsung/ump/Kconfig b/drivers/media/video/samsung/ump/Kconfig deleted file mode 100644 index 9d8e5e6..0000000 --- a/drivers/media/video/samsung/ump/Kconfig +++ /dev/null @@ -1,58 +0,0 @@ - -# -## S3C Multimedia Mali configuration -## -# -# For UMP -config VIDEO_UMP - bool "Enable UMP(Unified Memory Provider)" - default y - ---help--- - This enables UMP memory provider - -config UMP_VCM_ALLOC - depends on VIDEO_UMP && VCM - default y - bool "Enable ump-vcm(virtual contiguous memory) memory" - help - Use VCM(virtual-contiguous-memory) to allocate physical memory. - - -config UMP_R3P1_LSI - bool "Uses the R3P1 as a ump module" - depends on VIDEO_UMP - default n - ---help--- - This uses the r3p1 as a UMP kernel module - -choice -depends on VIDEO_UMP -prompt "UMP MEMEMORY OPTION" -default UMP_OSMEM_ONLY -config UMP_DED_ONLY - bool "ump dedicated memory only" - ---help--- - This enables UMP dedicated memory only option -config UMP_OSMEM_ONLY - bool "ump OS memory only" - ---help--- - This enables UMP OS memory only option -config UMP_VCM_ONLY - bool "ump VCM memory" - ---help--- - This enables UMP VCM memory only option - -endchoice -config UMP_MEM_SIZE -int "UMP Memory Size" - depends on VIDEO_UMP - default "512" - ---help--- - This value is dedicated memory size of UMP (unit is MByte). -# For UMP_DEBUG -config VIDEO_UMP_DEBUG - bool "Enables debug messages" - depends on VIDEO_UMP - default n - help - This enables UMP driver debug messages. diff --git a/drivers/media/video/samsung/ump/Kconfig_module b/drivers/media/video/samsung/ump/Kconfig_module deleted file mode 100644 index 3ae316c..0000000 --- a/drivers/media/video/samsung/ump/Kconfig_module +++ /dev/null @@ -1,16 +0,0 @@ -config UMP - tristate "UMP support" - depends on ARM - ---help--- - This enables support for the UMP memory allocation and sharing API. - - To compile this driver as a module, choose M here: the module will be - called ump. - -config UMP_DEBUG - bool "Enable extra debug in UMP" - depends on UMP - default y - ---help--- - This enabled extra debug checks and messages in UMP. - diff --git a/drivers/media/video/samsung/ump/Makefile b/drivers/media/video/samsung/ump/Makefile deleted file mode 100644 index 3a1aac0..0000000 --- a/drivers/media/video/samsung/ump/Makefile +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright (C) 2010-2012 ARM Limited. All rights reserved. -# -# This program is free software and is provided to you under the terms of the GNU General Public License version 2 -# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. -# -# A copy of the licence is included with the program, and can also be obtained from Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# - -ifeq ($(CONFIG_UMP_DED_ONLY),y) -UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) -USING_MEMORY=0 -endif - -ifeq ($(CONFIG_UMP_OSMEM_ONLY),y) -UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) -USING_MEMORY=1 -endif - -ifeq ($(CONFIG_UMP_VCM_ONLY),y) -UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) -USING_MEMORY=2 -endif - - -# For UMP Debug -ifeq ($(CONFIG_VIDEO_UMP_DEBUG),y) -DEFINES += -DDEBUG -endif - -# Set up our defines, which will be passed to gcc -DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER -DEFINES += -DUSING_MEMORY=$(USING_MEMORY) -DEFINES += -DUMP_MEM_SIZE=$(UMP_MEM_SIZE) -DEFINES += -DMALI_STATE_TRACKING=1 - -UDD_FILE_PREFIX := drivers/media/video/samsung/ump/ -KBUILDROOT = - -# linux build system integration - -obj-$(CONFIG_VIDEO_UMP) += ump.o - -# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: -# The ARM proprietary product will only include the license/proprietary directory -# The GPL product will only include the license/gpl directory - -INCLUDES += \ - -I$(UDD_FILE_PREFIX)\ - -I$(UDD_FILE_PREFIX)common\ - -I$(UDD_FILE_PREFIX)linux\ - -I$(UDD_FILE_PREFIX)include\ - -I$(UDD_FILE_PREFIX)linux/license/gpl/\ - -I$(UDD_FILE_PREFIX)../mali/common\ - -I$(UDD_FILE_PREFIX)../mali/linux - -OSKFILES+=\ - $(KBUILDROOT)../mali/linux/mali_osk_atomics.o \ - $(KBUILDROOT)../mali/linux/mali_osk_locks.o \ - $(KBUILDROOT)../mali/linux/mali_osk_math.o \ - $(KBUILDROOT)../mali/linux/mali_osk_memory.o \ - $(KBUILDROOT)../mali/linux/mali_osk_misc.o - -ump-y := \ - $(KBUILDROOT)linux/ump_kernel_linux.o \ - $(KBUILDROOT)linux/ump_kernel_memory_backend_os.o \ - $(KBUILDROOT)linux/ump_kernel_memory_backend_dedicated.o \ - $(KBUILDROOT)linux/ump_memory_backend.o \ - $(KBUILDROOT)linux/ump_ukk_wrappers.o \ - $(KBUILDROOT)linux/ump_ukk_ref_wrappers.o \ - $(KBUILDROOT)linux/ump_osk_atomics.o \ - $(KBUILDROOT)linux/ump_osk_low_level_mem.o \ - $(KBUILDROOT)linux/ump_osk_misc.o \ - $(KBUILDROOT)common/ump_kernel_common.o \ - $(KBUILDROOT)common/ump_kernel_descriptor_mapping.o \ - $(KBUILDROOT)common/ump_kernel_api.o \ - $(KBUILDROOT)common/ump_kernel_ref_drv.o\ - $(OSKFILES) - -ump-$(CONFIG_UMP_VCM_ALLOC) += \ - $(KBUILDROOT)linux/ump_kernel_memory_backend_vcm.o \ - -EXTRA_CFLAGS += $(INCLUDES) \ - $(DEFINES) - - -# Get subversion revision number, fall back to 0000 if no svn info is available -SVN_REV:=$(shell ((svnversion | grep -E "^[0-9]+" && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') - -EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV) -EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\" - diff --git a/drivers/media/video/samsung/ump/Makefile.common b/drivers/media/video/samsung/ump/Makefile.common deleted file mode 100644 index 26a3d6c..0000000 --- a/drivers/media/video/samsung/ump/Makefile.common +++ /dev/null @@ -1,20 +0,0 @@ -# -# Copyright (C) 2010-2012 ARM Limited. All rights reserved. -# -# This program is free software and is provided to you under the terms of the GNU General Public License version 2 -# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. -# -# A copy of the licence is included with the program, and can also be obtained from Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# - -SRC = $(UMP_FILE_PREFIX)common/ump_kernel_common.c \ - $(UMP_FILE_PREFIX)common/ump_kernel_descriptor_mapping.c \ - $(UMP_FILE_PREFIX)common/ump_kernel_api.c \ - $(UMP_FILE_PREFIX)common/ump_kernel_ref_drv.c - -# Get subversion revision number, fall back to 0000 if no svn info is available -SVN_REV:=$(shell ((svnversion | grep -E "^[0-9]+" && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') - -EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV) -EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\" diff --git a/drivers/media/video/samsung/ump/arch b/drivers/media/video/samsung/ump/arch deleted file mode 120000 index 58ffbe7..0000000 --- a/drivers/media/video/samsung/ump/arch +++ /dev/null @@ -1 +0,0 @@ -arch-release \ No newline at end of file diff --git a/drivers/media/video/samsung/ump/arch-debug b/drivers/media/video/samsung/ump/arch-debug deleted file mode 120000 index 0ed0909..0000000 --- a/drivers/media/video/samsung/ump/arch-debug +++ /dev/null @@ -1 +0,0 @@ -arch-pegasus-m400/ \ No newline at end of file diff --git a/drivers/media/video/samsung/ump/arch-orion-m400/config.h b/drivers/media/video/samsung/ump/arch-orion-m400/config.h deleted file mode 100644 index 7afbca6..0000000 --- a/drivers/media/video/samsung/ump/arch-orion-m400/config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_UMP_H__ -#define __ARCH_CONFIG_UMP_H__ - -#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY -#if (USING_MEMORY == 0) /* Dedicated Memory */ -#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000 -#else -#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0 -#endif - -#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024 -#endif /* __ARCH_CONFIG_UMP_H__ */ diff --git a/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h b/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h deleted file mode 100644 index 532fc94..0000000 --- a/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -#define ARCH_UMP_BACKEND_DEFAULT 0 -#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0xCE000000 -#define ARCH_UMP_MEMORY_SIZE_DEFAULT 32UL * 1024UL * 1024UL - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h b/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h deleted file mode 100644 index 7afbca6..0000000 --- a/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __ARCH_CONFIG_UMP_H__ -#define __ARCH_CONFIG_UMP_H__ - -#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY -#if (USING_MEMORY == 0) /* Dedicated Memory */ -#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000 -#else -#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0 -#endif - -#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024 -#endif /* __ARCH_CONFIG_UMP_H__ */ diff --git a/drivers/media/video/samsung/ump/arch-release b/drivers/media/video/samsung/ump/arch-release deleted file mode 120000 index 0ed0909..0000000 --- a/drivers/media/video/samsung/ump/arch-release +++ /dev/null @@ -1 +0,0 @@ -arch-pegasus-m400/ \ No newline at end of file diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_api.c b/drivers/media/video/samsung/ump/common/ump_kernel_api.c deleted file mode 100644 index 83f0d30..0000000 --- a/drivers/media/video/samsung/ump/common/ump_kernel_api.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "ump_osk.h" -#include "ump_uk_types.h" -#include "ump_kernel_interface.h" -#include "ump_kernel_common.h" - - - -/* ---------------- UMP kernel space API functions follows ---------------- */ - - - -UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(ump_dd_handle memh) -{ - ump_dd_mem * mem = (ump_dd_mem *)memh; - - DEBUG_ASSERT_POINTER(mem); - - DBG_MSG(5, ("Returning secure ID. ID: %u\n", mem->secure_id)); - - return mem->secure_id; -} - - - -UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id) -{ - ump_dd_mem * mem; - - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id)); - if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id)); - return UMP_DD_HANDLE_INVALID; - } - - ump_dd_reference_add(mem); - - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - return (ump_dd_handle)mem; -} - -UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id) -{ - ump_dd_mem * mem; - - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id)); - if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id)); - return UMP_DD_HANDLE_INVALID; - } - - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - return (ump_dd_handle)mem; -} - -UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle memh) -{ - ump_dd_mem * mem = (ump_dd_mem*) memh; - - DEBUG_ASSERT_POINTER(mem); - - return mem->nr_blocks; -} - - - -UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle memh, ump_dd_physical_block * blocks, unsigned long num_blocks) -{ - ump_dd_mem * mem = (ump_dd_mem *)memh; - - DEBUG_ASSERT_POINTER(mem); - - if (blocks == NULL) - { - DBG_MSG(1, ("NULL parameter in ump_dd_phys_blocks_get()\n")); - return UMP_DD_INVALID; - } - - if (mem->nr_blocks != num_blocks) - { - DBG_MSG(1, ("Specified number of blocks do not match actual number of blocks\n")); - return UMP_DD_INVALID; - } - - DBG_MSG(5, ("Returning physical block information. ID: %u\n", mem->secure_id)); - - _mali_osk_memcpy(blocks, mem->block_array, sizeof(ump_dd_physical_block) * mem->nr_blocks); - - return UMP_DD_SUCCESS; -} - - - -UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle memh, unsigned long index, ump_dd_physical_block * block) -{ - ump_dd_mem * mem = (ump_dd_mem *)memh; - - DEBUG_ASSERT_POINTER(mem); - - if (block == NULL) - { - DBG_MSG(1, ("NULL parameter in ump_dd_phys_block_get()\n")); - return UMP_DD_INVALID; - } - - if (index >= mem->nr_blocks) - { - DBG_MSG(5, ("Invalid index specified in ump_dd_phys_block_get()\n")); - return UMP_DD_INVALID; - } - - DBG_MSG(5, ("Returning physical block information. ID: %u, index: %lu\n", mem->secure_id, index)); - - *block = mem->block_array[index]; - - return UMP_DD_SUCCESS; -} - - - -UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle memh) -{ - ump_dd_mem * mem = (ump_dd_mem*)memh; - - DEBUG_ASSERT_POINTER(mem); - - DBG_MSG(5, ("Returning size. ID: %u, size: %lu\n", mem->secure_id, mem->size_bytes)); - - return mem->size_bytes; -} - - - -UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle memh) -{ - ump_dd_mem * mem = (ump_dd_mem*)memh; - int new_ref; - - DEBUG_ASSERT_POINTER(mem); - - new_ref = _ump_osk_atomic_inc_and_read(&mem->ref_count); - - DBG_MSG(5, ("Memory reference incremented. ID: %u, new value: %d\n", mem->secure_id, new_ref)); -} - - - -UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle memh) -{ - int new_ref; - ump_dd_mem * mem = (ump_dd_mem*)memh; - - DEBUG_ASSERT_POINTER(mem); - - /* We must hold this mutex while doing the atomic_dec_and_read, to protect - that elements in the ump_descriptor_mapping table is always valid. If they - are not, userspace may accidently map in this secure_ids right before its freed - giving a mapped backdoor into unallocated memory.*/ - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - new_ref = _ump_osk_atomic_dec_and_read(&mem->ref_count); - - DBG_MSG(5, ("Memory reference decremented. ID: %u, new value: %d\n", mem->secure_id, new_ref)); - - if (0 == new_ref) - { - DBG_MSG(3, ("Final release of memory. ID: %u\n", mem->secure_id)); - - ump_descriptor_mapping_free(device.secure_id_map, (int)mem->secure_id); - - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - mem->release_func(mem->ctx, mem); - _mali_osk_free(mem); - } - else - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - } -} - - - -/* --------------- Handling of user space requests follows --------------- */ - - -_mali_osk_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args ) -{ - ump_session_data * session_data; - - DEBUG_ASSERT_POINTER( args ); - DEBUG_ASSERT_POINTER( args->ctx ); - - session_data = (ump_session_data *)args->ctx; - - /* check compatability */ - if (args->version == UMP_IOCTL_API_VERSION) - { - DBG_MSG(3, ("API version set to newest %d (compatible)\n", GET_VERSION(args->version))); - args->compatible = 1; - session_data->api_version = args->version; - } - else if (args->version == MAKE_VERSION_ID(1)) - { - DBG_MSG(2, ("API version set to depricated: %d (compatible)\n", GET_VERSION(args->version))); - args->compatible = 1; - session_data->api_version = args->version; - } - else - { - DBG_MSG(2, ("API version set to %d (incompatible with client version %d)\n", GET_VERSION(UMP_IOCTL_API_VERSION), GET_VERSION(args->version))); - args->compatible = 0; - args->version = UMP_IOCTL_API_VERSION; /* report our version */ - } - - return _MALI_OSK_ERR_OK; -} - - -_mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info ) -{ - ump_session_memory_list_element * session_memory_element; - ump_session_memory_list_element * tmp; - ump_session_data * session_data; - _mali_osk_errcode_t ret = _MALI_OSK_ERR_INVALID_FUNC; - int secure_id; - - DEBUG_ASSERT_POINTER( release_info ); - DEBUG_ASSERT_POINTER( release_info->ctx ); - - /* Retreive the session data */ - session_data = (ump_session_data*)release_info->ctx; - - /* If there are many items in the memory session list we - * could be de-referencing this pointer a lot so keep a local copy - */ - secure_id = release_info->secure_id; - - DBG_MSG(4, ("Releasing memory with IOCTL, ID: %u\n", secure_id)); - - /* Iterate through the memory list looking for the requested secure ID */ - _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); - _MALI_OSK_LIST_FOREACHENTRY(session_memory_element, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list) - { - if ( session_memory_element->mem->secure_id == secure_id) - { - ump_dd_mem *release_mem; - - release_mem = session_memory_element->mem; - _mali_osk_list_del(&session_memory_element->list); - ump_dd_reference_release(release_mem); - _mali_osk_free(session_memory_element); - - ret = _MALI_OSK_ERR_OK; - break; - } - } - - _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id)); - - DBG_MSG(4, ("_ump_ukk_release() returning 0x%x\n", ret)); - return ret; -} - -_mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction ) -{ - ump_dd_mem * mem; - _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT; - - DEBUG_ASSERT_POINTER( user_interaction ); - - /* We lock the mappings so things don't get removed while we are looking for the memory */ - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)user_interaction->secure_id, (void**)&mem)) - { - user_interaction->size = mem->size_bytes; - DBG_MSG(4, ("Returning size. ID: %u, size: %lu ", (ump_secure_id)user_interaction->secure_id, (unsigned long)user_interaction->size)); - ret = _MALI_OSK_ERR_OK; - } - else - { - user_interaction->size = 0; - DBG_MSG(1, ("Failed to look up mapping in ump_ioctl_size_get(). ID: %u\n", (ump_secure_id)user_interaction->secure_id)); - } - - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - return ret; -} - - - -void _ump_ukk_msync( _ump_uk_msync_s *args ) -{ - ump_dd_mem * mem = NULL; - void *virtual = NULL; - u32 size = 0; - u32 offset = 0; - - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); - - if (NULL == mem) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_msync(). ID: %u\n", (ump_secure_id)args->secure_id)); - return; - } - /* Ensure the memory doesn't dissapear when we are flushing it. */ - ump_dd_reference_add(mem); - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - /* Returns the cache settings back to Userspace */ - args->is_cached=mem->is_cached; - - /* If this flag is the only one set, we should not do the actual flush, only the readout */ - if ( _UMP_UK_MSYNC_READOUT_CACHE_ENABLED==args->op ) - { - DBG_MSG(3, ("_ump_ukk_msync READOUT ID: %u Enabled: %d\n", (ump_secure_id)args->secure_id, mem->is_cached)); - goto msync_release_and_return; - } - - /* Nothing to do if the memory is not caches */ - if ( 0==mem->is_cached ) - { - DBG_MSG(3, ("_ump_ukk_msync IGNORING ID: %u Enabled: %d OP: %d\n", (ump_secure_id)args->secure_id, mem->is_cached, args->op)); - goto msync_release_and_return; - } - DBG_MSG(3, ("UMP[%02u] _ump_ukk_msync Flush OP: %d Address: 0x%08x Mapping: 0x%08x\n", - (ump_secure_id)args->secure_id, args->op, args->address, args->mapping)); - - if ( args->address ) - { - virtual = (void *)((u32)args->address); - offset = (u32)((args->address) - (args->mapping)); - } else { - /* Flush entire mapping when no address is specified. */ - virtual = args->mapping; - } - if ( args->size ) - { - size = args->size; - } else { - /* Flush entire mapping when no size is specified. */ - size = mem->size_bytes - offset; - } - - if ( (offset + size) > mem->size_bytes ) - { - DBG_MSG(1, ("Trying to flush more than the entire UMP allocation: offset: %u + size: %u > %u\n", offset, size, mem->size_bytes)); - goto msync_release_and_return; - } - - /* The actual cache flush - Implemented for each OS*/ - _ump_osk_msync( mem, virtual, offset, size, args->op, NULL); - -msync_release_and_return: - ump_dd_reference_release(mem); - return; -} - -void _ump_ukk_cache_operations_control(_ump_uk_cache_operations_control_s* args) -{ - ump_session_data * session_data; - ump_uk_cache_op_control op; - - DEBUG_ASSERT_POINTER( args ); - DEBUG_ASSERT_POINTER( args->ctx ); - - op = args->op; - session_data = (ump_session_data *)args->ctx; - - _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); - if ( op== _UMP_UK_CACHE_OP_START ) - { - session_data->cache_operations_ongoing++; - DBG_MSG(4, ("Cache ops start\n" )); - if ( session_data->cache_operations_ongoing != 1 ) - { - DBG_MSG(2, ("UMP: Number of simultanious cache control ops: %d\n", session_data->cache_operations_ongoing) ); - } - } - else if ( op== _UMP_UK_CACHE_OP_FINISH ) - { - DBG_MSG(4, ("Cache ops finish\n")); - session_data->cache_operations_ongoing--; - #if 0 - if ( session_data->has_pending_level1_cache_flush) - { - /* This function will set has_pending_level1_cache_flush=0 */ - _ump_osk_msync( NULL, NULL, 0, 0, _UMP_UK_MSYNC_FLUSH_L1, session_data); - } - #endif - - /* to be on the safe side: always flush l1 cache when cache operations are done */ - _ump_osk_msync( NULL, NULL, 0, 0, _UMP_UK_MSYNC_FLUSH_L1, session_data); - DBG_MSG(4, ("Cache ops finish end\n" )); - } - else - { - DBG_MSG(1, ("Illegal call to %s at line %d\n", __FUNCTION__, __LINE__)); - } - _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - -} - -void _ump_ukk_switch_hw_usage(_ump_uk_switch_hw_usage_s *args ) -{ - ump_dd_mem * mem = NULL; - ump_uk_user old_user; - ump_uk_msync_op cache_op = _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE; - ump_session_data *session_data; - - DEBUG_ASSERT_POINTER( args ); - DEBUG_ASSERT_POINTER( args->ctx ); - - session_data = (ump_session_data *)args->ctx; - - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); - - if (NULL == mem) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_switch_hw_usage(). ID: %u\n", (ump_secure_id)args->secure_id)); - return; - } - - old_user = mem->hw_device; - mem->hw_device = args->new_user; - - DBG_MSG(3, ("UMP[%02u] Switch usage Start New: %s Prev: %s.\n", (ump_secure_id)args->secure_id, args->new_user?"MALI":"CPU",old_user?"MALI":"CPU")); - - if ( ! mem->is_cached ) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(3, ("UMP[%02u] Changing owner of uncached memory. Cache flushing not needed.\n", (ump_secure_id)args->secure_id)); - return; - } - - if ( old_user == args->new_user) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(4, ("UMP[%02u] Setting the new_user equal to previous for. Cache flushing not needed.\n", (ump_secure_id)args->secure_id)); - return; - } - if ( - /* Previous AND new is both different from CPU */ - (old_user != _UMP_UK_USED_BY_CPU) && (args->new_user != _UMP_UK_USED_BY_CPU ) - ) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(4, ("UMP[%02u] Previous and new user is not CPU. Cache flushing not needed.\n", (ump_secure_id)args->secure_id)); - return; - } - - if ( (old_user != _UMP_UK_USED_BY_CPU ) && (args->new_user==_UMP_UK_USED_BY_CPU) ) - { - cache_op =_UMP_UK_MSYNC_INVALIDATE; - DBG_MSG(4, ("UMP[%02u] Cache invalidation needed\n", (ump_secure_id)args->secure_id)); -#ifdef UMP_SKIP_INVALIDATION -#error - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(4, ("UMP[%02u] Performing Cache invalidation SKIPPED\n", (ump_secure_id)args->secure_id)); - return; -#endif - } - /* Ensure the memory doesn't dissapear when we are flushing it. */ - ump_dd_reference_add(mem); - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - /* Take lock to protect: session->cache_operations_ongoing and session->has_pending_level1_cache_flush */ - _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); - /* Actual cache flush */ - _ump_osk_msync( mem, NULL, 0, mem->size_bytes, cache_op, session_data); - _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - - ump_dd_reference_release(mem); - DBG_MSG(4, ("UMP[%02u] Switch usage Finish\n", (ump_secure_id)args->secure_id)); - return; -} - -void _ump_ukk_lock(_ump_uk_lock_s *args ) -{ - ump_dd_mem * mem = NULL; - - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); - - if (NULL == mem) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(1, ("UMP[%02u] Failed to look up mapping in _ump_ukk_lock(). ID: %u\n", (ump_secure_id)args->secure_id)); - return; - } - ump_dd_reference_add(mem); - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - DBG_MSG(1, ("UMP[%02u] Lock. New lock flag: %d. Old Lock flag:\n", (u32)args->secure_id, (u32)args->lock_usage, (u32) mem->lock_usage )); - - mem->lock_usage = (ump_lock_usage) args->lock_usage; - - /** TODO: TAKE LOCK HERE */ - - ump_dd_reference_release(mem); -} - -void _ump_ukk_unlock(_ump_uk_unlock_s *args ) -{ - ump_dd_mem * mem = NULL; - - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); - - if (NULL == mem) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_unlock(). ID: %u\n", (ump_secure_id)args->secure_id)); - return; - } - ump_dd_reference_add(mem); - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - DBG_MSG(1, ("UMP[%02u] Unlocking. Old Lock flag:\n", (u32)args->secure_id, (u32) mem->lock_usage )); - - mem->lock_usage = (ump_lock_usage) UMP_NOT_LOCKED; - - /** TODO: RELEASE LOCK HERE */ - - ump_dd_reference_release(mem); -} diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_common.c b/drivers/media/video/samsung/ump/common/ump_kernel_common.c deleted file mode 100644 index a27bc77..0000000 --- a/drivers/media/video/samsung/ump/common/ump_kernel_common.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_bitops.h" -#include "mali_osk_list.h" -#include "ump_osk.h" -#include "ump_uk_types.h" -#include "ump_ukk.h" -#include "ump_kernel_common.h" -#include "ump_kernel_descriptor_mapping.h" -#include "ump_kernel_memory_backend.h" - - - -/** - * Define the initial and maximum size of number of secure_ids on the system - */ -#define UMP_SECURE_ID_TABLE_ENTRIES_INITIAL (128 ) -#define UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM (4096 ) - - -/** - * Define the initial and maximum size of the ump_session_data::cookies_map, - * which is a \ref ump_descriptor_mapping. This limits how many secure_ids - * may be mapped into a particular process using _ump_ukk_map_mem(). - */ - -#define UMP_COOKIES_PER_SESSION_INITIAL (UMP_SECURE_ID_TABLE_ENTRIES_INITIAL ) -#define UMP_COOKIES_PER_SESSION_MAXIMUM (UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM) - -struct ump_dev device; - -_mali_osk_errcode_t ump_kernel_constructor(void) -{ - _mali_osk_errcode_t err; - - /* Perform OS Specific initialization */ - err = _ump_osk_init(); - if( _MALI_OSK_ERR_OK != err ) - { - MSG_ERR(("Failed to initiaze the UMP Device Driver")); - return err; - } - - /* Init the global device */ - _mali_osk_memset(&device, 0, sizeof(device) ); - - /* Create the descriptor map, which will be used for mapping secure ID to ump_dd_mem structs */ - device.secure_id_map_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0 , 0); - if (NULL == device.secure_id_map_lock) - { - MSG_ERR(("Failed to create OSK lock for secure id lookup table\n")); - return _MALI_OSK_ERR_NOMEM; - } - - device.secure_id_map = ump_descriptor_mapping_create(UMP_SECURE_ID_TABLE_ENTRIES_INITIAL, UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM); - if (NULL == device.secure_id_map) - { - _mali_osk_lock_term(device.secure_id_map_lock); - MSG_ERR(("Failed to create secure id lookup table\n")); - return _MALI_OSK_ERR_NOMEM; - } - - /* Init memory backend */ - device.backend = ump_memory_backend_create(); - if (NULL == device.backend) - { - MSG_ERR(("Failed to create memory backend\n")); - _mali_osk_lock_term(device.secure_id_map_lock); - ump_descriptor_mapping_destroy(device.secure_id_map); - return _MALI_OSK_ERR_NOMEM; - } - - return _MALI_OSK_ERR_OK; -} - -void ump_kernel_destructor(void) -{ - DEBUG_ASSERT_POINTER(device.secure_id_map); - DEBUG_ASSERT_POINTER(device.secure_id_map_lock); - - _mali_osk_lock_term(device.secure_id_map_lock); - device.secure_id_map_lock = NULL; - - ump_descriptor_mapping_destroy(device.secure_id_map); - device.secure_id_map = NULL; - - device.backend->shutdown(device.backend); - device.backend = NULL; - - ump_memory_backend_destroy(); - - _ump_osk_term(); -} - -/** Creates a new UMP session - */ -_mali_osk_errcode_t _ump_ukk_open( void** context ) -{ - struct ump_session_data * session_data; - - /* allocated struct to track this session */ - session_data = (struct ump_session_data *)_mali_osk_malloc(sizeof(struct ump_session_data)); - if (NULL == session_data) - { - MSG_ERR(("Failed to allocate ump_session_data in ump_file_open()\n")); - return _MALI_OSK_ERR_NOMEM; - } - - session_data->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0); - if( NULL == session_data->lock ) - { - MSG_ERR(("Failed to initialize lock for ump_session_data in ump_file_open()\n")); - _mali_osk_free(session_data); - return _MALI_OSK_ERR_NOMEM; - } - - session_data->cookies_map = ump_descriptor_mapping_create( UMP_COOKIES_PER_SESSION_INITIAL, UMP_COOKIES_PER_SESSION_MAXIMUM ); - - if ( NULL == session_data->cookies_map ) - { - MSG_ERR(("Failed to create descriptor mapping for _ump_ukk_map_mem cookies\n")); - - _mali_osk_lock_term( session_data->lock ); - _mali_osk_free( session_data ); - return _MALI_OSK_ERR_NOMEM; - } - - _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_list); - - _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_mappings_list); - - /* Since initial version of the UMP interface did not use the API_VERSION ioctl we have to assume - that it is this version, and not the "latest" one: UMP_IOCTL_API_VERSION - Current and later API versions would do an additional call to this IOCTL and update this variable - to the correct one.*/ - session_data->api_version = MAKE_VERSION_ID(1); - - *context = (void*)session_data; - - session_data->cache_operations_ongoing = 0 ; - session_data->has_pending_level1_cache_flush = 0; - - DBG_MSG(2, ("New session opened\n")); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _ump_ukk_close( void** context ) -{ - struct ump_session_data * session_data; - ump_session_memory_list_element * item; - ump_session_memory_list_element * tmp; - - session_data = (struct ump_session_data *)*context; - if (NULL == session_data) - { - MSG_ERR(("Session data is NULL in _ump_ukk_close()\n")); - return _MALI_OSK_ERR_INVALID_ARGS; - } - - /* Unmap any descriptors mapped in. */ - if (0 == _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list)) - { - ump_memory_allocation *descriptor; - ump_memory_allocation *temp; - - DBG_MSG(1, ("Memory mappings found on session usage list during session termination\n")); - - /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */ - _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->list_head_session_memory_mappings_list, ump_memory_allocation, list) - { - _ump_uk_unmap_mem_s unmap_args; - DBG_MSG(4, ("Freeing block with phys address 0x%x size 0x%x mapped in user space at 0x%x\n", - descriptor->phys_addr, descriptor->size, descriptor->mapping)); - unmap_args.ctx = (void*)session_data; - unmap_args.mapping = descriptor->mapping; - unmap_args.size = descriptor->size; - unmap_args._ukk_private = NULL; /* NOTE: unused */ - unmap_args.cookie = descriptor->cookie; - - /* NOTE: This modifies the list_head_session_memory_mappings_list */ - _ump_ukk_unmap_mem( &unmap_args ); - } - } - - /* ASSERT that we really did free everything, because _ump_ukk_unmap_mem() - * can fail silently. */ - DEBUG_ASSERT( _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list) ); - - _MALI_OSK_LIST_FOREACHENTRY(item, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list) - { - _mali_osk_list_del(&item->list); - DBG_MSG(2, ("Releasing UMP memory %u as part of file close\n", item->mem->secure_id)); - ump_dd_reference_release(item->mem); - _mali_osk_free(item); - } - - ump_descriptor_mapping_destroy( session_data->cookies_map ); - - _mali_osk_lock_term(session_data->lock); - _mali_osk_free(session_data); - - DBG_MSG(2, ("Session closed\n")); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ) -{ - struct ump_session_data * session_data; - ump_memory_allocation * descriptor; /* Describes current mapping of memory */ - _mali_osk_errcode_t err; - unsigned long offset = 0; - unsigned long left; - ump_dd_handle handle; /* The real UMP handle for this memory. Its real datatype is ump_dd_mem* */ - ump_dd_mem * mem; /* The real UMP memory. It is equal to the handle, but with exposed struct */ - u32 block; - int map_id; - - session_data = (ump_session_data *)args->ctx; - if( NULL == session_data ) - { - MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); - return _MALI_OSK_ERR_INVALID_ARGS; - } - /* SEC kernel stability 2012-02-17 */ - if (NULL == session_data->cookies_map) - { - MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n")); - return _MALI_OSK_ERR_INVALID_ARGS; - } - descriptor = (ump_memory_allocation*) _mali_osk_calloc( 1, sizeof(ump_memory_allocation)); - if (NULL == descriptor) - { - MSG_ERR(("ump_ukk_map_mem: descriptor allocation failed\n")); - return _MALI_OSK_ERR_NOMEM; - } - - handle = ump_dd_handle_create_from_secure_id(args->secure_id); - if ( UMP_DD_HANDLE_INVALID == handle) - { - _mali_osk_free(descriptor); - DBG_MSG(1, ("Trying to map unknown secure ID %u\n", args->secure_id)); - return _MALI_OSK_ERR_FAULT; - } - - mem = (ump_dd_mem*)handle; - DEBUG_ASSERT(mem); - if (mem->size_bytes != args->size) - { - _mali_osk_free(descriptor); - ump_dd_reference_release(handle); - DBG_MSG(1, ("Trying to map too much or little. ID: %u, virtual size=%lu, UMP size: %lu\n", args->secure_id, args->size, mem->size_bytes)); - return _MALI_OSK_ERR_FAULT; - } - - map_id = ump_descriptor_mapping_allocate_mapping( session_data->cookies_map, (void*) descriptor ); - - if (map_id < 0) - { - _mali_osk_free(descriptor); - ump_dd_reference_release(handle); - DBG_MSG(1, ("ump_ukk_map_mem: unable to allocate a descriptor_mapping for return cookie\n")); - - return _MALI_OSK_ERR_NOMEM; - } - - descriptor->size = args->size; - descriptor->handle = handle; - descriptor->phys_addr = args->phys_addr; - descriptor->process_mapping_info = args->_ukk_private; - descriptor->ump_session = session_data; - descriptor->cookie = (u32)map_id; - - if ( mem->is_cached ) - { - descriptor->is_cached = 1; - args->is_cached = 1; - DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id)); - } - else if ( args->is_cached) - { - mem->is_cached = 1; - descriptor->is_cached = 1; - DBG_MSG(3, ("Warning mapping UMP secure_id: %d. As cached, while it was allocated uncached.\n", args->secure_id)); - } - else - { - descriptor->is_cached = 0; - args->is_cached = 0; - DBG_MSG(3, ("Mapping UMP secure_id: %d as Uncached.\n", args->secure_id)); - } - - _mali_osk_list_init( &descriptor->list ); - - err = _ump_osk_mem_mapregion_init( descriptor ); - if( _MALI_OSK_ERR_OK != err ) - { - DBG_MSG(1, ("Failed to initialize memory mapping in _ump_ukk_map_mem(). ID: %u\n", args->secure_id)); - ump_descriptor_mapping_free( session_data->cookies_map, map_id ); - _mali_osk_free(descriptor); - ump_dd_reference_release(mem); - return err; - } - - DBG_MSG(4, ("Mapping virtual to physical memory: ID: %u, size:%lu, first physical addr: 0x%08lx, number of regions: %lu\n", - mem->secure_id, - mem->size_bytes, - ((NULL != mem->block_array) ? mem->block_array->addr : 0), - mem->nr_blocks)); - - left = descriptor->size; - /* loop over all blocks and map them in */ - for (block = 0; block < mem->nr_blocks; block++) - { - unsigned long size_to_map; - - if (left > mem->block_array[block].size) - { - size_to_map = mem->block_array[block].size; - } - else - { - size_to_map = left; - } - - if (_MALI_OSK_ERR_OK != _ump_osk_mem_mapregion_map(descriptor, offset, (u32 *)&(mem->block_array[block].addr), size_to_map ) ) - { - DBG_MSG(1, ("WARNING: _ump_ukk_map_mem failed to map memory into userspace\n")); - ump_descriptor_mapping_free( session_data->cookies_map, map_id ); - ump_dd_reference_release(mem); - _ump_osk_mem_mapregion_term( descriptor ); - _mali_osk_free(descriptor); - return _MALI_OSK_ERR_FAULT; - } - left -= size_to_map; - offset += size_to_map; - } - - /* Add to the ump_memory_allocation tracking list */ - _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_list_add( &descriptor->list, &session_data->list_head_session_memory_mappings_list ); - _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - - args->mapping = descriptor->mapping; - args->cookie = descriptor->cookie; - - return _MALI_OSK_ERR_OK; -} - -void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args ) -{ - struct ump_session_data * session_data; - ump_memory_allocation * descriptor; - ump_dd_handle handle; - - session_data = (ump_session_data *)args->ctx; - - if( NULL == session_data ) - { - MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); - return; - } - /* SEC kernel stability 2012-02-17 */ - if (NULL == session_data->cookies_map) - { - MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n")); - return; - } - if (0 != ump_descriptor_mapping_get( session_data->cookies_map, (int)args->cookie, (void**)&descriptor) ) - { - MSG_ERR(("_ump_ukk_map_mem: cookie 0x%X not found for this session\n", args->cookie )); - return; - } - - DEBUG_ASSERT_POINTER(descriptor); - - handle = descriptor->handle; - if ( UMP_DD_HANDLE_INVALID == handle) - { - DBG_MSG(1, ("WARNING: Trying to unmap unknown handle: UNKNOWN\n")); - return; - } - - /* Remove the ump_memory_allocation from the list of tracked mappings */ - _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_list_del( &descriptor->list ); - _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - - ump_descriptor_mapping_free( session_data->cookies_map, (int)args->cookie ); - - ump_dd_reference_release(handle); - - _ump_osk_mem_mapregion_term( descriptor ); - _mali_osk_free(descriptor); -} - -u32 _ump_ukk_report_memory_usage( void ) -{ - if(device.backend->stat) - return device.backend->stat(device.backend); - else - return 0; -} diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_common.h b/drivers/media/video/samsung/ump/common/ump_kernel_common.h deleted file mode 100644 index 6e3a2e9..0000000 --- a/drivers/media/video/samsung/ump/common/ump_kernel_common.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __UMP_KERNEL_COMMON_H__ -#define __UMP_KERNEL_COMMON_H__ - -#include "ump_kernel_types.h" -#include "ump_kernel_interface.h" -#include "ump_kernel_descriptor_mapping.h" -#include "ump_kernel_memory_backend.h" - - -#ifdef DEBUG - extern int ump_debug_level; - #define UMP_DEBUG_PRINT(args) _mali_osk_dbgmsg args - #define UMP_DEBUG_CODE(args) args - #define DBG_MSG(level,args) do { /* args should be in brackets */ \ - ((level) <= ump_debug_level)?\ - UMP_DEBUG_PRINT(("UMP<" #level ">: ")), \ - UMP_DEBUG_PRINT(args):0; \ - } while (0) - - #define DBG_MSG_IF(level,condition,args) /* args should be in brackets */ \ - if((condition)&&((level) <= ump_debug_level)) {\ - UMP_DEBUG_PRINT(("UMP<" #level ">: ")); \ - UMP_DEBUG_PRINT(args); \ - } - - #define DBG_MSG_ELSE(level,args) /* args should be in brackets */ \ - else if((level) <= ump_debug_level) { \ - UMP_DEBUG_PRINT(("UMP<" #level ">: ")); \ - UMP_DEBUG_PRINT(args); \ - } - - #define DEBUG_ASSERT_POINTER(pointer) do {if( (pointer)== NULL) MSG_ERR(("NULL pointer " #pointer)); } while(0) - #define DEBUG_ASSERT(condition) do {if(!(condition)) MSG_ERR(("ASSERT failed: " #condition)); } while(0) -#else /* DEBUG */ - #define UMP_DEBUG_PRINT(args) do {} while(0) - #define UMP_DEBUG_CODE(args) - #define DBG_MSG(level,args) do {} while(0) - #define DBG_MSG_IF(level,condition,args) do {} while(0) - #define DBG_MSG_ELSE(level,args) do {} while(0) - #define DEBUG_ASSERT(condition) do {} while(0) - #define DEBUG_ASSERT_POINTER(pointer) do {} while(0) -#endif /* DEBUG */ - -#define MSG_ERR(args) do{ /* args should be in brackets */ \ - _mali_osk_dbgmsg("UMP: ERR: %s\n" ,__FILE__); \ - _mali_osk_dbgmsg( " %s()%4d\n", __FUNCTION__, __LINE__) ; \ - _mali_osk_dbgmsg args ; \ - _mali_osk_dbgmsg("\n"); \ - } while(0) - -#define MSG(args) do{ /* args should be in brackets */ \ - _mali_osk_dbgmsg("UMP: "); \ - _mali_osk_dbgmsg args; \ - } while (0) - - - -/* - * This struct is used to store per session data. - * A session is created when someone open() the device, and - * closed when someone close() it or the user space application terminates. - */ -typedef struct ump_session_data -{ - _mali_osk_list_t list_head_session_memory_list; /**< List of ump allocations made by the process (elements are ump_session_memory_list_element) */ - _mali_osk_list_t list_head_session_memory_mappings_list; /**< List of ump_memory_allocations mapped in */ - int api_version; - _mali_osk_lock_t * lock; - ump_descriptor_mapping * cookies_map; /**< Secure mapping of cookies from _ump_ukk_map_mem() */ - int cache_operations_ongoing; - int has_pending_level1_cache_flush; -} ump_session_data; - - - -/* - * This struct is used to track the UMP memory references a session has. - * We need to track this in order to be able to clean up after user space processes - * which don't do it themself (e.g. due to a crash or premature termination). - */ -typedef struct ump_session_memory_list_element -{ - struct ump_dd_mem * mem; - _mali_osk_list_t list; -} ump_session_memory_list_element; - - - -/* - * Device specific data, created when device driver is loaded, and then kept as the global variable device. - */ -typedef struct ump_dev -{ - _mali_osk_lock_t * secure_id_map_lock; - ump_descriptor_mapping * secure_id_map; - ump_memory_backend * backend; -} ump_dev; - - - -extern int ump_debug_level; -extern struct ump_dev device; - -_mali_osk_errcode_t ump_kernel_constructor(void); -void ump_kernel_destructor(void); -int map_errcode( _mali_osk_errcode_t err ); - -/** - * variables from user space cannot be dereferenced from kernel space; tagging them - * with __user allows the GCC compiler to generate a warning. Other compilers may - * not support this so we define it here as an empty macro if the compiler doesn't - * define it. - */ -#ifndef __user -#define __user -#endif - -#endif /* __UMP_KERNEL_COMMON_H__ */ diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c deleted file mode 100644 index cc7b8be..0000000 --- a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_bitops.h" -#include "ump_kernel_common.h" -#include "ump_kernel_descriptor_mapping.h" - -#define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1)) - -/** - * Allocate a descriptor table capable of holding 'count' mappings - * @param count Number of mappings in the table - * @return Pointer to a new table, NULL on error - */ -static ump_descriptor_table * descriptor_table_alloc(int count); - -/** - * Free a descriptor table - * @param table The table to free - */ -static void descriptor_table_free(ump_descriptor_table * table); - -ump_descriptor_mapping * ump_descriptor_mapping_create(int init_entries, int max_entries) -{ - ump_descriptor_mapping * map = _mali_osk_calloc(1, sizeof(ump_descriptor_mapping) ); - - init_entries = MALI_PAD_INT(init_entries); - max_entries = MALI_PAD_INT(max_entries); - - if (NULL != map) - { - map->table = descriptor_table_alloc(init_entries); - if (NULL != map->table) - { - map->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_READERWRITER, 0 , 0); - if ( NULL != map->lock ) - { - _mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */ - map->max_nr_mappings_allowed = max_entries; - map->current_nr_mappings = init_entries; - return map; - } - descriptor_table_free(map->table); - } - _mali_osk_free(map); - } - return NULL; -} - -void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map) -{ - descriptor_table_free(map->table); - _mali_osk_lock_term( map->lock ); - _mali_osk_free(map); -} - -int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target) -{ - int descriptor = -1;/*-EFAULT;*/ - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); - descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); - if (descriptor == map->current_nr_mappings) - { - int nr_mappings_new; - /* no free descriptor, try to expand the table */ - ump_descriptor_table * new_table; - ump_descriptor_table * old_table = map->table; - nr_mappings_new= map->current_nr_mappings *2; - - if (map->current_nr_mappings >= map->max_nr_mappings_allowed) - { - descriptor = -1; - goto unlock_and_exit; - } - - new_table = descriptor_table_alloc(nr_mappings_new); - if (NULL == new_table) - { - descriptor = -1; - goto unlock_and_exit; - } - - _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); - _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); - map->table = new_table; - map->current_nr_mappings = nr_mappings_new; - descriptor_table_free(old_table); - } - - /* we have found a valid descriptor, set the value and usage bit */ - _mali_osk_set_nonatomic_bit(descriptor, map->table->usage); - map->table->mappings[descriptor] = target; - -unlock_and_exit: - _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); - return descriptor; -} - -int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target) -{ - int result = -1;/*-EFAULT;*/ - DEBUG_ASSERT(map); - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) - { - *target = map->table->mappings[descriptor]; - result = 0; - } - else *target = NULL; - _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); - return result; -} - -int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target) -{ - int result = -1;/*-EFAULT;*/ - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) - { - map->table->mappings[descriptor] = target; - result = 0; - } - _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); - return result; -} - -void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor) -{ - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) - { - map->table->mappings[descriptor] = NULL; - _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage); - } - _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); -} - -static ump_descriptor_table * descriptor_table_alloc(int count) -{ - ump_descriptor_table * table; - - table = _mali_osk_calloc(1, sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count) ); - - if (NULL != table) - { - table->usage = (u32*)((u8*)table + sizeof(ump_descriptor_table)); - table->mappings = (void**)((u8*)table + sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG)); - } - - return table; -} - -static void descriptor_table_free(ump_descriptor_table * table) -{ - _mali_osk_free(table); -} diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h deleted file mode 100644 index 05b3982..0000000 --- a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_kernel_descriptor_mapping.h - */ - -#ifndef __UMP_KERNEL_DESCRIPTOR_MAPPING_H__ -#define __UMP_KERNEL_DESCRIPTOR_MAPPING_H__ - -#include "mali_osk.h" - -/** - * The actual descriptor mapping table, never directly accessed by clients - */ -typedef struct ump_descriptor_table -{ - u32 * usage; /**< Pointer to bitpattern indicating if a descriptor is valid/used or not */ - void** mappings; /**< Array of the pointers the descriptors map to */ -} ump_descriptor_table; - -/** - * The descriptor mapping object - * Provides a separate namespace where we can map an integer to a pointer - */ -typedef struct ump_descriptor_mapping -{ - _mali_osk_lock_t *lock; /**< Lock protecting access to the mapping object */ - int max_nr_mappings_allowed; /**< Max number of mappings to support in this namespace */ - int current_nr_mappings; /**< Current number of possible mappings */ - ump_descriptor_table * table; /**< Pointer to the current mapping table */ -} ump_descriptor_mapping; - -/** - * Create a descriptor mapping object - * Create a descriptor mapping capable of holding init_entries growable to max_entries - * @param init_entries Number of entries to preallocate memory for - * @param max_entries Number of entries to max support - * @return Pointer to a descriptor mapping object, NULL on failure - */ -ump_descriptor_mapping * ump_descriptor_mapping_create(int init_entries, int max_entries); - -/** - * Destroy a descriptor mapping object - * @param map The map to free - */ -void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map); - -/** - * Allocate a new mapping entry (descriptor ID) - * Allocates a new entry in the map. - * @param map The map to allocate a new entry in - * @param target The value to map to - * @return The descriptor allocated, a negative value on error - */ -int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target); - -/** - * Get the value mapped to by a descriptor ID - * @param map The map to lookup the descriptor id in - * @param descriptor The descriptor ID to lookup - * @param target Pointer to a pointer which will receive the stored value - * @return 0 on successful lookup, negative on error - */ -int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target); - -/** - * Set the value mapped to by a descriptor ID - * @param map The map to lookup the descriptor id in - * @param descriptor The descriptor ID to lookup - * @param target Pointer to replace the current value with - * @return 0 on successful lookup, negative on error - */ -int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target); - -/** - * Free the descriptor ID - * For the descriptor to be reused it has to be freed - * @param map The map to free the descriptor from - * @param descriptor The descriptor ID to free - */ -void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor); - -#endif /* __UMP_KERNEL_DESCRIPTOR_MAPPING_H__ */ diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h b/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h deleted file mode 100644 index 73915ee..0000000 --- a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_kernel_memory_mapping.h - */ - -#ifndef __UMP_KERNEL_MEMORY_BACKEND_H__ -#define __UMP_KERNEL_MEMORY_BACKEND_H__ - -#include "ump_kernel_interface.h" -#include "ump_kernel_types.h" - - -typedef struct ump_memory_allocation -{ - void * phys_addr; - void * mapping; - unsigned long size; - ump_dd_handle handle; - void * process_mapping_info; - u32 cookie; /**< necessary on some U/K interface implementations */ - struct ump_session_data * ump_session; /**< Session that this allocation belongs to */ - _mali_osk_list_t list; /**< List for linking together memory allocations into the session's memory head */ - u32 is_cached; -} ump_memory_allocation; - -typedef struct ump_memory_backend -{ - int (*allocate)(void* ctx, ump_dd_mem * descriptor); - void (*release)(void* ctx, ump_dd_mem * descriptor); - void (*shutdown)(struct ump_memory_backend * backend); - u32 (*stat)(struct ump_memory_backend *backend); - int (*pre_allocate_physical_check)(void *ctx, u32 size); - u32 (*adjust_to_mali_phys)(void *ctx, u32 cpu_phys); - void *(*get)(ump_dd_mem *mem, void *args); - void (*set)(ump_dd_mem *mem, void *args); - void * ctx; -} ump_memory_backend; - -ump_memory_backend * ump_memory_backend_create ( void ); -void ump_memory_backend_destroy( void ); - -#endif /*__UMP_KERNEL_MEMORY_BACKEND_H__ */ diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c b/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c deleted file mode 100644 index cb13232..0000000 --- a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "ump_osk.h" -#include "ump_uk_types.h" - -#include "ump_kernel_interface_ref_drv.h" -#include "ump_kernel_common.h" -#include "ump_kernel_descriptor_mapping.h" - -#define UMP_MINIMUM_SIZE 4096 -#define UMP_MINIMUM_SIZE_MASK (~(UMP_MINIMUM_SIZE-1)) -#define UMP_SIZE_ALIGN(x) (((x)+UMP_MINIMUM_SIZE-1)&UMP_MINIMUM_SIZE_MASK) -#define UMP_ADDR_ALIGN_OFFSET(x) ((x)&(UMP_MINIMUM_SIZE-1)) -static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor); - -UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks) -{ - ump_dd_mem * mem; - unsigned long size_total = 0; - int map_id; - u32 i; - - /* Go through the input blocks and verify that they are sane */ - for (i=0; i < num_blocks; i++) - { - unsigned long addr = blocks[i].addr; - unsigned long size = blocks[i].size; - - DBG_MSG(5, ("Adding physical memory to new handle. Address: 0x%08lx, size: %lu\n", addr, size)); - size_total += blocks[i].size; - - if (0 != UMP_ADDR_ALIGN_OFFSET(addr)) - { - MSG_ERR(("Trying to create UMP memory from unaligned physical address. Address: 0x%08lx\n", addr)); - return UMP_DD_HANDLE_INVALID; - } - - if (0 != UMP_ADDR_ALIGN_OFFSET(size)) - { - MSG_ERR(("Trying to create UMP memory with unaligned size. Size: %lu\n", size)); - return UMP_DD_HANDLE_INVALID; - } - } - - /* Allocate the ump_dd_mem struct for this allocation */ - mem = _mali_osk_malloc(sizeof(*mem)); - if (NULL == mem) - { - DBG_MSG(1, ("Could not allocate ump_dd_mem in ump_dd_handle_create_from_phys_blocks()\n")); - return UMP_DD_HANDLE_INVALID; - } - - /* Find a secure ID for this allocation */ - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*) mem); - - if (map_id < 0) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_free(mem); - DBG_MSG(1, ("Failed to allocate secure ID in ump_dd_handle_create_from_phys_blocks()\n")); - return UMP_DD_HANDLE_INVALID; - } - - /* Now, make a copy of the block information supplied by the user */ - mem->block_array = _mali_osk_malloc(sizeof(ump_dd_physical_block)* num_blocks); - if (NULL == mem->block_array) - { - ump_descriptor_mapping_free(device.secure_id_map, map_id); - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_free(mem); - DBG_MSG(1, ("Could not allocate a mem handle for function ump_dd_handle_create_from_phys_blocks().\n")); - return UMP_DD_HANDLE_INVALID; - } - - _mali_osk_memcpy(mem->block_array, blocks, sizeof(ump_dd_physical_block) * num_blocks); - - /* And setup the rest of the ump_dd_mem struct */ - _mali_osk_atomic_init(&mem->ref_count, 1); - mem->secure_id = (ump_secure_id)map_id; - mem->size_bytes = size_total; - mem->nr_blocks = num_blocks; - mem->backend_info = NULL; - mem->ctx = NULL; - mem->release_func = phys_blocks_release; - /* For now UMP handles created by ump_dd_handle_create_from_phys_blocks() is forced to be Uncached */ - mem->is_cached = 0; - mem->hw_device = _UMP_UK_USED_BY_CPU; - mem->lock_usage = UMP_NOT_LOCKED; - - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(3, ("UMP memory created. ID: %u, size: %lu\n", mem->secure_id, mem->size_bytes)); - - return (ump_dd_handle)mem; -} - -static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor) -{ - _mali_osk_free(descriptor->block_array); - descriptor->block_array = NULL; -} - -_mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction ) -{ - ump_session_data * session_data = NULL; - ump_dd_mem *new_allocation = NULL; - ump_session_memory_list_element * session_memory_element = NULL; - int map_id; - - DEBUG_ASSERT_POINTER( user_interaction ); - DEBUG_ASSERT_POINTER( user_interaction->ctx ); - - session_data = (ump_session_data *) user_interaction->ctx; - - session_memory_element = _mali_osk_calloc( 1, sizeof(ump_session_memory_list_element)); - if (NULL == session_memory_element) - { - DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n")); - return _MALI_OSK_ERR_NOMEM; - } - - - new_allocation = _mali_osk_calloc( 1, sizeof(ump_dd_mem)); - if (NULL==new_allocation) - { - _mali_osk_free(session_memory_element); - DBG_MSG(1, ("Failed to allocate ump_dd_mem in _ump_ukk_allocate()\n")); - return _MALI_OSK_ERR_NOMEM; - } - - /* Create a secure ID for this allocation */ - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*)new_allocation); - - if (map_id < 0) - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_free(session_memory_element); - _mali_osk_free(new_allocation); - DBG_MSG(1, ("Failed to allocate secure ID in ump_ioctl_allocate()\n")); - return - _MALI_OSK_ERR_INVALID_FUNC; - } - - /* Initialize the part of the new_allocation that we know so for */ - new_allocation->secure_id = (ump_secure_id)map_id; - _mali_osk_atomic_init(&new_allocation->ref_count,1); - if ( 0==(UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE & user_interaction->constraints) ) - new_allocation->is_cached = 0; - else new_allocation->is_cached = 1; - - /* special case a size of 0, we should try to emulate what malloc does in this case, which is to return a valid pointer that must be freed, but can't be dereferences */ - if (0 == user_interaction->size) - { - user_interaction->size = 1; /* emulate by actually allocating the minimum block size */ - } - - new_allocation->size_bytes = UMP_SIZE_ALIGN(user_interaction->size); /* Page align the size */ - new_allocation->lock_usage = UMP_NOT_LOCKED; - - /* Now, ask the active memory backend to do the actual memory allocation */ - if (!device.backend->allocate( device.backend->ctx, new_allocation ) ) - { - DBG_MSG(3, ("OOM: No more UMP memory left. Failed to allocate memory in ump_ioctl_allocate(). Size: %lu, requested size: %lu\n", new_allocation->size_bytes, (unsigned long)user_interaction->size)); - ump_descriptor_mapping_free(device.secure_id_map, map_id); - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_free(new_allocation); - _mali_osk_free(session_memory_element); - return _MALI_OSK_ERR_INVALID_FUNC; - } - new_allocation->hw_device = _UMP_UK_USED_BY_CPU; - new_allocation->ctx = device.backend->ctx; - new_allocation->release_func = device.backend->release; - - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - /* Initialize the session_memory_element, and add it to the session object */ - session_memory_element->mem = new_allocation; - _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_list_add(&(session_memory_element->list), &(session_data->list_head_session_memory_list)); - _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - - user_interaction->secure_id = new_allocation->secure_id; - user_interaction->size = new_allocation->size_bytes; - DBG_MSG(3, ("UMP memory allocated. ID: %u, size: %lu\n", new_allocation->secure_id, new_allocation->size_bytes)); - - return _MALI_OSK_ERR_OK; -} - - -UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args) -{ - ump_dd_mem * mem; - ump_secure_id secure_id; - - DEBUG_ASSERT_POINTER(memh); - - secure_id = ump_dd_secure_id_get(memh); - - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) - { - device.backend->set(mem, args); - } - else - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_set(). ID: %u\n", (ump_secure_id)secure_id)); - return UMP_DD_INVALID; - } - - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - return UMP_DD_SUCCESS; -} - -UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args) -{ - ump_dd_mem * mem; - void *result; - - _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) - { - result = device.backend->get(mem, args); - } - else - { - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_get(). ID: %u\n", (ump_secure_id)secure_id)); - return UMP_DD_HANDLE_INVALID; - } - - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - - return result; -} - -UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr) -{ - ump_dd_mem * mem; - - DBG_MSG(5, ("Getting handle from Virtual address. vaddr: %u\n", vaddr)); - - _ump_osk_mem_mapregion_get(&mem, vaddr); - - DBG_MSG(1, ("Getting handle's Handle : 0x%8lx\n", mem)); - - return (ump_dd_handle)mem; -} - diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_types.h b/drivers/media/video/samsung/ump/common/ump_kernel_types.h deleted file mode 100644 index 19a9755..0000000 --- a/drivers/media/video/samsung/ump/common/ump_kernel_types.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __UMP_KERNEL_TYPES_H__ -#define __UMP_KERNEL_TYPES_H__ - -#include "ump_kernel_interface.h" -#include "mali_osk.h" - - -typedef enum -{ - UMP_USED_BY_CPU = 0, - UMP_USED_BY_MALI = 1, - UMP_USED_BY_UNKNOWN_DEVICE= 100, -} ump_hw_usage; - -typedef enum -{ - UMP_NOT_LOCKED = 0, - UMP_READ = 1, - UMP_READ_WRITE = 3, -} ump_lock_usage; - - -/* - * This struct is what is "behind" a ump_dd_handle - */ -typedef struct ump_dd_mem -{ - ump_secure_id secure_id; - _mali_osk_atomic_t ref_count; - unsigned long size_bytes; - unsigned long nr_blocks; - ump_dd_physical_block * block_array; - void (*release_func)(void * ctx, struct ump_dd_mem * descriptor); - void * ctx; - void * backend_info; - int is_cached; - ump_hw_usage hw_device; - ump_lock_usage lock_usage; -} ump_dd_mem; - - - -#endif /* __UMP_KERNEL_TYPES_H__ */ diff --git a/drivers/media/video/samsung/ump/common/ump_osk.h b/drivers/media/video/samsung/ump/common/ump_osk.h deleted file mode 100644 index dabdc7f..0000000 --- a/drivers/media/video/samsung/ump/common/ump_osk.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_osk.h - * Defines the OS abstraction layer for the UMP kernel device driver (OSK) - */ - -#ifndef __UMP_OSK_H__ -#define __UMP_OSK_H__ - -#include -#include -#include "ump_uk_types.h" -#include "ump_kernel_common.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -_mali_osk_errcode_t _ump_osk_init( void ); - -_mali_osk_errcode_t _ump_osk_term( void ); - -int _ump_osk_atomic_inc_and_read( _mali_osk_atomic_t *atom ); - -int _ump_osk_atomic_dec_and_read( _mali_osk_atomic_t *atom ); - -_mali_osk_errcode_t _ump_osk_mem_mapregion_init( ump_memory_allocation *descriptor ); - -_mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descriptor, u32 offset, u32 * phys_addr, unsigned long size ); - -void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor ); - -void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data ); - -void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/media/video/samsung/ump/common/ump_uk_types.h b/drivers/media/video/samsung/ump/common/ump_uk_types.h deleted file mode 100644 index 143588d..0000000 --- a/drivers/media/video/samsung/ump/common/ump_uk_types.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_uk_types.h - * Defines the types and constants used in the user-kernel interface - */ - -#ifndef __UMP_UK_TYPES_H__ -#define __UMP_UK_TYPES_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Helpers for API version handling */ -#define MAKE_VERSION_ID(x) (((x) << 16UL) | (x)) -#define IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF)) -#define GET_VERSION(x) (((x) >> 16UL) & 0xFFFF) -#define IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y)))) - -/** - * API version define. - * Indicates the version of the kernel API - * The version is a 16bit integer incremented on each API change. - * The 16bit integer is stored twice in a 32bit integer - * So for version 1 the value would be 0x00010001 - */ -#define UMP_IOCTL_API_VERSION MAKE_VERSION_ID(2) - -typedef enum -{ - _UMP_IOC_QUERY_API_VERSION = 1, - _UMP_IOC_ALLOCATE, - _UMP_IOC_RELEASE, - _UMP_IOC_SIZE_GET, - _UMP_IOC_MAP_MEM, /* not used in Linux */ - _UMP_IOC_UNMAP_MEM, /* not used in Linux */ - _UMP_IOC_MSYNC, - _UMP_IOC_CACHE_OPERATIONS_CONTROL, - _UMP_IOC_SWITCH_HW_USAGE, - _UMP_IOC_LOCK, - _UMP_IOC_UNLOCK, -#ifdef CONFIG_ION_EXYNOS - _UMP_IOC_ION_IMPORT, -#endif -}_ump_uk_functions; - -typedef enum -{ - UMP_REF_DRV_UK_CONSTRAINT_NONE = 0, - UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR = 1, - UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE = 128, -} ump_uk_alloc_constraints; - -typedef enum -{ - _UMP_UK_MSYNC_CLEAN = 0, - _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE = 1, - _UMP_UK_MSYNC_INVALIDATE = 2, - _UMP_UK_MSYNC_FLUSH_L1 = 3, - _UMP_UK_MSYNC_READOUT_CACHE_ENABLED = 128, -} ump_uk_msync_op; - -typedef enum -{ - _UMP_UK_CACHE_OP_START = 0, - _UMP_UK_CACHE_OP_FINISH = 1, -} ump_uk_cache_op_control; - -typedef enum -{ - _UMP_UK_READ = 1, - _UMP_UK_READ_WRITE = 3, -} ump_uk_lock_usage; - -typedef enum -{ - _UMP_UK_USED_BY_CPU = 0, - _UMP_UK_USED_BY_MALI = 1, - _UMP_UK_USED_BY_UNKNOWN_DEVICE= 100, -} ump_uk_user; - -/** - * Get API version ([in,out] u32 api_version, [out] u32 compatible) - */ -typedef struct _ump_uk_api_version_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 version; /**< Set to the user space version on entry, stores the device driver version on exit */ - u32 compatible; /**< Non-null if the device is compatible with the client */ -} _ump_uk_api_version_s; - -/** - * ALLOCATE ([out] u32 secure_id, [in,out] u32 size, [in] contraints) - */ -typedef struct _ump_uk_allocate_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< Return value from DD to Userdriver */ - u32 size; /**< Input and output. Requested size; input. Returned size; output */ - ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ -} _ump_uk_allocate_s; - -#ifdef CONFIG_ION_EXYNOS -typedef struct _ump_uk_ion_import_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - int ion_fd; /**< ion_fd */ - u32 secure_id; /**< Return value from DD to Userdriver */ - u32 size; /**< Input and output. Requested size; input. Returned size; output */ - ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ -} _ump_uk_ion_import_s; -#endif - -/** - * SIZE_GET ([in] u32 secure_id, [out]size ) - */ -typedef struct _ump_uk_size_get_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< Input to DD */ - u32 size; /**< Returned size; output */ -} _ump_uk_size_get_s; - -/** - * Release ([in] u32 secure_id) - */ -typedef struct _ump_uk_release_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< Input to DD */ -} _ump_uk_release_s; - -typedef struct _ump_uk_map_mem_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; /**< [out] Returns user-space virtual address for the mapping */ - void *phys_addr; /**< [in] physical address */ - unsigned long size; /**< [in] size */ - u32 secure_id; /**< [in] secure_id to assign to mapping */ - void * _ukk_private; /**< Only used inside linux port between kernel frontend and common part to store vma */ - u32 cookie; - u32 is_cached; /**< [in,out] caching of CPU mappings */ -} _ump_uk_map_mem_s; - -typedef struct _ump_uk_unmap_mem_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; - u32 size; - void * _ukk_private; - u32 cookie; -} _ump_uk_unmap_mem_s; - -typedef struct _ump_uk_msync_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; /**< [in] mapping addr */ - void *address; /**< [in] flush start addr */ - u32 size; /**< [in] size to flush */ - ump_uk_msync_op op; /**< [in] flush operation */ - u32 cookie; /**< [in] cookie stored with reference to the kernel mapping internals */ - u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ - u32 is_cached; /**< [out] caching of CPU mappings */ -} _ump_uk_msync_s; - -typedef struct _ump_uk_cache_operations_control_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - ump_uk_cache_op_control op; /**< [in] cache operations start/stop */ -} _ump_uk_cache_operations_control_s; - - -typedef struct _ump_uk_switch_hw_usage_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ - ump_uk_user new_user; /**< [in] cookie stored with reference to the kernel mapping internals */ - -} _ump_uk_switch_hw_usage_s; - -typedef struct _ump_uk_lock_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ - ump_uk_lock_usage lock_usage; -} _ump_uk_lock_s; - -typedef struct _ump_uk_unlock_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ -} _ump_uk_unlock_s; - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_UK_TYPES_H__ */ diff --git a/drivers/media/video/samsung/ump/common/ump_ukk.h b/drivers/media/video/samsung/ump/common/ump_ukk.h deleted file mode 100644 index 56e4be3..0000000 --- a/drivers/media/video/samsung/ump/common/ump_ukk.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_ukk.h - * Defines the kernel-side interface of the user-kernel interface - */ - -#ifndef __UMP_UKK_H__ -#define __UMP_UKK_H__ - -#include "mali_osk.h" -#include "ump_uk_types.h" - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -_mali_osk_errcode_t _ump_ukk_open( void** context ); - -_mali_osk_errcode_t _ump_ukk_close( void** context ); - -_mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction ); - -_mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info ); - -_mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction ); - -_mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ); - -_mali_osk_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args ); - -void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args ); - -void _ump_ukk_msync( _ump_uk_msync_s *args ); - -void _ump_ukk_cache_operations_control(_ump_uk_cache_operations_control_s* args); - -void _ump_ukk_switch_hw_usage(_ump_uk_switch_hw_usage_s *args ); - -void _ump_ukk_lock(_ump_uk_lock_s *args ); - -void _ump_ukk_unlock(_ump_uk_unlock_s *args ); - -u32 _ump_ukk_report_memory_usage( void ); - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_UKK_H__ */ diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface.h b/drivers/media/video/samsung/ump/include/ump_kernel_interface.h deleted file mode 100644 index 042c8b1..0000000 --- a/drivers/media/video/samsung/ump/include/ump_kernel_interface.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_kernel_interface.h - * - * This file contains the kernel space part of the UMP API. - */ - -#ifndef __UMP_KERNEL_INTERFACE_H__ -#define __UMP_KERNEL_INTERFACE_H__ - - -/** @defgroup ump_kernel_space_api UMP Kernel Space API - * @{ */ - - -#include "ump_kernel_platform.h" - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -/** - * External representation of a UMP handle in kernel space. - */ -typedef void * ump_dd_handle; - -/** - * Typedef for a secure ID, a system wide identificator for UMP memory buffers. - */ -typedef unsigned int ump_secure_id; - - -/** - * Value to indicate an invalid UMP memory handle. - */ -#define UMP_DD_HANDLE_INVALID ((ump_dd_handle)0) - - -/** - * Value to indicate an invalid secure Id. - */ -#define UMP_INVALID_SECURE_ID ((ump_secure_id)-1) - - -/** - * UMP error codes for kernel space. - */ -typedef enum -{ - UMP_DD_SUCCESS, /**< indicates success */ - UMP_DD_INVALID, /**< indicates failure */ -} ump_dd_status_code; - - -/** - * Struct used to describe a physical block used by UMP memory - */ -typedef struct ump_dd_physical_block -{ - unsigned long addr; /**< The physical address of the block */ - unsigned long size; /**< The length of the block, typically page aligned */ -} ump_dd_physical_block; - - -/** - * Retrieves the secure ID for the specified UMP memory. - * - * This identificator is unique across the entire system, and uniquely identifies - * the specified UMP memory. This identificator can later be used through the - * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id" or - * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" - * functions in order to access this UMP memory, for instance from another process. - * - * @note There is a user space equivalent function called @ref ump_secure_id_get "ump_secure_id_get" - * - * @see ump_dd_handle_create_from_secure_id - * @see ump_handle_create_from_secure_id - * @see ump_secure_id_get - * - * @param mem Handle to UMP memory. - * - * @return Returns the secure ID for the specified UMP memory. - */ -UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(ump_dd_handle mem); - - -/** - * Retrieves a handle to allocated UMP memory. - * - * The usage of UMP memory is reference counted, so this will increment the reference - * count by one for the specified UMP memory. - * Use @ref ump_dd_reference_release "ump_dd_reference_release" when there is no longer any - * use for the retrieved handle. - * - * @note There is a user space equivalent function called @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" - * - * @see ump_dd_reference_release - * @see ump_handle_create_from_secure_id - * - * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function. - * - * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. - */ -UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id); - - -/** - * Retrieves the number of physical blocks used by the specified UMP memory. - * - * This function retrieves the number of @ref ump_dd_physical_block "ump_dd_physical_block" structs needed - * to describe the physical memory layout of the given UMP memory. This can later be used when calling - * the functions @ref ump_dd_phys_blocks_get "ump_dd_phys_blocks_get" and - * @ref ump_dd_phys_block_get "ump_dd_phys_block_get". - * - * @see ump_dd_phys_blocks_get - * @see ump_dd_phys_block_get - * - * @param mem Handle to UMP memory. - * - * @return The number of ump_dd_physical_block structs required to describe the physical memory layout of the specified UMP memory. - */ -UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle mem); - - -/** - * Retrieves all physical memory block information for specified UMP memory. - * - * This function can be used by other device drivers in order to create MMU tables. - * - * @note This function will fail if the num_blocks parameter is either to large or to small. - * - * @see ump_dd_phys_block_get - * - * @param mem Handle to UMP memory. - * @param blocks An array of @ref ump_dd_physical_block "ump_dd_physical_block" structs that will receive the physical description. - * @param num_blocks The number of blocks to return in the blocks array. Use the function - * @ref ump_dd_phys_block_count_get "ump_dd_phys_block_count_get" first to determine the number of blocks required. - * - * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. - */ -UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle mem, ump_dd_physical_block * blocks, unsigned long num_blocks); - - -/** - * Retrieves the physical memory block information for specified block for the specified UMP memory. - * - * This function can be used by other device drivers in order to create MMU tables. - * - * @note This function will return UMP_DD_INVALID if the specified index is out of range. - * - * @see ump_dd_phys_blocks_get - * - * @param mem Handle to UMP memory. - * @param index Which physical info block to retrieve. - * @param block Pointer to a @ref ump_dd_physical_block "ump_dd_physical_block" struct which will receive the requested information. - * - * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. - */ -UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle mem, unsigned long index, ump_dd_physical_block * block); - - -/** - * Retrieves the actual size of the specified UMP memory. - * - * The size is reported in bytes, and is typically page aligned. - * - * @note There is a user space equivalent function called @ref ump_size_get "ump_size_get" - * - * @see ump_size_get - * - * @param mem Handle to UMP memory. - * - * @return Returns the allocated size of the specified UMP memory, in bytes. - */ -UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle mem); - - -/** - * Adds an extra reference to the specified UMP memory. - * - * This function adds an extra reference to the specified UMP memory. This function should - * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_dd_handle - * variable. The function @ref ump_dd_reference_release "ump_dd_reference_release" must then be used - * to release each copy of the UMP memory handle. - * - * @note You are not required to call @ref ump_dd_reference_add "ump_dd_reference_add" - * for UMP handles returned from - * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id", - * because these handles are already reference counted by this function. - * - * @note There is a user space equivalent function called @ref ump_reference_add "ump_reference_add" - * - * @see ump_reference_add - * - * @param mem Handle to UMP memory. - */ -UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle mem); - - -/** - * Releases a reference from the specified UMP memory. - * - * This function should be called once for every reference to the UMP memory handle. - * When the last reference is released, all resources associated with this UMP memory - * handle are freed. - * - * @note There is a user space equivalent function called @ref ump_reference_release "ump_reference_release" - * - * @see ump_reference_release - * - * @param mem Handle to UMP memory. - */ -UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle mem); - - -#ifdef __cplusplus -} -#endif - - -/** @} */ /* end group ump_kernel_space_api */ - - -#endif /* __UMP_KERNEL_INTERFACE_H__ */ diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h b/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h deleted file mode 100644 index 36c5c9d..0000000 --- a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_kernel_interface.h - */ - -#ifndef __UMP_KERNEL_INTERFACE_REF_DRV_H__ -#define __UMP_KERNEL_INTERFACE_REF_DRV_H__ - -#include "ump_kernel_interface.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Turn specified physical memory into UMP memory. */ -UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks); -UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id); -UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args); -UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args); -UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr); - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_KERNEL_INTERFACE_REF_DRV_H__ */ diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_platform.h b/drivers/media/video/samsung/ump/include/ump_kernel_platform.h deleted file mode 100644 index 4349605..0000000 --- a/drivers/media/video/samsung/ump/include/ump_kernel_platform.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_kernel_platform.h - * - * This file should define UMP_KERNEL_API_EXPORT, - * which dictates how the UMP kernel API should be exported/imported. - * Modify this file, if needed, to match your platform setup. - */ - -#ifndef __UMP_KERNEL_PLATFORM_H__ -#define __UMP_KERNEL_PLATFORM_H__ - -/** @addtogroup ump_kernel_space_api - * @{ */ - -/** - * A define which controls how UMP kernel space API functions are imported and exported. - * This define should be set by the implementor of the UMP API. - */ - -#if defined(_WIN32) - -#if defined(UMP_BUILDING_UMP_LIBRARY) -#define UMP_KERNEL_API_EXPORT __declspec(dllexport) -#else -#define UMP_KERNEL_API_EXPORT __declspec(dllimport) -#endif - -#else - -#define UMP_KERNEL_API_EXPORT - -#endif - - -/** @} */ /* end group ump_kernel_space_api */ - - -#endif /* __UMP_KERNEL_PLATFORM_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h b/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h deleted file mode 100644 index 187e33b..0000000 --- a/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_kernel_license.h - * Defines for the macro MODULE_LICENSE. - */ - -#ifndef __UMP_KERNEL_LICENSE_H__ -#define __UMP_KERNEL_LICENSE_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define UMP_KERNEL_LINUX_LICENSE "GPL" -#define UMP_LICENSE_IS_GPL 1 - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_KERNEL_LICENSE_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_ioctl.h b/drivers/media/video/samsung/ump/linux/ump_ioctl.h deleted file mode 100644 index 83bb2a4..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_ioctl.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __UMP_IOCTL_H__ -#define __UMP_IOCTL_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include -#include - -#include - -#ifndef __user -#define __user -#endif - - -/** - * @file UMP_ioctl.h - * This file describes the interface needed to use the Linux device driver. - * The interface is used by the userpace UMP driver. - */ - -#define UMP_IOCTL_NR 0x90 - - -#define UMP_IOC_QUERY_API_VERSION _IOR(UMP_IOCTL_NR, _UMP_IOC_QUERY_API_VERSION, _ump_uk_api_version_s) -#define UMP_IOC_ALLOCATE _IOWR(UMP_IOCTL_NR, _UMP_IOC_ALLOCATE, _ump_uk_allocate_s) -#define UMP_IOC_RELEASE _IOR(UMP_IOCTL_NR, _UMP_IOC_RELEASE, _ump_uk_release_s) -#define UMP_IOC_SIZE_GET _IOWR(UMP_IOCTL_NR, _UMP_IOC_SIZE_GET, _ump_uk_size_get_s) -#define UMP_IOC_MSYNC _IOW(UMP_IOCTL_NR, _UMP_IOC_MSYNC, _ump_uk_msync_s) -#ifdef CONFIG_ION_EXYNOS -#define UMP_IOC_ION_IMPORT _IOW(UMP_IOCTL_NR, _UMP_IOC_ION_IMPORT, _ump_uk_ion_import_s) -#endif -#ifdef CONFIG_DMA_SHARED_BUFFER -#define UMP_IOC_DMABUF_IMPORT _IOW(UMP_IOCTL_NR, _UMP_IOC_DMABUF_IMPORT,\ - struct ump_uk_dmabuf) -#endif - -#define UMP_IOC_CACHE_OPERATIONS_CONTROL _IOW(UMP_IOCTL_NR, _UMP_IOC_CACHE_OPERATIONS_CONTROL, _ump_uk_cache_operations_control_s) -#define UMP_IOC_SWITCH_HW_USAGE _IOW(UMP_IOCTL_NR, _UMP_IOC_SWITCH_HW_USAGE, _ump_uk_switch_hw_usage_s) -#define UMP_IOC_LOCK _IOW(UMP_IOCTL_NR, _UMP_IOC_LOCK, _ump_uk_lock_s) -#define UMP_IOC_UNLOCK _IOW(UMP_IOCTL_NR, _UMP_IOC_UNLOCK, _ump_uk_unlock_s) - - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_IOCTL_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c deleted file mode 100644 index a358a3c..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include /* kernel module definitions */ -#include /* file system operations */ -#include /* character device definitions */ -#include /* request_mem_region */ -#include /* memory management functions and types */ -#include /* user space access */ -#include -#include -#include - -#include "arch/config.h" /* Configuration for current platform. The symlinc for arch is set by Makefile */ -#include "ump_ioctl.h" -#include "ump_kernel_common.h" -#include "ump_kernel_interface.h" -#include "ump_kernel_interface_ref_drv.h" -#include "ump_kernel_descriptor_mapping.h" -#include "ump_kernel_memory_backend.h" -#include "ump_kernel_memory_backend_os.h" -#include "ump_kernel_memory_backend_dedicated.h" -#include "ump_kernel_license.h" - -#include "ump_osk.h" -#include "ump_ukk.h" -#include "ump_uk_types.h" -#include "ump_ukk_wrappers.h" -#include "ump_ukk_ref_wrappers.h" - -#ifdef CONFIG_ION_EXYNOS -#include -extern struct ion_device *ion_exynos; -struct ion_client *ion_client_ump = NULL; -#endif - -/* Module parameter to control log level */ -int ump_debug_level = 2; -module_param(ump_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(ump_debug_level, "Higher number, more dmesg output"); - -/* By default the module uses any available major, but it's possible to set it at load time to a specific number */ -int ump_major = 243; -module_param(ump_major, int, S_IRUGO); /* r--r--r-- */ -MODULE_PARM_DESC(ump_major, "Device major number"); - -/* Name of the UMP device driver */ -static char ump_dev_name[] = "ump"; /* should be const, but the functions we call requires non-cost */ - - -#if UMP_LICENSE_IS_GPL -static struct dentry *ump_debugfs_dir = NULL; -#endif - -/* - * The data which we attached to each virtual memory mapping request we get. - * Each memory mapping has a reference to the UMP memory it maps. - * We release this reference when the last memory mapping is unmapped. - */ -typedef struct ump_vma_usage_tracker -{ - int references; - ump_dd_handle handle; -} ump_vma_usage_tracker; - -struct ump_device -{ - struct cdev cdev; -#if UMP_LICENSE_IS_GPL - struct class * ump_class; -#endif -}; - -/* The global variable containing the global device data */ -static struct ump_device ump_device; - - -/* Forward declare static functions */ -static int ump_file_open(struct inode *inode, struct file *filp); -static int ump_file_release(struct inode *inode, struct file *filp); -#ifdef HAVE_UNLOCKED_IOCTL -static long ump_file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -#else -static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -#endif -static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma); - -#if defined(CONFIG_VIDEO_UMP) -extern int map_errcode( _mali_osk_errcode_t err ); -#endif - -/* This variable defines the file operations this UMP device driver offer */ -static struct file_operations ump_fops = -{ - .owner = THIS_MODULE, - .open = ump_file_open, - .release = ump_file_release, -#ifdef HAVE_UNLOCKED_IOCTL - .unlocked_ioctl = ump_file_ioctl, -#else - .ioctl = ump_file_ioctl, -#endif - .mmap = ump_file_mmap -}; - - -/* This function is called by Linux to initialize this module. - * All we do is initialize the UMP device driver. - */ -static int ump_initialize_module(void) -{ - _mali_osk_errcode_t err; - - DBG_MSG(2, ("Inserting UMP device driver. Compiled: %s, time: %s\n", __DATE__, __TIME__)); - - err = ump_kernel_constructor(); - if (_MALI_OSK_ERR_OK != err) - { - MSG_ERR(("UMP device driver init failed\n")); - return map_errcode(err); - } - - MSG(("UMP device driver %s loaded\n", SVN_REV_STRING)); - return 0; -} - - - -/* - * This function is called by Linux to unload/terminate/exit/cleanup this module. - * All we do is terminate the UMP device driver. - */ -static void ump_cleanup_module(void) -{ -#ifdef CONFIG_ION_EXYNOS - if (ion_client_ump) - ion_client_destroy(ion_client_ump); -#endif - - DBG_MSG(2, ("Unloading UMP device driver\n")); - ump_kernel_destructor(); - DBG_MSG(2, ("Module unloaded\n")); -} - - - -static ssize_t ump_memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) -{ - char buf[64]; - size_t r; - u32 mem = _ump_ukk_report_memory_usage(); - - r = snprintf(buf, 64, "%u\n", mem); - return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); -} - -static const struct file_operations ump_memory_usage_fops = { - .owner = THIS_MODULE, - .read = ump_memory_used_read, -}; - -/* - * Initialize the UMP device driver. - */ -int ump_kernel_device_initialize(void) -{ - int err; - dev_t dev = 0; -#if UMP_LICENSE_IS_GPL - ump_debugfs_dir = debugfs_create_dir(ump_dev_name, NULL); - if (ERR_PTR(-ENODEV) == ump_debugfs_dir) - { - ump_debugfs_dir = NULL; - } - else - { - debugfs_create_file("memory_usage", 0400, ump_debugfs_dir, NULL, &ump_memory_usage_fops); - } -#endif - - if (0 == ump_major) - { - /* auto select a major */ - err = alloc_chrdev_region(&dev, 0, 1, ump_dev_name); - ump_major = MAJOR(dev); - } - else - { - /* use load time defined major number */ - dev = MKDEV(ump_major, 0); - err = register_chrdev_region(dev, 1, ump_dev_name); - } - - if (0 == err) - { - memset(&ump_device, 0, sizeof(ump_device)); - - /* initialize our char dev data */ - cdev_init(&ump_device.cdev, &ump_fops); - ump_device.cdev.owner = THIS_MODULE; - ump_device.cdev.ops = &ump_fops; - - /* register char dev with the kernel */ - err = cdev_add(&ump_device.cdev, dev, 1/*count*/); - if (0 == err) - { - -#if UMP_LICENSE_IS_GPL - ump_device.ump_class = class_create(THIS_MODULE, ump_dev_name); - if (IS_ERR(ump_device.ump_class)) - { - err = PTR_ERR(ump_device.ump_class); - } - else - { - struct device * mdev; - mdev = device_create(ump_device.ump_class, NULL, dev, NULL, ump_dev_name); - if (!IS_ERR(mdev)) - { - return 0; - } - - err = PTR_ERR(mdev); - } - cdev_del(&ump_device.cdev); -#else - return 0; -#endif - } - - unregister_chrdev_region(dev, 1); - } - - return err; -} - - - -/* - * Terminate the UMP device driver - */ -void ump_kernel_device_terminate(void) -{ - dev_t dev = MKDEV(ump_major, 0); - -#if UMP_LICENSE_IS_GPL - device_destroy(ump_device.ump_class, dev); - class_destroy(ump_device.ump_class); -#endif - - /* unregister char device */ - cdev_del(&ump_device.cdev); - - /* free major */ - unregister_chrdev_region(dev, 1); - -#if UMP_LICENSE_IS_GPL - if(ump_debugfs_dir) - debugfs_remove_recursive(ump_debugfs_dir); -#endif -} - -/* - * Open a new session. User space has called open() on us. - */ -static int ump_file_open(struct inode *inode, struct file *filp) -{ - struct ump_session_data * session_data; - _mali_osk_errcode_t err; - - /* input validation */ - if (0 != MINOR(inode->i_rdev)) - { - MSG_ERR(("Minor not zero in ump_file_open()\n")); - return -ENODEV; - } - - /* Call the OS-Independent UMP Open function */ - err = _ump_ukk_open((void**) &session_data ); - if( _MALI_OSK_ERR_OK != err ) - { - MSG_ERR(("Ump failed to open a new session\n")); - return map_errcode( err ); - } - - filp->private_data = (void*)session_data; - filp->f_pos = 0; - - return 0; /* success */ -} - - - -/* - * Close a session. User space has called close() or crashed/terminated. - */ -static int ump_file_release(struct inode *inode, struct file *filp) -{ - _mali_osk_errcode_t err; - - err = _ump_ukk_close((void**) &filp->private_data ); - if( _MALI_OSK_ERR_OK != err ) - { - return map_errcode( err ); - } - - return 0; /* success */ -} - - - -/* - * Handle IOCTL requests. - */ -#ifdef HAVE_UNLOCKED_IOCTL -static long ump_file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -#else -static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -#endif -{ - int err = -ENOTTY; - void __user * argument; - struct ump_session_data * session_data; - -#ifndef HAVE_UNLOCKED_IOCTL - (void)inode; /* inode not used */ -#endif - - session_data = (struct ump_session_data *)filp->private_data; - if (NULL == session_data) - { - MSG_ERR(("No session data attached to file object\n")); - return -ENOTTY; - } - - /* interpret the argument as a user pointer to something */ - argument = (void __user *)arg; - - switch (cmd) - { - case UMP_IOC_QUERY_API_VERSION: - err = ump_get_api_version_wrapper((u32 __user *)argument, session_data); - break; - - case UMP_IOC_ALLOCATE : - err = ump_allocate_wrapper((u32 __user *)argument, session_data); - break; -#ifdef CONFIG_ION_EXYNOS - case UMP_IOC_ION_IMPORT: - err = ump_ion_import_wrapper((u32 __user *)argument, session_data); - break; -#endif -#ifdef CONFIG_DMA_SHARED_BUFFER - case UMP_IOC_DMABUF_IMPORT: - err = ump_dmabuf_import_wrapper((u32 __user *)argument, - session_data); - break; -#endif - case UMP_IOC_RELEASE: - err = ump_release_wrapper((u32 __user *)argument, session_data); - break; - - case UMP_IOC_SIZE_GET: - err = ump_size_get_wrapper((u32 __user *)argument, session_data); - break; - - case UMP_IOC_MSYNC: - err = ump_msync_wrapper((u32 __user *)argument, session_data); - break; - - case UMP_IOC_CACHE_OPERATIONS_CONTROL: - err = ump_cache_operations_control_wrapper((u32 __user *)argument, session_data); - break; - - case UMP_IOC_SWITCH_HW_USAGE: - err = ump_switch_hw_usage_wrapper((u32 __user *)argument, session_data); - break; - - case UMP_IOC_LOCK: - err = ump_lock_wrapper((u32 __user *)argument, session_data); - break; - - case UMP_IOC_UNLOCK: - err = ump_unlock_wrapper((u32 __user *)argument, session_data); - break; - - default: - DBG_MSG(1, ("No handler for IOCTL. cmd: 0x%08x, arg: 0x%08lx\n", cmd, arg)); - err = -EFAULT; - break; - } - - return err; -} - -#ifndef CONFIG_VIDEO_UMP -int map_errcode( _mali_osk_errcode_t err ) -{ - switch(err) - { - case _MALI_OSK_ERR_OK : return 0; - case _MALI_OSK_ERR_FAULT: return -EFAULT; - case _MALI_OSK_ERR_INVALID_FUNC: return -ENOTTY; - case _MALI_OSK_ERR_INVALID_ARGS: return -EINVAL; - case _MALI_OSK_ERR_NOMEM: return -ENOMEM; - case _MALI_OSK_ERR_TIMEOUT: return -ETIMEDOUT; - case _MALI_OSK_ERR_RESTARTSYSCALL: return -ERESTARTSYS; - case _MALI_OSK_ERR_ITEM_NOT_FOUND: return -ENOENT; - default: return -EFAULT; - } -} -#endif - -/* - * Handle from OS to map specified virtual memory to specified UMP memory. - */ -static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma) -{ - _ump_uk_map_mem_s args; - _mali_osk_errcode_t err; - struct ump_session_data * session_data; - - /* Validate the session data */ - session_data = (struct ump_session_data *)filp->private_data; - if (NULL == session_data || NULL == session_data->cookies_map->table->mappings) - { - MSG_ERR(("mmap() called without any session data available\n")); - return -EFAULT; - } - - /* Re-pack the arguments that mmap() packed for us */ - args.ctx = session_data; - args.phys_addr = 0; - args.size = vma->vm_end - vma->vm_start; - args._ukk_private = vma; - args.secure_id = vma->vm_pgoff; - args.is_cached = 0; - - if (!(vma->vm_flags & VM_SHARED)) - { - args.is_cached = 1; - vma->vm_flags = vma->vm_flags | VM_SHARED | VM_MAYSHARE ; - DBG_MSG(3, ("UMP Map function: Forcing the CPU to use cache\n")); - } - /* By setting this flag, during a process fork; the child process will not have the parent UMP mappings */ - vma->vm_flags |= VM_DONTCOPY; - - DBG_MSG(4, ("UMP vma->flags: %x\n", vma->vm_flags )); - - /* Call the common mmap handler */ - err = _ump_ukk_map_mem( &args ); - if ( _MALI_OSK_ERR_OK != err) - { - MSG_ERR(("_ump_ukk_map_mem() failed in function ump_file_mmap()")); - return map_errcode( err ); - } - - return 0; /* success */ -} - -/* Export UMP kernel space API functions */ -EXPORT_SYMBOL(ump_dd_secure_id_get); -EXPORT_SYMBOL(ump_dd_handle_create_from_secure_id); -EXPORT_SYMBOL(ump_dd_phys_block_count_get); -EXPORT_SYMBOL(ump_dd_phys_block_get); -EXPORT_SYMBOL(ump_dd_phys_blocks_get); -EXPORT_SYMBOL(ump_dd_size_get); -EXPORT_SYMBOL(ump_dd_reference_add); -EXPORT_SYMBOL(ump_dd_reference_release); -EXPORT_SYMBOL(ump_dd_meminfo_get); -EXPORT_SYMBOL(ump_dd_meminfo_set); -EXPORT_SYMBOL(ump_dd_handle_get_from_vaddr); - -/* Export our own extended kernel space allocator */ -EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks); - -/* Setup init and exit functions for this module */ -//module_init(ump_initialize_module); -arch_initcall(ump_initialize_module); -module_exit(ump_cleanup_module); - -/* And some module informatio */ -MODULE_LICENSE(UMP_KERNEL_LINUX_LICENSE); -MODULE_AUTHOR("ARM Ltd."); -MODULE_VERSION(SVN_REV_STRING); diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h deleted file mode 100644 index 4985bb7..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __UMP_KERNEL_LINUX_H__ -#define __UMP_KERNEL_LINUX_H__ - -int ump_kernel_device_initialize(void); -void ump_kernel_device_terminate(void); - - -#endif /* __UMP_KERNEL_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c deleted file mode 100644 index 82c16cc..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* needed to detect kernel version specific code */ -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#else /* pre 2.6.26 the file was in the arch specific location */ -#include -#endif - -#include -#include -#include -#include -#include "ump_kernel_common.h" -#include "ump_kernel_memory_backend.h" - - - -#define UMP_BLOCK_SIZE (256UL * 1024UL) /* 256kB, remember to keep the ()s */ - - - -typedef struct block_info -{ - struct block_info * next; -} block_info; - - - -typedef struct block_allocator -{ - struct semaphore mutex; - block_info * all_blocks; - block_info * first_free; - u32 base; - u32 num_blocks; - u32 num_free; -} block_allocator; - - -static void block_allocator_shutdown(ump_memory_backend * backend); -static int block_allocator_allocate(void* ctx, ump_dd_mem * mem); -static void block_allocator_release(void * ctx, ump_dd_mem * handle); -static inline u32 get_phys(block_allocator * allocator, block_info * block); -static u32 block_allocator_stat(struct ump_memory_backend *backend); - - - -/* - * Create dedicated memory backend - */ -ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size) -{ - ump_memory_backend * backend; - block_allocator * allocator; - u32 usable_size; - u32 num_blocks; - - usable_size = (size + UMP_BLOCK_SIZE - 1) & ~(UMP_BLOCK_SIZE - 1); - num_blocks = usable_size / UMP_BLOCK_SIZE; - - if (0 == usable_size) - { - DBG_MSG(1, ("Memory block of size %u is unusable\n", size)); - return NULL; - } - - DBG_MSG(5, ("Creating dedicated UMP memory backend. Base address: 0x%08x, size: 0x%08x\n", base_address, size)); - DBG_MSG(6, ("%u usable bytes which becomes %u blocks\n", usable_size, num_blocks)); - - backend = kzalloc(sizeof(ump_memory_backend), GFP_KERNEL); - if (NULL != backend) - { - allocator = kmalloc(sizeof(block_allocator), GFP_KERNEL); - if (NULL != allocator) - { - allocator->all_blocks = kmalloc(sizeof(block_allocator) * num_blocks, GFP_KERNEL); - if (NULL != allocator->all_blocks) - { - int i; - - allocator->first_free = NULL; - allocator->num_blocks = num_blocks; - allocator->num_free = num_blocks; - allocator->base = base_address; - sema_init(&allocator->mutex, 1); - - for (i = 0; i < num_blocks; i++) - { - allocator->all_blocks[i].next = allocator->first_free; - allocator->first_free = &allocator->all_blocks[i]; - } - - backend->ctx = allocator; - backend->allocate = block_allocator_allocate; - backend->release = block_allocator_release; - backend->shutdown = block_allocator_shutdown; - backend->stat = block_allocator_stat; - backend->pre_allocate_physical_check = NULL; - backend->adjust_to_mali_phys = NULL; - backend->get = NULL; - backend->set = NULL; - - return backend; - } - kfree(allocator); - } - kfree(backend); - } - - return NULL; -} - - - -/* - * Destroy specified dedicated memory backend - */ -static void block_allocator_shutdown(ump_memory_backend * backend) -{ - block_allocator * allocator; - - BUG_ON(!backend); - BUG_ON(!backend->ctx); - - allocator = (block_allocator*)backend->ctx; - - DBG_MSG_IF(1, allocator->num_free != allocator->num_blocks, ("%u blocks still in use during shutdown\n", allocator->num_blocks - allocator->num_free)); - - kfree(allocator->all_blocks); - kfree(allocator); - kfree(backend); -} - - - -static int block_allocator_allocate(void* ctx, ump_dd_mem * mem) -{ - block_allocator * allocator; - u32 left; - block_info * last_allocated = NULL; - int i = 0; - - BUG_ON(!ctx); - BUG_ON(!mem); - - allocator = (block_allocator*)ctx; - left = mem->size_bytes; - - BUG_ON(!left); - BUG_ON(!&allocator->mutex); - - mem->nr_blocks = ((left + UMP_BLOCK_SIZE - 1) & ~(UMP_BLOCK_SIZE - 1)) / UMP_BLOCK_SIZE; - mem->block_array = (ump_dd_physical_block*)vmalloc(sizeof(ump_dd_physical_block) * mem->nr_blocks); - if (NULL == mem->block_array) - { - MSG_ERR(("Failed to allocate block array\n")); - return 0; - } - - if (down_interruptible(&allocator->mutex)) - { - MSG_ERR(("Could not get mutex to do block_allocate\n")); - return 0; - } - - mem->size_bytes = 0; - - while ((left > 0) && (allocator->first_free)) - { - block_info * block; - - block = allocator->first_free; - allocator->first_free = allocator->first_free->next; - block->next = last_allocated; - last_allocated = block; - allocator->num_free--; - - mem->block_array[i].addr = get_phys(allocator, block); - mem->block_array[i].size = UMP_BLOCK_SIZE; - mem->size_bytes += UMP_BLOCK_SIZE; - - i++; - - if (left < UMP_BLOCK_SIZE) left = 0; - else left -= UMP_BLOCK_SIZE; - } - - if (left) - { - block_info * block; - /* release all memory back to the pool */ - while (last_allocated) - { - block = last_allocated->next; - last_allocated->next = allocator->first_free; - allocator->first_free = last_allocated; - last_allocated = block; - allocator->num_free++; - } - - vfree(mem->block_array); - mem->backend_info = NULL; - mem->block_array = NULL; - - DBG_MSG(4, ("Could not find a mem-block for the allocation.\n")); - up(&allocator->mutex); - - return 0; - } - - mem->backend_info = last_allocated; - - up(&allocator->mutex); - mem->is_cached=0; - - return 1; -} - - - -static void block_allocator_release(void * ctx, ump_dd_mem * handle) -{ - block_allocator * allocator; - block_info * block, * next; - - BUG_ON(!ctx); - BUG_ON(!handle); - - allocator = (block_allocator*)ctx; - block = (block_info*)handle->backend_info; - BUG_ON(!block); - - if (down_interruptible(&allocator->mutex)) - { - MSG_ERR(("Allocator release: Failed to get mutex - memory leak\n")); - return; - } - - while (block) - { - next = block->next; - - BUG_ON( (block < allocator->all_blocks) || (block > (allocator->all_blocks + allocator->num_blocks))); - - block->next = allocator->first_free; - allocator->first_free = block; - allocator->num_free++; - - block = next; - } - DBG_MSG(3, ("%d blocks free after release call\n", allocator->num_free)); - up(&allocator->mutex); - - vfree(handle->block_array); - handle->block_array = NULL; -} - - - -/* - * Helper function for calculating the physical base adderss of a memory block - */ -static inline u32 get_phys(block_allocator * allocator, block_info * block) -{ - return allocator->base + ((block - allocator->all_blocks) * UMP_BLOCK_SIZE); -} - -static u32 block_allocator_stat(struct ump_memory_backend *backend) -{ - block_allocator *allocator; - BUG_ON(!backend); - allocator = (block_allocator*)backend->ctx; - BUG_ON(!allocator); - - return (allocator->num_blocks - allocator->num_free)* UMP_BLOCK_SIZE; -} diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h deleted file mode 100644 index ca8faae..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_kernel_memory_backend_dedicated.h - */ - -#ifndef __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ -#define __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ - -#include "ump_kernel_memory_backend.h" - -ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size); - -#endif /* __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ */ - 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 deleted file mode 100644 index 8f6a9b3..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* needed to detect kernel version specific code */ -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#else /* pre 2.6.26 the file was in the arch specific location */ -#include -#endif - -#include -#include -#include -#include -#include -#include -#include "ump_kernel_common.h" -#include "ump_kernel_memory_backend.h" - - - -typedef struct os_allocator -{ - struct semaphore mutex; - u32 num_pages_max; /**< Maximum number of pages to allocate from the OS */ - u32 num_pages_allocated; /**< Number of pages allocated from the OS */ -} os_allocator; - - - -static void os_free(void* ctx, ump_dd_mem * descriptor); -static int os_allocate(void* ctx, ump_dd_mem * descriptor); -static void os_memory_backend_destroy(ump_memory_backend * backend); -static u32 os_stat(struct ump_memory_backend *backend); - - - -/* - * Create OS memory backend - */ -ump_memory_backend * ump_os_memory_backend_create(const int max_allocation) -{ - ump_memory_backend * backend; - os_allocator * info; - - info = kmalloc(sizeof(os_allocator), GFP_KERNEL); - if (NULL == info) - { - return NULL; - } - - info->num_pages_max = max_allocation >> PAGE_SHIFT; - info->num_pages_allocated = 0; - - sema_init(&info->mutex, 1); - - backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL); - if (NULL == backend) - { - kfree(info); - return NULL; - } - - backend->ctx = info; - backend->allocate = os_allocate; - backend->release = os_free; - backend->shutdown = os_memory_backend_destroy; - backend->stat = os_stat; - backend->pre_allocate_physical_check = NULL; - backend->adjust_to_mali_phys = NULL; - backend->get = NULL; - backend->set = NULL; - - return backend; -} - - - -/* - * Destroy specified OS memory backend - */ -static void os_memory_backend_destroy(ump_memory_backend * backend) -{ - os_allocator * info = (os_allocator*)backend->ctx; - - DBG_MSG_IF(1, 0 != info->num_pages_allocated, ("%d pages still in use during shutdown\n", info->num_pages_allocated)); - - kfree(info); - kfree(backend); -} - - - -/* - * Allocate UMP memory - */ -static int os_allocate(void* ctx, ump_dd_mem * descriptor) -{ - u32 left; - os_allocator * info; - int pages_allocated = 0; - int is_cached; - - BUG_ON(!descriptor); - BUG_ON(!ctx); - - info = (os_allocator*)ctx; - left = descriptor->size_bytes; - is_cached = descriptor->is_cached; - - if (down_interruptible(&info->mutex)) - { - DBG_MSG(1, ("Failed to get mutex in os_free\n")); - return 0; /* failure */ - } - - descriptor->backend_info = NULL; - descriptor->nr_blocks = ((left + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) >> PAGE_SHIFT; - - DBG_MSG(5, ("Allocating page array. Size: %lu\n", descriptor->nr_blocks * sizeof(ump_dd_physical_block))); - - descriptor->block_array = (ump_dd_physical_block *)vmalloc(sizeof(ump_dd_physical_block) * descriptor->nr_blocks); - if (NULL == descriptor->block_array) - { - up(&info->mutex); - DBG_MSG(1, ("Block array could not be allocated\n")); - return 0; /* failure */ - } - - while (left > 0) - { - struct page * new_page; - - if (is_cached) - { - new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN ); - } else - { - new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD); - } - if (NULL == new_page) - { - MSG_ERR(("UMP memory allocated: Out of Memory !!\n")); - break; - } - - /* Ensure page caches are flushed. */ - if ( is_cached ) - { - descriptor->block_array[pages_allocated].addr = page_to_phys(new_page); - descriptor->block_array[pages_allocated].size = PAGE_SIZE; - } else - { - descriptor->block_array[pages_allocated].addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL ); - descriptor->block_array[pages_allocated].size = PAGE_SIZE; - } - - DBG_MSG(5, ("Allocated page 0x%08lx cached: %d\n", descriptor->block_array[pages_allocated].addr, is_cached)); - - if (left < PAGE_SIZE) - { - left = 0; - } - else - { - left -= PAGE_SIZE; - } - - pages_allocated++; - } - - DBG_MSG(5, ("Alloce for ID:%2d got %d pages, cached: %d\n", descriptor->secure_id, pages_allocated)); - - if (left) - { - DBG_MSG(1, ("Failed to allocate needed pages\n")); - DBG_MSG(1, ("UMP memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", - (pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); - - while(pages_allocated) - { - pages_allocated--; - if ( !is_cached ) - { - dma_unmap_page(NULL, descriptor->block_array[pages_allocated].addr, PAGE_SIZE, DMA_BIDIRECTIONAL); - } - __free_page(pfn_to_page(descriptor->block_array[pages_allocated].addr >> PAGE_SHIFT) ); - } - - up(&info->mutex); - - return 0; /* failure */ - } - - info->num_pages_allocated += pages_allocated; - - DBG_MSG(6, ("%d out of %d pages now allocated\n", info->num_pages_allocated, info->num_pages_max)); - - up(&info->mutex); - - return 1; /* success*/ -} - - -/* - * Free specified UMP memory - */ -static void os_free(void* ctx, ump_dd_mem * descriptor) -{ - os_allocator * info; - int i; - - BUG_ON(!ctx); - BUG_ON(!descriptor); - - info = (os_allocator*)ctx; - - BUG_ON(descriptor->nr_blocks > info->num_pages_allocated); - - if (down_interruptible(&info->mutex)) - { - DBG_MSG(1, ("Failed to get mutex in os_free\n")); - return; - } - - DBG_MSG(5, ("Releasing %lu OS pages\n", descriptor->nr_blocks)); - - info->num_pages_allocated -= descriptor->nr_blocks; - - up(&info->mutex); - - for ( i = 0; i < descriptor->nr_blocks; i++) - { - DBG_MSG(6, ("Freeing physical page. Address: 0x%08lx\n", descriptor->block_array[i].addr)); - if ( ! descriptor->is_cached) - { - dma_unmap_page(NULL, descriptor->block_array[i].addr, PAGE_SIZE, DMA_BIDIRECTIONAL); - } - __free_page(pfn_to_page(descriptor->block_array[i].addr>>PAGE_SHIFT) ); - } - - vfree(descriptor->block_array); -} - - -static u32 os_stat(struct ump_memory_backend *backend) -{ - os_allocator *info; - info = (os_allocator*)backend->ctx; - return info->num_pages_allocated * _MALI_OSK_MALI_PAGE_SIZE; -} diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h deleted file mode 100644 index 6f7e610..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_kernel_memory_backend_os.h - */ - -#ifndef __UMP_KERNEL_MEMORY_BACKEND_OS_H__ -#define __UMP_KERNEL_MEMORY_BACKEND_OS_H__ - -#include "ump_kernel_memory_backend.h" - -ump_memory_backend * ump_os_memory_backend_create(const int max_allocation); - -#endif /* __UMP_KERNEL_MEMORY_BACKEND_OS_H__ */ - diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c deleted file mode 100644 index 46797ea..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* create by boojin.kim@samsung.com */ -/* needed to detect kernel version specific code */ -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#else /* pre 2.6.26 the file was in the arch specific location */ -#include -#endif - -#include -#include -#include -#include -#include -#include "ump_kernel_common.h" -#include "ump_kernel_memory_backend.h" -#include "ump_kernel_interface_ref_drv.h" -#include "ump_kernel_memory_backend_vcm.h" -#include "../common/ump_uk_types.h" -#include -#include -#include - -#define UMP_REF_DRV_UK_VCM_DEV_G2D 12 - -typedef struct ump_vcm { - struct vcm *vcm; - struct vcm_res *vcm_res; - unsigned int dev_id; -} ump_vcm; - -typedef struct vcm_allocator { - struct semaphore mutex; - u32 num_vcm_blocks; -} vcm_allocator; - -static void ump_vcm_free(void* ctx, ump_dd_mem * descriptor); -static int ump_vcm_allocate(void* ctx, ump_dd_mem * descriptor); -static void *vcm_res_get(ump_dd_mem *mem, void* args); -static void vcm_attr_set(ump_dd_mem *mem, void* args); -static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor); -static void vcm_memory_backend_destroy(ump_memory_backend * backend); - - -/* - * Create VCM memory backend - */ -ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation) -{ - ump_memory_backend * backend; - vcm_allocator * info; - - info = kmalloc(sizeof(vcm_allocator), GFP_KERNEL); - if (NULL == info) - { - return NULL; - } - - info->num_vcm_blocks = 0; - - - sema_init(&info->mutex, 1); - - backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL); - if (NULL == backend) - { - kfree(info); - return NULL; - } - - backend->ctx = info; - backend->allocate = ump_vcm_allocate; - backend->release = ump_vcm_free; - backend->shutdown = vcm_memory_backend_destroy; - backend->pre_allocate_physical_check = NULL; - backend->adjust_to_mali_phys = NULL; - - backend->get = vcm_res_get; - backend->set = vcm_attr_set; - - - return backend; -} - -/* - * Destroy specified VCM memory backend - */ -static void vcm_memory_backend_destroy(ump_memory_backend * backend) -{ - vcm_allocator * info = (vcm_allocator*)backend->ctx; -#if 0 - DBG_MSG_IF(1, 0 != info->num_pages_allocated, ("%d pages still in use during shutdown\n", info->num_pages_allocated)); -#endif - kfree(info); - kfree(backend); -} - -/* - * Allocate UMP memory - */ -static int ump_vcm_allocate(void *ctx, ump_dd_mem * descriptor) -{ - int ret; /* success */ - vcm_allocator *info; - struct ump_vcm *ump_vcm; - - BUG_ON(!descriptor); - BUG_ON(!ctx); - - info = (vcm_allocator*)ctx; - - ump_vcm = kmalloc(sizeof(struct ump_vcm), GFP_KERNEL); - if (NULL == ump_vcm) - { - return 0; - } - - ump_vcm->dev_id = (int)descriptor->backend_info & ~UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE; - - if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_NONE) { /* None */ - ump_vcm->dev_id = UMP_REF_DRV_UK_VCM_DEV_G2D; /* this ID is G2D */ - } - else if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR) { /* Physical Linear */ - return 0; - } - else { /* Other VCM */ - ump_vcm->dev_id -= 2; - } - - DBG_MSG(5, ("Device ID for VCM : %d\n", ump_vcm->dev_id)); - ump_vcm->vcm = vcm_find_vcm(ump_vcm->dev_id); - - if (!ump_vcm->vcm) - { - return 0; - } - descriptor->backend_info = (void*)ump_vcm; - - if (down_interruptible(&info->mutex)) { - DBG_MSG(1, ("Failed to get mutex in ump_vcm_allocate\n")); - return 0; /* failure */ - } - - ret = vcm_mem_allocator(info, descriptor); - up(&info->mutex); - - return ret; /* success */ -} - -static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor) -{ - unsigned long num_blocks; - int i; - struct vcm_phys *phys; - struct vcm_phys_part *part; - int size_total = 0; - struct ump_vcm *ump_vcm; - - ump_vcm = (struct ump_vcm*)descriptor->backend_info; - - ump_vcm->vcm_res = - vcm_make_binding(ump_vcm->vcm, descriptor->size_bytes, - ump_vcm->dev_id, 0); - - phys = ump_vcm->vcm_res->phys; - part = phys->parts; - num_blocks = phys->count; - - DBG_MSG(5, - ("Allocating page array. Size: %lu, VCM Reservation : 0x%x\n", - phys->count * sizeof(ump_dd_physical_block), - ump_vcm->vcm_res->start)); - - /* Now, make a copy of the block information supplied by the user */ - descriptor->block_array = - (ump_dd_physical_block *) vmalloc(sizeof(ump_dd_physical_block) * - num_blocks); - - if (NULL == descriptor->block_array) { - vfree(descriptor->block_array); - DBG_MSG(1, ("Could not allocate a mem handle for function.\n")); - return 0; /* failure */ - } - - for (i = 0; i < num_blocks; i++) { - descriptor->block_array[i].addr = part->start; - descriptor->block_array[i].size = part->size; - - dmac_unmap_area(phys_to_virt(part->start), part->size, DMA_FROM_DEVICE); - outer_inv_range(part->start, part->start + part->size); - - ++part; - size_total += descriptor->block_array[i].size; - DBG_MSG(6, - ("UMP memory created with VCM. addr 0x%x, size: 0x%x\n", - descriptor->block_array[i].addr, - descriptor->block_array[i].size)); - } - - descriptor->size_bytes = size_total; - descriptor->nr_blocks = num_blocks; - descriptor->ctx = NULL; - - info->num_vcm_blocks += num_blocks; - return 1; -} - -/* - * Free specified UMP memory - */ -static void ump_vcm_free(void *ctx, ump_dd_mem * descriptor) -{ - struct ump_vcm *ump_vcm; - vcm_allocator *info; - - BUG_ON(!descriptor); - BUG_ON(!ctx); - - ump_vcm = (struct ump_vcm*)descriptor->backend_info; - info = (vcm_allocator*)ctx; - - BUG_ON(descriptor->nr_blocks > info->num_vcm_blocks); - - if (down_interruptible(&info->mutex)) { - DBG_MSG(1, ("Failed to get mutex in ump_vcm_free\n")); - return; - } - - DBG_MSG(5, ("Releasing %lu VCM pages\n", descriptor->nr_blocks)); - - info->num_vcm_blocks -= descriptor->nr_blocks; - - up(&info->mutex); - - DBG_MSG(6, ("Freeing physical page by VCM\n")); - vcm_destroy_binding(ump_vcm->vcm_res); - ump_vcm->vcm = NULL; - ump_vcm->vcm_res = NULL; - - kfree(ump_vcm); - vfree(descriptor->block_array); -} - -static void *vcm_res_get(ump_dd_mem *mem, void *args) -{ - struct ump_vcm *ump_vcm; - enum vcm_dev_id vcm_id; - - ump_vcm = (struct ump_vcm*)mem->backend_info; - vcm_id = (enum vcm_dev_id)args; - - if (vcm_reservation_in_vcm - (vcm_find_vcm(vcm_id), ump_vcm->vcm_res) - == S5PVCM_RES_NOT_IN_VCM) - return NULL; - else - return ump_vcm->vcm_res; -} - -static void vcm_attr_set(ump_dd_mem *mem, void *args) -{ - struct ump_vcm *ump_vcm, *ump_vcmh; - - ump_vcm = (struct ump_vcm*)args; - - ump_vcmh = kmalloc(sizeof(struct ump_vcm), GFP_KERNEL); - if (NULL == ump_vcmh) - { - return; - } - - ump_vcmh->dev_id = ump_vcm->dev_id; - ump_vcmh->vcm = ump_vcm->vcm; - ump_vcmh->vcm_res = ump_vcm->vcm_res; - - mem->backend_info= (void*)ump_vcmh; - - return; -} diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h deleted file mode 100644 index c1ead0d..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_kernel_memory_backend_vcm.h - */ - -#ifndef __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ -#define __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ - -#include "ump_kernel_memory_backend.h" - -ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation); - -#endif /* __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c b/drivers/media/video/samsung/ump/linux/ump_memory_backend.c deleted file mode 100644 index d067cfe..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include /* kernel module definitions */ -#include /* request_mem_region */ - -#include "arch/config.h" /* Configuration for current platform. The symlink for arch is set by Makefile */ - -#include "ump_osk.h" -#include "ump_kernel_common.h" -#include "ump_kernel_memory_backend_os.h" -#include "ump_kernel_memory_backend_dedicated.h" - -/* Configure which dynamic memory allocator to use */ -int ump_backend = ARCH_UMP_BACKEND_DEFAULT; -module_param(ump_backend, int, S_IRUGO); /* r--r--r-- */ -MODULE_PARM_DESC(ump_backend, "0 = dedicated memory backend (default), 1 = OS memory backend"); - -/* The base address of the memory block for the dedicated memory backend */ -unsigned int ump_memory_address = ARCH_UMP_MEMORY_ADDRESS_DEFAULT; -module_param(ump_memory_address, uint, S_IRUGO); /* r--r--r-- */ -MODULE_PARM_DESC(ump_memory_address, "The physical address to map for the dedicated memory backend"); - -/* The size of the memory block for the dedicated memory backend */ -unsigned int ump_memory_size = ARCH_UMP_MEMORY_SIZE_DEFAULT; -module_param(ump_memory_size, uint, S_IRUGO); /* r--r--r-- */ -MODULE_PARM_DESC(ump_memory_size, "The size of fixed memory to map in the dedicated memory backend"); - -ump_memory_backend* ump_memory_backend_create ( void ) -{ - ump_memory_backend * backend = NULL; - - /* Create the dynamic memory allocator backend */ - if (0 == ump_backend) - { - DBG_MSG(2, ("Using dedicated memory backend\n")); - - DBG_MSG(2, ("Requesting dedicated memory: 0x%08x, size: %u\n", ump_memory_address, ump_memory_size)); - /* Ask the OS if we can use the specified physical memory */ - if (NULL == request_mem_region(ump_memory_address, ump_memory_size, "UMP Memory")) - { - MSG_ERR(("Failed to request memory region (0x%08X - 0x%08X). Is Mali DD already loaded?\n", ump_memory_address, ump_memory_address + ump_memory_size - 1)); - return NULL; - } - backend = ump_block_allocator_create(ump_memory_address, ump_memory_size); - } - else if (1 == ump_backend) - { - DBG_MSG(2, ("Using OS memory backend, allocation limit: %d\n", ump_memory_size)); - backend = ump_os_memory_backend_create(ump_memory_size); - } -#ifdef CONFIG_UMP_VCM_ALLOC - else if (2 == ump_backend) - { - DBG_MSG(2, ("Using VCM memory backend, allocation limit: %d\n", ump_memory_size)); - backend = ump_vcm_memory_backend_create(ump_memory_size); - } -#endif - - return backend; -} - -void ump_memory_backend_destroy( void ) -{ - if (0 == ump_backend) - { - DBG_MSG(2, ("Releasing dedicated memory: 0x%08x\n", ump_memory_address)); - release_mem_region(ump_memory_address, ump_memory_size); - } -} diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c b/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c deleted file mode 100644 index b117d99..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_osk_atomics.c - * Implementation of the OS abstraction layer for the UMP kernel device driver - */ - -#include "ump_osk.h" -#include - -int _ump_osk_atomic_dec_and_read( _mali_osk_atomic_t *atom ) -{ - return atomic_dec_return((atomic_t *)&atom->u.val); -} - -int _ump_osk_atomic_inc_and_read( _mali_osk_atomic_t *atom ) -{ - return atomic_inc_return((atomic_t *)&atom->u.val); -} diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c b/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c deleted file mode 100644 index 8ae169a..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_osk_memory.c - * Implementation of the OS abstraction layer for the kernel device driver - */ - -/* needed to detect kernel version specific code */ -#include - -#include "ump_osk.h" -#include "ump_uk_types.h" -#include "ump_ukk.h" -#include "ump_kernel_common.h" -#include /* kernel module definitions */ -#include -#include -#include -#include - -#include -#include /* to verify pointers from user space */ -#include -#include - -typedef struct ump_vma_usage_tracker -{ - atomic_t references; - ump_memory_allocation *descriptor; -} ump_vma_usage_tracker; - -static void ump_vma_open(struct vm_area_struct * vma); -static void ump_vma_close(struct vm_area_struct * vma); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -static int ump_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf); -#else -static unsigned long ump_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address); -#endif - -static struct vm_operations_struct ump_vm_ops = -{ - .open = ump_vma_open, - .close = ump_vma_close, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - .fault = ump_cpu_page_fault_handler -#else - .nopfn = ump_cpu_page_fault_handler -#endif -}; - -/* - * Page fault for VMA region - * This should never happen since we always map in the entire virtual memory range. - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -static int ump_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf) -#else -static unsigned long ump_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address) -#endif -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - void __user * address; - address = vmf->virtual_address; -#endif - MSG_ERR(("Page-fault in UMP memory region caused by the CPU\n")); - MSG_ERR(("VMA: 0x%08lx, virtual address: 0x%08lx\n", (unsigned long)vma, address)); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - return VM_FAULT_SIGBUS; -#else - return NOPFN_SIGBUS; -#endif -} - -static void ump_vma_open(struct vm_area_struct * vma) -{ - ump_vma_usage_tracker * vma_usage_tracker; - int new_val; - - vma_usage_tracker = (ump_vma_usage_tracker*)vma->vm_private_data; - BUG_ON(NULL == vma_usage_tracker); - - new_val = atomic_inc_return(&vma_usage_tracker->references); - - DBG_MSG(4, ("VMA open, VMA reference count incremented. VMA: 0x%08lx, reference count: %d\n", (unsigned long)vma, new_val)); -} - -static void ump_vma_close(struct vm_area_struct * vma) -{ - ump_vma_usage_tracker * vma_usage_tracker; - _ump_uk_unmap_mem_s args; - int new_val; - - vma_usage_tracker = (ump_vma_usage_tracker*)vma->vm_private_data; - BUG_ON(NULL == vma_usage_tracker); - - new_val = atomic_dec_return(&vma_usage_tracker->references); - - DBG_MSG(4, ("VMA close, VMA reference count decremented. VMA: 0x%08lx, reference count: %d\n", (unsigned long)vma, new_val)); - - if (0 == new_val) - { - ump_memory_allocation * descriptor; - - descriptor = vma_usage_tracker->descriptor; - - args.ctx = descriptor->ump_session; - args.cookie = descriptor->cookie; - args.mapping = descriptor->mapping; - args.size = descriptor->size; - - args._ukk_private = NULL; /** @note unused */ - - DBG_MSG(4, ("No more VMA references left, releasing UMP memory\n")); - _ump_ukk_unmap_mem( & args ); - - /* vma_usage_tracker is free()d by _ump_osk_mem_mapregion_term() */ - } -} - -_mali_osk_errcode_t _ump_osk_mem_mapregion_init( ump_memory_allocation * descriptor ) -{ - ump_vma_usage_tracker * vma_usage_tracker; - struct vm_area_struct *vma; - - if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; - - vma_usage_tracker = kmalloc(sizeof(ump_vma_usage_tracker), GFP_KERNEL); - if (NULL == vma_usage_tracker) - { - DBG_MSG(1, ("Failed to allocate memory for ump_vma_usage_tracker in _mali_osk_mem_mapregion_init\n")); - return -_MALI_OSK_ERR_FAULT; - } - - vma = (struct vm_area_struct*)descriptor->process_mapping_info; - if (NULL == vma ) - { - kfree(vma_usage_tracker); - return _MALI_OSK_ERR_FAULT; - } - - vma->vm_private_data = vma_usage_tracker; - vma->vm_flags |= VM_IO; - vma->vm_flags |= VM_RESERVED; - - if (0==descriptor->is_cached) - { - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - } - DBG_MSG(3, ("Mapping with page_prot: 0x%x\n", vma->vm_page_prot )); - - /* Setup the functions which handle further VMA handling */ - vma->vm_ops = &ump_vm_ops; - - /* Do the va range allocation - in this case, it was done earlier, so we copy in that information */ - descriptor->mapping = (void __user*)vma->vm_start; - - atomic_set(&vma_usage_tracker->references, 1); /*this can later be increased if process is forked, see ump_vma_open() */ - vma_usage_tracker->descriptor = descriptor; - - return _MALI_OSK_ERR_OK; -} - -void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor ) -{ - struct vm_area_struct* vma; - ump_vma_usage_tracker * vma_usage_tracker; - - if (NULL == descriptor) return; - - /* Linux does the right thing as part of munmap to remove the mapping - * All that remains is that we remove the vma_usage_tracker setup in init() */ - vma = (struct vm_area_struct*)descriptor->process_mapping_info; - - vma_usage_tracker = vma->vm_private_data; - - /* We only get called if mem_mapregion_init succeeded */ - kfree(vma_usage_tracker); - return; -} - -_mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descriptor, u32 offset, u32 * phys_addr, unsigned long size ) -{ - struct vm_area_struct *vma; - _mali_osk_errcode_t retval; - - if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; - - vma = (struct vm_area_struct*)descriptor->process_mapping_info; - - if (NULL == vma ) return _MALI_OSK_ERR_FAULT; - - retval = remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, (*phys_addr) >> PAGE_SHIFT, size, vma->vm_page_prot) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK;; - - DBG_MSG(4, ("Mapping virtual to physical memory. ID: %u, vma: 0x%08lx, virtual addr:0x%08lx, physical addr: 0x%08lx, size:%lu, prot:0x%x, vm_flags:0x%x RETVAL: 0x%x\n", - ump_dd_secure_id_get(descriptor->handle), - (unsigned long)vma, - (unsigned long)(vma->vm_start + offset), - (unsigned long)*phys_addr, - size, - (unsigned int)vma->vm_page_prot, vma->vm_flags, retval)); - - return retval; -} - -static u32 _ump_osk_virt_to_phys_start(ump_dd_mem * mem, u32 start, u32 address, int *index) -{ - int i; - u32 offset = address - start; - ump_dd_physical_block *block; - u32 sum = 0; - - for (i=0; inr_blocks; i++) { - block = &mem->block_array[i]; - sum += block->size; - if (sum > offset) { - *index = i; - DBG_MSG(3, ("_ump_osk_virt_to_phys : index : %d, virtual 0x%x, phys 0x%x\n", i, address, (u32)block->addr + offset - (sum -block->size))); - return (u32)block->addr + offset - (sum -block->size); - } - } - - return _MALI_OSK_ERR_FAULT; -} - -static u32 _ump_osk_virt_to_phys_end(ump_dd_mem * mem, u32 start, u32 address, int *index) -{ - int i; - u32 offset = address - start; - ump_dd_physical_block *block; - u32 sum = 0; - - for (i=0; inr_blocks; i++) { - block = &mem->block_array[i]; - sum += block->size; - if (sum >= offset) { - *index = i; - DBG_MSG(3, ("_ump_osk_virt_to_phys : index : %d, virtual 0x%x, phys 0x%x\n", i, address, (u32)block->addr + offset - (sum -block->size))); - return (u32)block->addr + offset - (sum -block->size); - } - } - - return _MALI_OSK_ERR_FAULT; -} - -static void _ump_osk_msync_with_virt(ump_dd_mem * mem, ump_uk_msync_op op, u32 start, u32 address, u32 size) -{ - int start_index, end_index; - u32 start_p, end_p; - - DBG_MSG(3, ("Cache flush with user virtual address. start : 0x%x, end : 0x%x, address 0x%x, size 0x%x\n", start, start+mem->size_bytes, address, size)); - - start_p = _ump_osk_virt_to_phys_start(mem, start, address, &start_index); - end_p = _ump_osk_virt_to_phys_end(mem, start, address+size, &end_index); - - if (start_index==end_index) { - if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) - outer_flush_range(start_p, end_p); - else - outer_clean_range(start_p, end_p); - } else { - ump_dd_physical_block *block; - int i; - - for (i=start_index; i<=end_index; i++) { - block = &mem->block_array[i]; - - if (i == start_index) { - if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { - outer_flush_range(start_p, block->addr+block->size); - } else { - outer_clean_range(start_p, block->addr+block->size); - } - } - else if (i == end_index) { - if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { - outer_flush_range(block->addr, end_p); - } else { - outer_clean_range(block->addr, end_p); - } - break; - } - else { - if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { - outer_flush_range(block->addr, block->addr+block->size); - } else { - outer_clean_range(block->addr, block->addr+block->size); - } - } - } - } - return; -} - -static void level1_cache_flush_all(void) -{ - DBG_MSG(4, ("UMP[xx] Flushing complete L1 cache\n")); - __cpuc_flush_kern_all(); -} - -void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data ) -{ - int i; - const void *start_v, *end_v; - - /* Flush L1 using virtual address, the entire range in one go. - * Only flush if user space process has a valid write mapping on given address. */ - if( (mem) && (virt!=NULL) && (access_ok(VERIFY_WRITE, virt, size)) ) - { - start_v = (void *)virt; - end_v = (void *)(start_v + size - 1); - /* There is no dmac_clean_range, so the L1 is always flushed, - * also for UMP_MSYNC_CLEAN. */ - if (size >= SZ_64K) - flush_all_cpu_caches(); - else - dmac_flush_range(start_v, end_v); - - DBG_MSG(3, ("UMP[%02u] Flushing CPU L1 Cache. Cpu address: %x-%x\n", mem->secure_id, start_v,end_v)); - } - else - { - if (session_data) - { - if (op == _UMP_UK_MSYNC_FLUSH_L1 ) - { - DBG_MSG(4, ("UMP Pending L1 cache flushes: %d\n", session_data->has_pending_level1_cache_flush)); - session_data->has_pending_level1_cache_flush = 0; - level1_cache_flush_all(); - return; - } - else - { - if (session_data->cache_operations_ongoing) - { - session_data->has_pending_level1_cache_flush++; - DBG_MSG(4, ("UMP[%02u] Defering the L1 flush. Nr pending:%d\n", mem->secure_id, session_data->has_pending_level1_cache_flush) ); - } - else - { - /* Flushing the L1 cache for each switch_user() if ump_cache_operations_control(START) is not called */ - level1_cache_flush_all(); - } - } - } - else - { - DBG_MSG(4, ("Unkown state %s %d\n", __FUNCTION__, __LINE__)); - level1_cache_flush_all(); - } - } - - if ( NULL == mem ) return; - - if ( mem->size_bytes==size) - { - DBG_MSG(3, ("UMP[%02u] Flushing CPU L2 Cache\n",mem->secure_id)); - } - else - { - DBG_MSG(3, ("UMP[%02u] Flushing CPU L2 Cache. Blocks:%u, TotalSize:%u. FlushSize:%u Offset:0x%x FirstPaddr:0x%08x\n", - mem->secure_id, mem->nr_blocks, mem->size_bytes, size, offset, mem->block_array[0].addr)); - } - - - /* Flush L2 using physical addresses, block for block. */ - if ((virt!=NULL) && (mem->size_bytes >= SZ_1M)) { - if (op == _UMP_UK_MSYNC_CLEAN) - outer_clean_all(); - else if ((op == _UMP_UK_MSYNC_INVALIDATE) || (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE)) - outer_flush_all(); - return; - } - - for (i=0 ; i < mem->nr_blocks; i++) - { - u32 start_p, end_p; - ump_dd_physical_block *block; - block = &mem->block_array[i]; - - if(offset >= block->size) - { - offset -= block->size; - continue; - } - - if(offset) - { - start_p = (u32)block->addr + offset; - /* We'll zero the offset later, after using it to calculate end_p. */ - } - else - { - start_p = (u32)block->addr; - } - - if(size < block->size - offset) - { - end_p = start_p + size - 1; - size = 0; - } - else - { - if(offset) - { - end_p = start_p + (block->size - offset - 1); - size -= block->size - offset; - offset = 0; - } - else - { - end_p = start_p + block->size - 1; - size -= block->size; - } - } - - switch(op) - { - case _UMP_UK_MSYNC_CLEAN: - outer_clean_range(start_p, end_p); - break; - case _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE: - outer_flush_range(start_p, end_p); - break; - case _UMP_UK_MSYNC_INVALIDATE: - outer_inv_range(start_p, end_p); - break; - default: - break; - } - - if(0 == size) - { - /* Nothing left to flush. */ - break; - } - } - - return; -} - -void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - ump_vma_usage_tracker * vma_usage_tracker; - ump_memory_allocation *descriptor; - ump_dd_handle handle; - - DBG_MSG(3, ("_ump_osk_mem_mapregion_get: vaddr 0x%08lx\n", vaddr)); - - down_read(&mm->mmap_sem); - vma = find_vma(mm, vaddr); - up_read(&mm->mmap_sem); - if(!vma) - { - DBG_MSG(3, ("Not found VMA\n")); - *mem = NULL; - return; - } - DBG_MSG(4, ("Get vma: 0x%08lx vma->vm_start: 0x%08lx\n", (unsigned long)vma, vma->vm_start)); - - vma_usage_tracker = (struct ump_vma_usage_tracker*)vma->vm_private_data; - if(vma_usage_tracker == NULL) - { - DBG_MSG(3, ("Not found vma_usage_tracker\n")); - *mem = NULL; - return; - } - - descriptor = (struct ump_memory_allocation*)vma_usage_tracker->descriptor; - handle = (ump_dd_handle)descriptor->handle; - - DBG_MSG(3, ("Get handle: 0x%08lx\n", handle)); - *mem = (ump_dd_mem*)handle; -} - diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_misc.c b/drivers/media/video/samsung/ump/linux/ump_osk_misc.c deleted file mode 100644 index 3be6fed..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_osk_misc.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_osk_misc.c - * Implementation of the OS abstraction layer for the UMP kernel device driver - */ - - -#include "ump_osk.h" - -#include -#include "ump_kernel_linux.h" - -/* is called from ump_kernel_constructor in common code */ -_mali_osk_errcode_t _ump_osk_init( void ) -{ - if (0 != ump_kernel_device_initialize()) - { - return _MALI_OSK_ERR_FAULT; - } - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _ump_osk_term( void ) -{ - ump_kernel_device_terminate(); - return _MALI_OSK_ERR_OK; -} diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c deleted file mode 100644 index a6691ed..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_ukk_wrappers.c - * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls for the reference implementation - */ - - -#include /* user space access */ - -#include "ump_osk.h" -#include "ump_uk_types.h" -#include "ump_ukk.h" -#include "ump_kernel_common.h" - -#if defined(CONFIG_ION_EXYNOS) || defined(CONFIG_DMA_SHARED_BUFFER) -#include -#include "ump_kernel_interface_ref_drv.h" -#include "mali_osk_list.h" -#ifdef CONFIG_ION_EXYNOS -#include -#include "../../../../../gpu/ion/ion_priv.h" -extern struct ion_device *ion_exynos; -extern struct ion_client *ion_client_ump; -#endif -#ifdef CONFIG_DMA_SHARED_BUFFER -#include -#endif -#endif - -/* - * IOCTL operation; Allocate UMP memory - */ -int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data * session_data) -{ - _ump_uk_allocate_s user_interaction; - _mali_osk_errcode_t err; - - /* Sanity check input parameters */ - if (NULL == argument || NULL == session_data) - { - MSG_ERR(("NULL parameter in ump_ioctl_allocate()\n")); - return -ENOTTY; - } - - /* Copy the user space memory to kernel space (so we safely can read it) */ - if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) - { - MSG_ERR(("copy_from_user() in ump_ioctl_allocate()\n")); - return -EFAULT; - } - - user_interaction.ctx = (void *) session_data; - - err = _ump_ukk_allocate( &user_interaction ); - if( _MALI_OSK_ERR_OK != err ) - { - DBG_MSG(1, ("_ump_ukk_allocate() failed in ump_ioctl_allocate()\n")); - return map_errcode(err); - } - user_interaction.ctx = NULL; - - if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) - { - /* If the copy fails then we should release the memory. We can use the IOCTL release to accomplish this */ - _ump_uk_release_s release_args; - - MSG_ERR(("copy_to_user() failed in ump_ioctl_allocate()\n")); - - release_args.ctx = (void *) session_data; - release_args.secure_id = user_interaction.secure_id; - - err = _ump_ukk_release( &release_args ); - if(_MALI_OSK_ERR_OK != err) - { - MSG_ERR(("_ump_ukk_release() also failed when trying to release newly allocated memory in ump_ioctl_allocate()\n")); - } - - return -EFAULT; - } - - return 0; /* success */ -} -#ifdef CONFIG_ION_EXYNOS -/* - * IOCTL operation; Import fd to UMP memory - */ -int ump_ion_import_wrapper(u32 __user * argument, struct ump_session_data * session_data) -{ - _ump_uk_ion_import_s user_interaction; - ump_dd_handle *ump_handle; - ump_dd_physical_block * blocks; - unsigned long num_blocks; - struct ion_handle *ion_hnd; - struct scatterlist *sg; - struct scatterlist *sg_ion; - unsigned long i = 0; - - ump_session_memory_list_element * session_memory_element = NULL; - if (ion_client_ump==NULL) - ion_client_ump = ion_client_create(ion_exynos, -1, "ump"); - - /* Sanity check input parameters */ - if (NULL == argument || NULL == session_data) - { - MSG_ERR(("NULL parameter in ump_ioctl_allocate()\n")); - return -ENOTTY; - } - - /* Copy the user space memory to kernel space (so we safely can read it) */ - if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) - { - MSG_ERR(("copy_from_user() in ump_ioctl_allocate()\n")); - return -EFAULT; - } - - user_interaction.ctx = (void *) session_data; - - /* translate fd to secure ID*/ - ion_hnd = ion_import_fd(ion_client_ump, user_interaction.ion_fd); - sg_ion = ion_map_dma(ion_client_ump,ion_hnd); - - blocks = (ump_dd_physical_block*)_mali_osk_malloc(sizeof(ump_dd_physical_block)*1024); - - if (NULL == blocks) { - MSG_ERR(("Failed to allocate blocks in ump_ioctl_allocate()\n")); - return -ENOMEM; - } - - sg = sg_ion; - do { - blocks[i].addr = sg_phys(sg); - blocks[i].size = sg_dma_len(sg); - i++; - if (i>=1024) { - _mali_osk_free(blocks); - MSG_ERR(("ion_import fail() in ump_ioctl_allocate()\n")); - return -EFAULT; - } - sg = sg_next(sg); - } while(sg); - - num_blocks = i; - - /* Initialize the session_memory_element, and add it to the session object */ - session_memory_element = _mali_osk_calloc( 1, sizeof(ump_session_memory_list_element)); - - if (NULL == session_memory_element) - { - _mali_osk_free(blocks); - DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n")); - return -EFAULT; - } - - ump_handle = ump_dd_handle_create_from_phys_blocks(blocks, num_blocks); - if (UMP_DD_HANDLE_INVALID == ump_handle) - { - _mali_osk_free(session_memory_element); - _mali_osk_free(blocks); - DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n")); - return -EFAULT; - } - - session_memory_element->mem = (ump_dd_mem*)ump_handle; - _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_list_add(&(session_memory_element->list), &(session_data->list_head_session_memory_list)); - _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - ion_unmap_dma(ion_client_ump,ion_hnd); - ion_free(ion_client_ump, ion_hnd); - - _mali_osk_free(blocks); - - user_interaction.secure_id = ump_dd_secure_id_get(ump_handle); - user_interaction.size = ump_dd_size_get(ump_handle); - user_interaction.ctx = NULL; - - if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) - { - /* If the copy fails then we should release the memory. We can use the IOCTL release to accomplish this */ - - MSG_ERR(("copy_to_user() failed in ump_ioctl_allocate()\n")); - - return -EFAULT; - } - return 0; /* success */ -} -#endif - -#ifdef CONFIG_DMA_SHARED_BUFFER -int ump_dmabuf_import_wrapper(u32 __user *argument, - struct ump_session_data *session_data) -{ - ump_session_memory_list_element *session = NULL; - struct ump_uk_dmabuf ump_dmabuf; - ump_dd_handle *ump_handle; - ump_dd_physical_block *blocks; - struct dma_buf_attachment *attach; - struct dma_buf *dma_buf; - struct sg_table *sgt; - struct scatterlist *sgl; - unsigned long block_size; - /* FIXME */ - struct device dev; - unsigned int i = 0, npages; - int ret; - - /* Sanity check input parameters */ - if (!argument || !session_data) { - MSG_ERR(("NULL parameter.\n")); - return -EINVAL; - } - - if (copy_from_user(&ump_dmabuf, argument, - sizeof(struct ump_uk_dmabuf))) { - MSG_ERR(("copy_from_user() failed.\n")); - return -EFAULT; - } - - dma_buf = dma_buf_get(ump_dmabuf.fd); - if (IS_ERR(dma_buf)) - return PTR_ERR(dma_buf); - - /* - * check whether dma_buf imported already exists or not. - * - * TODO - * if already imported then dma_buf_put() should be called - * and then just return dma_buf imported. - */ - - attach = dma_buf_attach(dma_buf, &dev); - if (IS_ERR(attach)) { - ret = PTR_ERR(attach); - goto err_dma_buf_put; - } - - sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); - if (IS_ERR(sgt)) { - ret = PTR_ERR(sgt); - goto err_dma_buf_detach; - } - - npages = sgt->nents; - - /* really need? */ - ump_dmabuf.ctx = (void *)session_data; - - block_size = sizeof(ump_dd_physical_block) * npages; - - blocks = (ump_dd_physical_block *)_mali_osk_malloc(block_size); - sgl = sgt->sgl; - - while (i < npages) { - blocks[i].addr = sg_phys(sgl); - blocks[i].size = sg_dma_len(sgl); - sgl = sg_next(sgl); - i++; - } - - /* - * Initialize the session memory list element, and add it - * to the session object - */ - session = _mali_osk_calloc(1, sizeof(*session)); - if (!session) { - DBG_MSG(1, ("Failed to allocate session.\n")); - ret = -EFAULT; - goto err_free_block; - } - - ump_handle = ump_dd_handle_create_from_phys_blocks(blocks, i); - if (UMP_DD_HANDLE_INVALID == ump_handle) { - DBG_MSG(1, ("Failed to create ump handle.\n")); - ret = -EFAULT; - goto err_free_session; - } - - session->mem = (ump_dd_mem *)ump_handle; - - _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_list_add(&(session->list), - &(session_data->list_head_session_memory_list)); - _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - - _mali_osk_free(blocks); - - ump_dmabuf.ump_handle = (uint32_t)ump_handle; - ump_dmabuf.size = ump_dd_size_get(ump_handle); - - if (copy_to_user(argument, &ump_dmabuf, - sizeof(struct ump_uk_dmabuf))) { - MSG_ERR(("copy_to_user() failed.\n")); - ret = -EFAULT; - goto err_release_ump_handle; - } - - return 0; - -err_release_ump_handle: - ump_dd_reference_release(ump_handle); -err_free_session: - _mali_osk_free(session); -err_free_block: - _mali_osk_free(blocks); - dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); -err_dma_buf_detach: - dma_buf_detach(dma_buf, attach); -err_dma_buf_put: - dma_buf_put(dma_buf); - return ret; -} -#endif diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h deleted file mode 100644 index 416a584..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_ukk_wrappers.h - * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls for the reference implementation - */ - -#ifndef __UMP_UKK_REF_WRAPPERS_H__ -#define __UMP_UKK_REF_WRAPPERS_H__ - -#include -#include "ump_kernel_common.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - - -int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data * session_data); - -#ifdef CONFIG_ION_EXYNOS -int ump_ion_import_wrapper(u32 __user * argument, struct ump_session_data * session_data); -#endif - -#ifdef CONFIG_DMA_SHARED_BUFFER -int ump_dmabuf_import_wrapper(u32 __user *argument, - struct ump_session_data *session_data); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_UKK_REF_WRAPPERS_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c b/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c deleted file mode 100644 index 780f311..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_ukk_wrappers.c - * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls - */ - -#include /* user space access */ - -#include "ump_osk.h" -#include "ump_uk_types.h" -#include "ump_ukk.h" -#include "ump_kernel_common.h" - -/* - * IOCTL operation; Negotiate version of IOCTL API - */ -int ump_get_api_version_wrapper(u32 __user * argument, struct ump_session_data * session_data) -{ - _ump_uk_api_version_s version_info; - _mali_osk_errcode_t err; - - /* Sanity check input parameters */ - if (NULL == argument || NULL == session_data) - { - MSG_ERR(("NULL parameter in ump_ioctl_get_api_version()\n")); - return -ENOTTY; - } - - /* Copy the user space memory to kernel space (so we safely can read it) */ - if (0 != copy_from_user(&version_info, argument, sizeof(version_info))) - { - MSG_ERR(("copy_from_user() in ump_ioctl_get_api_version()\n")); - return -EFAULT; - } - - version_info.ctx = (void*) session_data; - err = _ump_uku_get_api_version( &version_info ); - if( _MALI_OSK_ERR_OK != err ) - { - MSG_ERR(("_ump_uku_get_api_version() failed in ump_ioctl_get_api_version()\n")); - return map_errcode(err); - } - - version_info.ctx = NULL; - - /* Copy ouput data back to user space */ - if (0 != copy_to_user(argument, &version_info, sizeof(version_info))) - { - MSG_ERR(("copy_to_user() failed in ump_ioctl_get_api_version()\n")); - return -EFAULT; - } - - return 0; /* success */ -} - - -/* - * IOCTL operation; Release reference to specified UMP memory. - */ -int ump_release_wrapper(u32 __user * argument, struct ump_session_data * session_data) -{ - _ump_uk_release_s release_args; - _mali_osk_errcode_t err; - - /* Sanity check input parameters */ - if (NULL == session_data) - { - MSG_ERR(("NULL parameter in ump_ioctl_release()\n")); - return -ENOTTY; - } - - /* Copy the user space memory to kernel space (so we safely can read it) */ - if (0 != copy_from_user(&release_args, argument, sizeof(release_args))) - { - MSG_ERR(("copy_from_user() in ump_ioctl_get_api_version()\n")); - return -EFAULT; - } - - release_args.ctx = (void*) session_data; - err = _ump_ukk_release( &release_args ); - if( _MALI_OSK_ERR_OK != err ) - { - MSG_ERR(("_ump_ukk_release() failed in ump_ioctl_release()\n")); - return map_errcode(err); - } - - - return 0; /* success */ -} - -/* - * IOCTL operation; Return size for specified UMP memory. - */ -int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * session_data) -{ - _ump_uk_size_get_s user_interaction; - _mali_osk_errcode_t err; - - /* Sanity check input parameters */ - if (NULL == argument || NULL == session_data) - { - MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); - return -ENOTTY; - } - - if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) - { - MSG_ERR(("copy_from_user() in ump_ioctl_size_get()\n")); - return -EFAULT; - } - - user_interaction.ctx = (void *) session_data; - err = _ump_ukk_size_get( &user_interaction ); - if( _MALI_OSK_ERR_OK != err ) - { - MSG_ERR(("_ump_ukk_size_get() failed in ump_ioctl_size_get()\n")); - return map_errcode(err); - } - - user_interaction.ctx = NULL; - - if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) - { - MSG_ERR(("copy_to_user() failed in ump_ioctl_size_get()\n")); - return -EFAULT; - } - - return 0; /* success */ -} - -/* - * IOCTL operation; Do cache maintenance on specified UMP memory. - */ -int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data) -{ - _ump_uk_msync_s user_interaction; - - /* Sanity check input parameters */ - if (NULL == argument || NULL == session_data) - { - MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); - return -ENOTTY; - } - - if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) - { - MSG_ERR(("copy_from_user() in ump_ioctl_msync()\n")); - return -EFAULT; - } - - user_interaction.ctx = (void *) session_data; - - _ump_ukk_msync( &user_interaction ); - - user_interaction.ctx = NULL; - - if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) - { - MSG_ERR(("copy_to_user() failed in ump_ioctl_msync()\n")); - return -EFAULT; - } - - return 0; /* success */ -} -int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_session_data * session_data) -{ - _ump_uk_cache_operations_control_s user_interaction; - - /* Sanity check input parameters */ - if (NULL == argument || NULL == session_data) - { - MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); - return -ENOTTY; - } - - if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) - { - MSG_ERR(("copy_from_user() in ump_ioctl_cache_operations_control()\n")); - return -EFAULT; - } - - user_interaction.ctx = (void *) session_data; - - _ump_ukk_cache_operations_control((_ump_uk_cache_operations_control_s*) &user_interaction ); - - user_interaction.ctx = NULL; - -#if 0 /* No data to copy back */ - if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) - { - MSG_ERR(("copy_to_user() failed in ump_ioctl_cache_operations_control()\n")); - return -EFAULT; - } -#endif - return 0; /* success */ -} - -int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data * session_data) -{ - _ump_uk_switch_hw_usage_s user_interaction; - - /* Sanity check input parameters */ - if (NULL == argument || NULL == session_data) - { - MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); - return -ENOTTY; - } - - if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) - { - MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n")); - return -EFAULT; - } - - user_interaction.ctx = (void *) session_data; - - _ump_ukk_switch_hw_usage( &user_interaction ); - - user_interaction.ctx = NULL; - -#if 0 /* No data to copy back */ - if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) - { - MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n")); - return -EFAULT; - } -#endif - return 0; /* success */ -} - -int ump_lock_wrapper(u32 __user * argument, struct ump_session_data * session_data) -{ - _ump_uk_lock_s user_interaction; - - /* Sanity check input parameters */ - if (NULL == argument || NULL == session_data) - { - MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); - return -ENOTTY; - } - - if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) - { - MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n")); - return -EFAULT; - } - - user_interaction.ctx = (void *) session_data; - - _ump_ukk_lock( &user_interaction ); - - user_interaction.ctx = NULL; - -#if 0 /* No data to copy back */ - if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) - { - MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n")); - return -EFAULT; - } -#endif - - return 0; /* success */ -} - -int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data * session_data) -{ - _ump_uk_unlock_s user_interaction; - - /* Sanity check input parameters */ - if (NULL == argument || NULL == session_data) - { - MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); - return -ENOTTY; - } - - if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) - { - MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n")); - return -EFAULT; - } - - user_interaction.ctx = (void *) session_data; - - _ump_ukk_unlock( &user_interaction ); - - user_interaction.ctx = NULL; - -#if 0 /* No data to copy back */ - if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) - { - MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n")); - return -EFAULT; - } -#endif - - return 0; /* success */ -} diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h b/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h deleted file mode 100644 index e87a903..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file ump_ukk_wrappers.h - * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls - */ - -#ifndef __UMP_UKK_WRAPPERS_H__ -#define __UMP_UKK_WRAPPERS_H__ - -#include -#include "ump_kernel_common.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - - - -int ump_get_api_version_wrapper(u32 __user * argument, struct ump_session_data * session_data); -int ump_release_wrapper(u32 __user * argument, struct ump_session_data * session_data); -int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * session_data); -int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data); -int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_session_data * session_data); -int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data * session_data); -int ump_lock_wrapper(u32 __user * argument, struct ump_session_data * session_data); -int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data * session_data); - - - - -#ifdef __cplusplus -} -#endif - - - -#endif /* __UMP_UKK_WRAPPERS_H__ */ -- cgit v1.1 From 0be3fbfd3cba7e301777d3e104b71c379c12533b Mon Sep 17 00:00:00 2001 From: sbrissen Date: Wed, 11 Dec 2013 13:33:57 -0500 Subject: Kona: up charging current to stock Change-Id: I20b9c19bd6d7fa67c9edd80261224414cde8c53c --- drivers/battery/max77693_charger.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/battery/max77693_charger.c b/drivers/battery/max77693_charger.c index 35289a6..5b4293c 100644 --- a/drivers/battery/max77693_charger.c +++ b/drivers/battery/max77693_charger.c @@ -109,10 +109,12 @@ /* MAX77693_CHG_REG_CHG_CNFG_04 */ #define MAX77693_CHG_MINVSYS_MASK 0xE0 #define MAX77693_CHG_MINVSYS_SHIFT 5 +#define MAX77693_CHG_MINVSYS_3_4V 0x04 #define MAX77693_CHG_MINVSYS_3_6V 0x06 #define MAX77693_CHG_CV_PRM_MASK 0x1F #define MAX77693_CHG_CV_PRM_SHIFT 0 #define MAX77693_CHG_CV_PRM_4_20V 0x16 +#define MAX77693_CHG_CV_PRM_4_30V 0x1A #define MAX77693_CHG_CV_PRM_4_35V 0x1D #define MAX77693_CHG_CV_PRM_4_40V 0x1F @@ -149,7 +151,11 @@ #define STABLE_POWER_DELAY 500 /* charger type detection */ +#if defined(CONFIG_MACH_KONA) +#define DET_ERR_RETRY 7 +#else #define DET_ERR_RETRY 5 +#endif #define DET_ERR_DELAY 200 /* soft charging */ @@ -855,7 +861,12 @@ chg_det_err: chg_data->reg_loop_deted = false; state = POWER_SUPPLY_TYPE_BATTERY; break; - case 0x1: /* USB cabled */ + case 0x1: /* USB cabled */ +#if defined(CONFIG_MACH_KONA) + if(mu_adc1k == 0x80) //MHL charging + state = POWER_SUPPLY_TYPE_MAINS; + else +#endif state = POWER_SUPPLY_TYPE_USB; #ifdef CONFIG_BATTERY_WPC_CHARGER wc_state = max77693_get_wc_state(chg_data); @@ -1101,8 +1112,14 @@ static void max77693_charger_reg_init(struct max77693_charger_data *chg_data) reg_data |= (0x00 << 3); /* 0min */ } else { #if defined(USE_2STEP_TERM) /* now only T0 */ +#if defined(CONFIG_MACH_KONA) + reg_data = (0x05 << 0); /* 250mA */ + reg_data |= (0x04 << 3); /* 40min */ +#else + reg_data = (0x04 << 0); /* 200mA */ reg_data |= (0x04 << 3); /* 40min */ +#endif #else #if defined(CONFIG_MACH_GC1) reg_data = (0x02 << 0); /* 150mA */ @@ -1121,13 +1138,19 @@ static void max77693_charger_reg_init(struct max77693_charger_data *chg_data) */ max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_04, ®_data); reg_data &= (~MAX77693_CHG_MINVSYS_MASK); +#if defined(CONFIG_MACH_KONA) + reg_data |= (MAX77693_CHG_MINVSYS_3_4V << MAX77693_CHG_MINVSYS_SHIFT); +#else reg_data |= (MAX77693_CHG_MINVSYS_3_6V << MAX77693_CHG_MINVSYS_SHIFT); +#endif reg_data &= (~MAX77693_CHG_CV_PRM_MASK); #if defined(CONFIG_MACH_M0) if ((system_rev != 3) && (system_rev >= 1)) reg_data |= (MAX77693_CHG_CV_PRM_4_35V << 0); else reg_data |= (MAX77693_CHG_CV_PRM_4_20V << 0); +#elif defined(CONFIG_MACH_KONA) + reg_data |= (MAX77693_CHG_CV_PRM_4_30V << 0); #else /* C1, C2, M3, T0, ... */ reg_data |= (MAX77693_CHG_CV_PRM_4_35V << 0); #endif -- cgit v1.1 From cb45b00f2febffb7711f898f2e98e7f53a0c84ba Mon Sep 17 00:00:00 2001 From: sbrissen Date: Fri, 13 Dec 2013 14:35:25 -0500 Subject: smdk4412: revert jpeg_dev from update 11 fixes front cam for some that broke from update 11 merge http://forum.xda-developers.com/showpost.php?p=48429637&postcount=576 Change-Id: I4a654f10e9ccd50a744a710ecd01d2d26f67401d --- drivers/media/video/samsung/jpeg/jpeg_dev.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/samsung/jpeg/jpeg_dev.c b/drivers/media/video/samsung/jpeg/jpeg_dev.c index 6ebcfb6..4038fd2 100644 --- a/drivers/media/video/samsung/jpeg/jpeg_dev.c +++ b/drivers/media/video/samsung/jpeg/jpeg_dev.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -248,12 +247,6 @@ int jpeg_mmap(struct file *filp, struct vm_area_struct *vma) size = vma->vm_end - vma->vm_start; - if (!cma_is_registered_region(jpeg_ctrl->mem.base, size)) { - pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n", - __func__, (unsigned int)size, jpeg_ctrl->mem.base); - return -EINVAL; - } - vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -- cgit v1.1 From f9a3f53f7726335685a8eea3a76560dfe62278eb Mon Sep 17 00:00:00 2001 From: sbrissen Date: Fri, 13 Dec 2013 22:02:30 -0500 Subject: smdk4412: fix mag cover turning screen off when charger is plugged in or disconnected while cover is closed and then opened. Change-Id: Ifa74d3d0689e1a5c84a4683c2fe24918bc5ab87a --- drivers/input/keyboard/gpio_keys.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index b1fddc8..6feb939 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -711,7 +711,9 @@ static void flip_cover_work(struct work_struct *work) flip_cover_open = ddata->flip_cover; if(!ts_powered_on && !ddata->flip_cover){ - printk("screen already off\n"); + printk("[keys] screen already off\n"); + }else if(ts_powered_on && ddata->flip_cover){ + printk("[keys] screen already on\n"); }else{ input_report_key(ddata->input, KEY_POWER, 1); input_sync(ddata->input); -- cgit v1.1 From fab9e4c915e35338d589b04b3b9c2a9ce283e960 Mon Sep 17 00:00:00 2001 From: sbrissen Date: Mon, 16 Dec 2013 13:18:35 -0500 Subject: smdk4412: remove some logging I added Change-Id: I264ee04c7c6726e68cdd186f22ab45dc8bf5be0f --- drivers/media/video/samsung/fimc/fimc_capture.c | 6 ------ drivers/mmc/card/block.c | 1 - 2 files changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/samsung/fimc/fimc_capture.c b/drivers/media/video/samsung/fimc/fimc_capture.c index 75928ed..e438205 100644 --- a/drivers/media/video/samsung/fimc/fimc_capture.c +++ b/drivers/media/video/samsung/fimc/fimc_capture.c @@ -1927,7 +1927,6 @@ int fimc_reqbufs_capture_mmap(void *fh, struct v4l2_requestbuffers *b) case V4L2_PIX_FMT_YVYU: /* fall through */ case V4L2_PIX_FMT_NV16: /* fall through */ case V4L2_PIX_FMT_NV61: /* fall through */ - fimc_err("%s : V4L2_PIX_FMT_YUYV - SBRISSEN\n", __func__); fimc_err("%s : w %d h %d \n",__func__, cap->fmt.width, cap->fmt.height); fimc_info1("%s : 1plane\n", __func__); @@ -1936,7 +1935,6 @@ int fimc_reqbufs_capture_mmap(void *fh, struct v4l2_requestbuffers *b) break; case V4L2_PIX_FMT_NV21: - fimc_err("%s : V4L2_PIX_FMT_NV12 - SBRISSEN\n", __func__); fimc_info1("%s : 2plane for NV21 w %d h %d\n", __func__, cap->fmt.width, cap->fmt.height); ret = fimc_alloc_buffers(ctrl, 2, @@ -1966,21 +1964,18 @@ int fimc_reqbufs_capture_mmap(void *fh, struct v4l2_requestbuffers *b) break; case V4L2_PIX_FMT_JPEG: - fimc_err("%s : V4L2_PIX_FMT_JPEG - SBRISSEN\n", __func__); fimc_info1("%s : JPEG 1plane\n", __func__); size = fimc_camera_get_jpeg_memsize(ctrl); fimc_info2("%s : JPEG 1plane size = %x\n", __func__, size); ret = fimc_alloc_buffers(ctrl, 1, size, 0, 8, cap->pktdata_enable, cap->pktdata_size); break; case V4L2_PIX_FMT_INTERLEAVED: - fimc_err("%s : V4L2_PIX_FMT_INTERLEAVED - SBRISSEN\n", __func__); fimc_info1("%s : Interleaved Format\n", __func__); size = fimc_camera_get_jpeg_memsize(ctrl); /*0xA00000*/ fimc_info2("%s : Interleaved size = %x\n", __func__, size); ret = fimc_alloc_buffers(ctrl, 1, size, 0, 8, cap->pktdata_enable, cap->pktdata_size); break; default: - fimc_err("%s : default - SBRISSEN\n", __func__); break; } @@ -1990,7 +1985,6 @@ int fimc_reqbufs_capture_mmap(void *fh, struct v4l2_requestbuffers *b) return -ENOMEM; } - fimc_err("%s : SBRISSEN - done\n", __func__); mutex_unlock(&ctrl->v4l2_lock); return 0; diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 1c63296..2d55947 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2020,7 +2020,6 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) mq_rq->packed_num -= idx; #ifdef CONFIG_WIMAX_CMC if (mq_rq->packed_num == 1) { - printk(KERN_ERR "SBRISSEN - I AM HERE\n"); mq_rq->packed_cmd = MMC_PACKED_NONE; mq_rq->packed_num = 0; } -- cgit v1.1 From 23c72d6d1716c1e6002089cf5d3a43477586e297 Mon Sep 17 00:00:00 2001 From: abmantis Date: Wed, 18 Dec 2013 23:53:47 +0000 Subject: filter multicast packages while suspended. in some crowded WLANs, with a lot of multicast packages circulating, the device would not enter deep sleep. this will allow the device to enter deep sleep. Change-Id: I72cfefe89af64a7152e644d5095a57823ef04f4e --- drivers/net/wireless/bcmdhd/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 40bc790..5121318 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -18,7 +18,7 @@ DHDCFLAGS += -Wall -Wstrict-prototypes -Dlinux -DLINUX -DBCMDRIVER \ DHDCFLAGS += -DCUSTOMER_HW4 DHDCFLAGS += -DDEBUGFS_CFG80211 -DHDCFLAGS += -DBLOCK_IPV6_PACKET -DPASS_IPV4_SUSPEND +DHDCFLAGS += -DBLOCK_IPV6_PACKET DHDCFLAGS += -DSUPPORT_DEEP_SLEEP DHDCFLAGS += -DSIMPLE_MAC_PRINT -- cgit v1.1 From b1663250fbbcfab17bd76665e9a95876f33a50a5 Mon Sep 17 00:00:00 2001 From: sbrissen Date: Thu, 19 Dec 2013 15:28:13 -0500 Subject: smdk4412: update ssp_sysfs from jf 4.4 drop This fixes the need to set an initial delay in the sensor hal in order for the sensors to enable and report data Change-Id: I1aa639e2cc30be60d00df253a90ea9dd1a6d501f --- drivers/sensorhub/ssp_sysfs.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/sensorhub/ssp_sysfs.c b/drivers/sensorhub/ssp_sysfs.c index 0ce5ff9..1bc7f17 100644 --- a/drivers/sensorhub/ssp_sysfs.c +++ b/drivers/sensorhub/ssp_sysfs.c @@ -103,7 +103,7 @@ static void change_sensor_delay(struct ssp_data *data, break; default: - data->aiCheckStatus[iSensorType] = ADD_SENSOR_STATE; + break; } } @@ -133,20 +133,7 @@ static int ssp_remove_sensor(struct ssp_data *data, data->adDelayBuf[uChangedSensor] = DEFUALT_POLLING_DELAY; - if (data->aiCheckStatus[uChangedSensor] == INITIALIZATION_STATE) { - data->aiCheckStatus[uChangedSensor] = NO_SENSOR_STATE; - if (uChangedSensor == ACCELEROMETER_SENSOR) - accel_open_calibration(data); - else if (uChangedSensor == GYROSCOPE_SENSOR) - gyro_open_calibration(data); - else if (uChangedSensor == PRESSURE_SENSOR) - pressure_open_calibration(data); - else if (uChangedSensor == PROXIMITY_SENSOR) { - proximity_open_lcd_ldi(data); - proximity_open_calibration(data); - } - return 0; - } else if (uChangedSensor == ORIENTATION_SENSOR) { + if (uChangedSensor == ORIENTATION_SENSOR) { if (!(atomic_read(&data->aSensorEnable) & (1 << ACCELEROMETER_SENSOR))) { uChangedSensor = ACCELEROMETER_SENSOR; @@ -200,6 +187,7 @@ static ssize_t set_sensors_enable(struct device *dev, int64_t dTemp; unsigned int uNewEnable = 0, uChangedSensor = 0; struct ssp_data *data = dev_get_drvdata(dev); + int iRet; if (strict_strtoll(buf, 10, &dTemp) < 0) return -1; @@ -215,11 +203,24 @@ static ssize_t set_sensors_enable(struct device *dev, if ((atomic_read(&data->aSensorEnable) & (1 << uChangedSensor)) != (uNewEnable & (1 << uChangedSensor))) { - if (uNewEnable & (1 << uChangedSensor)) - ssp_add_sensor(data, uChangedSensor); - else - ssp_remove_sensor(data, uChangedSensor, - uNewEnable); + if (!(uNewEnable & (1 << uChangedSensor))) + ssp_remove_sensor(data, uChangedSensor, + uNewEnable); /* disable */ + else { /* Change to ADD_SENSOR_STATE from KitKat */ + if (data->aiCheckStatus[uChangedSensor] == INITIALIZATION_STATE) { + if (uChangedSensor == ACCELEROMETER_SENSOR) + accel_open_calibration(data); + else if (uChangedSensor == GYROSCOPE_SENSOR) + gyro_open_calibration(data); + else if (uChangedSensor == PRESSURE_SENSOR) + pressure_open_calibration(data); + else if (uChangedSensor == PROXIMITY_SENSOR) { + proximity_open_lcd_ldi(data); + proximity_open_calibration(data); + } + } + data->aiCheckStatus[uChangedSensor] = ADD_SENSOR_STATE; + } break; } -- cgit v1.1 From bdb64beb2b3182ded6b4df3c700b2fae2c5650ef Mon Sep 17 00:00:00 2001 From: Truong Ta Xuan Date: Sun, 19 Jan 2014 08:15:49 +0700 Subject: Fix proximity sensor for GT-N5100 Change-Id: Ic5542259e9ff91ba20216844cf8a65f4a252c111 --- drivers/sensor/gp2a_proximity.c | 763 ++++++++++++++++++++++------------------ 1 file changed, 418 insertions(+), 345 deletions(-) (limited to 'drivers') diff --git a/drivers/sensor/gp2a_proximity.c b/drivers/sensor/gp2a_proximity.c index 7efbf3e..c1624e6 100644 --- a/drivers/sensor/gp2a_proximity.c +++ b/drivers/sensor/gp2a_proximity.c @@ -47,8 +47,6 @@ #define VENDOR "SHARP" #define CHIP_ID "GP2AP" -#define OFFSET_FILE_PATH "/efs/prox_cal" - #if 1 #define gprintk(fmt, x...) printk(KERN_INFO "%s(%d): "\ fmt, __func__ , __LINE__, ## x) @@ -56,17 +54,31 @@ fmt, __func__ , __LINE__, ## x) #define gprintk(x...) do { } while (0) #endif /**************************************************/ -#if defined(CONFIG_MACH_BAFFIN) -#define PROX_READ_NUM 20 +/* Calibration*/ +#define GP2A_CALIBRATION +#ifdef GP2A_CALIBRATION +#ifdef CONFIG_SLP +#define CALIBRATION_FILE_PATH "/csa/sensor/prox_cal_data" #else -#define PROX_READ_NUM 40 +#define CALIBRATION_FILE_PATH "/efs/prox_cal" +#endif +#endif +#if defined(CONFIG_MACH_KONA_SENSOR) +#define DEFAULT_THRESHOLD_DIFF 2 +#else +#define DEFAULT_THRESHOLD_DIFF 1 #endif +#define PROX_READ_NUM 40 #define PS_LOW_THD_L 0x08 #define PS_LOW_THD_H 0x09 #define PS_HIGH_THD_L 0x0A #define PS_HIGH_THD_H 0x0B +#if defined(CONFIG_MACH_KONA_SENSOR) +#define XTALK 8 +#define THDL 10 +#endif /* global var */ static struct i2c_driver opt_i2c_driver; static struct i2c_client *opt_i2c_client; @@ -85,17 +97,17 @@ struct gp2a_data { struct hrtimer prox_timer; struct workqueue_struct *prox_wq; struct work_struct work_prox; - int enabled; int proximity_data; int irq; int average[3]; /*for proximity adc average */ ktime_t prox_poll_delay; - - /* Auto Calibration */ - int offset_value; - int cal_result; - uint16_t threshold_high; - bool offset_cal_high; + u8 enabled; + u8 thresh_diff; + u8 power_state; +#ifdef GP2A_CALIBRATION + u8 default_threshold; + u8 cal_data; +#endif }; /* initial value for sensor register */ @@ -113,13 +125,17 @@ static u8 gp2a_original_image_030a[COL][2] = { /* {0x05 , 0x00}, */ /* {0x06 , 0xFF}, */ /* {0x07 , 0xFF}, */ -#if defined(CONFIG_MACH_BAFFIN) - {0x08, 0x08}, +#if defined(CONFIG_MACH_KONA_SENSOR) + {0x08, 0x08}, /*PS mode LTH(Loff): (??mm) */ #else - {0x08, 0x09}, /*PS mode LTH(Loff): (??mm) */ + {0x08, 0x09}, /*PS mode LTH(Loff): (??mm) */ #endif {0x09, 0x00}, /*PS mode LTH(Loff) : */ - {0x0A, 0x0A}, /*PS mode HTH(Lon) : (??mm) */ +#if defined(CONFIG_MACH_KONA_SENSOR) + {0x0A, 0x0A}, /*PS mode HTH(Lon) : (??mm) */ +#else + {0x0A, 0x0A}, /*PS mode HTH(Lon) : (??mm) */ +#endif {0x0B, 0x00}, /* PS mode HTH(Lon) : */ /* {0x13 , 0x08}, by sharp for internal calculation (type:0) */ /*alternating mode (PS+ALS), TYPE=1 @@ -150,27 +166,22 @@ static u8 gp2a_original_image[COL][2] = { {0x00, 0xC0} }; -#define THR_REG_LSB(data, reg) \ - { \ - reg = (u8)data & 0xff; \ - } -#define THR_REG_MSB(data, reg) \ - { \ - reg = (u8)data >> 8; \ - } - static int proximity_onoff(u8 onoff); +#ifdef GP2A_CALIBRATION +static int proximity_open_calibration(struct gp2a_data *data); +#endif int is_gp2a030a(void) { -#if defined(CONFIG_MACH_C1) || \ - defined(CONFIG_MACH_M0) || \ - defined(CONFIG_MACH_GRANDE) || \ +#if defined(CONFIG_MACH_GRANDE) || \ defined(CONFIG_MACH_IRON) return (system_rev != 0 && system_rev != 3); #endif -#if defined(CONFIG_MACH_M3) || \ - defined(CONFIG_MACH_BAFFIN) +#if defined(CONFIG_MACH_M3_USA_TMO) || \ + defined(CONFIG_MACH_BAFFIN) || \ + defined(CONFIG_MACH_KONA_SENSOR) ||\ + defined(CONFIG_MACH_TAB3) ||\ + defined(CONFIG_MACH_GC2PD) return 1; #endif #if defined(CONFIG_MACH_REDWOOD) @@ -180,17 +191,23 @@ int is_gp2a030a(void) return 0; } -static int gp2a_update_threshold(u8 (*selected_image)[2], - unsigned long new_threshold, bool update_reg) +static int gp2a_update_threshold(struct gp2a_data *data, + u8 (*selected_image)[2], u8 new_threshold, bool update_reg) { int i, err = 0; u8 set_value; + pr_info("%s, new = 0x%x, thresh_diff = %d\n", __func__, + new_threshold, data->thresh_diff); for (i = 0; i < COL; i++) { switch (selected_image[i][0]) { case PS_LOW_THD_L: /*PS mode LTH(Loff) for low 8bit*/ +#if defined(CONFIG_MACH_KONA_SENSOR) + set_value = (new_threshold-data->thresh_diff) & 0x00FF; +#else set_value = new_threshold & 0x00FF; +#endif break; case PS_LOW_THD_H: @@ -200,12 +217,17 @@ static int gp2a_update_threshold(u8 (*selected_image)[2], case PS_HIGH_THD_L: /*PS mode HTH(Lon) for low 8bit*/ - set_value = (new_threshold+1) & 0x00FF; +#if defined(CONFIG_MACH_KONA_SENSOR) + set_value = (new_threshold) & 0x00FF; +#else + set_value = (new_threshold+data->thresh_diff) & 0x00FF; +#endif break; case PS_HIGH_THD_H: /* PS mode HTH(Lon) for high 8bit*/ - set_value = ((new_threshold+1) & 0xFF00) >> 8; + set_value = ((new_threshold + +data->thresh_diff) & 0xFF00) >> 8; break; default: @@ -219,238 +241,14 @@ static int gp2a_update_threshold(u8 (*selected_image)[2], pr_err("%s : setting error i = %d, err=%d\n", __func__, i, err); return err; - } else - selected_image[i][1] = set_value; - } - - return err; -} - -static int proximity_adc_read(struct gp2a_data *data) -{ - int sum[OFFSET_ARRAY_LENGTH]; - int i = OFFSET_ARRAY_LENGTH-1; - int avg; - int min; - int max; - int total; - int D2_data; - unsigned char get_D2_data[2]; - - mutex_lock(&data->data_mutex); - do { - msleep(50); - opt_i2c_read(DATA2_LSB, get_D2_data, sizeof(get_D2_data)); - D2_data = (get_D2_data[1] << 8) | get_D2_data[0]; - sum[i] = D2_data; - if (i == 0) { - min = sum[i]; - max = sum[i]; } else { - if (sum[i] < min) - min = sum[i]; - else if (sum[i] > max) - max = sum[i]; + selected_image[i][1] = set_value; } - total += sum[i]; - } while (i--); - mutex_unlock(&data->data_mutex); - - total -= (min + max); - avg = (int)(total / (OFFSET_ARRAY_LENGTH - 2)); - pr_info("%s: offset = %d\n", __func__, avg); - - return avg; -} - - -static int proximity_open_calibration(struct gp2a_data *data) -{ - struct file *cal_filp = NULL; - int err = 0; - mm_segment_t old_fs; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - cal_filp = filp_open(OFFSET_FILE_PATH, - O_RDONLY, S_IRUGO | S_IWUSR | S_IWGRP); - - if (IS_ERR(cal_filp)) { - pr_err("%s: Can't open calibration file\n", __func__); - set_fs(old_fs); - err = PTR_ERR(cal_filp); - goto done; } - err = cal_filp->f_op->read(cal_filp, - (char *)&data->offset_value, - sizeof(int), &cal_filp->f_pos); - if (err != sizeof(int)) { - pr_err("%s: Can't read the cal data from file\n", __func__); - err = -EIO; - } - - pr_info("%s: (%d)\n", __func__, - data->offset_value); - - filp_close(cal_filp, current->files); -done: - set_fs(old_fs); return err; } -static int proximity_do_calibrate(struct gp2a_data *data, - bool do_calib, bool thresh_set) -{ - struct file *cal_filp; - int err; - int xtalk_avg = 0; - int offset_change = 0; - uint16_t thrd = 0; - u8 reg; - mm_segment_t old_fs; - - u8 (*cal_image)[2] = (is_gp2a030a() ? - gp2a_original_image_030a : gp2a_original_image); - - if (do_calib) { - if (thresh_set) { - /* for proximity_thresh_store */ - data->offset_value = - data->threshold_high - - (cal_image[6][1] << 8 | cal_image[5][1]); - } else { - /* tap offset button */ - /* get offset value */ - xtalk_avg = proximity_adc_read(data); - offset_change = - (cal_image[6][1] << 8 | cal_image[5][1]) - - DEFAULT_HI_THR; - if (xtalk_avg < offset_change) { - /* do not need calibration */ - data->cal_result = 0; - err = 0; - goto no_cal; - } - data->offset_value = xtalk_avg - offset_change; - } - /* update threshold */ - thrd = (cal_image[4][1] << 8 | cal_image[3][1]) - + (data->offset_value); - THR_REG_LSB(thrd, reg); - opt_i2c_write(cal_image[3][0], ®); - THR_REG_MSB(thrd, reg); - opt_i2c_write(cal_image[4][0], ®); - - thrd = (cal_image[4][1] << 8 | cal_image[5][1]) - +(data->offset_value); - THR_REG_LSB(thrd, reg); - opt_i2c_write(cal_image[5][0], ®); - THR_REG_MSB(thrd, reg); - opt_i2c_write(cal_image[6][0], ®); - - /* calibration result */ - if (!thresh_set) - data->cal_result = 1; - } else { - /* tap reset button */ - data->offset_value = 0; - /* update threshold */ - opt_i2c_write(cal_image[3][0], &cal_image[3][1]); - opt_i2c_write(cal_image[4][0], &cal_image[4][1]); - opt_i2c_write(cal_image[5][0], &cal_image[5][1]); - opt_i2c_write(cal_image[6][0], &cal_image[6][1]); - /* calibration result */ - data->cal_result = 2; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - cal_filp = filp_open(OFFSET_FILE_PATH, - O_CREAT | O_TRUNC | O_WRONLY, - S_IRUGO | S_IWUSR | S_IWGRP); - - if (IS_ERR(cal_filp)) { - pr_err("%s: Can't open calibration file\n", __func__); - set_fs(old_fs); - err = PTR_ERR(cal_filp); - goto done; - } - - err = cal_filp->f_op->write(cal_filp, - (char *)&data->offset_value, sizeof(int), - &cal_filp->f_pos); - if (err != sizeof(int)) { - pr_err("%s: Can't write the cal data to file\n", __func__); - err = -EIO; - } - - filp_close(cal_filp, current->files); -done: - set_fs(old_fs); -no_cal: - return err; -} - -static int proximity_manual_offset(struct gp2a_data *data, u8 change_on) -{ - struct file *cal_filp; - int err; - int16_t thrd; - u8 reg; - mm_segment_t old_fs; - - u8 (*manual_image)[2] = (is_gp2a030a() ? - gp2a_original_image_030a : gp2a_original_image); - - data->offset_value = change_on; - /* update threshold */ - thrd = manual_image[3][1]+(data->offset_value); - THR_REG_LSB(thrd, reg); - opt_i2c_write(manual_image[3][0], ®); - THR_REG_MSB(thrd, reg); - opt_i2c_write(manual_image[4][0], ®); - - thrd = manual_image[5][1]+(data->offset_value); - THR_REG_LSB(thrd, reg); - opt_i2c_write(manual_image[5][0], ®); - THR_REG_MSB(thrd, reg); - opt_i2c_write(manual_image[6][0], ®); - - /* calibration result */ - data->cal_result = 1; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - cal_filp = filp_open(OFFSET_FILE_PATH, - O_CREAT | O_TRUNC | O_WRONLY, - S_IRUGO | S_IWUSR | S_IWGRP); - - if (IS_ERR(cal_filp)) { - pr_err("%s: Can't open calibration file\n", __func__); - set_fs(old_fs); - err = PTR_ERR(cal_filp); - goto done; - } - - err = cal_filp->f_op->write(cal_filp, - (char *)&data->offset_value, sizeof(int), - &cal_filp->f_pos); - if (err != sizeof(int)) { - pr_err("%s: Can't write the cal data to file\n", __func__); - err = -EIO; - } - - filp_close(cal_filp, current->files); -done: - set_fs(old_fs); - return err; -} - - /* Proximity Sysfs interface */ static ssize_t proximity_enable_show(struct device *dev, @@ -477,28 +275,63 @@ proximity_enable_store(struct device *dev, err = kstrtoint(buf, 10, &value); if (err) - printk(KERN_ERR "%s, kstrtoint failed.", __func__); + pr_err("%s, kstrtoint failed.", __func__); if (value != 0 && value != 1) return count; gprintk("value = %d\n", value); - if (data->enabled && !value) { /* Proximity power off */ + if (data->enabled && !value) { /* proximity disable */ disable_irq(data->irq); - proximity_enable = value; + data->enabled = 0; proximity_onoff(0); disable_irq_wake(data->irq); - data->pdata->gp2a_led_on(false); - } else if (!data->enabled && value) { /* proximity power on */ - data->pdata->gp2a_led_on(true); - /*msleep(1); */ - proximity_enable = value; + /* proximity power off */ + if (data->pdata->gp2a_led_on + && data->power_state) { + data->pdata->gp2a_led_on(false); + data->power_state = 0; + } + +#ifdef CONFIG_SENSORS_GP2A_VDD_CONTROL + /* gp2a vdd power off */ + if (data->pdata->gp2a_vdd_on + && !(data->enabled & LIGHT_ENABLED)) { + data->pdata->gp2a_vdd_on(false); + data->power_state &= ~LIGHT_ENABLED; + } +#endif + } else if (!(data->enabled) && value) { /* proximity enable */ + /* proximity power on */ + if (data->pdata->gp2a_led_on + && !(data->power_state)) { + data->pdata->gp2a_led_on(true); + data->power_state = 1; + } + +#ifdef CONFIG_SENSORS_GP2A_VDD_CONTROL + /* gp2a vdd power on */ + if (data->pdata->gp2a_vdd_on + && !(data->power_state & LIGHT_ENABLED)) { + data->pdata->gp2a_vdd_on(true); + data->power_state |= LIGHT_ENABLED; + } +#endif + + /*msleep(1); */ +#ifdef GP2A_CALIBRATION + /* open cancelation data */ + err = proximity_open_calibration(data); + if (err < 0 && err != -ENOENT) + pr_err("%s: proximity_open_calibration() failed\n", + __func__); +#endif + data->enabled = 1; proximity_onoff(1); enable_irq_wake(data->irq); - msleep(160); input = gpio_get_value(data->pdata->p_out); input_report_abs(data->input_dev, ABS_DISTANCE, input); @@ -506,7 +339,6 @@ proximity_enable_store(struct device *dev, enable_irq(data->irq); } - data->enabled = value; return count; } @@ -515,8 +347,6 @@ static ssize_t proximity_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gp2a_data *data = dev_get_drvdata(dev); - static int count; /*count for proximity average */ - int D2_data = 0; unsigned char get_D2_data[2] = { 0, }; @@ -525,12 +355,7 @@ static ssize_t proximity_state_show(struct device *dev, mutex_unlock(&data->data_mutex); D2_data = (get_D2_data[1] << 8) | get_D2_data[0]; - data->average[count] = D2_data; - count++; - if (count == PROX_READ_NUM) - count = 0; - pr_debug("%s: D2_data = %d\n", __func__, D2_data); - return snprintf(buf, PAGE_SIZE, "%d\n", D2_data); + return sprintf(buf, "%d\n", D2_data); } static ssize_t proximity_avg_show(struct device *dev, @@ -559,7 +384,7 @@ static ssize_t proximity_avg_store(struct device *dev, } if (new_value && !proximity_avg_on) { - if (!(proximity_enable)) { + if (!(data->enabled)) { /*data->pdata->gp2a_led_on(true);*/ proximity_onoff(1); } @@ -573,7 +398,7 @@ static ssize_t proximity_avg_store(struct device *dev, hrtimer_cancel(&data->prox_timer); proximity_avg_on = 0; - if (!(proximity_enable)) { + if (!(data->enabled)) { proximity_onoff(0); /*data->pdata->gp2a_led_on(false);*/ } @@ -589,7 +414,7 @@ static ssize_t proximity_thresh_show(struct device *dev, struct device_attribute *attr, char *buf) { int i; - int threshold = 0; + u8 threshold = 0; u8 (*selected_image)[2] = (is_gp2a030a() ? gp2a_original_image_030a : gp2a_original_image); @@ -609,10 +434,11 @@ static ssize_t proximity_thresh_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - unsigned long threshold; + struct gp2a_data *data = dev_get_drvdata(dev); + u8 threshold = 0; int err = 0; - err = strict_strtoul(buf, 10, &threshold); + err = kstrtou8(buf, 10, &threshold); if (err) { pr_err("%s, conversion %s to number.\n", @@ -620,7 +446,7 @@ static ssize_t proximity_thresh_store(struct device *dev, return err; } - err = gp2a_update_threshold(is_gp2a030a() ? + err = gp2a_update_threshold(data, is_gp2a030a() ? gp2a_original_image_030a : gp2a_original_image, threshold, true); @@ -632,53 +458,262 @@ static ssize_t proximity_thresh_store(struct device *dev, return size; } +#ifdef GP2A_CALIBRATION +static u8 proximity_adc_read(struct gp2a_data *gp2a) +{ + int adc_arr[OFFSET_ARRAY_LENGTH]; + int total = 0, min = 0, max = 0; + u8 avg = 0; + int D2_data = 0; + unsigned char get_D2_data[2] = {0,}; + int i; + + for (i = 0; i < OFFSET_ARRAY_LENGTH; i++) { + mdelay(50); + mutex_lock(&gp2a->data_mutex); + opt_i2c_read(0x10, get_D2_data, sizeof(get_D2_data)); + mutex_unlock(&gp2a->data_mutex); + D2_data = (get_D2_data[1] << 8) | get_D2_data[0]; + adc_arr[i] = D2_data; + if (i == 0) { + min = adc_arr[i]; + max = adc_arr[i]; + } else { + if (adc_arr[i] < min) + min = adc_arr[i]; + else if (adc_arr[i] > max) + max = adc_arr[i]; + } + total += adc_arr[i]; + } + + total -= (min + max); + avg = (u8)(total / (OFFSET_ARRAY_LENGTH - 2)); + pr_info("%s: offset = %d\n", __func__, avg); + + return avg; +} + +static int proximity_open_calibration(struct gp2a_data *data) +{ + struct file *cancel_filp = NULL; + int err = 0; + mm_segment_t old_fs; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + cancel_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY, 0666); + if (IS_ERR(cancel_filp)) { + err = PTR_ERR(cancel_filp); + if (err != -ENOENT) + pr_err("%s: Can't open cancelation file\n", __func__); + set_fs(old_fs); + return err; + } + + err = cancel_filp->f_op->read(cancel_filp, + (char *)&data->cal_data, sizeof(u8), &cancel_filp->f_pos); + if (err != sizeof(u8)) { + pr_err("%s: Can't read the cancel data from file\n", __func__); + err = -EIO; + } + + if (data->cal_data != 0) {/*If there is an offset cal data. */ +#if defined(CONFIG_MACH_KONA_SENSOR) + if (is_gp2a030a()) { + gp2a_original_image_030a[5][1] = + data->default_threshold + data->cal_data; + gp2a_original_image_030a[3][1] = + data->default_threshold + + data->cal_data - DEFAULT_THRESHOLD_DIFF; + } +#else + if (is_gp2a030a()) + gp2a_original_image_030a[3][1] = + data->default_threshold + data->cal_data; + +#endif + else + gp2a_original_image[3][1] = + data->default_threshold + data->cal_data; + + pr_info("%s: prox_cal = %d, prox_thresh = 0x%x\n", + __func__, data->cal_data, (is_gp2a030a() ? + gp2a_original_image_030a[3][1] : + gp2a_original_image[3][1])); + } + + filp_close(cancel_filp, current->files); + set_fs(old_fs); + + return err; +} + +static int proximity_store_calibration(struct device *dev, bool do_calib) +{ + struct gp2a_data *gp2a = dev_get_drvdata(dev); + struct file *cancel_filp = NULL; + mm_segment_t old_fs; + int err = 0; + u8 thresh_x; + + if (do_calib) { + gp2a->cal_data = proximity_adc_read(gp2a); + if (is_gp2a030a()) { +#if defined(CONFIG_MACH_KONA_SENSOR) + gp2a_original_image_030a[3][1] = gp2a->cal_data+XTALK; + gp2a->cal_data = gp2a_original_image_030a[3][1]-THDL; +#else + /* if x-talk + 8 > threshold, threhold = x-talk + 8 */ + /* LTH = threshold - thresh_diff */ + thresh_x = gp2a->cal_data + 8 - gp2a->thresh_diff; + + if (thresh_x > gp2a_original_image_030a[3][1]) + gp2a_original_image_030a[3][1]= thresh_x; +#endif + } + else + gp2a_original_image[3][1] += gp2a->cal_data; + } else { /* reset */ + gp2a->cal_data = 0; + if (is_gp2a030a()) + gp2a_original_image_030a[3][1] = + gp2a->default_threshold; + else + gp2a_original_image[3][1] = gp2a->default_threshold; + } + + /* Update cal data. */ + gp2a_update_threshold(gp2a, is_gp2a030a() ? + gp2a_original_image_030a : gp2a_original_image, + (is_gp2a030a() ? + gp2a_original_image_030a[3][1] : + gp2a_original_image[3][1]), true); + + pr_info("%s: prox_cal = %d, prox_thresh = 0x%x\n", + __func__, gp2a->cal_data, (is_gp2a030a() ? + gp2a_original_image_030a[3][1] : + gp2a_original_image[3][1])); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + cancel_filp = filp_open(CALIBRATION_FILE_PATH, + O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, 0666); + if (IS_ERR(cancel_filp)) { + pr_err("%s: Can't open cancelation file\n", __func__); + set_fs(old_fs); + err = PTR_ERR(cancel_filp); + return err; + } + + err = cancel_filp->f_op->write(cancel_filp, + (char *)&gp2a->cal_data, sizeof(u8), &cancel_filp->f_pos); + if (err != sizeof(u8)) { + pr_err("%s: Can't write the cancel data to file\n", __func__); + err = -EIO; + } + + filp_close(cancel_filp, current->files); + set_fs(old_fs); + + return err; +} + static ssize_t proximity_cal_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct gp2a_data *data = dev_get_drvdata(dev); - int thresh_hi; - unsigned char get_D2_data[2]; - - msleep(20); - opt_i2c_read(PS_HT_LSB, get_D2_data, sizeof(get_D2_data)); - thresh_hi = (get_D2_data[1] << 8) | get_D2_data[0]; - data->threshold_high = thresh_hi; - return sprintf(buf, "%d,%d\n", - data->offset_value, data->threshold_high); +#if defined(CONFIG_MACH_KONA_SENSOR) + return sprintf(buf, "%d,%d\n", data->cal_data, + gp2a_original_image_030a[5][1]); +#else + return sprintf(buf, "%d,%d\n", data->cal_data, (is_gp2a030a() ? + gp2a_original_image_030a[5][1] : + gp2a_original_image[5][1])); +#endif } static ssize_t proximity_cal_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) + struct device_attribute *attr, + const char *buf, size_t size) { - struct gp2a_data *data = dev_get_drvdata(dev); bool do_calib; int err; - if (sysfs_streq(buf, "1")) { /* calibrate cancelation value */ + if (sysfs_streq(buf, "1")) /* calibrate cancelation value */ do_calib = true; - } else if (sysfs_streq(buf, "0")) { /* reset cancelation value */ + else if (sysfs_streq(buf, "0")) /* reset cancelation value */ do_calib = false; - } else { + else { pr_err("%s: invalid value %d\n", __func__, *buf); - err = -EINVAL; - goto done; + return -EINVAL; } - err = proximity_do_calibrate(data, do_calib, false); + + err = proximity_store_calibration(dev, do_calib); if (err < 0) { - pr_err("%s: proximity_store_offset() failed\n", __func__); - goto done; + pr_err("%s: proximity_store_calibration() failed\n", __func__); + return err; } -done: - return err; + + return size; } +static ssize_t proximity_thresh_diff_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gp2a_data *gp2a = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", gp2a->thresh_diff); +} + +static ssize_t proximity_thresh_diff_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct gp2a_data *gp2a = dev_get_drvdata(dev); + struct gp2a_platform_data *pdata = gp2a->pdata; + u8 threshold_diff = 0; + int err; + + err = kstrtou8(buf, 10, &threshold_diff); + if (err) { + pr_err("%s, conversion %s to number.\n", + __func__, buf); + return err; + } + + if ((threshold_diff > 0) && (threshold_diff < 5)) { /* update diff */ + gp2a->thresh_diff = threshold_diff; + } else if (threshold_diff == 0) { /* reset to default */ + pdata->gp2a_get_threshold(&gp2a->thresh_diff); + } else { + pr_err("%s: invalid value %d\n", __func__, *buf); + return -EINVAL; + } + + gp2a_update_threshold(gp2a, is_gp2a030a() ? + gp2a_original_image_030a : gp2a_original_image, + (is_gp2a030a() ? + gp2a_original_image_030a[3][1] : + gp2a_original_image[3][1]), true); + + return size; +} +#endif + static DEVICE_ATTR(enable, 0664, proximity_enable_show, proximity_enable_store); static DEVICE_ATTR(prox_avg, 0664, proximity_avg_show, proximity_avg_store); static DEVICE_ATTR(state, 0664, proximity_state_show, NULL); -static DEVICE_ATTR(prox_thresh, S_IRUGO | S_IWUSR, +static DEVICE_ATTR(prox_thresh, 0664, proximity_thresh_show, proximity_thresh_store); -static DEVICE_ATTR(prox_cal, 0664, proximity_cal_show, proximity_cal_store); +#ifdef GP2A_CALIBRATION +static DEVICE_ATTR(prox_cal, 0664, + proximity_cal_show, proximity_cal_store); +static DEVICE_ATTR(prox_diff, 0664, + proximity_thresh_diff_show, proximity_thresh_diff_store); +#endif static struct attribute *proximity_attributes[] = { &dev_attr_enable.attr, @@ -715,7 +750,6 @@ static ssize_t proximity_raw_data_show(struct device *dev, unsigned char get_D2_data[2] = { 0, }; struct gp2a_data *data = dev_get_drvdata(dev); - msleep(20); mutex_lock(&data->data_mutex); opt_i2c_read(0x10, get_D2_data, sizeof(get_D2_data)); mutex_unlock(&data->data_mutex); @@ -735,11 +769,10 @@ static void proxsensor_get_avgvalue(struct gp2a_data *data) u8 proximity_value = 0; unsigned char get_D2_data[2] = { 0, }; - mutex_lock(&data->data_mutex); - for (i = 0; i < PROX_READ_NUM; i++) { - msleep(20); + mutex_lock(&data->data_mutex); opt_i2c_read(0x10, get_D2_data, sizeof(get_D2_data)); + mutex_unlock(&data->data_mutex); proximity_value = (get_D2_data[1] << 8) | get_D2_data[0]; avg += proximity_value; @@ -751,7 +784,6 @@ static void proxsensor_get_avgvalue(struct gp2a_data *data) if (proximity_value > max) max = proximity_value; } - mutex_unlock(&data->data_mutex); avg /= PROX_READ_NUM; data->average[0] = min; @@ -901,7 +933,7 @@ static void gp2a_work_func_prox(struct work_struct *work) static int opt_i2c_init(void) { if (i2c_add_driver(&opt_i2c_driver)) { - printk(KERN_ERR "i2c_add_driver failed\n"); + pr_info("i2c_add_driver failed\n"); return -ENODEV; } return 0; @@ -911,16 +943,13 @@ int opt_i2c_read(u8 reg, unsigned char *rbuf, int len) { int ret = -1; struct i2c_msg msg; - /*int i;*/ if ((opt_i2c_client == NULL) || (!opt_i2c_client->adapter)) { - printk(KERN_ERR "%s %d (opt_i2c_client == NULL)\n", + pr_err("%s %d (opt_i2c_client == NULL)\n", __func__, __LINE__); return -ENODEV; } - /*gprintk("register num : 0x%x\n", reg); */ - msg.addr = opt_i2c_client->addr; msg.flags = I2C_M_WR; msg.len = 1; @@ -936,12 +965,9 @@ int opt_i2c_read(u8 reg, unsigned char *rbuf, int len) } if (ret < 0) - printk(KERN_ERR "%s, i2c transfer error ret=%d\n"\ + pr_err("%s, i2c transfer error ret=%d\n"\ , __func__, ret); - /* for (i=0;i= 0) return 0; } - printk(KERN_ERR "%s, i2c transfer error(%d)\n", __func__, err); + pr_err("%s, i2c transfer error(%d)\n", __func__, err); return err; } @@ -982,7 +1008,7 @@ static int proximity_input_init(struct gp2a_data *data) data->input_dev = input_allocate_device(); if (!data->input_dev) { - printk(KERN_ERR "%s, error\n", __func__); + pr_err("%s, error\n", __func__); return -ENOMEM; } @@ -1021,14 +1047,9 @@ static int gp2a_opt_probe(struct platform_device *pdev) return err; } /* gp2a power on */ +#if !defined(CONFIG_MACH_TAB3) || !defined(CONFIG_MACH_GC2PD) pdata->gp2a_led_on(true); - - if (pdata->gp2a_get_threshold) { - gp2a_update_threshold(is_gp2a030a() ? - gp2a_original_image_030a : gp2a_original_image, - pdata->gp2a_get_threshold(), false); - } - +#endif /* allocate driver_data */ gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL); if (!gp2a) { @@ -1036,10 +1057,35 @@ static int gp2a_opt_probe(struct platform_device *pdev) return -ENOMEM; } - proximity_enable = 0; +#ifdef CONFIG_SLP + gp2a->thresh_diff = DEFAULT_THRESHOLD_DIFF; +#endif +#if defined(CONFIG_MACH_KONA_SENSOR) + gp2a->thresh_diff = DEFAULT_THRESHOLD_DIFF; +#else + if (pdata->gp2a_get_threshold) + gp2a_update_threshold(gp2a, is_gp2a030a() ? + gp2a_original_image_030a : gp2a_original_image, + pdata->gp2a_get_threshold(&gp2a->thresh_diff), false); + else + gp2a->thresh_diff = DEFAULT_THRESHOLD_DIFF; +#endif +#ifdef GP2A_CALIBRATION +#if defined(CONFIG_MACH_KONA_SENSOR) + gp2a->default_threshold = (is_gp2a030a() ? + gp2a_original_image_030a[5][1] : + gp2a_original_image[5][1]); +#else + gp2a->default_threshold = (is_gp2a030a() ? + gp2a_original_image_030a[3][1] : + gp2a_original_image[3][1]); +#endif +#endif + + gp2a->enabled = 0; + proximity_sensor_detection = 0; proximity_avg_on = 0; - gp2a->enabled = 0; gp2a->pdata = pdata; /* prox_timer settings. we poll for prox_avg values using a timer. */ @@ -1082,9 +1128,19 @@ static int gp2a_opt_probe(struct platform_device *pdev) pr_err("opt_probe failed : i2c_client is NULL\n"); goto err_no_device; } else - printk(KERN_INFO "opt_i2c_client : (0x%p), address = %x\n", + pr_info("opt_i2c_client : (0x%p), address = %x\n", opt_i2c_client, opt_i2c_client->addr); +#ifdef CONFIG_SENSORS_GP2A_VDD_CONTROL + /* gp2a power on */ + if (pdata->gp2a_vdd_on) { + pdata->gp2a_vdd_on(true); + pr_info("%s, power : %d\n", __func__, gp2a-->power_state); + } + gp2a->power_state |= LIGHT_ENABLED; + msleep(20); +#endif + /* GP2A Regs INIT SETTINGS and Check I2C communication */ value = 0x00; /* shutdown mode op[3]=0 */ @@ -1148,12 +1204,20 @@ static int gp2a_opt_probe(struct platform_device *pdev) goto err_proximity_device_create_file6; } +#ifdef GP2A_CALIBRATION if (device_create_file(gp2a->proximity_dev, &dev_attr_prox_cal) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_prox_cal.attr.name); goto err_proximity_device_create_file7; } + if (device_create_file(gp2a->proximity_dev, &dev_attr_prox_diff) < 0) { + pr_err("%s: could not create device file(%s)!\n", __func__, + dev_attr_prox_diff.attr.name); + goto err_proximity_device_create_file8; + } +#endif + #ifdef CONFIG_SLP device_init_wakeup(gp2a->proximity_dev, true); #endif @@ -1165,14 +1229,18 @@ static int gp2a_opt_probe(struct platform_device *pdev) return 0; -err_proximity_device_create_file7: +#ifdef GP2A_CALIBRATION +err_proximity_device_create_file8: device_remove_file(gp2a->proximity_dev, &dev_attr_prox_cal); -err_proximity_device_create_file6: +err_proximity_device_create_file7: device_remove_file(gp2a->proximity_dev, &dev_attr_raw_data); -err_proximity_device_create_file5: +#endif +err_proximity_device_create_file6: device_remove_file(gp2a->proximity_dev, &dev_attr_name); -err_proximity_device_create_file4: +err_proximity_device_create_file5: device_remove_file(gp2a->proximity_dev, &dev_attr_vendor); +err_proximity_device_create_file4: + device_remove_file(gp2a->proximity_dev, &dev_attr_prox_thresh); err_proximity_device_create_file3: device_remove_file(gp2a->proximity_dev, &dev_attr_prox_avg); err_proximity_device_create_file2: @@ -1201,19 +1269,20 @@ static int gp2a_opt_remove(struct platform_device *pdev) struct gp2a_data *gp2a = platform_get_drvdata(pdev); if (gp2a == NULL) { - printk(KERN_ERR "%s, gp2a_data is NULL!!!!!\n", __func__); + pr_err("%s, gp2a_data is NULL!!!!!\n", __func__); return -1; } if (gp2a->enabled) { disable_irq(gp2a->irq); - proximity_enable = 0; + gp2a->enabled = 0; + proximity_onoff(0); disable_irq_wake(gp2a->irq); -#ifndef CONFIG_MACH_MIDAS_02_BD +#if !defined(CONFIG_MACH_MIDAS_02_BD) gp2a->pdata->gp2a_led_on(false); + gp2a->power_state = 0; #endif - gp2a->enabled = 0; } hrtimer_cancel(&gp2a->prox_timer); @@ -1228,6 +1297,10 @@ static int gp2a_opt_remove(struct platform_device *pdev) device_remove_file(gp2a->proximity_dev, &dev_attr_vendor); device_remove_file(gp2a->proximity_dev, &dev_attr_name); device_remove_file(gp2a->proximity_dev, &dev_attr_raw_data); +#ifdef GP2A_CALIBRATION + device_remove_file(gp2a->proximity_dev, &dev_attr_prox_cal); + device_remove_file(gp2a->proximity_dev, &dev_attr_prox_diff); +#endif sensors_classdev_unregister(gp2a->proximity_dev); if (gp2a->input_dev != NULL) { @@ -1274,6 +1347,7 @@ static int gp2a_opt_resume(struct platform_device *pdev) gprintk("\n"); if (gp2a->enabled) { + if (device_may_wakeup(&pdev->dev)) enable_irq_wake(gp2a->irq); } @@ -1308,8 +1382,7 @@ static int proximity_onoff(u8 onoff) opt_i2c_write(gp2a_original_image[i][0], &gp2a_original_image[i][1]); if (err < 0) - printk(KERN_ERR - "%s : turnning on error i = %d, err=%d\n", + pr_err("%s : turnning on error i = %d, err=%d\n", __func__, i, err); lightsensor_mode = 0; } @@ -1342,7 +1415,7 @@ static int opt_i2c_probe(struct i2c_client *client, gprintk("start!!!\n"); if (client == NULL) - printk(KERN_ERR "GP2A i2c client is NULL !!!\n"); + pr_err("GP2A i2c client is NULL !!!\n"); opt_i2c_client = client; gprintk("end!!!\n"); -- cgit v1.1 From 219edf3a61a7f71809d837033735d2bfa7f0d6da Mon Sep 17 00:00:00 2001 From: sbrissen Date: Tue, 4 Feb 2014 14:56:00 -0500 Subject: smdk4412: initial support for n5120 Change-Id: I21144c9f3146c9043b137f180c064627ebeed71e --- drivers/tty/serial/samsung.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index a3b31b8..5018800 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -483,10 +483,14 @@ static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) } else { umcon &= ~S3C2410_UMCOM_AFC; } - - } else if (port->line == CONFIG_GPS_S3C_UART) { + } +#if !defined(CONFIG_MACH_KONA_EUR_LTE) && !defined(CONFIG_MACH_KONALTE_USA_ATT) + else if (port->line == CONFIG_GPS_S3C_UART) { umcon |= S3C2410_UMCOM_AFC; - } else { + } +#endif + else { + umcon &= ~S3C2410_UMCOM_AFC; } -- cgit v1.1 From b1c5069196635586f0cc98cf3eca277c08b282f6 Mon Sep 17 00:00:00 2001 From: sbrissen Date: Fri, 7 Feb 2014 22:32:21 -0500 Subject: smdk4412: update fimc_capture and sr130pc20 cam driver -updates are from i605 4.3 kernel source -updates + small hack fixes front cam on kona Change-Id: If8348be6dbef50bb322a60d554d177e046eec429 --- drivers/media/video/samsung/fimc/fimc.h | 1 + drivers/media/video/samsung/fimc/fimc_capture.c | 55 +- drivers/media/video/sr130pc20.c | 45 +- drivers/media/video/sr130pc20.h | 9 + drivers/media/video/sr130pc20_regs_kona.h | 4229 +++++++++++++++++++++++ 5 files changed, 4305 insertions(+), 34 deletions(-) create mode 100644 drivers/media/video/sr130pc20_regs_kona.h (limited to 'drivers') diff --git a/drivers/media/video/samsung/fimc/fimc.h b/drivers/media/video/samsung/fimc/fimc.h index b648965..228a1c4 100644 --- a/drivers/media/video/samsung/fimc/fimc.h +++ b/drivers/media/video/samsung/fimc/fimc.h @@ -469,6 +469,7 @@ struct fimc_control { struct mutex lock; /* controller lock */ struct mutex v4l2_lock; spinlock_t outq_lock; + spinlock_t inq_lock; wait_queue_head_t wq; struct device *dev; #if defined(CONFIG_BUSFREQ_OPP) || defined(CONFIG_BUSFREQ_LOCK_WRAPPER) diff --git a/drivers/media/video/samsung/fimc/fimc_capture.c b/drivers/media/video/samsung/fimc/fimc_capture.c index e438205..f76345c 100644 --- a/drivers/media/video/samsung/fimc/fimc_capture.c +++ b/drivers/media/video/samsung/fimc/fimc_capture.c @@ -32,6 +32,10 @@ #include "fimc.h" +#ifdef CONFIG_MACH_KONA +extern fimc_is; +#endif + static struct pm_qos_request_list bus_qos_pm_qos_req; static const struct v4l2_fmtdesc capture_fmts[] = { @@ -816,6 +820,7 @@ static int fimc_configure_subdev(struct fimc_control *ctrl) if (!sd) { fimc_err("%s: v4l2 subdev board registering failed\n", __func__); + return -ENODEV; } /* Assign subdev to proper camera device pointer */ ctrl->cam->sd = sd; @@ -1435,7 +1440,7 @@ int fimc_s_fmt_vid_private(struct file *file, void *fh, struct v4l2_format *f) mbus_fmt = &ctrl->cap->mbus_fmt; mbus_fmt->width = pix->width; mbus_fmt->height = pix->height; -#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA) +#if defined(CONFIG_MACH_P4NOTE) /* Unfortuntely, we have to use pix->field (not pix->priv) since * pix.field is already used in the below else condtion statement * (in case that sub-devices are not registered) @@ -1445,6 +1450,11 @@ int fimc_s_fmt_vid_private(struct file *file, void *fh, struct v4l2_format *f) #if defined(CONFIG_MACH_GC1) mbus_fmt->field = pix->priv; #endif + +#if defined(CONFIG_MACH_KONA) + if(!fimc_is) + mbus_fmt->field = pix->field; +#endif printk(KERN_INFO "%s mbus_fmt->width = %d, height = %d,\n", __func__,mbus_fmt->width ,mbus_fmt->height); @@ -2146,6 +2156,7 @@ int fimc_querybuf_capture(void *fh, struct v4l2_buffer *b) int fimc_g_ctrl_capture(void *fh, struct v4l2_control *c) { struct fimc_control *ctrl = fh; + struct v4l2_frmsizeenum cam_frmsize; int ret = 0; fimc_dbg("%s\n", __func__); @@ -2167,6 +2178,24 @@ int fimc_g_ctrl_capture(void *fh, struct v4l2_control *c) c->value = ctrl->cap->cacheable; break; + case V4L2_CID_CAMERA_SENSOR_OUTPUT_SIZE: + cam_frmsize.index = -1; + cam_frmsize.discrete.width = 0; + cam_frmsize.discrete.height = 0; + + ret = v4l2_subdev_call(ctrl->cam->sd, video, enum_framesizes, + &cam_frmsize); + if (ret < 0) { + dev_err(ctrl->dev, "%s: enum_framesizes failed\n", + __func__); + if (ret != -ENOIOCTLCMD) + return ret; + } else { + c->value = (cam_frmsize.discrete.width << 16)|(cam_frmsize.discrete.height&0xFFFF); + dev_err(ctrl->dev,"sensor_output (%d, %d)\n", cam_frmsize.discrete.width, cam_frmsize.discrete.height); + } + break; + default: /* get ctrl supported by subdev */ /* WriteBack doesn't have subdev_call */ @@ -2933,9 +2962,20 @@ int fimc_streamon_capture(void *fh) fimc_start_capture(ctrl); ctrl->status = FIMC_STREAMON; - if (ctrl->is.sd && fimc_cam_use) + if (ctrl->is.sd && fimc_cam_use) { ret = v4l2_subdev_call(ctrl->is.sd, video, s_stream, 1); - printk(KERN_INFO "%s-- fimc%d\n", __func__, ctrl->id); + if (ret < 0) { + dev_err(ctrl->dev, "%s: s_stream failed\n", + __func__); + if (cam->type == CAM_TYPE_MIPI) { + if (cam->id == CAMERA_CSI_C) + s3c_csis_stop(CSI_CH_0); + else + s3c_csis_stop(CSI_CH_1); + } + return ret; + } + } /* if available buffer did not remained */ return 0; @@ -3138,17 +3178,16 @@ int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b) int available_bufnum; size_t length = 0; int i; + unsigned long spin_flags; if (!cap || !ctrl->cam) { fimc_err("%s: No capture device.\n", __func__); return -ENODEV; } - mutex_lock(&ctrl->v4l2_lock); if (pdata->hw_ver >= 0x51) { if (cap->bufs[idx].state != VIDEOBUF_IDLE) { fimc_err("%s: invalid state idx : %d\n", __func__, idx); - mutex_unlock(&ctrl->v4l2_lock); return -EINVAL; } else { if (b->memory == V4L2_MEMORY_USERPTR) { @@ -3170,7 +3209,6 @@ int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b) if (ret < 0) { fimc_err("%s: _qbuf_dmabuf error.\n", __func__); - mutex_unlock(&ctrl->v4l2_lock); return -ENODEV; } for (i = 0; i < vb->num_planes; i++) { @@ -3184,7 +3222,6 @@ int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b) } else { fimc_err("%s: Wrong sg value.\n", __func__); - mutex_unlock(&ctrl->v4l2_lock); return -ENODEV; } } @@ -3206,6 +3243,7 @@ int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b) #endif } + spin_lock_irqsave(&ctrl->inq_lock, spin_flags); fimc_hwset_output_buf_sequence(ctrl, idx, FIMC_FRAMECNT_SEQ_ENABLE); cap->bufs[idx].state = VIDEOBUF_QUEUED; if (ctrl->status == FIMC_BUFFER_STOP) { @@ -3220,13 +3258,12 @@ int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b) ctrl->restart = true; } } + spin_unlock_irqrestore(&ctrl->inq_lock, spin_flags); } } else { fimc_add_inqueue(ctrl, b->index); } - mutex_unlock(&ctrl->v4l2_lock); - if (!cap->cacheable) return 0; diff --git a/drivers/media/video/sr130pc20.c b/drivers/media/video/sr130pc20.c index ab2b8d5..8dbc83f 100644 --- a/drivers/media/video/sr130pc20.c +++ b/drivers/media/video/sr130pc20.c @@ -32,6 +32,9 @@ #define sr130pc20_writew(sd, addr, data) i2c_write_nop() #define sr130pc20_writel(sd, addr, data) i2c_write_nop() +int fimc_is; +EXPORT(fimc_is); + static int dbg_level; static const struct sr130pc20_fps sr130pc20_framerates[] = { @@ -1284,10 +1287,11 @@ static int sr130pc20_s_mbus_fmt(struct v4l2_subdev *sd, __func__, fmt->code, fmt->colorspace, fmt->width, fmt->height); v4l2_fill_pix_format(&state->req_fmt, fmt); - if (fmt->field < IS_MODE_CAPTURE_STILL) - state->format_mode = V4L2_PIX_FMT_MODE_PREVIEW; - else + if ((IS_MODE_CAPTURE_STILL == fmt->field) + && (SENSOR_CAMERA == state->sensor_mode)) state->format_mode = V4L2_PIX_FMT_MODE_CAPTURE; + else + state->format_mode = V4L2_PIX_FMT_MODE_PREVIEW; if (state->format_mode != V4L2_PIX_FMT_MODE_CAPTURE) { previous_index = state->preview.frmsize ? @@ -1407,10 +1411,14 @@ static int sr130pc20_s_parm(struct v4l2_subdev *sd, cam_dbg("s_parm state->fps=%d, state->req_fps=%d\n", state->fps, state->req_fps); - if ((state->req_fps < 0) || (state->req_fps > 30)) { - cam_err("%s: error, invalid frame rate %d. we'll set to 30\n", + if (state->req_fps < 0) { + cam_err("%s: error, invalid frame rate %d. we'll set to 0\n", __func__, state->req_fps); state->req_fps = 0; + } else if (state->req_fps > 25) { + cam_err("%s: error, invalid frame rate %d. we'll set to 25\n", + __func__, state->req_fps); + state->req_fps = 25; } return sr130pc20_set_frame_rate(sd, state->req_fps); @@ -1626,7 +1634,10 @@ static int sr130pc20_s_stream(struct v4l2_subdev *sd, int enable) cam_info("stream mode = %d\n", enable); - BUG_ON(!state->initialized); + if (unlikely(!state->initialized)) { + WARN(1, "s_stream, not initialized\n"); + return -EPERM; + } switch (enable) { case STREAM_MODE_CAM_OFF: @@ -1635,23 +1646,12 @@ static int sr130pc20_s_stream(struct v4l2_subdev *sd, int enable) break; case STREAM_MODE_CAM_ON: - switch (state->sensor_mode) { - case SENSOR_CAMERA: if (state->format_mode == V4L2_PIX_FMT_MODE_CAPTURE) err = sr130pc20_start_capture(sd); else err = sr130pc20_start_preview(sd); break; - case SENSOR_MOVIE: - err = sr130pc20_start_preview(sd); - break; - - default: - break; - } - break; - case STREAM_MODE_MOVIE_OFF: cam_info("movie off"); state->recording = 0; @@ -1674,14 +1674,6 @@ static int sr130pc20_s_stream(struct v4l2_subdev *sd, int enable) static inline int sr130pc20_check_i2c(struct v4l2_subdev *sd, u16 data) { - int err; - u32 val = 0; - - err = sr130pc20_readw(sd, 0x0000, &val); - if (unlikely(err)) - return err; - - cam_dbg("version: 0x%04X is 0x6017?\n", val); return 0; } @@ -1727,6 +1719,7 @@ static int sr130pc20_init(struct v4l2_subdev *sd, u32 val) CHECK_ERR_MSG(err, "failed to initialize camera device\n"); sr130pc20_init_parameter(sd); state->initialized = 1; + fimc_is = 1; return 0; } @@ -1775,6 +1768,7 @@ static int sr130pc20_s_config(struct v4l2_subdev *sd, state->format_mode = V4L2_PIX_FMT_MODE_PREVIEW; state->fps = 0; state->req_fps = -1; + state->write_fps = 0; /* Initialize the independant HW module like flash here */ state->flash.mode = FLASH_MODE_OFF; @@ -1880,6 +1874,7 @@ static int sr130pc20_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); mutex_destroy(&state->ctrl_lock); kfree(state); + fimc_is = 0; printk(KERN_DEBUG "%s %s: driver removed!!\n", dev_driver_string(&client->dev), dev_name(&client->dev)); diff --git a/drivers/media/video/sr130pc20.h b/drivers/media/video/sr130pc20.h index a831007..25a5949 100755 --- a/drivers/media/video/sr130pc20.h +++ b/drivers/media/video/sr130pc20.h @@ -547,6 +547,7 @@ struct sr130pc20_state { s32 vt_mode; s32 req_fps; s32 fps; + s32 write_fps; s32 freq; /* MCLK in Hz */ u32 one_frame_delay_ms; u32 light_level; /* light level */ @@ -638,9 +639,17 @@ extern int sr130pc20_create_file(struct class *cls); #include #include +#ifdef CONFIG_MACH_KONA +#define TUNING_FILE_PATH "/mnt/sdcard/sr130pc20_regs_kona.h" +#else #define TUNING_FILE_PATH "/mnt/sdcard/sr130pc20_regs.h" +#endif /* CONFIG_MACH_KONA */ #endif /* CONFIG_LOAD_FILE*/ +#ifdef CONFIG_MACH_KONA +#include "sr130pc20_regs_kona.h" +#else #include "sr130pc20_regs.h" +#endif #endif /* __SR130PC20_H__ */ diff --git a/drivers/media/video/sr130pc20_regs_kona.h b/drivers/media/video/sr130pc20_regs_kona.h new file mode 100644 index 0000000..ebc578b --- /dev/null +++ b/drivers/media/video/sr130pc20_regs_kona.h @@ -0,0 +1,4229 @@ +/* sr130pc20_regs.h + * + * Driver for s5k5ccgx (5MP Camera) from siliconfile + * + * Copyright (C) 2010, SAMSUNG ELECTRONICS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Change Date: 2012.06.28 + */ + +#ifndef __SR130PC20_REGS_H__ +#define __SR130PC20_REGS_H__ + +/* PV 1st */ + +static const sr130pc20_regset_t SR130PC20_Init_Reg[] = { + +/*0 Page*/ +0x0300, +0x0101, /*sleep*/ +0x0103, /*s/w reset*/ +0x0101, /*sleep*/ + +0x0800,/*Don't touch*/ +0x0937,/*Don't touch*/ +0x0a33,/*Don't touch*/ + +/*PLL Setting*/ +0xd005, +0xd130, +0xd201, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x1011, +0x1190, /*xy flip*/ +0x1200, +0x1488, + +0x0300, +0x2000, +0x2104, +0x2200, +0x2304, +0x2403, +0x25C0, +0x2605, +0x2700, + +0x4001, /*Hblank_280*/ +0x4118, +0x4200, /*Vblank 100*/ +0x4364, + +/*--------------- BLC*/ +0x8008, /*Don't touch */ +0x8197, /*Don't touch */ +0x8290, /*Don't touch */ +0x8330, /*Don't touch */ +0x84cc, /*Don't touch*/ +0x8500, /*Don't touch*/ +0x86d4, /*Don' t touch*/ +0x870f, /*Don't touch*/ +0x8834, /*Don't touch*/ + +0x900c, /*BLC_TIME_TH_ON*/ +0x910c, /*BLC_TIME_TH_OFF */ +0x92f0, /*BLC_AG_TH_ON*/ +0x93e8, /*BLC_AG_TH_OFF*/ + +0x9495, /*091202*/ +0x9590, /*091202 */ +0x9838, /*Don't touch*/ + +/*Dark BLC*/ +0xa001, /* 20100309*/ +0xa201, /* 20100309*/ +0xa401, /* 20100309*/ +0xa601, /* 20100309*/ + +/*Normal BLC*/ +0xa800, +0xaa00, +0xac00, +0xae00, + +/*Out BLC*/ +0x9900, +0x9a00, +0x9b00, +0x9c00, + +/*2 Page*/ +0x0302, +0x1200, /*Don't touch*/ +0x1400, /*Don't touch*/ +0x1500, /*Don't touch*/ +0x184C, /*Don't touch*/ +0x1900, /*Don't touch*/ +0x1A39, /*Don't touch*/ +0x1B00,/*Don't touch*/ +0x1C1a, /*Don't touch*/ +0x1D14, /*Don't touch*/ +0x1E30,/*Don't touch*/ +0x1F10,/*Don't touch*/ + +0x2077, +0x21de, +0x22a7, +0x2330, +0x2477, +0x2510, +0x2610, +0x273c, +0x2b80, +0x2c02, +0x2da0, +0x2e00, +0x2fa7, + +0x3000, +0x3199, +0x3200, +0x3300, +0x3422, +0x3601, +0x3701, +0x3888, +0x3988, +0x3d03, +0x3e0d, +0x3f02, + +0x49d1, +0x4a14, + +0x5021, +0x5201, +0x5381, +0x5410, +0x551c, +0x5611, +0x5818, +0x5916, +0x5da2, +0x5e5a, + +0x6093, /* 20120517 modify*/ +0x61a4, /* 20120517 modify*/ +0x6294, /* 20120517 modify*/ +0x63a3, /* 20120517 modify*/ +0x6494, /* 20120517 modify*/ +0x65a3, /* 20120517 modify*/ +0x670c, +0x680c, +0x690c, +0x6ab4, +0x6bc4, +0x6cb5, +0x6dc2, +0x6eb5, +0x6fc0, + +0x70b6, +0x71b8, +0x7295, /* 20120517 modify*/ +0x73a2, /* 20120517 modify*/ +0x7495, /* 20120517 modify*/ +0x75a2, /* 20120517 modify*/ +0x7695, /* 20120517 modify*/ +0x77a2, /* 20120517 modify*/ +0x7C92, /* 20120517 modify*/ +0x7Dff, /* 20120517 modify*/ + +0x8001, /* 20120517 modify*/ +0x818a, /* 20120517 modify*/ +0x821e, /* 20120517 modify*/ +0x8336, /* 20120517 modify*/ +0x8489, /* 20120517 modify*/ +0x858b, /* 20120517 modify*/ +0x8689, /* 20120517 modify*/ +0x878b, /* 20120517 modify*/ +0x88ab, +0x89bc, +0x8aac, +0x8bba, +0x8cad, +0x8db8, +0x8eae, +0x8fb2, + +0x90b3, +0x91b7, +0x9252, /* 20120517 modify*/ +0x936a, /* 20120517 modify*/ +0x9489, /* 20120517 modify*/ +0x958b, /* 20120517 modify*/ +0x9689, /* 20120517 modify*/ +0x978b, /* 20120517 modify*/ + +0xA002, +0xA186, /* 20120517 modify*/ +0xA202, +0xA386, /* 20120517 modify*/ +0xA486, /* 20120517 modify*/ +0xA502, +0xA686, /* 20120517 modify*/ +0xA702, +0xA892, /* 20120517 modify*/ +0xA994, /* 20120517 modify*/ +0xAA92, /* 20120517 modify*/ +0xAB94, /* 20120517 modify*/ +0xAC1c, +0xAD22, +0xAE1c, +0xAF22, + +0xB0a4, /* 20120517 modify*/ +0xB1ae, /* 20120517 modify*/ +0xB2a4, /* 20120517 modify*/ +0xB3ae, /* 20120517 modify*/ +0xB4a6, /* 20120517 modify*/ +0xB5ac, /* 20120517 modify*/ +0xB6a6, /* 20120517 modify*/ +0xB7ac, /* 20120517 modify*/ +0xB8a6, /* 20120517 modify*/ +0xB9ab, /* 20120517 modify*/ +0xBAa6, /* 20120517 modify*/ +0xBBab, /* 20120517 modify*/ +0xBCa6, /* 20120517 modify*/ +0xBDab, /* 20120517 modify*/ +0xBEa6, /* 20120517 modify*/ +0xBFab, /* 20120517 modify*/ + +0xc437, +0xc552, +0xc66b, +0xc786, +0xc838, /* 20120517 modify*/ +0xc950, /* 20120517 modify*/ +0xca38, /* 20120517 modify*/ +0xcb50, /* 20120517 modify*/ +0xcc6c, /* 20120517 modify*/ +0xcd84, /* 20120517 modify*/ +0xce6c, /* 20120517 modify*/ +0xcf84, /* 20120517 modify*/ + +/*0xd4a6,*/ +/*0xd5ac,*/ +/*0xd6a6,*/ +/*0xd7ac,*/ +/*add 20120517*/ +0xdc00, /* Added*/ +0xddaf, /* Added*/ +0xde00, /* Added*/ +0xdf90, /* Added*/ + +0xd010, +0xd114, +0xd220, +0xd300, +/*DCDC */ +0xd40c, /*DCDC_TIME_TH_ON*/ +0xd50c, /*DCDC_TIME_TH_OFF */ +0xd6f0, /*DCDC_AG_TH_ON*/ +0xd7e8, /*DCDC_AG_TH_OFF*/ + +0xea8a, + +0xF001, /* clock inversion*/ +0xF101, +0xF201, +0xF301, +0xF401, +0xF500, + +/*----------------------------------------------*/ +0x0310, /*page 10*/ +0x1001, /*Ycbcr422_bit Order: YUYV*/ +0x1103, +0x1230, /*y offset[4], dif_offset[5]*/ +0x1302, /*contrast effet enable : 0x02*/ +0x3400, /*hidden 10->00 100209*/ +0x3701, /*yc2d power save */ +0x3f04, /*100825*/ +0x4080, /*Y offset */ +0x4880, +0x5300, /*dif_offset option */ +0x5530, /*dif_offset option diff_offset max */ + +0x604f, /*out color sat en[7] | auto color decrement en[1] / + | manual color sat en[0]*/ + +0x6183, /*blue saturation_C0*/ +0x6280, /*red saturation_B0*/ + +0x63ff, /*auto decresment on AG th*/ +0x64c0, /*auto decresment on DG th*/ +0x66e4, /*Outdoor saturation step 137fps apply out th */ +0x6703, /*Outdoor saturation B/R*/ +0x7601, /* ADD 20121031 */ +0x7904, /* ADD 20121031 */ + +/* Hi 163 */ +/* PAGE 10 START*/ +0x0310, +0x8000, /* dsshin --> color enhance*/ +0xf500, /* dsshin --> h blank option*/ + +0x0311, /*page 11 D_LPF */ +0x103f, /*B[6]:Blue En Dlpf on[4:0] Sky over off : 0x7f->3f*/ +0x1120, /* Uniform Full GbGr/OV-Nr*/ + +0x1280, /*Blue MaxOpt blue sky max filter optoin rate : 0 0xc0->80*/ +0x13b8, /*dark2[7] | ratio[6:4] | dark3[3] | dark3 maxfilter ratio[2:0] */ + +0x30ba, /*Outdoor2 H th*/ +0x3110, /*Outdoor2 L th*/ +0x3250, /*Outdoor2 gain ratio*/ +0x331d, /*Outdoor2 H lum*/ +0x3420, /*Outdoor2 M lum*/ +0x351f, /*Outdoor2 L lum*/ + +0x36b0, /*Outdoor1 H th*/ +0x3718, /*Outdoor1 L th*/ +0x3850, /*Outdoor1 gain ratio 0x80->40*/ +0x391d, /*Outdoor1 H lum 0x28->1e*/ +0x3a20, /*Outdoor1 M lum 0x10->15*/ +0x3b1f, /*Outdoor1 L lum 0x08->20*/ + +0x3c3f, /*indoor H th*/ +0x3d16, /*indoor L th*/ +0x3e30, /*indoor gain ratio 0x44 6a */ +0x3f1a, /*indoor H lum 0x12 18 */ +0x4060, /*indoor M lum 0x18 1c*/ +0x411a, /*indoor L lum 0x18 3e*/ + +0x4298, /*dark1 H th*/ +0x4328, /*dark1 L th*/ +0x4465, /*dark1 gain ratio*/ +0x4516, /*dark1 H lum 0x38->0x28 */ +0x4630, /*dark1 M lum 0x27->0x17*/ +0x4734, /*dark1 L lum 0x20->0x1a */ + +0x4890, /*dark2 H th*/ +0x492a, /*dark2 L th*/ +0x4a65, /*dark2 gain ratio*/ +0x4b18, /*dark2 H lum */ +0x4c31, /*dark2 M lum*/ +0x4d36, /*dark2 L lum */ + +0x4e80, /*dark3 H th*/ +0x4f30, /*dark3 L th*/ +0x5065, /*dark3 gain ratio*/ +0x5119, /*dark3 H lum */ +0x5231, /*dark3 M lum */ +0x5336, /*dark3 L lum */ + +0x5a3f, /*blue sky mode out1/2 enable 0x27->3f */ +0x5b00, /*Impulse pixel enable dark123,in,out123 :: must be 0x07*/ +0x5c9f, /*Indoor maxfilter rate[7:5] | Uncertain onoff[4:0] 0x1f ->0x9f*/ + +0x603f, /*GbGr all enable*/ +0x620f, /*GbGr offset*/ + +0x650c, /*Outdoor GbGr rate H 100% M 25% L 100%*/ +0x660c, /*Indoor GbGr rate H 100% M 25% L 100%*/ +0x6700, /*dark GbGr rate H/M/L 100%*/ + +0x700c, /* Abberation On/Off B[1]: Outdoor B[0]: Indoor 07>>c*/ +0x75a0, /* Outdoor2 Abberation Luminance lvl */ +0x7db4, /* Indoor Abberation Luminance lvl*/ + +0x9608, /*indoor/Dark1 edgeoffset1*/ +0x9714, /*indoor/Dark1 center G value*/ +0x98f5, /*slope indoor :: left/right graph polarity, slope*/ +0x992a, /*indoor uncertain ratio control*/ +0x9a20, /*Edgeoffset_dark*/ + +/*DPC_CTRL*/ +0x0312, /*Preview DPC off[0x5c] on[0x5d]*/ +0x200f, +0x210f, + +0x2500, /* 0x30*/ + +0x2a01, +0x2e00, /*2010.8.25*/ + +0x3035, /*Texture region(most detail)*/ +0x31a0, /*STD uniform1 most blur region*/ +0x32b0, /*STD uniform2 2nd blur*/ +0x33c0, /*STD uniform3 3rd blur*/ +0x34d0, /*STD normal noise1 4th blur */ +0x35e0, /*STD normal noise2 5th blur*/ +0x36ff, /*STD normal noise3 6th blur*/ + +0x4083, /*Outdoor2 H th*/ +0x4120, /*Outdoor2 L th */ +0x4208, /*Outdoor2 H luminance */ +0x4310, /*Outdoor2 M luminance */ +0x4410, /*Outdoor2 l luminance */ +0x4550, /*Outdoor2 ratio*/ + +0x4683, /*Outdoor1 H th*/ +0x4720, /*Outdoor1 L th */ +0x4808, /*Outdoor1 H luminance*/ +0x4910, /*Outdoor1 M luminance*/ +0x4a10, /*Outdoor1 L luminance*/ +0x4b50, /*Outdoor1 ratio*/ + +0x4c80, /*Indoor H th*/ +0x4d48, /*Indoor L th*/ +0x4e30, /*indoor H lum*/ +0x4f30, /*indoor M lum*/ +0x5012, /*indoor L lum */ +0x5170, /*indoor ratio 0x10 -> 0x45*/ + +0x52a8, /*dark1 H th*/ +0x5330, /*dark1 L th */ +0x5428, /*dark1 H lum */ +0x553e, /*dark1 M lum*/ +0x5667, /*dark1 L lum*/ +0x576a, /*dark1 ratio*/ + +0x58a0, /*dark2 H th*/ +0x5940, /*dark2 L th*/ +0x5a28, /*dark2 H lum*/ +0x5b3f, /*dark2 M lum*/ +0x5c68, /*dark2 L lum*/ +0x5d70, /*dark2 ratio*/ + +0x5ea0, /*dark3 H th*/ +0x5f40, /*dark3 L th*/ +0x6029, /*dark3 H lum*/ +0x613f, /*dark3 M lum*/ +0x6269, /*dark3 L lum*/ +0x636a, /*dark3 ratio*/ + +/*C-filter(Out2&Out1)*/ +0x7010, +0x710a, + +/*C-filter(Indoor&Dark3)*/ +0x7210, +0x730a, + +/*C-filter(Dark2&Dark1)*/ +0x7418, +0x7512, + +0x8020, +0x8140, +0x8265, +0x851a, +0x8800, +0x8900, +0x905d, /*Preview DPC off[0x5c] on[0x5d]*/ + +/*DPC-Dark1,2,3*/ +0xad07, /*10825*/ +0xae07, /*10825*/ +0xaf07, /*10825*/ + +/*Blue Det..*/ +0xc558, /*BlueRange 2010.8.25 0x40->23 */ +0xc620, /*GreenRange 2010.8.25 0x3b->20 */ + +0xd088, /*2010.8.25*/ +0xd180, +0xd217,/*preview 17, full 67*/ +0xd300, +0xd400, +0xd50f,/*preview 0f, full 02*/ +0xd6ff, +0xd7ff,/*preview ff, full 18*/ +0xd800, +0xd904, + +/*interpolated with average*/ +0xdb38, /*resolution issue 0x00->0x18->0x38 */ +0xd904, /*strong_edge detect ratio*/ +0xe001, /*strong_edge detect ratio*/ + +0x0313, /*page 13 sharpness 1D*/ +0x10c5, +0x117b, +0x120e, +0x1400, + +0x1511, /*added option 1.3M*/ +0x1830, /*added option 1.3M*/ + +0x2015, +0x2113, +0x2233, +0x2308, /*hi_clip th1*/ +0x241a, /*hi_clip th2*/ +0x2506, /*low clip th*/ + +0x2618, +0x2730, +0x2910, /*time th*/ +0x2a30, /*pga th*/ + +0x2b03, /*lpf out2*/ +0x2c03, /*lpf out1*/ +0x2d0c, +0x2e12, +0x2f12, + +/*1D Edge*/ +0x500a, /*out2 hi nega*/ +0x5307, /* hi pos*/ +0x510c, /* mi nega*/ +0x5407, /* mi pos*/ +0x520b, /* lo nega*/ +0x5508, /* lo pos*/ + +0x560a, /*out1 hi nega*/ +0x5907, /* hi pos */ +0x570c, /* mi nega*/ +0x5a07, /* mi pos */ +0x580b, /* lo nega*/ +0x5b08, /* lo pos */ + +/*Indoor Edge*/ +0x5c08, /*indoor hi nega*/ +0x5f07, /* hi pos*/ +0x5d14, +0x6012, +0x5e0a, +0x6108, /* low pos*/ + +0x6208, /*dark1 hi nega*/ +0x6506, /* hi pos */ +0x6308, /* mid nega */ +0x6606, /* mid pos */ +0x6408, /* low nega */ +0x6706, /* low pos */ + +0x6807, /*dark2 hi nega*/ +0x6b05, /* hi pos */ +0x6907, /* mid nega */ +0x6c05, /* mid pos */ +0x6a07, /* low nega */ +0x6d05, /* low pos */ + +0x6e0a, /*dark3 hi nega*/ +0x7109, /* hi pos */ +0x6f0a, /* mid nega */ +0x7209, /* mid pos */ +0x700a, /* low nega */ +0x7309, /* low pos */ + + /* 2DY*/ +0x80c1, +0x811f, +0x82e1, +0x8333, + +0x9005, +0x9105, +0x9233, +0x9330, +0x9403, +0x9514, +0x9730, +0x9930, + +0xa002, /*2d lclp out2 nega*/ +0xa103, /*2d lclp out2 pos*/ +0xa202, /*2d lclp out1 nega*/ +0xa303, /*2d lclp out1 pos*/ +0xa403, /*2d lclp in nega*/ +0xa504, /*2d lclp in pos*/ +0xa607, /*2d lclp dark1 nega*/ +0xa708, /*2d lclp dark1 pos*/ +0xa807, /*2d lclp dark2 nega*/ +0xa908, /*2d lclp dark2 pos*/ +0xaa07, /*2d lclp dark3 nega*/ +0xab08, /*2d lclp dark3 pos*/ + +0xb010, /*out2 H Ne*/ +0xb310, /* H Po*/ +0xb11e, /* M Ne*/ +0xb41e, /* M Po*/ +0xb21f, /* L Ne*/ +0xb51e, /* L Po*/ + +0xb610, /*out1 H Ne */ +0xb910, /* H Po */ +0xb71e, /* M Ne */ +0xba1e, /* M Po */ +0xb81f, /* L Ne */ +0xbb1e, /* L Po */ + +0xbc20, /*indoor H Ne*/ +0xbf1e, /* H Po*/ +0xbd25, /* M Ne*/ +0xc023, /* M Po*/ +0xbe24, /* L Ne*/ +0xc122, /* L Po*/ + +0xc223, /*dark1 H Ne*/ +0xc523, /* H Po*/ +0xc329, /* M Ne*/ +0xc629, /* M Po*/ +0xc425, /* L Ne*/ +0xc725, /* L Po*/ + +0xc81c, /*dark2 H Ne*/ +0xcb1c, /* H Po*/ +0xc925, /* M Ne*/ +0xcc25, /* M Po*/ +0xca23, /* L Ne*/ +0xcd23, /* L Po*/ + +0xce1c, /*dark3 H Ne*/ +0xd11c, /* H Po*/ +0xcf25, /* M Ne*/ +0xd225, /* M Po*/ +0xd023, /* L Ne*/ +0xd323, /* L Po*/ + +/* PAGE 14 START*/ +0x0314, +0x1031, + +0x1480, /* GX*/ +0x1580, /* GY*/ +0x1680, /* RX*/ +0x1780, /* RY*/ +0x1880, /* BX*/ +0x1980, /* BY*/ + +0x2060, /* X Center*/ +0x2180, /* Y Center*/ + +0x2280, +0x2380, +0x2480, + +0x30c8, +0x312b, +0x3200, +0x3300, +0x3490, + +0x4056, /*R min's set 4e*/ +0x413a, /*Gr*/ +0x4237, /*B*/ +0x433a, /*Gb*/ + +0x0315, +0x1021, +0x1444, /*49*/ +0x1534, /*38*/ +0x1626, /*2b*/ +0x172f, + +0x30dd, +0x3162, +0x3205, +0x3326, +0x34bd, +0x3517, +0x3618, +0x3738, +0x38d0, + +0x40b0, +0x4130, +0x4200, +0x4300, +0x4400, +0x4500, +0x4699, +0x4719, +0x4800, + +0x5016, +0x51b2, +0x521c, +0x5306, +0x5420, +0x55a6, +0x560e, +0x57b2, +0x5824, + +0x0316, +0x1031, /*GMA_CTL*/ +0x187e, /*AG_ON*/ +0x197d, /*AG_OFF*/ +0x1a0e, /*TIME_ON*/ +0x1b01, /*TIME_OFF*/ +0x1Cdc, /*OUT_ON*/ +0x1Dfe, /*OUT_OFF*/ + +/*GMA Indoor*/ +0x3000, +0x3107, +0x321a, +0x3335, +0x345a, +0x357c, +0x3696, +0x37a9, +0x38b7, +0x39c6, +0x3ad2, +0x3bdc, +0x3ce4, +0x3deb, +0x3ef1, +0x3ff5, +0x40f9, +0x41fd, +0x42ff, + +/*RGMA Outdoor*/ +0x5000, +0x5103, +0x5213, +0x532e, +0x5459, +0x5579, +0x5690, +0x57a3, +0x58b4, +0x59c2, +0x5acd, +0x5bd7, +0x5ce0, +0x5de5, +0x5ee9, +0x5fee, +0x60f1, +0x61f3, +0x62f6, + +/*BGMA Dark*/ +0x7003, +0x7111, +0x721f, +0x7337, +0x7452, +0x756c, +0x7685, +0x779a, +0x78ad, +0x79bd, +0x7acb, +0x7bd6, +0x7ce0, +0x7de8, +0x7eef, +0x7ff4, +0x80f8, +0x81fb, +0x82fe, + +0x0324, /*Resol control */ +0x60c5, /*edge even frame | 16bit resol | white edge cnt | scene resol enable*/ +0x6104, /*even frame update */ +0x6408, +0x6500, +0x6626, /*edge th2 H */ +0x6700, /*edge th2 L */ + +0x0313, +0x1831, /*flat center Gb/Gr*/ +0x7402, /*det slope en | gausian filter*/ +0x750d, /*1D negative gain det 09 */ +0x760d, /*1D postive gain det 08*/ +0x7710, /*1D hclp2 det*/ +0x7808, /*outdoor flat threshold*/ +0x7910, /*indoor flat threshold*/ + +0x81df, /*det gain controler*/ +0x8690, /*2D negative gain det */ +0x8790, /*2D postive gain det */ +0x962a, /*2D hclp2 det*/ + +0x0312, /*0x12 page*/ +0xd088, +0xd9e4, + +/* PAGE 18 START*/ +0x0318, +0x1400, + +/* PAGE 20 START*/ +0x0320, +0x111c, +0x1830, +0x1a08, +0x2045,/*weight*/ +0x2130, +0x2210, +0x2300, +0x2400, + +0x28e7, /* add 20120223*/ +0x290d, /* 20100305 ad -> 0d*/ +0x2afd, +0x2bf8, + +0x2cc3, +0x2d5f, /* add 20120223*/ +0x2e33, +0x30f8, +0x3203, +0x332e, +0x3430, +0x35d4, +0x36ff, /*fe*/ +0x3732, +0x3804, +0x3922, +0x3ade, +0x3b22, +0x3cde, +0x3de1, + +0x5045, +0x5188, + +0x561a, +0x5780, +0x580e, +0x596a, +0x5a04, + +0x5e9d, /*AE_AWB_start*/ +0x5f76, /*AE_AWB_start*/ + +0x7033, /* 6c*/ +0x7182, /* 82(+8)*/ + +0x7621, +0x7771, +0x7822, /* 24*/ +0x7923, /* Y Target 70 => 25, 72 => 26*/ +0x7a23, /* 23*/ +0x7b22, /* 22*/ +0x7d23, + +0x8301, /*EXP Normal 33.33 fps */ +0x845f, +0x8590, +0x8601, /*EXPMin 7500.00 fps*/ +0x8790, +0x8805, /*EXP Max(120Hz) 8.00 fps */ +0x89b8, +0x8ad8, +0xa505, /*EXP Max(100Hz) 8.33 fps */ +0xa67e, +0xa740, +0x8B75, /*EXP100 */ +0x8C30, +0x8D61, /*EXP120 */ +0x8Ea8, +0x9c09, /*EXP Limit 1250.00 fps */ +0x9d60, +0x9e01, /*EXP Unit */ +0x9f90, +0x989d, + +0xb016, +0xb114, +0xb2f8, +0xb314, +0xb41b, +0xb546, +0xb631, +0xb729, +0xb826, +0xb924, +0xba22, +0xbb42, +0xbc41, +0xbd40, + +0xc010, +0xc138, +0xc238, +0xc338, +0xc407, + +0xc880, +0xc980, +0x109c, /* ae enable*/ +/* PAGE 20 END*/ + +/*AE_Weight*/ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2412, +0x2522, +0x2622, +0x2721, +0x2812, +0x2922, +0x2a22, +0x2b21, +0x2c12, +0x2d23, +0x2e32, +0x2f21, +0x3012, +0x3123, +0x3232, +0x3321, +0x3412, +0x3522, +0x3622, +0x3721, +0x3812, +0x3922, +0x3a22, +0x3b21, +0x3c11, +0x3d11, +0x3e11, +0x3f11, + +/* PAGE 22 START*/ +0x0322, +0x10fd, +0x112e, +0x1901, /* Low On*/ +0x2030, /* for wb speed*/ +0x2140, +0x2401, +0x257e, /* for tracking 20120314 */ + +0x3080, /* 20120224 test*/ +0x3180, +0x3811, +0x3934, + +0x40e8, +0x4143, /* 33*/ +0x4222, /* 22*/ + +0x43f3, /* f6*/ +0x4454, /* 44*/ +0x4522, /* 33*/ + +0x4600, +0x480a, +0x50b2, +0x5181, +0x5298, + +0x8038, +0x8120, +0x8238, /* 3a*/ + +0x8356, /* R Max*/ +0x8420, /* R Min*/ +0x8552, /* B Max*/ +0x8620, /* B Min*/ + +0x8745, +0x883a, +0x8933, +0x8a2c, + +0x8b42, +0x8c3d, +0x8d30, +0x8e2c, + +0x8f5a, +0x9059, +0x9155, +0x924e, +0x9344, +0x943a, +0x9534, +0x962c, +0x9723, +0x9820, +0x991f, +0x9a1f, + +0x9b77, +0x9c77, +0x9d48, +0x9e38, +0x9f30, + +0xa040, +0xa121, +0xa26f, +0xa3ff, + +0xa414, /* 1500fps*/ +0xa544, /* 700fps*/ +0xa6cf, + +0xad40, +0xae4a, + +0xaf2a, /* low temp Rgain*/ +0xb028, /* low temp Rgain*/ + +0xb100, /* 0x20 -> 0x00 0405 modify*/ +0xb4bf, /* for tracking 20120314*/ +0xb8a1, /* a2: b-2, R+2 b4 B-3, R+4 lowtemp b0 a1 Spec AWB A modify*/ +0xb900, +/* PAGE 22 END*/ + +/* PAGE 48 (MiPi 1600x1200)*/ +0x0300, + +/* PLL Setting */ +0xd005, +0xd130, +0xd205, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x0348, +/* MIPI TX Setting */ +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +0x1d0e, +0x1e07, +0x1f08, + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2b40,*/ + +0x3005, +0x3100, + +0x3207, +0x3309, +0x3401, +0x3501, + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_VT_Init_Reg[] = { +/*0 Page*/ +0x0300, +0x0101, /*sleep*/ +0x0103, /*s/w reset*/ +0x0101, /*sleep*/ + +0x0800,/*Don't touch*/ +0x0937,/*Don't touch*/ +0x0a33,/*Don't touch*/ + +/*PLL Setting*/ +0xd005, +0xd130, +0xd201, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x1011, +0x1194, /*xy flip*/ +0x1200, /*Sync type default:0x00 PCLK[2] 0 falling, 1 rising*/ +0x1488, + +/*--------------- windowing */ +0x0300, +0x2000, +0x2104, +0x2200, +0x2304, +0x2403, +0x25C0, +0x2605, +0x2700, + +0x4001, /*Hblank 280*/ +0x4118, +0x4200, /*Vblank 20*/ +0x4314, + +/*--------------- BLC*/ +0x8008, /*Don't touch */ +0x8197, /*Don't touch */ +0x8290, /*Don't touch */ +0x8330, /*Don't touch */ +0x84cc, /*Don't touch*/ +0x8500, /*Don't touch*/ +0x86d4, /*Don' t touch*/ +0x870f, /*Don't touch*/ +0x8834, /*Don't touch*/ + +0x9009, /*BLC_TIME_TH_ON*/ +0x9109, /*BLC_TIME_TH_OFF */ +0x92f0, /*BLC_AG_TH_ON*/ +0x93e8, /*BLC_AG_TH_OFF*/ + +0x9495, /*091202*/ +0x9590, /*091202 */ +0x9838, /*Don't touch*/ + +/*Dark BLC*/ +0xa001, /* 20100309*/ +0xa201, /* 20100309*/ +0xa401, /* 20100309*/ +0xa601, /* 20100309*/ + +/*Normal BLC*/ +0xa800, +0xaa00, +0xac00, +0xae00, + +/*Out BLC*/ +0x9900, +0x9a00, +0x9b00, +0x9c00, + +/*2 Page*/ +0x0302, +0x1200, /*Don't touch*/ +0x1400, /*Don't touch*/ +0x1500, /*Don't touch*/ +0x184C, /*Don't touch*/ +0x1900, /*Don't touch*/ +0x1A39, /*Don't touch*/ +0x1B00,/*Don't touch*/ +0x1C1a, /*Don't touch*/ +0x1D14, /*Don't touch*/ +0x1E30,/*Don't touch*/ +0x1F10,/*Don't touch*/ + +0x2077, +0x21de, +0x22a7, +0x2330, +0x2477, +0x2510, +0x2610, +0x273c, +0x2b80, +0x2c02, +0x2da0, +0x2e00, +0x2fa7, + +0x3000, +0x3199, +0x3200, +0x3300, +0x3422, +0x3601, +0x3701, +0x3888, +0x3988, +0x3d03, +0x3e0d, +0x3f02, + +0x49d1, +0x4a14, + +0x5021, +0x5201, +0x5381, +0x5410, +0x551c, +0x5611, +0x5818, +0x5916, +0x5da2, +0x5e5a, + +0x6093, /* 20120517 modify*/ +0x61a4, /* 20120517 modify*/ +0x6294, /* 20120517 modify*/ +0x63a3, /* 20120517 modify*/ +0x6494, /* 20120517 modify*/ +0x65a3, /* 20120517 modify*/ +0x670c, +0x680c, +0x690c, +0x6ab4, +0x6bc4, +0x6cb5, +0x6dc2, +0x6eb5, +0x6fc0, + +0x70b6, +0x71b8, +0x7295, /* 20120517 modify*/ +0x73a2, /* 20120517 modify*/ +0x7495, /* 20120517 modify*/ +0x75a2, /* 20120517 modify*/ +0x7695, /* 20120517 modify*/ +0x77a2, /* 20120517 modify*/ +0x7C92, /* 20120517 modify*/ +0x7Dff, /* 20120517 modify*/ + +0x8001, /* 20120517 modify*/ +0x818a, /* 20120517 modify*/ +0x821e, /* 20120517 modify*/ +0x8336, /* 20120517 modify*/ +0x8489, /* 20120517 modify*/ +0x858b, /* 20120517 modify*/ +0x8689, /* 20120517 modify*/ +0x878b, /* 20120517 modify*/ +0x88ab, +0x89bc, +0x8aac, +0x8bba, +0x8cad, +0x8db8, +0x8eae, +0x8fb2, + +0x90b3, +0x91b7, +0x9252, /* 20120517 modify*/ +0x936a, /* 20120517 modify*/ +0x9489, /* 20120517 modify*/ +0x958b, /* 20120517 modify*/ +0x9689, /* 20120517 modify*/ +0x978b, /* 20120517 modify*/ + +0xA002, +0xA186, /* 20120517 modify*/ +0xA202, +0xA386, /* 20120517 modify*/ +0xA486, /* 20120517 modify*/ +0xA502, +0xA686, /* 20120517 modify*/ +0xA702, +0xA892, /* 20120517 modify*/ +0xA994, /* 20120517 modify*/ +0xAA92, /* 20120517 modify*/ +0xAB94, /* 20120517 modify*/ +0xAC1c, +0xAD22, +0xAE1c, +0xAF22, + +0xB0a4, /* 20120517 modify*/ +0xB1ae, /* 20120517 modify*/ +0xB2a4, /* 20120517 modify*/ +0xB3ae, /* 20120517 modify*/ +0xB4a6, /* 20120517 modify*/ +0xB5ac, /* 20120517 modify*/ +0xB6a6, /* 20120517 modify*/ +0xB7ac, /* 20120517 modify*/ +0xB8a6, /* 20120517 modify*/ +0xB9ab, /* 20120517 modify*/ +0xBAa6, /* 20120517 modify*/ +0xBBab, /* 20120517 modify*/ +0xBCa6, /* 20120517 modify*/ +0xBDab, /* 20120517 modify*/ +0xBEa6, /* 20120517 modify*/ +0xBFab, /* 20120517 modify*/ + +0xc437, +0xc552, +0xc66b, +0xc786, +0xc838, /* 20120517 modify*/ +0xc950, /* 20120517 modify*/ +0xca38, /* 20120517 modify*/ +0xcb50, /* 20120517 modify*/ +0xcc6c, /* 20120517 modify*/ +0xcd84, /* 20120517 modify*/ +0xce6c, /* 20120517 modify*/ +0xcf84, /* 20120517 modify*/ + +/*0xd4a6,*/ +/*0xd5ac,*/ +/*0xd6a6,*/ +/*0xd7ac,*/ +/*add 20120517*/ +0xdc00, /* Added*/ +0xddaf, /* Added*/ +0xde00, /* Added*/ +0xdf90, /* Added*/ + +0xd010, +0xd114, +0xd220, +0xd300, +/*DCDC */ +0xd409, /*DCDC_TIME_TH_ON*/ +0xd509, /*DCDC_TIME_TH_OFF */ +0xd6f0, /*DCDC_AG_TH_ON*/ +0xd7e8, /*DCDC_AG_TH_OFF*/ + +0xea8a, + +0xF001, /* clock inversion*/ +0xF101, +0xF201, +0xF301, +0xF401, +0xF500, + +/*----------------------------------------------*/ +0x0310, /*page 10*/ +0x1001, /*Ycbcr422_bit Order: YUYV*/ +0x1230, /*y offset[4], dif_offset[5]*/ +0x1302, /*contrast effet enable : 0x02*/ +0x3400, /*hidden 10->00 100209*/ +0x3701, /*yc2d power save */ +0x3f04, /*100825*/ +0x4080, /*Y offset */ +0x4138, +0x4880, /*Contrast (Y = constrast * (Y - 128) + 128)*//*86 */ +0x50f0, +0x5300, /*dif_offset option */ +0x5530, /*dif_offset option diff_offset max */ + +0x6003, /*out color sat en[7] | auto color decrement en[1] / + | manual color sat en[0]*/ + + +0x6183, /*blue saturation_C0*/ +0x6280, /*red saturation_B0*/ + +0x63ff, /*auto decresment on AG th*/ +0x64ff, /*auto decresment on DG th*/ +0x66e4, /*Outdoor saturation step 137fps apply out th */ +0x6700, /*Outdoor saturation B/R*/ +0x7601, /* ADD 20121031 */ +0x7904, /* ADD 20121031 */ + +/* Hi 163 */ +/* PAGE 10 START*/ +0x0310, +0x8000, /* dsshin --> color enhance*/ +0xf500, /* dsshin --> h blank option*/ + +0x0311, /*page 11 D_LPF */ +0x103f, /*B[6]:Blue En Dlpf on[4:0] Sky over off : 0x7f->3f*/ +0x1120, /* Uniform Full GbGr/OV-Nr*/ + +0x1280, /*Blue MaxOpt blue sky max filter optoin rate : 0 0xc0->80*/ +0x13b8, /*dark2[7] | dark2 maxfilter ratio[6:4] + | dark3[3] | dark3 maxfilter ratio[2:0] */ + +0x30ba, /*Outdoor2 H th*/ +0x3110, /*Outdoor2 L th*/ +0x3250, /*Outdoor2 gain ratio*/ +0x331d, /*Outdoor2 H lum*/ +0x3420, /*Outdoor2 M lum*/ +0x351f, /*Outdoor2 L lum*/ + +0x36b0, /*Outdoor1 H th*/ +0x3718, /*Outdoor1 L th*/ +0x3850, /*Outdoor1 gain ratio 0x80->40*/ +0x391d, /*Outdoor1 H lum 0x28->1e*/ +0x3a20, /*Outdoor1 M lum 0x10->15*/ +0x3b1f, /*Outdoor1 L lum 0x08->20*/ + +0x3c3f, /*indoor H th*/ +0x3d16, /*indoor L th*/ +0x3e30, /*indoor gain ratio 0x44 6a */ +0x3f1a, /*indoor H lum 0x12 18 */ +0x4060, /*indoor M lum 0x18 1c*/ +0x411a, /*indoor L lum 0x18 3e*/ + +0x4298, /*dark1 H th*/ +0x4328, /*dark1 L th*/ +0x4465, /*dark1 gain ratio*/ +0x4516, /*dark1 H lum 0x38->0x28 */ +0x4630, /*dark1 M lum 0x27->0x17*/ +0x4734, /*dark1 L lum 0x20->0x1a */ + +0x4890, /*dark2 H th*/ +0x492a, /*dark2 L th*/ +0x4a65, /*dark2 gain ratio*/ +0x4b18, /*dark2 H lum */ +0x4c31, /*dark2 M lum*/ +0x4d36, /*dark2 L lum */ + +0x4e80, /*dark3 H th*/ +0x4f30, /*dark3 L th*/ +0x5065, /*dark3 gain ratio*/ +0x5119, /*dark3 H lum */ +0x5231, /*dark3 M lum */ +0x5336, /*dark3 L lum */ + +0x5a3f, /*blue sky mode out1/2 enable 0x27->3f */ +0x5b00, /*Impulse pixel enable dark123,in,out123 + :: must be 0x07 fix setting use!*/ +0x5c9f, /*Indoor maxfilter rate[7:5] | Uncertain onoff[4:0] 0x1f ->0x9f*/ + +0x603f, /*GbGr all enable*/ +0x620f, /*GbGr offset*/ +/*0x6325,*/ /*GbGr max_20120605_off*/ +/*0x6410,*/ /*GbGr min_20120605_off*/ + +0x650c, /*Outdoor GbGr rate H 100% M 25% L 100%*/ +0x660c, /*Indoor GbGr rate H 100% M 25% L 100%*/ +0x6700, /*dark GbGr rate H/M/L 100%*/ + +0x700c, /* Abberation On/Off B[1]: Outdoor B[0]: Indoor 07>>c*/ +0x75a0, /* Outdoor2 Abberation Luminance lvl */ +0x7db4, /* Indoor Abberation Luminance lvl*/ + +0x9608, /*indoor/Dark1 edgeoffset1*/ +0x9714, /*indoor/Dark1 center G value*/ +0x98f5, /*slope indoor :: left/right graph polarity, slope*/ +0x992a, /*indoor uncertain ratio control*/ +0x9a20, /*Edgeoffset_dark*/ + +/*DPC_CTRL*/ +0x0312, /*Preview DPC off[0x5c] on[0x5d]*/ +0x200e, +0x210e, + +0x2500, /* 0x30*/ + +0x2a01, +0x2e00, /*2010.8.25*/ + +0x3035, /*Texture region(most detail)*/ +0x31a0, /*STD uniform1 most blur region*/ +0x32b0, /*STD uniform2 2nd blur*/ +0x33c0, /*STD uniform3 3rd blur*/ +0x34d0, /*STD normal noise1 4th blur */ +0x35e0, /*STD normal noise2 5th blur*/ +0x36ff, /*STD normal noise3 6th blur*/ + +0x4083, /*Outdoor2 H th*/ +0x4120, /*Outdoor2 L th */ +0x4208, /*Outdoor2 H luminance */ +0x4310, /*Outdoor2 M luminance */ +0x4410, /*Outdoor2 l luminance */ +0x4550, /*Outdoor2 ratio*/ + +0x4683, /*Outdoor1 H th*/ +0x4720, /*Outdoor1 L th */ +0x4808, /*Outdoor1 H luminance*/ +0x4910, /*Outdoor1 M luminance*/ +0x4a10, /*Outdoor1 L luminance*/ +0x4b50, /*Outdoor1 ratio*/ + +0x4c80, /*Indoor H th*/ +0x4d48, /*Indoor L th*/ +0x4e30, /*indoor H lum*/ +0x4f30, /*indoor M lum*/ +0x5012, /*indoor L lum */ +0x5170, /*indoor ratio 0x10 -> 0x45*/ + +0x52a8, /*dark1 H th*/ +0x5330, /*dark1 L th */ +0x5428, /*dark1 H lum */ +0x553e, /*dark1 M lum*/ +0x5667, /*dark1 L lum*/ +0x576a, /*dark1 ratio*/ + +0x58a0, /*dark2 H th*/ +0x5940, /*dark2 L th*/ +0x5a28, /*dark2 H lum*/ +0x5b3f, /*dark2 M lum*/ +0x5c68, /*dark2 L lum*/ +0x5d70, /*dark2 ratio*/ + +0x5ea0, /*dark3 H th*/ +0x5f40, /*dark3 L th*/ +0x6029, /*dark3 H lum*/ +0x613f, /*dark3 M lum*/ +0x6269, /*dark3 L lum*/ +0x636a, /*dark3 ratio*/ + +/*C-filter(Out2&Out1)*/ +0x7010, +0x710a, + +/*C-filter(Indoor&Dark3)*/ +0x7210, +0x730a, + +/*C-filter(Dark2&Dark1)*/ +0x7418, +0x7512, + +0x8020, +0x8140, +0x8265, +0x851a, +0x8800, +0x8900, +0x905d, /*Preview DPC off[0x5c] on[0x5d]*/ + +/*DPC-Dark1,2,3*/ +0xad07, /*10825*/ +0xae07, /*10825*/ +0xaf07, /*10825*/ + +/*Blue Det..*/ +0xc558, /*BlueRange 2010.8.25 0x40->23 */ +0xc620, /*GreenRange 2010.8.25 0x3b->20 */ + +0xd088, /*2010.8.25*/ +0xd180, +0xd217,/*preview 17, full 67*/ +0xd300, +0xd400, +0xd50f,/*preview 0f, full 02*/ +0xd6ff, +0xd7ff,/*preview ff, full 18*/ +0xd800, +0xd904, + +/*interpolated with average*/ +0xdb38, /*resolution issue 0x00->0x18->0x38 */ +0xd904, /*strong_edge detect ratio*/ +0xe001, /*strong_edge detect ratio*/ + +0x0313, /*page 13 sharpness 1D*/ +0x10c5, +0x117b, +0x120e, +0x1400, + +0x1511, /*added option 1.3M*/ +0x1830, /*added option 1.3M*/ + +0x2015, +0x2113, +0x2233, +0x2308, /*hi_clip th1*/ +0x241a, /*hi_clip th2*/ +0x2506, /*low clip th*/ + +0x2618, +0x2730, +0x2910, /*time th*/ +0x2a30, /*pga th*/ + +0x2b03, /*lpf out2*/ +0x2c03, /*lpf out1*/ +0x2d0c, +0x2e12, +0x2f12, + +/*1D Edge*/ +0x500a, /*out2 hi nega*/ +0x5307, /* hi pos*/ +0x510c, /* mi nega*/ +0x5407, /* mi pos*/ +0x520b, /* lo nega*/ +0x5508, /* lo pos*/ + +0x560a, /*out1 hi nega*/ +0x5907, /* hi pos */ +0x570c, /* mi nega*/ +0x5a07, /* mi pos */ +0x580b, /* lo nega*/ +0x5b08, /* lo pos */ + +/*Indoor Edge*/ +0x5c08, /*indoor hi nega*/ +0x5f07, /* hi pos*/ +0x5d14, /* mid nega ,11*/ +0x6012, /* mid pos ,0*/ +0x5e0a, /* low nega */ +0x6108, /* low pos*/ + +0x6208, /*dark1 hi nega*/ +0x6506, /* hi pos */ +0x6308, /* mid nega */ +0x6606, /* mid pos */ +0x6408, /* low nega */ +0x6706, /* low pos */ + +0x6807, /*dark2 hi nega*/ +0x6b05, /* hi pos */ +0x6907, /* mid nega */ +0x6c05, /* mid pos */ +0x6a07, /* low nega */ +0x6d05, /* low pos */ + +0x6e0a, /*dark3 hi nega*/ +0x7109, /* hi pos */ +0x6f0a, /* mid nega */ +0x7209, /* mid pos */ +0x700a, /* low nega */ +0x7309, /* low pos */ + + /* 2DY*/ +0x80c1, +0x811f, +0x82e1, +0x8333, + +0x9005, +0x9105, +0x9233, +0x9330, +0x9403, +0x9514, +0x9730, +0x9930, + +0xa002, /*2d lclp out2 nega*/ +0xa103, /*2d lclp out2 pos*/ +0xa202, /*2d lclp out1 nega*/ +0xa303, /*2d lclp out1 pos*/ +0xa403, /*2d lclp in nega*/ +0xa504, /*2d lclp in pos*/ +0xa607, /*2d lclp dark1 nega*/ +0xa708, /*2d lclp dark1 pos*/ +0xa807, /*2d lclp dark2 nega*/ +0xa908, /*2d lclp dark2 pos*/ +0xaa07, /*2d lclp dark3 nega*/ +0xab08, /*2d lclp dark3 pos*/ + +0xb010, /*out2 H Ne*/ +0xb310, /* H Po*/ +0xb11e, /* M Ne*/ +0xb41e, /* M Po*/ +0xb21f, /* L Ne*/ +0xb51e, /* L Po*/ + +0xb610, /*out1 H Ne */ +0xb910, /* H Po */ +0xb71e, /* M Ne */ +0xba1e, /* M Po */ +0xb81f, /* L Ne */ +0xbb1e, /* L Po */ + +0xbc20, /*indoor H Ne*/ +0xbf1e, /* H Po*/ +0xbd25, /* M Ne*/ +0xc023, /* M Po*/ +0xbe24, /* L Ne*/ +0xc122, /* L Po*/ + +0xc223, /*dark1 H Ne*/ +0xc523, /* H Po*/ +0xc329, /* M Ne*/ +0xc629, /* M Po*/ +0xc425, /* L Ne*/ +0xc725, /* L Po*/ + +0xc81c, /*dark2 H Ne*/ +0xcb1c, /* H Po*/ +0xc925, /* M Ne*/ +0xcc25, /* M Po*/ +0xca23, /* L Ne*/ +0xcd23, /* L Po*/ + +0xce1c, /*dark3 H Ne*/ +0xd11c, /* H Po*/ +0xcf25, /* M Ne*/ +0xd225, /* M Po*/ +0xd023, /* L Ne*/ +0xd323, /* L Po*/ + +/* PAGE 14 START*/ +0x0314, +0x1031, + +0x1480, /* GX*/ +0x1580, /* GY*/ +0x1680, /* RX*/ +0x1780, /* RY*/ +0x1880, /* BX*/ +0x1980, /* BY*/ + +0x2060, /* X Center*/ +0x2180, /* Y Center*/ + +0x2280, +0x2380, +0x2480, + +0x30c8, +0x312b, +0x3200, +0x3300, +0x3490, + +0x4056, /*R min's set 4e*/ +0x413a, /*Gr*/ +0x4237, /*B*/ +0x433a, /*Gb*/ + +0x0315, +0x1021, +0x1444, /*49*/ +0x1534, /*38*/ +0x1626, /*2b*/ +0x172f, + +0x30dd, +0x3162, +0x3205, +0x3326, +0x34bd, +0x3517, +0x3618, +0x3738, +0x38d0, + +0x40b0, +0x4130, +0x4200, +0x4300, +0x4400, +0x4500, +0x4699, +0x4719, +0x4800, + +0x5016, +0x51b2, +0x521c, +0x5306, +0x5420, +0x55a6, +0x560e, +0x57b2, +0x5824, + +0x0316, +0x1031, /*GMA_CTL*/ +0x187e, /*AG_ON*/ +0x197d, /*AG_OFF*/ +0x1a0e, /*TIME_ON*/ +0x1b01, /*TIME_OFF*/ +0x1Cdc, /*OUT_ON*/ +0x1Dfe, /*OUT_OFF*/ + +/*GMA, Indoor*/ +0x3000, +0x3107, +0x321a, +0x3335, +0x345a, +0x357c, +0x3696, +0x37a9, +0x38b7, +0x39c6, +0x3ad2, +0x3bdc, +0x3ce4, +0x3deb, +0x3ef1, +0x3ff5, +0x40f9, +0x41fd, +0x42ff, + +/*RGMA, Outdoor*/ +0x5000, +0x5103, +0x5213, +0x532e, +0x5459, +0x5579, +0x5690, +0x57a3, +0x58b4, +0x59c2, +0x5acd, +0x5bd7, +0x5ce0, +0x5de5, +0x5ee9, +0x5fee, +0x60f1, +0x61f3, +0x62f6, + +/*BGMA Dark*/ +0x7000, +0x7107, +0x721a, +0x7335, +0x745a, +0x757c, +0x7696, +0x77a9, +0x78b7, +0x79c6, +0x7ad2, +0x7bdc, +0x7ce4, +0x7deb, +0x7ef1, +0x7ff5, +0x80f9, +0x81fd, +0x82ff, + +0x0324, /*Resol control */ +0x60c5, /*edge even frame | 16bit resol | white edge cnt | scene resol enable*/ +0x6104, /*even frame update */ +0x6408, /* 0x6435, edge th1 H*/ +0x6500, /*edge th1 L*/ +0x6626, /*edge th2 H */ +0x6700, /*edge th2 L */ + +0x0313, +0x1831, /*flat center Gb/Gr*/ +0x7402, /*det slope en | gausian filter*/ +0x750d, /*1D negative gain det 09 */ +0x760d, /*1D postive gain det 08*/ +0x7710, /*1D hclp2 det*/ +0x7808, /*outdoor flat threshold*/ +0x7910, /*indoor flat threshold*/ + +0x81df, /*det gain controler*/ +0x8690, /*2D negative gain det */ +0x8790, /*2D postive gain det */ +0x962a, /*2D hclp2 det*/ + +0x0312, /*0x12 page*/ +0xd088, +0xd9e4, + +/* PAGE 20 START*/ +0x0320, +0x111c, +0x1830, +0x1a08, +0x2045,/*weight*/ +0x2130, +0x2210, +0x2300, +0x2400, + +0x28e7, /* add 20120223*/ +0x290d, /* 20100305 ad -> 0d*/ +0x2afd, +0x2bf8, + +0x2cc3, +0x2d5f, /* add 20120223*/ +0x2e33, +0x30f8, +0x3203, +0x332e, +0x3430, +0x35d4, +0x36fe, +0x3732, +0x3804, +0x3922, +0x3ade, +0x3b22, +0x3cde, +0x3de1, + +0x5045, +0x5188, + +0x561a, +0x5780, +0x580e, +0x596a, +0x5a04, + +0x5e9d, /*AE_AWB_start*/ +0x5f76, /*AE_AWB_start*/ + +0x7040, /* 6c*/ +0x7182, /* 82(+8)*/ + +0x7621, +0x7791, +0x7822, /* 24*/ +0x792b, /* Y Target 70 => 25, 72 => 26*/ +0x7a23, /* 23*/ +0x7b22, /* 22*/ +0x7d23, + +0x8301, /*EXP Normal 33.33 fps */ +0x845f, +0x8590, + +0x8601, /*EXPMin 7500.00 fps*/ +0x8790, + +0x8803, /*EXP Max(120Hz) 12.00 fps*/ +0x89d0, +0x8a90, + +0xa504, /*EXP Max(100Hz) 11.11 fps*/ +0xa61e, +0xa7b0, + +0x8B75, /*EXP100 */ +0x8C30, +0x8D61, /*EXP120 */ +0x8Ea8, + +0x9104, /*EXP Fix 10.00 fps*/ +0x9293, +0x93e0, + +0x9c0a, /*EXP Limit 1071.43 fps*/ +0x9df0, +0x9e01, /*EXP Unit */ +0x9f90, +0x989d, + +0xb016, +0xb114, +0xb2f8, +0xb314, +0xb41b, +0xb546, +0xb631, +0xb729, +0xb826, +0xb924, +0xba22, +0xbb42, +0xbc41, +0xbd40, + +0xc010, +0xc138, +0xc238, +0xc338, +0xc407, + +0xc880, +0xc980, +0x109c, /* ae enable*/ +/* PAGE 20 END*/ + +/*AE_Weight*/ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2412, +0x2522, +0x2622, +0x2721, +0x2812, +0x2922, +0x2a22, +0x2b21, +0x2c12, +0x2d23, +0x2e32, +0x2f21, +0x3012, +0x3123, +0x3232, +0x3321, +0x3412, +0x3522, +0x3622, +0x3721, +0x3812, +0x3922, +0x3a22, +0x3b21, +0x3c11, +0x3d11, +0x3e11, +0x3f11, + +/* PAGE 22 START*/ +0x0322, +0x10fd, +0x112e, +0x1901, /* Low On*/ +0x2030, /* for wb speed*/ +0x2140, +0x2401, +0x257e, /* for tracking 20120314 */ + +0x3080, /* 20120224 test*/ +0x3180, +0x3811, +0x3934, + +0x40e8, +0x4143, /* 33*/ +0x4222, /* 22*/ + +0x43f3, /* f6*/ +0x4454, /* 44*/ +0x4522, /* 33*/ + +0x4600, +0x480a, +0x50b2, +0x5181, +0x5298, + +0x8038, +0x8120, +0x8238, /* 3a*/ + +0x8356, /* R Max*/ +0x8420, /* R Min*/ +0x8554, /* B Max*/ +0x8620, /* B Min*/ + +0x8746, +0x8836, +0x893a, +0x8a2f, + +0x8b3d, +0x8c37, +0x8d35, +0x8e32, + +0x8f5a, +0x9059, +0x9155, +0x924e, +0x9344, +0x943a, +0x9534, +0x962c, +0x9723, +0x9820, +0x991f, +0x9a1f, + +0x9b77, +0x9c77, +0x9d48, +0x9e38, +0x9f30, + +0xa040, +0xa121, +0xa26f, +0xa3ff, + +0xa414, /* 1500fps*/ +0xa544, /* 700fps*/ +0xa6cf, + +0xad40, +0xae4a, + +0xaf2a, /* low temp Rgain*/ +0xb028, /* low temp Rgain*/ + +0xb100, /* 0x20 -> 0x00 0405 modify*/ +0xb4bf, /* for tracking 20120314*/ +0xb8a1, /* a2: b-2, R+2 b4 B-3, R+4 lowtemp b0 a1 Spec AWB A modify*/ +0xb900, +/* PAGE 22 END*/ + +/* PAGE 48 (MiPi 1600x1200)*/ +0x0300, + +/* PLL Setting */ +0xd005, +0xd130, +0xd205, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +/* MIPI TX Setting */ +0x0348, +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +0x1d0e, +0x1e07, +0x1f08, +/*0x2000,*/ + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2a06,*/ +/*0x2b40,*/ +/*0x2c04,*/ +/*0x2db0,*/ + +0x3005, +0x3100, + +0x3207, +0x3309, +0x3401, +0x3501, +/*0x3601,*/ +/*0x3707,*/ +/*0x3802,*/ +/*0x3902,*/ + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_SmartStay_Init_Reg[] = { +/*0 Page*/ +0x0300, +0x0101, /*sleep*/ +0x0103, /*s/w reset*/ +0x0101, /*sleep*/ + +0x0800,/*Don't touch*/ +0x0937,/*Don't touch*/ +0x0a33,/*Don't touch*/ + +/*PLL Setting*/ +0xd005, +0xd130, +0xd201, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x1011, +0x1190, /*xy flip*/ +0x1200, +0x1488, + +0x0300, +0x2000, +0x2104, +0x2200, +0x2304, +0x2403, +0x25C0, +0x2605, +0x2700, + +0x4001, /*Hblank_280*/ +0x4118, +0x4201, /*Vblank 400*/ +0x4390, + +/*--------------- BLC*/ +0x8008, /*Don't touch */ +0x8197, /*Don't touch */ +0x8290, /*Don't touch */ +0x8330, /*Don't touch */ +0x84cc, /*Don't touch*/ +0x8500, /*Don't touch*/ +0x86d4, /*Don' t touch*/ +0x870f, /*Don't touch*/ +0x8834, /*Don't touch*/ + +0x900c, /*BLC_TIME_TH_ON*/ +0x910c, /*BLC_TIME_TH_OFF */ +0x92f7, /*BLC_AG_TH_ON*/ +0x93ef, /*BLC_AG_TH_OFF*/ + +0x9495, /*091202*/ +0x9590, /*091202 */ +0x9838, /*Don't touch*/ + +/*Dark BLC*/ +0xa000, /* 20100309*/ +0xa200, /* 20100309*/ +0xa400, /* 20100309*/ +0xa600, /* 20100309*/ + +/*Normal BLC*/ +0xa800, +0xaa00, +0xac00, +0xae00, + +/*Out BLC*/ +0x9900, +0x9a00, +0x9b00, +0x9c00, + +/*2 Page*/ +0x0302, +0x1200, /*Don't touch*/ +0x1400, /*Don't touch*/ +0x1500, /*Don't touch*/ +0x184C, /*Don't touch*/ +0x1900, /*Don't touch*/ +0x1A39, /*Don't touch*/ +0x1B00,/*Don't touch*/ +0x1C1a, /*Don't touch*/ +0x1D14, /*Don't touch*/ +0x1E30,/*Don't touch*/ +0x1F10,/*Don't touch*/ + +0x2077, +0x21de, +0x22a7, +0x2330, +0x2477, +0x2510, +0x2610, +0x273c, +0x2b80, +0x2c02, +0x2da0, +0x2e00, +0x2fa7, + +0x3000, +0x3199, +0x3200, +0x3300, +0x3422, +0x3601, +0x3701, +0x3888, +0x3988, +0x3d03, +0x3e0d, +0x3f02, + +0x49d1, +0x4a14, + +0x5021, +0x5201, +0x5381, +0x5410, +0x551c, +0x5611, +0x5818, +0x5916, +0x5da2, +0x5e5a, + +0x6093, /* 20120517 modify*/ +0x61a4, /* 20120517 modify*/ +0x6294, /* 20120517 modify*/ +0x63a3, /* 20120517 modify*/ +0x6494, /* 20120517 modify*/ +0x65a3, /* 20120517 modify*/ +0x670c, +0x680c, +0x690c, +0x6ab4, +0x6bc4, +0x6cb5, +0x6dc2, +0x6eb5, +0x6fc0, + +0x70b6, +0x71b8, +0x7295, /* 20120517 modify*/ +0x73a2, /* 20120517 modify*/ +0x7495, /* 20120517 modify*/ +0x75a2, /* 20120517 modify*/ +0x7695, /* 20120517 modify*/ +0x77a2, /* 20120517 modify*/ +0x7C92, /* 20120517 modify*/ +0x7Dff, /* 20120517 modify*/ + +0x8001, /* 20120517 modify*/ +0x818a, /* 20120517 modify*/ +0x821e, /* 20120517 modify*/ +0x8336, /* 20120517 modify*/ +0x8489, /* 20120517 modify*/ +0x858b, /* 20120517 modify*/ +0x8689, /* 20120517 modify*/ +0x878b, /* 20120517 modify*/ +0x88ab, +0x89bc, +0x8aac, +0x8bba, +0x8cad, +0x8db8, +0x8eae, +0x8fb2, + +0x90b3, +0x91b7, +0x9252, /* 20120517 modify*/ +0x936a, /* 20120517 modify*/ +0x9489, /* 20120517 modify*/ +0x958b, /* 20120517 modify*/ +0x9689, /* 20120517 modify*/ +0x978b, /* 20120517 modify*/ + +0xA002, +0xA186, /* 20120517 modify*/ +0xA202, +0xA386, /* 20120517 modify*/ +0xA486, /* 20120517 modify*/ +0xA502, +0xA686, /* 20120517 modify*/ +0xA702, +0xA892, /* 20120517 modify*/ +0xA994, /* 20120517 modify*/ +0xAA92, /* 20120517 modify*/ +0xAB94, /* 20120517 modify*/ +0xAC1c, +0xAD22, +0xAE1c, +0xAF22, + +0xB0a4, /* 20120517 modify*/ +0xB1ae, /* 20120517 modify*/ +0xB2a4, /* 20120517 modify*/ +0xB3ae, /* 20120517 modify*/ +0xB4a6, /* 20120517 modify*/ +0xB5ac, /* 20120517 modify*/ +0xB6a6, /* 20120517 modify*/ +0xB7ac, /* 20120517 modify*/ +0xB8a6, /* 20120517 modify*/ +0xB9ab, /* 20120517 modify*/ +0xBAa6, /* 20120517 modify*/ +0xBBab, /* 20120517 modify*/ +0xBCa6, /* 20120517 modify*/ +0xBDab, /* 20120517 modify*/ +0xBEa6, /* 20120517 modify*/ +0xBFab, /* 20120517 modify*/ + +0xc437, +0xc552, +0xc66b, +0xc786, +0xc838, /* 20120517 modify*/ +0xc950, /* 20120517 modify*/ +0xca38, /* 20120517 modify*/ +0xcb50, /* 20120517 modify*/ +0xcc6c, /* 20120517 modify*/ +0xcd84, /* 20120517 modify*/ +0xce6c, /* 20120517 modify*/ +0xcf84, /* 20120517 modify*/ + +/*0xd4a6,*/ +/*0xd5ac,*/ +/*0xd6a6,*/ +/*0xd7ac,*/ +/*add 20120517*/ +0xdc00, /* Added*/ +0xddaf, /* Added*/ +0xde00, /* Added*/ +0xdf90, /* Added*/ + +0xd010, +0xd114, +0xd220, +0xd300, +/*DCDC */ +0xd40c, /*DCDC_TIME_TH_ON*/ +0xd50c, /*DCDC_TIME_TH_OFF */ +0xd6f7, /*DCDC_AG_TH_ON*/ +0xd7ef, /*DCDC_AG_TH_OFF*/ + +0xea8a, + +0xF001, /* clock inversion*/ +0xF101, +0xF201, +0xF301, +0xF401, +0xF500, + +/*----------------------------------------------*/ +0x0310, /*page 10*/ +0x1001, /*Ycbcr422_bit Order: YUYV*/ +0x1103, +0x1230, /*y offset[4], dif_offset[5]*/ +0x1302, /*contrast effet enable : 0x02*/ +0x3400, /*hidden 10->00 100209*/ +0x3701, /*yc2d power save */ +0x3f04, /*100825*/ +0x4080, /*Y offset */ +0x4128, +0x4880, +0x5300, /*dif_offset option */ +0x5530, /*dif_offset option diff_offset max */ + +0x606b, /*out color sat en[7] | auto color decrement en[1] / + | manual color sat en[0]*/ + +0x6183, /*blue saturation_C0*/ +0x6280, /*red saturation_B0*/ + +0x63b0, /*auto decresment on AG th*/ +0x64ff, /*auto decresment on DG th*/ +0x66e4, /*Outdoor saturation step 137fps apply out th */ +0x6700, /*Outdoor saturation B/R*/ +0x7601, /* ADD 20121031 */ +0x7904, /* ADD 20121031 */ + +/* Hi 163 */ +/* PAGE 10 START*/ +0x0310, +0x8000, /* dsshin --> color enhance*/ +0xf500, /* dsshin --> h blank option*/ + +0x0311, /*page 11 D_LPF */ +0x103f, /*B[6]:Blue En Dlpf on[4:0] Sky over off : 0x7f->3f*/ +0x1120, /* Uniform Full GbGr/OV-Nr*/ + +0x1280, /*Blue MaxOpt blue sky max filter optoin rate : 0 0xc0->80*/ +0x13b8, /*dark2[7] | ratio[6:4] | dark3[3] | dark3 maxfilter ratio[2:0] */ + +0x30ba, /*Outdoor2 H th*/ +0x3110, /*Outdoor2 L th*/ +0x3250, /*Outdoor2 gain ratio*/ +0x331d, /*Outdoor2 H lum*/ +0x3420, /*Outdoor2 M lum*/ +0x351f, /*Outdoor2 L lum*/ + +0x36b0, /*Outdoor1 H th*/ +0x3718, /*Outdoor1 L th*/ +0x3850, /*Outdoor1 gain ratio 0x80->40*/ +0x391d, /*Outdoor1 H lum 0x28->1e*/ +0x3a20, /*Outdoor1 M lum 0x10->15*/ +0x3b1f, /*Outdoor1 L lum 0x08->20*/ + +0x3c3f, /*indoor H th*/ +0x3d16, /*indoor L th*/ +0x3e30, /*indoor gain ratio 0x44 6a */ +0x3f1a, /*indoor H lum 0x12 18 */ +0x4060, /*indoor M lum 0x18 1c*/ +0x411a, /*indoor L lum 0x18 3e*/ + +0x4280, /*dark1 H th*/ +0x4318, /*dark1 L th*/ +0x4480, /*dark1 gain ratio*/ +0x450f, /*dark1 H lum 0x38->0x28 */ +0x460c, /*dark1 M lum 0x27->0x17*/ +0x470b, /*dark1 L lum 0x20->0x1a */ + +0x4880, /*dark2 H th*/ +0x4918, /*dark2 L th*/ +0x4a80, /*dark2 gain ratio*/ +0x4b0f, /*dark2 H lum */ +0x4c0c, /*dark2 M lum*/ +0x4d0b, /*dark2 L lum */ + +0x4e80, /*dark3 H th*/ +0x4f23, /*dark3 L th*/ +0x5080, /*dark3 gain ratio*/ +0x511d, /*dark3 H lum */ +0x521f, /*dark3 M lum */ +0x531f, /*dark3 L lum */ + +0x5a3f, /*blue sky mode out1/2 enable 0x27->3f */ +0x5b00, /*Impulse pixel enable dark123,in,out123 :: must be 0x07*/ +0x5c9f, /*Indoor maxfilter rate[7:5] | Uncertain onoff[4:0] 0x1f ->0x9f*/ + +0x603f, /*GbGr all enable*/ +0x620f, /*GbGr offset*/ + +0x650c, /*Outdoor GbGr rate H 100% M 25% L 100%*/ +0x660c, /*Indoor GbGr rate H 100% M 25% L 100%*/ +0x6700, /*dark GbGr rate H/M/L 100%*/ + +0x700c, /* Abberation On/Off B[1]: Outdoor B[0]: Indoor 07>>c*/ +0x75a0, /* Outdoor2 Abberation Luminance lvl */ +0x7db4, /* Indoor Abberation Luminance lvl*/ + +0x9608, /*indoor/Dark1 edgeoffset1*/ +0x9714, /*indoor/Dark1 center G value*/ +0x98f5, /*slope indoor :: left/right graph polarity, slope*/ +0x992a, /*indoor uncertain ratio control*/ +0x9a20, /*Edgeoffset_dark*/ + +/*DPC_CTRL*/ +0x0312, /*Preview DPC off[0x5c] on[0x5d]*/ +0x200f, +0x210f, + +0x2500, /* 0x30*/ + +0x2a01, +0x2e00, /*2010.8.25*/ + +0x3035, /*Texture region(most detail)*/ +0x31a0, /*STD uniform1 most blur region*/ +0x32b0, /*STD uniform2 2nd blur*/ +0x33c0, /*STD uniform3 3rd blur*/ +0x34d0, /*STD normal noise1 4th blur */ +0x35e0, /*STD normal noise2 5th blur*/ +0x36ff, /*STD normal noise3 6th blur*/ + +0x4083, /*Outdoor2 H th*/ +0x4120, /*Outdoor2 L th */ +0x4208, /*Outdoor2 H luminance */ +0x4310, /*Outdoor2 M luminance */ +0x4410, /*Outdoor2 l luminance */ +0x4550, /*Outdoor2 ratio*/ + +0x4683, /*Outdoor1 H th*/ +0x4720, /*Outdoor1 L th */ +0x4808, /*Outdoor1 H luminance*/ +0x4910, /*Outdoor1 M luminance*/ +0x4a10, /*Outdoor1 L luminance*/ +0x4b50, /*Outdoor1 ratio*/ + +0x4c80, /*Indoor H th*/ +0x4d48, /*Indoor L th*/ +0x4e30, /*indoor H lum*/ +0x4f30, /*indoor M lum*/ +0x5012, /*indoor L lum */ +0x5170, /*indoor ratio 0x10 -> 0x45*/ + +0x52a8, /*dark1 H th*/ +0x5330, /*dark1 L th */ +0x5428, /*dark1 H lum */ +0x553e, /*dark1 M lum*/ +0x5667, /*dark1 L lum*/ +0x576a, /*dark1 ratio*/ + +0x58a0, /*dark2 H th*/ +0x5940, /*dark2 L th*/ +0x5a28, /*dark2 H lum*/ +0x5b3f, /*dark2 M lum*/ +0x5c68, /*dark2 L lum*/ +0x5d70, /*dark2 ratio*/ + +0x5ea0, /*dark3 H th*/ +0x5f1c, /*dark3 L th*/ +0x6029, /*dark3 H lum*/ +0x614a, /*dark3 M lum*/ +0x62ff, /*dark3 L lum*/ +0x63ff, /*dark3 ratio*/ + +/*C-filter(Out2&Out1)*/ +0x7010, +0x710a, + +/*C-filter(Indoor&Dark3)*/ +0x7210, +0x730a, + +/*C-filter(Dark2&Dark1)*/ +0x7418, +0x7512, + +0x8020, +0x8140, +0x8265, +0x851a, +0x8800, +0x8900, +0x905d, /*Preview DPC off[0x5c] on[0x5d]*/ + +/*DPC-Dark1,2,3*/ +0xad07, /*10825*/ +0xae07, /*10825*/ +0xaf07, /*10825*/ + +/*Blue Det..*/ +0xc558, /*BlueRange 2010.8.25 0x40->23 */ +0xc620, /*GreenRange 2010.8.25 0x3b->20 */ + +0xd088, /*2010.8.25*/ +0xd180, +0xd217,/*preview 17, full 67*/ +0xd300, +0xd400, +0xd50f,/*preview 0f, full 02*/ +0xd6ff, +0xd7ff,/*preview ff, full 18*/ +0xd800, +0xd904, + +/*interpolated with average*/ +0xdb38, /*resolution issue 0x00->0x18->0x38 */ +0xd904, /*strong_edge detect ratio*/ +0xe001, /*strong_edge detect ratio*/ + +0x0313, /*page 13 sharpness 1D*/ +0x10c5, +0x117b, +0x120e, +0x1400, + +0x1511, /*added option 1.3M*/ +0x1830, /*added option 1.3M*/ + +0x2015, +0x2113, +0x2233, +0x2308, /*hi_clip th1*/ +0x241a, /*hi_clip th2*/ +0x2506, /*low clip th*/ + +0x2618, +0x2730, +0x2910, /*time th*/ +0x2a30, /*pga th*/ + +0x2b03, /*lpf out2*/ +0x2c03, /*lpf out1*/ +0x2d0c, +0x2e12, +0x2f12, + +/*1D Edge*/ +0x500a, /*out2 hi nega*/ +0x5307, /* hi pos*/ +0x510c, /* mi nega*/ +0x5407, /* mi pos*/ +0x520b, /* lo nega*/ +0x5508, /* lo pos*/ + +0x560a, /*out1 hi nega*/ +0x5907, /* hi pos */ +0x570c, /* mi nega*/ +0x5a07, /* mi pos */ +0x580b, /* lo nega*/ +0x5b08, /* lo pos */ + +/*Indoor Edge*/ +0x5c08, /*indoor hi nega*/ +0x5f07, /* hi pos*/ +0x5d14, +0x6012, +0x5e0a, +0x6108, /* low pos*/ + +0x6208, /*dark1 hi nega*/ +0x6506, /* hi pos */ +0x6308, /* mid nega */ +0x6606, /* mid pos */ +0x6408, /* low nega */ +0x6706, /* low pos */ + +0x6807, /*dark2 hi nega*/ +0x6b05, /* hi pos */ +0x6907, /* mid nega */ +0x6c05, /* mid pos */ +0x6a07, /* low nega */ +0x6d05, /* low pos */ + +0x6e0a, /*dark3 hi nega*/ +0x7109, /* hi pos */ +0x6f0d, /* mid nega */ +0x720c, /* mid pos */ +0x700d, /* low nega */ +0x730c, /* low pos */ + + /* 2DY*/ +0x80c1, +0x811f, +0x82e1, +0x8333, + +0x9005, +0x9105, +0x9233, +0x9330, +0x9403, +0x9514, +0x9730, +0x9930, + +0xa002, /*2d lclp out2 nega*/ +0xa103, /*2d lclp out2 pos*/ +0xa202, /*2d lclp out1 nega*/ +0xa303, /*2d lclp out1 pos*/ +0xa403, /*2d lclp in nega*/ +0xa504, /*2d lclp in pos*/ +0xa607, /*2d lclp dark1 nega*/ +0xa708, /*2d lclp dark1 pos*/ +0xa807, /*2d lclp dark2 nega*/ +0xa908, /*2d lclp dark2 pos*/ +0xaa07, /*2d lclp dark3 nega*/ +0xab08, /*2d lclp dark3 pos*/ + +0xb010, /*out2 H Ne*/ +0xb310, /* H Po*/ +0xb11e, /* M Ne*/ +0xb41e, /* M Po*/ +0xb21f, /* L Ne*/ +0xb51e, /* L Po*/ + +0xb610, /*out1 H Ne */ +0xb910, /* H Po */ +0xb71e, /* M Ne */ +0xba1e, /* M Po */ +0xb81f, /* L Ne */ +0xbb1e, /* L Po */ + +0xbc20, /*indoor H Ne*/ +0xbf1e, /* H Po*/ +0xbd25, /* M Ne*/ +0xc023, /* M Po*/ +0xbe24, /* L Ne*/ +0xc122, /* L Po*/ + +0xc223, /*dark1 H Ne*/ +0xc523, /* H Po*/ +0xc329, /* M Ne*/ +0xc629, /* M Po*/ +0xc425, /* L Ne*/ +0xc725, /* L Po*/ + +0xc81c, /*dark2 H Ne*/ +0xcb1c, /* H Po*/ +0xc925, /* M Ne*/ +0xcc25, /* M Po*/ +0xca23, /* L Ne*/ +0xcd23, /* L Po*/ + +0xce1c, /*dark3 H Ne*/ +0xd11c, /* H Po*/ +0xcf29, /* M Ne*/ +0xd229, /* M Po*/ +0xd027, /* L Ne*/ +0xd327, /* L Po*/ + +/* PAGE 14 START*/ +0x0314, +0x1031, + +0x1480, /* GX*/ +0x1580, /* GY*/ +0x1680, /* RX*/ +0x1780, /* RY*/ +0x1880, /* BX*/ +0x1980, /* BY*/ + +0x2060, /* X Center*/ +0x2180, /* Y Center*/ + +0x2280, +0x2380, +0x2480, + +0x30c8, +0x312b, +0x3200, +0x3300, +0x3490, + +0x4056, /*R min's set 4e*/ +0x413a, /*Gr*/ +0x4237, /*B*/ +0x433a, /*Gb*/ + +0x0315, +0x1021, +0x1444, /*49*/ +0x1534, /*38*/ +0x1626, /*2b*/ +0x172f, + +0x30dd, +0x3162, +0x3205, +0x3326, +0x34bd, +0x3517, +0x3618, +0x3738, +0x38d0, + +0x40b0, +0x4130, +0x4200, +0x4300, +0x4400, +0x4500, +0x4699, +0x4719, +0x4800, + +0x5016, +0x51b2, +0x521c, +0x5306, +0x5420, +0x55a6, +0x560e, +0x57b2, +0x5824, + +0x0316, +0x1031, /*GMA_CTL*/ +0x187e, /*AG_ON*/ +0x197d, /*AG_OFF*/ +0x1a0e, /*TIME_ON*/ +0x1b01, /*TIME_OFF*/ +0x1Cdc, /*OUT_ON*/ +0x1Dfe, /*OUT_OFF*/ + +/*GMA Indoor*/ +0x3000, +0x3126, +0x3238, +0x3355, +0x347e, +0x3597, +0x36a9, +0x37ba, +0x38c7, +0x39d2, +0x3adb, +0x3be3, +0x3cea, +0x3dee, +0x3ef5, +0x3ff9, +0x40fc, +0x41fe, +0x42ff, + +/*RGMA Outdoor*/ +0x5000, +0x5126, +0x5238, +0x5355, +0x547e, +0x5597, +0x56a9, +0x57ba, +0x58c7, +0x59d2, +0x5adb, +0x5be3, +0x5cea, +0x5dee, +0x5ef5, +0x5ff9, +0x60fc, +0x61fe, +0x62ff, + +/*BGMA Dark*/ +0x7002, +0x712a, +0x723b, +0x7359, +0x7481, +0x759b, +0x76ac, +0x77be, +0x78ca, +0x79d4, +0x7adb, +0x7be4, +0x7ceb, +0x7def, +0x7ef6, +0x7ffa, +0x80fc, +0x81fe, +0x82ff, + +0x0324, /*Resol control */ +0x60c5, /*edge even frame | 16bit resol | white edge cnt | scene resol enable*/ +0x6104, /*even frame update */ +0x6408, +0x6500, +0x6626, /*edge th2 H */ +0x6700, /*edge th2 L */ + +0x0313, +0x1831, /*flat center Gb/Gr*/ +0x7402, /*det slope en | gausian filter*/ +0x750d, /*1D negative gain det 09 */ +0x760d, /*1D postive gain det 08*/ +0x7710, /*1D hclp2 det*/ +0x7808, /*outdoor flat threshold*/ +0x7910, /*indoor flat threshold*/ + +0x81df, /*det gain controler*/ +0x8690, /*2D negative gain det */ +0x8790, /*2D postive gain det */ +0x962a, /*2D hclp2 det*/ + +0x0312, /*0x12 page*/ +0xd088, +0xd9e4, + +/* PAGE 18 START*/ +0x0318, +0x1400, + +/* PAGE 20 START*/ +0x0320, +0x111c, +0x1830, +0x1a08, +0x2045,/*weight*/ +0x2130, +0x2210, +0x2300, +0x2400, + +0x28e7, /* add 20120223*/ +0x290d, /* 20100305 ad -> 0d*/ +0x2afd, +0x2bf8, + +0x2cc3, +0x2d5f, /* add 20120223*/ +0x2e33, +0x30f8, +0x3203, +0x332e, +0x3430, +0x35d4, +0x36ff, /*fe*/ +0x3732, +0x3804, +0x3922, +0x3ade, +0x3b22, +0x3cde, +0x3de1, + +0x5045, +0x5188, + +0x561a, +0x5780, +0x580e, +0x596a, +0x5a04, + +0x5e9d, /*AE_AWB_start*/ +0x5f76, /*AE_AWB_start*/ + +0x703f, /* 6c*/ +0x7180, /* 82(+8)*/ + +0x7621, +0x7781, +0x7822, /* 24*/ +0x7925, /* Y Target 70 => 25, 72 => 26*/ +0x7a23, /* 23*/ +0x7b22, /* 22*/ +0x7d23, + +0x8301, /*EXP Normal 30.00 fps */ +0x845f, +0x8590, +0x8601, /*EXPMin 7500.00 fps*/ +0x8790, +0x8805, /*EXP Max(120Hz) 8.00 fps */ +0x89b8, +0x8ad8, +0xa505, /*EXP Max(100Hz) 8.33 fps */ +0xa67e, +0xa740, +0x8B75, /*EXP100 */ +0x8C30, +0x8D61, /*EXP120 */ +0x8Ea8, +0x9c09, /*EXP Limit 1250.00 fps */ +0x9d60, +0x9e01, /*EXP Unit */ +0x9f90, +0x989d, + +0xb016, +0xb114, +0xb2f0, +0xb314, +0xb41b, +0xb546, +0xb631, +0xb729, +0xb826, +0xb924, +0xba22, +0xbb42, +0xbc41, +0xbd40, + +0xc010, +0xc138, +0xc238, +0xc338, +0xc407, + +0xc880, +0xc980, +0x109c, /* ae enable*/ +/* PAGE 20 END*/ + +/*AE_Weight*/ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2422, +0x2522, +0x2622, +0x2721, +0x2823, +0x2933, +0x2a32, +0x2b21, +0x2c23, +0x2d44, +0x2e32, +0x2f21, +0x3023, +0x3144, +0x3232, +0x3311, +0x3423, +0x3533, +0x3632, +0x3721, +0x3822, +0x3922, +0x3a22, +0x3b21, +0x3c11, +0x3d11, +0x3e11, +0x3f11, + +/* PAGE 22 START*/ +0x0322, +0x10fd, +0x112e, +0x1901, /* Low On*/ +0x2030, /* for wb speed*/ +0x2140, +0x2401, +0x257e, /* for tracking 20120314 */ + +0x3080, /* 20120224 test*/ +0x3180, +0x3811, +0x3934, + +0x40e8, +0x4143, /* 33*/ +0x4222, /* 22*/ + +0x43f3, /* f6*/ +0x4454, /* 44*/ +0x4522, /* 33*/ + +0x4600, +0x480a, +0x50b2, +0x5181, +0x5298, + +0x8038, +0x8120, +0x8238, /* 3a*/ + +0x8356, /* R Max*/ +0x8420, /* R Min*/ +0x8552, /* B Max*/ +0x8620, /* B Min*/ + +0x8746, +0x8836, +0x8939, +0x8a2d, + +0x8b3c, +0x8c36, +0x8d34, +0x8e31, + +0x8f5a, +0x9059, +0x9154, +0x924d, +0x9342, +0x943a, +0x9534, +0x962c, +0x9723, +0x9820, +0x991f, +0x9a1f, + +0x9b77, +0x9c77, +0x9d48, +0x9e38, +0x9f30, + +0xa040, +0xa122, +0xa26f, +0xa3ff, + +0xa414, /* 1500fps*/ +0xa544, /* 700fps*/ +0xa6cf, + +0xad40, +0xae4a, + +0xaf2a, /* low temp Rgain*/ +0xb028, /* low temp Rgain*/ + +0xb100, /* 0x20 -> 0x00 0405 modify*/ +0xb4bf, /* for tracking 20120314*/ +0xb8a1, /* a2: b-2, R+2 b4 B-3, R+4 lowtemp b0 a1 Spec AWB A modify*/ +0xb900, +/* PAGE 22 END*/ + +/* PAGE 48 (MiPi 1600x1200)*/ +0x0300, + +/* PLL Setting */ +0xd005, +0xd130, +0xd205, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x0348, +/* MIPI TX Setting */ +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +0x1d0e, +0x1e07, +0x1f08, + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2b40,*/ + +0x3005, +0x3100, + +0x3207, +0x3309, +0x3401, +0x3501, + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_stop_stream[] = { +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t SR130PC20_Preview_Mode[] = +{ +0x0300, +0x0101,/*sleep*/ + +0xd005,/*Pll Off*/ + +0x0320, +0x101c,/*AE off (0x0c:60Hz 0x1c:50Hz)*/ +0x0322, +0x107d,/*AWB off*/ + +0x0300, +0x1011, +/* 0x1190, *//*0x91 : mirror mode*/ + +/* page 11 yc_lpf */ +0x0311, +0x5b00,/*don't touch*/ + +/* PAGE 12 YC_LPF */ +0x0312, +0x200f, +0x210f, + +/*preview DPC*/ +0xd217, +0xd50f, +0xd7ff, + + +/* PAGE13 Sharpness 1D/2D */ +0x0313, +0x10c4, +0x80c0, + +/* PAGE 18 START*/ +0x0318, +0x1443, /*83*/ + +0x0320, +0x109c, /*AE ON (0x8c:60Hz 0x9c:50Hz)*/ +0x0322, +0x10fd, /*AWB ON*/ + +0x0300, /*Page 0 PLL on*/ +0xd005, +0xd130, +0xd205, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +/* MIPI TX Setting */ +0x0348, +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +/*0x1d09,*/ +0x1d0e, +0x1e07, +0x1f08, +/*0x2000,*/ + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2a06,*/ +/*0x2b40,*/ +/*0x2c04,*/ +/*0x2db0,*/ + +0x3005, +0x3100, + +0x3207, +0x3309, +0x3401, +0x3501, +/*0x3601,*/ +/*0x3707,*/ +/*0x3802,*/ +/*0x3902,*/ + +0x0300, +0x0100, + +}; + +static const sr130pc20_regset_t SR130PC20_Capture_Mode[] = +{ +0x0300, +0x0101,/*sleep*/ + +0xd005,/*Pll off*/ + +0x0322, +0x107d,/*AWB off*/ + +0x0300, +0x1000, +/* 0x1190, */ + +0x0302, +0x2faa, + +0x0311, +0x5b00,/*don't touch*/ + +0x0312, +0x200f, +0x210f, + +/*preview DPC*/ +0xd267, +0xd502, +0xd718, + +0x0313, +0x10c5, +0x80c1,/*Sharpness 2D On[0xc1] Off[0xc0]*/ + +/* PAGE 18 START*/ +0x0318, +0x1400, + +0x0300, +0xd005,/*pll on*/ +0xd130, +0xd201, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x0348, +/* MIPI TX Setting */ +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +0x1d0d, /* 0c:90ns , 0b:110ns */ +0x1e0f, +0x1f0a, +/*0x2000,*/ + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2a06,*/ +/*0x2b40,*/ +/*0x2c04,*/ +/*0x2db0,*/ + +0x300a, +0x3100, + +0x320d, +0x330b, +0x3402, +0x3504, +0x3601, +0x3709, +/*0x3802,*/ +/*0x3902,*/ + +0x0300, +0x0100,/*sleep off*/ + +}; + +static const sr130pc20_regset_t SR130PC20_Lowlux_Night_Capture_Mode[] = +{ +0x0300, +0x0101,/*sleep*/ + +0xd005,/*Pll off*/ + +0x0322, +0x107d,/*AWB off*/ + +0x0300, +0x1000, +/* 0x1190, */ + +0x0302, +0x2faa, + +0x0311, +0x5b00,/*don't touch*/ + +0x0312, +0x200f, +0x210f, + +/*preview DPC*/ +0xd267, +0xd502, +0xd718, + +0x0313, +0x10c5, +0x80c1,/*Sharpness 2D On[0xc1] Off[0xc0]*/ + +/* PAGE 18 START*/ +0x0318, +0x1400, + +0x0300, +0xd005,/*pll on*/ +0xd130, +0xd201, +0xd320, +0xd085, +0xd085, +0xd085, +0xd095, + +0x0348, +/* MIPI TX Setting */ +0x101c, +0x1100, +0x1200, +0x1400, +0x1604, +0x1700, +0x1880, +0x1900, +0x1aa0, +/*0x1b0d,*/ +0x1c02, +0x1d0d, /* 0c:90ns , 0b:110ns */ +0x1e0f, +0x1f0a, +/*0x2000,*/ + +0x2200, +0x2301, +0x241e, +0x2500, +0x2600, +0x2708, +0x2800, +/*0x2a06,*/ +/*0x2b40,*/ +/*0x2c04,*/ +/*0x2db0,*/ + +0x300a, +0x3100, + +0x320d, +0x330b, +0x3402, +0x3504, +0x3601, +0x3709, +/*0x3802,*/ +/*0x3902,*/ + +0x0300, +0x0100,/*sleep off*/ + +0xff03, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Sketch[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Pastel[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Black_White[] = +{ +0x0310, +0x1103, +0x1233, +0x1302, +0x4080, +0x4480, +0x4580, +}; + +static const sr130pc20_regset_t SR130PC20_Effect_Negative[] = +{ +0x0310, +0x1103, +0x1238, +0x1302, +0x4080, +0x4480, +0x4580, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Solar[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Normal[] = +{ +0x0310, +0x1103, +0x1230, +0x1302, +0x4080, +0x4480, +0x4580, +}; + +static const sr130pc20_regset_t sr130pc20_Effect_Sepia[] = +{ +0x0310, +0x1103, +0x1233, +0x1302, +0x4080, +0x4470, +0x4598, +}; + +static const sr130pc20_regset_t sr130pc20_Metering_Center[] = +{ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2412, +0x2522, +0x2622, +0x2721, +0x2812, +0x2922, +0x2a22, +0x2b21, +0x2c12, +0x2d23, +0x2e32, +0x2f21, +0x3012, +0x3123, +0x3232, +0x3321, +0x3412, +0x3522, +0x3622, +0x3721, +0x3812, +0x3922, +0x3a22, +0x3b21, +0x3c11, +0x3d11, +0x3e11, +0x3f11, +}; + +static const sr130pc20_regset_t sr130pc20_Metering_Matrix[] = +{ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2411, +0x2511, +0x2611, +0x2711, +0x2811, +0x2911, +0x2a11, +0x2b11, +0x2c11, +0x2d11, +0x2e11, +0x2f11, +0x3011, +0x3111, +0x3211, +0x3311, +0x3411, +0x3511, +0x3611, +0x3711, +0x3811, +0x3911, +0x3a11, +0x3b11, +0x3c11, +0x3d11, +0x3e11, +0x3f11, +}; + +static const sr130pc20_regset_t sr130pc20_Metering_Spot[] = +{ +0x0321, +0x2011, +0x2111, +0x2211, +0x2311, +0x2411, +0x2511, +0x2611, +0x2711, +0x2811, +0x2911, +0x2a11, +0x2b11, +0x2c11, +0x2d13, +0x2e31, +0x2f11, +0x3011, +0x3113, +0x3231, +0x3311, +0x3411, +0x3511, +0x3611, +0x3711, +0x3811, +0x3911, +0x3a11, +0x3b11, +0x3c11, +0x3d11, +0x3e11, +0x3f11, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_Default[] = +{ +0x0310, +0x4080, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_M1Step[] = +{ +0x0310, +0x4090, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_M2Step[] = +{ +0x0310, +0x40A0, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_M3Step[] = +{ +0x0310, +0x40B0, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_M4Step[] = +{ +0x0310, +0x40d0, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_P1Step[] = +{ +0x0310, +0x4010, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_P2Step[] = +{ +0x0310, +0x4020, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_P3Step[] = +{ +0x0310, +0x4030, +}; + +static const sr130pc20_regset_t SR130PC20_ExpSetting_P4Step[] = +{ +0x0310, +0x4050, +}; + +static const sr130pc20_regset_t sr130pc20_ISO_50[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_ISO_100[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_ISO_200[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_ISO_400[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_ISO_Auto[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Default[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Landscape[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Sports[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Party_Indoor[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Beach_Snow[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Sunset[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Duskdawn[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Candle_Light[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Fall_Color[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Portrait[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Nightshot[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Fireworks[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Text[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Scene_Backlight[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_Sharpness_Default[] = +{ +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_WB_Auto[] = +{ +0x0322, +0x106b, +0x112e, +0x8038, +0x8120, +0x8238, +0x8356, +0x8420, +0x8552, +0x8620, +0x10eb, +}; + +static const sr130pc20_regset_t sr130pc20_WB_Cloudy[] = +{ +0x0322, +0x106b, +0x112c, +0x8050, +0x8120, +0x8228, +0x8352, +0x844c, +0x852c, +0x8622, +0x10eb, +}; + +static const sr130pc20_regset_t sr130pc20_WB_Sunny[] = +{ +0x0322, +0x106b, +0x112c, +0x8038, +0x8120, +0x8235, +0x833b, +0x8434, +0x8538, +0x8631, +0x10eb, +}; + +static const sr130pc20_regset_t sr130pc20_WB_Fluorescent[] = +{ +0x0322, +0x106b, +0x112c, +0x8037, +0x8120, +0x8248, +0x8339, +0x8434, +0x854a, +0x8645, +0x10eb, +}; + +static const sr130pc20_regset_t sr130pc20_WB_Tungsten[] = +{ +0x0322, +0x106b, +0x112c, +0x8021, +0x8120, +0x824f, +0x8327, +0x841b, +0x8559, +0x8650, +0x10eb, +}; + +static const sr130pc20_regset_t sr130pc20_640_480_Preview[] = { +0x0300, +0x0101, + +0x0300, +0x1011, + +0x0318, +0x1000, + +0x0348, +0x3005, +0x3100, + +0x0300, +0x0100, + +0xff0a, +}; + +static const sr130pc20_regset_t sr130pc20_352_288_Preview[] = { +0x0300, +0x0101, +0x0300, +0x1011, + +0x0318, +0x1007, +0x1200, +0x2003, +0x2100, +0x2201, +0x2320, +0x2400, +0x2520, +0x2600, +0x2700, +0x2802, +0x29e0, +0x2a01, +0x2b20, +0x2c0d, +0x2d55, +0x2e0d, +0x2f55, +0x3051, + +0x0348, +0x3002, +0x31c0, + +0x0300, +0x0100, + +0xff28, +}; + +static const sr130pc20_regset_t sr130pc20_320_240_Preview[] = { +0x0300, +0x0101, + +0x0300, +0x1023, + +0x0318, +0x1000, + +0x0348, +0x3002, +0x3180, + +0x0300, +0x0100, + +0xff28, +}; + +static const sr130pc20_regset_t sr130pc20_176_144_Preview[] = { +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_1280_960_Capture[] = { +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_960_720_Capture[] = { +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_VGA_Capture[] = { +0xff00 +}; + +static const sr130pc20_regset_t sr130pc20_fps_auto[] = { +0xff00, +}; + +static const sr130pc20_regset_t sr130pc20_fps_7fix[] = { +0x0300, +0x0101, + +0x1190, + +0x4200, +0x4314, + +0x0320, +0x101C, + +0x0322, +0x107d, + +0x0320, +0x2af3, +0x2bf5, + +0x8301, /*EXP Normal 33.33 fps */ +0x845f, +0x8590, + +0x8806, /*EXP Max(120Hz) 7.50 fps */ +0x8968, +0x8aa0, + +0xa506, /*EXP Max(100Hz) 7.14 fps */ +0xa668, +0xa7a0, + +0x9106, /*EXP Fix 7.00 fps*/ +0x9289, +0x9370, + +0x0320, +0x109C, + +0x0322, +0x10fd, + +0x0300, +0x1194, + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_fps_15fix[] = { +0x0300, +0x0101, + +0x1190, + +0x4200, +0x4314, + +0x0320, +0x101C, + +0x0322, +0x107d, + +0x0310, /*page 10*/ +0x6007, +0x6380, /*auto decresment on AG th*/ + +0x0316, +0x7007, +0x711a, +0x722d, +0x7346, +0x746a, +0x7586, +0x769c, +0x77ad, +0x78bc, +0x79c9, +0x7ad4, +0x7bde, +0x7ce4, +0x7deb, +0x7ef1, +0x7ff5, +0x80f9, +0x81fd, +0x82ff, + +0x0322, +0x8f5d, +0x905a, +0x9156, +0x9250, +0x9348, +0x943f, + +0x0320, +0x2afd, +0x2bf8, + +0x8301, /*EXP Normal 33.33 fps */ +0x845f, +0x8590, + +0x8802, /*EXP Max(120Hz) 17.14 fps */ +0x89bf, +0x8a20, + +0xa502, /*EXP Max(100Hz) 16.67 fps */ +0xa6bf, +0xa720, + +0x9103, /*EXP Fix 15.00 fps*/ +0x920d, +0x9340, + +0x0320, +0x109C, + +0x0322, +0x10fd, + +0x0300, +0x1194, + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_fps_25fix[] = { +0x0300, +0x0101, + +0x1190, + +0x4200, +0x4362, + +0x0320, +0x101C, + +0x0322, +0x107d, + +0x0310, /*page 10*/ + +0x410a, +0x6007, +0x6380, /*auto decresment on AG th*/ + +0x0316, +0x7007, +0x711a, +0x722d, +0x7346, +0x746a, +0x7586, +0x769c, +0x77ad, +0x78bc, +0x79c9, +0x7ad4, +0x7bde, +0x7ce4, +0x7deb, +0x7ef1, +0x7ff5, +0x80f9, +0x81fd, +0x82ff, + +0x0322, +0x8f5d, +0x905a, +0x9156, +0x9250, +0x9348, +0x943f, + +0x0320, +0x2afd, +0x2bf8, + +0x8301, /*EXP Normal 33.33 fps */ +0x845d, +0x8538, + +0x8801, /*EXP Max(120Hz) 40.00 fps */ +0x895f, +0x8a90, + +0xa501, /*EXP Max(100Hz) 25.xx fps */ +0xa6d1, +0xa7a0, + +0x8b74, /*EXP100 */ +0x8c68, +0x8d60, /*EXP120 */ +0x8ee0, + +0x9101, /*EXP Fix 25.00 fps*/ +0x92d4, +0x93c0, + +0x0320, +0x109C, + +0x0322, +0x10fd, + +0x0300, +0x1194, + +0x0300, +0x0101, +}; + +static const sr130pc20_regset_t sr130pc20_fps_30fix[] = +{ +/* sensor limitation, use 25fps */ +0xff00, +}; + +#endif /* __SR130PC20_REGS_H__ */ -- cgit v1.1 From ecefed8471ad2a78e80ac0817e69defde022f5c5 Mon Sep 17 00:00:00 2001 From: sbrissen Date: Wed, 26 Mar 2014 15:49:16 -0400 Subject: synaptics_s7301: add disabling keypad Change-Id: I5af258d2245024918f08a1a7c93c6efcc4d177b3 --- drivers/input/touchscreen/synaptics_s7301.c | 30 ++++++++++++++----------- drivers/input/touchscreen/synaptics_sysfs.c | 34 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/synaptics_s7301.c b/drivers/input/touchscreen/synaptics_s7301.c index fb152e1..34d42e7 100644 --- a/drivers/input/touchscreen/synaptics_s7301.c +++ b/drivers/input/touchscreen/synaptics_s7301.c @@ -591,7 +591,7 @@ static void synaptics_ts_read_points(struct synaptics_drv_data *data, #endif u16 addr = data->f11.data_base_addr + 3; u16 x = 0, y = 0; - + #if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) ret = synaptics_ts_read_block(data, palm_addr, &palm, 1); @@ -1076,9 +1076,11 @@ static int __init synaptics_ts_probe(struct i2c_client *client, __set_bit(EV_KEY, input->evbit); __set_bit(MT_TOOL_FINGER, input->keybit); __set_bit(INPUT_PROP_DIRECT, input->propbit); + + atomic_set(&ddata->keypad_enable, 1); #if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED) - if (pdata->led_event) { + if (pdata->led_event && atomic_read(&ddata->keypad_enable)) { __set_bit(EV_LED, input->evbit); __set_bit(LED_MISC, input->ledbit); } @@ -1106,17 +1108,19 @@ static int __init synaptics_ts_probe(struct i2c_client *client, 0, 1, 0, 0); #endif #if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) - if (pdata->support_extend_button) { - for (ret = 0; ret < pdata->extend_button_map->nbuttons; ret++) { - if (pdata->extend_button_map->map[ret] != KEY_RESERVED) - input_set_capability(input, EV_KEY, - pdata->extend_button_map->map[ret]); - } - } else { - for (ret = 0; ret < pdata->button_map->nbuttons; ret++) - input_set_capability(input, EV_KEY, - pdata->button_map->map[ret]); - } + if(atomic_read(&ddata->keypad_enable)){ + if (pdata->support_extend_button) { + for (ret = 0; ret < pdata->extend_button_map->nbuttons; ret++) { + if (pdata->extend_button_map->map[ret] != KEY_RESERVED) + input_set_capability(input, EV_KEY, + pdata->extend_button_map->map[ret]); + } + } else { + for (ret = 0; ret < pdata->button_map->nbuttons; ret++) + input_set_capability(input, EV_KEY, + pdata->button_map->map[ret]); + } + } #endif ret = input_register_device(input); diff --git a/drivers/input/touchscreen/synaptics_sysfs.c b/drivers/input/touchscreen/synaptics_sysfs.c index be82954..840a362 100644 --- a/drivers/input/touchscreen/synaptics_sysfs.c +++ b/drivers/input/touchscreen/synaptics_sysfs.c @@ -1204,6 +1204,37 @@ static ssize_t sec_extra_button_store(struct device *dev, return size; } +static ssize_t sec_keypad_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", atomic_read(&data->keypad_enable)); +} + +static ssize_t sec_keypad_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct synaptics_drv_data *data = dev_get_drvdata(dev); + + unsigned int val = 0; + sscanf(buf, "%d", &val); + val = (val == 0 ? 0 : 1); + atomic_set(&data->keypad_enable, val); + if (val) { + set_bit(KEY_BACK, data->input->keybit); + set_bit(KEY_MENU, data->input->keybit); + set_bit(KEY_HOME, data->input->keybit); + } else { + clear_bit(KEY_BACK, data->input->keybit); + clear_bit(KEY_MENU, data->input->keybit); + clear_bit(KEY_HOME, data->input->keybit); + } + input_sync(data->input); + + return count; +} + static DEVICE_ATTR(touch_sensitivity, S_IRUGO | S_IWUSR, NULL, sec_touchkey_sensitivity_store); static DEVICE_ATTR(touchkey_back, S_IRUGO | S_IWUSR, @@ -1226,6 +1257,8 @@ static DEVICE_ATTR(extra_button_event, S_IRUGO | S_IWUSR, NULL, sec_extra_button_store); static DEVICE_ATTR(touchkey_button_status, S_IRUGO | S_IWUSR, sec_touchkey_button_status_show, NULL); +static DEVICE_ATTR(keypad_enable, S_IRUGO|S_IWUSR, + sec_keypad_enable_show, sec_keypad_enable_store); static struct attribute *sec_touchkey_sysfs_attributes[] = { &dev_attr_touch_sensitivity.attr, @@ -1239,6 +1272,7 @@ static struct attribute *sec_touchkey_sysfs_attributes[] = { &dev_attr_brightness.attr, &dev_attr_extra_button_event.attr, &dev_attr_touchkey_button_status.attr, + &dev_attr_keypad_enable.attr, NULL, }; -- cgit v1.1 From 7b33a26b963567fe06cc289b684775811c7a72ea Mon Sep 17 00:00:00 2001 From: sbrissen Date: Fri, 28 Mar 2014 08:17:17 -0400 Subject: smdk4412: cypress-touchkey - add keydisabler Change-Id: I85efd4c5b2d6a7283c430f5eca2a730ef6b03d18 --- drivers/input/keyboard/cypress/cypress-touchkey.c | 41 +++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers') diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.c b/drivers/input/keyboard/cypress/cypress-touchkey.c index d73ec15..8aafaad 100644 --- a/drivers/input/keyboard/cypress/cypress-touchkey.c +++ b/drivers/input/keyboard/cypress/cypress-touchkey.c @@ -673,6 +673,10 @@ static irqreturn_t touchkey_interrupt(int irq, void *dev_id) set_touchkey_debug('a'); + if (!atomic_read(&tkey_i2c->keypad_enable)) { + return; + } + retry = 3; while (retry--) { ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3); @@ -1411,6 +1415,40 @@ static ssize_t set_touchkey_firm_status_show(struct device *dev, return count; } +static ssize_t sec_keypad_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", atomic_read(&tkey_i2c->keypad_enable)); +} + +static ssize_t sec_keypad_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev); + + unsigned int val = 0; + sscanf(buf, "%d", &val); + val = (val == 0 ? 0 : 1); + atomic_set(&tkey_i2c->keypad_enable, val); + if (val) { + set_bit(KEY_BACK, tkey_i2c->input_dev->keybit); + set_bit(KEY_MENU, tkey_i2c->input_dev->keybit); + set_bit(KEY_HOME, tkey_i2c->input_dev->keybit); + } else { + clear_bit(KEY_BACK, tkey_i2c->input_dev->keybit); + clear_bit(KEY_MENU, tkey_i2c->input_dev->keybit); + clear_bit(KEY_HOME, tkey_i2c->input_dev->keybit); + } + input_sync(tkey_i2c->input_dev); + + return count; +} + +static DEVICE_ATTR(keypad_enable, S_IRUGO|S_IWUSR, sec_keypad_enable_show, + sec_keypad_enable_store); + static DEVICE_ATTR(recommended_version, S_IRUGO | S_IWUSR | S_IWGRP, touch_version_read, touch_version_write); static DEVICE_ATTR(updated_version, S_IRUGO | S_IWUSR | S_IWGRP, @@ -1496,6 +1534,7 @@ static struct attribute *touchkey_attributes[] = { &dev_attr_touchkey_threshold.attr, &dev_attr_autocal_enable.attr, &dev_attr_autocal_stat.attr, + &dev_attr_keypad_enable.attr, #endif NULL, }; @@ -1563,6 +1602,8 @@ static int i2c_touchkey_probe(struct i2c_client *client, set_bit(LED_MISC, input_dev->ledbit); set_bit(EV_KEY, input_dev->evbit); + atomic_set(&tkey_i2c->keypad_enable, 1); + for (i = 1; i < touchkey_count; i++) set_bit(touchkey_keycode[i], input_dev->keybit); -- cgit v1.1 From db79d5e31204bf77067462ce881b1af30d20bd01 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Tue, 2 Aug 2011 12:32:01 +0100 Subject: dm: suppress endian warnings Suppress sparse warnings about cpu_to_le32() by using __le32 types for on-disk data etc. Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 6 ++-- drivers/md/dm-log.c | 20 ++++++++---- drivers/md/dm-snap-persistent.c | 71 ++++++++++++++++++++++------------------- 3 files changed, 54 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index da5f5f2..c393583 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -238,7 +238,7 @@ static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, struct dm_crypt_request *dmreq) { memset(iv, 0, cc->iv_size); - *(u32 *)iv = cpu_to_le32(dmreq->iv_sector & 0xffffffff); + *(__le32 *)iv = cpu_to_le32(dmreq->iv_sector & 0xffffffff); return 0; } @@ -247,7 +247,7 @@ static int crypt_iv_plain64_gen(struct crypt_config *cc, u8 *iv, struct dm_crypt_request *dmreq) { memset(iv, 0, cc->iv_size); - *(u64 *)iv = cpu_to_le64(dmreq->iv_sector); + *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector); return 0; } @@ -414,7 +414,7 @@ static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, struct crypto_cipher *essiv_tfm = this_crypt_config(cc)->iv_private; memset(iv, 0, cc->iv_size); - *(u64 *)iv = cpu_to_le64(dmreq->iv_sector); + *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector); crypto_cipher_encrypt_one(essiv_tfm, iv, iv); return 0; diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 948e3f4..5f06fb6 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -197,15 +197,21 @@ EXPORT_SYMBOL(dm_dirty_log_destroy); #define MIRROR_DISK_VERSION 2 #define LOG_OFFSET 2 -struct log_header { - uint32_t magic; +struct log_header_disk { + __le32 magic; /* * Simple, incrementing version. no backward * compatibility. */ + __le32 version; + __le64 nr_regions; +} __packed; + +struct log_header_core { + uint32_t magic; uint32_t version; - sector_t nr_regions; + uint64_t nr_regions; }; struct log_c { @@ -239,10 +245,10 @@ struct log_c { int log_dev_failed; int log_dev_flush_failed; struct dm_dev *log_dev; - struct log_header header; + struct log_header_core header; struct dm_io_region header_location; - struct log_header *disk_header; + struct log_header_disk *disk_header; }; /* @@ -271,14 +277,14 @@ static inline void log_clear_bit(struct log_c *l, /*---------------------------------------------------------------- * Header IO *--------------------------------------------------------------*/ -static void header_to_disk(struct log_header *core, struct log_header *disk) +static void header_to_disk(struct log_header_core *core, struct log_header_disk *disk) { disk->magic = cpu_to_le32(core->magic); disk->version = cpu_to_le32(core->version); disk->nr_regions = cpu_to_le64(core->nr_regions); } -static void header_from_disk(struct log_header *core, struct log_header *disk) +static void header_from_disk(struct log_header_core *core, struct log_header_disk *disk) { core->magic = le32_to_cpu(disk->magic); core->version = le32_to_cpu(disk->version); diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index e4ecadf..39becbe 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -58,25 +58,30 @@ #define NUM_SNAPSHOT_HDR_CHUNKS 1 struct disk_header { - uint32_t magic; + __le32 magic; /* * Is this snapshot valid. There is no way of recovering * an invalid snapshot. */ - uint32_t valid; + __le32 valid; /* * Simple, incrementing version. no backward * compatibility. */ - uint32_t version; + __le32 version; /* In sectors */ - uint32_t chunk_size; -}; + __le32 chunk_size; +} __packed; struct disk_exception { + __le64 old_chunk; + __le64 new_chunk; +} __packed; + +struct core_exception { uint64_t old_chunk; uint64_t new_chunk; }; @@ -396,32 +401,32 @@ static struct disk_exception *get_exception(struct pstore *ps, uint32_t index) } static void read_exception(struct pstore *ps, - uint32_t index, struct disk_exception *result) + uint32_t index, struct core_exception *result) { - struct disk_exception *e = get_exception(ps, index); + struct disk_exception *de = get_exception(ps, index); /* copy it */ - result->old_chunk = le64_to_cpu(e->old_chunk); - result->new_chunk = le64_to_cpu(e->new_chunk); + result->old_chunk = le64_to_cpu(de->old_chunk); + result->new_chunk = le64_to_cpu(de->new_chunk); } static void write_exception(struct pstore *ps, - uint32_t index, struct disk_exception *de) + uint32_t index, struct core_exception *e) { - struct disk_exception *e = get_exception(ps, index); + struct disk_exception *de = get_exception(ps, index); /* copy it */ - e->old_chunk = cpu_to_le64(de->old_chunk); - e->new_chunk = cpu_to_le64(de->new_chunk); + de->old_chunk = cpu_to_le64(e->old_chunk); + de->new_chunk = cpu_to_le64(e->new_chunk); } static void clear_exception(struct pstore *ps, uint32_t index) { - struct disk_exception *e = get_exception(ps, index); + struct disk_exception *de = get_exception(ps, index); /* clear it */ - e->old_chunk = 0; - e->new_chunk = 0; + de->old_chunk = 0; + de->new_chunk = 0; } /* @@ -437,13 +442,13 @@ static int insert_exceptions(struct pstore *ps, { int r; unsigned int i; - struct disk_exception de; + struct core_exception e; /* presume the area is full */ *full = 1; for (i = 0; i < ps->exceptions_per_area; i++) { - read_exception(ps, i, &de); + read_exception(ps, i, &e); /* * If the new_chunk is pointing at the start of @@ -451,7 +456,7 @@ static int insert_exceptions(struct pstore *ps, * is we know that we've hit the end of the * exceptions. Therefore the area is not full. */ - if (de.new_chunk == 0LL) { + if (e.new_chunk == 0LL) { ps->current_committed = i; *full = 0; break; @@ -460,13 +465,13 @@ static int insert_exceptions(struct pstore *ps, /* * Keep track of the start of the free chunks. */ - if (ps->next_free <= de.new_chunk) - ps->next_free = de.new_chunk + 1; + if (ps->next_free <= e.new_chunk) + ps->next_free = e.new_chunk + 1; /* * Otherwise we add the exception to the snapshot. */ - r = callback(callback_context, de.old_chunk, de.new_chunk); + r = callback(callback_context, e.old_chunk, e.new_chunk); if (r) return r; } @@ -641,12 +646,12 @@ static void persistent_commit_exception(struct dm_exception_store *store, { unsigned int i; struct pstore *ps = get_info(store); - struct disk_exception de; + struct core_exception ce; struct commit_callback *cb; - de.old_chunk = e->old_chunk; - de.new_chunk = e->new_chunk; - write_exception(ps, ps->current_committed++, &de); + ce.old_chunk = e->old_chunk; + ce.new_chunk = e->new_chunk; + write_exception(ps, ps->current_committed++, &ce); /* * Add the callback to the back of the array. This code @@ -701,7 +706,7 @@ static int persistent_prepare_merge(struct dm_exception_store *store, chunk_t *last_new_chunk) { struct pstore *ps = get_info(store); - struct disk_exception de; + struct core_exception ce; int nr_consecutive; int r; @@ -722,9 +727,9 @@ static int persistent_prepare_merge(struct dm_exception_store *store, ps->current_committed = ps->exceptions_per_area; } - read_exception(ps, ps->current_committed - 1, &de); - *last_old_chunk = de.old_chunk; - *last_new_chunk = de.new_chunk; + read_exception(ps, ps->current_committed - 1, &ce); + *last_old_chunk = ce.old_chunk; + *last_new_chunk = ce.new_chunk; /* * Find number of consecutive chunks within the current area, @@ -733,9 +738,9 @@ static int persistent_prepare_merge(struct dm_exception_store *store, for (nr_consecutive = 1; nr_consecutive < ps->current_committed; nr_consecutive++) { read_exception(ps, ps->current_committed - 1 - nr_consecutive, - &de); - if (de.old_chunk != *last_old_chunk - nr_consecutive || - de.new_chunk != *last_new_chunk - nr_consecutive) + &ce); + if (ce.old_chunk != *last_old_chunk - nr_consecutive || + ce.new_chunk != *last_new_chunk - nr_consecutive) break; } -- cgit v1.1 From 104acdc96c2a5276ac8e1604f9c6cedef7552b42 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Tue, 2 Aug 2011 12:32:04 +0100 Subject: dm: ignore merge_bvec for snapshots when safe Add a new flag DMF_MERGE_IS_OPTIONAL to struct mapped_device to indicate whether the device can accept bios larger than the size its merge function returns. When set, use this to send large bios to snapshots which can split them if necessary. Snapshot I/O may be significantly fragmented and this approach seems to improve peformance. Before the patch, dm_set_device_limits restricted bio size to page size if the underlying device had a merge function and the target didn't provide a merge function. After the patch, dm_set_device_limits restricts bio size to page size if the underlying device has a merge function, doesn't have DMF_MERGE_IS_OPTIONAL flag and the target doesn't provide a merge function. The snapshot target can't provide a merge function because when the merge function is called, it is impossible to determine where the bio will be remapped. Previously this led us to impose a 4k limit, which we can now remove if the snapshot store is located on a device without a merge function. Together with another patch for optimizing full chunk writes, it improves performance from 29MB/s to 40MB/s when writing to the filesystem on snapshot store. If the snapshot store is placed on a non-dm device with a merge function (such as md-raid), device mapper still limits all bios to page size. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-table.c | 3 +-- drivers/md/dm.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/md/dm.h | 2 ++ 3 files changed, 64 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index ebdae6e..c8c0783 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -539,8 +539,7 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, * If not we'll force DM to use PAGE_SIZE or * smaller I/O, just to be safe. */ - - if (q->merge_bvec_fn && !ti->type->merge) + if (dm_queue_merge_is_compulsory(q) && !ti->type->merge) blk_limits_max_hw_sectors(limits, (unsigned int) (PAGE_SIZE >> 9)); return 0; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 9f472d5..1eeef9c 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -111,6 +111,7 @@ EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo); #define DMF_FREEING 3 #define DMF_DELETING 4 #define DMF_NOFLUSH_SUSPENDING 5 +#define DMF_MERGE_IS_OPTIONAL 6 /* * Work processed by per-device workqueue. @@ -2018,6 +2019,59 @@ static void __set_size(struct mapped_device *md, sector_t size) } /* + * Return 1 if the queue has a compulsory merge_bvec_fn function. + * + * If this function returns 0, then the device is either a non-dm + * device without a merge_bvec_fn, or it is a dm device that is + * able to split any bios it receives that are too big. + */ +int dm_queue_merge_is_compulsory(struct request_queue *q) +{ + struct mapped_device *dev_md; + + if (!q->merge_bvec_fn) + return 0; + + if (q->make_request_fn == dm_request) { + dev_md = q->queuedata; + if (test_bit(DMF_MERGE_IS_OPTIONAL, &dev_md->flags)) + return 0; + } + + return 1; +} + +static int dm_device_merge_is_compulsory(struct dm_target *ti, + struct dm_dev *dev, sector_t start, + sector_t len, void *data) +{ + struct block_device *bdev = dev->bdev; + struct request_queue *q = bdev_get_queue(bdev); + + return dm_queue_merge_is_compulsory(q); +} + +/* + * Return 1 if it is acceptable to ignore merge_bvec_fn based + * on the properties of the underlying devices. + */ +static int dm_table_merge_is_optional(struct dm_table *table) +{ + unsigned i = 0; + struct dm_target *ti; + + while (i < dm_table_get_num_targets(table)) { + ti = dm_table_get_target(table, i++); + + if (ti->type->iterate_devices && + ti->type->iterate_devices(ti, dm_device_merge_is_compulsory, NULL)) + return 0; + } + + return 1; +} + +/* * Returns old map, which caller must destroy. */ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, @@ -2027,6 +2081,7 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, struct request_queue *q = md->queue; sector_t size; unsigned long flags; + int merge_is_optional; size = dm_table_get_size(t); @@ -2052,10 +2107,16 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, __bind_mempools(md, t); + merge_is_optional = dm_table_merge_is_optional(t); + write_lock_irqsave(&md->map_lock, flags); old_map = md->map; md->map = t; dm_table_set_restrictions(t, q, limits); + if (merge_is_optional) + set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags); + else + clear_bit(DMF_MERGE_IS_OPTIONAL, &md->flags); write_unlock_irqrestore(&md->map_lock, flags); return old_map; diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 1aaf167..6745dbd 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -66,6 +66,8 @@ int dm_table_alloc_md_mempools(struct dm_table *t); void dm_table_free_md_mempools(struct dm_table *t); struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); +int dm_queue_merge_is_compulsory(struct request_queue *q); + void dm_lock_md_type(struct mapped_device *md); void dm_unlock_md_type(struct mapped_device *md); void dm_set_md_type(struct mapped_device *md, unsigned type); -- cgit v1.1 From fc90060e9e62815bec64cb9dc1a3221ab70737a3 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Tue, 2 Aug 2011 12:32:04 +0100 Subject: dm table: share target argument parsing functions Move multipath target argument parsing code into dm-table so other targets can share it. Signed-off-by: Mike Snitzer Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 7 +-- drivers/md/dm-mpath.c | 152 +++++++++++++++----------------------------------- drivers/md/dm-table.c | 57 +++++++++++++++++++ 3 files changed, 104 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index c393583..80d83f9 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -30,7 +30,6 @@ #include #define DM_MSG_PREFIX "crypt" -#define MESG_STR(x) x, sizeof(x) /* * context holding the current state of a multi-part conversion @@ -1779,12 +1778,12 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) if (argc < 2) goto error; - if (!strnicmp(argv[0], MESG_STR("key"))) { + if (!strcasecmp(argv[0], "key")) { if (!test_bit(DM_CRYPT_SUSPENDED, &cc->flags)) { DMWARN("not suspended during key manipulation."); return -EINVAL; } - if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) { + if (argc == 3 && !strcasecmp(argv[1], "set")) { ret = crypt_set_key(cc, argv[2]); if (ret) return ret; @@ -1792,7 +1791,7 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) ret = cc->iv_gen_ops->init(cc); return ret; } - if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) { + if (argc == 2 && !strcasecmp(argv[1], "wipe")) { if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) { ret = cc->iv_gen_ops->wipe(cc); if (ret) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 70373bf..d13c431 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -22,7 +22,6 @@ #include #define DM_MSG_PREFIX "multipath" -#define MESG_STR(x) x, sizeof(x) #define DM_PG_INIT_DELAY_MSECS 2000 #define DM_PG_INIT_DELAY_DEFAULT ((unsigned) -1) @@ -505,80 +504,29 @@ static void trigger_event(struct work_struct *work) * <#paths> <#per-path selector args> * [ []* ]+ ]+ *---------------------------------------------------------------*/ -struct param { - unsigned min; - unsigned max; - char *error; -}; - -static int read_param(struct param *param, char *str, unsigned *v, char **error) -{ - if (!str || - (sscanf(str, "%u", v) != 1) || - (*v < param->min) || - (*v > param->max)) { - *error = param->error; - return -EINVAL; - } - - return 0; -} - -struct arg_set { - unsigned argc; - char **argv; -}; - -static char *shift(struct arg_set *as) -{ - char *r; - - if (as->argc) { - as->argc--; - r = *as->argv; - as->argv++; - return r; - } - - return NULL; -} - -static void consume(struct arg_set *as, unsigned n) -{ - BUG_ON (as->argc < n); - as->argc -= n; - as->argv += n; -} - -static int parse_path_selector(struct arg_set *as, struct priority_group *pg, +static int parse_path_selector(struct dm_arg_set *as, struct priority_group *pg, struct dm_target *ti) { int r; struct path_selector_type *pst; unsigned ps_argc; - static struct param _params[] = { + static struct dm_arg _args[] = { {0, 1024, "invalid number of path selector args"}, }; - pst = dm_get_path_selector(shift(as)); + pst = dm_get_path_selector(dm_shift_arg(as)); if (!pst) { ti->error = "unknown path selector type"; return -EINVAL; } - r = read_param(_params, shift(as), &ps_argc, &ti->error); + r = dm_read_arg_group(_args, as, &ps_argc, &ti->error); if (r) { dm_put_path_selector(pst); return -EINVAL; } - if (ps_argc > as->argc) { - dm_put_path_selector(pst); - ti->error = "not enough arguments for path selector"; - return -EINVAL; - } - r = pst->create(&pg->ps, ps_argc, as->argv); if (r) { dm_put_path_selector(pst); @@ -587,12 +535,12 @@ static int parse_path_selector(struct arg_set *as, struct priority_group *pg, } pg->ps.type = pst; - consume(as, ps_argc); + dm_consume_args(as, ps_argc); return 0; } -static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, +static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps, struct dm_target *ti) { int r; @@ -609,7 +557,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, if (!p) return ERR_PTR(-ENOMEM); - r = dm_get_device(ti, shift(as), dm_table_get_mode(ti->table), + r = dm_get_device(ti, dm_shift_arg(as), dm_table_get_mode(ti->table), &p->path.dev); if (r) { ti->error = "error getting device"; @@ -660,16 +608,16 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, return ERR_PTR(r); } -static struct priority_group *parse_priority_group(struct arg_set *as, +static struct priority_group *parse_priority_group(struct dm_arg_set *as, struct multipath *m) { - static struct param _params[] = { + static struct dm_arg _args[] = { {1, 1024, "invalid number of paths"}, {0, 1024, "invalid number of selector args"} }; int r; - unsigned i, nr_selector_args, nr_params; + unsigned i, nr_selector_args, nr_args; struct priority_group *pg; struct dm_target *ti = m->ti; @@ -693,26 +641,26 @@ static struct priority_group *parse_priority_group(struct arg_set *as, /* * read the paths */ - r = read_param(_params, shift(as), &pg->nr_pgpaths, &ti->error); + r = dm_read_arg(_args, as, &pg->nr_pgpaths, &ti->error); if (r) goto bad; - r = read_param(_params + 1, shift(as), &nr_selector_args, &ti->error); + r = dm_read_arg(_args + 1, as, &nr_selector_args, &ti->error); if (r) goto bad; - nr_params = 1 + nr_selector_args; + nr_args = 1 + nr_selector_args; for (i = 0; i < pg->nr_pgpaths; i++) { struct pgpath *pgpath; - struct arg_set path_args; + struct dm_arg_set path_args; - if (as->argc < nr_params) { + if (as->argc < nr_args) { ti->error = "not enough path parameters"; r = -EINVAL; goto bad; } - path_args.argc = nr_params; + path_args.argc = nr_args; path_args.argv = as->argv; pgpath = parse_path(&path_args, &pg->ps, ti); @@ -723,7 +671,7 @@ static struct priority_group *parse_priority_group(struct arg_set *as, pgpath->pg = pg; list_add_tail(&pgpath->list, &pg->pgpaths); - consume(as, nr_params); + dm_consume_args(as, nr_args); } return pg; @@ -733,28 +681,23 @@ static struct priority_group *parse_priority_group(struct arg_set *as, return ERR_PTR(r); } -static int parse_hw_handler(struct arg_set *as, struct multipath *m) +static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m) { unsigned hw_argc; int ret; struct dm_target *ti = m->ti; - static struct param _params[] = { + static struct dm_arg _args[] = { {0, 1024, "invalid number of hardware handler args"}, }; - if (read_param(_params, shift(as), &hw_argc, &ti->error)) + if (dm_read_arg_group(_args, as, &hw_argc, &ti->error)) return -EINVAL; if (!hw_argc) return 0; - if (hw_argc > as->argc) { - ti->error = "not enough arguments for hardware handler"; - return -EINVAL; - } - - m->hw_handler_name = kstrdup(shift(as), GFP_KERNEL); + m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL); request_module("scsi_dh_%s", m->hw_handler_name); if (scsi_dh_handler_exist(m->hw_handler_name) == 0) { ti->error = "unknown hardware handler type"; @@ -778,7 +721,7 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m) for (i = 0, p+=j+1; i <= hw_argc - 2; i++, p+=j+1) j = sprintf(p, "%s", as->argv[i]); } - consume(as, hw_argc - 1); + dm_consume_args(as, hw_argc - 1); return 0; fail: @@ -787,52 +730,45 @@ fail: return ret; } -static int parse_features(struct arg_set *as, struct multipath *m) +static int parse_features(struct dm_arg_set *as, struct multipath *m) { int r; unsigned argc; struct dm_target *ti = m->ti; - const char *param_name; + const char *arg_name; - static struct param _params[] = { + static struct dm_arg _args[] = { {0, 5, "invalid number of feature args"}, {1, 50, "pg_init_retries must be between 1 and 50"}, {0, 60000, "pg_init_delay_msecs must be between 0 and 60000"}, }; - r = read_param(_params, shift(as), &argc, &ti->error); + r = dm_read_arg_group(_args, as, &argc, &ti->error); if (r) return -EINVAL; if (!argc) return 0; - if (argc > as->argc) { - ti->error = "not enough arguments for features"; - return -EINVAL; - } - do { - param_name = shift(as); + arg_name = dm_shift_arg(as); argc--; - if (!strnicmp(param_name, MESG_STR("queue_if_no_path"))) { + if (!strcasecmp(arg_name, "queue_if_no_path")) { r = queue_if_no_path(m, 1, 0); continue; } - if (!strnicmp(param_name, MESG_STR("pg_init_retries")) && + if (!strcasecmp(arg_name, "pg_init_retries") && (argc >= 1)) { - r = read_param(_params + 1, shift(as), - &m->pg_init_retries, &ti->error); + r = dm_read_arg(_args + 1, as, &m->pg_init_retries, &ti->error); argc--; continue; } - if (!strnicmp(param_name, MESG_STR("pg_init_delay_msecs")) && + if (!strcasecmp(arg_name, "pg_init_delay_msecs") && (argc >= 1)) { - r = read_param(_params + 2, shift(as), - &m->pg_init_delay_msecs, &ti->error); + r = dm_read_arg(_args + 2, as, &m->pg_init_delay_msecs, &ti->error); argc--; continue; } @@ -847,15 +783,15 @@ static int parse_features(struct arg_set *as, struct multipath *m) static int multipath_ctr(struct dm_target *ti, unsigned int argc, char **argv) { - /* target parameters */ - static struct param _params[] = { + /* target arguments */ + static struct dm_arg _args[] = { {0, 1024, "invalid number of priority groups"}, {0, 1024, "invalid initial priority group number"}, }; int r; struct multipath *m; - struct arg_set as; + struct dm_arg_set as; unsigned pg_count = 0; unsigned next_pg_num; @@ -876,11 +812,11 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, if (r) goto bad; - r = read_param(_params, shift(&as), &m->nr_priority_groups, &ti->error); + r = dm_read_arg(_args, &as, &m->nr_priority_groups, &ti->error); if (r) goto bad; - r = read_param(_params + 1, shift(&as), &next_pg_num, &ti->error); + r = dm_read_arg(_args + 1, &as, &next_pg_num, &ti->error); if (r) goto bad; @@ -1510,10 +1446,10 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) } if (argc == 1) { - if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) { + if (!strcasecmp(argv[0], "queue_if_no_path")) { r = queue_if_no_path(m, 1, 0); goto out; - } else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) { + } else if (!strcasecmp(argv[0], "fail_if_no_path")) { r = queue_if_no_path(m, 0, 0); goto out; } @@ -1524,18 +1460,18 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) goto out; } - if (!strnicmp(argv[0], MESG_STR("disable_group"))) { + if (!strcasecmp(argv[0], "disable_group")) { r = bypass_pg_num(m, argv[1], 1); goto out; - } else if (!strnicmp(argv[0], MESG_STR("enable_group"))) { + } else if (!strcasecmp(argv[0], "enable_group")) { r = bypass_pg_num(m, argv[1], 0); goto out; - } else if (!strnicmp(argv[0], MESG_STR("switch_group"))) { + } else if (!strcasecmp(argv[0], "switch_group")) { r = switch_pg_num(m, argv[1]); goto out; - } else if (!strnicmp(argv[0], MESG_STR("reinstate_path"))) + } else if (!strcasecmp(argv[0], "reinstate_path")) action = reinstate_path; - else if (!strnicmp(argv[0], MESG_STR("fail_path"))) + else if (!strcasecmp(argv[0], "fail_path")) action = fail_path; else { DMWARN("Unrecognised multipath message received."); diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index c8c0783..92cd686 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -801,6 +801,63 @@ int dm_table_add_target(struct dm_table *t, const char *type, return r; } +/* + * Target argument parsing helpers. + */ +static int validate_next_arg(struct dm_arg *arg, struct dm_arg_set *arg_set, + unsigned *value, char **error, unsigned grouped) +{ + const char *arg_str = dm_shift_arg(arg_set); + + if (!arg_str || + (sscanf(arg_str, "%u", value) != 1) || + (*value < arg->min) || + (*value > arg->max) || + (grouped && arg_set->argc < *value)) { + *error = arg->error; + return -EINVAL; + } + + return 0; +} + +int dm_read_arg(struct dm_arg *arg, struct dm_arg_set *arg_set, + unsigned *value, char **error) +{ + return validate_next_arg(arg, arg_set, value, error, 0); +} +EXPORT_SYMBOL(dm_read_arg); + +int dm_read_arg_group(struct dm_arg *arg, struct dm_arg_set *arg_set, + unsigned *value, char **error) +{ + return validate_next_arg(arg, arg_set, value, error, 1); +} +EXPORT_SYMBOL(dm_read_arg_group); + +const char *dm_shift_arg(struct dm_arg_set *as) +{ + char *r; + + if (as->argc) { + as->argc--; + r = *as->argv; + as->argv++; + return r; + } + + return NULL; +} +EXPORT_SYMBOL(dm_shift_arg); + +void dm_consume_args(struct dm_arg_set *as, unsigned num_args) +{ + BUG_ON(as->argc < num_args); + as->argc -= num_args; + as->argv += num_args; +} +EXPORT_SYMBOL(dm_consume_args); + static int dm_table_set_type(struct dm_table *t) { unsigned i; -- cgit v1.1 From c538f742a9e67eca1ccdc801e8173a7e4ce30644 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Tue, 2 Aug 2011 12:32:08 +0100 Subject: dm crypt: optionally support discard requests Add optional parameter field to dmcrypt table and support "allow_discards" option. Discard requests bypass crypt queue processing. Bio is simple remapped to underlying device. Note that discard will be never enabled by default because of security consequences. It is up to the administrator to enable it for encrypted devices. (Note that userspace cryptsetup does not understand new optional parameters yet. Support for this will come later. Until then, you should use 'dmsetup' to enable and disable this.) Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 80d83f9..3e64023 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1576,11 +1576,17 @@ bad_mem: static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) { struct crypt_config *cc; - unsigned int key_size; + unsigned int key_size, opt_params; unsigned long long tmpll; int ret; + struct dm_arg_set as; + const char *opt_string; + + static struct dm_arg _args[] = { + {0, 1, "Invalid number of feature args"}, + }; - if (argc != 5) { + if (argc < 5) { ti->error = "Not enough arguments"; return -EINVAL; } @@ -1649,6 +1655,30 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) } cc->start = tmpll; + argv += 5; + argc -= 5; + + /* Optional parameters */ + if (argc) { + as.argc = argc; + as.argv = argv; + + ret = dm_read_arg_group(_args, &as, &opt_params, &ti->error); + if (ret) + goto bad; + + opt_string = dm_shift_arg(&as); + + if (opt_params == 1 && opt_string && + !strcasecmp(opt_string, "allow_discards")) + ti->num_discard_requests = 1; + else if (opt_params) { + ret = -EINVAL; + ti->error = "Invalid feature arguments"; + goto bad; + } + } + ret = -ENOMEM; #if 1 cc->io_queue = create_singlethread_workqueue("kcryptd_io"); @@ -1690,9 +1720,16 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, struct dm_crypt_io *io; struct crypt_config *cc; - if (bio->bi_rw & REQ_FLUSH) { + /* + * If bio is REQ_FLUSH or REQ_DISCARD, just bypass crypt queues. + * - for REQ_FLUSH device-mapper core ensures that no IO is in-flight + * - for REQ_DISCARD caller must use flush if IO ordering matters + */ + if (unlikely(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) { cc = ti->private; bio->bi_bdev = cc->dev->bdev; + if (bio_sectors(bio)) + bio->bi_sector = cc->start + dm_target_offset(ti, bio->bi_sector); return DM_MAPIO_REMAPPED; } @@ -1735,6 +1772,10 @@ static int crypt_status(struct dm_target *ti, status_type_t type, DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset, cc->dev->name, (unsigned long long)cc->start); + + if (ti->num_discard_requests) + DMEMIT(" 1 allow_discards"); + break; } return 0; @@ -1831,7 +1872,7 @@ static int crypt_iterate_devices(struct dm_target *ti, static struct target_type crypt_target = { .name = "crypt", - .version = {1, 10, 0}, + .version = {1, 11, 0}, .module = THIS_MODULE, .ctr = crypt_ctr, .dtr = crypt_dtr, -- cgit v1.1 From eba4e205b4e3d82ab8dd6bb6855d51d4f214e153 Mon Sep 17 00:00:00 2001 From: markcs Date: Mon, 28 Apr 2014 21:10:05 +1000 Subject: smdk4412: update sound soc and codecs Includes updated kernel source from i9305 Change-Id: I91ae18b30d02de037701250c46a457d035da56e1 --- drivers/cpufreq/cpufreq_ondemand.c | 34 ----------------------- drivers/cpufreq/cpufreq_pegasusq.c | 28 +++++++++++++++++-- drivers/cpufreq/powernow-k8.c | 56 ++++++++++++++++++++------------------ 3 files changed, 55 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index e151adc..a87dc5d 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -85,7 +85,6 @@ struct cpu_dbs_info_s { cputime64_t prev_cpu_idle; cputime64_t prev_cpu_iowait; cputime64_t prev_cpu_wall; - unsigned int prev_cpu_wall_delta; cputime64_t prev_cpu_nice; struct cpufreq_policy *cur_policy; struct delayed_work work; @@ -609,10 +608,6 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) unsigned int idle_time, wall_time, iowait_time; unsigned int load, load_freq; int freq_avg; - bool deep_sleep_detected = false; - /* the evil magic numbers, only 2 at least */ - const unsigned int deep_sleep_backoff = 10; - const unsigned int deep_sleep_factor = 5; j_dbs_info = &per_cpu(od_cpu_dbs_info, j); @@ -623,32 +618,6 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) j_dbs_info->prev_cpu_wall); j_dbs_info->prev_cpu_wall = cur_wall_time; - /* - * Ignore wall delta jitters in both directions. An - * exceptionally long wall_time will likely result - * idle but it was waken up to do work so the next - * slice is less likely to want to run at low - * frequency. Let's evaluate the next slice instead of - * the idle long one that passed already and it's too - * late to reduce in frequency. As opposed an - * exceptionally short slice that just run at low - * frequency is unlikely to be idle, but we may go - * back to idle pretty soon and that not idle slice - * already passed. If short slices will keep coming - * after a series of long slices the exponential - * backoff will converge faster and we'll react faster - * to high load. As opposed we'll decay slower - * towards low load and long idle times. - */ - if (j_dbs_info->prev_cpu_wall_delta > - wall_time * deep_sleep_factor || - j_dbs_info->prev_cpu_wall_delta * deep_sleep_factor < - wall_time) - deep_sleep_detected = true; - j_dbs_info->prev_cpu_wall_delta = - (j_dbs_info->prev_cpu_wall_delta * deep_sleep_backoff - + wall_time) / (deep_sleep_backoff+1); - idle_time = (unsigned int) cputime64_sub(cur_idle_time, j_dbs_info->prev_cpu_idle); j_dbs_info->prev_cpu_idle = cur_idle_time; @@ -674,9 +643,6 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) idle_time += jiffies_to_usecs(cur_nice_jiffies); } - if (deep_sleep_detected) - continue; - /* * For the purpose of ondemand, waiting for disk IO is an * indication that you're performance critical, and not that diff --git a/drivers/cpufreq/cpufreq_pegasusq.c b/drivers/cpufreq/cpufreq_pegasusq.c index 208a991..c44af54 100644 --- a/drivers/cpufreq/cpufreq_pegasusq.c +++ b/drivers/cpufreq/cpufreq_pegasusq.c @@ -165,7 +165,7 @@ static unsigned int get_nr_run_avg(void) #define DEF_START_DELAY (0) #define UP_THRESHOLD_AT_MIN_FREQ (40) -#define FREQ_FOR_RESPONSIVENESS (400000) +#define FREQ_FOR_RESPONSIVENESS (500000) #define HOTPLUG_DOWN_INDEX (0) #define HOTPLUG_UP_INDEX (1) @@ -306,7 +306,7 @@ static void apply_hotplug_lock(void) lock = atomic_read(&g_hotplug_lock); flag = lock - online; - if (flag == 0) + if (lock == 0 || flag == 0) return; work = flag > 0 ? &dbs_info->up_work : &dbs_info->down_work; @@ -380,6 +380,13 @@ void cpufreq_pegasusq_min_cpu_unlock(void) lock = atomic_read(&g_hotplug_lock); if (lock == 0) return; +#if defined(CONFIG_HAS_EARLYSUSPEND) && EARLYSUSPEND_HOTPLUGLOCK + if (dbs_tuners_ins.early_suspend >= 0) { /* if LCD is off-state */ + atomic_set(&g_hotplug_lock, 1); + apply_hotplug_lock(); + return; + } +#endif flag = lock - online; if (flag >= 0) return; @@ -484,6 +491,21 @@ static ssize_t show_hotplug_lock(struct kobject *kobj, return sprintf(buf, "%d\n", atomic_read(&g_hotplug_lock)); } +static ssize_t show_cpucore_table(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + ssize_t count = 0; + int i; + + for (i = CONFIG_NR_CPUS; i > 0; i--) { + count += sprintf(&buf[count], "%d ", i); + } + count += sprintf(&buf[count], "\n"); + + return count; +} + + #define show_hotplug_param(file_name, num_core, up_down) \ static ssize_t show_##file_name##_##num_core##_##up_down \ (struct kobject *kobj, struct attribute *attr, char *buf) \ @@ -813,6 +835,7 @@ define_one_global_rw(max_cpu_lock); define_one_global_rw(min_cpu_lock); define_one_global_rw(hotplug_lock); define_one_global_rw(dvfs_debug); +define_one_global_ro(cpucore_table); static struct attribute *dbs_attributes[] = { &sampling_rate_min.attr, @@ -846,6 +869,7 @@ static struct attribute *dbs_attributes[] = { &hotplug_rq_3_0.attr, &hotplug_rq_3_1.attr, &hotplug_rq_4_0.attr, + &cpucore_table.attr, NULL }; diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index f6cd315..ad683ec 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -32,6 +32,7 @@ #include #include #include +#include /* for current / set_cpus_allowed() */ #include #include @@ -1131,23 +1132,16 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, return res; } -struct powernowk8_target_arg { - struct cpufreq_policy *pol; - unsigned targfreq; - unsigned relation; -}; - -static long powernowk8_target_fn(void *arg) +/* Driver entry point to switch to the target frequency */ +static int powernowk8_target(struct cpufreq_policy *pol, + unsigned targfreq, unsigned relation) { - struct powernowk8_target_arg *pta = arg; - struct cpufreq_policy *pol = pta->pol; - unsigned targfreq = pta->targfreq; - unsigned relation = pta->relation; + cpumask_var_t oldmask; struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); u32 checkfid; u32 checkvid; unsigned int newstate; - int ret; + int ret = -EIO; if (!data) return -EINVAL; @@ -1155,16 +1149,29 @@ static long powernowk8_target_fn(void *arg) checkfid = data->currfid; checkvid = data->currvid; + /* only run on specific CPU from here on. */ + /* This is poor form: use a workqueue or smp_call_function_single */ + if (!alloc_cpumask_var(&oldmask, GFP_KERNEL)) + return -ENOMEM; + + cpumask_copy(oldmask, tsk_cpus_allowed(current)); + set_cpus_allowed_ptr(current, cpumask_of(pol->cpu)); + + if (smp_processor_id() != pol->cpu) { + printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); + goto err_out; + } + if (pending_bit_stuck()) { printk(KERN_ERR PFX "failing targ, change pending bit set\n"); - return -EIO; + goto err_out; } pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", pol->cpu, targfreq, pol->min, pol->max, relation); if (query_current_values_with_pending_wait(data)) - return -EIO; + goto err_out; if (cpu_family != CPU_HW_PSTATE) { pr_debug("targ: curr fid 0x%x, vid 0x%x\n", @@ -1182,7 +1189,7 @@ static long powernowk8_target_fn(void *arg) if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) - return -EIO; + goto err_out; mutex_lock(&fidvid_mutex); @@ -1195,8 +1202,9 @@ static long powernowk8_target_fn(void *arg) ret = transition_frequency_fidvid(data, newstate); if (ret) { printk(KERN_ERR PFX "transition frequency failed\n"); + ret = 1; mutex_unlock(&fidvid_mutex); - return 1; + goto err_out; } mutex_unlock(&fidvid_mutex); @@ -1205,18 +1213,12 @@ static long powernowk8_target_fn(void *arg) data->powernow_table[newstate].index); else pol->cur = find_khz_freq_from_fid(data->currfid); + ret = 0; - return 0; -} - -/* Driver entry point to switch to the target frequency */ -static int powernowk8_target(struct cpufreq_policy *pol, - unsigned targfreq, unsigned relation) -{ - struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, - .relation = relation }; - - return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); +err_out: + set_cpus_allowed_ptr(current, oldmask); + free_cpumask_var(oldmask); + return ret; } /* Driver entry point to verify the policy and range of frequencies */ -- cgit v1.1 From fd943581d0f60320105aeef5c523060475dbf455 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 3 May 2014 14:04:59 +0200 Subject: n_tty: Fix n_tty_write crash when echoing in raw mode The tty atomic_write_lock does not provide an exclusion guarantee for the tty driver if the termios settings are LECHO & !OPOST. And since it is unexpected and not allowed to call TTY buffer helpers like tty_insert_flip_string concurrently, this may lead to crashes when concurrect writers call pty_write. In that case the following two writers: * the ECHOing from a workqueue and * pty_write from the process race and can overflow the corresponding TTY buffer like follows. If we look into tty_insert_flip_string_fixed_flag, there is: int space = __tty_buffer_request_room(port, goal, flags); struct tty_buffer *tb = port->buf.tail; ... memcpy(char_buf_ptr(tb, tb->used), chars, space); ... tb->used += space; so the race of the two can result in something like this: A B __tty_buffer_request_room __tty_buffer_request_room memcpy(buf(tb->used), ...) tb->used += space; memcpy(buf(tb->used), ...) ->BOOM B's memcpy is past the tty_buffer due to the previous A's tb->used increment. Since the N_TTY line discipline input processing can output concurrently with a tty write, obtain the N_TTY ldisc output_lock to serialize echo output with normal tty writes. This ensures the tty buffer helper tty_insert_flip_string is not called concurrently and everything is fine. Note that this is nicely reproducible by an ordinary user using forkpty and some setup around that (raw termios + ECHO). And it is present in kernels at least after commit d945cb9cce20ac7143c2de8d88b187f62db99bdc (pty: Rework the pty layer to use the normal buffering logic) in 2.6.31-rc3. js: add more info to the commit log js: switch to bool js: lock unconditionally js: lock only the tty->ops->write call References: CVE-2014-0196 Reported-and-tested-by: Jiri Slaby Signed-off-by: Peter Hurley Signed-off-by: Jiri Slaby Cc: Linus Torvalds Cc: Alan Cox Cc: Signed-off-by: Greg Kroah-Hartman [bwh: Backported to 3.4: output_lock is a member of struct tty_struct] Change-Id: I11d1685056e18f107c970fbe2cab5176ca3a91c4 --- drivers/tty/n_tty.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index d7164bf..4484d8d 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1989,7 +1989,9 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, tty->ops->flush_chars(tty); } else { while (nr > 0) { + mutex_lock(&tty->output_lock); c = tty->ops->write(tty, b, nr); + mutex_unlock(&tty->output_lock); if (c < 0) { retval = c; goto break_out; -- cgit v1.1 From bc39ad7239a956de69068934911ab2d0ab09cf55 Mon Sep 17 00:00:00 2001 From: sbrissen Date: Tue, 24 Jun 2014 10:59:02 -0400 Subject: smdk4412: update mali driver from GT-N7100_SEA_KK_Opensource Change-Id: I1ddaa2c88660427348f359a6477aced196c4d7dc --- drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c | 2 +- .../gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c | 10 ++++++---- drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c | 1 + .../gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c | 2 ++ 4 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c index aaf9c73..d20c88b 100644 --- a/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c @@ -13,7 +13,7 @@ #include "mali_kernel_common.h" /* MALI_SEC */ #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) -//#define MALI_SEC_MEM_VALIDATION +#define MALI_SEC_MEM_VALIDATION #include #include #include diff --git a/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c index 346ad7f..ce74d80 100644 --- a/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c +++ b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c @@ -106,8 +106,8 @@ mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ #define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */ #define ASV_LEVEL_PRIME 13 /* ASV0, 1, 12 is reserved */ #define ASV_LEVEL_PD 13 -#define ASV_LEVEL_4210_12 8 -#define ASV_LEVEL_4210_14 5 +#define ASV_LEVEL_4210_12» 8 +#define ASV_LEVEL_4210_14» 5 #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = { @@ -163,7 +163,6 @@ static unsigned int asv_3d_volt_4212_9_table[MALI_DVFS_STEPS][ASV_LEVEL_PD] = { #endif #endif }; - #else static unsigned int asv_3d_volt_4210_12_table[MALI_DVFS_STEPS][ASV_LEVEL_4210_12] = { @@ -481,6 +480,9 @@ void mali_clk_set_rate(unsigned int clk, unsigned int mhz) if (bis_vpll) { + /* in Pega-prime, vpll_src_clock means ext_xtal_clock!! */ + clk_set_parent(sclk_vpll_clock, vpll_src_clock); + clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ); clk_set_parent(vpll_src_clock, ext_xtal_clock); clk_set_parent(sclk_vpll_clock, fout_vpll_clock); @@ -1258,7 +1260,7 @@ int mali_dvfs_bottom_lock_pop(void) if (prev_status <= 0) { MALI_PRINT(("gpu bottom lock status is not valid for pop\n")); return -1; - } else if (prev_status == 1) { + } else if (prev_status >= 1) { bottom_lock_step = 0; MALI_PRINT(("gpu bottom lock release\n")); } diff --git a/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c index 306ea3d..cf072fb 100644 --- a/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c @@ -339,6 +339,7 @@ _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ) if (_MALI_OSK_ERR_OK != _ump_osk_mem_mapregion_map(descriptor, offset, (u32 *)&(mem->block_array[block].addr), size_to_map ) ) { DBG_MSG(1, ("WARNING: _ump_ukk_map_mem failed to map memory into userspace\n")); + printk(KERN_ALERT"UMP:_ump_ukk_map_mem failed to map memory into userspace\n"); ump_descriptor_mapping_free( session_data->cookies_map, map_id ); ump_dd_reference_release(mem); _ump_osk_mem_mapregion_term( descriptor ); diff --git a/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c index 0cee2c8..57c2a7f 100644 --- a/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c @@ -185,6 +185,8 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor) if (left) { DBG_MSG(1, ("Failed to allocate needed pages\n")); + printk(KERN_ALERT"UMP::Failed to allocated pages, totally pages = %d, allocated pages = %d, currently requested pages = %d \n", + (int)info->num_pages_max, (int)info->num_pages_allocated, left + pages_allocated); /* MALI_SEC */ DBG_MSG(1, ("UMP memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", (pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); -- cgit v1.1 From 0ef0f071edf955e4a7562c87cc085b373464d380 Mon Sep 17 00:00:00 2001 From: Jorge Ruesga Date: Thu, 10 Jul 2014 01:10:30 +0200 Subject: smdk4412: fix build Change-Id: I3b9e6cee7343c9dd3a7ae68694e60991047db50d Signed-off-by: Jorge Ruesga --- drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c index ce74d80..65acaa6 100644 --- a/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c +++ b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c @@ -106,8 +106,8 @@ mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ #define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */ #define ASV_LEVEL_PRIME 13 /* ASV0, 1, 12 is reserved */ #define ASV_LEVEL_PD 13 -#define ASV_LEVEL_4210_12» 8 -#define ASV_LEVEL_4210_14» 5 +#define ASV_LEVEL_4210_12 8 +#define ASV_LEVEL_4210_14 5 #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = { -- cgit v1.1 From a784c375212d90c5ae7b75b8ccc67c6e0d364acd Mon Sep 17 00:00:00 2001 From: sbrissen Date: Fri, 11 Jul 2014 14:07:27 -0400 Subject: smdk4412: fix kona bootloop Change-Id: I21c2828a547f8387dada2e6393d92fe115e2491f --- drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c index d20c88b..fac6d93 100644 --- a/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c @@ -13,7 +13,9 @@ #include "mali_kernel_common.h" /* MALI_SEC */ #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +#ifndef CONFIG_MACH_KONA #define MALI_SEC_MEM_VALIDATION +#endif #include #include #include -- cgit v1.1 From d90b43b963027b4d1559cec14e97117827a6458d Mon Sep 17 00:00:00 2001 From: Dorian Snyder Date: Sun, 15 Jun 2014 01:24:33 -0700 Subject: mali: add r3p1 for devices that need it d710 needs to use old mali drivers due to new ones causing signal to be completely killed Change-Id: I450c356b50e3f3521a63717a1c241e3b818b936f --- drivers/media/video/samsung/Kconfig | 2 + drivers/media/video/samsung/Makefile | 2 + drivers/media/video/samsung/mali/Kbuild_module | 295 ++++ drivers/media/video/samsung/mali/Kconfig | 63 + drivers/media/video/samsung/mali/Kconfig_module | 20 + drivers/media/video/samsung/mali/Makefile | 337 ++++ drivers/media/video/samsung/mali/Makefile_module | 97 ++ drivers/media/video/samsung/mali/arch | 1 + drivers/media/video/samsung/mali/arch-debug | 1 + .../video/samsung/mali/arch-orion-m400/config.h | 154 ++ .../samsung/mali/arch-pb-virtex5-m300/config.h | 85 + .../mali/arch-pb-virtex5-m400-1-direct/config.h | 92 + .../mali/arch-pb-virtex5-m400-1-pmu/config.h | 85 + .../samsung/mali/arch-pb-virtex5-m400-1/config.h | 77 + .../samsung/mali/arch-pb-virtex5-m400-2/config.h | 91 + .../samsung/mali/arch-pb-virtex5-m400-3/config.h | 105 ++ .../samsung/mali/arch-pb-virtex5-m400-4/config.h | 119 ++ .../video/samsung/mali/arch-pegasus-m400/config.h | 154 ++ drivers/media/video/samsung/mali/arch-release | 1 + .../samsung/mali/arch-ve-virtex6-m450-8/config.h | 174 ++ .../samsung/mali/common/mali_block_allocator.c | 391 +++++ .../samsung/mali/common/mali_block_allocator.h | 18 + .../media/video/samsung/mali/common/mali_cluster.c | 218 +++ .../media/video/samsung/mali/common/mali_cluster.h | 44 + .../samsung/mali/common/mali_device_pause_resume.c | 46 + .../samsung/mali/common/mali_device_pause_resume.h | 31 + .../media/video/samsung/mali/common/mali_dlbu.c | 285 ++++ .../media/video/samsung/mali/common/mali_dlbu.h | 45 + drivers/media/video/samsung/mali/common/mali_gp.c | 746 ++++++++ drivers/media/video/samsung/mali/common/mali_gp.h | 46 + .../media/video/samsung/mali/common/mali_gp_job.c | 49 + .../media/video/samsung/mali/common/mali_gp_job.h | 131 ++ .../video/samsung/mali/common/mali_gp_scheduler.c | 443 +++++ .../video/samsung/mali/common/mali_gp_scheduler.h | 30 + .../media/video/samsung/mali/common/mali_group.c | 841 +++++++++ .../media/video/samsung/mali/common/mali_group.h | 146 ++ .../media/video/samsung/mali/common/mali_hw_core.c | 46 + .../media/video/samsung/mali/common/mali_hw_core.h | 71 + .../video/samsung/mali/common/mali_kernel_common.h | 183 ++ .../video/samsung/mali/common/mali_kernel_core.c | 980 +++++++++++ .../video/samsung/mali/common/mali_kernel_core.h | 39 + .../mali/common/mali_kernel_descriptor_mapping.c | 184 ++ .../mali/common/mali_kernel_descriptor_mapping.h | 101 ++ .../video/samsung/mali/common/mali_kernel_mem_os.c | 354 ++++ .../video/samsung/mali/common/mali_kernel_mem_os.h | 37 + .../mali/common/mali_kernel_memory_engine.c | 376 ++++ .../mali/common/mali_kernel_memory_engine.h | 152 ++ .../samsung/mali/common/mali_kernel_utilization.c | 218 +++ .../samsung/mali/common/mali_kernel_utilization.h | 44 + .../video/samsung/mali/common/mali_kernel_vsync.c | 51 + .../video/samsung/mali/common/mali_l2_cache.c | 414 +++++ .../video/samsung/mali/common/mali_l2_cache.h | 43 + .../samsung/mali/common/mali_mem_validation.c | 71 + .../samsung/mali/common/mali_mem_validation.h | 19 + .../media/video/samsung/mali/common/mali_memory.c | 1319 ++++++++++++++ .../media/video/samsung/mali/common/mali_memory.h | 82 + drivers/media/video/samsung/mali/common/mali_mmu.c | 619 +++++++ drivers/media/video/samsung/mali/common/mali_mmu.h | 55 + .../samsung/mali/common/mali_mmu_page_directory.c | 475 ++++++ .../samsung/mali/common/mali_mmu_page_directory.h | 100 ++ drivers/media/video/samsung/mali/common/mali_osk.h | 1798 ++++++++++++++++++++ .../video/samsung/mali/common/mali_osk_bitops.h | 166 ++ .../video/samsung/mali/common/mali_osk_list.h | 184 ++ .../video/samsung/mali/common/mali_osk_mali.h | 222 +++ .../video/samsung/mali/common/mali_osk_profiling.h | 147 ++ drivers/media/video/samsung/mali/common/mali_pm.c | 552 ++++++ drivers/media/video/samsung/mali/common/mali_pm.h | 56 + drivers/media/video/samsung/mali/common/mali_pmu.c | 199 +++ drivers/media/video/samsung/mali/common/mali_pmu.h | 70 + drivers/media/video/samsung/mali/common/mali_pp.c | 710 ++++++++ drivers/media/video/samsung/mali/common/mali_pp.h | 47 + .../media/video/samsung/mali/common/mali_pp_job.c | 95 ++ .../media/video/samsung/mali/common/mali_pp_job.h | 273 +++ .../video/samsung/mali/common/mali_pp_scheduler.c | 594 +++++++ .../video/samsung/mali/common/mali_pp_scheduler.h | 38 + .../video/samsung/mali/common/mali_scheduler.c | 37 + .../video/samsung/mali/common/mali_scheduler.h | 21 + .../media/video/samsung/mali/common/mali_session.c | 47 + .../media/video/samsung/mali/common/mali_session.h | 65 + drivers/media/video/samsung/mali/common/mali_ukk.h | 612 +++++++ .../samsung/mali/common/mali_user_settings_db.c | 88 + .../samsung/mali/common/mali_user_settings_db.h | 40 + .../samsung/mali/include/linux/mali/mali_utgard.h | 28 + .../mali/include/linux/mali/mali_utgard_counters.h | 264 +++ .../mali/include/linux/mali/mali_utgard_ioctl.h | 86 + .../linux/mali/mali_utgard_profiling_events.h | 127 ++ .../mali/include/linux/mali/mali_utgard_uk_types.h | 1095 ++++++++++++ .../mali/linux/license/gpl/mali_kernel_license.h | 31 + .../media/video/samsung/mali/linux/mali_dma_buf.c | 392 +++++ .../media/video/samsung/mali/linux/mali_dma_buf.h | 29 + .../video/samsung/mali/linux/mali_kernel_linux.c | 634 +++++++ .../video/samsung/mali/linux/mali_kernel_linux.h | 43 + .../video/samsung/mali/linux/mali_kernel_pm.c | 268 +++ .../video/samsung/mali/linux/mali_kernel_pm.h | 17 + .../video/samsung/mali/linux/mali_kernel_sysfs.c | 1280 ++++++++++++++ .../video/samsung/mali/linux/mali_kernel_sysfs.h | 35 + .../media/video/samsung/mali/linux/mali_linux_pm.h | 50 + .../samsung/mali/linux/mali_linux_pm_testsuite.h | 32 + .../video/samsung/mali/linux/mali_linux_trace.h | 126 ++ .../video/samsung/mali/linux/mali_osk_atomics.c | 55 + .../media/video/samsung/mali/linux/mali_osk_irq.c | 266 +++ .../video/samsung/mali/linux/mali_osk_locks.c | 340 ++++ .../samsung/mali/linux/mali_osk_low_level_mem.c | 660 +++++++ .../media/video/samsung/mali/linux/mali_osk_mali.c | 34 + .../media/video/samsung/mali/linux/mali_osk_math.c | 22 + .../video/samsung/mali/linux/mali_osk_memory.c | 61 + .../media/video/samsung/mali/linux/mali_osk_misc.c | 64 + .../samsung/mali/linux/mali_osk_notification.c | 189 ++ .../media/video/samsung/mali/linux/mali_osk_pm.c | 83 + .../samsung/mali/linux/mali_osk_profiling_gator.c | 261 +++ .../mali/linux/mali_osk_profiling_internal.c | 324 ++++ .../video/samsung/mali/linux/mali_osk_specific.h | 130 ++ .../media/video/samsung/mali/linux/mali_osk_time.c | 51 + .../video/samsung/mali/linux/mali_osk_timers.c | 65 + .../video/samsung/mali/linux/mali_osk_wait_queue.c | 73 + .../samsung/mali/linux/mali_pmu_power_up_down.c | 65 + .../samsung/mali/linux/mali_profiling_events.h | 17 + .../media/video/samsung/mali/linux/mali_uk_types.h | 18 + .../media/video/samsung/mali/linux/mali_ukk_core.c | 104 ++ .../media/video/samsung/mali/linux/mali_ukk_gp.c | 113 ++ .../media/video/samsung/mali/linux/mali_ukk_mem.c | 259 +++ .../media/video/samsung/mali/linux/mali_ukk_pp.c | 88 + .../video/samsung/mali/linux/mali_ukk_profiling.c | 183 ++ .../video/samsung/mali/linux/mali_ukk_vsync.c | 41 + .../video/samsung/mali/linux/mali_ukk_wrappers.h | 68 + .../samsung/mali/platform/default/mali_platform.c | 43 + .../video/samsung/mali/platform/mali_platform.h | 153 ++ .../mali_platform_pmu_testing/mali_platform.c | 66 + .../mali/platform/orion-m400/mali_platform.c | 656 +++++++ .../mali/platform/orion-m400/mali_platform_dvfs.c | 448 +++++ .../mali/platform/pegasus-m400/mali_platform.c | 801 +++++++++ .../platform/pegasus-m400/mali_platform_dvfs.c | 847 +++++++++ .../media/video/samsung/mali/regs/mali_200_regs.h | 172 ++ .../media/video/samsung/mali/regs/mali_gp_regs.h | 214 +++ .../mali/timestamp-arm11-cc/mali_timestamp.c | 13 + .../mali/timestamp-arm11-cc/mali_timestamp.h | 48 + .../mali/timestamp-default/mali_timestamp.c | 13 + .../mali/timestamp-default/mali_timestamp.h | 26 + drivers/media/video/samsung/ump/Kconfig | 58 + drivers/media/video/samsung/ump/Kconfig_module | 16 + drivers/media/video/samsung/ump/Makefile | 93 + drivers/media/video/samsung/ump/Makefile.common | 20 + drivers/media/video/samsung/ump/arch | 1 + drivers/media/video/samsung/ump/arch-debug | 1 + .../video/samsung/ump/arch-orion-m400/config.h | 22 + .../video/samsung/ump/arch-pb-virtex5/config.h | 18 + .../video/samsung/ump/arch-pegasus-m400/config.h | 22 + drivers/media/video/samsung/ump/arch-release | 1 + .../video/samsung/ump/common/ump_kernel_api.c | 551 ++++++ .../video/samsung/ump/common/ump_kernel_common.c | 414 +++++ .../video/samsung/ump/common/ump_kernel_common.h | 128 ++ .../ump/common/ump_kernel_descriptor_mapping.c | 165 ++ .../ump/common/ump_kernel_descriptor_mapping.h | 91 + .../samsung/ump/common/ump_kernel_memory_backend.h | 51 + .../video/samsung/ump/common/ump_kernel_ref_drv.c | 260 +++ .../video/samsung/ump/common/ump_kernel_types.h | 53 + drivers/media/video/samsung/ump/common/ump_osk.h | 51 + .../media/video/samsung/ump/common/ump_uk_types.h | 208 +++ drivers/media/video/samsung/ump/common/ump_ukk.h | 61 + .../samsung/ump/include/ump_kernel_interface.h | 236 +++ .../ump/include/ump_kernel_interface_ref_drv.h | 35 + .../samsung/ump/include/ump_kernel_platform.h | 48 + .../ump/linux/license/gpl/ump_kernel_license.h | 31 + drivers/media/video/samsung/ump/linux/ump_ioctl.h | 61 + .../video/samsung/ump/linux/ump_kernel_linux.c | 492 ++++++ .../video/samsung/ump/linux/ump_kernel_linux.h | 18 + .../linux/ump_kernel_memory_backend_dedicated.c | 287 ++++ .../linux/ump_kernel_memory_backend_dedicated.h | 23 + .../ump/linux/ump_kernel_memory_backend_os.c | 260 +++ .../ump/linux/ump_kernel_memory_backend_os.h | 23 + .../ump/linux/ump_kernel_memory_backend_vcm.c | 290 ++++ .../ump/linux/ump_kernel_memory_backend_vcm.h | 22 + .../video/samsung/ump/linux/ump_memory_backend.c | 77 + .../video/samsung/ump/linux/ump_osk_atomics.c | 27 + .../samsung/ump/linux/ump_osk_low_level_mem.c | 485 ++++++ .../media/video/samsung/ump/linux/ump_osk_misc.c | 37 + .../video/samsung/ump/linux/ump_ukk_ref_wrappers.c | 320 ++++ .../video/samsung/ump/linux/ump_ukk_ref_wrappers.h | 43 + .../video/samsung/ump/linux/ump_ukk_wrappers.c | 306 ++++ .../video/samsung/ump/linux/ump_ukk_wrappers.h | 47 + 180 files changed, 34683 insertions(+) create mode 100644 drivers/media/video/samsung/mali/Kbuild_module create mode 100644 drivers/media/video/samsung/mali/Kconfig create mode 100644 drivers/media/video/samsung/mali/Kconfig_module create mode 100644 drivers/media/video/samsung/mali/Makefile create mode 100644 drivers/media/video/samsung/mali/Makefile_module create mode 120000 drivers/media/video/samsung/mali/arch create mode 120000 drivers/media/video/samsung/mali/arch-debug create mode 100644 drivers/media/video/samsung/mali/arch-orion-m400/config.h create mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h create mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h create mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h create mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h create mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h create mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h create mode 100644 drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h create mode 100644 drivers/media/video/samsung/mali/arch-pegasus-m400/config.h create mode 120000 drivers/media/video/samsung/mali/arch-release create mode 100644 drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h create mode 100644 drivers/media/video/samsung/mali/common/mali_block_allocator.c create mode 100644 drivers/media/video/samsung/mali/common/mali_block_allocator.h create mode 100644 drivers/media/video/samsung/mali/common/mali_cluster.c create mode 100644 drivers/media/video/samsung/mali/common/mali_cluster.h create mode 100644 drivers/media/video/samsung/mali/common/mali_device_pause_resume.c create mode 100644 drivers/media/video/samsung/mali/common/mali_device_pause_resume.h create mode 100644 drivers/media/video/samsung/mali/common/mali_dlbu.c create mode 100644 drivers/media/video/samsung/mali/common/mali_dlbu.h create mode 100644 drivers/media/video/samsung/mali/common/mali_gp.c create mode 100644 drivers/media/video/samsung/mali/common/mali_gp.h create mode 100644 drivers/media/video/samsung/mali/common/mali_gp_job.c create mode 100644 drivers/media/video/samsung/mali/common/mali_gp_job.h create mode 100644 drivers/media/video/samsung/mali/common/mali_gp_scheduler.c create mode 100644 drivers/media/video/samsung/mali/common/mali_gp_scheduler.h create mode 100644 drivers/media/video/samsung/mali/common/mali_group.c create mode 100644 drivers/media/video/samsung/mali/common/mali_group.h create mode 100644 drivers/media/video/samsung/mali/common/mali_hw_core.c create mode 100644 drivers/media/video/samsung/mali/common/mali_hw_core.h create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_common.h create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_core.c create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_core.h create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_mem_os.h create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_utilization.c create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_utilization.h create mode 100644 drivers/media/video/samsung/mali/common/mali_kernel_vsync.c create mode 100644 drivers/media/video/samsung/mali/common/mali_l2_cache.c create mode 100644 drivers/media/video/samsung/mali/common/mali_l2_cache.h create mode 100644 drivers/media/video/samsung/mali/common/mali_mem_validation.c create mode 100644 drivers/media/video/samsung/mali/common/mali_mem_validation.h create mode 100644 drivers/media/video/samsung/mali/common/mali_memory.c create mode 100644 drivers/media/video/samsung/mali/common/mali_memory.h create mode 100644 drivers/media/video/samsung/mali/common/mali_mmu.c create mode 100644 drivers/media/video/samsung/mali/common/mali_mmu.h create mode 100644 drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c create mode 100644 drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h create mode 100644 drivers/media/video/samsung/mali/common/mali_osk.h create mode 100644 drivers/media/video/samsung/mali/common/mali_osk_bitops.h create mode 100644 drivers/media/video/samsung/mali/common/mali_osk_list.h create mode 100644 drivers/media/video/samsung/mali/common/mali_osk_mali.h create mode 100644 drivers/media/video/samsung/mali/common/mali_osk_profiling.h create mode 100644 drivers/media/video/samsung/mali/common/mali_pm.c create mode 100644 drivers/media/video/samsung/mali/common/mali_pm.h create mode 100644 drivers/media/video/samsung/mali/common/mali_pmu.c create mode 100644 drivers/media/video/samsung/mali/common/mali_pmu.h create mode 100644 drivers/media/video/samsung/mali/common/mali_pp.c create mode 100644 drivers/media/video/samsung/mali/common/mali_pp.h create mode 100644 drivers/media/video/samsung/mali/common/mali_pp_job.c create mode 100644 drivers/media/video/samsung/mali/common/mali_pp_job.h create mode 100644 drivers/media/video/samsung/mali/common/mali_pp_scheduler.c create mode 100644 drivers/media/video/samsung/mali/common/mali_pp_scheduler.h create mode 100644 drivers/media/video/samsung/mali/common/mali_scheduler.c create mode 100644 drivers/media/video/samsung/mali/common/mali_scheduler.h create mode 100644 drivers/media/video/samsung/mali/common/mali_session.c create mode 100644 drivers/media/video/samsung/mali/common/mali_session.h create mode 100644 drivers/media/video/samsung/mali/common/mali_ukk.h create mode 100644 drivers/media/video/samsung/mali/common/mali_user_settings_db.c create mode 100644 drivers/media/video/samsung/mali/common/mali_user_settings_db.h create mode 100644 drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h create mode 100644 drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h create mode 100644 drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h create mode 100644 drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h create mode 100644 drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h create mode 100644 drivers/media/video/samsung/mali/linux/license/gpl/mali_kernel_license.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_dma_buf.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_dma_buf.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_linux.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_linux.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_pm.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_pm.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_linux_pm.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_linux_trace.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_atomics.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_irq.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_locks.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_mali.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_math.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_memory.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_misc.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_notification.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_pm.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_specific.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_time.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_timers.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_profiling_events.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_uk_types.h create mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_core.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_gp.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_mem.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_pp.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h create mode 100644 drivers/media/video/samsung/mali/platform/default/mali_platform.c create mode 100644 drivers/media/video/samsung/mali/platform/mali_platform.h create mode 100644 drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c create mode 100644 drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c create mode 100644 drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c create mode 100644 drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c create mode 100644 drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c create mode 100644 drivers/media/video/samsung/mali/regs/mali_200_regs.h create mode 100644 drivers/media/video/samsung/mali/regs/mali_gp_regs.h create mode 100644 drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c create mode 100644 drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h create mode 100644 drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c create mode 100644 drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h create mode 100644 drivers/media/video/samsung/ump/Kconfig create mode 100644 drivers/media/video/samsung/ump/Kconfig_module create mode 100644 drivers/media/video/samsung/ump/Makefile create mode 100644 drivers/media/video/samsung/ump/Makefile.common create mode 120000 drivers/media/video/samsung/ump/arch create mode 120000 drivers/media/video/samsung/ump/arch-debug create mode 100644 drivers/media/video/samsung/ump/arch-orion-m400/config.h create mode 100644 drivers/media/video/samsung/ump/arch-pb-virtex5/config.h create mode 100644 drivers/media/video/samsung/ump/arch-pegasus-m400/config.h create mode 120000 drivers/media/video/samsung/ump/arch-release create mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_api.c create mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_common.c create mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_common.h create mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c create mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h create mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h create mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c create mode 100644 drivers/media/video/samsung/ump/common/ump_kernel_types.h create mode 100644 drivers/media/video/samsung/ump/common/ump_osk.h create mode 100644 drivers/media/video/samsung/ump/common/ump_uk_types.h create mode 100644 drivers/media/video/samsung/ump/common/ump_ukk.h create mode 100644 drivers/media/video/samsung/ump/include/ump_kernel_interface.h create mode 100644 drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h create mode 100644 drivers/media/video/samsung/ump/include/ump_kernel_platform.h create mode 100644 drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h create mode 100644 drivers/media/video/samsung/ump/linux/ump_ioctl.h create mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_linux.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_linux.h create mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h create mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h create mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h create mode 100644 drivers/media/video/samsung/ump/linux/ump_memory_backend.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_osk_atomics.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_osk_misc.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h create mode 100644 drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h (limited to 'drivers') diff --git a/drivers/media/video/samsung/Kconfig b/drivers/media/video/samsung/Kconfig index 4824144..01232a0 100644 --- a/drivers/media/video/samsung/Kconfig +++ b/drivers/media/video/samsung/Kconfig @@ -17,6 +17,8 @@ if CPU_EXYNOS4210 || CPU_EXYNOS4212 || CPU_EXYNOS4412 source "drivers/media/video/samsung/fimc/Kconfig" source "drivers/media/video/samsung/tvout/Kconfig" source "drivers/media/video/samsung/mfc5x/Kconfig" + source "drivers/media/video/samsung/mali/Kconfig" + source "drivers/media/video/samsung/ump/Kconfig" endif config VIDEO_FIMG2D diff --git a/drivers/media/video/samsung/Makefile b/drivers/media/video/samsung/Makefile index 5a46253..e9905d2 100644 --- a/drivers/media/video/samsung/Makefile +++ b/drivers/media/video/samsung/Makefile @@ -12,6 +12,8 @@ obj-$(CONFIG_VIDEO_FIMG2D3X) += fimg2d3x/ obj-$(CONFIG_VIDEO_FIMG2D4X) += fimg2d4x/ endif +obj-$(CONFIG_VIDEO_UMP) += ump/ obj-$(CONFIG_VIDEO_TSI) += tsi/ +obj-$(CONFIG_VIDEO_MALI400MP) += mali/ EXTRA_CFLAGS += -Idrivers/media/video diff --git a/drivers/media/video/samsung/mali/Kbuild_module b/drivers/media/video/samsung/mali/Kbuild_module new file mode 100644 index 0000000..e865954 --- /dev/null +++ b/drivers/media/video/samsung/mali/Kbuild_module @@ -0,0 +1,295 @@ +# +# Copyright (C) 2010-2011 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained from Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +# This file is called by the Linux build system. + +OSKOS=linux + +# set up defaults if not defined by the user +USING_UMP ?= 0 +USING_OS_MEMORY ?= 0 +USING_MALI_PMM_TESTSUITE ?= 0 +OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 +USING_PROFILING ?= 1 +USING_INTERNAL_PROFILING ?= 0 +DISABLE_PP0 ?= 0 +DISABLE_PP1 ?= 0 +DISABLE_PP2 ?= 0 +DISABLE_PP3 ?= 0 +PROFILING_SKIP_PP_JOBS ?= 0 +PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 +PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH ?= 0 +TIMESTAMP ?= default +BUILD ?= debug +TARGET_PLATFORM ?= default +KERNEL_RUNTIME_PM_ENABLED ?= 0 +CONFIG ?= pb-virtex5-m200 +MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0 +MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 +MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 + +DEFINES := $(EXTRA_DEFINES) + +# Get path to driver source from Linux build system +DRIVER_DIR=$(src) + +# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: +# The ARM proprietary product will only include the license/proprietary directory +# The GPL product will only include the license/gpl directory + +ifeq ($(wildcard $(DRIVER_DIR)/linux/license/gpl/*),) +ccflags-y += -I$(DRIVER_DIR)/linux/license/proprietary +# Disable profiling for proprietary +override USING_PROFILING := 0 +$(warning "USING_PROFILING not supported, disabling.") +else +ccflags-y += -I$(DRIVER_DIR)/linux/license/gpl +endif + + +ifeq ($(USING_PROFILING),1) +ifeq ($(USING_INTERNAL_PROFILING),0) +ifndef CONFIG_TRACEPOINTS +# Should default to gator profiling, but we dont have the kernel feature required, so disable profiling +override USING_PROFILING = 0 +$(warning "CONFIG_TRACEPOINTS required for USING_PROFILING") +endif +endif +endif + +ifeq ($(USING_PROFILING),0) +# make sure user hasnt selected incompatible flags +override USING_INTERNAL_PROFILING = 0 +endif + +MALI_RELEASE_NAME=$(shell cat $(DRIVER_DIR)/.version 2> /dev/null) + +# Check if a Mali Core sub module should be enabled, true or false returned +submodule_enabled = $(shell gcc $(DEFINES) -E $1/arch/config.h | grep type | grep -c $(2)) + +OSKFILES = \ + $(OSKOS)/mali_osk_atomics.c \ + $(OSKOS)/mali_osk_irq.c \ + $(OSKOS)/mali_osk_locks.c \ + $(OSKOS)/mali_osk_wait_queue.c \ + $(OSKOS)/mali_osk_low_level_mem.c \ + $(OSKOS)/mali_osk_math.c \ + $(OSKOS)/mali_osk_memory.c \ + $(OSKOS)/mali_osk_misc.c \ + $(OSKOS)/mali_osk_mali.c \ + $(OSKOS)/mali_osk_notification.c \ + $(OSKOS)/mali_osk_time.c \ + $(OSKOS)/mali_osk_timers.c + +UKKFILES = \ + $(OSKOS)/mali_ukk_mem.c \ + $(OSKOS)/mali_ukk_gp.c \ + $(OSKOS)/mali_ukk_pp.c \ + $(OSKOS)/mali_ukk_core.c + +ifeq ($(USING_PROFILING),1) +UKKFILES += \ + $(OSKOS)/mali_ukk_profiling.c +endif + +ifeq ($(MALI_PLATFORM_FILE),) +MALI_PLATFORM_FILE = platform/default/mali_platform.c +endif + +# Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available +SVN_REV := $(shell (cd $(DRIVER_DIR); (svnversion | grep -E "^[0-9]+" && svnversion) || git svn info | grep '^Revision: '| sed -e 's/^Revision: //' ) 2>/dev/null ) +ifeq ($(SVN_REV),) +SVN_REV := $(MALI_RELEASE_NAME) +else +SVN_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV) +endif + +# Validate selected config +ifneq ($(shell [ -d $(DRIVER_DIR)/arch-$(CONFIG) ] && [ -f $(DRIVER_DIR)/arch-$(CONFIG)/config.h ] && echo "OK"), OK) +$(warning Current directory is $(shell pwd)) +$(error No configuration found for config $(CONFIG). Check that arch-$(CONFIG)/config.h exists) +else +# Link arch to the selected arch-config directory +$(shell [ -L $(DRIVER_DIR)/arch ] && rm $(DRIVER_DIR)/arch) +$(shell ln -sf arch-$(CONFIG) $(DRIVER_DIR)/arch) +$(shell touch $(DRIVER_DIR)/arch/config.h) +endif + +# Set up our defines, which will be passed to gcc +DEFINES += -DUSING_OS_MEMORY=$(USING_OS_MEMORY) +DEFINES += -DUSING_MMU=1 +DEFINES += -DUSING_UMP=$(USING_UMP) +DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP +DEFINES += -DMALI_INTERNAL_TIMELINE_PROFILING_ENABLED=$(USING_INTERNAL_PROFILING) +DEFINES += -DDISABLE_PP0=$(DISABLE_PP0) +DEFINES += -DDISABLE_PP1=$(DISABLE_PP1) +DEFINES += -DDISABLE_PP2=$(DISABLE_PP2) +DEFINES += -DDISABLE_PP3=$(DISABLE_PP3) +DEFINES += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS) +DEFINES += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS) +DEFINES += -DPROFILING_PRINT_L2_HITRATE_ON_GP_FINISH=$(PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH) + +DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) +DEFINES += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) +DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) +DEFINES += -DMALI_TIMELINE_PROFILING_ENABLED=$(USING_PROFILING) +DEFINES += -DMALI_POWER_MGMT_TEST_SUITE=$(USING_MALI_PMM_TESTSUITE) +ifeq ($(shell test $(SUBLEVEL) -gt 32 -a $(PATCHLEVEL) = 6 -a $(VERSION) = 2 -o $(VERSION) -gt 2 && echo "OK"),OK) +# MALI_STATE_TRACKING is only supported on Linux kernels from version 2.6.32. +DEFINES += -DMALI_STATE_TRACKING=1 +else +DEFINES += -DMALI_STATE_TRACKING=0 +endif +DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) + +MALI_PLATFORM_FILE = platform/$(TARGET_PLATFORM)/mali_platform.c + + +ifdef CONFIG_PM +ifdef CONFIG_PM_RUNTIME + KERNEL_RUNTIME_PM_ENABLED = 1 +endif +endif + +DEFINES += -DMALI_PMM_RUNTIME_JOB_CONTROL_ON=$(KERNEL_RUNTIME_PM_ENABLED) + +ifeq ($(BUILD), debug) +DEFINES += -DDEBUG +endif +DEFINES += -DSVN_REV=$(SVN_REV) +DEFINES += -DSVN_REV_STRING=\"$(SVN_REV)\" + +# Linux has its own mmap cleanup handlers (see mali_kernel_memory.c) +DEFINES += -DMALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP + +ifeq ($(USING_UMP),1) + DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=1 + ccflags-y += -I$(DRIVER_DIR)/../../ump/include/ump +else + DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=0 +endif + +# Use our defines when compiling +ccflags-y += $(DEFINES) -I$(DRIVER_DIR) -I$(DRIVER_DIR)/include -I$(DRIVER_DIR)/common -I$(DRIVER_DIR)/linux -I$(DRIVER_DIR)/platform + +# Source files which always are included in a build +SRC = \ + common/mali_kernel_core.c \ + linux/mali_kernel_linux.c \ + common/mali_kernel_descriptor_mapping.c \ + common/mali_session.c \ + common/mali_device_pause_resume.c \ + common/mali_kernel_vsync.c \ + linux/mali_ukk_vsync.c \ + linux/mali_kernel_sysfs.c \ + common/mali_mmu.c \ + common/mali_mmu_page_directory.c \ + common/mali_memory.c \ + common/mali_kernel_memory_engine.c \ + common/mali_block_allocator.c \ + common/mali_kernel_mem_os.c \ + common/mali_mem_validation.c \ + common/mali_hw_core.c \ + common/mali_gp.c \ + common/mali_pp.c \ + common/mali_pp_job.c \ + common/mali_gp_job.c \ + common/mali_scheduler.c \ + common/mali_gp_scheduler.c \ + common/mali_pp_scheduler.c \ + common/mali_cluster.c \ + common/mali_group.c \ + common/mali_dlbu.c \ + common/mali_pm.c \ + common/mali_pmu.c \ + common/mali_user_settings_db.c \ + $(OSKOS)/mali_osk_pm.c \ + linux/mali_kernel_pm.c \ + linux/mali_pmu_power_up_down.c \ + $(MALI_PLATFORM_FILE) \ + $(OSKFILES) \ + $(UKKFILES) \ + __malidrv_build_info.c + +# Selecting files to compile by parsing the config file + +ifeq ($(USING_INTERNAL_PROFILING),1) +PROFILING_BACKEND_SOURCES = \ + linux/mali_osk_profiling_internal.c \ + timestamp-$(TIMESTAMP)/mali_timestamp.c +ccflags-y += -I$(DRIVER_DIR)/timestamp-$(TIMESTAMP) +else +ifeq ($(USING_PROFILING),1) +PROFILING_BACKEND_SOURCES = \ + linux/mali_osk_profiling_gator.c +endif +endif + +# Add the profiling sources +SRC += $(PROFILING_BACKEND_SOURCES) + +ifeq ($(USING_MALI_PMM_TESTSUITE),1) +ccflags-y += -I$(DRIVER_DIR)/platform/mali_pmu_testing +endif + +mali-$(CONFIG_MALI400_GPU_UTILIZATION) += common/mali_kernel_utilization.o +mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_dma_buf.o + +ifneq ($(call submodule_enabled, $(DRIVER_DIR), MALI400PP),0) + # Mali-400 PP in use + ccflags-y += -DUSING_MALI400 +endif + +ifneq ($(call submodule_enabled, $(DRIVER_DIR), MALI300PP),0) + # Mali-400 PP in use + ccflags-y += -DUSING_MALI400 +endif + +ifneq ($(call submodule_enabled, $(DRIVER_DIR), MALI200),0) + # Mali200 in use + ccflags-y += -DUSING_MALI200 +endif + +# Always build in support for Mali L2 cache +SRC += common/mali_l2_cache.c + +# Tell the Linux build system to enable building of our .c files +mali-y += $(SRC:.c=.o) +# Tell the Linux build system from which .o file to create the kernel module +obj-$(CONFIG_MALI400) := mali.o + + +VERSION_STRINGS := +VERSION_STRINGS += CONFIG=$(CONFIG) +VERSION_STRINGS += USING_OS_MEMORY=$(USING_OS_MEMORY) +VERSION_STRINGS += API_VERSION=$(shell cd $(DRIVER_DIR); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) +VERSION_STRINGS += REPO_URL=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'URL: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^URL: ' | cut -d: -f2- | cut -b2-) +VERSION_STRINGS += REVISION=$(SVN_REV) +VERSION_STRINGS += CHANGED_REVISION=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'Last Changed Rev: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-) +VERSION_STRINGS += CHANGE_DATE=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'Last Changed Date: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-) +VERSION_STRINGS += BUILD_DATE=$(shell date) + +VERSION_STRINGS += BUILD=$(shell echo $(BUILD) | tr a-z A-Z) +VERSION_STRINGS += CPU=$(CPU) +VERSION_STRINGS += USING_UMP=$(USING_UMP) +VERSION_STRINGS += USING_MALI200=$(call submodule_enabled, $(DRIVER_DIR), MALI200) +VERSION_STRINGS += USING_MALI400=$(call submodule_enabled, $(DRIVER_DIR), MALI400) +VERSION_STRINGS += USING_MALI400_L2_CACHE=$(call submodule_enabled, $(DRIVER_DIR), MALI400L2) +VERSION_STRINGS += USING_GP2=$(call submodule_enabled, $(DRIVER_DIR), MALIGP2) +VERSION_STRINGS += KDIR=$(KDIR) +VERSION_STRINGS += MALI_PLATFORM_FILE=$(MALI_PLATFORM_FILE) +VERSION_STRINGS += OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) +VERSION_STRINGS += USING_PROFILING=$(USING_PROFILING) +VERSION_STRINGS += USING_INTERNAL_PROFILING=$(USING_INTERNAL_PROFILING) +VERSION_STRINGS += USING_GPU_UTILIZATION=$(CONFIG_MALI400_GPU_UTILIZATION) + +# Create file with Mali driver configuration +$(DRIVER_DIR)/__malidrv_build_info.c: + @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(DRIVER_DIR)/__malidrv_build_info.c diff --git a/drivers/media/video/samsung/mali/Kconfig b/drivers/media/video/samsung/mali/Kconfig new file mode 100644 index 0000000..e53d2b3 --- /dev/null +++ b/drivers/media/video/samsung/mali/Kconfig @@ -0,0 +1,63 @@ +# +## S3C Multimedia Mali configuration +## +# +# For Mali +config VIDEO_MALI400MP + bool "Enable MALI integration" + depends on VIDEO_SAMSUNG + default n + ---help--- + This enables MALI integration in the multimedia device driver + +choice +depends on VIDEO_MALI400MP +prompt "MALI MEMORY OPTION" +default MALI_OSMEM_ONLY +config MALI_DED_ONLY + bool "mali dedicated memory only" + ---help--- + This enables MALI dedicated memory only option +config MALI_DED_MMU + bool "mali dedicated memory with mmu enable" + ---help--- + This enables MALI dedicated memory with mmu enable option +config MALI_OSMEM_ONLY + bool "mali OS memory only" + ---help--- + This enables MALI OS memory only option +config MALI_DED_OSMEM + bool "mali dedicated memory and OS memory" + ---help--- + This enables MALI dedicated memory and OS memory option + +endchoice +config MALI_MEM_SIZE +int "Dedicated Memory Size" + depends on VIDEO_MALI400MP && (MALI_DED_ONLY || MALI_DED_MMU || MALI_DED_OSMEM) + default "128" + ---help--- + This value is dedicated memory size of Mali GPU(unit is MByte). + +config MALI_R3P1_LSI + bool "Uses the R3P1 as a kernel module" + depends on VIDEO_MALI400MP + default n + ---help--- + This uses the r3p1 as a MALI kernel module + + +# For DEBUG +config VIDEO_MALI400MP_DEBUG + bool "Enables debug messages" + depends on VIDEO_MALI400MP + default n + help + This enables Mali driver debug messages. + +config VIDEO_MALI400MP_DVFS + bool "Enables DVFS" + depends on VIDEO_MALI400MP && PM + default y + help + This enables Mali driver DVFS. diff --git a/drivers/media/video/samsung/mali/Kconfig_module b/drivers/media/video/samsung/mali/Kconfig_module new file mode 100644 index 0000000..1fdc638 --- /dev/null +++ b/drivers/media/video/samsung/mali/Kconfig_module @@ -0,0 +1,20 @@ +config MALI400_DEBUG + bool "Enable debug in Mali driver" + depends on MALI400 + ---help--- + This enabled extra debug checks and messages in the Mali-300/400/450 + driver. + +config MALI400_PROFILING + bool "Enable Mali profiling" + depends on MALI400 && TRACEPOINTS + ---help--- + This enables gator profiling of Mali GPU events. + +config MALI400_GPU_UTILIZATION + bool "Enable Mali GPU utilization tracking" + depends on MALI400 + ---help--- + This enables gathering and processing of the utilization of Mali GPU. + This data can be used as a basis to change GPU operating frequency. + diff --git a/drivers/media/video/samsung/mali/Makefile b/drivers/media/video/samsung/mali/Makefile new file mode 100644 index 0000000..3e25b61 --- /dev/null +++ b/drivers/media/video/samsung/mali/Makefile @@ -0,0 +1,337 @@ +# +# Copyright (C) 2010-2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained from Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +OSKOS :=linux +FILES_PREFIX= +MALI_INCLUDE_PREFIX := drivers/media/video/samsung/mali/ +KBUILDROOT = + +ifeq ($(CONFIG_MALI_DED_ONLY),y) +USING_OS_MEMORY=0 +USING_MMU=0 +USING_DED=1 +endif + +ifeq ($(CONFIG_MALI_DED_MMU),y) +USING_OS_MEMORY=0 +USING_MMU=1 +USING_DED=1 +endif + +ifeq ($(CONFIG_MALI_OSMEM_ONLY),y) +USING_MMU=1 +USING_DED=0 +USING_OS_MEMORY=1 +endif + +ifeq ($(CONFIG_MALI_DED_OSMEM),y) +USING_MMU=1 +USING_DED=1 +USING_OS_MEMORY=1 +endif + +ifeq ($(CONFIG_PM),y) + USING_PMM = 1 +ifeq ($(CONFIG_PM_RUNTIME),y) + KERNEL_RUNTIME_PM_ENABLED = 1 +endif +endif + +ifeq ($(CONFIG_VIDEO_MALI400MP_DVFS),y) +USING_GPU_UTILIZATION=1 +USING_MALI_DVFS_ENABLED=1 +endif + +ifeq ($(CONFIG_VIDEO_UMP_DEBUG),y) +BUILD=debug +endif + +ifeq ($(CONFIG_VIDEO_MALI400MP_STREAMLINE_PROFILING),y) +USING_PROFILING=1 +USING_TRACEPOINTS=1 +endif + +# set up defaults if not defined by the user +USE_UMPV2 ?= 0 +PANIC_ON_WATCHDOG_TIMEOUT ?= 1 +USING_MALI400 ?= 1 +USING_MMU ?= 1 +USING_DED ?= 0 +USING_UMP ?= 0 +ONLY_ZBT ?= 0 +USING_ZBT ?= 0 +USING_OS_MEMORY ?= 1 +USING_PMM ?= 0 +USING_MALI_RUN_TIME_PM ?= 0 +USING_MALI_PMM_TESTSUITE ?= 0 +USING_MALI_PMU ?= 0 +USING_GPU_UTILIZATION ?= 0 +OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 +USING_PROFILING ?= 0 +USING_INTERNAL_PROFILING ?= 0 +USING_TRACEPOINTS ?= 0 +USING_MALI_MAJOR_PREDEFINE = 1 +USING_MALI_DVFS_ENABLED ?= 1 +USING_MALI_PMM_EARLYSUSPEND ?= 0 +#USING_KERNEL_WITH_DMA_ALLOC_PHYS_PAGE ?= 0 +#CONFIG_MALI_MEM_SIZE ?= 512 +DISABLE_PP0 ?= 0 +DISABLE_PP1 ?= 0 +DISABLE_PP2 ?= 0 +DISABLE_PP3 ?= 0 +PROFILING_SKIP_PP_JOBS ?= 0 +PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 +PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH ?= 0 +TIMESTAMP ?= default +BUILD ?= release +TARGET_PLATFORM ?= default +KERNEL_RUNTIME_PM_ENABLED ?= 0 +MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0 +MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 +MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 + +# Get path to driver source from Linux build system +ifeq ($(USING_PROFILING),1) +ifeq ($(USING_INTERNAL_PROFILING),0) +ifndef CONFIG_TRACEPOINTS +# Should default to gator profiling, but we dont have the kernel feature required, so disable profiling +override USING_PROFILING = 0 +$(warning "CONFIG_TRACEPOINTS required for USING_PROFILING") +endif +endif +endif + +ifeq ($(USING_PROFILING),0) +# make sure user hasnt selected incompatible flags +override USING_INTERNAL_PROFILING = 0 +endif + +USING_MALI_SLP_GLOBAL_LOCK ?= 0 + +#config validtion check +ifeq ($(USING_OS_MEMORY),1) + USING_MMU = 1 +endif + +# Check if a Mali Core sub module should be enabled, true or false returned +#submodule_enabled = $(shell gcc $(DEFINES) -E $(FILES_PREFIX)/arch/config.h | grep type | grep -c $(2)) + +# Inside the kernel build system + +# This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak +-include ../../../arm_internal.mak + +# Set up our defines, which will be passed to gcc +DEFINES += -DONLY_ZBT=$(ONLY_ZBT) +DEFINES += -DUSING_ZBT=$(USING_ZBT) +DEFINES += -DUSING_MMU=$(USING_MMU) +DEFINES += -DUSING_OS_MEMORY=$(USING_OS_MEMORY) +DEFINES += -DUSING_DED=$(USING_DED) +DEFINES += -DUSING_UMP=$(USING_UMP) +DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP +DEFINES += -DUSING_MALI_PMU=$(USING_MALI_PMU) +DEFINES += -DMALI_PMM_RUNTIME_JOB_CONTROL_ON=$(KERNEL_RUNTIME_PM_ENABLED) +DEFINES += -DUSING_MALI_PMM=$(USING_PMM) +DEFINES += -DMALI_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) +DEFINES += -DCONFIG_MALI_MEM_SIZE=$(CONFIG_MALI_MEM_SIZE) +DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP +DEFINES += -DMALI_INTERNAL_TIMELINE_PROFILING_ENABLED=$(USING_INTERNAL_PROFILING) +DEFINES += -DMALI_MAJOR_PREDEFINE=$(USING_MALI_MAJOR_PREDEFINE) +DEFINES += -DMALI_DVFS_ENABLED=$(USING_MALI_DVFS_ENABLED) +DEFINES += -DUSING_MALI_PMM_EARLYSUSPEND=$(USING_MALI_PMM_EARLYSUSPEND) +DEFINES += -DMALI_STATE_TRACKING=0 +DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) +DEFINES += -DMALI_TRACEPOINTS_ENABLED=$(USING_TRACEPOINTS) +DEFINES += -DDISABLE_PP0=$(DISABLE_PP0) +DEFINES += -DDISABLE_PP1=$(DISABLE_PP1) +DEFINES += -DDISABLE_PP2=$(DISABLE_PP2) +DEFINES += -DDISABLE_PP3=$(DISABLE_PP3) +DEFINES += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS) +DEFINES += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS) +DEFINES += -DPROFILING_PRINT_L2_HITRATE_ON_GP_FINISH=$(PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH) +DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) +DEFINES += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) +DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) +DEFINES += -DMALI_TIMELINE_PROFILING_ENABLED=$(USING_PROFILING) +DEFINES += -DMALI_POWER_MGMT_TEST_SUITE=$(USING_MALI_PMM_TESTSUITE) +DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) + +ifeq ($(BUILD),debug) +DEFINES += -DDEBUG +endif + +# Linux has its own mmap cleanup handlers (see mali_kernel_mem_mmu.o) +DEFINES += -DMALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP + +# UMP +ifeq ($(CONFIG_VIDEO_UMP),y) + DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=1 + EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)../ump/include +else + DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=0 +endif + +# Target build file +obj-$(CONFIG_VIDEO_UMP) += mali.o + +# Use our defines when compiling +# MALI +INCLUDES = \ + -I$(MALI_INCLUDE_PREFIX)\ + -I$(MALI_INCLUDE_PREFIX)include \ + -I$(MALI_INCLUDE_PREFIX)common \ + -I$(MALI_INCLUDE_PREFIX)linux \ + -I$(MALI_INCLUDE_PREFIX)platform\ + -I$(MALI_INCLUDE_PREFIX)regs + +EXTRA_CFLAGS += $(INCLUDES)\ + $(DEFINES) + +EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)linux/license/gpl +EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)common/pmm + +# Source files which always are included in a build +ifeq ($(CONFIG_VIDEO_UMP),y) +OSKFILES=\ + $(FILES_PREFIX)$(OSKOS)/mali_osk_irq.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_wait_queue.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_low_level_mem.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_mali.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_notification.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_time.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_timers.o +else +OSKFILES=\ + $(FILES_PREFIX)$(OSKOS)/mali_osk_atomics.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_irq.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_locks.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_wait_queue.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_low_level_mem.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_math.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_memory.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_misc.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_mali.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_notification.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_time.o \ + $(FILES_PREFIX)$(OSKOS)/mali_osk_timers.o +endif #($(CONFIG_VIDEO_UMP),y) + +ifeq ($(CONFIG_CPU_EXYNOS4210),y) + MALI_PLATFORM_DIR = platform/orion-m400 +else + MALI_PLATFORM_DIR = platform/pegasus-m400 +endif #($(CONFIG_CPU_EXYNOS4210),y) + +MALI_PLATFORM_FILE=$(MALI_PLATFORM_DIR)/mali_platform.o +UKKFILES=\ + $(FILES_PREFIX)$(OSKOS)/mali_ukk_mem.o \ + $(FILES_PREFIX)$(OSKOS)/mali_ukk_gp.o \ + $(FILES_PREFIX)$(OSKOS)/mali_ukk_pp.o \ + $(FILES_PREFIX)$(OSKOS)/mali_ukk_core.o + +ifeq ($(USING_PROFILING),1) +UKKFILES += \ + $(FILES_PREFIX)$(OSKOS)/mali_ukk_profiling.o +endif + +mali-y := \ + common/mali_kernel_core.o \ + linux/mali_kernel_linux.o \ + common/mali_kernel_descriptor_mapping.o \ + common/mali_session.o \ + common/mali_device_pause_resume.o \ + common/mali_kernel_vsync.o \ + linux/mali_ukk_vsync.o \ + linux/mali_kernel_sysfs.o \ + common/mali_mmu.o \ + common/mali_mmu_page_directory.o \ + common/mali_memory.o \ + common/mali_kernel_memory_engine.o \ + common/mali_block_allocator.o \ + common/mali_kernel_mem_os.o \ + common/mali_mem_validation.o \ + common/mali_hw_core.o \ + common/mali_gp.o \ + common/mali_pp.o \ + common/mali_pp_job.o \ + common/mali_gp_job.o \ + common/mali_scheduler.o \ + common/mali_gp_scheduler.o \ + common/mali_pp_scheduler.o \ + common/mali_cluster.o \ + common/mali_group.o \ + common/mali_dlbu.o \ + common/mali_pm.o \ + common/mali_pmu.o \ + common/mali_user_settings_db.o \ + $(OSKOS)/mali_osk_pm.o \ + linux/mali_kernel_pm.o \ + linux/mali_pmu_power_up_down.o \ + $(MALI_PLATFORM_FILE) \ + $(OSKFILES) \ + $(UKKFILES) +# __malidrv_build_info.c + +# Selecting files to compile by parsing the config file + +ifeq ($(USING_INTERNAL_PROFILING),1) +PROFILING_BACKEND_SOURCES = \ + linux/mali_osk_profiling_internal.o \ + timestamp-$(TIMESTAMP)/mali_timestamp.o +EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)timestamp-$(TIMESTAMP) +else +ifeq ($(USING_PROFILING),1) +PROFILING_BACKEND_SOURCES = \ + linux/mali_osk_profiling_gator.o +endif +endif + +# Add the profiling sources +mali-y += $(PROFILING_BACKEND_SOURCES) + +# Mali-400 PP in use +ifeq ($(USING_MALI_PMM_TESTSUITE),1) +EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)platform/mali_pmu_testing +endif + +ifeq ($(USING_GPU_UTILIZATION),1) +EXTRA_CFLAGS += -DCONFIG_MALI400_GPU_UTILIZATION=1 + +mali-y += \ + common/mali_kernel_utilization.o +endif + +ifeq ($(USING_MALI_DVFS_ENABLED),1) +mali-y += $(MALI_PLATFORM_DIR)/mali_platform_dvfs.o +endif #($(USING_MALI_DVFS_ENABLED),1) + +EXTRA_CFLAGS += -DUSING_MALI400 + +# Mali Level2 cache in use +EXTRA_CFLAGS += -DUSING_MALI400_L2_CACHE +mali-y += common/mali_l2_cache.o + +# Mali SLP Global lock feature +ifeq ($(USING_MALI_SLP_GLOBAL_LOCK),1) +mali-y += \ + linux/mali_slp_global_lock.o +endif + + +ifeq ($(PANIC_ON_WATCHDOG_TIMEOUT),1) + EXTRA_CFLAGS += -DUSING_KERNEL_PANIC +endif + +# Get subversion revision number, fall back to 0000 if no svn info is available +SVN_REV:=$(shell ((svnversion | grep -E "^[0-9]+" && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') + +EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV) +EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\" + diff --git a/drivers/media/video/samsung/mali/Makefile_module b/drivers/media/video/samsung/mali/Makefile_module new file mode 100644 index 0000000..361ce08 --- /dev/null +++ b/drivers/media/video/samsung/mali/Makefile_module @@ -0,0 +1,97 @@ +# +# Copyright (C) 2010-2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained from Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +USE_UMPV2=0 + +# The Makefile sets up "arch" based on the CONFIG, creates the version info +# string and the __malidrv_build_info.c file, and then call the Linux build +# system to actually build the driver. After that point the Kbuild file takes +# over. + +# set up defaults if not defined by the user +ARCH ?= arm + +OSKOS=linux +FILES_PREFIX= + +check_cc2 = \ + $(shell if $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \ + then \ + echo "$(2)"; \ + else \ + echo "$(3)"; \ + fi ;) + +# This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak +-include ../../../arm_internal.mak + +# Check that required parameters are supplied. +ifeq ($(CONFIG),) +$(error "CONFIG must be specified.") +endif +ifeq ($(CPU)$(KDIR),) +$(error "KDIR or CPU must be specified.") +endif + +ifeq ($(USING_UMP),1) +ifeq ($(USE_UMPV2),1) +UMP_SYMVERS_FILE ?= ../umpv2/Module.symvers +else +UMP_SYMVERS_FILE ?= ../ump/Module.symvers +endif +KBUILD_EXTRA_SYMBOLS = $(realpath $(UMP_SYMVERS_FILE)) +$(warning $(KBUILD_EXTRA_SYMBOLS)) +endif + +# Get any user defined KDIR- or maybe even a hardcoded KDIR +-include KDIR_CONFIGURATION + +# Define host system directory +KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build + +ifeq ($(ARCH), arm) +# when compiling for ARM we're cross compiling +export CROSS_COMPILE ?= $(call check_cc2, arm-linux-gnueabi-gcc, arm-linux-gnueabi-, arm-none-linux-gnueabi-) +endif + +# look up KDIR based om CPU selection +KDIR ?= $(KDIR-$(CPU)) + +# validate lookup result +ifeq ($(KDIR),) +$(error No KDIR found for platform $(CPU)) +endif + +# report detected/selected settings +ifdef ARM_INTERNAL_BUILD +$(warning Config $(CONFIG)) +$(warning Host CPU $(CPU)) +$(warning OS_MEMORY $(USING_OS_MEMORY)) +endif + +# Set up build config +export CONFIG_MALI400=m + +ifeq ($(USING_GPU_UTILIZATION),1) +export EXTRA_DEFINES += -DCONFIG_MALI400_GPU_UTILIZATION=1 +export CONFIG_MALI400_GPU_UTILIZATION := y +endif + +all: $(UMP_SYMVERS_FILE) + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) modules + @rm $(FILES_PREFIX)__malidrv_build_info.c $(FILES_PREFIX)__malidrv_build_info.o + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + +kernelrelease: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) kernelrelease + +export CONFIG KBUILD_EXTRA_SYMBOLS diff --git a/drivers/media/video/samsung/mali/arch b/drivers/media/video/samsung/mali/arch new file mode 120000 index 0000000..58ffbe7 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch @@ -0,0 +1 @@ +arch-release \ No newline at end of file diff --git a/drivers/media/video/samsung/mali/arch-debug b/drivers/media/video/samsung/mali/arch-debug new file mode 120000 index 0000000..0ed0909 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-debug @@ -0,0 +1 @@ +arch-pegasus-m400/ \ No newline at end of file diff --git a/drivers/media/video/samsung/mali/arch-orion-m400/config.h b/drivers/media/video/samsung/mali/arch-orion-m400/config.h new file mode 100644 index 0000000..73502a2 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-orion-m400/config.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the EB platform with ZBT memory enabled */ +/*zepplin added 2010.08.17 for orion configuration*/ +#define MALI_BASE_ADDR 0x13000000 +#define GP_ADDR MALI_BASE_ADDR +#define L2_ADDR MALI_BASE_ADDR+0x1000 +#define PMU_ADDR MALI_BASE_ADDR+0x2000 +#define GP_MMU_ADDR MALI_BASE_ADDR+0x3000 +#define PP0_MMU_ADDR MALI_BASE_ADDR+0x4000 +#define PP1_MMU_ADDR MALI_BASE_ADDR+0x5000 +#define PP2_MMU_ADDR MALI_BASE_ADDR+0x6000 +#define PP3_MMU_ADDR MALI_BASE_ADDR+0x7000 +#define PP0_ADDR MALI_BASE_ADDR+0x8000 +#define PP1_ADDR MALI_BASE_ADDR+0xA000 +#define PP2_ADDR MALI_BASE_ADDR+0xC000 +#define PP3_ADDR MALI_BASE_ADDR+0xE000 + +/*for mmu and os memory*/ +#define MEM_BASE_ADDR 0x40000000 +#define MEM_TOTAL_SIZE 0x40000000 +#define MEM_MALI_OS_SIZE 0x40000000 + +/*for dedicated memory*/ +//#define MEM_MALI_BASE 0x58000000 +//#define MEM_MALI_SIZE 0x08000000 +#define MEM_MALI_SIZE CONFIG_MALI_MEM_SIZE*1024*1024 +#define MEM_MALI_BASE 0x80000000 - MEM_MALI_SIZE + +static _mali_osk_resource_t arch_configuration [] = +{ + { + .type = MALI400GP, + .description = "Mali-400 GP", + .base = GP_ADDR, + .irq = IRQ_GP_3D, + .mmu_id = 1 + }, + { + .type = MALI400PP, + .base = PP0_ADDR, + .irq = IRQ_PP0_3D, + .description = "Mali-400 PP 0", + .mmu_id = 2 + }, + { + .type = MALI400PP, + .base = PP1_ADDR, + .irq = IRQ_PP1_3D, + .description = "Mali-400 PP 1", + .mmu_id = 3 + }, + { + .type = MALI400PP, + .base = PP2_ADDR, + .irq = IRQ_PP2_3D, + .description = "Mali-400 PP 2", + .mmu_id = 4 + }, + { + .type = MALI400PP, + .base = PP3_ADDR, + .irq = IRQ_PP3_3D, + .description = "Mali-400 PP 3", + .mmu_id = 5 + }, +#if USING_MMU + { + .type = MMU, + .base = GP_MMU_ADDR, + .irq = IRQ_GPMMU_3D, + .description = "Mali-400 MMU for GP", + .mmu_id = 1 + }, + { + .type = MMU, + .base = PP0_MMU_ADDR, + .irq = IRQ_PPMMU0_3D, + .description = "Mali-400 MMU for PP 0", + .mmu_id = 2 + }, + { + .type = MMU, + .base = PP1_MMU_ADDR, + .irq = IRQ_PPMMU1_3D, + .description = "Mali-400 MMU for PP 1", + .mmu_id = 3 + }, + { + .type = MMU, + .base = PP2_MMU_ADDR, + .irq = IRQ_PPMMU2_3D, + .description = "Mali-400 MMU for PP 2", + .mmu_id = 4 + }, + { + .type = MMU, + .base = PP3_MMU_ADDR, + .irq = IRQ_PPMMU3_3D, + .description = "Mali-400 MMU for PP 3", + .mmu_id = 5 + }, +#if USING_OS_MEMORY + { + .type = OS_MEMORY, + .description = "System Memory", + .size = MEM_MALI_OS_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, +#endif +#if USING_DED /* Dedicated Memory */ + { + .type = MEMORY, + .description = "Dedicated Memory", + .base = MEM_MALI_BASE, + .size = MEM_MALI_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE + }, +#endif/* if USING_OS_MEMORY*/ + { + .type = MEM_VALIDATION, + .description = "Framebuffer Memory", + .base = MEM_BASE_ADDR, + .size = MEM_TOTAL_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE + }, +#else /* Not using MMU */ + { + .type = MEMORY, + .description = "Dedicated Memory", + .base = MEM_MALI_BASE, + .size = MEM_MALI_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE + }, +#endif + { + .type = MALI400L2, + .base = L2_ADDR, + .description = "Mali-400 L2 cache" + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h new file mode 100644 index 0000000..e579526 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the PB platform with ZBT memory enabled */ + +static _mali_osk_resource_t arch_configuration [] = +{ + { + .type = PMU, + .description = "Mali-300 PMU", + .base = 0xC0002000, + .irq = -1, + .mmu_id = 0 + + }, + { + .type = MALI300GP, + .description = "Mali-300 GP", + .base = 0xC0000000, + .irq = -1, + .mmu_id = 1 + }, + { + .type = MALI300PP, + .base = 0xc0008000, + .irq = -1, + .description = "Mali-300 PP", + .mmu_id = 2 + }, + { + .type = MMU, + .base = 0xC0003000, + .irq = -1, + .description = "Mali-300 MMU for GP", + .mmu_id = 1 + }, + { + .type = MMU, + .base = 0xC0004000, + .irq = -1, + .description = "Mali-300 MMU for PP", + .mmu_id = 2 + }, + { + .type = MEMORY, + .description = "Mali SDRAM remapped to baseboard", + .cpu_usage_adjust = -0x50000000, + .alloc_order = 0, /* Highest preference for this memory */ + .base = 0xD0000000, + .size = 0x10000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEMORY, + .description = "Mali ZBT", + .alloc_order = 5, /* Medium preference for this memory */ + .base = 0xe1000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEM_VALIDATION, + .description = "Framebuffer", + .base = 0xe0000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE + }, + { + .type = MALI300L2, + .base = 0xC0001000, + .description = "Mali-300 L2 cache" + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h new file mode 100644 index 0000000..3893d72 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the PB platform with ZBT memory enabled */ + +static _mali_osk_resource_t arch_configuration [] = +{ + + { + .type = PMU, + .description = "Mali-400 PMU", + .base = 0xC0002000, + .irq = -1, + .mmu_id = 0 + }, + { + .type = MALI400GP, + .description = "Mali-400 GP", + .base = 0xC0000000, + .irq = -1, + .mmu_id = 1 + }, + { + .type = MALI400PP, + .base = 0xc0008000, + .irq = -1, + .description = "Mali-400 PP", + .mmu_id = 2 + }, + { + .type = MMU, + .base = 0xC0003000, + .irq = -1, + .description = "Mali-400 MMU for GP", + .mmu_id = 1 + }, + { + .type = MMU, + .base = 0xC0004000, + .irq = -1, + .description = "Mali-400 MMU for PP", + .mmu_id = 2 + }, + { + .type = OS_MEMORY, + .description = "OS Memory", + .alloc_order = 10, /* Lowest preference for this memory */ + .size = 96 * 1024 * 1024, /* 96 MB */ + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEMORY, + .description = "Mali SDRAM remapped to baseboard", + .cpu_usage_adjust = 0, + .alloc_order = 5, /* Medium preference for this memory */ + .base = 0x80000000, + .size = 0x10000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEMORY, + .description = "Mali ZBT", + .alloc_order = 0, /* Highest preference for this memory */ + .base = 0xe1000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEM_VALIDATION, + .description = "Framebuffer", + .base = 0xe0000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE + }, + { + .type = MALI400L2, + .base = 0xC0001000, + .description = "Mali-400 L2 cache" + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h new file mode 100644 index 0000000..6d84ab1 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the PB platform with ZBT memory enabled */ + +static _mali_osk_resource_t arch_configuration [] = +{ + { + .type = PMU, + .description = "Mali-400 PMU", + .base = 0xC0002000, + .irq = -1, + .mmu_id = 0 + + }, + { + .type = MALI400GP, + .description = "Mali-400 GP", + .base = 0xC0000000, + .irq = -1, + .mmu_id = 1 + }, + { + .type = MALI400PP, + .base = 0xc0008000, + .irq = -1, + .description = "Mali-400 PP", + .mmu_id = 2 + }, + { + .type = MMU, + .base = 0xC0003000, + .irq = -1, + .description = "Mali-400 MMU for GP", + .mmu_id = 1 + }, + { + .type = MMU, + .base = 0xC0004000, + .irq = -1, + .description = "Mali-400 MMU for PP", + .mmu_id = 2 + }, + { + .type = MEMORY, + .description = "Mali SDRAM remapped to baseboard", + .cpu_usage_adjust = -0x50000000, + .alloc_order = 0, /* Highest preference for this memory */ + .base = 0xD0000000, + .size = 0x10000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEMORY, + .description = "Mali ZBT", + .alloc_order = 5, /* Medium preference for this memory */ + .base = 0xe1000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEM_VALIDATION, + .description = "Framebuffer", + .base = 0xe0000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE + }, + { + .type = MALI400L2, + .base = 0xC0001000, + .description = "Mali-400 L2 cache" + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h new file mode 100644 index 0000000..568ac0a --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the PB platform with ZBT memory enabled */ + +static _mali_osk_resource_t arch_configuration [] = +{ + { + .type = MALI400GP, + .description = "Mali-400 GP", + .base = 0xC0000000, + .irq = -1, + .mmu_id = 1 + }, + { + .type = MALI400PP, + .base = 0xc0008000, + .irq = -1, + .description = "Mali-400 PP", + .mmu_id = 2 + }, + { + .type = MMU, + .base = 0xC0003000, + .irq = -1, + .description = "Mali-400 MMU for GP", + .mmu_id = 1 + }, + { + .type = MMU, + .base = 0xC0004000, + .irq = -1, + .description = "Mali-400 MMU for PP", + .mmu_id = 2 + }, + { + .type = MEMORY, + .description = "Mali SDRAM remapped to baseboard", + .cpu_usage_adjust = -0x50000000, + .alloc_order = 0, /* Highest preference for this memory */ + .base = 0xD0000000, + .size = 0x10000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEMORY, + .description = "Mali ZBT", + .alloc_order = 5, /* Medium preference for this memory */ + .base = 0xe1000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEM_VALIDATION, + .description = "Framebuffer", + .base = 0xe0000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE + }, + { + .type = MALI400L2, + .base = 0xC0001000, + .description = "Mali-400 L2 cache" + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h new file mode 100644 index 0000000..98b8059 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the PB platform with ZBT memory enabled */ + +static _mali_osk_resource_t arch_configuration [] = +{ + { + .type = MALI400GP, + .description = "Mali-400 GP", + .base = 0xC0000000, + .irq = -1, + .mmu_id = 1 + }, + { + .type = MALI400PP, + .base = 0xc0008000, + .irq = -1, + .description = "Mali-400 PP 0", + .mmu_id = 2 + }, + { + .type = MALI400PP, + .base = 0xc000A000, + .irq = -1, + .description = "Mali-400 PP 1", + .mmu_id = 3 + }, + { + .type = MMU, + .base = 0xC0003000, + .irq = -1, + .description = "Mali-400 MMU for GP", + .mmu_id = 1 + }, + { + .type = MMU, + .base = 0xC0004000, + .irq = -1, + .description = "Mali-400 MMU for PP 0", + .mmu_id = 2 + }, + { + .type = MMU, + .base = 0xC0005000, + .irq = -1, + .description = "Mali-400 MMU for PP 1", + .mmu_id = 3 + }, + { + .type = MEMORY, + .description = "Mali SDRAM remapped to baseboard", + .cpu_usage_adjust = -0x50000000, + .alloc_order = 0, /* Highest preference for this memory */ + .base = 0xD0000000, + .size = 0x10000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEMORY, + .description = "Mali ZBT", + .alloc_order = 5, /* Medium preference for this memory */ + .base = 0xe1000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEM_VALIDATION, + .description = "Framebuffer", + .base = 0xe0000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE + }, + { + .type = MALI400L2, + .base = 0xC0001000, + .description = "Mali-400 L2 cache" + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h new file mode 100644 index 0000000..7b10925 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the PB platform with ZBT memory enabled */ + +static _mali_osk_resource_t arch_configuration [] = +{ + { + .type = MALI400GP, + .description = "Mali-400 GP", + .base = 0xC0000000, + .irq = -1, + .mmu_id = 1 + }, + { + .type = MALI400PP, + .base = 0xc0008000, + .irq = -1, + .description = "Mali-400 PP 0", + .mmu_id = 2 + }, + { + .type = MALI400PP, + .base = 0xc000A000, + .irq = -1, + .description = "Mali-400 PP 1", + .mmu_id = 3 + }, + { + .type = MALI400PP, + .base = 0xc000C000, + .irq = -1, + .description = "Mali-400 PP 2", + .mmu_id = 4 + }, + { + .type = MMU, + .base = 0xC0003000, + .irq = 102, + .description = "Mali-400 MMU for GP", + .mmu_id = 1 + }, + { + .type = MMU, + .base = 0xC0004000, + .irq = 102, + .description = "Mali-400 MMU for PP 0", + .mmu_id = 2 + }, + { + .type = MMU, + .base = 0xC0005000, + .irq = 102, + .description = "Mali-400 MMU for PP 1", + .mmu_id = 3 + }, + { + .type = MMU, + .base = 0xC0006000, + .irq = 102, + .description = "Mali-400 MMU for PP 2", + .mmu_id = 4 + }, + { + .type = MEMORY, + .description = "Mali SDRAM remapped to baseboard", + .cpu_usage_adjust = -0x50000000, + .alloc_order = 0, /* Highest preference for this memory */ + .base = 0xD0000000, + .size = 0x10000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEMORY, + .description = "Mali ZBT", + .alloc_order = 5, /* Medium preference for this memory */ + .base = 0xe1000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEM_VALIDATION, + .description = "Framebuffer", + .base = 0xe0000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE + }, + { + .type = MALI400L2, + .base = 0xC0001000, + .description = "Mali-400 L2 cache" + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h new file mode 100644 index 0000000..a15a6bd --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the EB platform with ZBT memory enabled */ + +static _mali_osk_resource_t arch_configuration [] = +{ + { + .type = MALI400GP, + .description = "Mali-400 GP", + .base = 0xC0000000, + .irq = -1, + .mmu_id = 1 + }, + { + .type = MALI400PP, + .base = 0xc0008000, + .irq = -1, + .description = "Mali-400 PP 0", + .mmu_id = 2 + }, + { + .type = MALI400PP, + .base = 0xc000A000, + .irq = -1, + .description = "Mali-400 PP 1", + .mmu_id = 3 + }, + { + .type = MALI400PP, + .base = 0xc000C000, + .irq = -1, + .description = "Mali-400 PP 2", + .mmu_id = 4 + }, + { + .type = MALI400PP, + .base = 0xc000E000, + .irq = -1, + .description = "Mali-400 PP 3", + .mmu_id = 5 + }, + { + .type = MMU, + .base = 0xC0003000, + .irq = 102, + .description = "Mali-400 MMU for GP", + .mmu_id = 1 + }, + { + .type = MMU, + .base = 0xC0004000, + .irq = 102, + .description = "Mali-400 MMU for PP 0", + .mmu_id = 2 + }, + { + .type = MMU, + .base = 0xC0005000, + .irq = 102, + .description = "Mali-400 MMU for PP 1", + .mmu_id = 3 + }, + { + .type = MMU, + .base = 0xC0006000, + .irq = 102, + .description = "Mali-400 MMU for PP 2", + .mmu_id = 4 + }, + { + .type = MMU, + .base = 0xC0007000, + .irq = 102, + .description = "Mali-400 MMU for PP 3", + .mmu_id = 5 + }, + { + .type = MEMORY, + .description = "Mali SDRAM remapped to baseboard", + .cpu_usage_adjust = -0x50000000, + .alloc_order = 0, /* Highest preference for this memory */ + .base = 0xD0000000, + .size = 0x10000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEMORY, + .description = "Mali ZBT", + .alloc_order = 5, /* Medium preference for this memory */ + .base = 0xe1000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEM_VALIDATION, + .description = "Framebuffer", + .base = 0xe0000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE + }, + { + .type = MALI400L2, + .base = 0xC0001000, + .description = "Mali-400 L2 cache" + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h b/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h new file mode 100644 index 0000000..d5196c3 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the EB platform with ZBT memory enabled */ +/*zepplin added 2010.08.17 for orion configuration*/ +#define MALI_BASE_ADDR 0x13000000 +#define GP_ADDR MALI_BASE_ADDR +#define L2_ADDR MALI_BASE_ADDR+0x1000 +#define PMU_ADDR MALI_BASE_ADDR+0x2000 +#define GP_MMU_ADDR MALI_BASE_ADDR+0x3000 +#define PP0_MMU_ADDR MALI_BASE_ADDR+0x4000 +#define PP1_MMU_ADDR MALI_BASE_ADDR+0x5000 +#define PP2_MMU_ADDR MALI_BASE_ADDR+0x6000 +#define PP3_MMU_ADDR MALI_BASE_ADDR+0x7000 +#define PP0_ADDR MALI_BASE_ADDR+0x8000 +#define PP1_ADDR MALI_BASE_ADDR+0xA000 +#define PP2_ADDR MALI_BASE_ADDR+0xC000 +#define PP3_ADDR MALI_BASE_ADDR+0xE000 + +/*for mmu and os memory*/ +#define MEM_BASE_ADDR 0x40000000 +#define MEM_TOTAL_SIZE 0x40000000 +#define MEM_MALI_OS_SIZE 0x40000000 + +/*for dedicated memory*/ +//#define MEM_MALI_BASE 0x58000000 +//#define MEM_MALI_SIZE 0x08000000 +#define MEM_MALI_SIZE CONFIG_MALI_MEM_SIZE*1024*1024 +#define MEM_MALI_BASE 0x80000000 - MEM_MALI_SIZE + +static _mali_osk_resource_t arch_configuration [] = +{ + { + .type = MALI400GP, + .description = "Mali-400 GP", + .base = GP_ADDR, + .irq = IRQ_GP_3D, + .mmu_id = 1 + }, + { + .type = MALI400PP, + .base = PP0_ADDR, + .irq = IRQ_PP0_3D, + .description = "Mali-400 PP 0", + .mmu_id = 2 + }, + { + .type = MALI400PP, + .base = PP1_ADDR, + .irq = IRQ_PP1_3D, + .description = "Mali-400 PP 1", + .mmu_id = 3 + }, + { + .type = MALI400PP, + .base = PP2_ADDR, + .irq = IRQ_PP2_3D, + .description = "Mali-400 PP 2", + .mmu_id = 4 + }, + { + .type = MALI400PP, + .base = PP3_ADDR, + .irq = IRQ_PP3_3D, + .description = "Mali-400 PP 3", + .mmu_id = 5 + }, +#if USING_MMU + { + .type = MMU, + .base = GP_MMU_ADDR, + .irq = IRQ_GPMMU_3D, + .description = "Mali-400 MMU for GP", + .mmu_id = 1 + }, + { + .type = MMU, + .base = PP0_MMU_ADDR, + .irq = IRQ_PPMMU0_3D, + .description = "Mali-400 MMU for PP 0", + .mmu_id = 2 + }, + { + .type = MMU, + .base = PP1_MMU_ADDR, + .irq = IRQ_PPMMU1_3D, + .description = "Mali-400 MMU for PP 1", + .mmu_id = 3 + }, + { + .type = MMU, + .base = PP2_MMU_ADDR, + .irq = IRQ_PPMMU2_3D, + .description = "Mali-400 MMU for PP 2", + .mmu_id = 4 + }, + { + .type = MMU, + .base = PP3_MMU_ADDR, + .irq = IRQ_PPMMU3_3D, + .description = "Mali-400 MMU for PP 3", + .mmu_id = 5 + }, +#if USING_OS_MEMORY + { + .type = OS_MEMORY, + .description = "System Memory", + .size = MEM_MALI_OS_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, +#endif +#if USING_DED /* Dedicated Memory */ + { + .type = MEMORY, + .description = "Dedicated Memory", + .base = MEM_MALI_BASE, + .size = MEM_MALI_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE + }, +#endif/* if USING_OS_MEMORY*/ + { + .type = MEM_VALIDATION, + .description = "memory validation", + .base = MEM_BASE_ADDR, + .size = MEM_TOTAL_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE + }, +#else /* Not using MMU */ + { + .type = MEMORY, + .description = "Dedicated Memory", + .base = MEM_MALI_BASE, + .size = MEM_MALI_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE + }, +#endif + { + .type = MALI400L2, + .base = L2_ADDR, + .description = "Mali-400 L2 cache" + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-release b/drivers/media/video/samsung/mali/arch-release new file mode 120000 index 0000000..0ed0909 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-release @@ -0,0 +1 @@ +arch-pegasus-m400/ \ No newline at end of file diff --git a/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h b/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h new file mode 100644 index 0000000..eb5da50 --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the Versatile Express platform */ + +#define MALI_BASE_ADDRESS 0xFC040000 + +static _mali_osk_resource_t arch_configuration [] = +{ + /* PMU */ + { + .type = PMU, + .base = MALI_BASE_ADDRESS + 0x02000, + .description = "MALI PMU" + }, + /* GP cluster */ + { + .type = MALI400L2, + .base = MALI_BASE_ADDRESS + 0x10000, + .description = "Mali-450 L2 cache for GP" + }, + { + .type = MALI400GP, + .description = "Mali-450 GP", + .base = MALI_BASE_ADDRESS, + .irq = -1, + }, + { + .type = MMU, + .base = MALI_BASE_ADDRESS + 0x3000, + .irq = 70, + .description = "Mali-450 MMU for GP", + }, + + /* PP0-3 cluster */ + { + .type = MALI400L2, + .base = MALI_BASE_ADDRESS + 0x1000, + .description = "Mali-450 L2 cache for PP0-3" + }, + { + .type = MALI400PP, + .base = MALI_BASE_ADDRESS + 0x8000, + .irq = 70, + .description = "Mali-450 PP0", + }, + { + .type = MMU, + .base = MALI_BASE_ADDRESS + 0x4000, + .irq = 70, + .description = "Mali-450 MMU for PP0", + }, + { + .type = MALI400PP, + .base = MALI_BASE_ADDRESS + 0xA000, + .irq = 70, + .description = "Mali-450 PP1", + }, + { + .type = MMU, + .base = MALI_BASE_ADDRESS + 0x5000, + .irq = 70, + .description = "Mali-450 MMU for PP1", + }, + { + .type = MALI400PP, + .base = MALI_BASE_ADDRESS + 0xC000, + .irq = 70, + .description = "Mali-450 PP2", + }, + { + .type = MMU, + .base = MALI_BASE_ADDRESS + 0x6000, + .irq = 70, + .description = "Mali-450 MMU for PP2", + }, + { + .type = MALI400PP, + .base = MALI_BASE_ADDRESS + 0xE000, + .irq = 70, + .description = "Mali-450 PP3", + }, + { + .type = MMU, + .base = MALI_BASE_ADDRESS + 0x7000, + .irq = 70, + .description = "Mali-450 MMU for PP3", + }, + + /* PP4-7 cluster */ + { + .type = MALI400L2, + .base = MALI_BASE_ADDRESS + 0x11000, + .description = "Mali-450 L2 cache for PP4-7" + }, + { + .type = MALI400PP, + .base = MALI_BASE_ADDRESS + 0x28000, + .irq = 70, + .description = "Mali-450 PP4", + }, + { + .type = MMU, + .base = MALI_BASE_ADDRESS + 0x1C000, + .irq = 70, + .description = "Mali-450 MMU for PP4", + }, + { + .type = MALI400PP, + .base = MALI_BASE_ADDRESS + 0x2A000, + .irq = 70, + .description = "Mali-450 PP5", + }, + { + .type = MMU, + .base = MALI_BASE_ADDRESS + 0x1D000, + .irq = 70, + .description = "Mali-450 MMU for PP5", + }, + { + .type = MALI400PP, + .base = MALI_BASE_ADDRESS + 0x2C000, + .irq = 70, + .description = "Mali-450 PP6", + }, + { + .type = MMU, + .base = MALI_BASE_ADDRESS + 0x1E000, + .irq = 70, + .description = "Mali-450 MMU for PP6", + }, + { + .type = MALI400PP, + .base = MALI_BASE_ADDRESS + 0x2E000, + .irq = 70, + .description = "Mali-450 PP7", + }, + { + .type = MMU, + .base = MALI_BASE_ADDRESS + 0x1F000, + .irq = 70, + .description = "Mali-450 MMU for PP7", + }, + + /* Memory */ + { + .type = OS_MEMORY, + .description = "Mali OS memory", + .cpu_usage_adjust = 0, + .alloc_order = 0, /* Highest preference for this memory */ + .base = 0x0, + .size = 256 * 1024 * 1024, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, + { + .type = MEM_VALIDATION, + .description = "Framebuffer", + .base = 0xe0000000, + .size = 0x01000000, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_block_allocator.c b/drivers/media/video/samsung/mali/common/mali_block_allocator.c new file mode 100644 index 0000000..269e662 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_block_allocator.c @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#include "mali_kernel_memory_engine.h" +#include "mali_block_allocator.h" +#include "mali_osk.h" + +#define MALI_BLOCK_SIZE (256UL * 1024UL) /* 256 kB, remember to keep the ()s */ + +typedef struct block_info +{ + struct block_info * next; +} block_info; + +/* The structure used as the handle produced by block_allocator_allocate, + * and removed by block_allocator_release */ +typedef struct block_allocator_allocation +{ + /* The list will be released in reverse order */ + block_info *last_allocated; + mali_allocation_engine * engine; + mali_memory_allocation * descriptor; + u32 start_offset; + u32 mapping_length; +} block_allocator_allocation; + + +typedef struct block_allocator +{ + _mali_osk_lock_t *mutex; + block_info * all_blocks; + block_info * first_free; + u32 base; + u32 cpu_usage_adjust; + u32 num_blocks; +} block_allocator; + +MALI_STATIC_INLINE u32 get_phys(block_allocator * info, block_info * block); +static mali_physical_memory_allocation_result block_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); +static void block_allocator_release(void * ctx, void * handle); +static mali_physical_memory_allocation_result block_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block); +static void block_allocator_release_page_table_block( mali_page_table_block *page_table_block ); +static void block_allocator_destroy(mali_physical_memory_allocator * allocator); +static u32 block_allocator_stat(mali_physical_memory_allocator * allocator); + +mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size, const char *name) +{ + mali_physical_memory_allocator * allocator; + block_allocator * info; + u32 usable_size; + u32 num_blocks; + + usable_size = size & ~(MALI_BLOCK_SIZE - 1); + MALI_DEBUG_PRINT(3, ("Mali block allocator create for region starting at 0x%08X length 0x%08X\n", base_address, size)); + MALI_DEBUG_PRINT(4, ("%d usable bytes\n", usable_size)); + num_blocks = usable_size / MALI_BLOCK_SIZE; + MALI_DEBUG_PRINT(4, ("which becomes %d blocks\n", num_blocks)); + + if (usable_size == 0) + { + MALI_DEBUG_PRINT(1, ("Memory block of size %d is unusable\n", size)); + return NULL; + } + + allocator = _mali_osk_malloc(sizeof(mali_physical_memory_allocator)); + if (NULL != allocator) + { + info = _mali_osk_malloc(sizeof(block_allocator)); + if (NULL != info) + { + info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_MEM_INFO); + if (NULL != info->mutex) + { + info->all_blocks = _mali_osk_malloc(sizeof(block_info) * num_blocks); + if (NULL != info->all_blocks) + { + u32 i; + info->first_free = NULL; + info->num_blocks = num_blocks; + + info->base = base_address; + info->cpu_usage_adjust = cpu_usage_adjust; + + for ( i = 0; i < num_blocks; i++) + { + info->all_blocks[i].next = info->first_free; + info->first_free = &info->all_blocks[i]; + } + + allocator->allocate = block_allocator_allocate; + allocator->allocate_page_table_block = block_allocator_allocate_page_table_block; + allocator->destroy = block_allocator_destroy; + allocator->stat = block_allocator_stat; + allocator->ctx = info; + allocator->name = name; + + return allocator; + } + _mali_osk_lock_term(info->mutex); + } + _mali_osk_free(info); + } + _mali_osk_free(allocator); + } + + return NULL; +} + +static void block_allocator_destroy(mali_physical_memory_allocator * allocator) +{ + block_allocator * info; + MALI_DEBUG_ASSERT_POINTER(allocator); + MALI_DEBUG_ASSERT_POINTER(allocator->ctx); + info = (block_allocator*)allocator->ctx; + + _mali_osk_free(info->all_blocks); + _mali_osk_lock_term(info->mutex); + _mali_osk_free(info); + _mali_osk_free(allocator); +} + +MALI_STATIC_INLINE u32 get_phys(block_allocator * info, block_info * block) +{ + return info->base + ((block - info->all_blocks) * MALI_BLOCK_SIZE); +} + +static mali_physical_memory_allocation_result block_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + block_allocator * info; + u32 left; + block_info * last_allocated = NULL; + mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_NONE; + block_allocator_allocation *ret_allocation; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(offset); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + info = (block_allocator*)ctx; + left = descriptor->size - *offset; + MALI_DEBUG_ASSERT(0 != left); + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; + + ret_allocation = _mali_osk_malloc( sizeof(block_allocator_allocation) ); + + if ( NULL == ret_allocation ) + { + /* Failure; try another allocator by returning MALI_MEM_ALLOC_NONE */ + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + return result; + } + + ret_allocation->start_offset = *offset; + ret_allocation->mapping_length = 0; + + while ((left > 0) && (info->first_free)) + { + block_info * block; + u32 phys_addr; + u32 padding; + u32 current_mapping_size; + + block = info->first_free; + info->first_free = info->first_free->next; + block->next = last_allocated; + last_allocated = block; + + phys_addr = get_phys(info, block); + + padding = *offset & (MALI_BLOCK_SIZE-1); + + if (MALI_BLOCK_SIZE - padding < left) + { + current_mapping_size = MALI_BLOCK_SIZE - padding; + } + else + { + current_mapping_size = left; + } + + if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, phys_addr + padding, info->cpu_usage_adjust, current_mapping_size)) + { + MALI_DEBUG_PRINT(1, ("Mapping of physical memory failed\n")); + result = MALI_MEM_ALLOC_INTERNAL_FAILURE; + mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->start_offset, ret_allocation->mapping_length, (_mali_osk_mem_mapregion_flags_t)0); + + /* release all memory back to the pool */ + while (last_allocated) + { + /* This relinks every block we've just allocated back into the free-list */ + block = last_allocated->next; + last_allocated->next = info->first_free; + info->first_free = last_allocated; + last_allocated = block; + } + + break; + } + + *offset += current_mapping_size; + left -= current_mapping_size; + ret_allocation->mapping_length += current_mapping_size; + } + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + if (last_allocated) + { + if (left) result = MALI_MEM_ALLOC_PARTIAL; + else result = MALI_MEM_ALLOC_FINISHED; + + /* Record all the information about this allocation */ + ret_allocation->last_allocated = last_allocated; + ret_allocation->engine = engine; + ret_allocation->descriptor = descriptor; + + alloc_info->ctx = info; + alloc_info->handle = ret_allocation; + alloc_info->release = block_allocator_release; + } + else + { + /* Free the allocation information - nothing to be passed back */ + _mali_osk_free( ret_allocation ); + } + + return result; +} + +static void block_allocator_release(void * ctx, void * handle) +{ + block_allocator * info; + block_info * block, * next; + block_allocator_allocation *allocation; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(handle); + + info = (block_allocator*)ctx; + allocation = (block_allocator_allocation*)handle; + block = allocation->last_allocated; + + MALI_DEBUG_ASSERT_POINTER(block); + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) + { + MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); + return; + } + + /* unmap */ + mali_allocation_engine_unmap_physical(allocation->engine, allocation->descriptor, allocation->start_offset, allocation->mapping_length, (_mali_osk_mem_mapregion_flags_t)0); + + while (block) + { + MALI_DEBUG_ASSERT(!((block < info->all_blocks) || (block > (info->all_blocks + info->num_blocks)))); + + next = block->next; + + /* relink into free-list */ + block->next = info->first_free; + info->first_free = block; + + /* advance the loop */ + block = next; + } + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_free( allocation ); +} + + +static mali_physical_memory_allocation_result block_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) +{ + block_allocator * info; + mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_INTERNAL_FAILURE; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(block); + info = (block_allocator*)ctx; + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; + + if (NULL != info->first_free) + { + void * virt; + u32 phys; + u32 size; + block_info * alloc; + alloc = info->first_free; + + phys = get_phys(info, alloc); /* Does not modify info or alloc */ + size = MALI_BLOCK_SIZE; /* Must be multiple of MALI_MMU_PAGE_SIZE */ + virt = _mali_osk_mem_mapioregion( phys, size, "Mali block allocator page tables" ); + + /* Failure of _mali_osk_mem_mapioregion will result in MALI_MEM_ALLOC_INTERNAL_FAILURE, + * because it's unlikely another allocator will be able to map in. */ + + if ( NULL != virt ) + { + block->ctx = info; /* same as incoming ctx */ + block->handle = alloc; + block->phys_base = phys; + block->size = size; + block->release = block_allocator_release_page_table_block; + block->mapping = virt; + + info->first_free = alloc->next; + + alloc->next = NULL; /* Could potentially link many blocks together instead */ + + result = MALI_MEM_ALLOC_FINISHED; + } + } + else result = MALI_MEM_ALLOC_NONE; + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + return result; +} + + +static void block_allocator_release_page_table_block( mali_page_table_block *page_table_block ) +{ + block_allocator * info; + block_info * block, * next; + + MALI_DEBUG_ASSERT_POINTER( page_table_block ); + + info = (block_allocator*)page_table_block->ctx; + block = (block_info*)page_table_block->handle; + + MALI_DEBUG_ASSERT_POINTER(info); + MALI_DEBUG_ASSERT_POINTER(block); + + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) + { + MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); + return; + } + + /* Unmap all the physical memory at once */ + _mali_osk_mem_unmapioregion( page_table_block->phys_base, page_table_block->size, page_table_block->mapping ); + + /** @note This loop handles the case where more than one block_info was linked. + * Probably unnecessary for page table block releasing. */ + while (block) + { + next = block->next; + + MALI_DEBUG_ASSERT(!((block < info->all_blocks) || (block > (info->all_blocks + info->num_blocks)))); + + block->next = info->first_free; + info->first_free = block; + + block = next; + } + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); +} + +static u32 block_allocator_stat(mali_physical_memory_allocator * allocator) +{ + block_allocator * info; + block_info *block; + u32 free_blocks = 0; + + MALI_DEBUG_ASSERT_POINTER(allocator); + + info = (block_allocator*)allocator->ctx; + block = info->first_free; + + while(block) + { + free_blocks++; + block = block->next; + } + return (info->num_blocks - free_blocks) * MALI_BLOCK_SIZE; +} diff --git a/drivers/media/video/samsung/mali/common/mali_block_allocator.h b/drivers/media/video/samsung/mali/common/mali_block_allocator.h new file mode 100644 index 0000000..6c6f13e --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_block_allocator.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_BLOCK_ALLOCATOR_H__ +#define __MALI_BLOCK_ALLOCATOR_H__ + +#include "mali_kernel_memory_engine.h" + +mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size, const char *name); + +#endif /* __MALI_BLOCK_ALLOCATOR_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_cluster.c b/drivers/media/video/samsung/mali/common/mali_cluster.c new file mode 100644 index 0000000..f0fb2b6 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_cluster.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_cluster.h" +#include "mali_osk.h" +#include "mali_group.h" +#include "mali_l2_cache.h" +#include "mali_scheduler.h" + +static struct mali_cluster *mali_global_clusters[MALI_MAX_NUMBER_OF_CLUSTERS] = { NULL, NULL, NULL }; +static u32 mali_global_num_clusters = 0; + +/** + * The structure represents a render cluster + * A render cluster is defined by all the cores that share the same Mali L2 cache + */ +struct mali_cluster +{ + struct mali_l2_cache_core *l2; + u32 number_of_groups; + struct mali_group* groups[MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER]; + u32 last_invalidated_id; + mali_bool power_is_enabled; +}; + +struct mali_cluster *mali_cluster_create(struct mali_l2_cache_core *l2_cache) +{ + struct mali_cluster *cluster = NULL; + + if (mali_global_num_clusters >= MALI_MAX_NUMBER_OF_CLUSTERS) + { + MALI_PRINT_ERROR(("Mali cluster: Too many cluster objects created\n")); + return NULL; + } + + cluster = _mali_osk_malloc(sizeof(struct mali_cluster)); + if (NULL != cluster) + { + _mali_osk_memset(cluster, 0, sizeof(struct mali_cluster)); + cluster->l2 = l2_cache; /* This cluster now owns this L2 cache object */ + cluster->last_invalidated_id = 0; + cluster->power_is_enabled = MALI_TRUE; + + mali_global_clusters[mali_global_num_clusters] = cluster; + mali_global_num_clusters++; + + return cluster; + } + + return NULL; +} + +void mali_cluster_power_is_enabled_set(struct mali_cluster * cluster, mali_bool power_is_enabled) +{ + cluster->power_is_enabled = power_is_enabled; +} + +mali_bool mali_cluster_power_is_enabled_get(struct mali_cluster * cluster) +{ + return cluster->power_is_enabled; +} + + +void mali_cluster_add_group(struct mali_cluster *cluster, struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(cluster); + + if (cluster->number_of_groups < MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER) + { + /* This cluster now owns the group object */ + cluster->groups[cluster->number_of_groups] = group; + cluster->number_of_groups++; + } +} + +void mali_cluster_delete(struct mali_cluster *cluster) +{ + u32 i; + + MALI_DEBUG_ASSERT_POINTER(cluster); + + /* Free all the resources we own */ + for (i = 0; i < cluster->number_of_groups; i++) + { + mali_group_delete(cluster->groups[i]); + } + + if (NULL != cluster->l2) + { + mali_l2_cache_delete(cluster->l2); + } + + for (i = 0; i < mali_global_num_clusters; i++) + { + if (mali_global_clusters[i] == cluster) + { + mali_global_clusters[i] = NULL; + mali_global_num_clusters--; + break; + } + } + + _mali_osk_free(cluster); +} + +void mali_cluster_reset(struct mali_cluster *cluster) +{ + u32 i; + + MALI_DEBUG_ASSERT_POINTER(cluster); + + /* Free all the resources we own */ + for (i = 0; i < cluster->number_of_groups; i++) + { + struct mali_group *group = cluster->groups[i]; + + mali_group_reset(group); + } + + if (NULL != cluster->l2) + { + mali_l2_cache_reset(cluster->l2); + } +} + +struct mali_l2_cache_core* mali_cluster_get_l2_cache_core(struct mali_cluster *cluster) +{ + MALI_DEBUG_ASSERT_POINTER(cluster); + return cluster->l2; +} + +struct mali_group *mali_cluster_get_group(struct mali_cluster *cluster, u32 index) +{ + MALI_DEBUG_ASSERT_POINTER(cluster); + + if (index < cluster->number_of_groups) + { + return cluster->groups[index]; + } + + return NULL; +} + +struct mali_cluster *mali_cluster_get_global_cluster(u32 index) +{ + if (MALI_MAX_NUMBER_OF_CLUSTERS > index) + { + return mali_global_clusters[index]; + } + + return NULL; +} + +u32 mali_cluster_get_glob_num_clusters(void) +{ + return mali_global_num_clusters; +} + +mali_bool mali_cluster_l2_cache_invalidate_all(struct mali_cluster *cluster, u32 id) +{ + MALI_DEBUG_ASSERT_POINTER(cluster); + + if (NULL != cluster->l2) + { + /* If the last cache invalidation was done by a job with a higher id we + * don't have to flush. Since user space will store jobs w/ their + * corresponding memory in sequence (first job #0, then job #1, ...), + * we don't have to flush for job n-1 if job n has already invalidated + * the cache since we know for sure that job n-1's memory was already + * written when job n was started. */ + if (((s32)id) <= ((s32)cluster->last_invalidated_id)) + { + return MALI_FALSE; + } + else + { + cluster->last_invalidated_id = mali_scheduler_get_new_id(); + } + + mali_l2_cache_invalidate_all(cluster->l2); + } + return MALI_TRUE; +} + +void mali_cluster_l2_cache_invalidate_all_force(struct mali_cluster *cluster) +{ + MALI_DEBUG_ASSERT_POINTER(cluster); + + if (NULL != cluster->l2) + { + cluster->last_invalidated_id = mali_scheduler_get_new_id(); + mali_l2_cache_invalidate_all(cluster->l2); + } +} + +void mali_cluster_invalidate_pages(u32 *pages, u32 num_pages) +{ + u32 i; + + for (i = 0; i < mali_global_num_clusters; i++) + { + /*additional check for cluster*/ + if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_clusters[i]->l2)) + { + mali_l2_cache_invalidate_pages(mali_global_clusters[i]->l2, pages, num_pages); + } + mali_l2_cache_unlock_power_state(mali_global_clusters[i]->l2); + /*check for failed power locking???*/ + } +} diff --git a/drivers/media/video/samsung/mali/common/mali_cluster.h b/drivers/media/video/samsung/mali/common/mali_cluster.h new file mode 100644 index 0000000..33debdb --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_cluster.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_CLUSTER_H__ +#define __MALI_CLUSTER_H__ + +#include "mali_osk.h" +#include "mali_l2_cache.h" + +/* Maximum 1 GP and 4 PP for a cluster (Mali-400 Quad-core) */ +#define MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER 5 +#define MALI_MAX_NUMBER_OF_CLUSTERS 3 + +struct mali_cluster; +struct mali_group; + +struct mali_cluster *mali_cluster_create(struct mali_l2_cache_core *l2_cache); +void mali_cluster_add_group(struct mali_cluster *cluster, struct mali_group *group); +void mali_cluster_delete(struct mali_cluster *cluster); + +void mali_cluster_power_is_enabled_set(struct mali_cluster * cluster, mali_bool power_is_enabled); +mali_bool mali_cluster_power_is_enabled_get(struct mali_cluster * cluster); + +void mali_cluster_reset(struct mali_cluster *cluster); + +struct mali_l2_cache_core* mali_cluster_get_l2_cache_core(struct mali_cluster *cluster); +struct mali_group *mali_cluster_get_group(struct mali_cluster *cluster, u32 index); + +struct mali_cluster *mali_cluster_get_global_cluster(u32 index); +u32 mali_cluster_get_glob_num_clusters(void); + +/* Returns MALI_TRUE if it did the flush */ +mali_bool mali_cluster_l2_cache_invalidate_all(struct mali_cluster *cluster, u32 id); +void mali_cluster_l2_cache_invalidate_all_force(struct mali_cluster *cluster); +void mali_cluster_invalidate_pages(u32 *pages, u32 num_pages); + +#endif /* __MALI_CLUSTER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c new file mode 100644 index 0000000..6af1279 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_device_pause_resume.c + * Implementation of the Mali pause/resume functionality + */ + +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" +#include "mali_pm.h" + +void mali_dev_pause(mali_bool *power_is_on) +{ + mali_gp_scheduler_suspend(); + mali_pp_scheduler_suspend(); + + /* + * Take and hold the PM lock to be sure we don't change power state as well. + * (it might be unsafe to for instance change frequency if Mali GPU is powered off) + */ + mali_pm_execute_state_change_lock(); + if (NULL != power_is_on) + { + *power_is_on = mali_pm_is_powered_on(); + } +} + +void mali_dev_resume(void) +{ + mali_pm_execute_state_change_unlock(); + mali_gp_scheduler_resume(); + mali_pp_scheduler_resume(); +} + +/* +EXPORT_SYMBOL(mali_dev_pause); +EXPORT_SYMBOL(mali_dev_resume); +*/ diff --git a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h new file mode 100644 index 0000000..6be75b0 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_DEVICE_PAUSE_RESUME_H__ +#define __MALI_DEVICE_PAUSE_RESUME_H__ + +#include "mali_osk.h" + +/** + * Pause the scheduling and power state changes of Mali device driver. + * mali_dev_resume() must always be called as soon as possible after this function + * in order to resume normal operation of the Mali driver. + * + * @param power_is_on Receives the power current status of Mali GPU. MALI_TRUE if GPU is powered on + */ +void mali_dev_pause(mali_bool *power_is_on); + +/** + * Resume scheduling and allow power changes in Mali device driver. + * This must always be called after mali_dev_pause(). + */ +void mali_dev_resume(void); + +#endif /* __MALI_DEVICE_PAUSE_RESUME_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_dlbu.c b/drivers/media/video/samsung/mali/common/mali_dlbu.c new file mode 100644 index 0000000..fcc51fa --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_dlbu.c @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_dlbu.h" +#include "mali_memory.h" +#include "mali_pp.h" +#include "mali_group.h" +#include "mali_osk.h" +#include "mali_hw_core.h" + +/** + * Size of DLBU registers in bytes + */ +#define MALI_DLBU_SIZE 0x400 + +u32 mali_dlbu_phys_addr = 0; +static mali_io_address mali_dlbu_cpu_addr = 0; + +static u32 mali_dlbu_tile_position; + +/** + * DLBU register numbers + * Used in the register read/write routines. + * See the hardware documentation for more information about each register + */ +typedef enum mali_dlbu_register { + MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR = 0x0000, /**< Master tile list physical base address; + 31:12 Physical address to the page used for the DLBU + 0 DLBU enable - set this bit to 1 enables the AXI bus + between PPs and L2s, setting to 0 disables the router and + no further transactions are sent to DLBU */ + MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR = 0x0004, /**< Master tile list virtual base address; + 31:12 Virtual address to the page used for the DLBU */ + MALI_DLBU_REGISTER_TLLIST_VBASEADDR = 0x0008, /**< Tile list virtual base address; + 31:12 Virtual address to the tile list. This address is used when + calculating the call address sent to PP.*/ + MALI_DLBU_REGISTER_FB_DIM = 0x000C, /**< Framebuffer dimension; + 23:16 Number of tiles in Y direction-1 + 7:0 Number of tiles in X direction-1 */ + MALI_DLBU_REGISTER_TLLIST_CONF = 0x0010, /**< Tile list configuration; + 29:28 select the size of each allocated block: 0=128 bytes, 1=256, 2=512, 3=1024 + 21:16 2^n number of tiles to be binned to one tile list in Y direction + 5:0 2^n number of tiles to be binned to one tile list in X direction */ + MALI_DLBU_REGISTER_START_TILE_POS = 0x0014, /**< Start tile positions; + 31:24 start position in Y direction for group 1 + 23:16 start position in X direction for group 1 + 15:8 start position in Y direction for group 0 + 7:0 start position in X direction for group 0 */ + MALI_DLBU_REGISTER_PP_ENABLE_MASK = 0x0018, /**< PP enable mask; + 7 enable PP7 for load balancing + 6 enable PP6 for load balancing + 5 enable PP5 for load balancing + 4 enable PP4 for load balancing + 3 enable PP3 for load balancing + 2 enable PP2 for load balancing + 1 enable PP1 for load balancing + 0 enable PP0 for load balancing */ +} mali_dlbu_register; + +typedef enum +{ + PP0ENABLE = 0, + PP1ENABLE, + PP2ENABLE, + PP3ENABLE, + PP4ENABLE, + PP5ENABLE, + PP6ENABLE, + PP7ENABLE +} mali_dlbu_pp_enable; + +struct mali_dlbu_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + u32 pp_cores_mask; /**< This is a mask for the PP cores whose operation will be controlled by LBU + see MALI_DLBU_REGISTER_PP_ENABLE_MASK register */ +}; + +_mali_osk_errcode_t mali_dlbu_initialize(void) +{ + + MALI_DEBUG_PRINT(2, ("Dynamic Load Balancing Unit initializing\n")); + + if (_MALI_OSK_ERR_OK == mali_mmu_get_table_page(&mali_dlbu_phys_addr, &mali_dlbu_cpu_addr)) + { + MALI_SUCCESS; + } + + return _MALI_OSK_ERR_FAULT; +} + +void mali_dlbu_terminate(void) +{ + MALI_DEBUG_PRINT(3, ("Mali DLBU: terminating\n")); + + mali_mmu_release_table_page(mali_dlbu_phys_addr); +} + +struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource) +{ + struct mali_dlbu_core *core = NULL; + + MALI_DEBUG_PRINT(2, ("Mali DLBU: Creating Mali dynamic load balancing unit: %s\n", resource->description)); + + core = _mali_osk_malloc(sizeof(struct mali_dlbu_core)); + if (NULL != core) + { + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI_DLBU_SIZE)) + { + if (_MALI_OSK_ERR_OK == mali_dlbu_reset(core)) + { + mali_hw_core_register_write(&core->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR, MALI_DLB_VIRT_ADDR); + + return core; + } + MALI_PRINT_ERROR(("Failed to reset DLBU %s\n", core->hw_core.description)); + mali_hw_core_delete(&core->hw_core); + } + + _mali_osk_free(core); + } + else + { + MALI_PRINT_ERROR(("Mali DLBU: Failed to allocate memory for DLBU core\n")); + } + + return NULL; +} + +void mali_dlbu_delete(struct mali_dlbu_core *dlbu) +{ + mali_dlbu_reset(dlbu); + mali_hw_core_delete(&dlbu->hw_core); + _mali_osk_free(dlbu); +} + +void mali_dlbu_enable(struct mali_dlbu_core *dlbu) +{ + u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR); + + wval |= 0x1; + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, wval); +} + +void mali_dlbu_disable(struct mali_dlbu_core *dlbu) +{ + u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR); + + wval |= (wval & 0xFFFFFFFE); + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, wval); +} + +_mali_osk_errcode_t mali_dlbu_enable_pp_core(struct mali_dlbu_core *dlbu, u32 pp_core_enable, u32 val) +{ + u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK); + + if((pp_core_enable < mali_pp_get_glob_num_pp_cores()) && ((0 == val) || (1 == val))) /* check for valid input parameters */ + { + if (val == 1) + { + val = (wval | (pp_core_enable <<= 0x1)); + } + if (val == 0) + { + val = (wval & ~(pp_core_enable << 0x1)); + } + wval |= val; + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, wval); + dlbu->pp_cores_mask = wval; + + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + +void mali_dlbu_enable_all_pp_cores(struct mali_dlbu_core *dlbu) +{ + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask); +} + +void mali_dlbu_disable_all_pp_cores(struct mali_dlbu_core *dlbu) +{ + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, 0x0); +} + +void mali_dlbu_setup(struct mali_dlbu_core *dlbu, u8 fb_xdim, u8 fb_ydim, u8 xtilesize, u8 ytilesize, u8 blocksize, u8 xgr0, u8 ygr0, u8 xgr1, u8 ygr1) +{ + u32 wval = 0x0; + + /* write the framebuffer dimensions */ + wval = (16 << (u32)fb_ydim) | (u32)fb_xdim; + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_FB_DIM, wval); + + /* write the tile list configuration */ + wval = 0x0; + wval = (28 << (u32)blocksize) | (16 << (u32)ytilesize) | ((u32)xtilesize); + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_CONF, wval); + + /* write the start tile position */ + wval = 0x0; + wval = (24 << (u32)ygr1 | (16 << (u32)xgr1) | 8 << (u32)ygr0) | (u32)xgr0; + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, wval); +} + +_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + MALI_DEBUG_ASSERT_POINTER(dlbu); + + MALI_DEBUG_PRINT(4, ("Mali DLBU: mali_dlbu_reset: %s\n", dlbu->hw_core.description)); + + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, mali_dlbu_phys_addr); + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, 0x00); + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_FB_DIM, 0x00); + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_CONF, 0x00); + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, 0x00); + + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask); + + err = _MALI_OSK_ERR_OK; + + return err; +} + +_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + u32 wval, rval; + struct mali_pp_core *pp_core = mali_group_get_pp_core(group); + + /* find the core id and set the mask */ + + if (NULL != pp_core) + { + wval = mali_pp_core_get_id(pp_core); + rval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK); + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, (wval << 0x1) | rval); + err = _MALI_OSK_ERR_OK; + } + + return err; +} + +void mali_dlbu_set_tllist_base_address(struct mali_dlbu_core *dlbu, u32 val) +{ + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, val); +} + +void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu) +{ + /* this function to implement (see documentation): + * 1) clear all bits in the enable register + * 2) wait until all PPs have finished - mali_pp_scheduler.c code - this done in interrupts call? + * 3) read the current tile position registers to get current tile positions - + * note that current tile position register is the same as start tile position - perhaps the name should be changed!!! */ + + /* 1) */ + mali_dlbu_disable_all_pp_cores(dlbu); + + /* 3) */ + mali_dlbu_tile_position = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS); +} + +void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu) +{ + /* this function to implement (see the document): + * 1) configure the dynamic load balancing unit as normal + * 2) set the current tile position registers as read when stopping the job + * 3) configure the PPs to start the job as normal - done by another part of the system - scheduler */ + + /* 1) */ + mali_dlbu_reset(dlbu); + /* ++ setup the needed values - see this */ + + /* 2) */ + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, mali_dlbu_tile_position); +} diff --git a/drivers/media/video/samsung/mali/common/mali_dlbu.h b/drivers/media/video/samsung/mali/common/mali_dlbu.h new file mode 100644 index 0000000..e3c3b9d --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_dlbu.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_DLBU_H__ +#define __MALI_DLBU_H__ + +#include "mali_osk.h" +#include "mali_group.h" + +#define MALI_DLB_VIRT_ADDR 0xFFF00000 /* master tile virtual address fixed at this value and mapped into every session */ + +extern u32 mali_dlbu_phys_addr; + +struct mali_dlbu_core; + +_mali_osk_errcode_t mali_dlbu_initialize(void); +void mali_dlbu_terminate(void); + +struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource); +void mali_dlbu_delete(struct mali_dlbu_core *dlbu); + +void mali_dlbu_enable(struct mali_dlbu_core *dlbu); +void mali_dlbu_disable(struct mali_dlbu_core *dlbu); + +_mali_osk_errcode_t mali_dlbu_enable_pp_core(struct mali_dlbu_core *dlbu, u32 pp_core_enable, u32 val); +void mali_dlbu_enable_all_pp_cores(struct mali_dlbu_core *dlbu); +void mali_dlbu_disable_all_pp_cores(struct mali_dlbu_core *dlbu); + +_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu); +void mali_dlbu_setup(struct mali_dlbu_core *dlbu, u8 fb_xdim, u8 fb_ydim, u8 xtilesize, u8 ytilesize, u8 blocksize, u8 xgr0, u8 ygr0, u8 xgr1, u8 ygr1); + +_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group); +void mali_dlbu_set_tllist_base_address(struct mali_dlbu_core *dlbu, u32 val); + +void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu); +void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu); + +#endif /* __MALI_DLBU_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_gp.c b/drivers/media/video/samsung/mali/common/mali_gp.c new file mode 100644 index 0000000..1624e46 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_gp.c @@ -0,0 +1,746 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_gp.h" +#include "mali_hw_core.h" +#include "mali_group.h" +#include "mali_osk.h" +#include "regs/mali_gp_regs.h" +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#if MALI_TIMELINE_PROFILING_ENABLED +#include "mali_osk_profiling.h" +#endif + +/** + * Definition of the GP core struct + * Used to track a GP core in the system. + */ +struct mali_gp_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + struct mali_group *group; /**< Parent group for this core */ + _mali_osk_irq_t *irq; /**< IRQ handler */ + struct mali_gp_job *running_job; /**< Current running job */ + _mali_osk_timer_t *timeout_timer; /**< timeout timer for this core */ + u32 timeout_job_id; /**< job id for the timed out job - relevant only if gp_core_timed_out == MALI_TRUE */ + mali_bool core_timed_out; /**< if MALI_TRUE, this gp core has timed out; if MALI_FALSE, no timeout on this gp core */ + u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ + u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ + u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */ + u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */ +}; + +static struct mali_gp_core *mali_global_gp_core = NULL; + +/* Interrupt handlers */ +static _mali_osk_errcode_t mali_gp_upper_half(void *data); +static void mali_gp_bottom_half(void *data); +static void mali_gp_irq_probe_trigger(void *data); +static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data); +static void mali_gp_post_process_job(struct mali_gp_core *core, mali_bool suspend); +static void mali_gp_timeout(void *data); + +struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group) +{ + struct mali_gp_core* core = NULL; + + MALI_DEBUG_ASSERT(NULL == mali_global_gp_core); + MALI_DEBUG_PRINT(2, ("Mali GP: Creating Mali GP core: %s\n", resource->description)); + + core = _mali_osk_malloc(sizeof(struct mali_gp_core)); + if (NULL != core) + { + core->group = group; + core->running_job = NULL; + core->counter_src0 = MALI_HW_CORE_NO_COUNTER; + core->counter_src1 = MALI_HW_CORE_NO_COUNTER; + core->counter_src0_used = MALI_HW_CORE_NO_COUNTER; + core->counter_src1_used = MALI_HW_CORE_NO_COUNTER; + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALIGP2_REGISTER_ADDRESS_SPACE_SIZE)) + { + _mali_osk_errcode_t ret; + + mali_group_lock(group); + ret = mali_gp_reset(core); + mali_group_unlock(group); + + if (_MALI_OSK_ERR_OK == ret) + { + /* Setup IRQ handlers (which will do IRQ probing if needed) */ + core->irq = _mali_osk_irq_init(resource->irq, + mali_gp_upper_half, + mali_gp_bottom_half, + mali_gp_irq_probe_trigger, + mali_gp_irq_probe_ack, + core, + "mali_gp_irq_handlers"); + if (NULL != core->irq) + { + /* Initialise the timeout timer */ + core->timeout_timer = _mali_osk_timer_init(); + if(NULL != core->timeout_timer) + { + _mali_osk_timer_setcallback(core->timeout_timer, mali_gp_timeout, (void *)core); + MALI_DEBUG_PRINT(4, ("Mali GP: set global gp core from 0x%08X to 0x%08X\n", mali_global_gp_core, core)); + mali_global_gp_core = core; + + return core; + } + else + { + MALI_PRINT_ERROR(("Failed to setup timeout timer for GP core %s\n", core->hw_core.description)); + /* Release IRQ handlers */ + _mali_osk_irq_term(core->irq); + } + } + else + { + MALI_PRINT_ERROR(("Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description)); + } + } + mali_hw_core_delete(&core->hw_core); + } + + _mali_osk_free(core); + } + else + { + MALI_PRINT_ERROR(("Failed to allocate memory for GP core\n")); + } + + return NULL; +} + +void mali_gp_delete(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + _mali_osk_timer_term(core->timeout_timer); + _mali_osk_irq_term(core->irq); + mali_hw_core_delete(&core->hw_core); + mali_global_gp_core = NULL; + _mali_osk_free(core); +} + +void mali_gp_stop_bus(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS); +} + +_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core) +{ + int i; + const int request_loop_count = 20; + + MALI_DEBUG_ASSERT_POINTER(core); + + /* Send the stop bus command. */ + mali_gp_stop_bus(core); + + /* Wait for bus to be stopped */ + for (i = 0; i < request_loop_count; i++) + { + if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) + { + break; + } + _mali_osk_time_ubusydelay(10); + } + + if (request_loop_count == i) + { + MALI_PRINT_ERROR(("Mali GP: Failed to stop bus on %s\n", core->hw_core.description)); + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +void mali_gp_hard_reset(struct mali_gp_core *core) +{ + const int reset_finished_loop_count = 15; + const u32 reset_wait_target_register = MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW; + const u32 reset_invalid_value = 0xC0FFE000; + const u32 reset_check_value = 0xC01A0000; + const u32 reset_default_value = 0; + int i; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_DEBUG_PRINT(4, ("Mali GP: Hard reset of core %s\n", core->hw_core.description)); + MALI_ASSERT_GROUP_LOCKED(core->group); + + mali_gp_post_process_job(core, MALI_FALSE); + + mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_invalid_value); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_RESET); + + for (i = 0; i < reset_finished_loop_count; i++) + { + mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_check_value); + if (reset_check_value == mali_hw_core_register_read(&core->hw_core, reset_wait_target_register)) + { + break; + } + } + + if (i == reset_finished_loop_count) + { + MALI_PRINT_ERROR(("Mali GP: The hard reset loop didn't work, unable to recover\n")); + } + + mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_default_value); /* set it back to the default */ + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); + +} + +_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core) +{ + int i; + const int request_loop_count = 20; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_DEBUG_PRINT(4, ("Mali GP: Reset of core %s\n", core->hw_core.description)); + MALI_ASSERT_GROUP_LOCKED(core->group); + + mali_gp_post_process_job(core, MALI_FALSE); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ + +#if defined(USING_MALI200) + + /* On Mali-200, stop the bus, then do a hard reset of the core */ + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS); + + for (i = 0; i < request_loop_count; i++) + { + if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) + { + break; + } + _mali_osk_time_ubusydelay(10); + } + + if (request_loop_count == i) + { + MALI_PRINT_ERROR(("Mali GP: Failed to stop bus for core %s, unable to recover\n", core->hw_core.description)); + return _MALI_OSK_ERR_FAULT; + } + + /* the bus was stopped OK, do the hard reset */ + mali_gp_hard_reset(core); + +#elif defined(USING_MALI400) + + /* Mali-300 and Mali-400 have a safe reset command which we use */ + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET); + + for (i = 0; i < request_loop_count; i++) + { + if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED) + { + break; + } + _mali_osk_time_ubusydelay(10); + } + + if (request_loop_count == i) + { + MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, unable to recover\n", core->hw_core.description)); + return _MALI_OSK_ERR_FAULT; + } +#else +#error "no supported mali core defined" +#endif + + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); + + return _MALI_OSK_ERR_OK; +} + +void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job) +{ + u32 startcmd = 0; + u32 *frame_registers = mali_gp_job_get_frame_registers(job); + core->counter_src0_used = core->counter_src0; + core->counter_src1_used = core->counter_src1; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_ASSERT_GROUP_LOCKED(core->group); + + if (mali_gp_job_has_vs_job(job)) + { + startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS; + } + + if (mali_gp_job_has_plbu_job(job)) + { + startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU; + } + + MALI_DEBUG_ASSERT(0 != startcmd); + + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR, frame_registers, MALIGP2_NUM_REGS_FRAME); + +#if PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH + { + /* Read hits and Read misses*/ + mali_l2_cache_core_set_counter_src0(mali_l2_cache_core_get_glob_l2_core(0), 20); + mali_l2_cache_core_set_counter_src1(mali_l2_cache_core_get_glob_l2_core(0), 21); + } +#endif + + /* This selects which performance counters we are reading */ + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + /* global_config has enabled HW counters, this will override anything specified by user space */ + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); + } + if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); + } + } + else + { + /* Use HW counters from job object, if any */ + u32 perf_counter_flag = mali_gp_job_get_perf_counter_flag(job); + if (0 != perf_counter_flag) + { + if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) + { + core->counter_src0_used = mali_gp_job_get_perf_counter_src0(job); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); + } + + if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) + { + core->counter_src1_used = mali_gp_job_get_perf_counter_src1(job); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); + } + } + } + + MALI_DEBUG_PRINT(3, ("Mali GP: Starting job (0x%08x) on core %s with command 0x%08X\n", job, core->hw_core.description, startcmd)); + + /* Barrier to make sure the previous register write is finished */ + _mali_osk_write_mem_barrier(); + + /* This is the command that starts the core. */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, startcmd); + + /* Barrier to make sure the previous register write is finished */ + _mali_osk_write_mem_barrier(); + + /* Setup the timeout timer value and save the job id for the job running on the gp core */ + + _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); + core->timeout_job_id = mali_gp_job_get_id(job); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, + job->frame_builder_id, job->flush_id, 0, 0, 0); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), job->pid, job->tid, 0, 0, 0); +#endif + + core->running_job = job; +} + +void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr) +{ + u32 irq_readout; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_ASSERT_GROUP_LOCKED(core->group); + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT); + + if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG)); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* re-enable interrupts */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, start_addr); + mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, end_addr); + + MALI_DEBUG_PRINT(3, ("Mali GP: Resuming job\n")); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC); + _mali_osk_write_mem_barrier(); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0); +#endif + } + /* + * else: core has been reset between PLBU_OUT_OF_MEM interrupt and this new heap response. + * A timeout or a page fault on Mali-200 PP core can cause this behaviour. + */ +} + +void mali_gp_abort_job(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + MALI_ASSERT_GROUP_LOCKED(core->group); + + if (_MALI_OSK_ERR_FAULT != mali_gp_reset(core)) + { + _mali_osk_timer_del(core->timeout_timer); + } +} + +u32 mali_gp_core_get_version(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VERSION); +} + +mali_bool mali_gp_core_set_counter_src0(struct mali_gp_core *core, u32 counter) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + core->counter_src0 = counter; + return MALI_TRUE; +} + +mali_bool mali_gp_core_set_counter_src1(struct mali_gp_core *core, u32 counter) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + core->counter_src1 = counter; + return MALI_TRUE; +} + +u32 mali_gp_core_get_counter_src0(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return core->counter_src0; +} + +u32 mali_gp_core_get_counter_src1(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return core->counter_src1; +} + +struct mali_gp_core *mali_gp_get_global_gp_core(void) +{ + return mali_global_gp_core; +} + +/* ------------- interrupt handling below ------------------ */ +static _mali_osk_errcode_t mali_gp_upper_half(void *data) +{ + struct mali_gp_core *core = (struct mali_gp_core *)data; + u32 irq_readout; + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); + if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout) + { + /* Mask out all IRQs from this core until IRQ is handled */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); +#endif + + /* We do need to handle this in a bottom half */ + _mali_osk_irq_schedulework(core->irq); + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + +static void mali_gp_bottom_half(void *data) +{ + struct mali_gp_core *core = (struct mali_gp_core *)data; + u32 irq_readout; + u32 irq_errors; + +#if MALI_TIMELINE_PROFILING_ENABLED +#if 0 /* Bottom half TLP logging is currently not supported */ + _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0); +#endif +#endif + + mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */ + + if ( MALI_FALSE == mali_group_power_is_on(core->group) ) + { + MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description)); + mali_group_unlock(core->group); + return; + } + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED; + MALI_DEBUG_PRINT(4, ("Mali GP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description)); + + if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST)) + { + u32 core_status = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS); + if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE)) + { + mali_gp_post_process_job(core, MALI_FALSE); + MALI_DEBUG_PRINT(4, ("Mali GP: Job completed, calling group handler\n")); + mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_COMPLETED); /* Will release group lock */ + return; + } + } + + /* + * Now lets look at the possible error cases (IRQ indicating error or timeout) + * END_CMD_LST, HANG and PLBU_OOM interrupts are not considered error. + */ + irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM); + if (0 != irq_errors) + { + mali_gp_post_process_job(core, MALI_FALSE); + MALI_PRINT_ERROR(("Mali GP: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, core->hw_core.description)); + mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_FAILED); /* Will release group lock */ + return; + } + else if (MALI_TRUE == core->core_timed_out) /* SW timeout */ + { + if (core->timeout_job_id == mali_gp_job_get_id(core->running_job)) + { + mali_gp_post_process_job(core, MALI_FALSE); + MALI_DEBUG_PRINT(2, ("Mali GP: Job %d timed out\n", mali_gp_job_get_id(core->running_job))); + mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_TIMED_OUT); + } + core->core_timed_out = MALI_FALSE; + return; + } + else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) + { + /* GP wants more memory in order to continue. + * + * This must be handled prior to HANG because this actually can + * generate a HANG while waiting for more memory. + * And it must be handled before the completion interrupts, + * since the PLBU can run out of memory after VS is complete; + * in which case the OOM must be handled before to complete the + * PLBU work. + */ + mali_gp_post_process_job(core, MALI_TRUE); + MALI_DEBUG_PRINT(3, ("Mali GP: PLBU needs more heap memory\n")); + mali_group_bottom_half(core->group, GROUP_EVENT_GP_OOM); /* Will release group lock */ + return; + } + else if (irq_readout & MALIGP2_REG_VAL_IRQ_HANG) + { + /* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_HANG); + } + + /* + * The only way to get here is if we got a HANG interrupt, which we ignore, or only one of two needed END_CMD_LST interrupts. + * Re-enable interrupts and let core continue to run. + */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); + mali_group_unlock(core->group); + +#if MALI_TIMELINE_PROFILING_ENABLED +#if 0 /* Bottom half TLP logging is currently not supported */ + _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0); +#endif +#endif +} + +static void mali_gp_irq_probe_trigger(void *data) +{ + struct mali_gp_core *core = (struct mali_gp_core *)data; + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* @@@@ This should not be needed */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG); + _mali_osk_mem_barrier(); +} + +static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data) +{ + struct mali_gp_core *core = (struct mali_gp_core *)data; + u32 irq_readout; + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); + if (MALIGP2_REG_VAL_IRQ_FORCE_HANG & irq_readout) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_FORCE_HANG); + _mali_osk_mem_barrier(); + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + +/* ------ local helper functions below --------- */ + +static void mali_gp_post_process_job(struct mali_gp_core *core, mali_bool suspend) +{ + MALI_ASSERT_GROUP_LOCKED(core->group); + + if (NULL != core->running_job) + { + u32 val0 = 0; + u32 val1 = 0; +#if MALI_TIMELINE_PROFILING_ENABLED + u32 event_id; +#endif + +#if PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH + { + u32 src0, value0, src1, value1, sum, per_thousand, per_thousand_now, diff0, diff1; + static u32 print_nr=0; + static u32 prev0=0; + static u32 prev1=0; + if ( !(++print_nr&511) ) + { + mali_l2_cache_core_get_counter_values(mali_l2_cache_core_get_glob_l2_core(0), &src0, &value0, &src1, &value1); + MALI_DEBUG_ASSERT( src0==20 ); /* Read hits */ + MALI_DEBUG_ASSERT( src1==21 ); /* Read misses */ + + sum = value0+value1; + if ( sum > 1000000 ) + { + per_thousand = value0 / (sum/1000); + } + else + { + per_thousand = (value0*1000) / (sum); + } + diff0 = value0-prev0; + diff1 = value1-prev1; + + sum = diff0 + diff1 ; + if ( sum > 1000000 ) + { + per_thousand_now = diff0 / (sum/1000); + } + else + { + per_thousand_now = (diff0*1000) / (sum); + } + + prev0=value0; + prev1=value1; + if (per_thousand_now<=1000) + { + MALI_DEBUG_PRINT(2, ("Mali L2: Read hits/misses: %d/%d = %d thousand_parts total, since previous: %d\n", value0, value1, per_thousand, per_thousand_now)); + } + + } + } +#endif + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + val0 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE); + if (mali_gp_job_get_perf_counter_flag(core->running_job) && + _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_gp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used) + { + /* We retrieved the counter that user space asked for, so return the value through the job object */ + mali_gp_job_set_perf_counter_value0(core->running_job, val0); + } + else + { + /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ + mali_gp_job_set_perf_counter_value0(core->running_job, MALI_HW_CORE_INVALID_VALUE); + } + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, val0); +#endif + + } + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + val1 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE); + if (mali_gp_job_get_perf_counter_flag(core->running_job) && + _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_gp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used) + { + /* We retrieved the counter that user space asked for, so return the value through the job object */ + mali_gp_job_set_perf_counter_value1(core->running_job, val1); + } + else + { + /* User space asked for a counter, but this is not what we retrieved (overridden by counter src set on core) */ + mali_gp_job_set_perf_counter_value1(core->running_job, MALI_HW_CORE_INVALID_VALUE); + } + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, val1); +#endif + } + +#if MALI_TIMELINE_PROFILING_ENABLED + if (MALI_TRUE == suspend) + { + event_id = MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0); + } + else + { + event_id = MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0); + } + _mali_osk_profiling_add_event(event_id, val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0); +#endif + + mali_gp_job_set_current_heap_addr(core->running_job, + mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR)); + + if (MALI_TRUE != suspend) + { + /* We are no longer running a job... */ + core->running_job = NULL; + _mali_osk_timer_del(core->timeout_timer); + } + } +} + +/* callback function for gp core timeout */ +static void mali_gp_timeout(void *data) +{ + struct mali_gp_core * core = ((struct mali_gp_core *)data); + + MALI_DEBUG_PRINT(3, ("Mali GP: TIMEOUT callback \n")); + core->core_timed_out = MALI_TRUE; + _mali_osk_irq_schedulework(core->irq); +} + +#if 0 +void mali_gp_print_state(struct mali_gp_core *core) +{ + MALI_DEBUG_PRINT(2, ("Mali GP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) )); +} +#endif + +#if MALI_STATE_TRACKING +u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "\tGP: %s\n", core->hw_core.description); + + return n; +} +#endif diff --git a/drivers/media/video/samsung/mali/common/mali_gp.h b/drivers/media/video/samsung/mali/common/mali_gp.h new file mode 100644 index 0000000..3175b75 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_gp.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_GP_H__ +#define __MALI_GP_H__ + +#include "mali_osk.h" +#include "mali_gp_job.h" + +struct mali_gp_core; +struct mali_group; + +_mali_osk_errcode_t mali_gp_initialize(void); +void mali_gp_terminate(void); + +struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group); +void mali_gp_delete(struct mali_gp_core *core); + +void mali_gp_stop_bus(struct mali_gp_core *core); +_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core); +void mali_gp_hard_reset(struct mali_gp_core *core); +_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core); + +void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job); +void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr); + +void mali_gp_abort_job(struct mali_gp_core *core); + +u32 mali_gp_core_get_version(struct mali_gp_core *core); + +mali_bool mali_gp_core_set_counter_src0(struct mali_gp_core *core, u32 counter); +mali_bool mali_gp_core_set_counter_src1(struct mali_gp_core *core, u32 counter); +u32 mali_gp_core_get_counter_src0(struct mali_gp_core *core); +u32 mali_gp_core_get_counter_src1(struct mali_gp_core *core); +struct mali_gp_core *mali_gp_get_global_gp_core(void); + +u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size); + +#endif /* __MALI_GP_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_gp_job.c b/drivers/media/video/samsung/mali/common/mali_gp_job.c new file mode 100644 index 0000000..abe1d93 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_gp_job.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_gp_job.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_uk_types.h" + +struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id) +{ + struct mali_gp_job *job; + + job = _mali_osk_malloc(sizeof(struct mali_gp_job)); + if (NULL != job) + { + _mali_osk_list_init(&job->list); + job->session = session; + job->id = id; + job->user_id = args->user_job_ptr; + _mali_osk_memcpy(job->frame_registers, args->frame_registers, sizeof(job->frame_registers)); + job->heap_current_addr = args->frame_registers[4]; + job->perf_counter_flag = args->perf_counter_flag; + job->perf_counter_src0 = args->perf_counter_src0; + job->perf_counter_src1 = args->perf_counter_src1; + job->perf_counter_value0 = 0; + job->perf_counter_value1 = 0; + + job->pid = _mali_osk_get_pid(); + job->tid = _mali_osk_get_tid(); + job->frame_builder_id = args->frame_builder_id; + job->flush_id = args->flush_id; + + return job; + } + + return NULL; +} + +void mali_gp_job_delete(struct mali_gp_job *job) +{ + _mali_osk_free(job); +} diff --git a/drivers/media/video/samsung/mali/common/mali_gp_job.h b/drivers/media/video/samsung/mali/common/mali_gp_job.h new file mode 100644 index 0000000..9c29f1c --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_gp_job.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_GP_JOB_H__ +#define __MALI_GP_JOB_H__ + +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_uk_types.h" +#include "mali_session.h" + +/** + * The structure represends a GP job, including all sub-jobs + * (This struct unfortunatly needs to be public because of how the _mali_osk_list_* + * mechanism works) + */ +struct mali_gp_job +{ + _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */ + struct mali_session_data *session; /**< Session which submitted this job */ + u32 id; /**< identifier for this job in kernel space (sequential numbering) */ + u32 user_id; /**< identifier for the job in user space */ + u32 frame_registers[MALIGP2_NUM_REGS_FRAME]; /**< core specific registers associated with this job, see ARM DDI0415A */ + u32 heap_current_addr; /**< Holds the current HEAP address when the job has completed */ + u32 perf_counter_flag; /**< bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ + u32 perf_counter_src0; /**< source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ + u32 perf_counter_src1; /**< source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ + u32 perf_counter_value0; /**< Value of performance counter 0 (to be returned to user space) */ + u32 perf_counter_value1; /**< Value of performance counter 1 (to be returned to user space) */ + u32 pid; /**< Process ID of submitting process */ + u32 tid; /**< Thread ID of submitting thread */ + u32 frame_builder_id; /**< id of the originating frame builder */ + u32 flush_id; /**< flush id within the originating frame builder */ +}; + +struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id); +void mali_gp_job_delete(struct mali_gp_job *job); + +MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job) +{ + return (NULL == job) ? 0 : job->id; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_user_id(struct mali_gp_job *job) +{ + return job->user_id; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_frame_builder_id(struct mali_gp_job *job) +{ + return job->frame_builder_id; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_flush_id(struct mali_gp_job *job) +{ + return job->flush_id; +} + +MALI_STATIC_INLINE u32* mali_gp_job_get_frame_registers(struct mali_gp_job *job) +{ + return job->frame_registers; +} + +MALI_STATIC_INLINE struct mali_session_data *mali_gp_job_get_session(struct mali_gp_job *job) +{ + return job->session; +} + +MALI_STATIC_INLINE mali_bool mali_gp_job_has_vs_job(struct mali_gp_job *job) +{ + return (job->frame_registers[0] != job->frame_registers[1]) ? MALI_TRUE : MALI_FALSE; +} + +MALI_STATIC_INLINE mali_bool mali_gp_job_has_plbu_job(struct mali_gp_job *job) +{ + return (job->frame_registers[2] != job->frame_registers[3]) ? MALI_TRUE : MALI_FALSE; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_current_heap_addr(struct mali_gp_job *job) +{ + return job->heap_current_addr; +} + +MALI_STATIC_INLINE void mali_gp_job_set_current_heap_addr(struct mali_gp_job *job, u32 heap_addr) +{ + job->heap_current_addr = heap_addr; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_flag(struct mali_gp_job *job) +{ + return job->perf_counter_flag; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src0(struct mali_gp_job *job) +{ + return job->perf_counter_src0; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src1(struct mali_gp_job *job) +{ + return job->perf_counter_src1; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value0(struct mali_gp_job *job) +{ + return job->perf_counter_value0; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value1(struct mali_gp_job *job) +{ + return job->perf_counter_value1; +} + +MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value0(struct mali_gp_job *job, u32 value) +{ + job->perf_counter_value0 = value; +} + +MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value1(struct mali_gp_job *job, u32 value) +{ + job->perf_counter_value1 = value; +} + +#endif /* __MALI_GP_JOB_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c new file mode 100644 index 0000000..f06d899 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_gp_scheduler.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_scheduler.h" +#include "mali_gp.h" +#include "mali_gp_job.h" +#include "mali_group.h" +#include "mali_cluster.h" + +enum mali_gp_slot_state +{ + MALI_GP_SLOT_STATE_IDLE, + MALI_GP_SLOT_STATE_WORKING, +}; + +/* A render slot is an entity which jobs can be scheduled onto */ +struct mali_gp_slot +{ + struct mali_group *group; + /* + * We keep track of the state here as well as in the group object + * so we don't need to take the group lock so often (and also avoid clutter with the working lock) + */ + enum mali_gp_slot_state state; + u32 returned_cookie; +}; + +static u32 gp_version = 0; +static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */ +static struct mali_gp_slot slot; + +/* Variables to allow safe pausing of the scheduler */ +static _mali_osk_wait_queue_t *gp_scheduler_working_wait_queue = NULL; +static u32 pause_count = 0; + +static mali_bool mali_gp_scheduler_is_suspended(void); + +static _mali_osk_lock_t *gp_scheduler_lock = NULL; +/* Contains tid of thread that locked the scheduler or 0, if not locked */ + +_mali_osk_errcode_t mali_gp_scheduler_initialize(void) +{ + u32 i; + + _MALI_OSK_INIT_LIST_HEAD(&job_queue); + + gp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); + if (NULL == gp_scheduler_lock) + { + return _MALI_OSK_ERR_NOMEM; + } + + gp_scheduler_working_wait_queue = _mali_osk_wait_queue_init(); + if (NULL == gp_scheduler_working_wait_queue) + { + _mali_osk_lock_term(gp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } + + /* Find all the available GP cores */ + for (i = 0; i < mali_cluster_get_glob_num_clusters(); i++) + { + u32 group_id = 0; + struct mali_cluster *curr_cluster = mali_cluster_get_global_cluster(i); + struct mali_group *group = mali_cluster_get_group(curr_cluster, group_id); + while (NULL != group) + { + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) + { + if (0 == gp_version) + { + /* Retrieve GP version */ + gp_version = mali_gp_core_get_version(gp_core); + } + slot.group = group; + slot.state = MALI_GP_SLOT_STATE_IDLE; + break; /* There are only one GP, no point in looking for more */ + } + group_id++; + group = mali_cluster_get_group(curr_cluster, group_id); + } + } + + return _MALI_OSK_ERR_OK; +} + +void mali_gp_scheduler_terminate(void) +{ + _mali_osk_wait_queue_term(gp_scheduler_working_wait_queue); + _mali_osk_lock_term(gp_scheduler_lock); +} + +MALI_STATIC_INLINE void mali_gp_scheduler_lock(void) +{ + if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW)) + { + /* Non-interruptable lock failed: this should never happen. */ + MALI_DEBUG_ASSERT(0); + } + MALI_DEBUG_PRINT(5, ("Mali GP scheduler: GP scheduler lock taken\n")); +} + +MALI_STATIC_INLINE void mali_gp_scheduler_unlock(void) +{ + MALI_DEBUG_PRINT(5, ("Mali GP scheduler: Releasing GP scheduler lock\n")); + _mali_osk_lock_signal(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW); +} + +#ifdef DEBUG +MALI_STATIC_INLINE void mali_gp_scheduler_assert_locked(void) +{ + MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock); +} +#define MALI_ASSERT_GP_SCHEDULER_LOCKED() mali_gp_scheduler_assert_locked() +#else +#define MALI_ASSERT_GP_SCHEDULER_LOCKED() +#endif + +static void mali_gp_scheduler_schedule(void) +{ + struct mali_gp_job *job; + + MALI_ASSERT_GP_SCHEDULER_LOCKED(); + + if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue)) + { + MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", + pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0)); + return; /* Nothing to do, so early out */ + } + + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list); + + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job)); + if (_MALI_OSK_ERR_OK == mali_group_start_gp_job(slot.group, job)) + { + /* Mark slot as busy */ + slot.state = MALI_GP_SLOT_STATE_WORKING; + + /* Remove from queue of unscheduled jobs */ + _mali_osk_list_del(&job->list); + } + else + { + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Failed to start GP job\n")); + } +} + +static void mali_gp_scheduler_return_job_to_user(struct mali_gp_job *job, mali_bool success) +{ + _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s)); + if (NULL != notobj) + { + _mali_uk_gp_job_finished_s *jobres = notobj->result_buffer; + _mali_osk_memset(jobres, 0, sizeof(_mali_uk_gp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ + jobres->user_job_ptr = mali_gp_job_get_user_id(job); + if (MALI_TRUE == success) + { + jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; + } + else + { + jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; + } + + jobres->heap_current_addr = mali_gp_job_get_current_heap_addr(job); + jobres->perf_counter0 = mali_gp_job_get_perf_counter_value0(job); + jobres->perf_counter1 = mali_gp_job_get_perf_counter_value1(job); + + mali_session_send_notification(mali_gp_job_get_session(job), notobj); + } + else + { + MALI_PRINT_ERROR(("Mali GP scheduler: Unable to allocate notification object\n")); + } + + mali_gp_job_delete(job); +} + + +void mali_gp_scheduler_do_schedule(void) +{ + mali_gp_scheduler_lock(); + + mali_gp_scheduler_schedule(); + + mali_gp_scheduler_unlock(); +} + +void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success) +{ + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) completed (%s)\n", mali_gp_job_get_id(job), job, success ? "success" : "failure")); + + mali_gp_scheduler_lock(); + + /* Mark slot as idle again */ + slot.state = MALI_GP_SLOT_STATE_IDLE; + + /* If paused, then this was the last job, so wake up sleeping workers */ + if (pause_count > 0) + { + _mali_osk_wait_queue_wake_up(gp_scheduler_working_wait_queue); + } + else + { + mali_gp_scheduler_schedule(); + } + + mali_gp_scheduler_unlock(); + + mali_gp_scheduler_return_job_to_user(job, success); +} + +void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job) +{ + _mali_osk_notification_t *notobj; + + notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); + + if (NULL != notobj) + { + _mali_uk_gp_job_suspended_s * jobres; + + mali_gp_scheduler_lock(); + + jobres = (_mali_uk_gp_job_suspended_s *)notobj->result_buffer; + + jobres->user_job_ptr = mali_gp_job_get_user_id(job); + jobres->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY; + jobres->cookie = mali_gp_job_get_id(job); + slot.returned_cookie = jobres->cookie; + + mali_session_send_notification(mali_gp_job_get_session(job), notobj); + + mali_gp_scheduler_unlock(); + } + + /* + * If this function failed, then we could return the job to user space right away, + * but there is a job timer anyway that will do that eventually. + * This is not exactly a common case anyway. + */ +} + +void mali_gp_scheduler_suspend(void) +{ + mali_gp_scheduler_lock(); + pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ + mali_gp_scheduler_unlock(); + + _mali_osk_wait_queue_wait_event(gp_scheduler_working_wait_queue, mali_gp_scheduler_is_suspended); +} + +void mali_gp_scheduler_resume(void) +{ + mali_gp_scheduler_lock(); + pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */ + if (0 == pause_count) + { + mali_gp_scheduler_schedule(); + } + mali_gp_scheduler_unlock(); +} + +_mali_osk_errcode_t _mali_ukk_gp_start_job(_mali_uk_gp_start_job_s *args) +{ + struct mali_session_data *session; + struct mali_gp_job *job; + + MALI_DEBUG_ASSERT_POINTER(args); + + if (NULL == args->ctx) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } + + session = (struct mali_session_data*)args->ctx; + if (NULL == session) + { + return _MALI_OSK_ERR_FAULT; + } + + job = mali_gp_job_create(session, args, mali_scheduler_get_new_id()); + if (NULL == job) + { + return _MALI_OSK_ERR_NOMEM; + } + +#if PROFILING_SKIP_PP_AND_GP_JOBS +#warning GP jobs will not be executed + mali_gp_scheduler_return_job_to_user(job, MALI_TRUE); + return _MALI_OSK_ERR_OK; +#endif + + mali_gp_scheduler_lock(); + + _mali_osk_list_addtail(&job->list, &job_queue); + + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job)); + + mali_gp_scheduler_schedule(); + + mali_gp_scheduler_unlock(); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores(_mali_uk_get_gp_number_of_cores_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + args->number_of_cores = 1; + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_get_gp_core_version(_mali_uk_get_gp_core_version_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + args->version = gp_version; + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s *args) +{ + struct mali_session_data *session; + _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT; + + MALI_DEBUG_ASSERT_POINTER(args); + + if (NULL == args->ctx) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } + + session = (struct mali_session_data*)args->ctx; + if (NULL == session) + { + return _MALI_OSK_ERR_FAULT; + } + + mali_gp_scheduler_lock(); + + /* Make sure that the cookie returned by user space is the same as we provided in the first place */ + if (args->cookie != slot.returned_cookie) + { + MALI_DEBUG_PRINT(2, ("Mali GP scheduler: Got an illegal cookie from user space, expected %u but got %u (job id)\n", slot.returned_cookie, args->cookie)) ; + mali_gp_scheduler_unlock(); + return _MALI_OSK_ERR_FAULT; + } + + mali_gp_scheduler_unlock(); + + switch (args->code) + { + case _MALIGP_JOB_RESUME_WITH_NEW_HEAP: + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Resuming job %u with new heap; 0x%08X - 0x%08X\n", args->cookie, args->arguments[0], args->arguments[1])); + mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]); + ret = _MALI_OSK_ERR_OK; + break; + + case _MALIGP_JOB_ABORT: + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting job %u, no new heap provided\n", args->cookie)); + mali_group_abort_gp_job(slot.group, args->cookie); + ret = _MALI_OSK_ERR_OK; + break; + + default: + MALI_PRINT_ERROR(("Mali GP scheduler: Wrong suspend response from user space\n")); + ret = _MALI_OSK_ERR_FAULT; + break; + } + + return ret; + +} + +void mali_gp_scheduler_abort_session(struct mali_session_data *session) +{ + struct mali_gp_job *job, *tmp; + + mali_gp_scheduler_lock(); + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting all jobs from session 0x%08x\n", session)); + + /* Check queue for jobs and remove */ + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_gp_job, list) + { + if (mali_gp_job_get_session(job) == session) + { + MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Removing GP job 0x%08x from queue\n", job)); + _mali_osk_list_del(&(job->list)); + mali_gp_job_delete(job); + } + } + + mali_gp_scheduler_unlock(); + + /* Abort running jobs from this session. It is safe to do this outside + * the scheduler lock as there is only one GP core, and the queue has + * already been emptied, as long as there are no new jobs coming in + * from user space. */ + mali_group_abort_session(slot.group, session); +} + +static mali_bool mali_gp_scheduler_is_suspended(void) +{ + mali_bool ret; + + mali_gp_scheduler_lock(); + ret = pause_count > 0 && slot.state == MALI_GP_SLOT_STATE_IDLE; + mali_gp_scheduler_unlock(); + + return ret; +} + + +#if MALI_STATE_TRACKING +u32 mali_gp_scheduler_dump_state(char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "GP\n"); + n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty"); + + n += mali_group_dump_state(slot.group, buf + n, size - n); + n += _mali_osk_snprintf(buf + n, size - n, "\t\tState: %d\n", mali_group_gp_state(slot.group)); + n += _mali_osk_snprintf(buf + n, size - n, "\n"); + + return n; +} +#endif diff --git a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h new file mode 100644 index 0000000..ef58509 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_GP_SCHEDULER_H__ +#define __MALI_GP_SCHEDULER_H__ + +#include "mali_osk.h" +#include "mali_cluster.h" +#include "mali_gp_job.h" + +_mali_osk_errcode_t mali_gp_scheduler_initialize(void); +void mali_gp_scheduler_terminate(void); + +void mali_gp_scheduler_do_schedule(void); +void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success); +void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job); +void mali_gp_scheduler_abort_session(struct mali_session_data *session); +u32 mali_gp_scheduler_dump_state(char *buf, u32 size); + +void mali_gp_scheduler_suspend(void); +void mali_gp_scheduler_resume(void); + +#endif /* __MALI_GP_SCHEDULER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_group.c b/drivers/media/video/samsung/mali/common/mali_group.c new file mode 100644 index 0000000..94bf774 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_group.c @@ -0,0 +1,841 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_group.h" +#include "mali_osk.h" +#include "mali_cluster.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_mmu.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" +#include "mali_pm.h" + +/* + * The group object is the most important object in the device driver, + * and acts as the center of many HW operations. + * The reason for this is that operations on the MMU will affect all + * cores connected to this MMU (a group is defined by the MMU and the + * cores which are connected to this). + * The group lock is thus the most important lock, followed by the + * GP and PP scheduler locks. They must be taken in the following + * order: + * GP/PP lock first, then group lock(s). + */ + +/** + * The structure represents a render group + * A render group is defined by all the cores that share the same Mali MMU + */ + +struct mali_group +{ + struct mali_cluster *cluster; + + struct mali_mmu_core *mmu; + struct mali_session_data *session; + int page_dir_ref_count; + mali_bool power_is_on; +#if defined(USING_MALI200) + mali_bool pagedir_activation_failed; +#endif + + struct mali_gp_core *gp_core; + enum mali_group_core_state gp_state; + struct mali_gp_job *gp_running_job; + + struct mali_pp_core *pp_core; + enum mali_group_core_state pp_state; + struct mali_pp_job *pp_running_job; + u32 pp_running_sub_job; + + _mali_osk_lock_t *lock; +}; + +static struct mali_group *mali_global_groups[MALI_MAX_NUMBER_OF_GROUPS]; +static u32 mali_global_num_groups = 0; + +enum mali_group_activate_pd_status +{ + MALI_GROUP_ACTIVATE_PD_STATUS_FAILED, + MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD, + MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD, +}; + +/* local helper functions */ +static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session); +static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session); +static void mali_group_recovery_reset(struct mali_group *group); +static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success); + +void mali_group_lock(struct mali_group *group) +{ + if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(group->lock, _MALI_OSK_LOCKMODE_RW)) + { + /* Non-interruptable lock failed: this should never happen. */ + MALI_DEBUG_ASSERT(0); + } + MALI_DEBUG_PRINT(5, ("Mali group: Group lock taken 0x%08X\n", group)); +} + +void mali_group_unlock(struct mali_group *group) +{ + MALI_DEBUG_PRINT(5, ("Mali group: Releasing group lock 0x%08X\n", group)); + _mali_osk_lock_signal(group->lock, _MALI_OSK_LOCKMODE_RW); +} + +#ifdef DEBUG +void mali_group_assert_locked(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); +} +#endif + + +struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_mmu_core *mmu) +{ + struct mali_group *group = NULL; + + if (mali_global_num_groups >= MALI_MAX_NUMBER_OF_GROUPS) + { + MALI_PRINT_ERROR(("Mali group: Too many group objects created\n")); + return NULL; + } + + group = _mali_osk_malloc(sizeof(struct mali_group)); + if (NULL != group) + { + _mali_osk_memset(group, 0, sizeof(struct mali_group)); + group->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_GROUP); + if (NULL != group->lock) + { + group->cluster = cluster; + group->mmu = mmu; /* This group object now owns the MMU object */ + group->session = NULL; + group->page_dir_ref_count = 0; + group->power_is_on = MALI_TRUE; + + group->gp_state = MALI_GROUP_CORE_STATE_IDLE; + group->pp_state = MALI_GROUP_CORE_STATE_IDLE; +#if defined(USING_MALI200) + group->pagedir_activation_failed = MALI_FALSE; +#endif + mali_global_groups[mali_global_num_groups] = group; + mali_global_num_groups++; + + return group; + } + _mali_osk_free(group); + } + + return NULL; +} + +void mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core) +{ + /* This group object now owns the GP core object */ + group->gp_core = gp_core; +} + +void mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core) +{ + /* This group object now owns the PP core object */ + group->pp_core = pp_core; +} + +void mali_group_delete(struct mali_group *group) +{ + u32 i; + + /* Delete the resources that this group owns */ + if (NULL != group->gp_core) + { + mali_gp_delete(group->gp_core); + } + + if (NULL != group->pp_core) + { + mali_pp_delete(group->pp_core); + } + + if (NULL != group->mmu) + { + mali_mmu_delete(group->mmu); + } + + for (i = 0; i < mali_global_num_groups; i++) + { + if (mali_global_groups[i] == group) + { + mali_global_groups[i] = NULL; + mali_global_num_groups--; + break; + } + } + + _mali_osk_lock_term(group->lock); + + _mali_osk_free(group); +} + +/* Called from mali_cluster_reset() when the system is re-turned on */ +void mali_group_reset(struct mali_group *group) +{ + mali_group_lock(group); + + group->session = NULL; + + if (NULL != group->mmu) + { + mali_mmu_reset(group->mmu); + } + + if (NULL != group->gp_core) + { + mali_gp_reset(group->gp_core); + } + + if (NULL != group->pp_core) + { + mali_pp_reset(group->pp_core); + } + + mali_group_unlock(group); +} + +struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group) +{ + return group->gp_core; +} + +struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group) +{ + return group->pp_core; +} + +_mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job) +{ + struct mali_session_data *session; + enum mali_group_activate_pd_status activate_status; + + MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); + + mali_pm_core_event(MALI_CORE_EVENT_GP_START); + + session = mali_gp_job_get_session(job); + + mali_group_lock(group); + + mali_cluster_l2_cache_invalidate_all(group->cluster, mali_gp_job_get_id(job)); + + activate_status = mali_group_activate_page_directory(group, session); + if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) + { + /* if session is NOT kept Zapping is done as part of session switch */ + if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) + { + mali_mmu_zap_tlb_without_stall(group->mmu); + } + mali_gp_job_start(group->gp_core, job); + group->gp_running_job = job; + group->gp_state = MALI_GROUP_CORE_STATE_WORKING; + + mali_group_unlock(group); + + return _MALI_OSK_ERR_OK; + } + +#if defined(USING_MALI200) + group->pagedir_activation_failed = MALI_TRUE; +#endif + + mali_group_unlock(group); + + mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_GP_START */ + return _MALI_OSK_ERR_FAULT; +} + +_mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job) +{ + struct mali_session_data *session; + enum mali_group_activate_pd_status activate_status; + + MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); + + mali_pm_core_event(MALI_CORE_EVENT_PP_START); + + session = mali_pp_job_get_session(job); + + mali_group_lock(group); + + mali_cluster_l2_cache_invalidate_all(group->cluster, mali_pp_job_get_id(job)); + + activate_status = mali_group_activate_page_directory(group, session); + if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) + { + /* if session is NOT kept Zapping is done as part of session switch */ + if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) + { + MALI_DEBUG_PRINT(3, ("PP starting job PD_Switch 0 Flush 1 Zap 1\n")); + mali_mmu_zap_tlb_without_stall(group->mmu); + } + mali_pp_job_start(group->pp_core, job, sub_job); + group->pp_running_job = job; + group->pp_running_sub_job = sub_job; + group->pp_state = MALI_GROUP_CORE_STATE_WORKING; + + mali_group_unlock(group); + + return _MALI_OSK_ERR_OK; + } + +#if defined(USING_MALI200) + group->pagedir_activation_failed = MALI_TRUE; +#endif + + mali_group_unlock(group); + + mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_PP_START */ + return _MALI_OSK_ERR_FAULT; +} + +void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr) +{ + mali_group_lock(group); + + if (group->gp_state != MALI_GROUP_CORE_STATE_OOM || + mali_gp_job_get_id(group->gp_running_job) != job_id) + { + mali_group_unlock(group); + return; /* Illegal request or job has already been aborted */ + } + + mali_cluster_l2_cache_invalidate_all_force(group->cluster); + mali_mmu_zap_tlb_without_stall(group->mmu); + + mali_gp_resume_with_new_heap(group->gp_core, start_addr, end_addr); + group->gp_state = MALI_GROUP_CORE_STATE_WORKING; + + mali_group_unlock(group); +} + +void mali_group_abort_gp_job(struct mali_group *group, u32 job_id) +{ + mali_group_lock(group); + + if (group->gp_state == MALI_GROUP_CORE_STATE_IDLE || + mali_gp_job_get_id(group->gp_running_job) != job_id) + { + mali_group_unlock(group); + return; /* No need to cancel or job has already been aborted or completed */ + } + + mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* Will release group lock */ +} + +void mali_group_abort_pp_job(struct mali_group *group, u32 job_id) +{ + mali_group_lock(group); + + if (group->pp_state == MALI_GROUP_CORE_STATE_IDLE || + mali_pp_job_get_id(group->pp_running_job) != job_id) + { + mali_group_unlock(group); + return; /* No need to cancel or job has already been aborted or completed */ + } + + mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* Will release group lock */ +} + +void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session) +{ + struct mali_gp_job *gp_job; + struct mali_pp_job *pp_job; + u32 gp_job_id = 0; + u32 pp_job_id = 0; + mali_bool abort_pp = MALI_FALSE; + mali_bool abort_gp = MALI_FALSE; + + mali_group_lock(group); + + gp_job = group->gp_running_job; + pp_job = group->pp_running_job; + + if (gp_job && mali_gp_job_get_session(gp_job) == session) + { + MALI_DEBUG_PRINT(4, ("Aborting GP job 0x%08x from session 0x%08x\n", gp_job, session)); + + gp_job_id = mali_gp_job_get_id(gp_job); + abort_gp = MALI_TRUE; + } + + if (pp_job && mali_pp_job_get_session(pp_job) == session) + { + MALI_DEBUG_PRINT(4, ("Mali group: Aborting PP job 0x%08x from session 0x%08x\n", pp_job, session)); + + pp_job_id = mali_pp_job_get_id(pp_job); + abort_pp = MALI_TRUE; + } + + mali_group_unlock(group); + + /* These functions takes and releases the group lock */ + if (0 != abort_gp) + { + mali_group_abort_gp_job(group, gp_job_id); + } + if (0 != abort_pp) + { + mali_group_abort_pp_job(group, pp_job_id); + } + + mali_group_lock(group); + mali_group_remove_session_if_unused(group, session); + mali_group_unlock(group); +} + +enum mali_group_core_state mali_group_gp_state(struct mali_group *group) +{ + return group->gp_state; +} + +enum mali_group_core_state mali_group_pp_state(struct mali_group *group) +{ + return group->pp_state; +} + +/* group lock need to be taken before calling mali_group_bottom_half */ +void mali_group_bottom_half(struct mali_group *group, enum mali_group_event_t event) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + switch (event) + { + case GROUP_EVENT_PP_JOB_COMPLETED: + mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_TRUE); /* PP job SUCCESS */ + /* group lock is released by mali_group_complete_jobs() call above */ + break; + case GROUP_EVENT_PP_JOB_FAILED: + mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* PP job FAIL */ + /* group lock is released by mali_group_complete_jobs() call above */ + break; + case GROUP_EVENT_PP_JOB_TIMED_OUT: + mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* PP job TIMEOUT */ + /* group lock is released by mali_group_complete_jobs() call above */ + break; + case GROUP_EVENT_GP_JOB_COMPLETED: + mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_TRUE); /* GP job SUCCESS */ + /* group lock is released by mali_group_complete_jobs() call above */ + break; + case GROUP_EVENT_GP_JOB_FAILED: + mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* GP job FAIL */ + /* group lock is released by mali_group_complete_jobs() call above */ + break; + case GROUP_EVENT_GP_JOB_TIMED_OUT: + mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* GP job TIMEOUT */ + /* group lock is released by mali_group_complete_jobs() call above */ + break; + case GROUP_EVENT_GP_OOM: + group->gp_state = MALI_GROUP_CORE_STATE_OOM; + mali_group_unlock(group); /* Nothing to do on the HW side, so just release group lock right away */ + mali_gp_scheduler_oom(group, group->gp_running_job); + break; + case GROUP_EVENT_MMU_PAGE_FAULT: + mali_group_complete_jobs(group, MALI_TRUE, MALI_TRUE, MALI_FALSE); /* GP and PP job FAIL */ + /* group lock is released by mali_group_complete_jobs() call above */ + break; + default: + break; + } +} + +struct mali_mmu_core *mali_group_get_mmu(struct mali_group *group) +{ + return group->mmu; +} + +struct mali_session_data *mali_group_get_session(struct mali_group *group) +{ + return group->session; +} + +struct mali_group *mali_group_get_glob_group(u32 index) +{ + if(mali_global_num_groups > index) + { + return mali_global_groups[index]; + } + + return NULL; +} + +u32 mali_group_get_glob_num_groups(void) +{ + return mali_global_num_groups; +} + +/* Used to check if scheduler for the other core type needs to be called on job completion. + * + * Used only for Mali-200, where job start may fail if the only MMU is busy + * with another session's address space. + */ +static inline mali_bool mali_group_other_reschedule_needed(struct mali_group *group) +{ + MALI_ASSERT_GROUP_LOCKED(group); + +#if defined(USING_MALI200) + if (group->pagedir_activation_failed) + { + group->pagedir_activation_failed = MALI_FALSE; + return MALI_TRUE; + } + else +#endif + { + return MALI_FALSE; + } +} + +static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session) +{ + enum mali_group_activate_pd_status retval; + MALI_ASSERT_GROUP_LOCKED(group); + + MALI_DEBUG_PRINT(5, ("Mali group: Activating page directory 0x%08X from session 0x%08X on group 0x%08X\n", mali_session_get_page_directory(session), session, group)); + MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count); + + if (0 != group->page_dir_ref_count) + { + if (group->session != session) + { + MALI_DEBUG_PRINT(4, ("Mali group: Activating session FAILED: 0x%08x on group 0x%08X. Existing session: 0x%08x\n", session, group, group->session)); + return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED; + } + else + { + MALI_DEBUG_PRINT(4, ("Mali group: Activating session already activated: 0x%08x on group 0x%08X. New Ref: %d\n", session, group, 1+group->page_dir_ref_count)); + retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD; + + } + } + else + { + /* There might be another session here, but it is ok to overwrite it since group->page_dir_ref_count==0 */ + if (group->session != session) + { + mali_bool activate_success; + MALI_DEBUG_PRINT(5, ("Mali group: Activate session: %08x previous: %08x on group 0x%08X. Ref: %d\n", session, group->session, group, 1+group->page_dir_ref_count)); + + activate_success = mali_mmu_activate_page_directory(group->mmu, mali_session_get_page_directory(session)); + MALI_DEBUG_ASSERT(activate_success); + if ( MALI_FALSE== activate_success ) return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED; + group->session = session; + retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD; + } + else + { + MALI_DEBUG_PRINT(4, ("Mali group: Activate existing session 0x%08X on group 0x%08X. Ref: %d\n", session->page_directory, group, 1+group->page_dir_ref_count)); + retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD; + } + } + + group->page_dir_ref_count++; + return retval; +} + +static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + MALI_DEBUG_ASSERT(0 < group->page_dir_ref_count); + MALI_DEBUG_ASSERT(session == group->session); + + group->page_dir_ref_count--; + + /* As an optimization, the MMU still points to the group->session even if (0 == group->page_dir_ref_count), + and we do not call mali_mmu_activate_empty_page_directory(group->mmu); */ + MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count); +} + +void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (0 == group->page_dir_ref_count) + { + MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); + MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); + + if (group->session == session) + { + MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on); + MALI_DEBUG_PRINT(3, ("Mali group: Deactivating unused session 0x%08X on group %08X\n", session, group)); + mali_mmu_activate_empty_page_directory(group->mmu); + group->session = NULL; + } + } +} + +void mali_group_power_on(void) +{ + int i; + for (i = 0; i < mali_global_num_groups; i++) + { + struct mali_group *group = mali_global_groups[i]; + mali_group_lock(group); + MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); + MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); + MALI_DEBUG_ASSERT_POINTER(group->cluster); + group->power_is_on = MALI_TRUE; + mali_cluster_power_is_enabled_set(group->cluster, MALI_TRUE); + mali_group_unlock(group); + } + MALI_DEBUG_PRINT(3,("group: POWER ON\n")); +} + +mali_bool mali_group_power_is_on(struct mali_group *group) +{ + MALI_ASSERT_GROUP_LOCKED(group); + return group->power_is_on; +} + +void mali_group_power_off(void) +{ + int i; + /* It is necessary to set group->session = NULL; so that the powered off MMU is not written to on map /unmap */ + /* It is necessary to set group->power_is_on=MALI_FALSE so that pending bottom_halves does not access powered off cores. */ + for (i = 0; i < mali_global_num_groups; i++) + { + struct mali_group *group = mali_global_groups[i]; + mali_group_lock(group); + MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); + MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); + MALI_DEBUG_ASSERT_POINTER(group->cluster); + group->session = NULL; + MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on); + group->power_is_on = MALI_FALSE; + mali_cluster_power_is_enabled_set(group->cluster, MALI_FALSE); + mali_group_unlock(group); + } + MALI_DEBUG_PRINT(3,("group: POWER OFF\n")); +} + + +static void mali_group_recovery_reset(struct mali_group *group) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + /* Stop cores, bus stop */ + if (NULL != group->pp_core) + { + mali_pp_stop_bus(group->pp_core); + } + if (NULL != group->gp_core) + { + mali_gp_stop_bus(group->gp_core); + } + + /* Flush MMU */ + mali_mmu_activate_fault_flush_page_directory(group->mmu); + mali_mmu_page_fault_done(group->mmu); + + /* Wait for cores to stop bus */ + if (NULL != group->pp_core) + { + mali_pp_stop_bus_wait(group->pp_core); + } + if (NULL != group->gp_core) + { + mali_gp_stop_bus_wait(group->gp_core); + } + + /* Reset cores */ + if (NULL != group->pp_core) + { + mali_pp_hard_reset(group->pp_core); + } + if (NULL != group->gp_core) + { + mali_gp_hard_reset(group->gp_core); + } + + /* Reset MMU */ + mali_mmu_reset(group->mmu); + group->session = NULL; +} + +/* Group lock need to be taken before calling mali_group_complete_jobs. Will release the lock here. */ +static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success) +{ + mali_bool need_group_reset = MALI_FALSE; + mali_bool gp_success = success; + mali_bool pp_success = success; + + MALI_ASSERT_GROUP_LOCKED(group); + + if (complete_gp && !complete_pp) + { + MALI_DEBUG_ASSERT_POINTER(group->gp_core); + if (_MALI_OSK_ERR_OK == mali_gp_reset(group->gp_core)) + { + struct mali_gp_job *gp_job_to_return = group->gp_running_job; + group->gp_state = MALI_GROUP_CORE_STATE_IDLE; + group->gp_running_job = NULL; + + MALI_DEBUG_ASSERT_POINTER(gp_job_to_return); + + mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return)); + + if(mali_group_other_reschedule_needed(group)) + { + mali_group_unlock(group); + mali_pp_scheduler_do_schedule(); + } + else + { + mali_group_unlock(group); + } + + mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success); + mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ + + return; + } + else + { + need_group_reset = MALI_TRUE; + MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset GP, need to reset entire group\n")); + pp_success = MALI_FALSE; /* This might kill PP as well, so this should fail */ + } + } + if (complete_pp && !complete_gp) + { + MALI_DEBUG_ASSERT_POINTER(group->pp_core); + if (_MALI_OSK_ERR_OK == mali_pp_reset(group->pp_core)) + { + struct mali_pp_job *pp_job_to_return = group->pp_running_job; + u32 pp_sub_job_to_return = group->pp_running_sub_job; + group->pp_state = MALI_GROUP_CORE_STATE_IDLE; + group->pp_running_job = NULL; + + MALI_DEBUG_ASSERT_POINTER(pp_job_to_return); + + mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return)); + + if(mali_group_other_reschedule_needed(group)) + { + mali_group_unlock(group); + mali_gp_scheduler_do_schedule(); + } + else + { + mali_group_unlock(group); + } + + mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success); + mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ + + return; + } + else + { + need_group_reset = MALI_TRUE; + MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n")); + gp_success = MALI_FALSE; /* This might kill GP as well, so this should fail */ + } + } + else if (complete_gp && complete_pp) + { + need_group_reset = MALI_TRUE; + } + + if (MALI_TRUE == need_group_reset) + { + struct mali_gp_job *gp_job_to_return = group->gp_running_job; + struct mali_pp_job *pp_job_to_return = group->pp_running_job; + u32 pp_sub_job_to_return = group->pp_running_sub_job; + mali_bool schedule_other = MALI_FALSE; + + MALI_DEBUG_PRINT(3, ("Mali group: Resetting entire group\n")); + + group->gp_state = MALI_GROUP_CORE_STATE_IDLE; + group->gp_running_job = NULL; + if (NULL != gp_job_to_return) + { + mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return)); + } + + group->pp_state = MALI_GROUP_CORE_STATE_IDLE; + group->pp_running_job = NULL; + if (NULL != pp_job_to_return) + { + mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return)); + } + + /* The reset has to be done after mali_group_deactivate_page_directory() */ + mali_group_recovery_reset(group); + + if (mali_group_other_reschedule_needed(group) && (NULL == gp_job_to_return || NULL == pp_job_to_return)) + { + schedule_other = MALI_TRUE; + } + + mali_group_unlock(group); + + if (NULL != gp_job_to_return) + { + mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success); + mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ + } + else if (schedule_other) + { + mali_pp_scheduler_do_schedule(); + } + + if (NULL != pp_job_to_return) + { + mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success); + mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ + } + else if (schedule_other) + { + mali_gp_scheduler_do_schedule(); + } + + return; + } + + mali_group_unlock(group); +} + +#if MALI_STATE_TRACKING +u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group); + if (group->gp_core) + { + n += mali_gp_dump_state(group->gp_core, buf + n, size - n); + n += _mali_osk_snprintf(buf + n, size - n, "\tGP state: %d\n", group->gp_state); + n += _mali_osk_snprintf(buf + n, size - n, "\tGP job: %p\n", group->gp_running_job); + } + if (group->pp_core) + { + n += mali_pp_dump_state(group->pp_core, buf + n, size - n); + n += _mali_osk_snprintf(buf + n, size - n, "\tPP state: %d\n", group->pp_state); + n += _mali_osk_snprintf(buf + n, size - n, "\tPP job: %p, subjob %d \n", + group->pp_running_job, group->pp_running_sub_job); + } + + return n; +} +#endif diff --git a/drivers/media/video/samsung/mali/common/mali_group.h b/drivers/media/video/samsung/mali/common/mali_group.h new file mode 100644 index 0000000..3533d13 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_group.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_GROUP_H__ +#define __MALI_GROUP_H__ + +#include "linux/jiffies.h" +#include "mali_osk.h" +#include "mali_cluster.h" +#include "mali_mmu.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_session.h" + +/* max runtime [ms] for a core job - used by timeout timers */ +#define MAX_RUNTIME 5000 +/** @brief A mali group object represents a MMU and a PP and/or a GP core. + * + */ +#define MALI_MAX_NUMBER_OF_GROUPS 9 + +struct mali_group; + +enum mali_group_event_t +{ + GROUP_EVENT_PP_JOB_COMPLETED, /**< PP job completed successfully */ + GROUP_EVENT_PP_JOB_FAILED, /**< PP job completed with failure */ + GROUP_EVENT_PP_JOB_TIMED_OUT, /**< PP job reached max runtime */ + GROUP_EVENT_GP_JOB_COMPLETED, /**< GP job completed successfully */ + GROUP_EVENT_GP_JOB_FAILED, /**< GP job completed with failure */ + GROUP_EVENT_GP_JOB_TIMED_OUT, /**< GP job reached max runtime */ + GROUP_EVENT_GP_OOM, /**< GP job ran out of heap memory */ + GROUP_EVENT_MMU_PAGE_FAULT, /**< MMU page fault */ +}; + +enum mali_group_core_state +{ + MALI_GROUP_CORE_STATE_IDLE, + MALI_GROUP_CORE_STATE_WORKING, + MALI_GROUP_CORE_STATE_OOM +}; + +/** @brief Create a new Mali group object + * + * @param cluster Pointer to the cluster to which the group is connected. + * @param mmu Pointer to the MMU that defines this group + * @return A pointer to a new group object + */ +struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_mmu_core *mmu); +void mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core); +void mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core); +void mali_group_delete(struct mali_group *group); + +/** @brief Reset group + * + * This function will reset the entire group, including all the cores present in the group. + * + * @param group Pointer to the group to reset + */ +void mali_group_reset(struct mali_group *group); + +/** @brief Get pointer to GP core object + */ +struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group); + +/** @brief Get pointer to PP core object + */ +struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group); + +/** @brief Lock group object + * + * Most group functions will lock the group object themselves. The expection is + * the group_bottom_half which requires the group to be locked on entry. + * + * @param group Pointer to group to lock + */ +void mali_group_lock(struct mali_group *group); + +/** @brief Unlock group object + * + * @param group Pointer to group to unlock + */ +void mali_group_unlock(struct mali_group *group); +#ifdef DEBUG +void mali_group_assert_locked(struct mali_group *group); +#define MALI_ASSERT_GROUP_LOCKED(group) mali_group_assert_locked(group) +#else +#define MALI_ASSERT_GROUP_LOCKED(group) +#endif + +/** @brief Start GP job + */ +_mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job); +/** @brief Start fragment of PP job + */ +_mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job); + +/** @brief Resume GP job that suspended waiting for more heap memory + */ +void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr); +/** @brief Abort GP job + * + * Used to abort suspended OOM jobs when user space failed to allocte more memory. + */ +void mali_group_abort_gp_job(struct mali_group *group, u32 job_id); +/** @brief Abort all GP jobs from \a session + * + * Used on session close when terminating all running and queued jobs from \a session. + */ +void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session); + +enum mali_group_core_state mali_group_gp_state(struct mali_group *group); +enum mali_group_core_state mali_group_pp_state(struct mali_group *group); + +/** @brief The common group bottom half interrupt handler + * + * This is only called from the GP and PP bottom halves. + * + * The action taken is dictated by the \a event. + * + * @param event The event code + */ +void mali_group_bottom_half(struct mali_group *group, enum mali_group_event_t event); + +struct mali_mmu_core *mali_group_get_mmu(struct mali_group *group); +struct mali_session_data *mali_group_get_session(struct mali_group *group); + +void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session_data); + +void mali_group_power_on(void); +void mali_group_power_off(void); +mali_bool mali_group_power_is_on(struct mali_group *group); + +struct mali_group *mali_group_get_glob_group(u32 index); +u32 mali_group_get_glob_num_groups(void); + +u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size); + +#endif /* __MALI_GROUP_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_hw_core.c b/drivers/media/video/samsung/mali/common/mali_hw_core.c new file mode 100644 index 0000000..0b08622 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_hw_core.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_hw_core.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" + +_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size) +{ + core->phys_addr = resource->base; + core->description = resource->description; + core->size = reg_size; + if (_MALI_OSK_ERR_OK == _mali_osk_mem_reqregion(core->phys_addr, core->size, core->description)) + { + core->mapped_registers = _mali_osk_mem_mapioregion(core->phys_addr, core->size, core->description); + if (NULL != core->mapped_registers) + { + return _MALI_OSK_ERR_OK; + } + else + { + MALI_PRINT_ERROR(("Failed to map memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr)); + } + _mali_osk_mem_unreqregion(core->phys_addr, core->size); + } + else + { + MALI_PRINT_ERROR(("Failed to request memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr)); + } + + return _MALI_OSK_ERR_FAULT; +} + +void mali_hw_core_delete(struct mali_hw_core *core) +{ + _mali_osk_mem_unmapioregion(core->phys_addr, core->size, core->mapped_registers); + core->mapped_registers = NULL; + _mali_osk_mem_unreqregion(core->phys_addr, core->size); +} diff --git a/drivers/media/video/samsung/mali/common/mali_hw_core.h b/drivers/media/video/samsung/mali/common/mali_hw_core.h new file mode 100644 index 0000000..c797804 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_hw_core.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_HW_CORE_H__ +#define __MALI_HW_CORE_H__ + +#include "mali_osk.h" +#include "mali_kernel_common.h" + +/** + * The common parts for all Mali HW cores (GP, PP, MMU, L2 and PMU) + * This struct is embedded inside all core specific structs. + */ +struct mali_hw_core +{ + u32 phys_addr; /**< Physical address of the registers */ + u32 size; /**< Size of registers */ + mali_io_address mapped_registers; /**< Virtual mapping of the registers */ + const char* description; /**< Name of unit (as specified in device configuration) */ +}; + +#define MALI_HW_CORE_NO_COUNTER ((u32)-1) +#define MALI_HW_CORE_INVALID_VALUE ((u32)-1) + +_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size); +void mali_hw_core_delete(struct mali_hw_core *core); + +MALI_STATIC_INLINE u32 mali_hw_core_register_read(struct mali_hw_core *core, u32 relative_address) +{ + u32 read_val; + read_val = _mali_osk_mem_ioread32(core->mapped_registers, relative_address); + MALI_DEBUG_PRINT(6, ("register_read for core %s, relative addr=0x%04X, val=0x%08X\n", + core->description, relative_address, read_val)); + return read_val; +} + +MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed(struct mali_hw_core *core, u32 relative_address, u32 new_val) +{ + MALI_DEBUG_PRINT(6, ("register_write_relaxed for core %s, relative addr=0x%04X, val=0x%08X\n", + core->description, relative_address, new_val)); + _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val); +} + +MALI_STATIC_INLINE void mali_hw_core_register_write(struct mali_hw_core *core, u32 relative_address, u32 new_val) +{ + MALI_DEBUG_PRINT(6, ("register_write for core %s, relative addr=0x%04X, val=0x%08X\n", + core->description, relative_address, new_val)); + _mali_osk_mem_iowrite32(core->mapped_registers, relative_address, new_val); +} + +MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed(struct mali_hw_core *core, u32 relative_address, u32 *write_array, u32 nr_of_regs) +{ + u32 i; + MALI_DEBUG_PRINT(6, ("register_write_array: for core %s, relative addr=0x%04X, nr of regs=%u\n", + core->description,relative_address, nr_of_regs)); + + /* Do not use burst writes against the registers */ + for (i = 0; i< nr_of_regs; i++) + { + mali_hw_core_register_write_relaxed(core, relative_address + i*4, write_array[i]); + } +} + +#endif /* __MALI_HW_CORE_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_common.h b/drivers/media/video/samsung/mali/common/mali_kernel_common.h new file mode 100644 index 0000000..b354f92 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_common.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_COMMON_H__ +#define __MALI_KERNEL_COMMON_H__ + +/* Make sure debug is defined when it should be */ +#ifndef DEBUG + #if defined(_DEBUG) + #define DEBUG + #endif +#endif + +/* Macro for generating a kernel panic. + * Turned on off by compile-time Makefile settings + */ +#if defined(USING_KERNEL_PANIC) +#include + #define MALI_PANIC(fmt, args...) panic( fmt, ## args ); +#else + #define MALI_PANIC(fmt, args...) +#endif + +/* The file include several useful macros for error checking, debugging and printing. + * - MALI_PRINTF(...) Do not use this function: Will be included in Release builds. + * - MALI_DEBUG_PRINT(nr, (X) ) Prints the second argument if nr<=MALI_DEBUG_LEVEL. + * - MALI_DEBUG_ERROR( (X) ) Prints an errortext, a source trace, and the given error message. + * - MALI_DEBUG_ASSERT(exp,(X)) If the asserted expr is false, the program will exit. + * - MALI_DEBUG_ASSERT_POINTER(pointer) Triggers if the pointer is a zero pointer. + * - MALI_DEBUG_CODE( X ) The code inside the macro is only compiled in Debug builds. + * + * The (X) means that you must add an extra parenthesis around the argumentlist. + * + * The printf function: MALI_PRINTF(...) is routed to _mali_osk_debugmsg + * + * Suggested range for the DEBUG-LEVEL is [1:6] where + * [1:2] Is messages with highest priority, indicate possible errors. + * [3:4] Is messages with medium priority, output important variables. + * [5:6] Is messages with low priority, used during extensive debugging. + */ + + /** + * Fundamental error macro. Reports an error code. This is abstracted to allow us to + * easily switch to a different error reporting method if we want, and also to allow + * us to search for error returns easily. + * + * Note no closing semicolon - this is supplied in typical usage: + * + * MALI_ERROR(MALI_ERROR_OUT_OF_MEMORY); + */ +#define MALI_ERROR(error_code) return (error_code) + +/** + * Basic error macro, to indicate success. + * Note no closing semicolon - this is supplied in typical usage: + * + * MALI_SUCCESS; + */ +#define MALI_SUCCESS MALI_ERROR(_MALI_OSK_ERR_OK) + +/** + * Basic error macro. This checks whether the given condition is true, and if not returns + * from this function with the supplied error code. This is a macro so that we can override it + * for stress testing. + * + * Note that this uses the do-while-0 wrapping to ensure that we don't get problems with dangling + * else clauses. Note also no closing semicolon - this is supplied in typical usage: + * + * MALI_CHECK((p!=NULL), ERROR_NO_OBJECT); + */ +#define MALI_CHECK(condition, error_code) do { if(!(condition)) MALI_ERROR(error_code); } while(0) + +/** + * Error propagation macro. If the expression given is anything other than _MALI_OSK_NO_ERROR, + * then the value is returned from the enclosing function as an error code. This effectively + * acts as a guard clause, and propagates error values up the call stack. This uses a + * temporary value to ensure that the error expression is not evaluated twice. + * If the counter for forcing a failure has been set using _mali_force_error, this error will be + * returned without evaluating the expression in MALI_CHECK_NO_ERROR + */ +#define MALI_CHECK_NO_ERROR(expression) \ + do { _mali_osk_errcode_t _check_no_error_result=(expression); \ + if(_check_no_error_result != _MALI_OSK_ERR_OK) \ + MALI_ERROR(_check_no_error_result); \ + } while(0) + +/** + * Pointer check macro. Checks non-null pointer. + */ +#define MALI_CHECK_NON_NULL(pointer, error_code) MALI_CHECK( ((pointer)!=NULL), (error_code) ) + +/** + * Error macro with goto. This checks whether the given condition is true, and if not jumps + * to the specified label using a goto. The label must therefore be local to the function in + * which this macro appears. This is most usually used to execute some clean-up code before + * exiting with a call to ERROR. + * + * Like the other macros, this is a macro to allow us to override the condition if we wish, + * e.g. to force an error during stress testing. + */ +#define MALI_CHECK_GOTO(condition, label) do { if(!(condition)) goto label; } while(0) + +/** + * Explicitly ignore a parameter passed into a function, to suppress compiler warnings. + * Should only be used with parameter names. + */ +#define MALI_IGNORE(x) x=x + +#define MALI_PRINTF(args) _mali_osk_dbgmsg args; + +#define MALI_PRINT_ERROR(args) do{ \ + MALI_PRINTF(("Mali: ERR: %s\n" ,__FILE__)); \ + MALI_PRINTF((" %s()%4d\n ", __FUNCTION__, __LINE__)) ; \ + MALI_PRINTF(args); \ + MALI_PRINTF(("\n")); \ + } while(0) + +#define MALI_PRINT(args) do{ \ + MALI_PRINTF(("Mali: ")); \ + MALI_PRINTF(args); \ + } while (0) + +#ifdef DEBUG +#ifndef mali_debug_level +extern int mali_debug_level; +#endif + +#define MALI_DEBUG_CODE(code) code +#define MALI_DEBUG_PRINT(level, args) do { \ + if((level) <= mali_debug_level)\ + {MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); } \ + } while (0) + +#define MALI_DEBUG_PRINT_ERROR(args) MALI_PRINT_ERROR(args) + +#define MALI_DEBUG_PRINT_IF(level,condition,args) \ + if((condition)&&((level) <= mali_debug_level))\ + {MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); } + +#define MALI_DEBUG_PRINT_ELSE(level, args)\ + else if((level) <= mali_debug_level)\ + { MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); } + +/** + * @note these variants of DEBUG ASSERTS will cause a debugger breakpoint + * to be entered (see _mali_osk_break() ). An alternative would be to call + * _mali_osk_abort(), on OSs that support it. + */ +#define MALI_DEBUG_PRINT_ASSERT(condition, args) do {if( !(condition)) { MALI_PRINT_ERROR(args); _mali_osk_break(); } } while(0) +#define MALI_DEBUG_ASSERT_POINTER(pointer) do {if( (pointer)== NULL) {MALI_PRINT_ERROR(("NULL pointer " #pointer)); _mali_osk_break();} } while(0) +#define MALI_DEBUG_ASSERT(condition) do {if( !(condition)) {MALI_PRINT_ERROR(("ASSERT failed: " #condition )); _mali_osk_break();} } while(0) + +#else /* DEBUG */ + +#define MALI_DEBUG_CODE(code) +#define MALI_DEBUG_PRINT(string,args) do {} while(0) +#define MALI_DEBUG_PRINT_ERROR(args) do {} while(0) +#define MALI_DEBUG_PRINT_IF(level,condition,args) do {} while(0) +#define MALI_DEBUG_PRINT_ELSE(level,condition,args) do {} while(0) +#define MALI_DEBUG_PRINT_ASSERT(condition,args) do {} while(0) +#define MALI_DEBUG_ASSERT_POINTER(pointer) do {} while(0) +#define MALI_DEBUG_ASSERT(condition) do {} while(0) + +#endif /* DEBUG */ + +/** + * variables from user space cannot be dereferenced from kernel space; tagging them + * with __user allows the GCC compiler to generate a warning. Other compilers may + * not support this so we define it here as an empty macro if the compiler doesn't + * define it. + */ +#ifndef __user +#define __user +#endif + +#endif /* __MALI_KERNEL_COMMON_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.c b/drivers/media/video/samsung/mali/common/mali_kernel_core.c new file mode 100644 index 0000000..45e86d2 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_core.c @@ -0,0 +1,980 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_ukk.h" +#include "mali_kernel_core.h" +#include "mali_memory.h" +#include "mali_mem_validation.h" +#include "mali_mmu.h" +#include "mali_mmu_page_directory.h" +#include "mali_dlbu.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" +#include "mali_cluster.h" +#include "mali_group.h" +#include "mali_pm.h" +#include "mali_pmu.h" +#include "mali_scheduler.h" +#ifdef CONFIG_MALI400_GPU_UTILIZATION +#include "mali_kernel_utilization.h" +#endif +#include "mali_l2_cache.h" +#if MALI_TIMELINE_PROFILING_ENABLED +#include "mali_osk_profiling.h" +#endif + +/** Pointer to table of resource definitions available to the Mali driver. + * _mali_osk_resources_init() sets up the pointer to this table. + */ +static _mali_osk_resource_t *arch_configuration = NULL; + +/** Start profiling from module load? */ +int mali_boot_profiling = 0; + +/** Number of resources initialized by _mali_osk_resources_init() */ +static u32 num_resources; + +static _mali_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN; +static u32 global_gpu_base_address = 0; +static u32 global_gpu_major_version = 0; +static u32 global_gpu_minor_version = 0; + +static u32 first_pp_offset = 0; + +#define HANG_CHECK_MSECS_DEFAULT 500 /* 500 ms */ +#define WATCHDOG_MSECS_DEFAULT 4000 /* 4 s */ + +/* timer related */ +int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT; +int mali_hang_check_interval = HANG_CHECK_MSECS_DEFAULT; + +static _mali_osk_resource_t *mali_find_resource(_mali_osk_resource_type_t type, u32 offset) +{ + int i; + u32 addr = global_gpu_base_address + offset; + + for (i = 0; i < num_resources; i++) + { + if (type == arch_configuration[i].type && arch_configuration[i].base == addr) + { + return &(arch_configuration[i]); + } + } + + return NULL; +} + +static u32 mali_count_resources(_mali_osk_resource_type_t type) +{ + int i; + u32 retval = 0; + + for (i = 0; i < num_resources; i++) + { + if (type == arch_configuration[i].type) + { + retval++; + } + } + + return retval; +} + + +static _mali_osk_errcode_t mali_parse_gpu_base_and_first_pp_offset_address(void) +{ + int i; + _mali_osk_resource_t *first_gp_resource = NULL; + _mali_osk_resource_t *first_pp_resource = NULL; + + for (i = 0; i < num_resources; i++) + { + if (MALI_GP == arch_configuration[i].type) + { + if (NULL == first_gp_resource || first_gp_resource->base > arch_configuration[i].base) + { + first_gp_resource = &(arch_configuration[i]); + } + } + if (MALI_PP == arch_configuration[i].type) + { + if (NULL == first_pp_resource || first_pp_resource->base > arch_configuration[i].base) + { + first_pp_resource = &(arch_configuration[i]); + } + } + } + + if (NULL == first_gp_resource || NULL == first_pp_resource) + { + MALI_PRINT_ERROR(("No GP+PP core specified in config file\n")); + return _MALI_OSK_ERR_FAULT; + } + + if (first_gp_resource->base < first_pp_resource->base) + { + /* GP is first, so we are dealing with Mali-300, Mali-400 or Mali-450 */ + global_gpu_base_address = first_gp_resource->base; + first_pp_offset = 0x8000; + } + else + { + /* PP is first, so we are dealing with Mali-200 */ + global_gpu_base_address = first_pp_resource->base; + first_pp_offset = 0x0; + } + MALI_SUCCESS; +} + +static _mali_osk_errcode_t mali_parse_product_info(void) +{ + _mali_osk_resource_t *first_pp_resource = NULL; + + /* Find the first PP core */ + first_pp_resource = mali_find_resource(MALI_PP, first_pp_offset); + if (NULL != first_pp_resource) + { + /* Create a dummy PP object for this core so that we can read the version register */ + struct mali_group *group = mali_group_create(NULL, NULL); + if (NULL != group) + { + /*struct mali_pp_core *pp_core = mali_pp_create(first_pp_resource, group, 0);*/ + struct mali_pp_core *pp_core = mali_pp_create(first_pp_resource, group); + if (NULL != pp_core) + { + u32 pp_version = mali_pp_core_get_version(pp_core); + mali_pp_delete(pp_core); + mali_group_delete(group); + + global_gpu_major_version = (pp_version >> 8) & 0xFF; + global_gpu_minor_version = pp_version & 0xFF; + + switch (pp_version >> 16) + { + case MALI200_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI200; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-200 r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + break; + case MALI300_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI300; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-300 r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + break; + case MALI400_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI400; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-400 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + break; + case MALI450_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI450; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-450 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + break; + default: + MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version)); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; + } + else + { + MALI_PRINT_ERROR(("Failed to create initial PP object\n")); + } + } + else + { + MALI_PRINT_ERROR(("Failed to create initial group object\n")); + } + } + else + { + MALI_PRINT_ERROR(("First PP core not specified in config file\n")); + } + + return _MALI_OSK_ERR_FAULT; +} + +static void mali_delete_clusters(void) +{ + u32 i; + u32 number_of_clusters = mali_cluster_get_glob_num_clusters(); + + for (i = 0; i < number_of_clusters; i++) + { + mali_cluster_delete(mali_cluster_get_global_cluster(i)); + } +} + +static _mali_osk_errcode_t mali_create_cluster(_mali_osk_resource_t *resource) +{ + if (NULL != resource) + { + struct mali_l2_cache_core *l2_cache; + + if (mali_l2_cache_core_get_glob_num_l2_cores() >= mali_l2_cache_core_get_max_num_l2_cores()) + { + MALI_PRINT_ERROR(("Found too many L2 cache core objects, max %u is supported\n", mali_l2_cache_core_get_max_num_l2_cores())); + return _MALI_OSK_ERR_FAULT; + } + + MALI_DEBUG_PRINT(3, ("Found L2 cache %s, starting new cluster\n", resource->description)); + + /*l2_cache = mali_l2_cache_create(resource, global_num_l2_cache_cores);*/ + l2_cache = mali_l2_cache_create(resource); + if (NULL == l2_cache) + { + MALI_PRINT_ERROR(("Failed to create L2 cache object\n")); + return _MALI_OSK_ERR_FAULT; + } + + if (NULL == mali_cluster_create(l2_cache)) + { + MALI_PRINT_ERROR(("Failed to create cluster object\n")); + mali_l2_cache_delete(l2_cache); + return _MALI_OSK_ERR_FAULT; + } + } + else + { + mali_cluster_create(NULL); + if (NULL == mali_cluster_get_global_cluster(0)) + { + MALI_PRINT_ERROR(("Failed to create cluster object\n")); + return _MALI_OSK_ERR_FAULT; + } + } + + MALI_DEBUG_PRINT(3, ("Created cluster object\n")); + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_parse_config_cluster(void) +{ + if (_MALI_PRODUCT_ID_MALI200 == global_product_id) + { + /* Create dummy cluster without L2 cache */ + return mali_create_cluster(NULL); + } + else if (_MALI_PRODUCT_ID_MALI300 == global_product_id || _MALI_PRODUCT_ID_MALI400 == global_product_id) + { + _mali_osk_resource_t *l2_resource = mali_find_resource(MALI_L2, 0x1000); + if (NULL == l2_resource) + { + MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n")); + return _MALI_OSK_ERR_FAULT; + } + + return mali_create_cluster(l2_resource); + } + else if (_MALI_PRODUCT_ID_MALI450 == global_product_id) + { + /* + * L2 for GP at 0x10000 + * L2 for PP0-3 at 0x01000 + * L2 for PP4-7 at 0x11000 (optional) + */ + + _mali_osk_resource_t *l2_gp_resource; + _mali_osk_resource_t *l2_pp_grp0_resource; + _mali_osk_resource_t *l2_pp_grp1_resource; + + /* Make cluster for GP's L2 */ + l2_gp_resource = mali_find_resource(MALI_L2, 0x10000); + if (NULL != l2_gp_resource) + { + _mali_osk_errcode_t ret; + MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for GP\n")); + ret = mali_create_cluster(l2_gp_resource); + if (_MALI_OSK_ERR_OK != ret) + { + return ret; + } + } + else + { + MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Make cluster for first PP core group */ + l2_pp_grp0_resource = mali_find_resource(MALI_L2, 0x1000); + if (NULL != l2_pp_grp0_resource) + { + _mali_osk_errcode_t ret; + MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for PP group 0\n")); + ret = mali_create_cluster(l2_pp_grp0_resource); + if (_MALI_OSK_ERR_OK != ret) + { + return ret; + } + } + else + { + MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for PP group 0 in config file\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Second PP core group is optional, don't fail if we don't find it */ + l2_pp_grp1_resource = mali_find_resource(MALI_L2, 0x11000); + if (NULL != l2_pp_grp1_resource) + { + _mali_osk_errcode_t ret; + MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for PP group 0\n")); + ret = mali_create_cluster(l2_pp_grp1_resource); + if (_MALI_OSK_ERR_OK != ret) + { + return ret; + } + } + } + + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_create_group(struct mali_cluster *cluster, + _mali_osk_resource_t *resource_mmu, + _mali_osk_resource_t *resource_gp, + _mali_osk_resource_t *resource_pp) +{ + struct mali_mmu_core *mmu; + struct mali_group *group; + struct mali_pp_core *pp; + + MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description)); + + /* Create the MMU object */ + mmu = mali_mmu_create(resource_mmu); + if (NULL == mmu) + { + MALI_PRINT_ERROR(("Failed to create MMU object\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Create the group object */ + group = mali_group_create(cluster, mmu); + if (NULL == group) + { + MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description)); + mali_mmu_delete(mmu); + return _MALI_OSK_ERR_FAULT; + } + + /* Set pointer back to group in mmu.*/ + mali_mmu_set_group(mmu, group); + + /* Add this group to current cluster */ + mali_cluster_add_group(cluster, group); + + if (NULL != resource_gp) + { + /* Create the GP core object inside this group */ + /* global_gp_core = mali_gp_create(resource_gp, group); */ + if (NULL == mali_gp_create(resource_gp, group)) + { + /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ + MALI_PRINT_ERROR(("Failed to create GP object\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Add GP object to this group */ + MALI_DEBUG_PRINT(3, ("Adding GP %s to group\n", resource_gp->description)); + mali_group_add_gp_core(group, mali_gp_get_global_gp_core()); + } + + if (NULL != resource_pp) + { + /* Create the PP core object inside this group */ + pp = mali_pp_create(resource_pp, group); + + if (NULL == pp) + { + /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ + MALI_PRINT_ERROR(("Failed to create PP object\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Add PP object to this group */ + MALI_DEBUG_PRINT(3, ("Adding PP %s to group\n", resource_pp->description)); + mali_group_add_pp_core(group, pp); + } + + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_parse_config_groups(void) +{ + if (_MALI_PRODUCT_ID_MALI200 == global_product_id) + { + _mali_osk_resource_t *resource_gp; + _mali_osk_resource_t *resource_pp; + _mali_osk_resource_t *resource_mmu; + + MALI_DEBUG_ASSERT(1 == mali_cluster_get_glob_num_clusters()); + + resource_gp = mali_find_resource(MALI_GP, 0x02000); + resource_pp = mali_find_resource(MALI_PP, 0x00000); + resource_mmu = mali_find_resource(MMU, 0x03000); + + if (NULL == resource_mmu || NULL == resource_gp || NULL == resource_pp) + { + /* Missing mandatory core(s) */ + return _MALI_OSK_ERR_FAULT; + } + + /*return mali_create_group(global_clusters[0], resource_mmu, resource_gp, resource_pp);*/ + return mali_create_group(mali_cluster_get_global_cluster(0), resource_mmu, resource_gp, resource_pp); + } + else if (_MALI_PRODUCT_ID_MALI300 == global_product_id || + _MALI_PRODUCT_ID_MALI400 == global_product_id || + _MALI_PRODUCT_ID_MALI450 == global_product_id) + { + _mali_osk_errcode_t err; + int cluster_id_gp = 0; + int cluster_id_pp_grp0 = 0; + int cluster_id_pp_grp1 = 0; + int i; + _mali_osk_resource_t *resource_gp; + _mali_osk_resource_t *resource_gp_mmu; + _mali_osk_resource_t *resource_pp[mali_pp_get_max_num_pp_cores()]; + _mali_osk_resource_t *resource_pp_mmu[mali_pp_get_max_num_pp_cores()]; + u32 max_num_pp_cores = mali_pp_get_max_num_pp_cores(); + + if (_MALI_PRODUCT_ID_MALI450 == global_product_id) + { + /* Mali-450 has separate L2s for GP, and PP core group(s) */ + cluster_id_pp_grp0 = 1; + cluster_id_pp_grp1 = 2; + } + + resource_gp = mali_find_resource(MALI_GP, 0x00000); + resource_gp_mmu = mali_find_resource(MMU, 0x03000); + resource_pp[0] = mali_find_resource(MALI_PP, 0x08000); + resource_pp[1] = mali_find_resource(MALI_PP, 0x0A000); + resource_pp[2] = mali_find_resource(MALI_PP, 0x0C000); + resource_pp[3] = mali_find_resource(MALI_PP, 0x0E000); + resource_pp[4] = mali_find_resource(MALI_PP, 0x28000); + resource_pp[5] = mali_find_resource(MALI_PP, 0x2A000); + resource_pp[6] = mali_find_resource(MALI_PP, 0x2C000); + resource_pp[7] = mali_find_resource(MALI_PP, 0x2E000); + resource_pp_mmu[0] = mali_find_resource(MMU, 0x04000); + resource_pp_mmu[1] = mali_find_resource(MMU, 0x05000); + resource_pp_mmu[2] = mali_find_resource(MMU, 0x06000); + resource_pp_mmu[3] = mali_find_resource(MMU, 0x07000); + resource_pp_mmu[4] = mali_find_resource(MMU, 0x1C000); + resource_pp_mmu[5] = mali_find_resource(MMU, 0x1D000); + resource_pp_mmu[6] = mali_find_resource(MMU, 0x1E000); + resource_pp_mmu[7] = mali_find_resource(MMU, 0x1F000); + + if (NULL == resource_gp || NULL == resource_gp_mmu || NULL == resource_pp[0] || NULL == resource_pp_mmu[0]) + { + /* Missing mandatory core(s) */ + MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU (0x%08X, 0x%08X, 0x%08X, 0x%08X)\n", + resource_gp, resource_gp_mmu, resource_pp[0], resource_pp_mmu[0])); + return _MALI_OSK_ERR_FAULT; + } + + MALI_DEBUG_ASSERT(1 <= mali_cluster_get_glob_num_clusters()); + err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_gp), resource_gp_mmu, resource_gp, NULL); + if (err != _MALI_OSK_ERR_OK) + { + return err; + } + + /* Create group for first (and mandatory) PP core */ + MALI_DEBUG_ASSERT(mali_cluster_get_glob_num_clusters() >= (cluster_id_pp_grp0 + 1)); /* >= 1 on Mali-300 and Mali-400, >= 2 on Mali-450 */ + err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp0), resource_pp_mmu[0], NULL, resource_pp[0]); + if (err != _MALI_OSK_ERR_OK) + { + return err; + } + + /* Create groups for rest of the cores in the first PP core group */ + for (i = 1; i < 4; i++) /* First half of the PP cores belong to first core group */ + { + if (NULL != resource_pp[i]) + { + err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp0), resource_pp_mmu[i], NULL, resource_pp[i]); + if (err != _MALI_OSK_ERR_OK) + { + return err; + } + } + } + + /* Create groups for cores in the second PP core group */ + for (i = 4; i < max_num_pp_cores; i++) /* Second half of the PP cores belong to second core group */ + { + if (NULL != resource_pp[i]) + { + MALI_DEBUG_ASSERT(mali_cluster_get_glob_num_clusters() >= 2); /* Only Mali-450 have more than 4 PPs, and these cores belong to second core group */ + err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp1), resource_pp_mmu[i], NULL, resource_pp[i]); + if (err != _MALI_OSK_ERR_OK) + { + return err; + } + } + } + } + + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_parse_config_pmu(void) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; + _mali_osk_resource_t *resource_pmu; + u32 number_of_pp_cores; + u32 number_of_l2_caches; + + resource_pmu = mali_find_resource(PMU, 0x02000); + number_of_pp_cores = mali_count_resources(MALI_PP); + number_of_l2_caches = mali_count_resources(MALI_L2); + + if (NULL != resource_pmu) + { + if (NULL == mali_pmu_create(resource_pmu, number_of_pp_cores, number_of_l2_caches)) + { + err = _MALI_OSK_ERR_FAULT; + } + } + return err; +} + +static _mali_osk_errcode_t mali_parse_config_memory(void) +{ + int i; + _mali_osk_errcode_t ret; + + for(i = 0; i < num_resources; i++) + { + switch(arch_configuration[i].type) + { + case OS_MEMORY: + ret = mali_memory_core_resource_os_memory(&arch_configuration[i]); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to register OS_MEMORY\n")); + mali_memory_terminate(); + return ret; + } + break; + case MEMORY: + ret = mali_memory_core_resource_dedicated_memory(&arch_configuration[i]); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to register MEMORY\n")); + mali_memory_terminate(); + return ret; + } + break; + case MEM_VALIDATION: + ret = mali_mem_validation_add_range(&arch_configuration[i]); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to register MEM_VALIDATION\n")); + mali_memory_terminate(); + return ret; + } + break; + default: + break; + } + } + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_initialize_subsystems(void) +{ + _mali_osk_errcode_t err; + mali_bool is_pmu_enabled; + + err = mali_session_initialize(); + if (_MALI_OSK_ERR_OK != err) goto session_init_failed; + +#if MALI_TIMELINE_PROFILING_ENABLED + err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE); + if (_MALI_OSK_ERR_OK != err) + { + /* No biggie if we wheren't able to initialize the profiling */ + MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n")); + } +#endif + + /* Get data from config.h */ + err = _mali_osk_resources_init(&arch_configuration, &num_resources); + if (_MALI_OSK_ERR_OK != err) goto osk_resources_init_failed; + + /* Initialize driver subsystems */ + err = mali_memory_initialize(); + if (_MALI_OSK_ERR_OK != err) goto memory_init_failed; + + /* Configure memory early. Memory allocation needed for mali_mmu_initialize. */ + err = mali_parse_config_memory(); + if (_MALI_OSK_ERR_OK != err) goto parse_memory_config_failed; + + /* Parsing the GPU base address and first pp offset */ + err = mali_parse_gpu_base_and_first_pp_offset_address(); + if (_MALI_OSK_ERR_OK != err) goto parse_gpu_base_address_failed; + + /* Initialize the MALI PMU */ + err = mali_parse_config_pmu(); + if (_MALI_OSK_ERR_OK != err) goto parse_pmu_config_failed; + + is_pmu_enabled = mali_pmu_get_global_pmu_core() != NULL ? MALI_TRUE : MALI_FALSE; + + /* Initialize the power management module */ + err = mali_pm_initialize(); + if (_MALI_OSK_ERR_OK != err) goto pm_init_failed; + + /* Make sure the power stays on for the rest of this function */ + mali_pm_always_on(MALI_TRUE); + + /* Detect which Mali GPU we are dealing with */ + err = mali_parse_product_info(); + if (_MALI_OSK_ERR_OK != err) goto product_info_parsing_failed; + + /* The global_product_id is now populated with the correct Mali GPU */ + + /* Initialize MMU module */ + err = mali_mmu_initialize(); + if (_MALI_OSK_ERR_OK != err) goto mmu_init_failed; + + /* Initialize the DLBU module for Mali-450 */ + if (_MALI_PRODUCT_ID_MALI450 == global_product_id) + { + err = mali_dlbu_initialize(); + if (_MALI_OSK_ERR_OK != err) goto dlbu_init_failed; + } + + /* Start configuring the actual Mali hardware. */ + err = mali_parse_config_cluster(); + if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed; + err = mali_parse_config_groups(); + if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed; + + /* Initialize the schedulers */ + err = mali_scheduler_initialize(); + if (_MALI_OSK_ERR_OK != err) goto scheduler_init_failed; + err = mali_gp_scheduler_initialize(); + if (_MALI_OSK_ERR_OK != err) goto gp_scheduler_init_failed; + err = mali_pp_scheduler_initialize(); + if (_MALI_OSK_ERR_OK != err) goto pp_scheduler_init_failed; + +#ifdef CONFIG_MALI400_GPU_UTILIZATION + /* Initialize the GPU utilization tracking */ + err = mali_utilization_init(); + if (_MALI_OSK_ERR_OK != err) goto utilization_init_failed; +#endif + + /* We no longer need to stay */ + mali_pm_always_on(MALI_FALSE); + MALI_SUCCESS; /* all ok */ + + /* Error handling */ +#ifdef CONFIG_MALI400_GPU_UTILIZATION +utilization_init_failed: + mali_pp_scheduler_terminate(); +#endif +pp_scheduler_init_failed: + mali_gp_scheduler_terminate(); +gp_scheduler_init_failed: + mali_scheduler_terminate(); +scheduler_init_failed: +config_parsing_failed: + mali_delete_clusters(); /* Delete clusters even if config parsing failed. */ + if (_MALI_PRODUCT_ID_MALI450 == global_product_id) + { + mali_dlbu_terminate(); + } +dlbu_init_failed: + mali_mmu_terminate(); +mmu_init_failed: + /* Nothing to roll back */ +product_info_parsing_failed: + mali_pm_terminate(); +pm_init_failed: + if (is_pmu_enabled) + { + mali_pmu_delete(mali_pmu_get_global_pmu_core()); + } +parse_pmu_config_failed: +parse_gpu_base_address_failed: +parse_memory_config_failed: + mali_memory_terminate(); +memory_init_failed: + _mali_osk_resources_term(&arch_configuration, num_resources); +osk_resources_init_failed: +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_term(); +#endif + mali_session_terminate(); +session_init_failed: + return err; +} + +void mali_terminate_subsystems(void) +{ + struct mali_pmu_core *pmu; + + MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n")); + + /* shut down subsystems in reverse order from startup */ + + mali_pm_always_on(MALI_TRUE); /* Mali will be powered off once PM subsystem terminates */ + +#ifdef CONFIG_MALI400_GPU_UTILIZATION + mali_utilization_term(); +#endif + + mali_pp_scheduler_terminate(); + mali_gp_scheduler_terminate(); + mali_scheduler_terminate(); + + mali_delete_clusters(); /* Delete clusters even if config parsing failed. */ + + if (_MALI_PRODUCT_ID_MALI450 == global_product_id) + { + mali_dlbu_terminate(); + } + + mali_mmu_terminate(); + + pmu = mali_pmu_get_global_pmu_core(); + if (NULL != pmu) + { + mali_pmu_delete(pmu); + } + + mali_pm_terminate(); + + mali_memory_terminate(); + + _mali_osk_resources_term(&arch_configuration, num_resources); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_term(); +#endif + + mali_session_terminate(); +} + +_mali_product_id_t mali_kernel_core_get_product_id(void) +{ + return global_product_id; +} + +void mali_kernel_core_wakeup(void) +{ + u32 i; + u32 glob_num_clusters = mali_cluster_get_glob_num_clusters(); + struct mali_cluster *cluster; + + for (i = 0; i < glob_num_clusters; i++) + { + cluster = mali_cluster_get_global_cluster(i); + mali_cluster_reset(cluster); + } +} + +_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args ) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + /* check compatability */ + if ( args->version == _MALI_UK_API_VERSION ) + { + args->compatible = 1; + } + else + { + args->compatible = 0; + } + + args->version = _MALI_UK_API_VERSION; /* report our version */ + + /* success regardless of being compatible or not */ + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args ) +{ + _mali_osk_errcode_t err; + _mali_osk_notification_t *notification; + _mali_osk_notification_queue_t *queue; + + /* check input */ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + queue = ((struct mali_session_data *)args->ctx)->ioctl_queue; + + /* if the queue does not exist we're currently shutting down */ + if (NULL == queue) + { + MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); + args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS; + MALI_SUCCESS; + } + + /* receive a notification, might sleep */ + err = _mali_osk_notification_queue_receive(queue, ¬ification); + if (_MALI_OSK_ERR_OK != err) + { + MALI_ERROR(err); /* errcode returned, pass on to caller */ + } + + /* copy the buffer to the user */ + args->type = (_mali_uk_notification_type)notification->notification_type; + _mali_osk_memcpy(&args->data, notification->result_buffer, notification->result_buffer_size); + + /* finished with the notification */ + _mali_osk_notification_delete( notification ); + + MALI_SUCCESS; /* all ok */ +} + +_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args ) +{ + _mali_osk_notification_t * notification; + _mali_osk_notification_queue_t *queue; + + /* check input */ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + queue = ((struct mali_session_data *)args->ctx)->ioctl_queue; + + /* if the queue does not exist we're currently shutting down */ + if (NULL == queue) + { + MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); + MALI_SUCCESS; + } + + notification = _mali_osk_notification_create(args->type, 0); + if ( NULL == notification) + { + MALI_PRINT_ERROR( ("Failed to create notification object\n")); + return _MALI_OSK_ERR_NOMEM; + } + + _mali_osk_notification_queue_send(queue, notification); + + MALI_SUCCESS; /* all ok */ +} + +_mali_osk_errcode_t _mali_ukk_open(void **context) +{ + struct mali_session_data *session_data; + + /* allocated struct to track this session */ + session_data = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data)); + MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_NOMEM); + + MALI_DEBUG_PRINT(2, ("Session starting\n")); + + /* create a response queue for this session */ + session_data->ioctl_queue = _mali_osk_notification_queue_init(); + if (NULL == session_data->ioctl_queue) + { + _mali_osk_free(session_data); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + session_data->page_directory = mali_mmu_pagedir_alloc(); + if (NULL == session_data->page_directory) + { + _mali_osk_notification_queue_term(session_data->ioctl_queue); + _mali_osk_free(session_data); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session_data->page_directory, MALI_DLB_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE)) + { + MALI_PRINT_ERROR(("Failed to map DLB page into session\n")); + _mali_osk_notification_queue_term(session_data->ioctl_queue); + _mali_osk_free(session_data); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + if (0 != mali_dlbu_phys_addr) + { + mali_mmu_pagedir_update(session_data->page_directory, MALI_DLB_VIRT_ADDR, mali_dlbu_phys_addr, _MALI_OSK_MALI_PAGE_SIZE, MALI_CACHE_STANDARD); + } + + if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session_data)) + { + mali_mmu_pagedir_free(session_data->page_directory); + _mali_osk_notification_queue_term(session_data->ioctl_queue); + _mali_osk_free(session_data); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + *context = (void*)session_data; + + /* Add session to the list of all sessions. */ + mali_session_add(session_data); + + MALI_DEBUG_PRINT(3, ("Session started\n")); + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_close(void **context) +{ + struct mali_session_data *session; + MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS); + session = (struct mali_session_data *)*context; + + MALI_DEBUG_PRINT(3, ("Session ending\n")); + + /* Remove session from list of all sessions. */ + mali_session_remove(session); + + /* Abort queued and running jobs */ + mali_gp_scheduler_abort_session(session); + mali_pp_scheduler_abort_session(session); + + /* Flush pending work. + * Needed to make sure all bottom half processing related to this + * session has been completed, before we free internal data structures. + */ + _mali_osk_flush_workqueue(NULL); + + /* Free remaining memory allocated to this session */ + mali_memory_session_end(session); + + /* Free session data structures */ + mali_mmu_pagedir_free(session->page_directory); + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + + *context = NULL; + + MALI_DEBUG_PRINT(2, ("Session has ended\n")); + + MALI_SUCCESS; +} + +#if MALI_STATE_TRACKING +u32 _mali_kernel_core_dump_state(char* buf, u32 size) +{ + int n = 0; /* Number of bytes written to buf */ + + n += mali_gp_scheduler_dump_state(buf + n, size - n); + n += mali_pp_scheduler_dump_state(buf + n, size - n); + + return n; +} +#endif diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.h b/drivers/media/video/samsung/mali/common/mali_kernel_core.h new file mode 100644 index 0000000..d424c48 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_core.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_CORE_H__ +#define __MALI_KERNEL_CORE_H__ + +#include "mali_osk.h" + +extern int mali_hang_check_interval; +extern int mali_max_job_runtime; + +typedef enum +{ + _MALI_PRODUCT_ID_UNKNOWN, + _MALI_PRODUCT_ID_MALI200, + _MALI_PRODUCT_ID_MALI300, + _MALI_PRODUCT_ID_MALI400, + _MALI_PRODUCT_ID_MALI450, +} _mali_product_id_t; + +_mali_osk_errcode_t mali_initialize_subsystems(void); + +void mali_terminate_subsystems(void); + +void mali_kernel_core_wakeup(void); + +_mali_product_id_t mali_kernel_core_get_product_id(void); + +u32 _mali_kernel_core_dump_state(char* buf, u32 size); + +#endif /* __MALI_KERNEL_CORE_H__ */ + diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c new file mode 100644 index 0000000..b9f05ca --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_kernel_descriptor_mapping.h" +#include "mali_osk.h" +#include "mali_osk_bitops.h" + +#define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1)) + +/** + * Allocate a descriptor table capable of holding 'count' mappings + * @param count Number of mappings in the table + * @return Pointer to a new table, NULL on error + */ +static mali_descriptor_table * descriptor_table_alloc(int count); + +/** + * Free a descriptor table + * @param table The table to free + */ +static void descriptor_table_free(mali_descriptor_table * table); + +mali_descriptor_mapping * mali_descriptor_mapping_create(int init_entries, int max_entries) +{ + mali_descriptor_mapping * map = _mali_osk_calloc(1, sizeof(mali_descriptor_mapping)); + + init_entries = MALI_PAD_INT(init_entries); + max_entries = MALI_PAD_INT(max_entries); + + if (NULL != map) + { + map->table = descriptor_table_alloc(init_entries); + if (NULL != map->table) + { + map->lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP); + if (NULL != map->lock) + { + _mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */ + map->max_nr_mappings_allowed = max_entries; + map->current_nr_mappings = init_entries; + return map; + } + descriptor_table_free(map->table); + } + _mali_osk_free(map); + } + return NULL; +} + +void mali_descriptor_mapping_destroy(mali_descriptor_mapping * map) +{ + descriptor_table_free(map->table); + _mali_osk_lock_term(map->lock); + _mali_osk_free(map); +} + +_mali_osk_errcode_t mali_descriptor_mapping_allocate_mapping(mali_descriptor_mapping * map, void * target, int *odescriptor) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + int new_descriptor; + + MALI_DEBUG_ASSERT_POINTER(map); + MALI_DEBUG_ASSERT_POINTER(odescriptor); + + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + new_descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); + if (new_descriptor == map->current_nr_mappings) + { + /* no free descriptor, try to expand the table */ + mali_descriptor_table * new_table, * old_table; + if (map->current_nr_mappings >= map->max_nr_mappings_allowed) goto unlock_and_exit; + + map->current_nr_mappings += BITS_PER_LONG; + new_table = descriptor_table_alloc(map->current_nr_mappings); + if (NULL == new_table) goto unlock_and_exit; + + old_table = map->table; + _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); + _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); + map->table = new_table; + descriptor_table_free(old_table); + } + + /* we have found a valid descriptor, set the value and usage bit */ + _mali_osk_set_nonatomic_bit(new_descriptor, map->table->usage); + map->table->mappings[new_descriptor] = target; + *odescriptor = new_descriptor; + err = _MALI_OSK_ERR_OK; + +unlock_and_exit: + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); + MALI_ERROR(err); +} + +void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping * map, void (*callback)(int, void*)) +{ + int i; + + MALI_DEBUG_ASSERT_POINTER(map); + MALI_DEBUG_ASSERT_POINTER(callback); + + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + /* id 0 is skipped as it's an reserved ID not mapping to anything */ + for (i = 1; i < map->current_nr_mappings; ++i) + { + if (_mali_osk_test_bit(i, map->table->usage)) + { + callback(i, map->table->mappings[i]); + } + } + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); +} + +_mali_osk_errcode_t mali_descriptor_mapping_get(mali_descriptor_mapping * map, int descriptor, void** target) +{ + _mali_osk_errcode_t result = _MALI_OSK_ERR_FAULT; + MALI_DEBUG_ASSERT_POINTER(map); + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + *target = map->table->mappings[descriptor]; + result = _MALI_OSK_ERR_OK; + } + else *target = NULL; + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); + MALI_ERROR(result); +} + +_mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping * map, int descriptor, void * target) +{ + _mali_osk_errcode_t result = _MALI_OSK_ERR_FAULT; + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + map->table->mappings[descriptor] = target; + result = _MALI_OSK_ERR_OK; + } + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); + MALI_ERROR(result); +} + +void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor) +{ + void *old_value = NULL; + + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + old_value = map->table->mappings[descriptor]; + map->table->mappings[descriptor] = NULL; + _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage); + } + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); + + return old_value; +} + +static mali_descriptor_table * descriptor_table_alloc(int count) +{ + mali_descriptor_table * table; + + table = _mali_osk_calloc(1, sizeof(mali_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count)); + + if (NULL != table) + { + table->usage = (u32*)((u8*)table + sizeof(mali_descriptor_table)); + table->mappings = (void**)((u8*)table + sizeof(mali_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG)); + } + + return table; +} + +static void descriptor_table_free(mali_descriptor_table * table) +{ + _mali_osk_free(table); +} diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h new file mode 100644 index 0000000..82ed94d --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_kernel_descriptor_mapping.h + */ + +#ifndef __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ +#define __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ + +#include "mali_osk.h" + +/** + * The actual descriptor mapping table, never directly accessed by clients + */ +typedef struct mali_descriptor_table +{ + u32 * usage; /**< Pointer to bitpattern indicating if a descriptor is valid/used or not */ + void** mappings; /**< Array of the pointers the descriptors map to */ +} mali_descriptor_table; + +/** + * The descriptor mapping object + * Provides a separate namespace where we can map an integer to a pointer + */ +typedef struct mali_descriptor_mapping +{ + _mali_osk_lock_t *lock; /**< Lock protecting access to the mapping object */ + int max_nr_mappings_allowed; /**< Max number of mappings to support in this namespace */ + int current_nr_mappings; /**< Current number of possible mappings */ + mali_descriptor_table * table; /**< Pointer to the current mapping table */ +} mali_descriptor_mapping; + +/** + * Create a descriptor mapping object + * Create a descriptor mapping capable of holding init_entries growable to max_entries + * @param init_entries Number of entries to preallocate memory for + * @param max_entries Number of entries to max support + * @return Pointer to a descriptor mapping object, NULL on failure + */ +mali_descriptor_mapping * mali_descriptor_mapping_create(int init_entries, int max_entries); + +/** + * Destroy a descriptor mapping object + * @param map The map to free + */ +void mali_descriptor_mapping_destroy(mali_descriptor_mapping * map); + +/** + * Allocate a new mapping entry (descriptor ID) + * Allocates a new entry in the map. + * @param map The map to allocate a new entry in + * @param target The value to map to + * @return The descriptor allocated, a negative value on error + */ +_mali_osk_errcode_t mali_descriptor_mapping_allocate_mapping(mali_descriptor_mapping * map, void * target, int *descriptor); + +/** + * Get the value mapped to by a descriptor ID + * @param map The map to lookup the descriptor id in + * @param descriptor The descriptor ID to lookup + * @param target Pointer to a pointer which will receive the stored value + * @return 0 on successful lookup, negative on error + */ +_mali_osk_errcode_t mali_descriptor_mapping_get(mali_descriptor_mapping * map, int descriptor, void** target); + +/** + * Set the value mapped to by a descriptor ID + * @param map The map to lookup the descriptor id in + * @param descriptor The descriptor ID to lookup + * @param target Pointer to replace the current value with + * @return 0 on successful lookup, negative on error + */ +_mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping * map, int descriptor, void * target); + +/** + * Call the specified callback function for each descriptor in map. + * Entire function is mutex protected. + * @param map The map to do callbacks for + * @param callback A callback function which will be calle for each entry in map + */ +void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping * map, void (*callback)(int, void*)); + +/** + * Free the descriptor ID + * For the descriptor to be reused it has to be freed + * @param map The map to free the descriptor from + * @param descriptor The descriptor ID to free + * + * @return old value of descriptor mapping + */ +void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor); + +#endif /* __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c new file mode 100644 index 0000000..8ff3d37 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#include "mali_kernel_memory_engine.h" +#include "mali_osk.h" + +typedef struct os_allocation +{ + u32 num_pages; + u32 offset_start; + mali_allocation_engine * engine; + mali_memory_allocation * descriptor; +} os_allocation; + +typedef struct os_allocator +{ + _mali_osk_lock_t *mutex; + + /** + * Maximum number of pages to allocate from the OS + */ + u32 num_pages_max; + + /** + * Number of pages allocated from the OS + */ + u32 num_pages_allocated; + + /** CPU Usage adjustment (add to mali physical address to get cpu physical address) */ + u32 cpu_usage_adjust; +} os_allocator; + +static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); +static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block); +static void os_allocator_release(void * ctx, void * handle); +static void os_allocator_page_table_block_release( mali_page_table_block *page_table_block ); +static void os_allocator_destroy(mali_physical_memory_allocator * allocator); +static u32 os_allocator_stat(mali_physical_memory_allocator * allocator); + +mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u32 cpu_usage_adjust, const char *name) +{ + mali_physical_memory_allocator * allocator; + os_allocator * info; + + max_allocation = (max_allocation + _MALI_OSK_CPU_PAGE_SIZE-1) & ~(_MALI_OSK_CPU_PAGE_SIZE-1); + + MALI_DEBUG_PRINT(2, ("Mali OS memory allocator created with max allocation size of 0x%X bytes, cpu_usage_adjust 0x%08X\n", max_allocation, cpu_usage_adjust)); + + allocator = _mali_osk_malloc(sizeof(mali_physical_memory_allocator)); + if (NULL != allocator) + { + info = _mali_osk_malloc(sizeof(os_allocator)); + if (NULL != info) + { + info->num_pages_max = max_allocation / _MALI_OSK_CPU_PAGE_SIZE; + info->num_pages_allocated = 0; + info->cpu_usage_adjust = cpu_usage_adjust; + + info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_MEM_INFO); + if (NULL != info->mutex) + { + allocator->allocate = os_allocator_allocate; + allocator->allocate_page_table_block = os_allocator_allocate_page_table_block; + allocator->destroy = os_allocator_destroy; + allocator->stat = os_allocator_stat; + allocator->ctx = info; + allocator->name = name; + + return allocator; + } + _mali_osk_free(info); + } + _mali_osk_free(allocator); + } + + return NULL; +} + +static u32 os_allocator_stat(mali_physical_memory_allocator * allocator) +{ + os_allocator * info; + info = (os_allocator*)allocator->ctx; + return info->num_pages_allocated * _MALI_OSK_MALI_PAGE_SIZE; +} + +static void os_allocator_destroy(mali_physical_memory_allocator * allocator) +{ + os_allocator * info; + MALI_DEBUG_ASSERT_POINTER(allocator); + MALI_DEBUG_ASSERT_POINTER(allocator->ctx); + info = (os_allocator*)allocator->ctx; + _mali_osk_lock_term(info->mutex); + _mali_osk_free(info); + _mali_osk_free(allocator); +} + +static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_NONE; + u32 left; + os_allocator * info; + os_allocation * allocation; + int pages_allocated = 0; + _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(offset); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + info = (os_allocator*)ctx; + left = descriptor->size - *offset; + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; + + /** @note this code may not work on Linux, or may require a more complex Linux implementation */ + allocation = _mali_osk_malloc(sizeof(os_allocation)); + if (NULL != allocation) + { + u32 os_mem_max_usage = info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE; + allocation->offset_start = *offset; + allocation->num_pages = ((left + _MALI_OSK_CPU_PAGE_SIZE - 1) & ~(_MALI_OSK_CPU_PAGE_SIZE - 1)) >> _MALI_OSK_CPU_PAGE_ORDER; + MALI_DEBUG_PRINT(6, ("Allocating page array of size %d bytes\n", allocation->num_pages * sizeof(struct page*))); + + while (left > 0) + { + err = mali_allocation_engine_map_physical(engine, descriptor, *offset, MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, info->cpu_usage_adjust, _MALI_OSK_CPU_PAGE_SIZE); + if ( _MALI_OSK_ERR_OK != err) + { + if ( _MALI_OSK_ERR_NOMEM == err) + { + /* 'Partial' allocation (or, out-of-memory on first page) */ + break; + } + + MALI_DEBUG_PRINT(1, ("Mapping of physical memory failed\n")); + + /* Fatal error, cleanup any previous pages allocated. */ + if ( pages_allocated > 0 ) + { + mali_allocation_engine_unmap_physical( engine, descriptor, allocation->offset_start, _MALI_OSK_CPU_PAGE_SIZE*pages_allocated, _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR ); + /* (*offset) doesn't need to be restored; it will not be used by the caller on failure */ + } + + pages_allocated = 0; + + result = MALI_MEM_ALLOC_INTERNAL_FAILURE; + break; + } + + /* Loop iteration */ + if (left < _MALI_OSK_CPU_PAGE_SIZE) left = 0; + else left -= _MALI_OSK_CPU_PAGE_SIZE; + + pages_allocated++; + + *offset += _MALI_OSK_CPU_PAGE_SIZE; + } + + if (left) MALI_PRINT(("Out of memory. Mali memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", + (info->num_pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); + + /* Loop termination; decide on result */ + if (pages_allocated) + { + MALI_DEBUG_PRINT(6, ("Allocated %d pages\n", pages_allocated)); + if (left) result = MALI_MEM_ALLOC_PARTIAL; + else result = MALI_MEM_ALLOC_FINISHED; + + /* Some OS do not perform a full cache flush (including all outer caches) for uncached mapped memory. + * They zero the memory through a cached mapping, then flush the inner caches but not the outer caches. + * This is required for MALI to have the correct view of the memory. + */ + _mali_osk_cache_ensure_uncached_range_flushed( (void *)descriptor, allocation->offset_start, pages_allocated *_MALI_OSK_CPU_PAGE_SIZE ); + allocation->num_pages = pages_allocated; + allocation->engine = engine; /* Necessary to make the engine's unmap call */ + allocation->descriptor = descriptor; /* Necessary to make the engine's unmap call */ + info->num_pages_allocated += pages_allocated; + + MALI_DEBUG_PRINT(6, ("%d out of %d pages now allocated\n", info->num_pages_allocated, info->num_pages_max)); + + alloc_info->ctx = info; + alloc_info->handle = allocation; + alloc_info->release = os_allocator_release; + } + else + { + MALI_DEBUG_PRINT(6, ("Releasing pages array due to no pages allocated\n")); + _mali_osk_free( allocation ); + } + } + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + return result; +} + +static void os_allocator_release(void * ctx, void * handle) +{ + os_allocator * info; + os_allocation * allocation; + mali_allocation_engine * engine; + mali_memory_allocation * descriptor; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(handle); + + info = (os_allocator*)ctx; + allocation = (os_allocation*)handle; + engine = allocation->engine; + descriptor = allocation->descriptor; + + MALI_DEBUG_ASSERT_POINTER( engine ); + MALI_DEBUG_ASSERT_POINTER( descriptor ); + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) + { + MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); + return; + } + + MALI_DEBUG_PRINT(6, ("Releasing %d os pages\n", allocation->num_pages)); + + MALI_DEBUG_ASSERT( allocation->num_pages <= info->num_pages_allocated); + info->num_pages_allocated -= allocation->num_pages; + + mali_allocation_engine_unmap_physical( engine, descriptor, allocation->offset_start, _MALI_OSK_CPU_PAGE_SIZE*allocation->num_pages, _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR ); + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_free(allocation); +} + +static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) +{ +#if defined(CONFIG_MACH_KONA) +#ifndef CONFIG_FORCE_MAX_ZONEORDER + int allocation_order = 10; +#else + int allocation_order = CONFIG_FORCE_MAX_ZONEORDER - 1; +#endif +#else + int allocation_order = 11; /* _MALI_OSK_CPU_PAGE_SIZE << 6 */ +#endif + void *virt = NULL; + u32 size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; + os_allocator * info; + + u32 cpu_phys_base; + + MALI_DEBUG_ASSERT_POINTER(ctx); + info = (os_allocator*)ctx; + + /* Ensure we don't allocate more than we're supposed to from the ctx */ + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; + + /* if the number of pages to be requested lead to exceeding the memory + * limit in info->num_pages_max, reduce the size that is to be requested. */ + while ( (info->num_pages_allocated + (1 << allocation_order) > info->num_pages_max) + && _mali_osk_mem_check_allocated(info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE) ) + { + if ( allocation_order > 0 ) { + --allocation_order; + } else { + /* return OOM */ + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + return MALI_MEM_ALLOC_NONE; + } + } + + /* try to allocate 2^(allocation_order) pages, if that fails, try + * allocation_order-1 to allocation_order 0 (inclusive) */ + while ( allocation_order >= 0 ) + { + size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; + virt = _mali_osk_mem_allocioregion( &cpu_phys_base, size ); + + if (NULL != virt) break; + + --allocation_order; + } + + if ( NULL == virt ) + { + MALI_DEBUG_PRINT(1, ("Failed to allocate consistent memory. Is CONSISTENT_DMA_SIZE set too low?\n")); + /* return OOM */ + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + return MALI_MEM_ALLOC_NONE; + } + + MALI_DEBUG_PRINT(5, ("os_allocator_allocate_page_table_block: Allocation of order %i succeeded\n", + allocation_order)); + + /* we now know the size of the allocation since we know for what + * allocation_order the allocation succeeded */ + size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; + + + block->release = os_allocator_page_table_block_release; + block->ctx = ctx; + block->handle = (void*)allocation_order; + block->size = size; + block->phys_base = cpu_phys_base - info->cpu_usage_adjust; + block->mapping = virt; + + info->num_pages_allocated += (1 << allocation_order); + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + + return MALI_MEM_ALLOC_FINISHED; +} + +static void os_allocator_page_table_block_release( mali_page_table_block *page_table_block ) +{ + os_allocator * info; + u32 allocation_order; + u32 pages_allocated; + + MALI_DEBUG_ASSERT_POINTER( page_table_block ); + + info = (os_allocator*)page_table_block->ctx; + + MALI_DEBUG_ASSERT_POINTER( info ); + + allocation_order = (u32)page_table_block->handle; + + pages_allocated = 1 << allocation_order; + + MALI_DEBUG_ASSERT( pages_allocated * _MALI_OSK_CPU_PAGE_SIZE == page_table_block->size ); + + if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) + { + MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n")); + return; + } + + MALI_DEBUG_ASSERT( pages_allocated <= info->num_pages_allocated); + info->num_pages_allocated -= pages_allocated; + + /* Adjust phys_base from mali physical address to CPU physical address */ + _mali_osk_mem_freeioregion( page_table_block->phys_base + info->cpu_usage_adjust, page_table_block->size, page_table_block->mapping ); + + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); +} diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.h b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.h new file mode 100644 index 0000000..59e6494 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_MEM_OS_H__ +#define __MALI_KERNEL_MEM_OS_H__ + +/** + * @brief Creates an object that manages allocating OS memory + * + * Creates an object that provides an interface to allocate OS memory and + * have it mapped into the Mali virtual memory space. + * + * The object exposes pointers to + * - allocate OS memory + * - allocate Mali page tables in OS memory + * - destroy the object + * + * Allocations from OS memory are of type mali_physical_memory_allocation + * which provides a function to release the allocation. + * + * @param max_allocation max. number of bytes that can be allocated from OS memory + * @param cpu_usage_adjust value to add to mali physical addresses to obtain CPU physical addresses + * @param name description of the allocator + * @return pointer to mali_physical_memory_allocator object. NULL on failure. + **/ +mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u32 cpu_usage_adjust, const char *name); + +#endif /* __MALI_KERNEL_MEM_OS_H__ */ + + diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c new file mode 100644 index 0000000..d770e3e --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#include "mali_kernel_memory_engine.h" +#include "mali_osk.h" +#include "mali_osk_list.h" + +typedef struct memory_engine +{ + mali_kernel_mem_address_manager * mali_address; + mali_kernel_mem_address_manager * process_address; +} memory_engine; + +mali_allocation_engine mali_allocation_engine_create(mali_kernel_mem_address_manager * mali_address_manager, mali_kernel_mem_address_manager * process_address_manager) +{ + memory_engine * engine; + + /* Mali Address Manager need not support unmap_physical */ + MALI_DEBUG_ASSERT_POINTER(mali_address_manager); + MALI_DEBUG_ASSERT_POINTER(mali_address_manager->allocate); + MALI_DEBUG_ASSERT_POINTER(mali_address_manager->release); + MALI_DEBUG_ASSERT_POINTER(mali_address_manager->map_physical); + + /* Process Address Manager must support unmap_physical for OS allocation + * error path handling */ + MALI_DEBUG_ASSERT_POINTER(process_address_manager); + MALI_DEBUG_ASSERT_POINTER(process_address_manager->allocate); + MALI_DEBUG_ASSERT_POINTER(process_address_manager->release); + MALI_DEBUG_ASSERT_POINTER(process_address_manager->map_physical); + MALI_DEBUG_ASSERT_POINTER(process_address_manager->unmap_physical); + + + engine = (memory_engine*)_mali_osk_malloc(sizeof(memory_engine)); + if (NULL == engine) return NULL; + + engine->mali_address = mali_address_manager; + engine->process_address = process_address_manager; + + return (mali_allocation_engine)engine; +} + +void mali_allocation_engine_destroy(mali_allocation_engine engine) +{ + MALI_DEBUG_ASSERT_POINTER(engine); + _mali_osk_free(engine); +} + +_mali_osk_errcode_t mali_allocation_engine_allocate_memory(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, mali_physical_memory_allocator * physical_allocators, _mali_osk_list_t *tracking_list ) +{ + memory_engine * engine = (memory_engine*)mem_engine; + + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(physical_allocators); + /* ASSERT that the list member has been initialized, even if it won't be + * used for tracking. We need it to be initialized to see if we need to + * delete it from a list in the release function. */ + MALI_DEBUG_ASSERT( NULL != descriptor->list.next && NULL != descriptor->list.prev ); + + if (_MALI_OSK_ERR_OK == engine->mali_address->allocate(descriptor)) + { + _mali_osk_errcode_t res = _MALI_OSK_ERR_OK; + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + res = engine->process_address->allocate(descriptor); + } + if ( _MALI_OSK_ERR_OK == res ) + { + /* address space setup OK, commit physical memory to the allocation */ + mali_physical_memory_allocator * active_allocator = physical_allocators; + struct mali_physical_memory_allocation * active_allocation_tracker = &descriptor->physical_allocation; + u32 offset = 0; + + while ( NULL != active_allocator ) + { + switch (active_allocator->allocate(active_allocator->ctx, mem_engine, descriptor, &offset, active_allocation_tracker)) + { + case MALI_MEM_ALLOC_FINISHED: + if ( NULL != tracking_list ) + { + /* Insert into the memory session list */ + /* ASSERT that it is not already part of a list */ + MALI_DEBUG_ASSERT( _mali_osk_list_empty( &descriptor->list ) ); + _mali_osk_list_add( &descriptor->list, tracking_list ); + } + + MALI_SUCCESS; /* all done */ + case MALI_MEM_ALLOC_NONE: + /* reuse current active_allocation_tracker */ + MALI_DEBUG_PRINT( 4, ("Memory Engine Allocate: No allocation on %s, resorting to %s\n", + ( active_allocator->name ) ? active_allocator->name : "UNNAMED", + ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") ); + active_allocator = active_allocator->next; + break; + case MALI_MEM_ALLOC_PARTIAL: + if (NULL != active_allocator->next) + { + /* need a new allocation tracker */ + active_allocation_tracker->next = _mali_osk_calloc(1, sizeof(mali_physical_memory_allocation)); + if (NULL != active_allocation_tracker->next) + { + active_allocation_tracker = active_allocation_tracker->next; + MALI_DEBUG_PRINT( 2, ("Memory Engine Allocate: Partial allocation on %s, resorting to %s\n", + ( active_allocator->name ) ? active_allocator->name : "UNNAMED", + ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") ); + active_allocator = active_allocator->next; + break; + } + } + /* FALL THROUGH */ + case MALI_MEM_ALLOC_INTERNAL_FAILURE: + active_allocator = NULL; /* end the while loop */ + break; + } + } + + MALI_PRINT(("Memory allocate failed, could not allocate size %d kB.\n", descriptor->size/1024)); + + /* allocation failure, start cleanup */ + /* loop over any potential partial allocations */ + active_allocation_tracker = &descriptor->physical_allocation; + while (NULL != active_allocation_tracker) + { + /* handle blank trackers which will show up during failure */ + if (NULL != active_allocation_tracker->release) + { + active_allocation_tracker->release(active_allocation_tracker->ctx, active_allocation_tracker->handle); + } + active_allocation_tracker = active_allocation_tracker->next; + } + + /* free the allocation tracker objects themselves, skipping the tracker stored inside the descriptor itself */ + for ( active_allocation_tracker = descriptor->physical_allocation.next; active_allocation_tracker != NULL; ) + { + void * buf = active_allocation_tracker; + active_allocation_tracker = active_allocation_tracker->next; + _mali_osk_free(buf); + } + + /* release the address spaces */ + + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + engine->process_address->release(descriptor); + } + } + engine->mali_address->release(descriptor); + } + + MALI_ERROR(_MALI_OSK_ERR_FAULT); +} + +void mali_allocation_engine_release_memory(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor) +{ + mali_allocation_engine_release_pt1_mali_pagetables_unmap(mem_engine, descriptor); + mali_allocation_engine_release_pt2_physical_memory_free(mem_engine, descriptor); +} + +void mali_allocation_engine_release_pt1_mali_pagetables_unmap(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor) +{ + memory_engine * engine = (memory_engine*)mem_engine; + + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + + /* Calling: mali_address_manager_release() */ + /* This function is allowed to be called several times, and it only does the release on the first call. */ + engine->mali_address->release(descriptor); +} + +void mali_allocation_engine_release_pt2_physical_memory_free(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor) +{ + memory_engine * engine = (memory_engine*)mem_engine; + mali_physical_memory_allocation * active_allocation_tracker; + + /* Remove this from a tracking list in session_data->memory_head */ + if ( ! _mali_osk_list_empty( &descriptor->list ) ) + { + _mali_osk_list_del( &descriptor->list ); + /* Clear the list for debug mode, catch use-after-free */ + MALI_DEBUG_CODE( descriptor->list.next = descriptor->list.prev = NULL; ) + } + + active_allocation_tracker = &descriptor->physical_allocation; + while (NULL != active_allocation_tracker) + { + MALI_DEBUG_ASSERT_POINTER(active_allocation_tracker->release); + active_allocation_tracker->release(active_allocation_tracker->ctx, active_allocation_tracker->handle); + active_allocation_tracker = active_allocation_tracker->next; + } + + /* free the allocation tracker objects themselves, skipping the tracker stored inside the descriptor itself */ + for ( active_allocation_tracker = descriptor->physical_allocation.next; active_allocation_tracker != NULL; ) + { + void * buf = active_allocation_tracker; + active_allocation_tracker = active_allocation_tracker->next; + _mali_osk_free(buf); + } + + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + engine->process_address->release(descriptor); + } +} + +_mali_osk_errcode_t mali_allocation_engine_map_physical(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, u32 offset, u32 phys, u32 cpu_usage_adjust, u32 size) +{ + _mali_osk_errcode_t err; + memory_engine * engine = (memory_engine*)mem_engine; + _mali_osk_mem_mapregion_flags_t unmap_flags = (_mali_osk_mem_mapregion_flags_t)0; + + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + + MALI_DEBUG_PRINT(7, ("Mapping phys 0x%08X length 0x%08X at offset 0x%08X\n", phys, size, offset)); + + MALI_DEBUG_ASSERT_POINTER(engine->mali_address); + MALI_DEBUG_ASSERT_POINTER(engine->mali_address->map_physical); + + /* Handle process address manager first, because we may need them to + * allocate the physical page */ + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + /* Handle OS-allocated specially, since an adjustment may be required */ + if ( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC == phys ) + { + MALI_DEBUG_ASSERT( _MALI_OSK_CPU_PAGE_SIZE == size ); + + /* Set flags to use on error path */ + unmap_flags |= _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR; + + err = engine->process_address->map_physical(descriptor, offset, &phys, size); + /* Adjust for cpu physical address to mali physical address */ + phys -= cpu_usage_adjust; + } + else + { + u32 cpu_phys; + /* Adjust mali physical address to cpu physical address */ + cpu_phys = phys + cpu_usage_adjust; + err = engine->process_address->map_physical(descriptor, offset, &cpu_phys, size); + } + + if ( _MALI_OSK_ERR_OK != err ) + { + MALI_DEBUG_PRINT(2, ("Map failed: %s %d\n", __FUNCTION__, __LINE__)); + MALI_ERROR( err ); + } + } + + MALI_DEBUG_PRINT(7, ("Mapping phys 0x%08X length 0x%08X at offset 0x%08X to CPUVA 0x%08X\n", phys, size, offset, (u32)(descriptor->mapping) + offset)); + + /* Mali address manager must use the physical address - no point in asking + * it to allocate another one for us */ + MALI_DEBUG_ASSERT( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC != phys ); + + err = engine->mali_address->map_physical(descriptor, offset, &phys, size); + + if ( _MALI_OSK_ERR_OK != err ) + { + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + MALI_DEBUG_PRINT( 2, ("Process address manager succeeded, but Mali Address manager failed for phys=0x%08X size=0x%08X, offset=0x%08X. Will unmap.\n", phys, size, offset)); + engine->process_address->unmap_physical(descriptor, offset, size, unmap_flags); + } + MALI_DEBUG_PRINT(2, ("Map mali failed: %s %d\n", __FUNCTION__, __LINE__)); + MALI_ERROR( err ); + } + + MALI_SUCCESS; +} + +void mali_allocation_engine_unmap_physical(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t unmap_flags ) +{ + memory_engine * engine = (memory_engine*)mem_engine; + + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + + MALI_DEBUG_PRINT(7, ("UnMapping length 0x%08X at offset 0x%08X\n", size, offset)); + + MALI_DEBUG_ASSERT_POINTER(engine->mali_address); + MALI_DEBUG_ASSERT_POINTER(engine->process_address); + + if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE ) + { + /* Mandetory for process_address manager to have an unmap function*/ + engine->process_address->unmap_physical( descriptor, offset, size, unmap_flags ); + } + + /* Optional for mali_address manager to have an unmap function*/ + if ( NULL != engine->mali_address->unmap_physical ) + { + engine->mali_address->unmap_physical( descriptor, offset, size, unmap_flags ); + } +} + + +_mali_osk_errcode_t mali_allocation_engine_allocate_page_tables(mali_allocation_engine engine, mali_page_table_block * descriptor, mali_physical_memory_allocator * physical_provider) +{ + mali_physical_memory_allocator * active_allocator = physical_provider; + + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(physical_provider); + + while ( NULL != active_allocator ) + { + switch (active_allocator->allocate_page_table_block(active_allocator->ctx, descriptor)) + { + case MALI_MEM_ALLOC_FINISHED: + MALI_SUCCESS; /* all done */ + case MALI_MEM_ALLOC_NONE: + /* try next */ + MALI_DEBUG_PRINT( 2, ("Memory Engine Allocate PageTables: No allocation on %s, resorting to %s\n", + ( active_allocator->name ) ? active_allocator->name : "UNNAMED", + ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") ); + active_allocator = active_allocator->next; + break; + case MALI_MEM_ALLOC_PARTIAL: + MALI_DEBUG_PRINT(1, ("Invalid return value from allocate_page_table_block call: MALI_MEM_ALLOC_PARTIAL\n")); + /* FALL THROUGH */ + case MALI_MEM_ALLOC_INTERNAL_FAILURE: + MALI_DEBUG_PRINT(1, ("Aborting due to allocation failure\n")); + active_allocator = NULL; /* end the while loop */ + break; + } + } + + MALI_ERROR(_MALI_OSK_ERR_FAULT); +} + + +void mali_allocation_engine_report_allocators( mali_physical_memory_allocator * physical_provider ) +{ + mali_physical_memory_allocator * active_allocator = physical_provider; + MALI_DEBUG_ASSERT_POINTER(physical_provider); + + MALI_DEBUG_PRINT( 1, ("Mali memory allocators will be used in this order of preference (lowest numbered first) :\n")); + while ( NULL != active_allocator ) + { + if ( NULL != active_allocator->name ) + { + MALI_DEBUG_PRINT( 1, ("\t%d: %s\n", active_allocator->alloc_order, active_allocator->name) ); + } + else + { + MALI_DEBUG_PRINT( 1, ("\t%d: (UNNAMED ALLOCATOR)\n", active_allocator->alloc_order) ); + } + active_allocator = active_allocator->next; + } + +} + +u32 mali_allocation_engine_memory_usage(mali_physical_memory_allocator *allocator) +{ + u32 sum = 0; + while(NULL != allocator) + { + /* Only count allocators that have set up a stat function. */ + if(allocator->stat) + sum += allocator->stat(allocator); + + allocator = allocator->next; + } + + return sum; +} diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h new file mode 100644 index 0000000..3b41cee --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_MEMORY_ENGINE_H__ +#define __MALI_KERNEL_MEMORY_ENGINE_H__ + +typedef void * mali_allocation_engine; + +typedef enum { MALI_MEM_ALLOC_FINISHED, MALI_MEM_ALLOC_PARTIAL, MALI_MEM_ALLOC_NONE, MALI_MEM_ALLOC_INTERNAL_FAILURE } mali_physical_memory_allocation_result; + +typedef struct mali_physical_memory_allocation +{ + void (*release)(void * ctx, void * handle); /**< Function to call on to release the physical memory */ + void * ctx; + void * handle; + struct mali_physical_memory_allocation * next; +} mali_physical_memory_allocation; + +struct mali_page_table_block; + +typedef struct mali_page_table_block +{ + void (*release)(struct mali_page_table_block *page_table_block); + void * ctx; + void * handle; + u32 size; /**< In bytes, should be a multiple of MALI_MMU_PAGE_SIZE to avoid internal fragementation */ + u32 phys_base; /**< Mali physical address */ + mali_io_address mapping; +} mali_page_table_block; + + +/** @addtogroup _mali_osk_low_level_memory + * @{ */ + +typedef enum +{ + MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE = 0x1, + MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE = 0x2, +} mali_memory_allocation_flag; + +/** + * Supplying this 'magic' physical address requests that the OS allocate the + * physical address at page commit time, rather than committing a specific page + */ +#define MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC ((u32)(-1)) + +typedef struct mali_memory_allocation +{ + /* Information about the allocation */ + void * mapping; /**< CPU virtual address where the memory is mapped at */ + u32 mali_address; /**< The Mali seen address of the memory allocation */ + u32 size; /**< Size of the allocation */ + u32 permission; /**< Permission settings */ + mali_memory_allocation_flag flags; + u32 cache_settings; /* type: mali_memory_cache_settings, found in Ump DD breaks if we include it...*/ + + _mali_osk_lock_t * lock; + + /* Manager specific information pointers */ + void * mali_addr_mapping_info; /**< Mali address allocation specific info */ + void * process_addr_mapping_info; /**< Mapping manager specific info */ + + mali_physical_memory_allocation physical_allocation; + + _mali_osk_list_t list; /**< List for linking together memory allocations into the session's memory head */ +} mali_memory_allocation; +/** @} */ /* end group _mali_osk_low_level_memory */ + + +typedef struct mali_physical_memory_allocator +{ + mali_physical_memory_allocation_result (*allocate)(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); + mali_physical_memory_allocation_result (*allocate_page_table_block)(void * ctx, mali_page_table_block * block); /* MALI_MEM_ALLOC_PARTIAL not allowed */ + void (*destroy)(struct mali_physical_memory_allocator * allocator); + u32 (*stat)(struct mali_physical_memory_allocator * allocator); + void * ctx; + const char * name; /**< Descriptive name for use in mali_allocation_engine_report_allocators, or NULL */ + u32 alloc_order; /**< Order in which the allocations should happen */ + struct mali_physical_memory_allocator * next; +} mali_physical_memory_allocator; + +typedef struct mali_kernel_mem_address_manager +{ + _mali_osk_errcode_t (*allocate)(mali_memory_allocation *); /**< Function to call to reserve an address */ + void (*release)(mali_memory_allocation *); /**< Function to call to free the address allocated */ + + /** + * Function called for each physical sub allocation. + * Called for each physical block allocated by the physical memory manager. + * @param[in] descriptor The memory descriptor in question + * @param[in] off Offset from the start of range + * @param[in,out] phys_addr A pointer to the physical address of the start of the + * physical block. When *phys_addr == MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC + * is used, this requests the function to allocate the physical page + * itself, and return it through the pointer provided. + * @param[in] size Length in bytes of the physical block + * @return _MALI_OSK_ERR_OK on success. + * A value of type _mali_osk_errcode_t other than _MALI_OSK_ERR_OK indicates failure. + * Specifically, _MALI_OSK_ERR_UNSUPPORTED indicates that the function + * does not support allocating physical pages itself. + */ + _mali_osk_errcode_t (*map_physical)(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size); + + /** + * Function called to remove a physical sub allocation. + * Called on error paths where one of the address managers fails. + * + * @note this is optional. For address managers where this is not + * implemented, the value of this member is NULL. The memory engine + * currently does not require the mali address manager to be able to + * unmap individual pages, but the process address manager must have this + * capability. + * + * @param[in] descriptor The memory descriptor in question + * @param[in] off Offset from the start of range + * @param[in] size Length in bytes of the physical block + * @param[in] flags flags to use on a per-page basis. For OS-allocated + * physical pages, this must include _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR. + * @return _MALI_OSK_ERR_OK on success. + * A value of type _mali_osk_errcode_t other than _MALI_OSK_ERR_OK indicates failure. + */ + void (*unmap_physical)(mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags); + +} mali_kernel_mem_address_manager; + +mali_allocation_engine mali_allocation_engine_create(mali_kernel_mem_address_manager * mali_address_manager, mali_kernel_mem_address_manager * process_address_manager); + +void mali_allocation_engine_destroy(mali_allocation_engine engine); + +int mali_allocation_engine_allocate_memory(mali_allocation_engine engine, mali_memory_allocation * descriptor, mali_physical_memory_allocator * physical_provider, _mali_osk_list_t *tracking_list ); +void mali_allocation_engine_release_memory(mali_allocation_engine engine, mali_memory_allocation * descriptor); + +void mali_allocation_engine_release_pt1_mali_pagetables_unmap(mali_allocation_engine engine, mali_memory_allocation * descriptor); +void mali_allocation_engine_release_pt2_physical_memory_free(mali_allocation_engine engine, mali_memory_allocation * descriptor); + +int mali_allocation_engine_map_physical(mali_allocation_engine engine, mali_memory_allocation * descriptor, u32 offset, u32 phys, u32 cpu_usage_adjust, u32 size); +void mali_allocation_engine_unmap_physical(mali_allocation_engine engine, mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t unmap_flags); + +int mali_allocation_engine_allocate_page_tables(mali_allocation_engine, mali_page_table_block * descriptor, mali_physical_memory_allocator * physical_provider); + +void mali_allocation_engine_report_allocators(mali_physical_memory_allocator * physical_provider); + +u32 mali_allocation_engine_memory_usage(mali_physical_memory_allocator *allocator); + +#endif /* __MALI_KERNEL_MEMORY_ENGINE_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c new file mode 100644 index 0000000..a374dbf --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_utilization.h" +#include "mali_osk.h" +#include "mali_platform.h" + +/* Define how often to calculate and report GPU utilization, in milliseconds */ +#define MALI_GPU_UTILIZATION_TIMEOUT 1000 + +static _mali_osk_lock_t *time_data_lock; + +static _mali_osk_atomic_t num_running_cores; + +static u64 period_start_time = 0; +static u64 work_start_time = 0; +static u64 accumulated_work_time = 0; + +static _mali_osk_timer_t *utilization_timer = NULL; +static mali_bool timer_running = MALI_FALSE; + + +static void calculate_gpu_utilization(void* arg) +{ + u64 time_now; + u64 time_period; + u32 leading_zeroes; + u32 shift_val; + u32 work_normalized; + u32 period_normalized; + u32 utilization; + + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + if (accumulated_work_time == 0 && work_start_time == 0) + { + /* Don't reschedule timer, this will be started if new work arrives */ + timer_running = MALI_FALSE; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + /* No work done for this period, report zero usage */ + mali_gpu_utilization_handler(0); + + return; + } + + time_now = _mali_osk_time_get_ns(); + time_period = time_now - period_start_time; + + /* If we are currently busy, update working period up to now */ + if (work_start_time != 0) + { + accumulated_work_time += (time_now - work_start_time); + work_start_time = time_now; + } + + /* + * We have two 64-bit values, a dividend and a divisor. + * To avoid dependencies to a 64-bit divider, we shift down the two values + * equally first. + * We shift the dividend up and possibly the divisor down, making the result X in 256. + */ + + /* Shift the 64-bit values down so they fit inside a 32-bit integer */ + leading_zeroes = _mali_osk_clz((u32)(time_period >> 32)); + shift_val = 32 - leading_zeroes; + work_normalized = (u32)(accumulated_work_time >> shift_val); + period_normalized = (u32)(time_period >> shift_val); + + /* + * Now, we should report the usage in parts of 256 + * this means we must shift up the dividend or down the divisor by 8 + * (we could do a combination, but we just use one for simplicity, + * but the end result should be good enough anyway) + */ + if (period_normalized > 0x00FFFFFF) + { + /* The divisor is so big that it is safe to shift it down */ + period_normalized >>= 8; + } + else + { + /* + * The divisor is so small that we can shift up the dividend, without loosing any data. + * (dividend is always smaller than the divisor) + */ + work_normalized <<= 8; + } + + utilization = work_normalized / period_normalized; + + accumulated_work_time = 0; + period_start_time = time_now; /* starting a new period */ + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT)); + + + mali_gpu_utilization_handler(utilization); +} + +_mali_osk_errcode_t mali_utilization_init(void) +{ + time_data_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | + _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_UTILIZATION); + + if (NULL == time_data_lock) + { + return _MALI_OSK_ERR_FAULT; + } + + _mali_osk_atomic_init(&num_running_cores, 0); + + utilization_timer = _mali_osk_timer_init(); + if (NULL == utilization_timer) + { + _mali_osk_lock_term(time_data_lock); + return _MALI_OSK_ERR_FAULT; + } + _mali_osk_timer_setcallback(utilization_timer, calculate_gpu_utilization, NULL); + + return _MALI_OSK_ERR_OK; +} + +void mali_utilization_suspend(void) +{ + if (NULL != utilization_timer) + { + _mali_osk_timer_del(utilization_timer); + timer_running = MALI_FALSE; + } +} + +void mali_utilization_term(void) +{ + if (NULL != utilization_timer) + { + _mali_osk_timer_del(utilization_timer); + timer_running = MALI_FALSE; + _mali_osk_timer_term(utilization_timer); + utilization_timer = NULL; + } + + _mali_osk_atomic_term(&num_running_cores); + + _mali_osk_lock_term(time_data_lock); +} + +void mali_utilization_core_start(u64 time_now) +{ + if (_mali_osk_atomic_inc_return(&num_running_cores) == 1) + { + /* + * We went from zero cores working, to one core working, + * we now consider the entire GPU for being busy + */ + + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + if (time_now < period_start_time) + { + /* + * This might happen if the calculate_gpu_utilization() was able + * to run between the sampling of time_now and us grabbing the lock above + */ + time_now = period_start_time; + } + + work_start_time = time_now; + if (timer_running != MALI_TRUE) + { + timer_running = MALI_TRUE; + period_start_time = work_start_time; /* starting a new period */ + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT)); + } + else + { + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } + } +} + +void mali_utilization_core_end(u64 time_now) +{ + if (_mali_osk_atomic_dec_return(&num_running_cores) == 0) + { + /* + * No more cores are working, so accumulate the time we was busy. + */ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + if (time_now < work_start_time) + { + /* + * This might happen if the calculate_gpu_utilization() was able + * to run between the sampling of time_now and us grabbing the lock above + */ + time_now = work_start_time; + } + + accumulated_work_time += (time_now - work_start_time); + work_start_time = 0; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } +} diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h new file mode 100644 index 0000000..1f60517 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_UTILIZATION_H__ +#define __MALI_KERNEL_UTILIZATION_H__ + +#include "mali_osk.h" + +/** + * Initialize/start the Mali GPU utilization metrics reporting. + * + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t mali_utilization_init(void); + +/** + * Terminate the Mali GPU utilization metrics reporting + */ +void mali_utilization_term(void); + +/** + * Should be called when a job is about to execute a job + */ +void mali_utilization_core_start(u64 time_now); + +/** + * Should be called to stop the utilization timer during system suspend + */ +void mali_utilization_suspend(void); + +/** + * Should be called when a job has completed executing a job + */ +void mali_utilization_core_end(u64 time_now); + + +#endif /* __MALI_KERNEL_UTILIZATION_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c b/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c new file mode 100644 index 0000000..63c9f5b --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_ukk.h" + +#if MALI_TIMELINE_PROFILING_ENABLED +#include "mali_osk_profiling.h" +#endif + +_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args) +{ + _mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event; + MALI_IGNORE(event); /* event is not used for release code, and that is OK */ + +#if MALI_TIMELINE_PROFILING_ENABLED + /* + * Manually generate user space events in kernel space. + * This saves user space from calling kernel space twice in this case. + * We just need to remember to add pid and tid manually. + */ + if ( event==_MALI_UK_VSYNC_EVENT_BEGIN_WAIT) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC, + _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); + } + + if (event==_MALI_UK_VSYNC_EVENT_END_WAIT) + { + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC, + _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); + } +#endif + + MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event)); + MALI_SUCCESS; +} + diff --git a/drivers/media/video/samsung/mali/common/mali_l2_cache.c b/drivers/media/video/samsung/mali/common/mali_l2_cache.c new file mode 100644 index 0000000..b7267f1 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_l2_cache.c @@ -0,0 +1,414 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "mali_kernel_common.h" +#include "mali_osk.h" + +#include "mali_l2_cache.h" +#include "mali_hw_core.h" +#include "mali_pm.h" + +/** + * Size of the Mali L2 cache registers in bytes + */ +#define MALI400_L2_CACHE_REGISTERS_SIZE 0x30 + +#define MALI_MAX_NUMBER_OF_L2_CACHE_CORES 3 + +/** + * Mali L2 cache register numbers + * Used in the register read/write routines. + * See the hardware documentation for more information about each register + */ +typedef enum mali_l2_cache_register { + MALI400_L2_CACHE_REGISTER_STATUS = 0x0008, + /*unused = 0x000C */ + MALI400_L2_CACHE_REGISTER_COMMAND = 0x0010, /**< Misc cache commands, e.g. clear */ + MALI400_L2_CACHE_REGISTER_CLEAR_PAGE = 0x0014, + MALI400_L2_CACHE_REGISTER_MAX_READS = 0x0018, /**< Limit of outstanding read requests */ + MALI400_L2_CACHE_REGISTER_ENABLE = 0x001C, /**< Enable misc cache features */ + MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0 = 0x0020, + MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0 = 0x0024, + MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1 = 0x0028, + MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1 = 0x002C, +} mali_l2_cache_register; + +/** + * Mali L2 cache commands + * These are the commands that can be sent to the Mali L2 cache unit + */ +typedef enum mali_l2_cache_command +{ + MALI400_L2_CACHE_COMMAND_CLEAR_ALL = 0x01, /**< Clear the entire cache */ + /* Read HW TRM carefully before adding/using other commands than the clear above */ +} mali_l2_cache_command; + +/** + * Mali L2 cache commands + * These are the commands that can be sent to the Mali L2 cache unit + */ +typedef enum mali_l2_cache_enable +{ + MALI400_L2_CACHE_ENABLE_DEFAULT = 0x0, /**< Default state of enable register */ + MALI400_L2_CACHE_ENABLE_ACCESS = 0x01, /**< Permit cacheable accesses */ + MALI400_L2_CACHE_ENABLE_READ_ALLOCATE = 0x02, /**< Permit cache read allocate */ +} mali_l2_cache_enable; + +/** + * Mali L2 cache status bits + */ +typedef enum mali_l2_cache_status +{ + MALI400_L2_CACHE_STATUS_COMMAND_BUSY = 0x01, /**< Command handler of L2 cache is busy */ + MALI400_L2_CACHE_STATUS_DATA_BUSY = 0x02, /**< L2 cache is busy handling data requests */ +} mali_l2_cache_status; + +/** + * Definition of the L2 cache core struct + * Used to track a L2 cache unit in the system. + * Contains information about the mapping of the registers + */ +struct mali_l2_cache_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + u32 core_id; /**< Unique core ID */ + _mali_osk_lock_t *command_lock; /**< Serialize all L2 cache commands */ + _mali_osk_lock_t *counter_lock; /**< Synchronize L2 cache counter access */ + u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ + u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ +}; + +#define MALI400_L2_MAX_READS_DEFAULT 0x1C + +static struct mali_l2_cache_core *mali_global_l2_cache_cores[MALI_MAX_NUMBER_OF_L2_CACHE_CORES]; +static u32 mali_global_num_l2_cache_cores = 0; + +int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT; + +/* Local helper functions */ +static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val); + + +struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource) +{ + struct mali_l2_cache_core *cache = NULL; + + MALI_DEBUG_PRINT(2, ("Mali L2 cache: Creating Mali L2 cache: %s\n", resource->description)); + + if (mali_global_num_l2_cache_cores >= MALI_MAX_NUMBER_OF_L2_CACHE_CORES) + { + MALI_PRINT_ERROR(("Mali L2 cache: Too many L2 cache core objects created\n")); + return NULL; + } + + cache = _mali_osk_malloc(sizeof(struct mali_l2_cache_core)); + if (NULL != cache) + { + cache->core_id = mali_global_num_l2_cache_cores; + cache->counter_src0 = MALI_HW_CORE_NO_COUNTER; + cache->counter_src1 = MALI_HW_CORE_NO_COUNTER; + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&cache->hw_core, resource, MALI400_L2_CACHE_REGISTERS_SIZE)) + { + cache->command_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, + 0, _MALI_OSK_LOCK_ORDER_L2_COMMAND); + if (NULL != cache->command_lock) + { + cache->counter_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, + 0, _MALI_OSK_LOCK_ORDER_L2_COUNTER); + if (NULL != cache->counter_lock) + { + if (_MALI_OSK_ERR_OK == mali_l2_cache_reset(cache)) + { + mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = cache; + mali_global_num_l2_cache_cores++; + + return cache; + } + else + { + MALI_PRINT_ERROR(("Mali L2 cache: Failed to reset L2 cache core %s\n", cache->hw_core.description)); + } + + _mali_osk_lock_term(cache->counter_lock); + } + else + { + MALI_PRINT_ERROR(("Mali L2 cache: Failed to create counter lock for L2 cache core %s\n", cache->hw_core.description)); + } + + _mali_osk_lock_term(cache->command_lock); + } + else + { + MALI_PRINT_ERROR(("Mali L2 cache: Failed to create command lock for L2 cache core %s\n", cache->hw_core.description)); + } + + mali_hw_core_delete(&cache->hw_core); + } + + _mali_osk_free(cache); + } + else + { + MALI_PRINT_ERROR(("Mali L2 cache: Failed to allocate memory for L2 cache core\n")); + } + + return NULL; +} + +void mali_l2_cache_delete(struct mali_l2_cache_core *cache) +{ + u32 i; + + /* reset to defaults */ + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)MALI400_L2_MAX_READS_DEFAULT); + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_DEFAULT); + + _mali_osk_lock_term(cache->counter_lock); + _mali_osk_lock_term(cache->command_lock); + mali_hw_core_delete(&cache->hw_core); + + for (i = 0; i < mali_global_num_l2_cache_cores; i++) + { + if (mali_global_l2_cache_cores[i] == cache) + { + mali_global_l2_cache_cores[i] = NULL; + mali_global_num_l2_cache_cores--; + } + } + + _mali_osk_free(cache); +} + +u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache) +{ + return cache->core_id; +} + +mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter) +{ + u32 value = 0; /* disabled src */ + mali_bool core_is_on; + + MALI_DEBUG_ASSERT_POINTER(cache); + + core_is_on = mali_l2_cache_lock_power_state(cache); + + _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + cache->counter_src0 = counter; + + if (MALI_HW_CORE_NO_COUNTER != counter) + { + value = counter; + } + + if (MALI_TRUE == core_is_on) + { + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, value); + } + + _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + mali_l2_cache_unlock_power_state(cache); + + return MALI_TRUE; +} + +mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter) +{ + u32 value = 0; /* disabled src */ + mali_bool core_is_on; + + MALI_DEBUG_ASSERT_POINTER(cache); + + core_is_on = mali_l2_cache_lock_power_state(cache); + + _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + cache->counter_src1 = counter; + + if (MALI_HW_CORE_NO_COUNTER != counter) + { + value = counter; + } + + if (MALI_TRUE == core_is_on) + { + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, value); + } + + _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + mali_l2_cache_unlock_power_state(cache); + + return MALI_TRUE; +} + +u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache) +{ + return cache->counter_src0; +} + +u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache) +{ + return cache->counter_src1; +} + +void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1) +{ + MALI_DEBUG_ASSERT(NULL != src0); + MALI_DEBUG_ASSERT(NULL != value0); + MALI_DEBUG_ASSERT(NULL != src1); + MALI_DEBUG_ASSERT(NULL != value1); + + /* Caller must hold the PM lock and know that we are powered on */ + + _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + *src0 = cache->counter_src0; + *src1 = cache->counter_src1; + + if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) + { + *value0 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0); + } + + if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) + { + *value1 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1); + } + + _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); +} + +struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index) +{ + if (MALI_MAX_NUMBER_OF_L2_CACHE_CORES > index) + { + return mali_global_l2_cache_cores[index]; + } + + return NULL; +} + +u32 mali_l2_cache_core_get_glob_num_l2_cores(void) +{ + return mali_global_num_l2_cache_cores; +} + +u32 mali_l2_cache_core_get_max_num_l2_cores(void) +{ + return MALI_MAX_NUMBER_OF_L2_CACHE_CORES; +} + +_mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache) +{ + /* Invalidate cache (just to keep it in a known state at startup) */ + mali_l2_cache_invalidate_all(cache); + + /* Enable cache */ + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_ACCESS | (u32)MALI400_L2_CACHE_ENABLE_READ_ALLOCATE); + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)mali_l2_max_reads); + + /* Restart any performance counters (if enabled) */ + _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) + { + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, cache->counter_src0); + } + + if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER) + { + mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, cache->counter_src1); + } + + _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache) +{ + return mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); +} + +_mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages) +{ + u32 i; + _mali_osk_errcode_t ret1, ret = _MALI_OSK_ERR_OK; + + for (i = 0; i < num_pages; i++) + { + ret1 = mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, pages[i]); + if (_MALI_OSK_ERR_OK != ret1) + { + ret = ret1; + } + } + + return ret; +} + +mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache) +{ + /* + * Take PM lock and check power state. + * Returns MALI_TRUE if module is powered on. + * Power state will not change until mali_l2_cache_unlock_power_state() is called. + */ + mali_pm_lock(); + return mali_pm_is_powered_on(); +} + +void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache) +{ + /* Release PM lock */ + mali_pm_unlock(); +} + +/* -------- local helper functions below -------- */ + + +static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val) +{ + int i = 0; + const int loop_count = 100000; + + /* + * Grab lock in order to send commands to the L2 cache in a serialized fashion. + * The L2 cache will ignore commands if it is busy. + */ + _mali_osk_lock_wait(cache->command_lock, _MALI_OSK_LOCKMODE_RW); + + /* First, wait for L2 cache command handler to go idle */ + + for (i = 0; i < loop_count; i++) + { + if (!(mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_STATUS) & (u32)MALI400_L2_CACHE_STATUS_COMMAND_BUSY)) + { + break; + } + } + + if (i == loop_count) + { + _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW); + MALI_DEBUG_PRINT(1, ( "Mali L2 cache: aborting wait for command interface to go idle\n")); + MALI_ERROR( _MALI_OSK_ERR_FAULT ); + } + + /* then issue the command */ + mali_hw_core_register_write(&cache->hw_core, reg, val); + + _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW); + + MALI_SUCCESS; +} diff --git a/drivers/media/video/samsung/mali/common/mali_l2_cache.h b/drivers/media/video/samsung/mali/common/mali_l2_cache.h new file mode 100644 index 0000000..5a8e4da --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_l2_cache.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_L2_CACHE_H__ +#define __MALI_KERNEL_L2_CACHE_H__ + +#include "mali_osk.h" + +struct mali_l2_cache_core; + +_mali_osk_errcode_t mali_l2_cache_initialize(void); +void mali_l2_cache_terminate(void); + +struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t * resource); +void mali_l2_cache_delete(struct mali_l2_cache_core *cache); + +u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache); + +mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter); +mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter); +u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache); +u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache); +void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1); +struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index); +u32 mali_l2_cache_core_get_glob_num_l2_cores(void); +u32 mali_l2_cache_core_get_max_num_l2_cores(void); + +_mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache); + +_mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache); +_mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages); + +mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache); +void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache); + +#endif /* __MALI_KERNEL_L2_CACHE_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_mem_validation.c b/drivers/media/video/samsung/mali/common/mali_mem_validation.c new file mode 100644 index 0000000..ea9c428 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_mem_validation.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_mem_validation.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" + +#define MALI_INVALID_MEM_ADDR 0xFFFFFFFF + +typedef struct +{ + u32 phys_base; /**< Mali physical base of the memory, page aligned */ + u32 size; /**< size in bytes of the memory, multiple of page size */ +} _mali_mem_validation_t; + +static _mali_mem_validation_t mali_mem_validator = { MALI_INVALID_MEM_ADDR, MALI_INVALID_MEM_ADDR }; + +_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t *resource) +{ + /* Check that no other MEM_VALIDATION resources exist */ + if (MALI_INVALID_MEM_ADDR != mali_mem_validator.phys_base) + { + MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; another range is already specified\n", resource->description)); + return _MALI_OSK_ERR_FAULT; + } + + /* Check restrictions on page alignment */ + if ((0 != (resource->base & (~_MALI_OSK_CPU_PAGE_MASK))) || + (0 != (resource->size & (~_MALI_OSK_CPU_PAGE_MASK)))) + { + MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; incorrect alignment\n", resource->description)); + return _MALI_OSK_ERR_FAULT; + } + + mali_mem_validator.phys_base = resource->base; + mali_mem_validator.size = resource->size; + MALI_DEBUG_PRINT(2, ("Memory Validator '%s' installed for Mali physical address base=0x%08X, size=0x%08X\n", + resource->description, mali_mem_validator.phys_base, mali_mem_validator.size)); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size) +{ + if (phys_addr < (phys_addr + size)) /* Don't allow overflow (or zero size) */ + { + if ((0 == ( phys_addr & (~_MALI_OSK_CPU_PAGE_MASK))) && + (0 == ( size & (~_MALI_OSK_CPU_PAGE_MASK)))) + { + if ((phys_addr >= mali_mem_validator.phys_base) && + ((phys_addr + (size - 1)) >= mali_mem_validator.phys_base) && + (phys_addr <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) && + ((phys_addr + (size - 1)) <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) ) + { + MALI_DEBUG_PRINT(3, ("Accepted range 0x%08X + size 0x%08X (= 0x%08X)\n", phys_addr, size, (phys_addr + size - 1))); + return _MALI_OSK_ERR_OK; + } + } + } + + MALI_PRINT_ERROR(("MALI PHYSICAL RANGE VALIDATION ERROR: The range supplied was: phys_base=0x%08X, size=0x%08X\n", phys_addr, size)); + + return _MALI_OSK_ERR_FAULT; +} diff --git a/drivers/media/video/samsung/mali/common/mali_mem_validation.h b/drivers/media/video/samsung/mali/common/mali_mem_validation.h new file mode 100644 index 0000000..2043b44 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_mem_validation.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_MEM_VALIDATION_H__ +#define __MALI_MEM_VALIDATION_H__ + +#include "mali_osk.h" + +_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t * resource); +_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size); + +#endif /* __MALI_MEM_VALIDATION_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_memory.c b/drivers/media/video/samsung/mali/common/mali_memory.c new file mode 100644 index 0000000..75506ed --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_memory.c @@ -0,0 +1,1319 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_kernel_descriptor_mapping.h" +#include "mali_mem_validation.h" +#include "mali_memory.h" +#include "mali_mmu_page_directory.h" +#include "mali_kernel_memory_engine.h" +#include "mali_block_allocator.h" +#include "mali_kernel_mem_os.h" +#include "mali_session.h" +#include "mali_l2_cache.h" +#include "mali_cluster.h" +#include "mali_group.h" +#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +#include "ump_kernel_interface.h" +#endif + +/* kernel side OS functions and user-kernel interface */ +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_ukk.h" +#include "mali_osk_list.h" +#include "mali_osk_bitops.h" + +/** + * Per-session memory descriptor mapping table sizes + */ +#define MALI_MEM_DESCRIPTORS_INIT 64 +#define MALI_MEM_DESCRIPTORS_MAX 65536 + +typedef struct dedicated_memory_info +{ + u32 base; + u32 size; + struct dedicated_memory_info * next; +} dedicated_memory_info; + +/* types used for external_memory and ump_memory physical memory allocators, which are using the mali_allocation_engine */ +#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +typedef struct ump_mem_allocation +{ + mali_allocation_engine * engine; + mali_memory_allocation * descriptor; + u32 initial_offset; + u32 size_allocated; + ump_dd_handle ump_mem; +} ump_mem_allocation ; +#endif + +typedef struct external_mem_allocation +{ + mali_allocation_engine * engine; + mali_memory_allocation * descriptor; + u32 initial_offset; + u32 size; +} external_mem_allocation; + +/** + * @brief Internal function for unmapping memory + * + * Worker function for unmapping memory from a user-process. We assume that the + * session/descriptor's lock was obtained before entry. For example, the + * wrapper _mali_ukk_mem_munmap() will lock the descriptor, then call this + * function to do the actual unmapping. mali_memory_core_session_end() could + * also call this directly (depending on compilation options), having locked + * the descriptor. + * + * This function will fail if it is unable to put the MMU in stall mode (which + * might be the case if a page fault is also being processed). + * + * @param args see _mali_uk_mem_munmap_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ); + +#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +static void ump_memory_release(void * ctx, void * handle); +static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); +#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0*/ + + +static void external_memory_release(void * ctx, void * handle); +static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); + + +/* nop functions */ + +/* mali address manager needs to allocate page tables on allocate, write to page table(s) on map, write to page table(s) and release page tables on release */ +static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor); /* validates the range, allocates memory for the page tables if needed */ +static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size); +static void mali_address_manager_release(mali_memory_allocation * descriptor); + +/* MMU variables */ + +typedef struct mali_mmu_page_table_allocation +{ + _mali_osk_list_t list; + u32 * usage_map; + u32 usage_count; + u32 num_pages; + mali_page_table_block pages; +} mali_mmu_page_table_allocation; + +typedef struct mali_mmu_page_table_allocations +{ + _mali_osk_lock_t *lock; + _mali_osk_list_t partial; + _mali_osk_list_t full; + /* we never hold on to a empty allocation */ +} mali_mmu_page_table_allocations; + +static mali_kernel_mem_address_manager mali_address_manager = +{ + mali_address_manager_allocate, /* allocate */ + mali_address_manager_release, /* release */ + mali_address_manager_map, /* map_physical */ + NULL /* unmap_physical not present*/ +}; + +/* the mmu page table cache */ +static struct mali_mmu_page_table_allocations page_table_cache; + + +static mali_kernel_mem_address_manager process_address_manager = +{ + _mali_osk_mem_mapregion_init, /* allocate */ + _mali_osk_mem_mapregion_term, /* release */ + _mali_osk_mem_mapregion_map, /* map_physical */ + _mali_osk_mem_mapregion_unmap /* unmap_physical */ +}; + +static _mali_osk_errcode_t mali_mmu_page_table_cache_create(void); +static void mali_mmu_page_table_cache_destroy(void); + +static mali_allocation_engine memory_engine = NULL; +static mali_physical_memory_allocator * physical_memory_allocators = NULL; + +static dedicated_memory_info * mem_region_registrations = NULL; + +mali_allocation_engine mali_mem_get_memory_engine(void) +{ + return memory_engine; +} + +/* called during module init */ +_mali_osk_errcode_t mali_memory_initialize(void) +{ + _mali_osk_errcode_t err; + + MALI_DEBUG_PRINT(2, ("Memory system initializing\n")); + + err = mali_mmu_page_table_cache_create(); + if(_MALI_OSK_ERR_OK != err) + { + MALI_ERROR(err); + } + + memory_engine = mali_allocation_engine_create(&mali_address_manager, &process_address_manager); + MALI_CHECK_NON_NULL( memory_engine, _MALI_OSK_ERR_FAULT); + + MALI_SUCCESS; +} + +/* called if/when our module is unloaded */ +void mali_memory_terminate(void) +{ + MALI_DEBUG_PRINT(2, ("Memory system terminating\n")); + + mali_mmu_page_table_cache_destroy(); + + while ( NULL != mem_region_registrations) + { + dedicated_memory_info * m; + m = mem_region_registrations; + mem_region_registrations = m->next; + _mali_osk_mem_unreqregion(m->base, m->size); + _mali_osk_free(m); + } + + while ( NULL != physical_memory_allocators) + { + mali_physical_memory_allocator * m; + m = physical_memory_allocators; + physical_memory_allocators = m->next; + m->destroy(m); + } + + if (NULL != memory_engine) + { + mali_allocation_engine_destroy(memory_engine); + memory_engine = NULL; + } +} + +_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data * session_data) +{ + MALI_DEBUG_PRINT(5, ("Memory session begin\n")); + + /* create descriptor mapping table */ + session_data->descriptor_mapping = mali_descriptor_mapping_create(MALI_MEM_DESCRIPTORS_INIT, MALI_MEM_DESCRIPTORS_MAX); + + if (NULL == session_data->descriptor_mapping) + { + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + session_data->memory_lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK + | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_SESSION); + if (NULL == session_data->memory_lock) + { + mali_descriptor_mapping_destroy(session_data->descriptor_mapping); + _mali_osk_free(session_data); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + /* Init the session's memory allocation list */ + _MALI_OSK_INIT_LIST_HEAD( &session_data->memory_head ); + + MALI_DEBUG_PRINT(5, ("MMU session begin: success\n")); + MALI_SUCCESS; +} + +static void descriptor_table_cleanup_callback(int descriptor_id, void* map_target) +{ + mali_memory_allocation * descriptor; + + descriptor = (mali_memory_allocation*)map_target; + + MALI_DEBUG_PRINT(3, ("Cleanup of descriptor %d mapping to 0x%x in descriptor table\n", descriptor_id, map_target)); + MALI_DEBUG_ASSERT(descriptor); + + mali_allocation_engine_release_memory(memory_engine, descriptor); + _mali_osk_free(descriptor); +} + +void mali_memory_session_end(struct mali_session_data *session_data) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_BUSY; + + MALI_DEBUG_PRINT(3, ("MMU session end\n")); + + if (NULL == session_data) + { + MALI_DEBUG_PRINT(1, ("No session data found during session end\n")); + return; + } + + while (err == _MALI_OSK_ERR_BUSY) + { + /* Lock the session so we can modify the memory list */ + _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + err = _MALI_OSK_ERR_OK; + + /* Free all memory engine allocations */ + if (0 == _mali_osk_list_empty(&session_data->memory_head)) + { + mali_memory_allocation *descriptor; + mali_memory_allocation *temp; + _mali_uk_mem_munmap_s unmap_args; + + MALI_DEBUG_PRINT(1, ("Memory found on session usage list during session termination\n")); + + unmap_args.ctx = session_data; + + /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */ + _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->memory_head, mali_memory_allocation, list) + { + MALI_DEBUG_PRINT(4, ("Freeing block with mali address 0x%x size %d mapped in user space at 0x%x\n", + descriptor->mali_address, descriptor->size, descriptor->size, descriptor->mapping) + ); + /* ASSERT that the descriptor's lock references the correct thing */ + MALI_DEBUG_ASSERT( descriptor->lock == session_data->memory_lock ); + /* Therefore, we have already locked the descriptor */ + + unmap_args.size = descriptor->size; + unmap_args.mapping = descriptor->mapping; + unmap_args.cookie = (u32)descriptor; + + /* + * This removes the descriptor from the list, and frees the descriptor + * + * Does not handle the _MALI_OSK_SPECIFIC_INDIRECT_MMAP case, since + * the only OS we are aware of that requires indirect MMAP also has + * implicit mmap cleanup. + */ + err = _mali_ukk_mem_munmap_internal( &unmap_args ); + + if (err == _MALI_OSK_ERR_BUSY) + { + _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + /* + * Reason for this; + * We where unable to stall the MMU, probably because we are in page fault handling. + * Sleep for a while with the session lock released, then try again. + * Abnormal termination of programs with running Mali jobs is a normal reason for this. + */ + _mali_osk_time_ubusydelay(10); + break; /* Will jump back into: "while (err == _MALI_OSK_ERR_BUSY)" */ + } + } + } + } + /* Assert that we really did free everything */ + MALI_DEBUG_ASSERT( _mali_osk_list_empty(&session_data->memory_head) ); + + if (NULL != session_data->descriptor_mapping) + { + mali_descriptor_mapping_call_for_each(session_data->descriptor_mapping, descriptor_table_cleanup_callback); + mali_descriptor_mapping_destroy(session_data->descriptor_mapping); + session_data->descriptor_mapping = NULL; + } + + _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + /** + * @note Could the VMA close handler mean that we use the session data after it was freed? + * In which case, would need to refcount the session data, and free on VMA close + */ + + /* Free the lock */ + _mali_osk_lock_term( session_data->memory_lock ); + + return; +} + +_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource) +{ + mali_physical_memory_allocator * allocator; + mali_physical_memory_allocator ** next_allocator_list; + + u32 alloc_order = resource->alloc_order; + + allocator = mali_os_allocator_create(resource->size, resource->cpu_usage_adjust, resource->description); + if (NULL == allocator) + { + MALI_DEBUG_PRINT(1, ("Failed to create OS memory allocator\n")); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + allocator->alloc_order = alloc_order; + + /* link in the allocator: insertion into ordered list + * resources of the same alloc_order will be Last-in-first */ + next_allocator_list = &physical_memory_allocators; + + while (NULL != *next_allocator_list && + (*next_allocator_list)->alloc_order < alloc_order ) + { + next_allocator_list = &((*next_allocator_list)->next); + } + + allocator->next = (*next_allocator_list); + (*next_allocator_list) = allocator; + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource) +{ + mali_physical_memory_allocator * allocator; + mali_physical_memory_allocator ** next_allocator_list; + dedicated_memory_info * cleanup_data; + + u32 alloc_order = resource->alloc_order; + + /* do the low level linux operation first */ + + /* Request ownership of the memory */ + if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(resource->base, resource->size, resource->description)) + { + MALI_DEBUG_PRINT(1, ("Failed to request memory region %s (0x%08X - 0x%08X)\n", resource->description, resource->base, resource->base + resource->size - 1)); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + /* create generic block allocator object to handle it */ + allocator = mali_block_allocator_create(resource->base, resource->cpu_usage_adjust, resource->size, resource->description ); + + if (NULL == allocator) + { + MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n")); + _mali_osk_mem_unreqregion(resource->base, resource->size); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + /* save low level cleanup info */ + allocator->alloc_order = alloc_order; + + cleanup_data = _mali_osk_malloc(sizeof(dedicated_memory_info)); + + if (NULL == cleanup_data) + { + _mali_osk_mem_unreqregion(resource->base, resource->size); + allocator->destroy(allocator); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + cleanup_data->base = resource->base; + cleanup_data->size = resource->size; + + cleanup_data->next = mem_region_registrations; + mem_region_registrations = cleanup_data; + + /* link in the allocator: insertion into ordered list + * resources of the same alloc_order will be Last-in-first */ + next_allocator_list = &physical_memory_allocators; + + while ( NULL != *next_allocator_list && + (*next_allocator_list)->alloc_order < alloc_order ) + { + next_allocator_list = &((*next_allocator_list)->next); + } + + allocator->next = (*next_allocator_list); + (*next_allocator_list) = allocator; + + MALI_SUCCESS; +} + +#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + ump_dd_handle ump_mem; + u32 nr_blocks; + u32 i; + ump_dd_physical_block * ump_blocks; + ump_mem_allocation *ret_allocation; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + ret_allocation = _mali_osk_malloc( sizeof( ump_mem_allocation ) ); + if ( NULL==ret_allocation ) return MALI_MEM_ALLOC_INTERNAL_FAILURE; + + ump_mem = (ump_dd_handle)ctx; + + MALI_DEBUG_PRINT(4, ("In ump_memory_commit\n")); + + nr_blocks = ump_dd_phys_block_count_get(ump_mem); + + MALI_DEBUG_PRINT(4, ("Have %d blocks\n", nr_blocks)); + + if (nr_blocks == 0) + { + MALI_DEBUG_PRINT(1, ("No block count\n")); + _mali_osk_free( ret_allocation ); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + + ump_blocks = _mali_osk_malloc(sizeof(*ump_blocks)*nr_blocks ); + if ( NULL==ump_blocks ) + { + _mali_osk_free( ret_allocation ); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + + if (UMP_DD_INVALID == ump_dd_phys_blocks_get(ump_mem, ump_blocks, nr_blocks)) + { + _mali_osk_free(ump_blocks); + _mali_osk_free( ret_allocation ); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + + /* Store away the initial offset for unmapping purposes */ + ret_allocation->initial_offset = *offset; + + for(i=0; iinitial_offset; + MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n")); + + /* unmap all previous blocks (if any) */ + mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 ); + + _mali_osk_free(ump_blocks); + _mali_osk_free(ret_allocation); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + *offset += ump_blocks[i].size; + } + + if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) + { + /* Map in an extra virtual guard page at the end of the VMA */ + MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n")); + if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[0].addr , 0, _MALI_OSK_MALI_PAGE_SIZE )) + { + u32 size_allocated = *offset - ret_allocation->initial_offset; + MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n")); + + /* unmap all previous blocks (if any) */ + mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 ); + + _mali_osk_free(ump_blocks); + _mali_osk_free(ret_allocation); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + *offset += _MALI_OSK_MALI_PAGE_SIZE; + } + + _mali_osk_free( ump_blocks ); + + ret_allocation->engine = engine; + ret_allocation->descriptor = descriptor; + ret_allocation->ump_mem = ump_mem; + ret_allocation->size_allocated = *offset - ret_allocation->initial_offset; + + alloc_info->ctx = NULL; + alloc_info->handle = ret_allocation; + alloc_info->next = NULL; + alloc_info->release = ump_memory_release; + + return MALI_MEM_ALLOC_FINISHED; +} + +static void ump_memory_release(void * ctx, void * handle) +{ + ump_dd_handle ump_mem; + ump_mem_allocation *allocation; + + allocation = (ump_mem_allocation *)handle; + + MALI_DEBUG_ASSERT_POINTER( allocation ); + + ump_mem = allocation->ump_mem; + + MALI_DEBUG_ASSERT(UMP_DD_HANDLE_INVALID!=ump_mem); + + /* At present, this is a no-op. But, it allows the mali_address_manager to + * do unmapping of a subrange in future. */ + mali_allocation_engine_unmap_physical( allocation->engine, + allocation->descriptor, + allocation->initial_offset, + allocation->size_allocated, + (_mali_osk_mem_mapregion_flags_t)0 + ); + _mali_osk_free( allocation ); + + + ump_dd_reference_release(ump_mem) ; + return; +} + +_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args ) +{ + ump_dd_handle ump_mem; + mali_physical_memory_allocator external_memory_allocator; + struct mali_session_data *session_data; + mali_memory_allocation * descriptor; + int md; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)args->ctx; + MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); + + /* check arguments */ + /* NULL might be a valid Mali address */ + if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + + /* size must be a multiple of the system page size */ + if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + + MALI_DEBUG_PRINT(3, + ("Requested to map ump memory with secure id %d into virtual memory 0x%08X, size 0x%08X\n", + args->secure_id, args->mali_address, args->size)); + + ump_mem = ump_dd_handle_create_from_secure_id( (int)args->secure_id ) ; + + if ( UMP_DD_HANDLE_INVALID==ump_mem ) MALI_ERROR(_MALI_OSK_ERR_FAULT); + + descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); + if (NULL == descriptor) + { + ump_dd_reference_release(ump_mem); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + descriptor->size = args->size; + descriptor->mapping = NULL; + descriptor->mali_address = args->mali_address; + descriptor->mali_addr_mapping_info = (void*)session_data; + descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ + descriptor->cache_settings = (u32) MALI_CACHE_STANDARD; + descriptor->lock = session_data->memory_lock; + + if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) + { + descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; + } + _mali_osk_list_init( &descriptor->list ); + + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md)) + { + ump_dd_reference_release(ump_mem); + _mali_osk_free(descriptor); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + external_memory_allocator.allocate = ump_memory_commit; + external_memory_allocator.allocate_page_table_block = NULL; + external_memory_allocator.ctx = ump_mem; + external_memory_allocator.name = "UMP Memory"; + external_memory_allocator.next = NULL; + + _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL)) + { + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + mali_descriptor_mapping_free(session_data->descriptor_mapping, md); + ump_dd_reference_release(ump_mem); + _mali_osk_free(descriptor); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + args->cookie = md; + + MALI_DEBUG_PRINT(5,("Returning from UMP attach\n")); + + /* All OK */ + MALI_SUCCESS; +} + + +_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args ) +{ + mali_memory_allocation * descriptor; + struct mali_session_data *session_data; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)args->ctx; + MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); + + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor)) + { + MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release ump memory\n", args->cookie)); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + descriptor = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie); + + if (NULL != descriptor) + { + _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + mali_allocation_engine_release_memory(memory_engine, descriptor); + + _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + _mali_osk_free(descriptor); + } + + MALI_SUCCESS; + +} +#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 */ + + +static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + u32 * data; + external_mem_allocation * ret_allocation; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + ret_allocation = _mali_osk_malloc( sizeof(external_mem_allocation) ); + + if ( NULL == ret_allocation ) + { + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + + data = (u32*)ctx; + + ret_allocation->engine = engine; + ret_allocation->descriptor = descriptor; + ret_allocation->initial_offset = *offset; + + alloc_info->ctx = NULL; + alloc_info->handle = ret_allocation; + alloc_info->next = NULL; + alloc_info->release = external_memory_release; + + MALI_DEBUG_PRINT(5, ("External map: mapping phys 0x%08X at mali virtual address 0x%08X staring at offset 0x%08X length 0x%08X\n", data[0], descriptor->mali_address, *offset, data[1])); + + if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, data[1])) + { + MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n")); + _mali_osk_free(ret_allocation); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + *offset += data[1]; + + if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) + { + /* Map in an extra virtual guard page at the end of the VMA */ + MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n")); + if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, _MALI_OSK_MALI_PAGE_SIZE)) + { + u32 size_allocated = *offset - ret_allocation->initial_offset; + MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n")); + + /* unmap what we previously mapped */ + mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 ); + _mali_osk_free(ret_allocation); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + *offset += _MALI_OSK_MALI_PAGE_SIZE; + } + + ret_allocation->size = *offset - ret_allocation->initial_offset; + + return MALI_MEM_ALLOC_FINISHED; +} + +static void external_memory_release(void * ctx, void * handle) +{ + external_mem_allocation * allocation; + + allocation = (external_mem_allocation *) handle; + MALI_DEBUG_ASSERT_POINTER( allocation ); + + /* At present, this is a no-op. But, it allows the mali_address_manager to + * do unmapping of a subrange in future. */ + + mali_allocation_engine_unmap_physical( allocation->engine, + allocation->descriptor, + allocation->initial_offset, + allocation->size, + (_mali_osk_mem_mapregion_flags_t)0 + ); + + _mali_osk_free( allocation ); + + return; +} + +_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args ) +{ + mali_physical_memory_allocator external_memory_allocator; + struct mali_session_data *session_data; + u32 info[2]; + mali_memory_allocation * descriptor; + int md; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)args->ctx; + MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); + + external_memory_allocator.allocate = external_memory_commit; + external_memory_allocator.allocate_page_table_block = NULL; + external_memory_allocator.ctx = &info[0]; + external_memory_allocator.name = "External Memory"; + external_memory_allocator.next = NULL; + + /* check arguments */ + /* NULL might be a valid Mali address */ + if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + + /* size must be a multiple of the system page size */ + if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + + MALI_DEBUG_PRINT(3, + ("Requested to map physical memory 0x%x-0x%x into virtual memory 0x%x\n", + (void*)args->phys_addr, + (void*)(args->phys_addr + args->size -1), + (void*)args->mali_address) + ); + + /* Validate the mali physical range */ + if (_MALI_OSK_ERR_OK != mali_mem_validation_check(args->phys_addr, args->size)) + { + return _MALI_OSK_ERR_FAULT; + } + + info[0] = args->phys_addr; + info[1] = args->size; + + descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); + if (NULL == descriptor) MALI_ERROR(_MALI_OSK_ERR_NOMEM); + + descriptor->size = args->size; + descriptor->mapping = NULL; + descriptor->mali_address = args->mali_address; + descriptor->mali_addr_mapping_info = (void*)session_data; + descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ + descriptor->cache_settings = (u32)MALI_CACHE_STANDARD; + descriptor->lock = session_data->memory_lock; + if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) + { + descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; + } + _mali_osk_list_init( &descriptor->list ); + + _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL)) + { + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_free(descriptor); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md)) + { + mali_allocation_engine_release_memory(memory_engine, descriptor); + _mali_osk_free(descriptor); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + args->cookie = md; + + MALI_DEBUG_PRINT(5,("Returning from range_map_external_memory\n")); + + /* All OK */ + MALI_SUCCESS; +} + + +_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args ) +{ + mali_memory_allocation * descriptor; + void* old_value; + struct mali_session_data *session_data; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)args->ctx; + MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS); + + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor)) + { + MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to unmap external memory\n", args->cookie)); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } + + old_value = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie); + + if (NULL != old_value) + { + _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + mali_allocation_engine_release_memory(memory_engine, descriptor); + + _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + _mali_osk_free(descriptor); + } + + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args ) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + args->memory_size = 2 * 1024 * 1024 * 1024UL; /* 2GB address space */ + args->mali_address_base = 1 * 1024 * 1024 * 1024UL; /* staring at 1GB, causing this layout: (0-1GB unused)(1GB-3G usage by Mali)(3G-4G unused) */ + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args ) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + MALI_SUCCESS; +} + +static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor) +{ + struct mali_session_data *session_data; + u32 actual_size; + + MALI_DEBUG_ASSERT_POINTER(descriptor); + + session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + + actual_size = descriptor->size; + + if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) + { + actual_size += _MALI_OSK_MALI_PAGE_SIZE; + } + + return mali_mmu_pagedir_map(session_data->page_directory, descriptor->mali_address, actual_size); +} + +static void mali_address_manager_release(mali_memory_allocation * descriptor) +{ + const u32 illegal_mali_address = 0xffffffff; + struct mali_session_data *session_data; + MALI_DEBUG_ASSERT_POINTER(descriptor); + + /* It is allowed to call this function several times on the same descriptor. + When memory is released we set the illegal_mali_address so we can early out here. */ + if ( illegal_mali_address == descriptor->mali_address) return; + + session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + mali_mmu_pagedir_unmap(session_data->page_directory, descriptor->mali_address, descriptor->size); + + descriptor->mali_address = illegal_mali_address ; +} + +static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size) +{ + struct mali_session_data *session_data; + u32 mali_address; + + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(phys_addr); + + session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + MALI_DEBUG_ASSERT_POINTER(session_data); + + mali_address = descriptor->mali_address + offset; + + MALI_DEBUG_PRINT(7, ("Mali map: mapping 0x%08X to Mali address 0x%08X length 0x%08X\n", *phys_addr, mali_address, size)); + + mali_mmu_pagedir_update(session_data->page_directory, mali_address, *phys_addr, size, descriptor->cache_settings); + + MALI_SUCCESS; +} + +/* This handler registered to mali_mmap for MMU builds */ +_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args ) +{ + struct mali_session_data *session_data; + mali_memory_allocation * descriptor; + + /* validate input */ + if (NULL == args) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: args was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); } + + /* Unpack arguments */ + session_data = (struct mali_session_data *)args->ctx; + + /* validate input */ + if (NULL == session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_FAULT); } + + descriptor = (mali_memory_allocation*) _mali_osk_calloc( 1, sizeof(mali_memory_allocation) ); + if (NULL == descriptor) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: descriptor was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_NOMEM); } + + descriptor->size = args->size; + descriptor->mali_address = args->phys_addr; + descriptor->mali_addr_mapping_info = (void*)session_data; + + descriptor->process_addr_mapping_info = args->ukk_private; /* save to be used during physical manager callback */ + descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE; + descriptor->cache_settings = (u32) args->cache_settings ; + descriptor->lock = session_data->memory_lock; + _mali_osk_list_init( &descriptor->list ); + + _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + if (0 == mali_allocation_engine_allocate_memory(memory_engine, descriptor, physical_memory_allocators, &session_data->memory_head)) + { + /* We do not FLUSH nor TLB_ZAP on MMAP, since we do both of those on job start*/ + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + + args->mapping = descriptor->mapping; + args->cookie = (u32)descriptor; + + MALI_DEBUG_PRINT(7, ("MMAP OK\n")); + MALI_SUCCESS; + } + else + { + _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW); + /* OOM, but not a fatal error */ + MALI_DEBUG_PRINT(4, ("Memory allocation failure, OOM\n")); + _mali_osk_free(descriptor); + /* Linux will free the CPU address allocation, userspace client the Mali address allocation */ + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } +} + +static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ) +{ + struct mali_session_data *session_data; + mali_memory_allocation * descriptor; + + u32 num_groups = mali_group_get_glob_num_groups(); + struct mali_group *group; + u32 i; + + descriptor = (mali_memory_allocation *)args->cookie; + MALI_DEBUG_ASSERT_POINTER(descriptor); + + /** @note args->context unused; we use the memory_session from the cookie */ + /* args->mapping and args->size are also discarded. They are only necessary + for certain do_munmap implementations. However, they could be used to check the + descriptor at this point. */ + + session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + MALI_DEBUG_ASSERT_POINTER(session_data); + + /* Unmapping the memory from the mali virtual address space. + It is allowed to call this function severeal times, which might happen if zapping below fails. */ + mali_allocation_engine_release_pt1_mali_pagetables_unmap(memory_engine, descriptor); + +#ifdef MALI_UNMAP_FLUSH_ALL_MALI_L2 + { + u32 number_of_clusters = mali_cluster_get_glob_num_clusters(); + for (i = 0; i < number_of_clusters; i++) + { + struct mali_cluster *cluster; + cluster = mali_cluster_get_global_cluster(i); + if( mali_cluster_power_is_enabled_get(cluster) ) + { + mali_cluster_l2_cache_invalidate_all_force(cluster); + } + } + } +#endif + + for (i = 0; i < num_groups; i++) + { + group = mali_group_get_glob_group(i); + mali_group_lock(group); + mali_group_remove_session_if_unused(group, session_data); + if (mali_group_get_session(group) == session_data) + { + /* The Zap also does the stall and disable_stall */ + mali_bool zap_success = mali_mmu_zap_tlb(mali_group_get_mmu(group)); + if (MALI_TRUE != zap_success) + { + MALI_DEBUG_PRINT(2, ("Mali memory unmap failed. Doing pagefault handling.\n")); + mali_group_bottom_half(group, GROUP_EVENT_MMU_PAGE_FAULT); + /* The bottom half will also do the unlock */ + continue; + } + } + mali_group_unlock(group); + } + + /* Removes the descriptor from the session's memory list, releases physical memory, releases descriptor */ + mali_allocation_engine_release_pt2_physical_memory_free(memory_engine, descriptor); + + _mali_osk_free(descriptor); + + return _MALI_OSK_ERR_OK; +} + +/* Handler for unmapping memory for MMU builds */ +_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args ) +{ + mali_memory_allocation * descriptor; + _mali_osk_lock_t *descriptor_lock; + _mali_osk_errcode_t err; + + descriptor = (mali_memory_allocation *)args->cookie; + MALI_DEBUG_ASSERT_POINTER(descriptor); + + /** @note args->context unused; we use the memory_session from the cookie */ + /* args->mapping and args->size are also discarded. They are only necessary + for certain do_munmap implementations. However, they could be used to check the + descriptor at this point. */ + + MALI_DEBUG_ASSERT_POINTER((struct mali_session_data *)descriptor->mali_addr_mapping_info); + + descriptor_lock = descriptor->lock; /* should point to the session data lock... */ + + err = _MALI_OSK_ERR_BUSY; + while (err == _MALI_OSK_ERR_BUSY) + { + if (descriptor_lock) + { + _mali_osk_lock_wait( descriptor_lock, _MALI_OSK_LOCKMODE_RW ); + } + + err = _mali_ukk_mem_munmap_internal( args ); + + if (descriptor_lock) + { + _mali_osk_lock_signal( descriptor_lock, _MALI_OSK_LOCKMODE_RW ); + } + + if (err == _MALI_OSK_ERR_BUSY) + { + /* + * Reason for this; + * We where unable to stall the MMU, probably because we are in page fault handling. + * Sleep for a while with the session lock released, then try again. + * Abnormal termination of programs with running Mali jobs is a normal reason for this. + */ + _mali_osk_time_ubusydelay(10); + } + } + + return err; +} + +u32 _mali_ukk_report_memory_usage(void) +{ + return mali_allocation_engine_memory_usage(physical_memory_allocators); +} + +_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping) +{ + _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + + if (0 == _mali_osk_list_empty(&page_table_cache.partial)) + { + mali_mmu_page_table_allocation * alloc = _MALI_OSK_LIST_ENTRY(page_table_cache.partial.next, mali_mmu_page_table_allocation, list); + int page_number = _mali_osk_find_first_zero_bit(alloc->usage_map, alloc->num_pages); + MALI_DEBUG_PRINT(6, ("Partial page table allocation found, using page offset %d\n", page_number)); + _mali_osk_set_nonatomic_bit(page_number, alloc->usage_map); + alloc->usage_count++; + if (alloc->num_pages == alloc->usage_count) + { + /* full, move alloc to full list*/ + _mali_osk_list_move(&alloc->list, &page_table_cache.full); + } + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + + *table_page = (MALI_MMU_PAGE_SIZE * page_number) + alloc->pages.phys_base; + *mapping = (mali_io_address)((MALI_MMU_PAGE_SIZE * page_number) + (u32)alloc->pages.mapping); + MALI_DEBUG_PRINT(4, ("Page table allocated for VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page )); + MALI_SUCCESS; + } + else + { + mali_mmu_page_table_allocation * alloc; + /* no free pages, allocate a new one */ + + alloc = (mali_mmu_page_table_allocation *)_mali_osk_calloc(1, sizeof(mali_mmu_page_table_allocation)); + if (NULL == alloc) + { + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + *table_page = MALI_INVALID_PAGE; + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + _MALI_OSK_INIT_LIST_HEAD(&alloc->list); + + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_page_tables(memory_engine, &alloc->pages, physical_memory_allocators)) + { + MALI_DEBUG_PRINT(1, ("No more memory for page tables\n")); + _mali_osk_free(alloc); + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + *table_page = MALI_INVALID_PAGE; + *mapping = NULL; + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + /* create the usage map */ + alloc->num_pages = alloc->pages.size / MALI_MMU_PAGE_SIZE; + alloc->usage_count = 1; + MALI_DEBUG_PRINT(3, ("New page table cache expansion, %d pages in new cache allocation\n", alloc->num_pages)); + alloc->usage_map = _mali_osk_calloc(1, ((alloc->num_pages + BITS_PER_LONG - 1) & ~(BITS_PER_LONG-1) / BITS_PER_LONG) * sizeof(unsigned long)); + if (NULL == alloc->usage_map) + { + MALI_DEBUG_PRINT(1, ("Failed to allocate memory to describe MMU page table cache usage\n")); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc); + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + *table_page = MALI_INVALID_PAGE; + *mapping = NULL; + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + _mali_osk_set_nonatomic_bit(0, alloc->usage_map); + + if (alloc->num_pages > 1) + { + _mali_osk_list_add(&alloc->list, &page_table_cache.partial); + } + else + { + _mali_osk_list_add(&alloc->list, &page_table_cache.full); + } + + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + *table_page = alloc->pages.phys_base; /* return the first page */ + *mapping = alloc->pages.mapping; /* Mapping for first page */ + MALI_DEBUG_PRINT(4, ("Page table allocated: VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page )); + MALI_SUCCESS; + } +} + +void mali_mmu_release_table_page(u32 pa) +{ + mali_mmu_page_table_allocation * alloc, * temp_alloc; + + MALI_DEBUG_PRINT_IF(1, pa & 4095, ("Bad page address 0x%x given to mali_mmu_release_table_page\n", (void*)pa)); + + MALI_DEBUG_PRINT(4, ("Releasing table page 0x%08X to the cache\n", pa)); + + _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + + /* find the entry this address belongs to */ + /* first check the partial list */ + _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.partial, mali_mmu_page_table_allocation, list) + { + u32 start = alloc->pages.phys_base; + u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE; + if (pa >= start && pa <= last) + { + MALI_DEBUG_ASSERT(0 != _mali_osk_test_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map)); + _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map); + alloc->usage_count--; + + _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE); + + if (0 == alloc->usage_count) + { + /* empty, release whole page alloc */ + _mali_osk_list_del(&alloc->list); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc->usage_map); + _mali_osk_free(alloc); + } + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + MALI_DEBUG_PRINT(4, ("(partial list)Released table page 0x%08X to the cache\n", pa)); + return; + } + } + + /* the check the full list */ + _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.full, mali_mmu_page_table_allocation, list) + { + u32 start = alloc->pages.phys_base; + u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE; + if (pa >= start && pa <= last) + { + _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map); + alloc->usage_count--; + + _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE); + + + if (0 == alloc->usage_count) + { + /* empty, release whole page alloc */ + _mali_osk_list_del(&alloc->list); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc->usage_map); + _mali_osk_free(alloc); + } + else + { + /* transfer to partial list */ + _mali_osk_list_move(&alloc->list, &page_table_cache.partial); + } + + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); + MALI_DEBUG_PRINT(4, ("(full list)Released table page 0x%08X to the cache\n", pa)); + return; + } + } + + MALI_DEBUG_PRINT(1, ("pa 0x%x not found in the page table cache\n", (void*)pa)); + + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); +} + +static _mali_osk_errcode_t mali_mmu_page_table_cache_create(void) +{ + page_table_cache.lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK + | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE); + MALI_CHECK_NON_NULL( page_table_cache.lock, _MALI_OSK_ERR_FAULT ); + _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.partial); + _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.full); + MALI_SUCCESS; +} + +static void mali_mmu_page_table_cache_destroy(void) +{ + mali_mmu_page_table_allocation * alloc, *temp; + + _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.partial, mali_mmu_page_table_allocation, list) + { + MALI_DEBUG_PRINT_IF(1, 0 != alloc->usage_count, ("Destroying page table cache while pages are tagged as in use. %d allocations still marked as in use.\n", alloc->usage_count)); + _mali_osk_list_del(&alloc->list); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc->usage_map); + _mali_osk_free(alloc); + } + + MALI_DEBUG_PRINT_IF(1, 0 == _mali_osk_list_empty(&page_table_cache.full), ("Page table cache full list contains one or more elements \n")); + + _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.full, mali_mmu_page_table_allocation, list) + { + MALI_DEBUG_PRINT(1, ("Destroy alloc 0x%08X with usage count %d\n", (u32)alloc, alloc->usage_count)); + _mali_osk_list_del(&alloc->list); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc->usage_map); + _mali_osk_free(alloc); + } + + _mali_osk_lock_term(page_table_cache.lock); +} diff --git a/drivers/media/video/samsung/mali/common/mali_memory.h b/drivers/media/video/samsung/mali/common/mali_memory.h new file mode 100644 index 0000000..78e2945 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_memory.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_MEMORY_H__ +#define __MALI_MEMORY_H__ + +#include "mali_osk.h" +#include "mali_session.h" + +struct mali_cluster; +struct mali_group; + +/** @brief Initialize Mali memory subsystem + * + * Allocate and initialize internal data structures. Must be called before + * allocating Mali memory. + * + * @return On success _MALI_OSK_ERR_OK, othervise some error code describing the error. + */ +_mali_osk_errcode_t mali_memory_initialize(void); + +/** @brief Terminate Mali memory system + * + * Clean up and release internal data structures. + */ +void mali_memory_terminate(void); + +/** @brief Start new Mali memory session + * + * Allocate and prepare session specific memory allocation data data. The + * session page directory, lock, and descriptor map is set up. + * + * @param mali_session_data pointer to the session data structure + */ +_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data *mali_session_data); + +/** @brief Close a Mali memory session + * + * Release session specific memory allocation related data. + * + * @param mali_session_data pointer to the session data structure + */ +void mali_memory_session_end(struct mali_session_data *mali_session_data); + +/** @brief Allocate a page table page + * + * Allocate a page for use as a page directory or page table. The page is + * mapped into kernel space. + * + * @return _MALI_OSK_ERR_OK on success, othervise an error code + * @param table_page GPU pointer to the allocated page + * @param mapping CPU pointer to the mapping of the allocated page + */ +_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping); + +/** @brief Release a page table page + * + * Release a page table page allocated through \a mali_mmu_get_table_page + * + * @param pa the GPU address of the page to release + */ +void mali_mmu_release_table_page(u32 pa); + + +/** @brief Parse resource and prepare the OS memory allocator + */ +_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource); + +/** @brief Parse resource and prepare the dedicated memory allocator + */ +_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource); + +mali_allocation_engine mali_mem_get_memory_engine(void); + +#endif /* __MALI_MEMORY_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_mmu.c b/drivers/media/video/samsung/mali/common/mali_mmu.c new file mode 100644 index 0000000..2f2fa4d --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_mmu.c @@ -0,0 +1,619 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_bitops.h" +#include "mali_osk_list.h" +#include "mali_ukk.h" + +#include "mali_mmu.h" +#include "mali_hw_core.h" +#include "mali_group.h" +#include "mali_mmu_page_directory.h" + +/** + * Size of the MMU registers in bytes + */ +#define MALI_MMU_REGISTERS_SIZE 0x24 + +/** + * MMU register numbers + * Used in the register read/write routines. + * See the hardware documentation for more information about each register + */ +typedef enum mali_mmu_register { + MALI_MMU_REGISTER_DTE_ADDR = 0x0000, /**< Current Page Directory Pointer */ + MALI_MMU_REGISTER_STATUS = 0x0004, /**< Status of the MMU */ + MALI_MMU_REGISTER_COMMAND = 0x0008, /**< Command register, used to control the MMU */ + MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x000C, /**< Logical address of the last page fault */ + MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x010, /**< Used to invalidate the mapping of a single page from the MMU */ + MALI_MMU_REGISTER_INT_RAWSTAT = 0x0014, /**< Raw interrupt status, all interrupts visible */ + MALI_MMU_REGISTER_INT_CLEAR = 0x0018, /**< Indicate to the MMU that the interrupt has been received */ + MALI_MMU_REGISTER_INT_MASK = 0x001C, /**< Enable/disable types of interrupts */ + MALI_MMU_REGISTER_INT_STATUS = 0x0020 /**< Interrupt status based on the mask */ +} mali_mmu_register; + +/** + * MMU interrupt register bits + * Each cause of the interrupt is reported + * through the (raw) interrupt status registers. + * Multiple interrupts can be pending, so multiple bits + * can be set at once. + */ +typedef enum mali_mmu_interrupt +{ + MALI_MMU_INTERRUPT_PAGE_FAULT = 0x01, /**< A page fault occured */ + MALI_MMU_INTERRUPT_READ_BUS_ERROR = 0x02 /**< A bus read error occured */ +} mali_mmu_interrupt; + +/** + * MMU commands + * These are the commands that can be sent + * to the MMU unit. + */ +typedef enum mali_mmu_command +{ + MALI_MMU_COMMAND_ENABLE_PAGING = 0x00, /**< Enable paging (memory translation) */ + MALI_MMU_COMMAND_DISABLE_PAGING = 0x01, /**< Disable paging (memory translation) */ + MALI_MMU_COMMAND_ENABLE_STALL = 0x02, /**< Enable stall on page fault */ + MALI_MMU_COMMAND_DISABLE_STALL = 0x03, /**< Disable stall on page fault */ + MALI_MMU_COMMAND_ZAP_CACHE = 0x04, /**< Zap the entire page table cache */ + MALI_MMU_COMMAND_PAGE_FAULT_DONE = 0x05, /**< Page fault processed */ + MALI_MMU_COMMAND_HARD_RESET = 0x06 /**< Reset the MMU back to power-on settings */ +} mali_mmu_command; + +typedef enum mali_mmu_status_bits +{ + MALI_MMU_STATUS_BIT_PAGING_ENABLED = 1 << 0, + MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE = 1 << 1, + MALI_MMU_STATUS_BIT_STALL_ACTIVE = 1 << 2, + MALI_MMU_STATUS_BIT_IDLE = 1 << 3, + MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY = 1 << 4, + MALI_MMU_STATUS_BIT_PAGE_FAULT_IS_WRITE = 1 << 5, +} mali_mmu_status_bits; + +/** + * Definition of the MMU struct + * Used to track a MMU unit in the system. + * Contains information about the mapping of the registers + */ +struct mali_mmu_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + struct mali_group *group; /**< Parent core group */ + _mali_osk_irq_t *irq; /**< IRQ handler */ +}; + +/** + * The MMU interrupt handler + * Upper half of the MMU interrupt processing. + * Called by the kernel when the MMU has triggered an interrupt. + * The interrupt function supports IRQ sharing. So it'll probe the MMU in question + * @param irq The irq number (not used) + * @param dev_id Points to the MMU object being handled + * @param regs Registers of interrupted process (not used) + * @return Standard Linux interrupt result. + * Subset used by the driver is IRQ_HANDLED processed + * IRQ_NONE Not processed + */ +static _mali_osk_errcode_t mali_mmu_upper_half(void * data); + +/** + * The MMU reset hander + * Bottom half of the MMU interrupt processing for page faults and bus errors + * @param work The item to operate on, NULL in our case + */ +static void mali_mmu_bottom_half(void *data); + +static void mali_mmu_probe_trigger(void *data); +static _mali_osk_errcode_t mali_mmu_probe_ack(void *data); + +MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu); + +/* page fault queue flush helper pages + * note that the mapping pointers are currently unused outside of the initialization functions */ +static u32 mali_page_fault_flush_page_directory = MALI_INVALID_PAGE; +static u32 mali_page_fault_flush_page_table = MALI_INVALID_PAGE; +static u32 mali_page_fault_flush_data_page = MALI_INVALID_PAGE; + +/* an empty page directory (no address valid) which is active on any MMU not currently marked as in use */ +static u32 mali_empty_page_directory = MALI_INVALID_PAGE; + +_mali_osk_errcode_t mali_mmu_initialize(void) +{ + /* allocate the helper pages */ + mali_empty_page_directory = mali_allocate_empty_page(); + if(0 == mali_empty_page_directory) + { + mali_empty_page_directory = MALI_INVALID_PAGE; + return _MALI_OSK_ERR_NOMEM; + } + + if (_MALI_OSK_ERR_OK != mali_create_fault_flush_pages(&mali_page_fault_flush_page_directory, + &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page)) + { + mali_free_empty_page(mali_empty_page_directory); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; +} + +void mali_mmu_terminate(void) +{ + MALI_DEBUG_PRINT(3, ("Mali MMU: terminating\n")); + + /* Free global helper pages */ + mali_free_empty_page(mali_empty_page_directory); + + /* Free the page fault flush pages */ + mali_destroy_fault_flush_pages(&mali_page_fault_flush_page_directory, + &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page); +} + +struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource) +{ + struct mali_mmu_core* mmu = NULL; + + MALI_DEBUG_ASSERT_POINTER(resource); + + MALI_DEBUG_PRINT(2, ("Mali MMU: Creating Mali MMU: %s\n", resource->description)); + + mmu = _mali_osk_calloc(1,sizeof(struct mali_mmu_core)); + if (NULL != mmu) + { + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE)) + { + if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu)) + { + /* Setup IRQ handlers (which will do IRQ probing if needed) */ + mmu->irq = _mali_osk_irq_init(resource->irq, + mali_mmu_upper_half, + mali_mmu_bottom_half, + mali_mmu_probe_trigger, + mali_mmu_probe_ack, + mmu, + "mali_mmu_irq_handlers"); + if (NULL != mmu->irq) + { + return mmu; + } + else + { + MALI_PRINT_ERROR(("Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description)); + } + } + mali_hw_core_delete(&mmu->hw_core); + } + + _mali_osk_free(mmu); + } + else + { + MALI_PRINT_ERROR(("Failed to allocate memory for MMU\n")); + } + + return NULL; +} + +void mali_mmu_delete(struct mali_mmu_core *mmu) +{ + _mali_osk_irq_term(mmu->irq); + mali_hw_core_delete(&mmu->hw_core); + _mali_osk_free(mmu); +} + +void mali_mmu_set_group(struct mali_mmu_core *mmu, struct mali_group *group) +{ + mmu->group = group; +} + +static void mali_mmu_enable_paging(struct mali_mmu_core *mmu) +{ + const int max_loop_count = 100; + const int delay_in_usecs = 1; + int i; + + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING); + + for (i = 0; i < max_loop_count; ++i) + { + if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED) + { + break; + } + _mali_osk_time_ubusydelay(delay_in_usecs); + } + if (max_loop_count == i) + { + MALI_PRINT_ERROR(("Enable paging request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); + } +} + +mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu) +{ + const int max_loop_count = 100; + const int delay_in_usecs = 999; + int i; + u32 mmu_status; + + /* There are no group when it is called from mali_mmu_create */ + if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group); + + mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + + if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) ) + { + MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enebled.\n")); + return MALI_TRUE; + } + + if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) + { + MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it is in pagefault state.\n")); + return MALI_FALSE; + } + + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL); + + for (i = 0; i < max_loop_count; ++i) + { + mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + if ( mmu_status & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) + { + break; + } + if ( 0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED ))) + { + break; + } + _mali_osk_time_ubusydelay(delay_in_usecs); + } + if (max_loop_count == i) + { + MALI_PRINT_ERROR(("Enable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); + return MALI_FALSE; + } + + if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) + { + MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it has a pagefault.\n")); + return MALI_FALSE; + } + + return MALI_TRUE; +} + +void mali_mmu_disable_stall(struct mali_mmu_core *mmu) +{ + const int max_loop_count = 100; + const int delay_in_usecs = 1; + int i; + u32 mmu_status; + /* There are no group when it is called from mali_mmu_create */ + if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group); + + mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + + if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) + { + MALI_DEBUG_PRINT(3, ("MMU disable skipped since it was not enabled.\n")); + return; + } + if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) + { + MALI_DEBUG_PRINT(2, ("Aborting MMU disable stall request since it is in pagefault state.\n")); + return; + } + + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL); + + for (i = 0; i < max_loop_count; ++i) + { + u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) ) + { + break; + } + if ( status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) + { + break; + } + if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) + { + break; + } + _mali_osk_time_ubusydelay(delay_in_usecs); + } + if (max_loop_count == i) MALI_DEBUG_PRINT(1,("Disable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); +} + +void mali_mmu_page_fault_done(struct mali_mmu_core *mmu) +{ + MALI_ASSERT_GROUP_LOCKED(mmu->group); + MALI_DEBUG_PRINT(4, ("Mali MMU: %s: Leaving page fault mode\n", mmu->hw_core.description)); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE); +} + +MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu) +{ + const int max_loop_count = 100; + const int delay_in_usecs = 1; + int i; + /* The _if_ is neccessary when called from mali_mmu_create and NULL==group */ + if (mmu->group)MALI_ASSERT_GROUP_LOCKED(mmu->group); + + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_HARD_RESET); + + for (i = 0; i < max_loop_count; ++i) + { + if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR) == 0) + { + break; + } + _mali_osk_time_ubusydelay(delay_in_usecs); + } + if (max_loop_count == i) + { + MALI_PRINT_ERROR(("Reset request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + mali_bool stall_success; + MALI_DEBUG_ASSERT_POINTER(mmu); + /* The _if_ is neccessary when called from mali_mmu_create and NULL==group */ + if (mmu->group) + { + MALI_ASSERT_GROUP_LOCKED(mmu->group); + } + + stall_success = mali_mmu_enable_stall(mmu); + + /* The stall can not fail in current hw-state */ + MALI_DEBUG_ASSERT(stall_success); + + MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description)); + + if (_MALI_OSK_ERR_OK == mali_mmu_raw_reset(mmu)) + { + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR); + /* no session is active, so just activate the empty page directory */ + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory); + mali_mmu_enable_paging(mmu); + err = _MALI_OSK_ERR_OK; + } + mali_mmu_disable_stall(mmu); + + return err; +} + + +/* ------------- interrupt handling below ------------------ */ + +static _mali_osk_errcode_t mali_mmu_upper_half(void * data) +{ + struct mali_mmu_core *mmu = (struct mali_mmu_core *)data; + u32 int_stat; + + MALI_DEBUG_ASSERT_POINTER(mmu); + + /* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */ + int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS); + if (0 != int_stat) + { + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, 0); + mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + + if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT) + { + _mali_osk_irq_schedulework(mmu->irq); + } + + if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR) + { + /* clear interrupt flag */ + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR); + /* reenable it */ + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, + mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK) | MALI_MMU_INTERRUPT_READ_BUS_ERROR); + MALI_PRINT_ERROR(("Mali MMU: Read bus error\n")); + } + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + +static void mali_mmu_bottom_half(void * data) +{ + struct mali_mmu_core *mmu = (struct mali_mmu_core*)data; + u32 raw, status, fault_address; + + MALI_DEBUG_ASSERT_POINTER(mmu); + + MALI_DEBUG_PRINT(3, ("Mali MMU: Page fault bottom half: Locking subsystems\n")); + + mali_group_lock(mmu->group); /* Unlocked in mali_group_bottom_half */ + + if ( MALI_FALSE == mali_group_power_is_on(mmu->group) ) + { + MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.",mmu->hw_core.description)); + mali_group_unlock(mmu->group); + return; + } + + raw = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT); + status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + + if ( (0==(raw & MALI_MMU_INTERRUPT_PAGE_FAULT)) && (0==(status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) ) + { + MALI_DEBUG_PRINT(2, ("Mali MMU: Page fault bottom half: No Irq found.\n")); + mali_group_unlock(mmu->group); + /* MALI_DEBUG_ASSERT(0); */ + return; + } + + /* An actual page fault has occurred. */ + + fault_address = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_PAGE_FAULT_ADDR); + + MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n", + (void*)fault_address, + (status >> 6) & 0x1F, + (status & 32) ? "write" : "read", + mmu->hw_core.description)); + + mali_group_bottom_half(mmu->group, GROUP_EVENT_MMU_PAGE_FAULT); /* Unlocks the group lock */ +} + +mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu) +{ + mali_bool stall_success; + MALI_ASSERT_GROUP_LOCKED(mmu->group); + + stall_success = mali_mmu_enable_stall(mmu); + + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); + + if (MALI_FALSE == stall_success) + { + /* False means that it is in Pagefault state. Not possible to disable_stall then */ + return MALI_FALSE; + } + + mali_mmu_disable_stall(mmu); + return MALI_TRUE; +} + +void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu) +{ + MALI_ASSERT_GROUP_LOCKED(mmu->group); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); +} + + +void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address) +{ + MALI_ASSERT_GROUP_LOCKED(mmu->group); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_ZAP_ONE_LINE, MALI_MMU_PDE_ENTRY(mali_address)); +} + +static void mali_mmu_activate_address_space(struct mali_mmu_core *mmu, u32 page_directory) +{ + MALI_ASSERT_GROUP_LOCKED(mmu->group); + /* The MMU must be in stalled or page fault mode, for this writing to work */ + MALI_DEBUG_ASSERT( 0 != ( mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) + & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) ); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, page_directory); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); + +} + +mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mali_page_directory *pagedir) +{ + mali_bool stall_success; + MALI_DEBUG_ASSERT_POINTER(mmu); + MALI_ASSERT_GROUP_LOCKED(mmu->group); + + MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description)); + stall_success = mali_mmu_enable_stall(mmu); + + if ( MALI_FALSE==stall_success ) return MALI_FALSE; + mali_mmu_activate_address_space(mmu, pagedir->page_directory); + mali_mmu_disable_stall(mmu); + return MALI_TRUE; +} + +void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu) +{ + mali_bool stall_success; + MALI_DEBUG_ASSERT_POINTER(mmu); + MALI_ASSERT_GROUP_LOCKED(mmu->group); + MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description)); + + stall_success = mali_mmu_enable_stall(mmu); + /* This function can only be called when the core is idle, so it could not fail. */ + MALI_DEBUG_ASSERT( stall_success ); + mali_mmu_activate_address_space(mmu, mali_empty_page_directory); + mali_mmu_disable_stall(mmu); +} + +void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu) +{ + mali_bool stall_success; + MALI_DEBUG_ASSERT_POINTER(mmu); + MALI_ASSERT_GROUP_LOCKED(mmu->group); + + MALI_DEBUG_PRINT(3, ("Activating the page fault flush page directory on MMU %s\n", mmu->hw_core.description)); + stall_success = mali_mmu_enable_stall(mmu); + /* This function is expect to fail the stalling, since it might be in PageFault mode when it is called */ + mali_mmu_activate_address_space(mmu, mali_page_fault_flush_page_directory); + if ( MALI_TRUE==stall_success ) mali_mmu_disable_stall(mmu); +} + +/* Is called when we want the mmu to give an interrupt */ +static void mali_mmu_probe_trigger(void *data) +{ + struct mali_mmu_core *mmu = (struct mali_mmu_core *)data; + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT, MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR); +} + +/* Is called when the irq probe wants the mmu to acknowledge an interrupt from the hw */ +static _mali_osk_errcode_t mali_mmu_probe_ack(void *data) +{ + struct mali_mmu_core *mmu = (struct mali_mmu_core *)data; + u32 int_stat; + + int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS); + + MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_acknowledge: intstat 0x%x\n", int_stat)); + if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT) + { + MALI_DEBUG_PRINT(2, ("Probe: Page fault detect: PASSED\n")); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT); + } + else + { + MALI_DEBUG_PRINT(1, ("Probe: Page fault detect: FAILED\n")); + } + + if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR) + { + MALI_DEBUG_PRINT(2, ("Probe: Bus read error detect: PASSED\n")); + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR); + } + else + { + MALI_DEBUG_PRINT(1, ("Probe: Bus read error detect: FAILED\n")); + } + + if ( (int_stat & (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) == + (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) + { + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + +#if 0 +void mali_mmu_print_state(struct mali_mmu_core *mmu) +{ + MALI_DEBUG_PRINT(2, ("MMU: State of %s is 0x%08x\n", mmu->hw_core.description, mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); +} +#endif diff --git a/drivers/media/video/samsung/mali/common/mali_mmu.h b/drivers/media/video/samsung/mali/common/mali_mmu.h new file mode 100644 index 0000000..c7274b8 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_mmu.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_MMU_H__ +#define __MALI_MMU_H__ + +#include "mali_osk.h" +#include "mali_mmu_page_directory.h" + +/* Forward declaration from mali_group.h */ +struct mali_group; + +struct mali_mmu_core; + +_mali_osk_errcode_t mali_mmu_initialize(void); + +void mali_mmu_terminate(void); + +struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource); +void mali_mmu_set_group(struct mali_mmu_core *mmu, struct mali_group *group); +void mali_mmu_delete(struct mali_mmu_core *mmu); + +_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu); +mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu); +void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu); +void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address); + +mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core* mmu, struct mali_page_directory *pagedir); +void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu); +void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu); + +/** + * Issues the enable stall command to the MMU and waits for HW to complete the request + * @param mmu The MMU to enable paging for + * @return MALI_TRUE if HW stall was successfully engaged, otherwise MALI_FALSE (req timed out) + */ +mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu); + +/** + * Issues the disable stall command to the MMU and waits for HW to complete the request + * @param mmu The MMU to enable paging for + */ +void mali_mmu_disable_stall(struct mali_mmu_core *mmu); + +void mali_mmu_page_fault_done(struct mali_mmu_core *mmu); + + +#endif /* __MALI_MMU_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c new file mode 100644 index 0000000..cc91ae9 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c @@ -0,0 +1,475 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#include "mali_osk.h" +#include "mali_uk_types.h" +#include "mali_mmu_page_directory.h" +#include "mali_memory.h" + +#include "mali_cluster.h" +#include "mali_group.h" + +static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data); + +u32 mali_allocate_empty_page(void) +{ + _mali_osk_errcode_t err; + mali_io_address mapping; + u32 address; + + if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&address, &mapping)) + { + /* Allocation failed */ + return 0; + } + + MALI_DEBUG_ASSERT_POINTER( mapping ); + + err = fill_page(mapping, 0); + if (_MALI_OSK_ERR_OK != err) + { + mali_mmu_release_table_page(address); + } + return address; +} + +void mali_free_empty_page(u32 address) +{ + if (MALI_INVALID_PAGE != address) + { + mali_mmu_release_table_page(address); + } +} + +_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page) +{ + _mali_osk_errcode_t err; + mali_io_address page_directory_mapping; + mali_io_address page_table_mapping; + mali_io_address data_page_mapping; + + err = mali_mmu_get_table_page(data_page, &data_page_mapping); + if (_MALI_OSK_ERR_OK == err) + { + err = mali_mmu_get_table_page(page_table, &page_table_mapping); + if (_MALI_OSK_ERR_OK == err) + { + err = mali_mmu_get_table_page(page_directory, &page_directory_mapping); + if (_MALI_OSK_ERR_OK == err) + { + fill_page(data_page_mapping, 0); + fill_page(page_table_mapping, *data_page | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT); + fill_page(page_directory_mapping, *page_table | MALI_MMU_FLAGS_PRESENT); + MALI_SUCCESS; + } + mali_mmu_release_table_page(*page_table); + *page_table = MALI_INVALID_PAGE; + } + mali_mmu_release_table_page(*data_page); + *data_page = MALI_INVALID_PAGE; + } + return err; +} + +void mali_destroy_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page) +{ + if (MALI_INVALID_PAGE != *page_directory) + { + mali_mmu_release_table_page(*page_directory); + *page_directory = MALI_INVALID_PAGE; + } + + if (MALI_INVALID_PAGE != *page_table) + { + mali_mmu_release_table_page(*page_table); + *page_table = MALI_INVALID_PAGE; + } + + if (MALI_INVALID_PAGE != *data_page) + { + mali_mmu_release_table_page(*data_page); + *data_page = MALI_INVALID_PAGE; + } +} + +static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data) +{ + int i; + MALI_DEBUG_ASSERT_POINTER( mapping ); + + for(i = 0; i < MALI_MMU_PAGE_SIZE/4; i++) + { + _mali_osk_mem_iowrite32_relaxed( mapping, i * sizeof(u32), data); + } + _mali_osk_mem_barrier(); + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size) +{ + const int first_pde = MALI_MMU_PDE_ENTRY(mali_address); + const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1); + _mali_osk_errcode_t err; + mali_io_address pde_mapping; + u32 pde_phys; + int i; + + for(i = first_pde; i <= last_pde; i++) + { + if(0 == (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & MALI_MMU_FLAGS_PRESENT)) + { + /* Page table not present */ + MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]); + MALI_DEBUG_ASSERT(NULL == pagedir->page_entries_mapped[i]); + + err = mali_mmu_get_table_page(&pde_phys, &pde_mapping); + if(_MALI_OSK_ERR_OK != err) + { + MALI_PRINT_ERROR(("Failed to allocate page table page.\n")); + return err; + } + pagedir->page_entries_mapped[i] = pde_mapping; + + /* Update PDE, mark as present */ + _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32), + pde_phys | MALI_MMU_FLAGS_PRESENT); + + MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]); + pagedir->page_entries_usage_count[i] = 1; + } + else + { + pagedir->page_entries_usage_count[i]++; + } + } + _mali_osk_write_mem_barrier(); + + MALI_SUCCESS; +} + +MALI_STATIC_INLINE void mali_mmu_zero_pte(mali_io_address page_table, u32 mali_address, u32 size) +{ + int i; + const int first_pte = MALI_MMU_PTE_ENTRY(mali_address); + const int last_pte = MALI_MMU_PTE_ENTRY(mali_address + size - 1); + + for (i = first_pte; i <= last_pte; i++) + { + _mali_osk_mem_iowrite32_relaxed(page_table, i * sizeof(u32), 0); + } +} + +_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size) +{ + const int first_pde = MALI_MMU_PDE_ENTRY(mali_address); + const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1); + u32 left = size; + int i; +#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 + mali_bool pd_changed = MALI_FALSE; + u32 pages_to_invalidate[3]; /* hard-coded to 3: max two pages from the PT level plus max one page from PD level */ + u32 num_pages_inv = 0; +#endif + + /* For all page directory entries in range. */ + for (i = first_pde; i <= last_pde; i++) + { + u32 size_in_pde, offset; + + MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[i]); + MALI_DEBUG_ASSERT(0 != pagedir->page_entries_usage_count[i]); + + /* Offset into page table, 0 if mali_address is 4MiB aligned */ + offset = (mali_address & (MALI_MMU_VIRTUAL_PAGE_SIZE - 1)); + if (left < MALI_MMU_VIRTUAL_PAGE_SIZE - offset) + { + size_in_pde = left; + } + else + { + size_in_pde = MALI_MMU_VIRTUAL_PAGE_SIZE - offset; + } + + pagedir->page_entries_usage_count[i]--; + + /* If entire page table is unused, free it */ + if (0 == pagedir->page_entries_usage_count[i]) + { + u32 page_address; + MALI_DEBUG_PRINT(4, ("Releasing page table as this is the last reference\n")); + /* last reference removed, no need to zero out each PTE */ + + page_address = MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32))); + pagedir->page_entries_mapped[i] = NULL; + _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32), 0); + + mali_mmu_release_table_page(page_address); +#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 + pd_changed = MALI_TRUE; +#endif + } + else + { +#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 + pages_to_invalidate[num_pages_inv] = mali_page_directory_get_phys_address(pagedir, i); + num_pages_inv++; + MALI_DEBUG_ASSERT(num_pages_inv<3); +#endif + + /* If part of the page table is still in use, zero the relevant PTEs */ + mali_mmu_zero_pte(pagedir->page_entries_mapped[i], mali_address, size_in_pde); + } + + left -= size_in_pde; + mali_address += size_in_pde; + } + _mali_osk_write_mem_barrier(); + +#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 + /* L2 pages invalidation */ + if (MALI_TRUE == pd_changed) + { + pages_to_invalidate[num_pages_inv] = pagedir->page_directory; + num_pages_inv++; + MALI_DEBUG_ASSERT(num_pages_inv<3); + } + + if (_MALI_PRODUCT_ID_MALI200 != mali_kernel_core_get_product_id()) + { + mali_cluster_invalidate_pages(pages_to_invalidate, num_pages_inv); + } +#endif + + MALI_SUCCESS; +} + +struct mali_page_directory *mali_mmu_pagedir_alloc(void) +{ + struct mali_page_directory *pagedir; + + pagedir = _mali_osk_calloc(1, sizeof(struct mali_page_directory)); + if(NULL == pagedir) + { + return NULL; + } + + if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&pagedir->page_directory, &pagedir->page_directory_mapped)) + { + _mali_osk_free(pagedir); + return NULL; + } + + /* Zero page directory */ + fill_page(pagedir->page_directory_mapped, 0); + + return pagedir; +} + +void mali_mmu_pagedir_free(struct mali_page_directory *pagedir) +{ + const int num_page_table_entries = sizeof(pagedir->page_entries_mapped) / sizeof(pagedir->page_entries_mapped[0]); + int i; + + /* Free referenced page tables and zero PDEs. */ + for (i = 0; i < num_page_table_entries; i++) + { + if (pagedir->page_directory_mapped && (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, sizeof(u32)*i) & MALI_MMU_FLAGS_PRESENT)) + { + mali_mmu_release_table_page( _mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK); + _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i * sizeof(u32), 0); + } + } + _mali_osk_write_mem_barrier(); + + /* Free the page directory page. */ + mali_mmu_release_table_page(pagedir->page_directory); + + _mali_osk_free(pagedir); +} + + +void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size, mali_memory_cache_settings cache_settings) +{ + u32 end_address = mali_address + size; + u32 permission_bits; + + switch ( cache_settings ) + { + case MALI_CACHE_GP_READ_ALLOCATE: + MALI_DEBUG_PRINT(3, ("Map L2 GP_Read_allocate\n")); + permission_bits = MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE; + break; + + case MALI_CACHE_STANDARD: + MALI_DEBUG_PRINT(3, ("Map L2 Standard\n")); + /*falltrough */ + default: + if ( MALI_CACHE_STANDARD != cache_settings) MALI_PRINT_ERROR(("Wrong cache settings\n")); + permission_bits = MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT; + } + + /* Map physical pages into MMU page tables */ + for ( ; mali_address < end_address; mali_address += MALI_MMU_PAGE_SIZE, phys_address += MALI_MMU_PAGE_SIZE) + { + MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)]); + _mali_osk_mem_iowrite32_relaxed(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)], + MALI_MMU_PTE_ENTRY(mali_address) * sizeof(u32), + phys_address | permission_bits); + } + _mali_osk_write_mem_barrier(); +} + +u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index) +{ + return (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, index*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK); +} + +/* For instrumented */ +struct dump_info +{ + u32 buffer_left; + u32 register_writes_size; + u32 page_table_dump_size; + u32 *buffer; +}; + +static _mali_osk_errcode_t writereg(u32 where, u32 what, const char *comment, struct dump_info *info) +{ + if (NULL != info) + { + info->register_writes_size += sizeof(u32)*2; /* two 32-bit words */ + + if (NULL != info->buffer) + { + /* check that we have enough space */ + if (info->buffer_left < sizeof(u32)*2) MALI_ERROR(_MALI_OSK_ERR_NOMEM); + + *info->buffer = where; + info->buffer++; + + *info->buffer = what; + info->buffer++; + + info->buffer_left -= sizeof(u32)*2; + } + } + + MALI_SUCCESS; +} + +static _mali_osk_errcode_t dump_page(mali_io_address page, u32 phys_addr, struct dump_info * info) +{ + if (NULL != info) + { + /* 4096 for the page and 4 bytes for the address */ + const u32 page_size_in_elements = MALI_MMU_PAGE_SIZE / 4; + const u32 page_size_in_bytes = MALI_MMU_PAGE_SIZE; + const u32 dump_size_in_bytes = MALI_MMU_PAGE_SIZE + 4; + + info->page_table_dump_size += dump_size_in_bytes; + + if (NULL != info->buffer) + { + if (info->buffer_left < dump_size_in_bytes) MALI_ERROR(_MALI_OSK_ERR_NOMEM); + + *info->buffer = phys_addr; + info->buffer++; + + _mali_osk_memcpy(info->buffer, page, page_size_in_bytes); + info->buffer += page_size_in_elements; + + info->buffer_left -= dump_size_in_bytes; + } + } + + MALI_SUCCESS; +} + +static _mali_osk_errcode_t dump_mmu_page_table(struct mali_page_directory *pagedir, struct dump_info * info) +{ + MALI_DEBUG_ASSERT_POINTER(pagedir); + MALI_DEBUG_ASSERT_POINTER(info); + + if (NULL != pagedir->page_directory_mapped) + { + int i; + + MALI_CHECK_NO_ERROR( + dump_page(pagedir->page_directory_mapped, pagedir->page_directory, info) + ); + + for (i = 0; i < 1024; i++) + { + if (NULL != pagedir->page_entries_mapped[i]) + { + MALI_CHECK_NO_ERROR( + dump_page(pagedir->page_entries_mapped[i], + _mali_osk_mem_ioread32(pagedir->page_directory_mapped, + i * sizeof(u32)) & ~MALI_MMU_FLAGS_MASK, info) + ); + } + } + } + + MALI_SUCCESS; +} + +static _mali_osk_errcode_t dump_mmu_registers(struct mali_page_directory *pagedir, struct dump_info * info) +{ + MALI_CHECK_NO_ERROR(writereg(0x00000000, pagedir->page_directory, + "set the page directory address", info)); + MALI_CHECK_NO_ERROR(writereg(0x00000008, 4, "zap???", info)); + MALI_CHECK_NO_ERROR(writereg(0x00000008, 0, "enable paging", info)); + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args ) +{ + struct dump_info info = { 0, 0, 0, NULL }; + struct mali_session_data * session_data; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)(args->ctx); + + MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info)); + MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info)); + args->size = info.register_writes_size + info.page_table_dump_size; + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args ) +{ + struct dump_info info = { 0, 0, 0, NULL }; + struct mali_session_data * session_data; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + MALI_CHECK_NON_NULL(args->buffer, _MALI_OSK_ERR_INVALID_ARGS); + + session_data = (struct mali_session_data *)(args->ctx); + + info.buffer_left = args->size; + info.buffer = args->buffer; + + args->register_writes = info.buffer; + MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info)); + + args->page_table_dump = info.buffer; + MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info)); + + args->register_writes_size = info.register_writes_size; + args->page_table_dump_size = info.page_table_dump_size; + + MALI_SUCCESS; +} diff --git a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h new file mode 100644 index 0000000..628833a --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_MMU_PAGE_DIRECTORY_H__ +#define __MALI_MMU_PAGE_DIRECTORY_H__ + +#include "mali_osk.h" + +/** + * Size of an MMU page in bytes + */ +#define MALI_MMU_PAGE_SIZE 0x1000 + +/* + * Size of the address space referenced by a page table page + */ +#define MALI_MMU_VIRTUAL_PAGE_SIZE 0x400000 /* 4 MiB */ + +/** + * Page directory index from address + * Calculates the page directory index from the given address + */ +#define MALI_MMU_PDE_ENTRY(address) (((address)>>22) & 0x03FF) + +/** + * Page table index from address + * Calculates the page table index from the given address + */ +#define MALI_MMU_PTE_ENTRY(address) (((address)>>12) & 0x03FF) + +/** + * Extract the memory address from an PDE/PTE entry + */ +#define MALI_MMU_ENTRY_ADDRESS(value) ((value) & 0xFFFFFC00) + +#define MALI_INVALID_PAGE ((u32)(~0)) + +/** + * + */ +typedef enum mali_mmu_entry_flags +{ + MALI_MMU_FLAGS_PRESENT = 0x01, + MALI_MMU_FLAGS_READ_PERMISSION = 0x02, + MALI_MMU_FLAGS_WRITE_PERMISSION = 0x04, + MALI_MMU_FLAGS_OVERRIDE_CACHE = 0x8, + MALI_MMU_FLAGS_WRITE_CACHEABLE = 0x10, + MALI_MMU_FLAGS_WRITE_ALLOCATE = 0x20, + MALI_MMU_FLAGS_WRITE_BUFFERABLE = 0x40, + MALI_MMU_FLAGS_READ_CACHEABLE = 0x80, + MALI_MMU_FLAGS_READ_ALLOCATE = 0x100, + MALI_MMU_FLAGS_MASK = 0x1FF, +} mali_mmu_entry_flags; + + +#define MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE ( \ +MALI_MMU_FLAGS_PRESENT | \ + MALI_MMU_FLAGS_READ_PERMISSION | \ + MALI_MMU_FLAGS_WRITE_PERMISSION | \ + MALI_MMU_FLAGS_OVERRIDE_CACHE | \ + MALI_MMU_FLAGS_WRITE_CACHEABLE | \ + MALI_MMU_FLAGS_WRITE_BUFFERABLE | \ + MALI_MMU_FLAGS_READ_CACHEABLE | \ + MALI_MMU_FLAGS_READ_ALLOCATE ) + + +struct mali_page_directory +{ + u32 page_directory; /**< Physical address of the memory session's page directory */ + mali_io_address page_directory_mapped; /**< Pointer to the mapped version of the page directory into the kernel's address space */ + + mali_io_address page_entries_mapped[1024]; /**< Pointers to the page tables which exists in the page directory mapped into the kernel's address space */ + u32 page_entries_usage_count[1024]; /**< Tracks usage count of the page table pages, so they can be releases on the last reference */ +}; + +/* Map Mali virtual address space (i.e. ensure page tables exist for the virtual range) */ +_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size); +_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size); + +/* Back virtual address space with actual pages. Assumes input is contiguous and 4k aligned. */ +void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size, u32 cache_settings); + +u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index); + +u32 mali_allocate_empty_page(void); +void mali_free_empty_page(u32 address); +_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page); +void mali_destroy_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page); + +struct mali_page_directory *mali_mmu_pagedir_alloc(void); +void mali_mmu_pagedir_free(struct mali_page_directory *pagedir); + +#endif /* __MALI_MMU_PAGE_DIRECTORY_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk.h b/drivers/media/video/samsung/mali/common/mali_osk.h new file mode 100644 index 0000000..e32d15d --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_osk.h @@ -0,0 +1,1798 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk.h + * Defines the OS abstraction layer for the kernel device driver (OSK) + */ + +#ifndef __MALI_OSK_H__ +#define __MALI_OSK_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @addtogroup uddapi Unified Device Driver (UDD) APIs + * + * @{ + */ + +/** + * @addtogroup oskapi UDD OS Abstraction for Kernel-side (OSK) APIs + * + * @{ + */ + +/** @defgroup _mali_osk_miscellaneous OSK Miscellaneous functions, constants and types + * @{ */ + +/* Define integer types used by OSK. Note: these currently clash with Linux so we only define them if not defined already */ +#ifndef __KERNEL__ + typedef unsigned char u8; + typedef signed char s8; + typedef unsigned short u16; + typedef signed short s16; + typedef unsigned int u32; + typedef signed int s32; + typedef unsigned long long u64; + #define BITS_PER_LONG (sizeof(long)*8) +#else + /* Ensure Linux types u32, etc. are defined */ + #include +#endif + +/** @brief Mali Boolean type which uses MALI_TRUE and MALI_FALSE + */ + typedef unsigned long mali_bool; + +#ifndef MALI_TRUE + #define MALI_TRUE ((mali_bool)1) +#endif + +#ifndef MALI_FALSE + #define MALI_FALSE ((mali_bool)0) +#endif + +/** + * @brief OSK Error codes + * + * Each OS may use its own set of error codes, and may require that the + * User/Kernel interface take certain error code. This means that the common + * error codes need to be sufficiently rich to pass the correct error code + * thorugh from the OSK to U/K layer, across all OSs. + * + * The result is that some error codes will appear redundant on some OSs. + * Under all OSs, the OSK layer must translate native OS error codes to + * _mali_osk_errcode_t codes. Similarly, the U/K layer must translate from + * _mali_osk_errcode_t codes to native OS error codes. + */ +typedef enum +{ + _MALI_OSK_ERR_OK = 0, /**< Success. */ + _MALI_OSK_ERR_FAULT = -1, /**< General non-success */ + _MALI_OSK_ERR_INVALID_FUNC = -2, /**< Invalid function requested through User/Kernel interface (e.g. bad IOCTL number) */ + _MALI_OSK_ERR_INVALID_ARGS = -3, /**< Invalid arguments passed through User/Kernel interface */ + _MALI_OSK_ERR_NOMEM = -4, /**< Insufficient memory */ + _MALI_OSK_ERR_TIMEOUT = -5, /**< Timeout occurred */ + _MALI_OSK_ERR_RESTARTSYSCALL = -6, /**< Special: On certain OSs, must report when an interruptable mutex is interrupted. Ignore otherwise. */ + _MALI_OSK_ERR_ITEM_NOT_FOUND = -7, /**< Table Lookup failed */ + _MALI_OSK_ERR_BUSY = -8, /**< Device/operation is busy. Try again later */ + _MALI_OSK_ERR_UNSUPPORTED = -9, /**< Optional part of the interface used, and is unsupported */ +} _mali_osk_errcode_t; + +/** @} */ /* end group _mali_osk_miscellaneous */ + + +/** @defgroup _mali_osk_irq OSK IRQ handling + * @{ */ + +/** @brief Private type for IRQ handling objects */ +typedef struct _mali_osk_irq_t_struct _mali_osk_irq_t; + +/** @brief Optional function to trigger an irq from a resource + * + * This function is implemented by the common layer to allow probing of a resource's IRQ. + * @param arg resource-specific data */ +typedef void (*_mali_osk_irq_trigger_t)( void * arg ); + +/** @brief Optional function to acknowledge an irq from a resource + * + * This function is implemented by the common layer to allow probing of a resource's IRQ. + * @param arg resource-specific data + * @return _MALI_OSK_ERR_OK if the IRQ was successful, or a suitable _mali_osk_errcode_t on failure. */ +typedef _mali_osk_errcode_t (*_mali_osk_irq_ack_t)( void * arg ); + +/** @brief IRQ 'upper-half' handler callback. + * + * This function is implemented by the common layer to do the initial handling of a + * resource's IRQ. This maps on to the concept of an ISR that does the minimum + * work necessary before handing off to an IST. + * + * The communication of the resource-specific data from the ISR to the IST is + * handled by the OSK implementation. + * + * On most systems, the IRQ upper-half handler executes in IRQ context. + * Therefore, the system may have restrictions about what can be done in this + * context + * + * If an IRQ upper-half handler requires more work to be done than can be + * acheived in an IRQ context, then it may defer the work with + * _mali_osk_irq_schedulework(). Refer to \ref _mali_osk_irq_schedulework() for + * more information. + * + * @param arg resource-specific data + * @return _MALI_OSK_ERR_OK if the IRQ was correctly handled, or a suitable + * _mali_osk_errcode_t otherwise. + */ +typedef _mali_osk_errcode_t (*_mali_osk_irq_uhandler_t)( void * arg ); + +/** @brief IRQ 'bottom-half' handler callback. + * + * This function is implemented by the common layer to do the deferred handling + * of a resource's IRQ. Usually, this work cannot be carried out in IRQ context + * by the IRQ upper-half handler. + * + * The IRQ bottom-half handler maps on to the concept of an IST that may + * execute some time after the actual IRQ has fired. + * + * All OSK-registered IRQ bottom-half handlers will be serialized, across all + * CPU-cores in the system. + * + * Refer to \ref _mali_osk_irq_schedulework() for more information on the + * IRQ work-queue, and the calling of the IRQ bottom-half handler. + * + * @param arg resource-specific data + */ +typedef void (*_mali_osk_irq_bhandler_t)( void * arg ); +/** @} */ /* end group _mali_osk_irq */ + + +/** @defgroup _mali_osk_atomic OSK Atomic counters + * @{ */ + +/** @brief Public type of atomic counters + * + * This is public for allocation on stack. On systems that support it, this is just a single 32-bit value. + * On others, it could be encapsulating an object stored elsewhere. + * + * Regardless of implementation, the \ref _mali_osk_atomic functions \b must be used + * for all accesses to the variable's value, even if atomicity is not required. + * Do not access u.val or u.obj directly. + */ +typedef struct +{ + union + { + u32 val; + void *obj; + } u; +} _mali_osk_atomic_t; +/** @} */ /* end group _mali_osk_atomic */ + + +/** @defgroup _mali_osk_lock OSK Mutual Exclusion Locks + * @{ */ + + +/** @brief OSK Mutual Exclusion Lock ordered list + * + * This lists the various types of locks in the system and is used to check + * that locks are taken in the correct order. + * + * Holding more than one lock of the same order at the same time is not + * allowed. + * + */ +typedef enum +{ + _MALI_OSK_LOCK_ORDER_LAST = 0, + + _MALI_OSK_LOCK_ORDER_PM_EXECUTE, + _MALI_OSK_LOCK_ORDER_UTILIZATION, + _MALI_OSK_LOCK_ORDER_L2_COUNTER, + _MALI_OSK_LOCK_ORDER_PROFILING, + _MALI_OSK_LOCK_ORDER_L2_COMMAND, + _MALI_OSK_LOCK_ORDER_PM_CORE_STATE, + _MALI_OSK_LOCK_ORDER_GROUP, + _MALI_OSK_LOCK_ORDER_SCHEDULER, + + _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP, + _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE, + _MALI_OSK_LOCK_ORDER_MEM_INFO, + _MALI_OSK_LOCK_ORDER_MEM_SESSION, + + _MALI_OSK_LOCK_ORDER_SESSIONS, + + _MALI_OSK_LOCK_ORDER_FIRST +} _mali_osk_lock_order_t; + + +/** @brief OSK Mutual Exclusion Lock flags type + * + * Flags are supplied at the point where the Lock is initialized. Each flag can + * be combined with others using bitwise OR, '|'. + * + * The flags must be sufficiently rich to cope with all our OSs. This means + * that on some OSs, certain flags can be completely ignored. We define a + * number of terms that are significant across all OSs: + * + * - Sleeping/non-sleeping mutexs. Sleeping mutexs can block on waiting, and so + * schedule out the current thread. This is significant on OSs where there are + * situations in which the current thread must not be put to sleep. On OSs + * without this restriction, sleeping and non-sleeping mutexes can be treated + * as the same (if that is required). + * - Interruptable/non-interruptable mutexes. For sleeping mutexes, it may be + * possible for the sleep to be interrupted for a reason other than the thread + * being able to obtain the lock. OSs behaving in this way may provide a + * mechanism to control whether sleeping mutexes can be interrupted. On OSs + * that do not support the concept of interruption, \b or they do not support + * control of mutex interruption, then interruptable mutexes may be treated + * as non-interruptable. + * + * Some constrains apply to the lock type flags: + * + * - Spinlocks are by nature, non-interruptable. Hence, they must always be + * combined with the NONINTERRUPTABLE flag, because it is meaningless to ask + * for a spinlock that is interruptable (and this highlights its + * non-interruptable-ness). For example, on certain OSs they should be used when + * you must not sleep. + * - Reader/writer is an optimization hint, and any type of lock can be + * reader/writer. Since this is an optimization hint, the implementation need + * not respect this for any/all types of lock. For example, on certain OSs, + * there's no interruptable reader/writer mutex. If such a thing were requested + * on that OS, the fact that interruptable was requested takes priority over the + * reader/writer-ness, because reader/writer-ness is not necessary for correct + * operation. + * - Any lock can use the order parameter. + * - A onelock is an optimization hint specific to certain OSs. It can be + * specified when it is known that only one lock will be held by the thread, + * and so can provide faster mutual exclusion. This can be safely ignored if + * such optimization is not required/present. + * + * The absence of any flags (the value 0) results in a sleeping-mutex, which is interruptable. + */ +typedef enum +{ + _MALI_OSK_LOCKFLAG_SPINLOCK = 0x1, /**< Specifically, don't sleep on those architectures that require it */ + _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE = 0x2, /**< The mutex cannot be interrupted, e.g. delivery of signals on those architectures where this is required */ + _MALI_OSK_LOCKFLAG_READERWRITER = 0x4, /**< Optimise for readers/writers */ + _MALI_OSK_LOCKFLAG_ORDERED = 0x8, /**< Use the order parameter; otherwise use automatic ordering */ + _MALI_OSK_LOCKFLAG_ONELOCK = 0x10, /**< Each thread can only hold one lock at a time */ + _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ = 0x20, /**< IRQ version of spinlock */ + /** @enum _mali_osk_lock_flags_t + * + * Flags from 0x10000--0x80000000 are RESERVED for User-mode */ + +} _mali_osk_lock_flags_t; + +/** @brief Mutual Exclusion Lock Mode Optimization hint + * + * The lock mode is used to implement the read/write locking of locks specified + * as _MALI_OSK_LOCKFLAG_READERWRITER. In this case, the RO mode can be used + * to allow multiple concurrent readers, but no writers. The RW mode is used for + * writers, and so will wait for all readers to release the lock (if any present). + * Further readers and writers will wait until the writer releases the lock. + * + * The mode is purely an optimization hint: for example, it is permissible for + * all locks to behave in RW mode, regardless of that supplied. + * + * It is an error to attempt to use locks in anything other that RW mode when + * _MALI_OSK_LOCKFLAG_READERWRITER is not supplied. + * + */ +typedef enum +{ + _MALI_OSK_LOCKMODE_UNDEF = -1, /**< Undefined lock mode. For internal use only */ + _MALI_OSK_LOCKMODE_RW = 0x0, /**< Read-write mode, default. All readers and writers are mutually-exclusive */ + _MALI_OSK_LOCKMODE_RO, /**< Read-only mode, to support multiple concurrent readers, but mutual exclusion in the presence of writers. */ + /** @enum _mali_osk_lock_mode_t + * + * Lock modes 0x40--0x7F are RESERVED for User-mode */ +} _mali_osk_lock_mode_t; + +/** @brief Private type for Mutual Exclusion lock objects */ +typedef struct _mali_osk_lock_t_struct _mali_osk_lock_t; + +#ifdef DEBUG +/** @brief Macro for asserting that the current thread holds a given lock + */ +#define MALI_DEBUG_ASSERT_LOCK_HELD(l) MALI_DEBUG_ASSERT(_mali_osk_lock_get_owner(l) == _mali_osk_get_tid()); + +/** @brief returns a lock's owner (thread id) if debugging is enabled + */ +u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock ); +#endif + +/** @} */ /* end group _mali_osk_lock */ + +/** @defgroup _mali_osk_low_level_memory OSK Low-level Memory Operations + * @{ */ + +/** + * @brief Private data type for use in IO accesses to/from devices. + * + * This represents some range that is accessible from the device. Examples + * include: + * - Device Registers, which could be readable and/or writeable. + * - Memory that the device has access to, for storing configuration structures. + * + * Access to this range must be made through the _mali_osk_mem_ioread32() and + * _mali_osk_mem_iowrite32() functions. + */ +typedef struct _mali_io_address * mali_io_address; + +/** @defgroup _MALI_OSK_CPU_PAGE CPU Physical page size macros. + * + * The order of the page size is supplied for + * ease of use by algorithms that might require it, since it is easier to know + * it ahead of time rather than calculating it. + * + * The Mali Page Mask macro masks off the lower bits of a physical address to + * give the start address of the page for that physical address. + * + * @note The Mali device driver code is designed for systems with 4KB page size. + * Changing these macros will not make the entire Mali device driver work with + * page sizes other than 4KB. + * + * @note The CPU Physical Page Size has been assumed to be the same as the Mali + * Physical Page Size. + * + * @{ + */ + +/** CPU Page Order, as log to base 2 of the Page size. @see _MALI_OSK_CPU_PAGE_SIZE */ +#define _MALI_OSK_CPU_PAGE_ORDER ((u32)12) +/** CPU Page Size, in bytes. */ +#define _MALI_OSK_CPU_PAGE_SIZE (((u32)1) << (_MALI_OSK_CPU_PAGE_ORDER)) +/** CPU Page Mask, which masks off the offset within a page */ +#define _MALI_OSK_CPU_PAGE_MASK (~((((u32)1) << (_MALI_OSK_CPU_PAGE_ORDER)) - ((u32)1))) +/** @} */ /* end of group _MALI_OSK_CPU_PAGE */ + +/** @defgroup _MALI_OSK_MALI_PAGE Mali Physical Page size macros + * + * Mali Physical page size macros. The order of the page size is supplied for + * ease of use by algorithms that might require it, since it is easier to know + * it ahead of time rather than calculating it. + * + * The Mali Page Mask macro masks off the lower bits of a physical address to + * give the start address of the page for that physical address. + * + * @note The Mali device driver code is designed for systems with 4KB page size. + * Changing these macros will not make the entire Mali device driver work with + * page sizes other than 4KB. + * + * @note The Mali Physical Page Size has been assumed to be the same as the CPU + * Physical Page Size. + * + * @{ + */ + +/** Mali Page Order, as log to base 2 of the Page size. @see _MALI_OSK_MALI_PAGE_SIZE */ +#define _MALI_OSK_MALI_PAGE_ORDER ((u32)12) +/** Mali Page Size, in bytes. */ +#define _MALI_OSK_MALI_PAGE_SIZE (((u32)1) << (_MALI_OSK_MALI_PAGE_ORDER)) +/** Mali Page Mask, which masks off the offset within a page */ +#define _MALI_OSK_MALI_PAGE_MASK (~((((u32)1) << (_MALI_OSK_MALI_PAGE_ORDER)) - ((u32)1))) +/** @} */ /* end of group _MALI_OSK_MALI_PAGE*/ + +/** @brief flags for mapping a user-accessible memory range + * + * Where a function with prefix '_mali_osk_mem_mapregion' accepts flags as one + * of the function parameters, it will use one of these. These allow per-page + * control over mappings. Compare with the mali_memory_allocation_flag type, + * which acts over an entire range + * + * These may be OR'd together with bitwise OR (|), but must be cast back into + * the type after OR'ing. + */ +typedef enum +{ + _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR = 0x1, /**< Physical address is OS Allocated */ +} _mali_osk_mem_mapregion_flags_t; +/** @} */ /* end group _mali_osk_low_level_memory */ + +/** @defgroup _mali_osk_notification OSK Notification Queues + * @{ */ + +/** @brief Private type for notification queue objects */ +typedef struct _mali_osk_notification_queue_t_struct _mali_osk_notification_queue_t; + +/** @brief Public notification data object type */ +typedef struct _mali_osk_notification_t_struct +{ + u32 notification_type; /**< The notification type */ + u32 result_buffer_size; /**< Size of the result buffer to copy to user space */ + void * result_buffer; /**< Buffer containing any type specific data */ +} _mali_osk_notification_t; + +/** @} */ /* end group _mali_osk_notification */ + + +/** @defgroup _mali_osk_timer OSK Timer Callbacks + * @{ */ + +/** @brief Function to call when a timer expires + * + * When a timer expires, this function is called. Note that on many systems, + * a timer callback will be executed in IRQ context. Therefore, restrictions + * may apply on what can be done inside the timer callback. + * + * If a timer requires more work to be done than can be acheived in an IRQ + * context, then it may defer the work with a work-queue. For example, it may + * use \ref _mali_osk_irq_schedulework() to make use of the IRQ bottom-half handler + * to carry out the remaining work. + * + * Stopping the timer with \ref _mali_osk_timer_del() blocks on compeletion of + * the callback. Therefore, the callback may not obtain any mutexes also held + * by any callers of _mali_osk_timer_del(). Otherwise, a deadlock may occur. + * + * @param arg Function-specific data */ +typedef void (*_mali_osk_timer_callback_t)(void * arg ); + +/** @brief Private type for Timer Callback Objects */ +typedef struct _mali_osk_timer_t_struct _mali_osk_timer_t; +/** @} */ /* end group _mali_osk_timer */ + + +/** @addtogroup _mali_osk_list OSK Doubly-Linked Circular Lists + * @{ */ + +/** @brief Public List objects. + * + * To use, add a _mali_osk_list_t member to the structure that may become part + * of a list. When traversing the _mali_osk_list_t objects, use the + * _MALI_OSK_CONTAINER_OF() macro to recover the structure from its + *_mali_osk_list_t member + * + * Each structure may have multiple _mali_osk_list_t members, so that the + * structure is part of multiple lists. When traversing lists, ensure that the + * correct _mali_osk_list_t member is used, because type-checking will be + * lost by the compiler. + */ +typedef struct _mali_osk_list_s +{ + struct _mali_osk_list_s *next; + struct _mali_osk_list_s *prev; +} _mali_osk_list_t; + +/** @brief Initialize a list to be a head of an empty list + * @param exp the list to initialize. */ +#define _MALI_OSK_INIT_LIST_HEAD(exp) _mali_osk_list_init(exp) + +/** @brief Define a list variable, which is uninitialized. + * @param exp the name of the variable that the list will be defined as. */ +#define _MALI_OSK_LIST_HEAD(exp) _mali_osk_list_t exp + +/** @brief Find the containing structure of another structure + * + * This is the reverse of the operation 'offsetof'. This means that the + * following condition is satisfied: + * + * ptr == _MALI_OSK_CONTAINER_OF( &ptr->member, type, member ) + * + * When ptr is of type 'type'. + * + * Its purpose it to recover a larger structure that has wrapped a smaller one. + * + * @note no type or memory checking occurs to ensure that a wrapper structure + * does in fact exist, and that it is being recovered with respect to the + * correct member. + * + * @param ptr the pointer to the member that is contained within the larger + * structure + * @param type the type of the structure that contains the member + * @param member the name of the member in the structure that ptr points to. + * @return a pointer to a \a type object which contains \a member, as pointed + * to by \a ptr. + */ +#define _MALI_OSK_CONTAINER_OF(ptr, type, member) \ + ((type *)( ((char *)ptr) - offsetof(type,member) )) + +/** @brief Find the containing structure of a list + * + * When traversing a list, this is used to recover the containing structure, + * given that is contains a _mali_osk_list_t member. + * + * Each list must be of structures of one type, and must link the same members + * together, otherwise it will not be possible to correctly recover the + * sturctures that the lists link. + * + * @note no type or memory checking occurs to ensure that a structure does in + * fact exist for the list entry, and that it is being recovered with respect + * to the correct list member. + * + * @param ptr the pointer to the _mali_osk_list_t member in this structure + * @param type the type of the structure that contains the member + * @param member the member of the structure that ptr points to. + * @return a pointer to a \a type object which contains the _mali_osk_list_t + * \a member, as pointed to by the _mali_osk_list_t \a *ptr. + */ +#define _MALI_OSK_LIST_ENTRY(ptr, type, member) \ + _MALI_OSK_CONTAINER_OF(ptr, type, member) + +/** @brief Enumerate a list safely + * + * With this macro, lists can be enumerated in a 'safe' manner. That is, + * entries can be deleted from the list without causing an error during + * enumeration. To achieve this, a 'temporary' pointer is required, which must + * be provided to the macro. + * + * Use it like a 'for()', 'while()' or 'do()' construct, and so it must be + * followed by a statement or compound-statement which will be executed for + * each list entry. + * + * Upon loop completion, providing that an early out was not taken in the + * loop body, then it is guaranteed that ptr->member == list, even if the loop + * body never executed. + * + * @param ptr a pointer to an object of type 'type', which points to the + * structure that contains the currently enumerated list entry. + * @param tmp a pointer to an object of type 'type', which must not be used + * inside the list-execution statement. + * @param list a pointer to a _mali_osk_list_t, from which enumeration will + * begin + * @param type the type of the structure that contains the _mali_osk_list_t + * member that is part of the list to be enumerated. + * @param member the _mali_osk_list_t member of the structure that is part of + * the list to be enumerated. + */ +#define _MALI_OSK_LIST_FOREACHENTRY(ptr, tmp, list, type, member) \ + for (ptr = _MALI_OSK_LIST_ENTRY((list)->next, type, member), \ + tmp = _MALI_OSK_LIST_ENTRY(ptr->member.next, type, member); \ + &ptr->member != (list); \ + ptr = tmp, tmp = _MALI_OSK_LIST_ENTRY(tmp->member.next, type, member)) +/** @} */ /* end group _mali_osk_list */ + + +/** @addtogroup _mali_osk_miscellaneous + * @{ */ + +/** @brief The known resource types + * + * @note \b IMPORTANT: these must remain fixed, and only be extended. This is + * because not all systems use a header file for reading in their resources. + * The resources may instead come from a data file where these resources are + * 'hard-coded' in, because there's no easy way of transferring the enum values + * into such data files. E.g. the C-Pre-processor does \em not process enums. + */ +typedef enum _mali_osk_resource_type +{ + RESOURCE_TYPE_FIRST =0, /**< Duplicate resource marker for the first resource*/ + + MEMORY =0, /**< Physically contiguous memory block, not managed by the OS */ + OS_MEMORY =1, /**< Memory managed by and shared with the OS */ + + MALI_PP =2, /**< Mali Pixel Processor core */ + MALI450PP =2, /**< Compatibility option */ + MALI400PP =2, /**< Compatibility option */ + MALI300PP =2, /**< Compatibility option */ + MALI200 =2, /**< Compatibility option */ + + MALI_GP =3, /**< Mali Geometry Processor core */ + MALI450GP =3, /**< Compatibility option */ + MALI400GP =3, /**< Compatibility option */ + MALI300GP =3, /**< Compatibility option */ + MALIGP2 =3, /**< Compatibility option */ + + MMU =4, /**< Mali MMU (Memory Management Unit) */ + + FPGA_FRAMEWORK =5, /**< Mali registers specific to FPGA implementations */ + + MALI_L2 =6, /**< Mali Level 2 cache core */ + MALI450L2 =6, /**< Compatibility option */ + MALI400L2 =6, /**< Compatibility option */ + MALI300L2 =6, /**< Compatibility option */ + + MEM_VALIDATION =7, /**< External Memory Validator */ + + PMU =8, /**< Power Manangement Unit */ + + RESOURCE_TYPE_COUNT /**< The total number of known resources */ +} _mali_osk_resource_type_t; + +/** @brief resource description struct + * + * _mali_osk_resources_init() will enumerate objects of this type. Not all + * members have a valid meaning across all types. + * + * The mmu_id is used to group resources to a certain MMU, since there may be + * more than one MMU in the system, and each resource may be using a different + * MMU: + * - For MMU resources, the setting of mmu_id is a uniquely identifying number. + * - For Other resources, the setting of mmu_id determines which MMU the + * resource uses. + */ +typedef struct _mali_osk_resource +{ + _mali_osk_resource_type_t type; /**< type of the resource */ + const char * description; /**< short description of the resource */ + u32 base; /**< Physical base address of the resource, as seen by Mali resources. */ + s32 cpu_usage_adjust; /**< Offset added to the base address of the resource to arrive at the CPU physical address of the resource (if different from the Mali physical address) */ + u32 size; /**< Size in bytes of the resource - either the size of its register range, or the size of the memory block. */ + u32 irq; /**< IRQ number delivered to the CPU, or -1 to tell the driver to probe for it (if possible) */ + u32 flags; /**< Resources-specific flags. */ + u32 mmu_id; /**< Identifier for Mali MMU resources. */ + u32 alloc_order; /**< Order in which MEMORY/OS_MEMORY resources are used */ +} _mali_osk_resource_t; +/** @} */ /* end group _mali_osk_miscellaneous */ + + +#include "mali_kernel_memory_engine.h" /* include for mali_memory_allocation and mali_physical_memory_allocation type */ + +/** @addtogroup _mali_osk_irq + * @{ */ + +/** @brief Fake IRQ number for testing purposes + */ +#define _MALI_OSK_IRQ_NUMBER_FAKE ((u32)0xFFFFFFF1) + +/** @addtogroup _mali_osk_irq + * @{ */ + +/** @brief PMM Virtual IRQ number + */ +#define _MALI_OSK_IRQ_NUMBER_PMM ((u32)0xFFFFFFF2) + + +/** @brief Initialize IRQ handling for a resource + * + * The _mali_osk_irq_t returned must be written into the resource-specific data + * pointed to by data. This is so that the upper and lower handlers can call + * _mali_osk_irq_schedulework(). + * + * @note The caller must ensure that the resource does not generate an + * interrupt after _mali_osk_irq_init() finishes, and before the + * _mali_osk_irq_t is written into the resource-specific data. Otherwise, + * the upper-half handler will fail to call _mali_osk_irq_schedulework(). + * + * @param irqnum The IRQ number that the resource uses, as seen by the CPU. + * The value -1 has a special meaning which indicates the use of probing, and trigger_func and ack_func must be + * non-NULL. + * @param uhandler The upper-half handler, corresponding to a ISR handler for + * the resource + * @param bhandler The lower-half handler, corresponding to an IST handler for + * the resource + * @param trigger_func Optional: a function to trigger the resource's irq, to + * probe for the interrupt. Use NULL if irqnum != -1. + * @param ack_func Optional: a function to acknowledge the resource's irq, to + * probe for the interrupt. Use NULL if irqnum != -1. + * @param data resource-specific data, which will be passed to uhandler, + * bhandler and (if present) trigger_func and ack_funnc + * @param description textual description of the IRQ resource. + * @return on success, a pointer to a _mali_osk_irq_t object, which represents + * the IRQ handling on this resource. NULL on failure. + */ +_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, _mali_osk_irq_bhandler_t bhandler, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *data, const char *description ); + +/** @brief Cause a queued, deferred call of the IRQ bottom-half. + * + * _mali_osk_irq_schedulework provides a mechanism for enqueuing deferred calls + * to the IRQ bottom-half handler. The queue is known as the IRQ work-queue. + * After calling _mali_osk_irq_schedulework(), the IRQ bottom-half handler will + * be scheduled to run at some point in the future. + * + * This is called by the IRQ upper-half to defer further processing of + * IRQ-related work to the IRQ bottom-half handler. This is necessary for work + * that cannot be done in an IRQ context by the IRQ upper-half handler. Timer + * callbacks also use this mechanism, because they are treated as though they + * operate in an IRQ context. Refer to \ref _mali_osk_timer_t for more + * information. + * + * Code that operates in a kernel-process context (with no IRQ context + * restrictions) may also enqueue deferred calls to the IRQ bottom-half. The + * advantage over direct calling is that deferred calling allows the caller and + * IRQ bottom half to hold the same mutex, with a guarantee that they will not + * deadlock just by using this mechanism. + * + * _mali_osk_irq_schedulework() places deferred call requests on a queue, to + * allow for more than one thread to make a deferred call. Therfore, if it is + * called 'K' times, then the IRQ bottom-half will be scheduled 'K' times too. + * 'K' is a number that is implementation-specific. + * + * _mali_osk_irq_schedulework() is guaranteed to not block on: + * - enqueuing a deferred call request. + * - the completion of the IRQ bottom-half handler. + * + * This is to prevent deadlock. For example, if _mali_osk_irq_schedulework() + * blocked, then it would cause a deadlock when the following two conditions + * hold: + * - The IRQ bottom-half callback (of type _mali_osk_irq_bhandler_t) locks + * a mutex + * - And, at the same time, the caller of _mali_osk_irq_schedulework() also + * holds the same mutex + * + * @note care must be taken to not overflow the queue that + * _mali_osk_irq_schedulework() operates on. Code must be structured to + * ensure that the number of requests made to the queue is bounded. Otherwise, + * IRQs will be lost. + * + * The queue that _mali_osk_irq_schedulework implements is a FIFO of N-writer, + * 1-reader type. The writers are the callers of _mali_osk_irq_schedulework + * (all OSK-registered IRQ upper-half handlers in the system, watchdog timers, + * callers from a Kernel-process context). The reader is a single thread that + * handles all OSK-registered IRQs. + * + * The consequence of the queue being a 1-reader type is that calling + * _mali_osk_irq_schedulework() on different _mali_osk_irq_t objects causes + * their IRQ bottom-halves to be serialized, across all CPU-cores in the + * system. + * + * @param irq a pointer to the _mali_osk_irq_t object corresponding to the + * resource whose IRQ bottom-half must begin processing. + */ +void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq ); + +/** @brief Terminate IRQ handling on a resource. + * + * This will disable the interrupt from the device, and then waits for the + * IRQ work-queue to finish the work that is currently in the queue. That is, + * for every deferred call currently in the IRQ work-queue, it waits for each + * of those to be processed by their respective IRQ bottom-half handler. + * + * This function is used to ensure that the bottom-half handler of the supplied + * IRQ object will not be running at the completion of this function call. + * However, the caller must ensure that no other sources could call the + * _mali_osk_irq_schedulework() on the same IRQ object. For example, the + * relevant timers must be stopped. + * + * @note While this function is being called, other OSK-registered IRQs in the + * system may enqueue work for their respective bottom-half handlers. This + * function will not wait for those entries in the work-queue to be flushed. + * + * Since this blocks on the completion of work in the IRQ work-queue, the + * caller of this function \b must \b not hold any mutexes that are taken by + * any OSK-registered IRQ bottom-half handler. To do so may cause a deadlock. + * + * @param irq a pointer to the _mali_osk_irq_t object corresponding to the + * resource whose IRQ handling is to be terminated. + */ +void _mali_osk_irq_term( _mali_osk_irq_t *irq ); + +/** @brief flushing workqueue. + * + * This will flush the workqueue. + * + * @param irq a pointer to the _mali_osk_irq_t object corresponding to the + * resource whose IRQ handling is to be terminated. + */ +void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq ); + +/** @} */ /* end group _mali_osk_irq */ + + +/** @addtogroup _mali_osk_atomic + * @{ */ + +/** @brief Decrement an atomic counter + * + * @note It is an error to decrement the counter beyond -(1<<23) + * + * @param atom pointer to an atomic counter */ +void _mali_osk_atomic_dec( _mali_osk_atomic_t *atom ); + +/** @brief Decrement an atomic counter, return new value + * + * @param atom pointer to an atomic counter + * @return The new value, after decrement */ +u32 _mali_osk_atomic_dec_return( _mali_osk_atomic_t *atom ); + +/** @brief Increment an atomic counter + * + * @note It is an error to increment the counter beyond (1<<23)-1 + * + * @param atom pointer to an atomic counter */ +void _mali_osk_atomic_inc( _mali_osk_atomic_t *atom ); + +/** @brief Increment an atomic counter, return new value + * + * @param atom pointer to an atomic counter */ +u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom ); + +/** @brief Initialize an atomic counter + * + * @note the parameter required is a u32, and so signed integers should be + * cast to u32. + * + * @param atom pointer to an atomic counter + * @param val the value to initialize the atomic counter. + * @return _MALI_OSK_ERR_OK on success, otherwise, a suitable + * _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_osk_atomic_init( _mali_osk_atomic_t *atom, u32 val ); + +/** @brief Read a value from an atomic counter + * + * This can only be safely used to determine the value of the counter when it + * is guaranteed that other threads will not be modifying the counter. This + * makes its usefulness limited. + * + * @param atom pointer to an atomic counter + */ +u32 _mali_osk_atomic_read( _mali_osk_atomic_t *atom ); + +/** @brief Terminate an atomic counter + * + * @param atom pointer to an atomic counter + */ +void _mali_osk_atomic_term( _mali_osk_atomic_t *atom ); +/** @} */ /* end group _mali_osk_atomic */ + + +/** @defgroup _mali_osk_memory OSK Memory Allocation + * @{ */ + +/** @brief Allocate zero-initialized memory. + * + * Returns a buffer capable of containing at least \a n elements of \a size + * bytes each. The buffer is initialized to zero. + * + * If there is a need for a bigger block of memory (16KB or bigger), then + * consider to use _mali_osk_vmalloc() instead, as this function might + * map down to a OS function with size limitations. + * + * The buffer is suitably aligned for storage and subsequent access of every + * type that the compiler supports. Therefore, the pointer to the start of the + * buffer may be cast into any pointer type, and be subsequently accessed from + * such a pointer, without loss of information. + * + * When the buffer is no longer in use, it must be freed with _mali_osk_free(). + * Failure to do so will cause a memory leak. + * + * @note Most toolchains supply memory allocation functions that meet the + * compiler's alignment requirements. + * + * @param n Number of elements to allocate + * @param size Size of each element + * @return On success, the zero-initialized buffer allocated. NULL on failure + */ +void *_mali_osk_calloc( u32 n, u32 size ); + +/** @brief Allocate memory. + * + * Returns a buffer capable of containing at least \a size bytes. The + * contents of the buffer are undefined. + * + * If there is a need for a bigger block of memory (16KB or bigger), then + * consider to use _mali_osk_vmalloc() instead, as this function might + * map down to a OS function with size limitations. + * + * The buffer is suitably aligned for storage and subsequent access of every + * type that the compiler supports. Therefore, the pointer to the start of the + * buffer may be cast into any pointer type, and be subsequently accessed from + * such a pointer, without loss of information. + * + * When the buffer is no longer in use, it must be freed with _mali_osk_free(). + * Failure to do so will cause a memory leak. + * + * @note Most toolchains supply memory allocation functions that meet the + * compiler's alignment requirements. + * + * Remember to free memory using _mali_osk_free(). + * @param size Number of bytes to allocate + * @return On success, the buffer allocated. NULL on failure. + */ +void *_mali_osk_malloc( u32 size ); + +/** @brief Free memory. + * + * Reclaims the buffer pointed to by the parameter \a ptr for the system. + * All memory returned from _mali_osk_malloc() and _mali_osk_calloc() + * must be freed before the application exits. Otherwise, + * a memory leak will occur. + * + * Memory must be freed once. It is an error to free the same non-NULL pointer + * more than once. + * + * It is legal to free the NULL pointer. + * + * @param ptr Pointer to buffer to free + */ +void _mali_osk_free( void *ptr ); + +/** @brief Allocate memory. + * + * Returns a buffer capable of containing at least \a size bytes. The + * contents of the buffer are undefined. + * + * This function is potentially slower than _mali_osk_malloc() and _mali_osk_calloc(), + * but do support bigger sizes. + * + * The buffer is suitably aligned for storage and subsequent access of every + * type that the compiler supports. Therefore, the pointer to the start of the + * buffer may be cast into any pointer type, and be subsequently accessed from + * such a pointer, without loss of information. + * + * When the buffer is no longer in use, it must be freed with _mali_osk_free(). + * Failure to do so will cause a memory leak. + * + * @note Most toolchains supply memory allocation functions that meet the + * compiler's alignment requirements. + * + * Remember to free memory using _mali_osk_free(). + * @param size Number of bytes to allocate + * @return On success, the buffer allocated. NULL on failure. + */ +void *_mali_osk_valloc( u32 size ); + +/** @brief Free memory. + * + * Reclaims the buffer pointed to by the parameter \a ptr for the system. + * All memory returned from _mali_osk_valloc() must be freed before the + * application exits. Otherwise a memory leak will occur. + * + * Memory must be freed once. It is an error to free the same non-NULL pointer + * more than once. + * + * It is legal to free the NULL pointer. + * + * @param ptr Pointer to buffer to free + */ +void _mali_osk_vfree( void *ptr ); + +/** @brief Copies memory. + * + * Copies the \a len bytes from the buffer pointed by the parameter \a src + * directly to the buffer pointed by \a dst. + * + * It is an error for \a src to overlap \a dst anywhere in \a len bytes. + * + * @param dst Pointer to the destination array where the content is to be + * copied. + * @param src Pointer to the source of data to be copied. + * @param len Number of bytes to copy. + * @return \a dst is always passed through unmodified. + */ +void *_mali_osk_memcpy( void *dst, const void *src, u32 len ); + +/** @brief Fills memory. + * + * Sets the first \a n bytes of the block of memory pointed to by \a s to + * the specified value + * @param s Pointer to the block of memory to fill. + * @param c Value to be set, passed as u32. Only the 8 Least Significant Bits (LSB) + * are used. + * @param n Number of bytes to be set to the value. + * @return \a s is always passed through unmodified + */ +void *_mali_osk_memset( void *s, u32 c, u32 n ); +/** @} */ /* end group _mali_osk_memory */ + + +/** @brief Checks the amount of memory allocated + * + * Checks that not more than \a max_allocated bytes are allocated. + * + * Some OS bring up an interactive out of memory dialogue when the + * system runs out of memory. This can stall non-interactive + * apps (e.g. automated test runs). This function can be used to + * not trigger the OOM dialogue by keeping allocations + * within a certain limit. + * + * @return MALI_TRUE when \a max_allocated bytes are not in use yet. MALI_FALSE + * when at least \a max_allocated bytes are in use. + */ +mali_bool _mali_osk_mem_check_allocated( u32 max_allocated ); + +/** @addtogroup _mali_osk_lock + * @{ */ + +/** @brief Initialize a Mutual Exclusion Lock + * + * Locks are created in the signalled (unlocked) state. + * + * initial must be zero, since there is currently no means of expressing + * whether a reader/writer lock should be initially locked as a reader or + * writer. This would require some encoding to be used. + * + * 'Automatic' ordering means that locks must be obtained in the order that + * they were created. For all locks that can be held at the same time, they must + * either all provide the order parameter, or they all must use 'automatic' + * ordering - because there is no way of mixing 'automatic' and 'manual' + * ordering. + * + * @param flags flags combined with bitwise OR ('|'), or zero. There are + * restrictions on which flags can be combined, @see _mali_osk_lock_flags_t. + * @param initial For future expansion into semaphores. SBZ. + * @param order The locking order of the mutex. That is, locks obtained by the + * same thread must have been created with an increasing order parameter, for + * deadlock prevention. Setting to zero causes 'automatic' ordering to be used. + * @return On success, a pointer to a _mali_osk_lock_t object. NULL on failure. + */ +_mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial, u32 order ); + +/** @brief Wait for a lock to be signalled (obtained) + + * After a thread has successfully waited on the lock, the lock is obtained by + * the thread, and is marked as unsignalled. The thread releases the lock by + * signalling it. + * + * In the case of Reader/Writer locks, multiple readers can obtain a lock in + * the absence of writers, which is a performance optimization (providing that + * the readers never write to the protected resource). + * + * To prevent deadlock, locks must always be obtained in the same order. + * + * For locks marked as _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, it is a + * programming error for the function to exit without obtaining the lock. This + * means that the error code must only be checked for interruptible locks. + * + * @param lock the lock to wait upon (obtain). + * @param mode the mode in which the lock should be obtained. Unless the lock + * was created with _MALI_OSK_LOCKFLAG_READERWRITER, this must be + * _MALI_OSK_LOCKMODE_RW. + * @return On success, _MALI_OSK_ERR_OK. For interruptible locks, a suitable + * _mali_osk_errcode_t will be returned on failure, and the lock will not be + * obtained. In this case, the error code must be propagated up to the U/K + * interface. + */ +_mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode); + + +/** @brief Signal (release) a lock + * + * Locks may only be signalled by the thread that originally waited upon the + * lock. + * + * @note In the OSU, a flag exists to allow any thread to signal a + * lock. Such functionality is not present in the OSK. + * + * @param lock the lock to signal (release). + * @param mode the mode in which the lock should be obtained. This must match + * the mode in which the lock was waited upon. + */ +void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ); + +/** @brief Terminate a lock + * + * This terminates a lock and frees all associated resources. + * + * It is a programming error to terminate the lock when it is held (unsignalled) + * by a thread. + * + * @param lock the lock to terminate. + */ +void _mali_osk_lock_term( _mali_osk_lock_t *lock ); +/** @} */ /* end group _mali_osk_lock */ + + +/** @addtogroup _mali_osk_low_level_memory + * @{ */ + +/** @brief Issue a memory barrier + * + * This defines an arbitrary memory barrier operation, which forces an ordering constraint + * on memory read and write operations. + */ +void _mali_osk_mem_barrier( void ); + +/** @brief Issue a write memory barrier + * + * This defines an write memory barrier operation which forces an ordering constraint + * on memory write operations. + */ +void _mali_osk_write_mem_barrier( void ); + +/** @brief Map a physically contiguous region into kernel space + * + * This is primarily used for mapping in registers from resources, and Mali-MMU + * page tables. The mapping is only visable from kernel-space. + * + * Access has to go through _mali_osk_mem_ioread32 and _mali_osk_mem_iowrite32 + * + * @param phys CPU-physical base address of the memory to map in. This must + * be aligned to the system's page size, which is assumed to be 4K. + * @param size the number of bytes of physically contiguous address space to + * map in + * @param description A textual description of the memory being mapped in. + * @return On success, a Mali IO address through which the mapped-in + * memory/registers can be accessed. NULL on failure. + */ +mali_io_address _mali_osk_mem_mapioregion( u32 phys, u32 size, const char *description ); + +/** @brief Unmap a physically contiguous address range from kernel space. + * + * The address range should be one previously mapped in through + * _mali_osk_mem_mapioregion. + * + * It is a programming error to do (but not limited to) the following: + * - attempt an unmap twice + * - unmap only part of a range obtained through _mali_osk_mem_mapioregion + * - unmap more than the range obtained through _mali_osk_mem_mapioregion + * - unmap an address range that was not successfully mapped using + * _mali_osk_mem_mapioregion + * - provide a mapping that does not map to phys. + * + * @param phys CPU-physical base address of the memory that was originally + * mapped in. This must be aligned to the system's page size, which is assumed + * to be 4K + * @param size The number of bytes that were originally mapped in. + * @param mapping The Mali IO address through which the mapping is + * accessed. + */ +void _mali_osk_mem_unmapioregion( u32 phys, u32 size, mali_io_address mapping ); + +/** @brief Allocate and Map a physically contiguous region into kernel space + * + * This is used for allocating physically contiguous regions (such as Mali-MMU + * page tables) and mapping them into kernel space. The mapping is only + * visible from kernel-space. + * + * The alignment of the returned memory is guaranteed to be at least + * _MALI_OSK_CPU_PAGE_SIZE. + * + * Access must go through _mali_osk_mem_ioread32 and _mali_osk_mem_iowrite32 + * + * @note This function is primarily to provide support for OSs that are + * incapable of separating the tasks 'allocate physically contiguous memory' + * and 'map it into kernel space' + * + * @param[out] phys CPU-physical base address of memory that was allocated. + * (*phys) will be guaranteed to be aligned to at least + * _MALI_OSK_CPU_PAGE_SIZE on success. + * + * @param[in] size the number of bytes of physically contiguous memory to + * allocate. This must be a multiple of _MALI_OSK_CPU_PAGE_SIZE. + * + * @return On success, a Mali IO address through which the mapped-in + * memory/registers can be accessed. NULL on failure, and (*phys) is unmodified. + */ +mali_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 size ); + +/** @brief Free a physically contiguous address range from kernel space. + * + * The address range should be one previously mapped in through + * _mali_osk_mem_allocioregion. + * + * It is a programming error to do (but not limited to) the following: + * - attempt a free twice on the same ioregion + * - free only part of a range obtained through _mali_osk_mem_allocioregion + * - free more than the range obtained through _mali_osk_mem_allocioregion + * - free an address range that was not successfully mapped using + * _mali_osk_mem_allocioregion + * - provide a mapping that does not map to phys. + * + * @param phys CPU-physical base address of the memory that was originally + * mapped in, which was aligned to _MALI_OSK_CPU_PAGE_SIZE. + * @param size The number of bytes that were originally mapped in, which was + * a multiple of _MALI_OSK_CPU_PAGE_SIZE. + * @param mapping The Mali IO address through which the mapping is + * accessed. + */ +void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address mapping ); + +/** @brief Request a region of physically contiguous memory + * + * This is used to ensure exclusive access to a region of physically contigous + * memory. + * + * It is acceptable to implement this as a stub. However, it is then the job + * of the System Integrator to ensure that no other device driver will be using + * the physical address ranges used by Mali, while the Mali device driver is + * loaded. + * + * @param phys CPU-physical base address of the memory to request. This must + * be aligned to the system's page size, which is assumed to be 4K. + * @param size the number of bytes of physically contiguous address space to + * request. + * @param description A textual description of the memory being requested. + * @return _MALI_OSK_ERR_OK on success. Otherwise, a suitable + * _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description ); + +/** @brief Un-request a region of physically contiguous memory + * + * This is used to release a regious of physically contiguous memory previously + * requested through _mali_osk_mem_reqregion, so that other device drivers may + * use it. This will be called at time of Mali device driver termination. + * + * It is a programming error to attempt to: + * - unrequest a region twice + * - unrequest only part of a range obtained through _mali_osk_mem_reqregion + * - unrequest more than the range obtained through _mali_osk_mem_reqregion + * - unrequest an address range that was not successfully requested using + * _mali_osk_mem_reqregion + * + * @param phys CPU-physical base address of the memory to un-request. This must + * be aligned to the system's page size, which is assumed to be 4K + * @param size the number of bytes of physically contiguous address space to + * un-request. + */ +void _mali_osk_mem_unreqregion( u32 phys, u32 size ); + +/** @brief Read from a location currently mapped in through + * _mali_osk_mem_mapioregion + * + * This reads a 32-bit word from a 32-bit aligned location. It is a programming + * error to provide unaligned locations, or to read from memory that is not + * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or + * _mali_osk_mem_allocioregion(). + * + * @param mapping Mali IO address to read from + * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4 + * @return the 32-bit word from the specified location. + */ +u32 _mali_osk_mem_ioread32( volatile mali_io_address mapping, u32 offset ); + +/** @brief Write to a location currently mapped in through + * _mali_osk_mem_mapioregion without memory barriers + * + * This write a 32-bit word to a 32-bit aligned location without using memory barrier. + * It is a programming error to provide unaligned locations, or to write to memory that is not + * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or + * _mali_osk_mem_allocioregion(). + * + * @param mapping Mali IO address to write to + * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4 + * @param val the 32-bit word to write. + */ +void _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val ); + +/** @brief Write to a location currently mapped in through + * _mali_osk_mem_mapioregion with write memory barrier + * + * This write a 32-bit word to a 32-bit aligned location. It is a programming + * error to provide unaligned locations, or to write to memory that is not + * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or + * _mali_osk_mem_allocioregion(). + * + * @param mapping Mali IO address to write to + * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4 + * @param val the 32-bit word to write. + */ +void _mali_osk_mem_iowrite32( volatile mali_io_address mapping, u32 offset, u32 val ); + +/** @brief Flush all CPU caches + * + * This should only be implemented if flushing of the cache is required for + * memory mapped in through _mali_osk_mem_mapregion. + */ +void _mali_osk_cache_flushall( void ); + +/** @brief Flush any caches necessary for the CPU and MALI to have the same view of a range of uncached mapped memory + * + * This should only be implemented if your OS doesn't do a full cache flush (inner & outer) + * after allocating uncached mapped memory. + * + * Some OS do not perform a full cache flush (including all outer caches) for uncached mapped memory. + * They zero the memory through a cached mapping, then flush the inner caches but not the outer caches. + * This is required for MALI to have the correct view of the memory. + */ +void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size ); + +/** @} */ /* end group _mali_osk_low_level_memory */ + + +/** @addtogroup _mali_osk_notification + * + * User space notification framework + * + * Communication with user space of asynchronous events is performed through a + * synchronous call to the \ref u_k_api. + * + * Since the events are asynchronous, the events have to be queued until a + * synchronous U/K API call can be made by user-space. A U/K API call might also + * be received before any event has happened. Therefore the notifications the + * different subsystems wants to send to user space has to be queued for later + * reception, or a U/K API call has to be blocked until an event has occured. + * + * Typical uses of notifications are after running of jobs on the hardware or + * when changes to the system is detected that needs to be relayed to user + * space. + * + * After an event has occured user space has to be notified using some kind of + * message. The notification framework supports sending messages to waiting + * threads or queueing of messages until a U/K API call is made. + * + * The notification queue is a FIFO. There are no restrictions on the numbers + * of readers or writers in the queue. + * + * A message contains what user space needs to identifiy how to handle an + * event. This includes a type field and a possible type specific payload. + * + * A notification to user space is represented by a + * \ref _mali_osk_notification_t object. A sender gets hold of such an object + * using _mali_osk_notification_create(). The buffer given by the + * _mali_osk_notification_t::result_buffer field in the object is used to store + * any type specific data. The other fields are internal to the queue system + * and should not be touched. + * + * @{ */ + +/** @brief Create a notification object + * + * Returns a notification object which can be added to the queue of + * notifications pending for user space transfer. + * + * The implementation will initialize all members of the + * \ref _mali_osk_notification_t object. In particular, the + * _mali_osk_notification_t::result_buffer member will be initialized to point + * to \a size bytes of storage, and that storage will be suitably aligned for + * storage of any structure. That is, the created buffer meets the same + * requirements as _mali_osk_malloc(). + * + * The notification object must be deleted when not in use. Use + * _mali_osk_notification_delete() for deleting it. + * + * @note You \b must \b not call _mali_osk_free() on a \ref _mali_osk_notification_t, + * object, or on a _mali_osk_notification_t::result_buffer. You must only use + * _mali_osk_notification_delete() to free the resources assocaited with a + * \ref _mali_osk_notification_t object. + * + * @param type The notification type + * @param size The size of the type specific buffer to send + * @return Pointer to a notification object with a suitable buffer, or NULL on error. + */ +_mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ); + +/** @brief Delete a notification object + * + * This must be called to reclaim the resources of a notification object. This + * includes: + * - The _mali_osk_notification_t::result_buffer + * - The \ref _mali_osk_notification_t itself. + * + * A notification object \b must \b not be used after it has been deleted by + * _mali_osk_notification_delete(). + * + * In addition, the notification object may not be deleted while it is in a + * queue. That is, if it has been placed on a queue with + * _mali_osk_notification_queue_send(), then it must not be deleted until + * it has been received by a call to _mali_osk_notification_queue_receive(). + * Otherwise, the queue may be corrupted. + * + * @param object the notification object to delete. + */ +void _mali_osk_notification_delete( _mali_osk_notification_t *object ); + +/** @brief Create a notification queue + * + * Creates a notification queue which can be used to queue messages for user + * delivery and get queued messages from + * + * The queue is a FIFO, and has no restrictions on the numbers of readers or + * writers. + * + * When the queue is no longer in use, it must be terminated with + * \ref _mali_osk_notification_queue_term(). Failure to do so will result in a + * memory leak. + * + * @return Pointer to a new notification queue or NULL on error. + */ +_mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void ); + +/** @brief Destroy a notification queue + * + * Destroys a notification queue and frees associated resources from the queue. + * + * A notification queue \b must \b not be destroyed in the following cases: + * - while there are \ref _mali_osk_notification_t objects in the queue. + * - while there are writers currently acting upon the queue. That is, while + * a thread is currently calling \ref _mali_osk_notification_queue_send() on + * the queue, or while a thread may call + * \ref _mali_osk_notification_queue_send() on the queue in the future. + * - while there are readers currently waiting upon the queue. That is, while + * a thread is currently calling \ref _mali_osk_notification_queue_receive() on + * the queue, or while a thread may call + * \ref _mali_osk_notification_queue_receive() on the queue in the future. + * + * Therefore, all \ref _mali_osk_notification_t objects must be flushed and + * deleted by the code that makes use of the notification queues, since only + * they know the structure of the _mali_osk_notification_t::result_buffer + * (even if it may only be a flat sturcture). + * + * @note Since the queue is a FIFO, the code using notification queues may + * create its own 'flush' type of notification, to assist in flushing the + * queue. + * + * Once the queue has been destroyed, it must not be used again. + * + * @param queue The queue to destroy + */ +void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue ); + +/** @brief Schedule notification for delivery + * + * When a \ref _mali_osk_notification_t object has been created successfully + * and set up, it may be added to the queue of objects waiting for user space + * transfer. + * + * The sending will not block if the queue is full. + * + * A \ref _mali_osk_notification_t object \b must \b not be put on two different + * queues at the same time, or enqueued twice onto a single queue before + * reception. However, it is acceptable for it to be requeued \em after reception + * from a call to _mali_osk_notification_queue_receive(), even onto the same queue. + * + * Again, requeuing must also not enqueue onto two different queues at the same + * time, or enqueue onto the same queue twice before reception. + * + * @param queue The notification queue to add this notification to + * @param object The entry to add + */ +void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object ); + +#if MALI_STATE_TRACKING +/** @brief Receive a notification from a queue + * + * Check if a notification queue is empty. + * + * @param queue The queue to check. + * @return MALI_TRUE if queue is empty, otherwise MALI_FALSE. + */ +mali_bool _mali_osk_notification_queue_is_empty( _mali_osk_notification_queue_t *queue ); +#endif + +/** @brief Receive a notification from a queue + * + * Receives a single notification from the given queue. + * + * If no notifciations are ready the thread will sleep until one becomes ready. + * Therefore, notifications may not be received into an + * IRQ or 'atomic' context (that is, a context where sleeping is disallowed). + * + * @param queue The queue to receive from + * @param result Pointer to storage of a pointer of type + * \ref _mali_osk_notification_t*. \a result will be written to such that the + * expression \a (*result) will evaluate to a pointer to a valid + * \ref _mali_osk_notification_t object, or NULL if none were received. + * @return _MALI_OSK_ERR_OK on success. _MALI_OSK_ERR_RESTARTSYSCALL if the sleep was interrupted. + */ +_mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ); + +/** @brief Dequeues a notification from a queue + * + * Receives a single notification from the given queue. + * + * If no notifciations are ready the function call will return an error code. + * + * @param queue The queue to receive from + * @param result Pointer to storage of a pointer of type + * \ref _mali_osk_notification_t*. \a result will be written to such that the + * expression \a (*result) will evaluate to a pointer to a valid + * \ref _mali_osk_notification_t object, or NULL if none were received. + * @return _MALI_OSK_ERR_OK on success, _MALI_OSK_ERR_ITEM_NOT_FOUND if queue was empty. + */ +_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ); + +/** @} */ /* end group _mali_osk_notification */ + + +/** @addtogroup _mali_osk_timer + * + * Timers use the OS's representation of time, which are 'ticks'. This is to + * prevent aliasing problems between the internal timer time, and the time + * asked for. + * + * @{ */ + +/** @brief Initialize a timer + * + * Allocates resources for a new timer, and initializes them. This does not + * start the timer. + * + * @return a pointer to the allocated timer object, or NULL on failure. + */ +_mali_osk_timer_t *_mali_osk_timer_init(void); + +/** @brief Start a timer + * + * It is an error to start a timer without setting the callback via + * _mali_osk_timer_setcallback(). + * + * It is an error to use this to start an already started timer. + * + * The timer will expire in \a ticks_to_expire ticks, at which point, the + * callback function will be invoked with the callback-specific data, + * as registered by _mali_osk_timer_setcallback(). + * + * @param tim the timer to start + * @param ticks_to_expire the amount of time in ticks for the timer to run + * before triggering. + */ +void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire ); + +/** @brief Modify a timer + * + * Set the absolute time at which a timer will expire, and start it if it is + * stopped. If \a expiry_tick is in the past (determined by + * _mali_osk_time_after() ), the timer fires immediately. + * + * It is an error to modify a timer without setting the callback via + * _mali_osk_timer_setcallback(). + * + * The timer will expire at absolute time \a expiry_tick, at which point, the + * callback function will be invoked with the callback-specific data, as set + * by _mali_osk_timer_setcallback(). + * + * @param tim the timer to modify, and start if necessary + * @param expiry_tick the \em absolute time in ticks at which this timer should + * trigger. + * + */ +void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick); + +/** @brief Stop a timer, and block on its completion. + * + * Stop the timer. When the function returns, it is guaranteed that the timer's + * callback will not be running on any CPU core. + * + * Since stoping the timer blocks on compeletion of the callback, the callback + * may not obtain any mutexes that the caller holds. Otherwise, a deadlock will + * occur. + * + * @note While the callback itself is guaranteed to not be running, work + * enqueued on the IRQ work-queue by the timer (with + * \ref _mali_osk_irq_schedulework()) may still run. The timer callback and IRQ + * bottom-half handler must take this into account. + * + * It is legal to stop an already stopped timer. + * + * @param tim the timer to stop. + * + */ +void _mali_osk_timer_del( _mali_osk_timer_t *tim ); + +/** @brief Set a timer's callback parameters. + * + * This must be called at least once before a timer is started/modified. + * + * After a timer has been stopped or expires, the callback remains set. This + * means that restarting the timer will call the same function with the same + * parameters on expiry. + * + * @param tim the timer to set callback on. + * @param callback Function to call when timer expires + * @param data Function-specific data to supply to the function on expiry. + */ +void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data ); + +/** @brief Terminate a timer, and deallocate resources. + * + * The timer must first be stopped by calling _mali_osk_timer_del(). + * + * It is a programming error for _mali_osk_timer_term() to be called on: + * - timer that is currently running + * - a timer that is currently executing its callback. + * + * @param tim the timer to deallocate. + */ +void _mali_osk_timer_term( _mali_osk_timer_t *tim ); +/** @} */ /* end group _mali_osk_timer */ + + +/** @defgroup _mali_osk_time OSK Time functions + * + * \ref _mali_osk_time use the OS's representation of time, which are + * 'ticks'. This is to prevent aliasing problems between the internal timer + * time, and the time asked for. + * + * OS tick time is measured as a u32. The time stored in a u32 may either be + * an absolute time, or a time delta between two events. Whilst it is valid to + * use math opeartors to \em change the tick value represented as a u32, it + * is often only meaningful to do such operations on time deltas, rather than + * on absolute time. However, it is meaningful to add/subtract time deltas to + * absolute times. + * + * Conversion between tick time and milliseconds (ms) may not be loss-less, + * and are \em implementation \em depenedant. + * + * Code use OS time must take this into account, since: + * - a small OS time may (or may not) be rounded + * - a large time may (or may not) overflow + * + * @{ */ + +/** @brief Return whether ticka occurs after tickb + * + * Some OSs handle tick 'rollover' specially, and so can be more robust against + * tick counters rolling-over. This function must therefore be called to + * determine if a time (in ticks) really occurs after another time (in ticks). + * + * @param ticka ticka + * @param tickb tickb + * @return non-zero if ticka represents a time that occurs after tickb. + * Zero otherwise. + */ +int _mali_osk_time_after( u32 ticka, u32 tickb ); + +/** @brief Convert milliseconds to OS 'ticks' + * + * @param ms time interval in milliseconds + * @return the corresponding time interval in OS ticks. + */ +u32 _mali_osk_time_mstoticks( u32 ms ); + +/** @brief Convert OS 'ticks' to milliseconds + * + * @param ticks time interval in OS ticks. + * @return the corresponding time interval in milliseconds + */ +u32 _mali_osk_time_tickstoms( u32 ticks ); + + +/** @brief Get the current time in OS 'ticks'. + * @return the current time in OS 'ticks'. + */ +u32 _mali_osk_time_tickcount( void ); + +/** @brief Cause a microsecond delay + * + * The delay will have microsecond resolution, and is necessary for correct + * operation of the driver. At worst, the delay will be \b at least \a usecs + * microseconds, and so may be (significantly) more. + * + * This function may be implemented as a busy-wait, which is the most sensible + * implementation. On OSs where there are situations in which a thread must not + * sleep, this is definitely implemented as a busy-wait. + * + * @param usecs the number of microseconds to wait for. + */ +void _mali_osk_time_ubusydelay( u32 usecs ); + +/** @brief Return time in nano seconds, since any given reference. + * + * @return Time in nano seconds + */ +u64 _mali_osk_time_get_ns( void ); + + +/** @} */ /* end group _mali_osk_time */ + +/** @defgroup _mali_osk_math OSK Math + * @{ */ + +/** @brief Count Leading Zeros (Little-endian) + * + * @note This function must be implemented to support the reference + * implementation of _mali_osk_find_first_zero_bit, as defined in + * mali_osk_bitops.h. + * + * @param val 32-bit words to count leading zeros on + * @return the number of leading zeros. + */ +u32 _mali_osk_clz( u32 val ); +/** @} */ /* end group _mali_osk_math */ + +/** @defgroup _mali_osk_wait_queue OSK Wait Queue functionality + * @{ */ +/** @brief Private type for wait queue objects */ +typedef struct _mali_osk_wait_queue_t_struct _mali_osk_wait_queue_t; + +/** @brief Initialize an empty Wait Queue */ +_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void ); + +/** @brief Sleep if condition is false + * + * @param queue the queue to use + * @param condition function pointer to a boolean function + * + * Put thread to sleep if the given \a codition function returns false. When + * being asked to wake up again, the condition will be re-checked and the + * thread only woken up if the condition is now true. + */ +void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void) ); + +/** @brief Wake up all threads in wait queue if their respective conditions are + * true + * + * @param queue the queue whose threads should be woken up + * + * Wake up all threads in wait queue \a queue whose condition is now true. + */ +void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue ); + +/** @brief terminate a wait queue + * + * @param queue the queue to terminate. + */ +void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue ); +/** @} */ /* end group _mali_osk_wait_queue */ + + +/** @addtogroup _mali_osk_miscellaneous + * @{ */ + +/** @brief Output a device driver debug message. + * + * The interpretation of \a fmt is the same as the \c format parameter in + * _mali_osu_vsnprintf(). + * + * @param fmt a _mali_osu_vsnprintf() style format string + * @param ... a variable-number of parameters suitable for \a fmt + */ +void _mali_osk_dbgmsg( const char *fmt, ... ); + +/** @brief Print fmt into buf. + * + * The interpretation of \a fmt is the same as the \c format parameter in + * _mali_osu_vsnprintf(). + * + * @param buf a pointer to the result buffer + * @param size the total number of bytes allowed to write to \a buf + * @param fmt a _mali_osu_vsnprintf() style format string + * @param ... a variable-number of parameters suitable for \a fmt + * @return The number of bytes written to \a buf + */ +u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... ); + +/** @brief Abnormal process abort. + * + * Terminates the caller-process if this function is called. + * + * This function will be called from Debug assert-macros in mali_kernel_common.h. + * + * This function will never return - because to continue from a Debug assert + * could cause even more problems, and hinder debugging of the initial problem. + * + * This function is only used in Debug builds, and is not used in Release builds. + */ +void _mali_osk_abort(void); + +/** @brief Sets breakpoint at point where function is called. + * + * This function will be called from Debug assert-macros in mali_kernel_common.h, + * to assist in debugging. If debugging at this level is not required, then this + * function may be implemented as a stub. + * + * This function is only used in Debug builds, and is not used in Release builds. + */ +void _mali_osk_break(void); + +/** @brief Return an identificator for calling process. + * + * @return Identificator for calling process. + */ +u32 _mali_osk_get_pid(void); + +/** @brief Return an identificator for calling thread. + * + * @return Identificator for calling thread. + */ +u32 _mali_osk_get_tid(void); + +/** @brief Enable OS controlled runtime power management + */ +void _mali_osk_pm_dev_enable(void); + +/** @brief Tells the OS that device is now idle + */ +_mali_osk_errcode_t _mali_osk_pm_dev_idle(void); + +/** @brief Tells the OS that the device is about to become active + */ +_mali_osk_errcode_t _mali_osk_pm_dev_activate(void); + +/** @} */ /* end group _mali_osk_miscellaneous */ + +/** @} */ /* end group osuapi */ + +/** @} */ /* end group uddapi */ + + +#ifdef __cplusplus +} +#endif + +#include "mali_osk_specific.h" /* include any per-os specifics */ + +/* Check standard inlines */ +#ifndef MALI_STATIC_INLINE + #error MALI_STATIC_INLINE not defined on your OS +#endif + +#ifndef MALI_NON_STATIC_INLINE + #error MALI_NON_STATIC_INLINE not defined on your OS +#endif + +#endif /* __MALI_OSK_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk_bitops.h b/drivers/media/video/samsung/mali/common/mali_osk_bitops.h new file mode 100644 index 0000000..ada1488 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_osk_bitops.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_bitops.h + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#ifndef __MALI_OSK_BITOPS_H__ +#define __MALI_OSK_BITOPS_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +MALI_STATIC_INLINE void _mali_internal_clear_bit( u32 bit, u32 *addr ) +{ + MALI_DEBUG_ASSERT( bit < 32 ); + MALI_DEBUG_ASSERT( NULL != addr ); + + (*addr) &= ~(1 << bit); +} + +MALI_STATIC_INLINE void _mali_internal_set_bit( u32 bit, u32 *addr ) +{ + MALI_DEBUG_ASSERT( bit < 32 ); + MALI_DEBUG_ASSERT( NULL != addr ); + + (*addr) |= (1 << bit); +} + +MALI_STATIC_INLINE u32 _mali_internal_test_bit( u32 bit, u32 value ) +{ + MALI_DEBUG_ASSERT( bit < 32 ); + return value & (1 << bit); +} + +MALI_STATIC_INLINE int _mali_internal_find_first_zero_bit( u32 value ) +{ + u32 inverted; + u32 negated; + u32 isolated; + u32 leading_zeros; + + /* Begin with xxx...x0yyy...y, where ys are 1, number of ys is in range 0..31 */ + inverted = ~value; /* zzz...z1000...0 */ + /* Using count_trailing_zeros on inverted value - + * See ARM System Developers Guide for details of count_trailing_zeros */ + + /* Isolate the zero: it is preceeded by a run of 1s, so add 1 to it */ + negated = (u32)-inverted ; /* -a == ~a + 1 (mod 2^n) for n-bit numbers */ + /* negated = xxx...x1000...0 */ + + isolated = negated & inverted ; /* xxx...x1000...0 & zzz...z1000...0, zs are ~xs */ + /* And so the first zero bit is in the same position as the 1 == number of 1s that preceeded it + * Note that the output is zero if value was all 1s */ + + leading_zeros = _mali_osk_clz( isolated ); + + return 31 - leading_zeros; +} + + +/** @defgroup _mali_osk_bitops OSK Non-atomic Bit-operations + * @{ */ + +/** + * These bit-operations do not work atomically, and so locks must be used if + * atomicity is required. + * + * Reference implementations for Little Endian are provided, and so it should + * not normally be necessary to re-implement these. Efficient bit-twiddling + * techniques are used where possible, implemented in portable C. + * + * Note that these reference implementations rely on _mali_osk_clz() being + * implemented. + */ + +/** @brief Clear a bit in a sequence of 32-bit words + * @param nr bit number to clear, starting from the (Little-endian) least + * significant bit + * @param addr starting point for counting. + */ +MALI_STATIC_INLINE void _mali_osk_clear_nonatomic_bit( u32 nr, u32 *addr ) +{ + addr += nr >> 5; /* find the correct word */ + nr = nr & ((1 << 5)-1); /* The bit number within the word */ + + _mali_internal_clear_bit( nr, addr ); +} + +/** @brief Set a bit in a sequence of 32-bit words + * @param nr bit number to set, starting from the (Little-endian) least + * significant bit + * @param addr starting point for counting. + */ +MALI_STATIC_INLINE void _mali_osk_set_nonatomic_bit( u32 nr, u32 *addr ) +{ + addr += nr >> 5; /* find the correct word */ + nr = nr & ((1 << 5)-1); /* The bit number within the word */ + + _mali_internal_set_bit( nr, addr ); +} + +/** @brief Test a bit in a sequence of 32-bit words + * @param nr bit number to test, starting from the (Little-endian) least + * significant bit + * @param addr starting point for counting. + * @return zero if bit was clear, non-zero if set. Do not rely on the return + * value being related to the actual word under test. + */ +MALI_STATIC_INLINE u32 _mali_osk_test_bit( u32 nr, u32 *addr ) +{ + addr += nr >> 5; /* find the correct word */ + nr = nr & ((1 << 5)-1); /* The bit number within the word */ + + return _mali_internal_test_bit( nr, *addr ); +} + +/* Return maxbit if not found */ +/** @brief Find the first zero bit in a sequence of 32-bit words + * @param addr starting point for search. + * @param maxbit the maximum number of bits to search + * @return the number of the first zero bit found, or maxbit if none were found + * in the specified range. + */ +MALI_STATIC_INLINE u32 _mali_osk_find_first_zero_bit( const u32 *addr, u32 maxbit ) +{ + u32 total; + + for ( total = 0; total < maxbit; total += 32, ++addr ) + { + int result; + result = _mali_internal_find_first_zero_bit( *addr ); + + /* non-negative signifies the bit was found */ + if ( result >= 0 ) + { + total += (u32)result; + break; + } + } + + /* Now check if we reached maxbit or above */ + if ( total >= maxbit ) + { + total = maxbit; + } + + return total; /* either the found bit nr, or maxbit if not found */ +} +/** @} */ /* end group _mali_osk_bitops */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_OSK_BITOPS_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk_list.h b/drivers/media/video/samsung/mali/common/mali_osk_list.h new file mode 100644 index 0000000..5987b0a --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_osk_list.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_list.h + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#ifndef __MALI_OSK_LIST_H__ +#define __MALI_OSK_LIST_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +MALI_STATIC_INLINE void __mali_osk_list_add(_mali_osk_list_t *new_entry, _mali_osk_list_t *prev, _mali_osk_list_t *next) +{ + next->prev = new_entry; + new_entry->next = next; + new_entry->prev = prev; + prev->next = new_entry; +} + +MALI_STATIC_INLINE void __mali_osk_list_del(_mali_osk_list_t *prev, _mali_osk_list_t *next) +{ + next->prev = prev; + prev->next = next; +} + +/** @addtogroup _mali_osk_list + * @{ */ + +/** Reference implementations of Doubly-linked Circular Lists are provided. + * There is often no need to re-implement these. + * + * @note The implementation may differ subtly from any lists the OS provides. + * For this reason, these lists should not be mixed with OS-specific lists + * inside the OSK/UKK implementation. */ + +/** @brief Initialize a list element. + * + * All list elements must be initialized before use. + * + * Do not use on any list element that is present in a list without using + * _mali_osk_list_del first, otherwise this will break the list. + * + * @param list the list element to initialize + */ +MALI_STATIC_INLINE void _mali_osk_list_init( _mali_osk_list_t *list ) +{ + list->next = list; + list->prev = list; +} + +/** @brief Insert a single list element after an entry in a list + * + * As an example, if this is inserted to the head of a list, then this becomes + * the first element of the list. + * + * Do not use to move list elements from one list to another, as it will break + * the originating list. + * + * + * @param newlist the list element to insert + * @param list the list in which to insert. The new element will be the next + * entry in this list + */ +MALI_STATIC_INLINE void _mali_osk_list_add( _mali_osk_list_t *new_entry, _mali_osk_list_t *list ) +{ + __mali_osk_list_add(new_entry, list, list->next); +} + +/** @brief Insert a single list element before an entry in a list + * + * As an example, if this is inserted to the head of a list, then this becomes + * the last element of the list. + * + * Do not use to move list elements from one list to another, as it will break + * the originating list. + * + * @param newlist the list element to insert + * @param list the list in which to insert. The new element will be the previous + * entry in this list + */ +MALI_STATIC_INLINE void _mali_osk_list_addtail( _mali_osk_list_t *new_entry, _mali_osk_list_t *list ) +{ + __mali_osk_list_add(new_entry, list->prev, list); +} + +/** @brief Remove a single element from a list + * + * The element will no longer be present in the list. The removed list element + * will be uninitialized, and so should not be traversed. It must be + * initialized before further use. + * + * @param list the list element to remove. + */ +MALI_STATIC_INLINE void _mali_osk_list_del( _mali_osk_list_t *list ) +{ + __mali_osk_list_del(list->prev, list->next); +} + +/** @brief Remove a single element from a list, and re-initialize it + * + * The element will no longer be present in the list. The removed list element + * will initialized, and so can be used as normal. + * + * @param list the list element to remove and initialize. + */ +MALI_STATIC_INLINE void _mali_osk_list_delinit( _mali_osk_list_t *list ) +{ + __mali_osk_list_del(list->prev, list->next); + _mali_osk_list_init(list); +} + +/** @brief Determine whether a list is empty. + * + * An empty list is one that contains a single element that points to itself. + * + * @param list the list to check. + * @return non-zero if the list is empty, and zero otherwise. + */ +MALI_STATIC_INLINE int _mali_osk_list_empty( _mali_osk_list_t *list ) +{ + return list->next == list; +} + +/** @brief Move a list element from one list to another. + * + * The list element must be initialized. + * + * As an example, moving a list item to the head of a new list causes this item + * to be the first element in the new list. + * + * @param move the list element to move + * @param list the new list into which the element will be inserted, as the next + * element in the list. + */ +MALI_STATIC_INLINE void _mali_osk_list_move( _mali_osk_list_t *move_entry, _mali_osk_list_t *list ) +{ + __mali_osk_list_del(move_entry->prev, move_entry->next); + _mali_osk_list_add(move_entry, list); +} + +/** @brief Join two lists + * + * The list element must be initialized. + * + * Allows you to join a list into another list at a specific location + * + * @param list the new list to add + * @param at the location in a list to add the new list into + */ +MALI_STATIC_INLINE void _mali_osk_list_splice( _mali_osk_list_t *list, _mali_osk_list_t *at ) +{ + if (!_mali_osk_list_empty(list)) + { + /* insert all items from 'list' after 'at' */ + _mali_osk_list_t *first = list->next; + _mali_osk_list_t *last = list->prev; + _mali_osk_list_t *split = at->next; + + first->prev = at; + at->next = first; + + last->next = split; + split->prev = last; + } +} +/** @} */ /* end group _mali_osk_list */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_OSK_LIST_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk_mali.h b/drivers/media/video/samsung/mali/common/mali_osk_mali.h new file mode 100644 index 0000000..427fcc8 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_osk_mali.h @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_mali.h + * Defines the OS abstraction layer which is specific for the Mali kernel device driver (OSK) + */ + +#ifndef __MALI_OSK_MALI_H__ +#define __MALI_OSK_MALI_H__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup _mali_osk_miscellaneous + * @{ */ + +/** @brief Read the Mali Resource configuration + * + * Populates a _mali_arch_resource_t array from configuration settings, which + * are stored in an OS-specific way. + * + * For example, these may be compiled in to a static structure, or read from + * the filesystem at startup. + * + * On failure, do not call _mali_osk_resources_term. + * + * @param arch_config a pointer to the store the pointer to the resources + * @param num_resources the number of resources read + * @return _MALI_OSK_ERR_OK on success. _MALI_OSK_ERR_NOMEM on allocation + * error. For other failures, a suitable _mali_osk_errcode_t is returned. + */ +_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources ); + +/** @brief Free resources allocated by _mali_osk_resources_init. + * + * Frees the _mali_arch_resource_t array allocated by _mali_osk_resources_init + * + * @param arch_config a pointer to the stored the pointer to the resources + * @param num_resources the number of resources in the array + */ +void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources); +/** @} */ /* end group _mali_osk_miscellaneous */ + +/** @addtogroup _mali_osk_low_level_memory + * @{ */ + +/** @brief Initialize a user-space accessible memory range + * + * This initializes a virtual address range such that it is reserved for the + * current process, but does not map any physical pages into this range. + * + * This function may initialize or adjust any members of the + * mali_memory_allocation \a descriptor supplied, before the physical pages are + * mapped in with _mali_osk_mem_mapregion_map(). + * + * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE + * set in \a descriptor->flags. It is an error to call this function without + * setting this flag. Otherwise, \a descriptor->flags bits are reserved for + * future expansion + * + * The \a descriptor's process_addr_mapping_info member can be modified to + * allocate OS-specific information. Note that on input, this will be a + * ukk_private word from the U/K inteface, as inserted by _mali_ukk_mem_mmap(). + * This is used to pass information from the U/K interface to the OSK interface, + * if necessary. The precise usage of the process_addr_mapping_info member + * depends on the U/K implementation of _mali_ukk_mem_mmap(). + * + * Therefore, the U/K implementation of _mali_ukk_mem_mmap() and the OSK + * implementation of _mali_osk_mem_mapregion_init() must agree on the meaning and + * usage of the ukk_private word and process_addr_mapping_info member. + * + * Refer to \ref u_k_api for more information on the U/K interface. + * + * On successful return, \a descriptor's mapping member will be correct for + * use with _mali_osk_mem_mapregion_term() and _mali_osk_mem_mapregion_map(). + * + * @param descriptor the mali_memory_allocation to initialize. + */ +_mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descriptor ); + +/** @brief Terminate a user-space accessible memory range + * + * This terminates a virtual address range reserved in the current user process, + * where none, some or all of the virtual address ranges have mappings to + * physical pages. + * + * It will unmap any physical pages that had been mapped into a reserved + * virtual address range for the current process, and then releases the virtual + * address range. Any extra book-keeping information or resources allocated + * during _mali_osk_mem_mapregion_init() will also be released. + * + * The \a descriptor itself is not freed - this must be handled by the caller of + * _mali_osk_mem_mapregion_term(). + * + * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE + * set in descriptor->flags. It is an error to call this function without + * setting this flag. Otherwise, descriptor->flags bits are reserved for + * future expansion + * + * @param descriptor the mali_memory_allocation to terminate. + */ +void _mali_osk_mem_mapregion_term( mali_memory_allocation * descriptor ); + +/** @brief Map physical pages into a user process's virtual address range + * + * This is used to map a number of physically contigous pages into a + * user-process's virtual address range, which was previously reserved by a + * call to _mali_osk_mem_mapregion_init(). + * + * This need not provide a mapping for the entire virtual address range + * reserved for \a descriptor - it may be used to map single pages per call. + * + * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE + * set in \a descriptor->flags. It is an error to call this function without + * setting this flag. Otherwise, \a descriptor->flags bits are reserved for + * future expansion + * + * The function may supply \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC. + * In this case, \a size must be set to \ref _MALI_OSK_CPU_PAGE_SIZE, and the function + * will allocate the physical page itself. The physical address of the + * allocated page will be returned through \a phys_addr. + * + * It is an error to set \a size != \ref _MALI_OSK_CPU_PAGE_SIZE while + * \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, + * since it is not always possible for OSs to support such a setting through this + * interface. + * + * @note \b IMPORTANT: This code must validate the input parameters. If the + * range defined by \a offset and \a size is outside the range allocated in + * \a descriptor, then this function \b MUST not attempt any mapping, and must + * instead return a suitable \ref _mali_osk_errcode_t \b failure code. + * + * @param[in,out] descriptor the mali_memory_allocation representing the + * user-process's virtual address range to map into. + * + * @param[in] offset the offset into the virtual address range. This is only added + * to the mapping member of the \a descriptor, and not the \a phys_addr parameter. + * It must be a multiple of \ref _MALI_OSK_CPU_PAGE_SIZE. + * + * @param[in,out] phys_addr a pointer to the physical base address to begin the + * mapping from. If \a size == \ref _MALI_OSK_CPU_PAGE_SIZE and + * \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, then this + * function will allocate the physical page itself, and return the + * physical address of the page through \a phys_addr, which will be aligned to + * \ref _MALI_OSK_CPU_PAGE_SIZE. Otherwise, \a *phys_addr must be aligned to + * \ref _MALI_OSK_CPU_PAGE_SIZE, and is unmodified after the call. + * \a phys_addr is unaffected by the \a offset parameter. + * + * @param[in] size the number of bytes to map in. This must be a multiple of + * \ref _MALI_OSK_CPU_PAGE_SIZE. + * + * @return _MALI_OSK_ERR_OK on sucess, otherwise a _mali_osk_errcode_t value + * on failure + * + * @note could expand to use _mali_osk_mem_mapregion_flags_t instead of + * \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, but note that we must + * also modify the mali process address manager in the mmu/memory engine code. + */ +_mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size ); + + +/** @brief Unmap physical pages from a user process's virtual address range + * + * This is used to unmap a number of physically contigous pages from a + * user-process's virtual address range, which were previously mapped by a + * call to _mali_osk_mem_mapregion_map(). If the range specified was allocated + * from OS memory, then that memory will be returned to the OS. Whilst pages + * will be mapped out, the Virtual address range remains reserved, and at the + * same base address. + * + * When this function is used to unmap pages from OS memory + * (_mali_osk_mem_mapregion_map() was called with *phys_addr == + * \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC), then the \a flags must + * include \ref _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR. This is because + * it is not always easy for an OS implementation to discover whether the + * memory was OS allocated or not (and so, how it should release the memory). + * + * For this reason, only a range of pages of the same allocation type (all OS + * allocated, or none OS allocacted) may be unmapped in one call. Multiple + * calls must be made if allocations of these different types exist across the + * entire region described by the \a descriptor. + * + * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE + * set in \a descriptor->flags. It is an error to call this function without + * setting this flag. Otherwise, \a descriptor->flags bits are reserved for + * future expansion + * + * @param[in,out] descriptor the mali_memory_allocation representing the + * user-process's virtual address range to map into. + * + * @param[in] offset the offset into the virtual address range. This is only added + * to the mapping member of the \a descriptor. \a offset must be a multiple of + * \ref _MALI_OSK_CPU_PAGE_SIZE. + * + * @param[in] size the number of bytes to unmap. This must be a multiple of + * \ref _MALI_OSK_CPU_PAGE_SIZE. + * + * @param[in] flags specifies how the memory should be unmapped. For a range + * of pages that were originally OS allocated, this must have + * \ref _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR set. + */ +void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags ); +/** @} */ /* end group _mali_osk_low_level_memory */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_OSK_MALI_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk_profiling.h b/drivers/media/video/samsung/mali/common/mali_osk_profiling.h new file mode 100644 index 0000000..fd9a8fb --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_osk_profiling.h @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_OSK_PROFILING_H__ +#define __MALI_OSK_PROFILING_H__ + +#if MALI_TIMELINE_PROFILING_ENABLED + +#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +#include "mali_linux_trace.h" +#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */ + +#include "mali_profiling_events.h" + +#define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576 + +#define MALI_PROFILING_NO_HW_COUNTER = ((u32)-1) + +/** @defgroup _mali_osk_profiling External profiling connectivity + * @{ */ + +/** + * Initialize the profiling module. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start); + +/* + * Terminate the profiling module. + */ +void _mali_osk_profiling_term(void); + +/** + * Start recording profiling data + * + * The specified limit will determine how large the capture buffer is. + * MALI_PROFILING_MAX_BUFFER_ENTRIES determines the maximum size allowed by the device driver. + * + * @param limit The desired maximum number of events to record on input, the actual maximum on output. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit); + +/** + * Add an profiling event + * + * @param event_id The event identificator. + * @param data0 First data parameter, depending on event_id specified. + * @param data1 Second data parameter, depending on event_id specified. + * @param data2 Third data parameter, depending on event_id specified. + * @param data3 Fourth data parameter, depending on event_id specified. + * @param data4 Fifth data parameter, depending on event_id specified. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +/* Call Linux tracepoint directly */ +#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) trace_mali_timeline_event((event_id), (data0), (data1), (data2), (data3), (data4)) +#else +/* Internal profiling is handled like a plain function call */ +void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4); +#endif + +/** + * Report a hardware counter event. + * + * @param counter_id The ID of the counter. + * @param value The value of the counter. + */ + +#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +/* Call Linux tracepoint directly */ +#define _mali_osk_profiling_report_hw_counter(counter_id, value) trace_mali_hw_counter(counter_id, value) +#else +/* Internal profiling is handled like a plain function call */ +void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value); +#endif + +/** + * Report SW counters + * + * @param counters array of counter values + */ +void _mali_osk_profiling_report_sw_counters(u32 *counters); + +/** + * Stop recording profiling data + * + * @param count Returns the number of recorded events. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count); + +/** + * Retrieves the number of events that can be retrieved + * + * @return The number of recorded events that can be retrieved. + */ +u32 _mali_osk_profiling_get_count(void); + +/** + * Retrieve an event + * + * @param index Event index (start with 0 and continue until this function fails to retrieve all events) + * @param timestamp The timestamp for the retrieved event will be stored here. + * @param event_id The event ID for the retrieved event will be stored here. + * @param data The 5 data values for the retrieved event will be stored here. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]); + +/** + * Clear the recorded buffer. + * + * This is needed in order to start another recording. + * + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_clear(void); + +/** + * Checks if a recording of profiling data is in progress + * + * @return MALI_TRUE if recording of profiling data is in progress, MALI_FALSE if not + */ +mali_bool _mali_osk_profiling_is_recording(void); + +/** + * Checks if profiling data is available for retrival + * + * @return MALI_TRUE if profiling data is avaiable, MALI_FALSE if not + */ +mali_bool _mali_osk_profiling_have_recording(void); + +/** @} */ /* end group _mali_osk_profiling */ + +#endif /* MALI_TIMELINE_PROFILING_ENABLED */ + +#endif /* __MALI_OSK_PROFILING_H__ */ + + diff --git a/drivers/media/video/samsung/mali/common/mali_pm.c b/drivers/media/video/samsung/mali/common/mali_pm.c new file mode 100644 index 0000000..933e54e --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_pm.c @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_pm.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" +#include "mali_platform.h" +#include "mali_kernel_utilization.h" +#include "mali_kernel_core.h" +#include "mali_group.h" + +#define MALI_PM_LIGHT_SLEEP_TIMEOUT 1000 + +enum mali_pm_scheme +{ + MALI_PM_SCHEME_DYNAMIC, + MALI_PM_SCHEME_OS_SUSPENDED, + MALI_PM_SCHEME_ALWAYS_ON +}; + +enum mali_pm_level +{ + MALI_PM_LEVEL_1_ON, + MALI_PM_LEVEL_2_STANDBY, + MALI_PM_LEVEL_3_LIGHT_SLEEP, + MALI_PM_LEVEL_4_DEEP_SLEEP +}; +static _mali_osk_lock_t *mali_pm_lock_set_next_state; +static _mali_osk_lock_t *mali_pm_lock_set_core_states; +static _mali_osk_lock_t *mali_pm_lock_execute_state_change; +static _mali_osk_irq_t *wq_irq; + +static _mali_osk_timer_t *idle_timer = NULL; +static mali_bool idle_timer_running = MALI_FALSE; +static u32 mali_pm_event_number = 0; + +static u32 num_active_gps = 0; +static u32 num_active_pps = 0; + +static enum mali_pm_scheme current_scheme = MALI_PM_SCHEME_DYNAMIC; +static enum mali_pm_level current_level = MALI_PM_LEVEL_1_ON; +static enum mali_pm_level next_level_dynamic = MALI_PM_LEVEL_2_STANDBY; /* Should be the state we go to when we go out of MALI_PM_SCHEME_ALWAYS_ON during init */ + + + +static _mali_osk_errcode_t mali_pm_upper_half(void *data); +static void mali_pm_bottom_half(void *data); +static void mali_pm_powerup(void); +static void mali_pm_powerdown(mali_power_mode power_mode); + +static void timeout_light_sleep(void* arg); +#if 0 +/* Deep sleep timout not supported */ +static void timeout_deep_sleep(void* arg); +#endif +static u32 mali_pm_event_number_get(void); +static void mali_pm_event(enum mali_pm_event pm_event, mali_bool schedule_work, u32 timer_time ); + +_mali_osk_errcode_t mali_pm_initialize(void) +{ + mali_pm_lock_execute_state_change = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PM_EXECUTE); + + if (NULL != mali_pm_lock_execute_state_change ) + { + mali_pm_lock_set_next_state = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ONELOCK| _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_LAST); + + if (NULL != mali_pm_lock_set_next_state) + { + mali_pm_lock_set_core_states = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PM_CORE_STATE); + + if (NULL != mali_pm_lock_set_core_states) + { + idle_timer = _mali_osk_timer_init(); + if (NULL != idle_timer) + { + wq_irq = _mali_osk_irq_init(_MALI_OSK_IRQ_NUMBER_PMM, + mali_pm_upper_half, + mali_pm_bottom_half, + NULL, + NULL, + (void *)NULL, + "Mali PM deferred work"); + if (NULL != wq_irq) + { + if (_MALI_OSK_ERR_OK == mali_platform_init()) + { +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON + _mali_osk_pm_dev_enable(); + mali_pm_powerup(); +#endif + return _MALI_OSK_ERR_OK; + } + + _mali_osk_irq_term(wq_irq); + } + + _mali_osk_timer_del(idle_timer); + _mali_osk_timer_term(idle_timer); + } + _mali_osk_lock_term(mali_pm_lock_set_core_states); + } + _mali_osk_lock_term(mali_pm_lock_set_next_state); + } + _mali_osk_lock_term(mali_pm_lock_execute_state_change); + } + + return _MALI_OSK_ERR_FAULT; +} + +void mali_pm_terminate(void) +{ + mali_platform_deinit(); + _mali_osk_irq_term(wq_irq); + _mali_osk_timer_del(idle_timer); + _mali_osk_timer_term(idle_timer); + _mali_osk_lock_term(mali_pm_lock_execute_state_change); + _mali_osk_lock_term(mali_pm_lock_set_next_state); + _mali_osk_lock_term(mali_pm_lock_set_core_states); +} + + +inline void mali_pm_lock(void) +{ + _mali_osk_lock_wait(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW); +} + +inline void mali_pm_unlock(void) +{ + _mali_osk_lock_signal(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW); +} + +inline void mali_pm_execute_state_change_lock(void) +{ + _mali_osk_lock_wait(mali_pm_lock_execute_state_change,_MALI_OSK_LOCKMODE_RW); +} + +inline void mali_pm_execute_state_change_unlock(void) +{ + _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW); +} + +static void mali_pm_powerup(void) +{ +#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON + MALI_DEBUG_PRINT(3, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n")); + mali_platform_power_mode_change(MALI_POWER_MODE_ON); +#else + /* Aquire our reference */ + _mali_osk_pm_dev_activate(); +#endif + mali_group_power_on(); +} + +static void mali_pm_powerdown(mali_power_mode power_mode) +{ + if ( (MALI_PM_LEVEL_1_ON == current_level) || (MALI_PM_LEVEL_2_STANDBY == current_level) ) + { + mali_group_power_off(); + } + +#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON + mali_platform_power_mode_change(power_mode); +#else + _mali_osk_pm_dev_idle(); + + if (MALI_POWER_MODE_DEEP_SLEEP == power_mode) + { + mali_platform_power_mode_change(power_mode); + } +#endif +} + +mali_bool mali_pm_is_powered_on(void) +{ + mali_bool is_on = MALI_TRUE; + + if( ! (MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme) ) + { + is_on = MALI_FALSE; + } + else if ( ! (MALI_PM_LEVEL_1_ON == current_level || MALI_PM_LEVEL_2_STANDBY == current_level)) + { + is_on = MALI_FALSE; + } + else if ( ! (MALI_PM_LEVEL_1_ON == next_level_dynamic || MALI_PM_LEVEL_2_STANDBY == next_level_dynamic)) + { + is_on = MALI_FALSE; + } + + return is_on; +} + +MALI_DEBUG_CODE( +static const char *state_as_string(enum mali_pm_level level) +{ + switch(level) + { + case MALI_PM_LEVEL_1_ON: + return "MALI_PM_LEVEL_1_ON"; + case MALI_PM_LEVEL_2_STANDBY: + return "MALI_PM_LEVEL_2_STANDBY"; + case MALI_PM_LEVEL_3_LIGHT_SLEEP: + return "MALI_PM_LEVEL_3_LIGHT_SLEEP"; + case MALI_PM_LEVEL_4_DEEP_SLEEP: + return "MALI_PM_LEVEL_4_DEEP_SLEEP"; + default: + return "UNKNOWN LEVEL"; + } +}); + +/* This could be used from another thread (work queue), if we need that */ +static void mali_pm_process_next(void) +{ + enum mali_pm_level pm_level_to_set; + + _mali_osk_lock_wait(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW); + + pm_level_to_set = current_level; + + if (MALI_PM_SCHEME_DYNAMIC == current_scheme) + { + pm_level_to_set = next_level_dynamic; + + MALI_DEBUG_PRINT(4, ("Mali PM: Dynamic scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(pm_level_to_set))); + + if (current_level == pm_level_to_set) + { + goto end_function; /* early out, no change in power level */ + } + + /* Start timers according to new state, so we get STANDBY -> LIGHT_SLEEP -> DEEP_SLEEP */ + + if (MALI_TRUE == idle_timer_running) + { + /* There is an existing timeout, so delete it */ + _mali_osk_timer_del(idle_timer); + idle_timer_running = MALI_FALSE; + } + + /* Making sure that we turn on through the platform file + Since it was turned OFF directly through the platform file. + This might lead to double turn-on, but the plaform file supports that.*/ + if ( current_level == MALI_PM_LEVEL_4_DEEP_SLEEP) + { + mali_pm_powerup(); + mali_kernel_core_wakeup(); + + } + if (MALI_PM_LEVEL_1_ON == pm_level_to_set) + { + if (MALI_PM_LEVEL_2_STANDBY != current_level) + { + /* We only need to do anything if we came from one of the sleeping states */ + mali_pm_powerup(); + + /* Wake up Mali cores since we came from a sleep state */ + mali_kernel_core_wakeup(); + } + } + else if (MALI_PM_LEVEL_2_STANDBY == pm_level_to_set) + { + /* This is just an internal state, so we don't bother to report it to the platform file */ + idle_timer_running = MALI_TRUE; + _mali_osk_timer_setcallback(idle_timer, timeout_light_sleep, (void*) mali_pm_event_number_get()); + _mali_osk_timer_add(idle_timer, _mali_osk_time_mstoticks(MALI_PM_LIGHT_SLEEP_TIMEOUT)); + } + else if (MALI_PM_LEVEL_3_LIGHT_SLEEP == pm_level_to_set) + { + mali_pm_powerdown(MALI_POWER_MODE_LIGHT_SLEEP); + } + else if (MALI_PM_LEVEL_4_DEEP_SLEEP == pm_level_to_set) + { + MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n")); + mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP); + } + } + else if (MALI_PM_SCHEME_OS_SUSPENDED == current_scheme) + { + MALI_DEBUG_PRINT(4, ("Mali PM: OS scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(MALI_PM_LEVEL_4_DEEP_SLEEP))); + + pm_level_to_set = MALI_PM_LEVEL_4_DEEP_SLEEP; + + if (current_level == pm_level_to_set) + { + goto end_function; /* early out, no change in power level */ + } + + /* Cancel any timers */ + if (MALI_TRUE == idle_timer_running) + { + /* There is an existing timeout, so delete it */ + _mali_osk_timer_del(idle_timer); + idle_timer_running = MALI_FALSE; + } + + MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n")); + mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP); + next_level_dynamic = current_level; + } + else if (MALI_PM_SCHEME_ALWAYS_ON == current_scheme) + { + MALI_DEBUG_PRINT(4, ("Mali PM: Always on scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(MALI_PM_LEVEL_1_ON))); + + pm_level_to_set = MALI_PM_LEVEL_1_ON; + if (current_level == pm_level_to_set) + { + goto end_function; /* early out, no change in power level */ + } + + MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n")); + mali_pm_powerup(); + if (MALI_PM_LEVEL_2_STANDBY != current_level) + { + /* Wake up Mali cores since we came from a sleep state */ + mali_kernel_core_wakeup(); + } + } + else + { + MALI_PRINT_ERROR(("MALI PM: Illegal scheme")); + } + + current_level = pm_level_to_set; + +end_function: + _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW); + +} + +void mali_pm_always_on(mali_bool enable) +{ + if (MALI_TRUE == enable) + { + /* The event is processed in current thread synchronously */ + mali_pm_event(MALI_PM_EVENT_SCHEME_ALWAYS_ON, MALI_FALSE, 0 ); + } + else + { + /* The event is processed in current thread synchronously */ + mali_pm_event(MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL, MALI_FALSE, 0 ); + } +} + +static _mali_osk_errcode_t mali_pm_upper_half(void *data) +{ + /* not used */ + return _MALI_OSK_ERR_OK; +} + +static void mali_pm_bottom_half(void *data) +{ + mali_pm_process_next(); +} + +static u32 mali_pm_event_number_get(void) +{ + u32 retval; + + mali_pm_lock(); /* spinlock: mali_pm_lock_set_next_state */ + retval = ++mali_pm_event_number; + if (0==retval ) retval = ++mali_pm_event_number; + mali_pm_unlock(); + + return retval; +} + +static void mali_pm_event(enum mali_pm_event pm_event, mali_bool schedule_work, u32 timer_time ) +{ + mali_pm_lock(); /* spinlock: mali_pm_lock_set_next_state */ + /* Only timer events should set this variable, all other events must set it to zero. */ + if ( 0 != timer_time ) + { + MALI_DEBUG_ASSERT( (pm_event==MALI_PM_EVENT_TIMER_LIGHT_SLEEP) || (pm_event==MALI_PM_EVENT_TIMER_DEEP_SLEEP) ); + if ( mali_pm_event_number != timer_time ) + { + /* In this case there have been processed newer events since the timer event was set up. + If so we always ignore the timing event */ + mali_pm_unlock(); + return; + } + } + else + { + /* Delete possible ongoing timers + if ( (MALI_PM_LEVEL_2_STANDBY==current_level) || (MALI_PM_LEVEL_3_LIGHT_SLEEP==current_level) ) + { + _mali_osk_timer_del(idle_timer); + } + */ + } + mali_pm_event_number++; + switch (pm_event) + { + case MALI_PM_EVENT_CORES_WORKING: + next_level_dynamic = MALI_PM_LEVEL_1_ON; + MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); + break; + case MALI_PM_EVENT_CORES_IDLE: + next_level_dynamic = MALI_PM_LEVEL_2_STANDBY; + /*MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme );*/ + break; + case MALI_PM_EVENT_TIMER_LIGHT_SLEEP: + MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme ); + MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); + next_level_dynamic = MALI_PM_LEVEL_3_LIGHT_SLEEP; + break; + case MALI_PM_EVENT_TIMER_DEEP_SLEEP: + MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme ); + MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); + next_level_dynamic = MALI_PM_LEVEL_4_DEEP_SLEEP; + break; + case MALI_PM_EVENT_OS_SUSPEND: + MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme ); + MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); + current_scheme = MALI_PM_SCHEME_OS_SUSPENDED; + next_level_dynamic = MALI_PM_LEVEL_4_DEEP_SLEEP; /* Dynamic scheme will go into level when we are resumed */ + break; + case MALI_PM_EVENT_OS_RESUME: + MALI_DEBUG_ASSERT(MALI_PM_SCHEME_OS_SUSPENDED == current_scheme ); + current_scheme = MALI_PM_SCHEME_DYNAMIC; + break; + case MALI_PM_EVENT_SCHEME_ALWAYS_ON: + MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); + current_scheme = MALI_PM_SCHEME_ALWAYS_ON; + break; + case MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL: + MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme ); + current_scheme = MALI_PM_SCHEME_DYNAMIC; + break; + default: + MALI_DEBUG_PRINT_ERROR(("Unknown next state.")); + mali_pm_unlock(); + return; + } + mali_pm_unlock(); + + if (MALI_TRUE == schedule_work) + { + _mali_osk_irq_schedulework(wq_irq); + } + else + { + mali_pm_process_next(); + } +} + +static void timeout_light_sleep(void* arg) +{ + /* State change only if no newer power events have happend from the time in arg. + Actual work will be scheduled on worker thread. */ + mali_pm_event(MALI_PM_EVENT_TIMER_LIGHT_SLEEP, MALI_TRUE, (u32) arg); +} + +void mali_pm_core_event(enum mali_core_event core_event) +{ + mali_bool transition_working = MALI_FALSE; + mali_bool transition_idle = MALI_FALSE; + + _mali_osk_lock_wait(mali_pm_lock_set_core_states, _MALI_OSK_LOCKMODE_RW); + + switch (core_event) + { + case MALI_CORE_EVENT_GP_START: + if (num_active_pps + num_active_gps == 0) + { + transition_working = MALI_TRUE; + } + num_active_gps++; + break; + case MALI_CORE_EVENT_GP_STOP: + if (num_active_pps + num_active_gps == 1) + { + transition_idle = MALI_TRUE; + } + num_active_gps--; + break; + case MALI_CORE_EVENT_PP_START: + if (num_active_pps + num_active_gps == 0) + { + transition_working = MALI_TRUE; + } + num_active_pps++; + break; + case MALI_CORE_EVENT_PP_STOP: + if (num_active_pps + num_active_gps == 1) + { + transition_idle = MALI_TRUE; + } + num_active_pps--; + break; + } + + if (transition_working == MALI_TRUE) + { +#ifdef CONFIG_MALI400_GPU_UTILIZATION + mali_utilization_core_start(_mali_osk_time_get_ns()); +#endif + mali_pm_event(MALI_PM_EVENT_CORES_WORKING, MALI_FALSE, 0); /* process event in same thread */ + } + else if (transition_idle == MALI_TRUE) + { +#ifdef CONFIG_MALI400_GPU_UTILIZATION + mali_utilization_core_end(_mali_osk_time_get_ns()); +#endif + mali_pm_event(MALI_PM_EVENT_CORES_IDLE, MALI_FALSE, 0); /* process event in same thread */ + } + + _mali_osk_lock_signal(mali_pm_lock_set_core_states, _MALI_OSK_LOCKMODE_RW); +} + +void mali_pm_os_suspend(void) +{ + MALI_DEBUG_PRINT(2, ("Mali PM: OS suspending...\n")); + + mali_gp_scheduler_suspend(); + mali_pp_scheduler_suspend(); + mali_pm_event(MALI_PM_EVENT_OS_SUSPEND, MALI_FALSE, 0); /* process event in same thread */ + + MALI_DEBUG_PRINT(2, ("Mali PM: OS suspend completed\n")); +} + +void mali_pm_os_resume(void) +{ + MALI_DEBUG_PRINT(2, ("Mali PM: OS resuming...\n")); + + mali_pm_event(MALI_PM_EVENT_OS_RESUME, MALI_FALSE, 0); /* process event in same thread */ + mali_gp_scheduler_resume(); + mali_pp_scheduler_resume(); + + MALI_DEBUG_PRINT(2, ("Mali PM: OS resume completed\n")); +} + +void mali_pm_runtime_suspend(void) +{ + MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime suspended\n")); + mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP); +} + +void mali_pm_runtime_resume(void) +{ + MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime resumed\n")); + mali_platform_power_mode_change(MALI_POWER_MODE_ON); +} diff --git a/drivers/media/video/samsung/mali/common/mali_pm.h b/drivers/media/video/samsung/mali/common/mali_pm.h new file mode 100644 index 0000000..d4ccfde --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_pm.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PM_H__ +#define __MALI_PM_H__ + +#include "mali_osk.h" + +enum mali_core_event +{ + MALI_CORE_EVENT_GP_START, + MALI_CORE_EVENT_GP_STOP, + MALI_CORE_EVENT_PP_START, + MALI_CORE_EVENT_PP_STOP +}; + +enum mali_pm_event +{ + MALI_PM_EVENT_CORES_WORKING, + MALI_PM_EVENT_CORES_IDLE, + MALI_PM_EVENT_TIMER_LIGHT_SLEEP, + MALI_PM_EVENT_TIMER_DEEP_SLEEP, + MALI_PM_EVENT_OS_SUSPEND, + MALI_PM_EVENT_OS_RESUME, + MALI_PM_EVENT_SCHEME_ALWAYS_ON, + MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL, +}; + +_mali_osk_errcode_t mali_pm_initialize(void); +void mali_pm_terminate(void); +void mali_pm_always_on(mali_bool enable); + +void mali_pm_lock(void); +void mali_pm_unlock(void); +void mali_pm_execute_state_change_lock(void); + +void mali_pm_execute_state_change_unlock(void); + +mali_bool mali_pm_is_powered_on(void); + +void mali_pm_core_event(enum mali_core_event core_event); + +void mali_pm_os_suspend(void); +void mali_pm_os_resume(void); +void mali_pm_runtime_suspend(void); +void mali_pm_runtime_resume(void); + + +#endif /* __MALI_PM_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_pmu.c b/drivers/media/video/samsung/mali/common/mali_pmu.c new file mode 100644 index 0000000..348b5dc --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_pmu.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_pmu.c + * Mali driver functions for Mali 400 PMU hardware + */ +#include "mali_hw_core.h" +#include "mali_pmu.h" +#include "mali_pp.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" + +static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches); + +/** @brief MALI inbuilt PMU hardware info and PMU hardware has knowledge of cores power mask + */ +struct mali_pmu_core +{ + struct mali_hw_core hw_core; + u32 mali_registered_cores_power_mask; +}; + +static struct mali_pmu_core *mali_global_pmu_core = NULL; + +/** @brief Register layout for hardware PMU + */ +typedef enum { + PMU_REG_ADDR_MGMT_POWER_UP = 0x00, /*< Power up register */ + PMU_REG_ADDR_MGMT_POWER_DOWN = 0x04, /*< Power down register */ + PMU_REG_ADDR_MGMT_STATUS = 0x08, /*< Core sleep status register */ + PMU_REG_ADDR_MGMT_INT_MASK = 0x0C, /*< Interrupt mask register */ + PMU_REGISTER_ADDRESS_SPACE_SIZE = 0x10, /*< Size of register space */ +} pmu_reg_addr_mgmt_addr; + +struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches) +{ + struct mali_pmu_core* pmu; + + MALI_DEBUG_ASSERT(NULL == mali_global_pmu_core); + MALI_DEBUG_PRINT(2, ("Mali PMU: Creating Mali PMU core\n")); + + pmu = (struct mali_pmu_core *)_mali_osk_malloc(sizeof(struct mali_pmu_core)); + if (NULL != pmu) + { + pmu->mali_registered_cores_power_mask = mali_pmu_detect_mask(number_of_pp_cores, number_of_l2_caches); + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&pmu->hw_core, resource, PMU_REGISTER_ADDRESS_SPACE_SIZE)) + { + if (_MALI_OSK_ERR_OK == mali_pmu_reset(pmu)) + { + mali_global_pmu_core = pmu; + return pmu; + } + mali_hw_core_delete(&pmu->hw_core); + } + _mali_osk_free(pmu); + } + + return NULL; +} + +void mali_pmu_delete(struct mali_pmu_core *pmu) +{ + MALI_DEBUG_ASSERT_POINTER(pmu); + + mali_hw_core_delete(&pmu->hw_core); + _mali_osk_free(pmu); + pmu = NULL; +} + +_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu) +{ + /* Don't use interrupts - just poll status */ + mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0); + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_pmu_powerdown_all(struct mali_pmu_core *pmu) +{ + u32 stat; + u32 timeout; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT( pmu->mali_registered_cores_power_mask != 0 ); + MALI_DEBUG_PRINT( 4, ("Mali PMU: power down (0x%08X)\n", pmu->mali_registered_cores_power_mask) ); + + mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_DOWN, pmu->mali_registered_cores_power_mask); + + /* Wait for cores to be powered down (100 x 100us = 100ms) */ + timeout = 100; + do + { + /* Get status of sleeping cores */ + stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); + stat &= pmu->mali_registered_cores_power_mask; + if( stat == pmu->mali_registered_cores_power_mask ) break; /* All cores we wanted are now asleep */ + _mali_osk_time_ubusydelay(100); + timeout--; + } while( timeout > 0 ); + + if( timeout == 0 ) + { + return _MALI_OSK_ERR_TIMEOUT; + } + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_pmu_powerup_all(struct mali_pmu_core *pmu) +{ + u32 stat; + u32 timeout; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT( pmu->mali_registered_cores_power_mask != 0 ); /* Shouldn't be zero */ + MALI_DEBUG_PRINT( 4, ("Mali PMU: power up (0x%08X)\n", pmu->mali_registered_cores_power_mask) ); + + mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_UP, pmu->mali_registered_cores_power_mask); + + /* Wait for cores to be powered up (100 x 100us = 100ms) */ + timeout = 100; + do + { + /* Get status of sleeping cores */ + stat = mali_hw_core_register_read(&pmu->hw_core,PMU_REG_ADDR_MGMT_STATUS); + stat &= pmu->mali_registered_cores_power_mask; + if( stat == 0 ) break; /* All cores we wanted are now awake */ + _mali_osk_time_ubusydelay(100); + timeout--; + } while( timeout > 0 ); + + if( timeout == 0 ) + { + return _MALI_OSK_ERR_TIMEOUT; + } + + return _MALI_OSK_ERR_OK; +} + +struct mali_pmu_core *mali_pmu_get_global_pmu_core(void) +{ + return mali_global_pmu_core; +} + +static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches) +{ + u32 mask = 0; + + if (number_of_l2_caches == 1) + { + /* Mali-300 or Mali-400 */ + u32 i; + + /* GP */ + mask = 0x01; + + /* L2 cache */ + mask |= 0x01<<1; + + /* Set bit for each PP core */ + for (i = 0; i < number_of_pp_cores; i++) + { + mask |= 0x01<<(i+2); + } + } + else if (number_of_l2_caches > 1) + { + /* Mali-450 */ + + /* GP (including its L2 cache) */ + mask = 0x01; + + /* There is always at least one PP (including its L2 cache) */ + mask |= 0x01<<1; + + /* Additional PP cores in same L2 cache */ + if (number_of_pp_cores >= 2) + { + mask |= 0x01<<2; + } + + /* Additional PP cores in a third L2 cache */ + if (number_of_pp_cores >= 5) + { + mask |= 0x01<<3; + } + } + + MALI_DEBUG_PRINT(4, ("Mali PMU: Power mask is 0x%08X (%u + %u)\n", mask, number_of_pp_cores, number_of_l2_caches)); + + return mask; +} diff --git a/drivers/media/video/samsung/mali/common/mali_pmu.h b/drivers/media/video/samsung/mali/common/mali_pmu.h new file mode 100644 index 0000000..fd10c08 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_pmu.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_platform.h + * Platform specific Mali driver functions + */ + +#include "mali_osk.h" + +struct mali_pmu_core; + +/** @brief Initialisation of MALI PMU + * + * This is called from entry point of the driver in order to create and intialize the PMU resource + * + * @param resource it will be a pointer to a PMU resource + * @param number_of_pp_cores Number of found PP resources in configuration + * @param number_of_l2_caches Number of found L2 cache resources in configuration + * @return The created PMU object, or NULL in case of failure. + */ +struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches); + +/** @brief It deallocates the PMU resource + * + * This is called on the exit of the driver to terminate the PMU resource + * + * @param pmu Pointer to PMU core object to delete + */ +void mali_pmu_delete(struct mali_pmu_core *pmu); + +/** @brief Reset PMU core + * + * @param pmu Pointer to PMU core object to reset + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu); + +/** @brief MALI GPU power down using MALI in-built PMU + * + * called to power down all cores + * + * @param pmu Pointer to PMU core object to power down + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmu_powerdown_all(struct mali_pmu_core *pmu); + + +/** @brief MALI GPU power up using MALI in-built PMU + * + * called to power up all cores + * + * @param pmu Pointer to PMU core object to power up + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmu_powerup_all(struct mali_pmu_core *pmu); + + +/** @brief Retrieves the Mali PMU core object (if any) + * + * @return The Mali PMU object, or NULL if no PMU exists. + */ +struct mali_pmu_core *mali_pmu_get_global_pmu_core(void); diff --git a/drivers/media/video/samsung/mali/common/mali_pp.c b/drivers/media/video/samsung/mali/common/mali_pp.c new file mode 100644 index 0000000..5549f82 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_pp.c @@ -0,0 +1,710 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_pp.h" +#include "mali_hw_core.h" +#include "mali_group.h" +#include "mali_osk.h" +#include "regs/mali_200_regs.h" +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#if MALI_TIMELINE_PROFILING_ENABLED +#include "mali_osk_profiling.h" +#endif + +/* See mali_gp.c file for description on how to handle the interrupt mask. + * This is how to do it on PP: mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); + */ + +#define MALI_MAX_NUMBER_OF_PP_CORES 8 + +/** + * Definition of the PP core struct + * Used to track a PP core in the system. + */ +struct mali_pp_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + struct mali_group *group; /**< Parent group for this core */ + _mali_osk_irq_t *irq; /**< IRQ handler */ + u32 core_id; /**< Unique core ID */ + struct mali_pp_job *running_job; /**< Current running (super) job */ + u32 running_sub_job; /**< Current running sub job */ + _mali_osk_timer_t *timeout_timer; /**< timeout timer for this core */ + u32 timeout_job_id; /**< job id for the timed out job - relevant only if pp_core_timed_out == MALI_TRUE */ + mali_bool core_timed_out; /**< if MALI_TRUE, this pp core has timed out; if MALI_FALSE, no timeout on this pp core */ + u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ + u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ + u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */ + u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */ +}; + +static struct mali_pp_core* mali_global_pp_cores[MALI_MAX_NUMBER_OF_PP_CORES]; +static u32 mali_global_num_pp_cores = 0; + +/* Interrupt handlers */ +static _mali_osk_errcode_t mali_pp_upper_half(void *data); +static void mali_pp_bottom_half(void *data); +static void mali_pp_irq_probe_trigger(void *data); +static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data); +static void mali_pp_post_process_job(struct mali_pp_core *core); +static void mali_pp_timeout(void *data); + +struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group) +{ + struct mali_pp_core* core = NULL; + + MALI_DEBUG_PRINT(2, ("Mali PP: Creating Mali PP core: %s\n", resource->description)); + MALI_DEBUG_PRINT(2, ("Mali PP: Base address of PP core: 0x%x\n", resource->base)); + + if (mali_global_num_pp_cores >= MALI_MAX_NUMBER_OF_PP_CORES) + { + MALI_PRINT_ERROR(("Mali PP: Too many PP core objects created\n")); + return NULL; + } + + core = _mali_osk_malloc(sizeof(struct mali_pp_core)); + if (NULL != core) + { + core->group = group; + core->core_id = mali_global_num_pp_cores; + core->running_job = NULL; + core->counter_src0 = MALI_HW_CORE_NO_COUNTER; + core->counter_src1 = MALI_HW_CORE_NO_COUNTER; + core->counter_src0_used = MALI_HW_CORE_NO_COUNTER; + core->counter_src1_used = MALI_HW_CORE_NO_COUNTER; + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI200_REG_SIZEOF_REGISTER_BANK)) + { + _mali_osk_errcode_t ret; + + mali_group_lock(group); + ret = mali_pp_reset(core); + mali_group_unlock(group); + + if (_MALI_OSK_ERR_OK == ret) + { + /* Setup IRQ handlers (which will do IRQ probing if needed) */ + core->irq = _mali_osk_irq_init(resource->irq, + mali_pp_upper_half, + mali_pp_bottom_half, + mali_pp_irq_probe_trigger, + mali_pp_irq_probe_ack, + core, + "mali_pp_irq_handlers"); + if (NULL != core->irq) + { + /* Initialise the timeout timer */ + core->timeout_timer = _mali_osk_timer_init(); + if(NULL != core->timeout_timer) + { + _mali_osk_timer_setcallback(core->timeout_timer, mali_pp_timeout, (void *)core); + + mali_global_pp_cores[mali_global_num_pp_cores] = core; + mali_global_num_pp_cores++; + + return core; + } + else + { + MALI_PRINT_ERROR(("Failed to setup timeout timer for PP core %s\n", core->hw_core.description)); + /* Release IRQ handlers */ + _mali_osk_irq_term(core->irq); + } + } + else + { + MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description)); + } + } + mali_hw_core_delete(&core->hw_core); + } + + _mali_osk_free(core); + } + else + { + MALI_PRINT_ERROR(("Mali PP: Failed to allocate memory for PP core\n")); + } + + return NULL; +} + +void mali_pp_delete(struct mali_pp_core *core) +{ + u32 i; + + MALI_DEBUG_ASSERT_POINTER(core); + + _mali_osk_timer_term(core->timeout_timer); + _mali_osk_irq_term(core->irq); + mali_hw_core_delete(&core->hw_core); + + /* Remove core from global list */ + for (i = 0; i < mali_global_num_pp_cores; i++) + { + if (mali_global_pp_cores[i] == core) + { + mali_global_pp_cores[i] = NULL; + mali_global_num_pp_cores--; + break; + } + } + + _mali_osk_free(core); +} + +void mali_pp_stop_bus(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + /* Will only send the stop bus command, and not wait for it to complete */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS); +} + +_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core) +{ + int i; + const int request_loop_count = 20; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_ASSERT_GROUP_LOCKED(core->group); + + /* Send the stop bus command. */ + mali_pp_stop_bus(core); + + /* Wait for bus to be stopped */ + for (i = 0; i < request_loop_count; i++) + { + if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED) + break; + _mali_osk_time_ubusydelay(10); + } + + if (request_loop_count == i) + { + MALI_PRINT_ERROR(("Mali PP: Failed to stop bus on %s. Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core) +{ + /* Bus must be stopped before calling this function */ + const int reset_finished_loop_count = 15; + const u32 reset_invalid_value = 0xC0FFE000; + const u32 reset_check_value = 0xC01A0000; + int i; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_DEBUG_PRINT(2, ("Mali PP: Hard reset of core %s\n", core->hw_core.description)); + MALI_ASSERT_GROUP_LOCKED(core->group); + + mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */ + + /* Set register to a bogus value. The register will be used to detect when reset is complete */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value); + + /* Force core to reset */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET); + + /* Wait for reset to be complete */ + for (i = 0; i < reset_finished_loop_count; i++) + { + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_check_value); + if (reset_check_value == mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW)) + { + break; + } + _mali_osk_time_ubusydelay(10); + } + + if (i == reset_finished_loop_count) + { + MALI_PRINT_ERROR(("Mali PP: The hard reset loop didn't work, unable to recover\n")); + } + + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, 0x00000000); /* set it back to the default */ + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core) +{ + int i; + const int request_loop_count = 20; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description)); + MALI_ASSERT_GROUP_LOCKED(core->group); + + mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */ + + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ + +#if defined(USING_MALI200) + + /* On Mali-200, stop the bus, then do a hard reset of the core */ + + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS); + + for (i = 0; i < request_loop_count; i++) + { + if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED) + { + break; + } + _mali_osk_time_ubusydelay(10); + } + + if (request_loop_count == i) + { + MALI_PRINT_ERROR(("Mali PP: Failed to stop bus for core %s, unable to recover\n", core->hw_core.description)); + return _MALI_OSK_ERR_FAULT ; + } + + /* the bus was stopped OK, do the hard reset */ + mali_pp_hard_reset(core); + +#elif defined(USING_MALI400) + + /* Mali-300 and Mali-400 have a safe reset command which we use */ + + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI400PP_REG_VAL_IRQ_RESET_COMPLETED); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET); + + for (i = 0; i < request_loop_count; i++) + { + if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400PP_REG_VAL_IRQ_RESET_COMPLETED) + { + break; + } + _mali_osk_time_ubusydelay(10); + } + + if (request_loop_count == i) + { + MALI_DEBUG_PRINT(2, ("Mali PP: Failed to reset core %s, Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); + return _MALI_OSK_ERR_FAULT; + } +#else +#error "no supported mali core defined" +#endif + + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); + + return _MALI_OSK_ERR_OK; +} + +void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job) +{ + u32 *frame_registers = mali_pp_job_get_frame_registers(job); + u32 *wb0_registers = mali_pp_job_get_wb0_registers(job); + u32 *wb1_registers = mali_pp_job_get_wb1_registers(job); + u32 *wb2_registers = mali_pp_job_get_wb2_registers(job); + core->counter_src0_used = core->counter_src0; + core->counter_src1_used = core->counter_src1; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_ASSERT_GROUP_LOCKED(core->group); + + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, frame_registers, MALI200_NUM_REGS_FRAME); + if (0 != sub_job) + { + /* + * There are two frame registers which are different for each sub job. + * For the first sub job, these are correctly represented in the frame register array, + * but we need to patch these for all other sub jobs + */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job)); + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job)); + } + + if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ + { + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, MALI200_NUM_REGS_WBx); + } + + if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ + { + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, MALI200_NUM_REGS_WBx); + } + + if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ + { + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, MALI200_NUM_REGS_WBx); + } + + /* This selects which performance counters we are reading */ + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + /* global_config has enabled HW counters, this will override anything specified by user space */ + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); + } + if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); + } + } + else + { + /* Use HW counters from job object, if any */ + u32 perf_counter_flag = mali_pp_job_get_perf_counter_flag(job); + if (0 != perf_counter_flag) + { + if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) + { + core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); + } + + if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) + { + core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); + } + } + } + + MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description)); + + /* Adding barrier to make sure all rester writes are finished */ + _mali_osk_write_mem_barrier(); + + /* This is the command that starts the core. */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING); + + /* Adding barrier to make sure previous rester writes is finished */ + _mali_osk_write_mem_barrier(); + + /* Setup the timeout timer value and save the job id for the job running on the pp core */ + _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); + core->timeout_job_id = mali_pp_job_get_id(job); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, job->frame_builder_id, job->flush_id, 0, 0, 0); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), job->pid, job->tid, 0, 0, 0); +#endif + + core->running_job = job; + core->running_sub_job = sub_job; +} + +u32 mali_pp_core_get_version(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION); +} + +u32 mali_pp_core_get_id(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return core->core_id; +} + +mali_bool mali_pp_core_set_counter_src0(struct mali_pp_core *core, u32 counter) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + core->counter_src0 = counter; + return MALI_TRUE; +} + +mali_bool mali_pp_core_set_counter_src1(struct mali_pp_core *core, u32 counter) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + core->counter_src1 = counter; + return MALI_TRUE; +} + +u32 mali_pp_core_get_counter_src0(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return core->counter_src0; +} + +u32 mali_pp_core_get_counter_src1(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return core->counter_src1; +} + +struct mali_pp_core* mali_pp_get_global_pp_core(u32 index) +{ + if (MALI_MAX_NUMBER_OF_PP_CORES > index) + { + return mali_global_pp_cores[index]; + } + + return NULL; +} + +u32 mali_pp_get_glob_num_pp_cores(void) +{ + return mali_global_num_pp_cores; +} + +u32 mali_pp_get_max_num_pp_cores(void) +{ + return MALI_MAX_NUMBER_OF_PP_CORES; +} + +/* ------------- interrupt handling below ------------------ */ +static _mali_osk_errcode_t mali_pp_upper_half(void *data) +{ + struct mali_pp_core *core = (struct mali_pp_core *)data; + u32 irq_readout; + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); + if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout) + { + /* Mask out all IRQs from this core until IRQ is handled */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); +#endif + + /* We do need to handle this in a bottom half */ + _mali_osk_irq_schedulework(core->irq); + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + +static void mali_pp_bottom_half(void *data) +{ + struct mali_pp_core *core = (struct mali_pp_core *)data; + u32 irq_readout; + u32 irq_errors; + +#if MALI_TIMELINE_PROFILING_ENABLED +#if 0 /* Bottom half TLP logging is currently not supported */ + _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); +#endif +#endif + + mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */ + + if ( MALI_FALSE == mali_group_power_is_on(core->group) ) + { + MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description)); + mali_group_unlock(core->group); + return; + } + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED; + + MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description)); + + if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME) + { + mali_pp_post_process_job(core); + MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n")); + mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_COMPLETED); /* Will release group lock */ + return; + } + + /* + * Now lets look at the possible error cases (IRQ indicating error or timeout) + * END_OF_FRAME and HANG interrupts are not considered error. + */ + irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG); + if (0 != irq_errors) + { + mali_pp_post_process_job(core); + MALI_PRINT_ERROR(("Mali PP: Unknown interrupt 0x%08X from core %s, aborting job\n", + irq_readout, core->hw_core.description)); + mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_FAILED); /* Will release group lock */ + return; + } + else if (MALI_TRUE == core->core_timed_out) /* SW timeout */ + { + if (core->timeout_job_id == mali_pp_job_get_id(core->running_job)) + { + mali_pp_post_process_job(core); + MALI_DEBUG_PRINT(2, ("Mali PP: Job %d timed out on core %s\n", + mali_pp_job_get_id(core->running_job), core->hw_core.description)); + mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_TIMED_OUT); /* Will release group lock */ + } + else + { + mali_group_unlock(core->group); + } + core->core_timed_out = MALI_FALSE; + return; + } + else if (irq_readout & MALI200_REG_VAL_IRQ_HANG) + { + /* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_HANG); + } + + /* + * The only way to get here is if we got a HANG interrupt, which we ignore. + * Re-enable interrupts and let core continue to run + */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); + mali_group_unlock(core->group); + +#if MALI_TIMELINE_PROFILING_ENABLED +#if 0 /* Bottom half TLP logging is currently not supported */ + _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); +#endif +#endif +} + +static void mali_pp_irq_probe_trigger(void *data) +{ + struct mali_pp_core *core = (struct mali_pp_core *)data; + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); /* @@@@ This should not be needed */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG); + _mali_osk_mem_barrier(); +} + +static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data) +{ + struct mali_pp_core *core = (struct mali_pp_core *)data; + u32 irq_readout; + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); + if (MALI200_REG_VAL_IRQ_FORCE_HANG & irq_readout) + { + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_FORCE_HANG); + _mali_osk_mem_barrier(); + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + + +/* ------ local helper functions below --------- */ +static void mali_pp_post_process_job(struct mali_pp_core *core) +{ + MALI_ASSERT_GROUP_LOCKED(core->group); + + if (NULL != core->running_job) + { + u32 val0 = 0; + u32 val1 = 0; +#if MALI_TIMELINE_PROFILING_ENABLED + int counter_index = COUNTER_FP0_C0 + (2 * core->core_id); +#endif + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + val0 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE); + if (mali_pp_job_get_perf_counter_flag(core->running_job) && + _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_pp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used) + { + /* We retrieved the counter that user space asked for, so return the value through the job object */ + mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, val0); + } + else + { + /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ + mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); + } + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_report_hw_counter(counter_index, val0); +#endif + } + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + val1 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE); + if (mali_pp_job_get_perf_counter_flag(core->running_job) && + _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_pp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used) + { + /* We retrieved the counter that user space asked for, so return the value through the job object */ + mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, val1); + } + else + { + /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ + mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); + } + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_report_hw_counter(counter_index + 1, val1); +#endif + } + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), + val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0); +#endif + + /* We are no longer running a job... */ + core->running_job = NULL; + _mali_osk_timer_del(core->timeout_timer); + } +} + +/* callback function for pp core timeout */ +static void mali_pp_timeout(void *data) +{ + struct mali_pp_core * core = ((struct mali_pp_core *)data); + + MALI_DEBUG_PRINT(3, ("Mali PP: TIMEOUT callback \n")); + core->core_timed_out = MALI_TRUE; + _mali_osk_irq_schedulework(core->irq); +} + +#if 0 +static void mali_pp_print_registers(struct mali_pp_core *core) +{ + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_VERSION = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_MASK = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE))); +} +#endif + +#if 0 +void mali_pp_print_state(struct mali_pp_core *core) +{ + MALI_DEBUG_PRINT(2, ("Mali PP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) )); +} +#endif + +#if MALI_STATE_TRACKING +u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "\tPP #%d: %s\n", core->core_id, core->hw_core.description); + + return n; +} +#endif diff --git a/drivers/media/video/samsung/mali/common/mali_pp.h b/drivers/media/video/samsung/mali/common/mali_pp.h new file mode 100644 index 0000000..9b425a0 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_pp.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PP_H__ +#define __MALI_PP_H__ + +#include "mali_osk.h" +#include "mali_pp_job.h" + +struct mali_pp_core; +struct mali_group; + +_mali_osk_errcode_t mali_pp_initialize(void); +void mali_pp_terminate(void); + +struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group); +void mali_pp_delete(struct mali_pp_core *core); + +void mali_pp_stop_bus(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core); + +void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job); + +u32 mali_pp_core_get_version(struct mali_pp_core *core); + +u32 mali_pp_core_get_id(struct mali_pp_core *core); + +mali_bool mali_pp_core_set_counter_src0(struct mali_pp_core *core, u32 counter); +mali_bool mali_pp_core_set_counter_src1(struct mali_pp_core *core, u32 counter); +u32 mali_pp_core_get_counter_src0(struct mali_pp_core *core); +u32 mali_pp_core_get_counter_src1(struct mali_pp_core *core); +struct mali_pp_core* mali_pp_get_global_pp_core(u32 index); +u32 mali_pp_get_glob_num_pp_cores(void); +u32 mali_pp_get_max_num_pp_cores(void); +/* Debug */ +u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size); + +#endif /* __MALI_PP_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_pp_job.c b/drivers/media/video/samsung/mali/common/mali_pp_job.c new file mode 100644 index 0000000..47b8a0a --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_pp_job.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_pp_job.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_kernel_common.h" +#include "mali_uk_types.h" + +struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, u32 id) +{ + struct mali_pp_job *job; + + if (args->num_cores > _MALI_PP_MAX_SUB_JOBS) + { + MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n")); + return NULL; + } + + job = _mali_osk_malloc(sizeof(struct mali_pp_job)); + if (NULL != job) + { + u32 i; + _mali_osk_list_init(&job->list); + job->session = session; + job->id = id; + job->user_id = args->user_job_ptr; + job->barrier = args->flags & _MALI_PP_JOB_FLAG_BARRIER ? MALI_TRUE : MALI_FALSE; + job->active_barrier = job->barrier; + job->no_notification = args->flags & _MALI_PP_JOB_FLAG_NO_NOTIFICATION ? MALI_TRUE : MALI_FALSE; + _mali_osk_memcpy(job->frame_registers, args->frame_registers, sizeof(job->frame_registers)); + _mali_osk_memcpy(job->frame_registers_addr_frame, args->frame_registers_addr_frame, sizeof(job->frame_registers_addr_frame)); + _mali_osk_memcpy(job->frame_registers_addr_stack, args->frame_registers_addr_stack, sizeof(job->frame_registers_addr_stack)); + + /* Only copy write back registers for the units that are enabled */ + job->wb0_registers[0] = 0; + job->wb1_registers[0] = 0; + job->wb2_registers[0] = 0; + if (args->wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ + { + _mali_osk_memcpy(job->wb0_registers, args->wb0_registers, sizeof(job->wb0_registers)); + } + if (args->wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ + { + _mali_osk_memcpy(job->wb1_registers, args->wb1_registers, sizeof(job->wb1_registers)); + } + if (args->wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ + { + _mali_osk_memcpy(job->wb2_registers, args->wb2_registers, sizeof(job->wb2_registers)); + } + + job->perf_counter_flag = args->perf_counter_flag; + job->perf_counter_src0 = args->perf_counter_src0; + job->perf_counter_src1 = args->perf_counter_src1; + for (i = 0; i < args->num_cores; i++) + { + job->perf_counter_value0[i] = 0; + job->perf_counter_value1[i] = 0; + } + job->sub_job_count = args->num_cores; + job->sub_jobs_started = 0; + job->sub_jobs_completed = 0; + job->sub_job_errors = 0; + + job->pid = _mali_osk_get_pid(); + job->tid = _mali_osk_get_tid(); + job->frame_builder_id = args->frame_builder_id; + job->flush_id = args->flush_id; + + return job; + } + + return NULL; +} + +void mali_pp_job_delete(struct mali_pp_job *job) +{ + _mali_osk_free(job); +} + +_mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job) +{ + if ((0 == job->frame_registers[0]) || (0 == job->frame_registers[1])) + { + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} diff --git a/drivers/media/video/samsung/mali/common/mali_pp_job.h b/drivers/media/video/samsung/mali/common/mali_pp_job.h new file mode 100644 index 0000000..4399c1d --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_pp_job.h @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PP_JOB_H__ +#define __MALI_PP_JOB_H__ + +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_uk_types.h" +#include "mali_session.h" +#include "mali_kernel_common.h" +#include "regs/mali_200_regs.h" + +/** + * The structure represends a PP job, including all sub-jobs + * (This struct unfortunatly needs to be public because of how the _mali_osk_list_* + * mechanism works) + */ +struct mali_pp_job +{ + _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */ + struct mali_session_data *session; /**< Session which submitted this job */ + u32 id; /**< identifier for this job in kernel space (sequencial numbering) */ + u32 user_id; /**< identifier for the job in user space */ + u32 frame_registers[_MALI_PP_MAX_FRAME_REGISTERS]; /**< core specific registers associated with this job, see ARM DDI0415A */ + u32 frame_registers_addr_frame[_MALI_PP_MAX_SUB_JOBS - 1]; /**< ADDR_FRAME registers for sub job 1-7 */ + u32 frame_registers_addr_stack[_MALI_PP_MAX_SUB_JOBS - 1]; /**< ADDR_STACK registers for sub job 1-7 */ + u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 0 registers */ + u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 1 registers */ + u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 2 registers */ + u32 perf_counter_flag; /**< bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ + u32 perf_counter_src0; /**< Source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ + u32 perf_counter_src1; /**< Source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ + u32 perf_counter_value0[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 0 (to be returned to user space), one for each sub job */ + u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 1 (to be returned to user space), one for each sub job */ + u32 sub_job_count; /**< Total number of sub-jobs in this superjob */ + u32 sub_jobs_started; /**< Total number of sub-jobs started (always started in ascending order) */ + u32 sub_jobs_completed; /**< Number of completed sub-jobs in this superjob */ + u32 sub_job_errors; /**< Bitfield with errors (errors for each single sub-job is or'ed together) */ + u32 pid; /**< Process ID of submitting process */ + u32 tid; /**< Thread ID of submitting thread */ + u32 frame_builder_id; /**< id of the originating frame builder */ + u32 flush_id; /**< flush id within the originating frame builder */ + mali_bool barrier; /**< [in] MALI_TRUE means wait for all my previous jobs to complete before scheduling this one */ + mali_bool active_barrier; /**< [in] Changes from MALI_TRUE to MALI_FALSE when barrier has been resolved */ + mali_bool no_notification; /**< [in] MALI_TRUE means do not notify user space when this job has completed */ +}; + +struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, u32 id); +void mali_pp_job_delete(struct mali_pp_job *job); + +_mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job); + +/****************************************************** + * simple utility functions for dealing with pp jobs: + *****************************************************/ + +MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job) +{ + return (NULL == job) ? 0 : job->id; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_user_id(struct mali_pp_job *job) +{ + return job->user_id; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_frame_builder_id(struct mali_pp_job *job) +{ + return job->frame_builder_id; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_flush_id(struct mali_pp_job *job) +{ + return job->flush_id; +} + +MALI_STATIC_INLINE u32* mali_pp_job_get_frame_registers(struct mali_pp_job *job) +{ + return job->frame_registers; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 sub_job) +{ + if (sub_job == 0) + { + return job->frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)]; + } + else if (sub_job < _MALI_PP_MAX_SUB_JOBS) + { + return job->frame_registers_addr_frame[sub_job - 1]; + } + + return 0; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 sub_job) +{ + if (sub_job == 0) + { + return job->frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)]; + } + else if (sub_job < _MALI_PP_MAX_SUB_JOBS) + { + return job->frame_registers_addr_stack[sub_job - 1]; + } + + return 0; +} + +MALI_STATIC_INLINE u32* mali_pp_job_get_wb0_registers(struct mali_pp_job *job) +{ + return job->wb0_registers; +} + +MALI_STATIC_INLINE u32* mali_pp_job_get_wb1_registers(struct mali_pp_job *job) +{ + return job->wb1_registers; +} + +MALI_STATIC_INLINE u32* mali_pp_job_get_wb2_registers(struct mali_pp_job *job) +{ + return job->wb2_registers; +} + +MALI_STATIC_INLINE void mali_pp_job_disable_wb0(struct mali_pp_job *job) +{ + job->wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; +} + +MALI_STATIC_INLINE void mali_pp_job_disable_wb1(struct mali_pp_job *job) +{ + job->wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; +} + +MALI_STATIC_INLINE void mali_pp_job_disable_wb2(struct mali_pp_job *job) +{ + job->wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; +} + +MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali_pp_job *job) +{ + return job->session; +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_has_unstarted_sub_jobs(struct mali_pp_job *job) +{ + return (job->sub_jobs_started < job->sub_job_count) ? MALI_TRUE : MALI_FALSE; +} + +/* Function used when we are terminating a session with jobs. Return TRUE if it has a rendering job. + Makes sure that no new subjobs is started. */ +MALI_STATIC_INLINE mali_bool mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(struct mali_pp_job *job) +{ + /* All can not be started, since then it would not be in the job queue */ + MALI_DEBUG_ASSERT( job->sub_jobs_started != job->sub_job_count ); + + /* If at least one job is started */ + if ( (job->sub_jobs_started > 0) ) + { + /* If at least one job is currently being rendered, and thus assigned to a group and core */ + if (job->sub_jobs_started > job->sub_jobs_completed ) + { + u32 jobs_remaining = job->sub_job_count - job->sub_jobs_started; + job->sub_jobs_started += jobs_remaining; + job->sub_jobs_completed += jobs_remaining; + job->sub_job_errors += jobs_remaining; + /* Returning TRUE indicating that we can not delete this job which is being redered */ + return MALI_TRUE; + } + } + /* The job is not being rendered to at the moment and can then safely be deleted */ + return MALI_FALSE; +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_is_complete(struct mali_pp_job *job) +{ + return (job->sub_job_count == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_job *job) +{ + return job->sub_jobs_started; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_sub_job_count(struct mali_pp_job *job) +{ + return job->sub_job_count; +} + +MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job, u32 sub_job) +{ + /* Assert that we are marking the "first unstarted sub job" as started */ + MALI_DEBUG_ASSERT(job->sub_jobs_started == sub_job); + job->sub_jobs_started++; +} + +MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_completed(struct mali_pp_job *job, mali_bool success) +{ + job->sub_jobs_completed++; + if ( MALI_FALSE == success ) + { + job->sub_job_errors++; + } +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_was_success(struct mali_pp_job *job) +{ + if ( 0 == job->sub_job_errors ) + { + return MALI_TRUE; + } + return MALI_FALSE; +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_has_active_barrier(struct mali_pp_job *job) +{ + return job->active_barrier; +} + +MALI_STATIC_INLINE void mali_pp_job_barrier_enforced(struct mali_pp_job *job) +{ + job->active_barrier = MALI_FALSE; +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_use_no_notification(struct mali_pp_job *job) +{ + return job->no_notification; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_flag(struct mali_pp_job *job) +{ + return job->perf_counter_flag; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src0(struct mali_pp_job *job) +{ + return job->perf_counter_src0; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src1(struct mali_pp_job *job) +{ + return job->perf_counter_src1; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value0(struct mali_pp_job *job, u32 sub_job) +{ + return job->perf_counter_value0[sub_job]; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value1(struct mali_pp_job *job, u32 sub_job) +{ + return job->perf_counter_value1[sub_job]; +} + +MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value0(struct mali_pp_job *job, u32 sub_job, u32 value) +{ + job->perf_counter_value0[sub_job] = value; +} + +MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value1(struct mali_pp_job *job, u32 sub_job, u32 value) +{ + job->perf_counter_value1[sub_job] = value; +} + +#endif /* __MALI_PP_JOB_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c new file mode 100644 index 0000000..a944055 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c @@ -0,0 +1,594 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_pp_scheduler.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_scheduler.h" +#include "mali_pp.h" +#include "mali_pp_job.h" +#include "mali_group.h" +#include "mali_cluster.h" + +/* Maximum of 8 PP cores (a group can only have maximum of 1 PP core) */ +#define MALI_MAX_NUMBER_OF_PP_GROUPS 8 + +static mali_bool mali_pp_scheduler_is_suspended(void); + +enum mali_pp_slot_state +{ + MALI_PP_SLOT_STATE_IDLE, + MALI_PP_SLOT_STATE_WORKING, +}; + +/* A render slot is an entity which jobs can be scheduled onto */ +struct mali_pp_slot +{ + struct mali_group *group; + /* + * We keep track of the state here as well as in the group object + * so we don't need to take the group lock so often (and also avoid clutter with the working lock) + */ + enum mali_pp_slot_state state; + struct mali_session_data *session; +}; + +static u32 pp_version = 0; +static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */ +static struct mali_pp_slot slots[MALI_MAX_NUMBER_OF_PP_GROUPS]; +static u32 num_slots = 0; +static u32 num_slots_idle = 0; + +/* Variables to allow safe pausing of the scheduler */ +static _mali_osk_wait_queue_t *pp_scheduler_working_wait_queue = NULL; +static u32 pause_count = 0; + +static _mali_osk_lock_t *pp_scheduler_lock = NULL; +/* Contains tid of thread that locked the scheduler or 0, if not locked */ +MALI_DEBUG_CODE(static u32 pp_scheduler_lock_owner = 0); + +_mali_osk_errcode_t mali_pp_scheduler_initialize(void) +{ + u32 i; + + _MALI_OSK_INIT_LIST_HEAD(&job_queue); + + pp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); + if (NULL == pp_scheduler_lock) + { + return _MALI_OSK_ERR_NOMEM; + } + + pp_scheduler_working_wait_queue = _mali_osk_wait_queue_init(); + if (NULL == pp_scheduler_working_wait_queue) + { + _mali_osk_lock_term(pp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } + + /* Find all the available PP cores */ + for (i = 0; i < mali_cluster_get_glob_num_clusters(); i++) + { + u32 group_id = 0; + struct mali_cluster *curr_cluster = mali_cluster_get_global_cluster(i); + struct mali_group *group = mali_cluster_get_group(curr_cluster, group_id); + while (NULL != group) + { + struct mali_pp_core *pp_core = mali_group_get_pp_core(group); + if (NULL != pp_core) + { + if (0 == pp_version) + { + /* Retrieve PP version from first avaiable PP core */ + pp_version = mali_pp_core_get_version(pp_core); + } + slots[num_slots].group = group; + slots[num_slots].state = MALI_PP_SLOT_STATE_IDLE; + slots[num_slots].session = NULL; + num_slots++; + num_slots_idle++; + } + group_id++; + group = mali_cluster_get_group(curr_cluster, group_id); + } + } + + return _MALI_OSK_ERR_OK; +} + +void mali_pp_scheduler_terminate(void) +{ + _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); + _mali_osk_lock_term(pp_scheduler_lock); +} + +MALI_STATIC_INLINE void mali_pp_scheduler_lock(void) +{ + if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW)) + { + /* Non-interruptable lock failed: this should never happen. */ + MALI_DEBUG_ASSERT(0); + } + MALI_DEBUG_PRINT(5, ("Mali PP scheduler: PP scheduler lock taken\n")); + MALI_DEBUG_ASSERT(0 == pp_scheduler_lock_owner); + MALI_DEBUG_CODE(pp_scheduler_lock_owner = _mali_osk_get_tid()); +} + +MALI_STATIC_INLINE void mali_pp_scheduler_unlock(void) +{ + MALI_DEBUG_PRINT(5, ("Mali PP scheduler: Releasing PP scheduler lock\n")); + MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner); + MALI_DEBUG_CODE(pp_scheduler_lock_owner = 0); + _mali_osk_lock_signal(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW); +} + +#ifdef DEBUG +MALI_STATIC_INLINE void mali_pp_scheduler_assert_locked(void) +{ + MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner); +} +#define MALI_ASSERT_PP_SCHEDULER_LOCKED() mali_pp_scheduler_assert_locked() +#else +#define MALI_ASSERT_PP_SCHEDULER_LOCKED() +#endif + +static mali_bool mali_pp_scheduler_session_has_running_jobs(struct mali_session_data *session) +{ + u32 i; + + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + + if (num_slots_idle == num_slots) + { + return MALI_FALSE; + } + + for (i = 0; i < num_slots; i++) + { + if (MALI_PP_SLOT_STATE_WORKING == slots[i].state) + { + if (slots[i].session == session) + { + return MALI_TRUE; + } + } + } + + return MALI_FALSE; +} + +static void mali_pp_scheduler_schedule(void) +{ + u32 i; + struct mali_pp_job *job; +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS + struct mali_session_data * session; +#endif + + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + + if (0 < pause_count || 0 == num_slots_idle || _mali_osk_list_empty(&job_queue)) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", + pause_count, num_slots_idle)); + return; /* Nothing to do, so early out */ + } + + +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP + if ( num_slots_idle < num_slots ) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started, since only %d/%d cores are available\n", num_slots_idle,num_slots)); + return; + } +#endif + +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS + /* Finding initial session for the PP cores */ + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); + session = job->session; + if ( num_slots != num_slots_idle ) + { + for (i = 0; (i < num_slots) ; i++) + { + if ( slots[i].state == MALI_PP_SLOT_STATE_IDLE ) + { + continue; + } + session = mali_group_get_session(slots[i].group); + break; + } + } +#endif + + for (i = 0; (i < num_slots) && (0 < num_slots_idle); i++) + { + u32 sub_job; + + if (_mali_osk_list_empty(&job_queue)) /* move this check down to where we know we have started all sub jobs for this job??? */ + { + break; /* No more jobs to schedule, so early out */ + } + + if (MALI_PP_SLOT_STATE_IDLE != slots[i].state) + { + continue; + } + + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); /* All jobs on the job_queue should have unstarted sub jobs */ + + if (MALI_TRUE == mali_pp_job_has_active_barrier(job)) + { + if (MALI_TRUE == mali_pp_scheduler_session_has_running_jobs(mali_pp_job_get_session(job))) + { + /* There is already a running job from this session, so we need to enforce the barrier */ + return; + } + else + { + /* Barrier is now enforced, update job object so we don't delay execution of sub-jobs */ + mali_pp_job_barrier_enforced(job); + } + } + + #if MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED + if ( (0==job->sub_jobs_started) && (num_slots_idle < num_slots) && (job->sub_job_count > num_slots_idle)) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job with %d subjobs not started, since only %d/%d cores are available\n", job->sub_job_count, num_slots_idle,num_slots)); + return; + } + #endif + + #if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS + if ( job->session != session ) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started since existing job is from another application\n")); + return; + } + #endif + + sub_job = mali_pp_job_get_first_unstarted_sub_job(job); + + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Starting job %u (0x%08X) part %u/%u\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job))); + if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(slots[i].group, job, sub_job)) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u started\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job))); + + /* Mark this sub job as started */ + mali_pp_job_mark_sub_job_started(job, sub_job); + + /* Mark slot as busy */ + slots[i].state = MALI_PP_SLOT_STATE_WORKING; + slots[i].session = mali_pp_job_get_session(job); + num_slots_idle--; + + if (!mali_pp_job_has_unstarted_sub_jobs(job)) + { + /* + * All sub jobs have now started for this job, remove this job from the job queue. + * The job will now only be referred to by the slots which are running it. + * The last slot to complete will make sure it is returned to user space. + */ + _mali_osk_list_del(&job->list); +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP + MALI_DEBUG_PRINT(6, ("Mali PP scheduler: Skip scheduling more jobs when MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP is set.\n")); + return; +#endif + } + } + else + { + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Failed to start PP job\n")); + return; + } + } +} + +static void mali_pp_scheduler_return_job_to_user(struct mali_pp_job *job) +{ + if (MALI_FALSE == mali_pp_job_use_no_notification(job)) + { + _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s)); + if (NULL != notobj) + { + u32 i; + u32 sub_jobs = mali_pp_job_get_sub_job_count(job); + mali_bool success = mali_pp_job_was_success(job); + + _mali_uk_pp_job_finished_s *jobres = notobj->result_buffer; + _mali_osk_memset(jobres, 0, sizeof(_mali_uk_pp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ + jobres->user_job_ptr = mali_pp_job_get_user_id(job); + if (MALI_TRUE == success) + { + jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; + } + else + { + jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; + } + + for (i = 0; i < sub_jobs; i++) + { + jobres->perf_counter0[i] = mali_pp_job_get_perf_counter_value0(job, i); + jobres->perf_counter1[i] = mali_pp_job_get_perf_counter_value1(job, i); + } + + mali_session_send_notification(mali_pp_job_get_session(job), notobj); + } + else + { + MALI_PRINT_ERROR(("Mali PP scheduler: Unable to allocate notification object\n")); + } + } + + mali_pp_job_delete(job); +} + +void mali_pp_scheduler_do_schedule(void) +{ + mali_pp_scheduler_lock(); + + mali_pp_scheduler_schedule(); + + mali_pp_scheduler_unlock(); +} + +void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success) +{ + u32 i; + mali_bool job_is_done; + + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u completed (%s)\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job), success ? "success" : "failure")); + + mali_pp_scheduler_lock(); + + /* Find slot which was running this job */ + for (i = 0; i < num_slots; i++) + { + if (slots[i].group == group) + { + MALI_DEBUG_ASSERT(MALI_PP_SLOT_STATE_WORKING == slots[i].state); + slots[i].state = MALI_PP_SLOT_STATE_IDLE; + slots[i].session = NULL; + num_slots_idle++; + mali_pp_job_mark_sub_job_completed(job, success); + } + } + + /* If paused, then this was the last job, so wake up sleeping workers */ + if (pause_count > 0) + { + /* Wake up sleeping workers. Their wake-up condition is that + * num_slots == num_slots_idle, so unless we are done working, no + * threads will actually be woken up. + */ + _mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue); + } + else + { + mali_pp_scheduler_schedule(); + } + + job_is_done = mali_pp_job_is_complete(job); + + mali_pp_scheduler_unlock(); + + if (job_is_done) + { + /* Send notification back to user space */ + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for job %u (0x%08X)\n", mali_pp_job_get_id(job), job)); + mali_pp_scheduler_return_job_to_user(job); + } +} + +void mali_pp_scheduler_suspend(void) +{ + mali_pp_scheduler_lock(); + pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ + mali_pp_scheduler_unlock(); + + /*mali_pp_scheduler_working_lock();*/ + /* We have now aquired the working lock, which means that we have successfully paused the scheduler */ + /*mali_pp_scheduler_working_unlock();*/ + + /* go to sleep. When woken up again (in mali_pp_scheduler_job_done), the + * mali_pp_scheduler_suspended() function will be called. This will return true + * iff state is idle and pause_count > 0, so if the core is active this + * will not do anything. + */ + _mali_osk_wait_queue_wait_event(pp_scheduler_working_wait_queue, mali_pp_scheduler_is_suspended); +} + +void mali_pp_scheduler_resume(void) +{ + mali_pp_scheduler_lock(); + pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */ + if (0 == pause_count) + { + mali_pp_scheduler_schedule(); + } + mali_pp_scheduler_unlock(); +} + +_mali_osk_errcode_t _mali_ukk_pp_start_job(_mali_uk_pp_start_job_s *args) +{ + struct mali_session_data *session; + struct mali_pp_job *job; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); + + session = (struct mali_session_data*)args->ctx; + + job = mali_pp_job_create(session, args, mali_scheduler_get_new_id()); + if (NULL == job) + { + return _MALI_OSK_ERR_NOMEM; + } + + if (_MALI_OSK_ERR_OK != mali_pp_job_check(job)) + { + /* Not a valid job, return to user immediately */ + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + +#if PROFILING_SKIP_PP_JOBS || PROFILING_SKIP_PP_AND_GP_JOBS +#warning PP jobs will not be executed + mali_pp_scheduler_return_job_to_user(job); + return _MALI_OSK_ERR_OK; +#endif + + mali_pp_scheduler_lock(); + + _mali_osk_list_addtail(&job->list, &job_queue); + + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) with %u parts queued\n", mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job))); + + mali_pp_scheduler_schedule(); + + mali_pp_scheduler_unlock(); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores(_mali_uk_get_pp_number_of_cores_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); + args->number_of_cores = num_slots; + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_get_pp_core_version(_mali_uk_get_pp_core_version_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); + args->version = pp_version; + return _MALI_OSK_ERR_OK; +} + +void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args) +{ + struct mali_session_data *session; + struct mali_pp_job *job; + struct mali_pp_job *tmp; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); + + session = (struct mali_session_data*)args->ctx; + + mali_pp_scheduler_lock(); + + /* Check queue for jobs that match */ + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list) + { + if (mali_pp_job_get_session(job) == session && + mali_pp_job_get_frame_builder_id(job) == (u32)args->fb_id && + mali_pp_job_get_flush_id(job) == (u32)args->flush_id) + { + if (args->wbx & _MALI_UK_PP_JOB_WB0) + { + mali_pp_job_disable_wb0(job); + } + if (args->wbx & _MALI_UK_PP_JOB_WB1) + { + mali_pp_job_disable_wb1(job); + } + if (args->wbx & _MALI_UK_PP_JOB_WB2) + { + mali_pp_job_disable_wb2(job); + } + break; + } + } + + mali_pp_scheduler_unlock(); +} + +void mali_pp_scheduler_abort_session(struct mali_session_data *session) +{ + struct mali_pp_job *job, *tmp; + int i; + + mali_pp_scheduler_lock(); + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Aborting all jobs from session 0x%08x\n", session)); + + /* Check queue for jobs and remove */ + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list) + { + if (mali_pp_job_get_session(job) == session) + { + _mali_osk_list_del(&(job->list)); + + if ( mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(job) ) + { + /* The job is in the render pipeline, we can not delete it yet. */ + /* It will be deleted in the mali_group_abort_session() call below */ + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Keeping partially started PP job 0x%08x in queue\n", job)); + continue; + } + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Removing PP job 0x%08x from queue\n", job)); + mali_pp_job_delete(job); + } + } + + mali_pp_scheduler_unlock(); + + /* Abort running jobs from this session */ + for (i = 0; i < num_slots; i++) + { + struct mali_group *group = slots[i].group; + + MALI_DEBUG_PRINT(5, ("PP sched abort: Looking at group 0x%08x\n", group)); + + if (MALI_PP_SLOT_STATE_WORKING == slots[i].state) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Aborting session 0x%08x from group 0x%08x\n", session, group)); + + mali_group_abort_session(group, session); + } + } +} + +static mali_bool mali_pp_scheduler_is_suspended(void) +{ + mali_bool ret; + + mali_pp_scheduler_lock(); + ret = pause_count > 0 && num_slots == num_slots_idle; + mali_pp_scheduler_unlock(); + + return ret; +} + +#if MALI_STATE_TRACKING +u32 mali_pp_scheduler_dump_state(char *buf, u32 size) +{ + int n = 0; + int i; + + n += _mali_osk_snprintf(buf + n, size - n, "PP:\n"); + n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty"); + n += _mali_osk_snprintf(buf + n, size - n, "\n"); + + for (i = 0; i < num_slots; i++) + { + n += mali_group_dump_state(slots[i].group, buf + n, size - n); + n += _mali_osk_snprintf(buf + n, size - n, "\t\tState: %d\n", slots[i].state); + } + + return n; +} +#endif diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h new file mode 100644 index 0000000..48eb3bd --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PP_SCHEDULER_H__ +#define __MALI_PP_SCHEDULER_H__ + +#include "mali_osk.h" +#include "mali_cluster.h" +#include "mali_pp_job.h" + +_mali_osk_errcode_t mali_pp_scheduler_initialize(void); +void mali_pp_scheduler_terminate(void); + +void mali_pp_scheduler_do_schedule(void); +void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success); + +void mali_pp_scheduler_suspend(void); +void mali_pp_scheduler_resume(void); + +/** @brief Abort all PP jobs from session running or queued + * + * This functions aborts all PP jobs from the specified session. Queued jobs are removed from the queue and jobs + * currently running on a core will be aborted. + * + * @param session Pointer to session whose jobs should be aborted + */ +void mali_pp_scheduler_abort_session(struct mali_session_data *session); + +u32 mali_pp_scheduler_dump_state(char *buf, u32 size); + +#endif /* __MALI_PP_SCHEDULER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_scheduler.c b/drivers/media/video/samsung/mali/common/mali_scheduler.c new file mode 100644 index 0000000..f360209 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_scheduler.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" + +static _mali_osk_atomic_t mali_job_autonumber; + +_mali_osk_errcode_t mali_scheduler_initialize(void) +{ + if ( _MALI_OSK_ERR_OK != _mali_osk_atomic_init(&mali_job_autonumber, 0)) + { + MALI_DEBUG_PRINT(1, ("Initialization of atomic job id counter failed.\n")); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; +} + +void mali_scheduler_terminate(void) +{ + _mali_osk_atomic_term(&mali_job_autonumber); +} + +u32 mali_scheduler_get_new_id(void) +{ + u32 job_id = _mali_osk_atomic_inc_return(&mali_job_autonumber); + return job_id; +} + diff --git a/drivers/media/video/samsung/mali/common/mali_scheduler.h b/drivers/media/video/samsung/mali/common/mali_scheduler.h new file mode 100644 index 0000000..74f0947 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_scheduler.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_SCHEDULER_H__ +#define __MALI_SCHEDULER_H__ + +#include "mali_osk.h" + +_mali_osk_errcode_t mali_scheduler_initialize(void); +void mali_scheduler_terminate(void); + +u32 mali_scheduler_get_new_id(void); + +#endif /* __MALI_SCHEDULER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_session.c b/drivers/media/video/samsung/mali/common/mali_session.c new file mode 100644 index 0000000..2394bb9 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_session.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_session.h" + +_MALI_OSK_LIST_HEAD(mali_sessions); + +_mali_osk_lock_t *mali_sessions_lock; + +_mali_osk_errcode_t mali_session_initialize(void) +{ + _MALI_OSK_INIT_LIST_HEAD(&mali_sessions); + + mali_sessions_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_SESSIONS); + + if (NULL == mali_sessions_lock) return _MALI_OSK_ERR_NOMEM; + + return _MALI_OSK_ERR_OK; +} + +void mali_session_terminate(void) +{ + _mali_osk_lock_term(mali_sessions_lock); +} + +void mali_session_add(struct mali_session_data *session) +{ + mali_session_lock(); + _mali_osk_list_add(&session->link, &mali_sessions); + mali_session_unlock(); +} + +void mali_session_remove(struct mali_session_data *session) +{ + mali_session_lock(); + _mali_osk_list_delinit(&session->link); + mali_session_unlock(); +} diff --git a/drivers/media/video/samsung/mali/common/mali_session.h b/drivers/media/video/samsung/mali/common/mali_session.h new file mode 100644 index 0000000..c8640b5 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_session.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_SESSION_H__ +#define __MALI_SESSION_H__ + +#include "mali_mmu_page_directory.h" +#include "mali_kernel_descriptor_mapping.h" +#include "mali_osk.h" +#include "mali_osk_list.h" + +struct mali_session_data +{ + _mali_osk_notification_queue_t * ioctl_queue; + + _mali_osk_lock_t *memory_lock; /**< Lock protecting the vm manipulation */ + mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */ + _mali_osk_list_t memory_head; /**< Track all the memory allocated in this session, for freeing on abnormal termination */ + + struct mali_page_directory *page_directory; /**< MMU page directory for this session */ + + _MALI_OSK_LIST_HEAD(link); /**< Link for list of all sessions */ +}; + +_mali_osk_errcode_t mali_session_initialize(void); +void mali_session_terminate(void); + +/* List of all sessions. Actual list head in mali_kernel_core.c */ +extern _mali_osk_list_t mali_sessions; +/* Lock to protect modification and access to the mali_sessions list */ +extern _mali_osk_lock_t *mali_sessions_lock; + +MALI_STATIC_INLINE void mali_session_lock(void) +{ + _mali_osk_lock_wait(mali_sessions_lock, _MALI_OSK_LOCKMODE_RW); +} + +MALI_STATIC_INLINE void mali_session_unlock(void) +{ + _mali_osk_lock_signal(mali_sessions_lock, _MALI_OSK_LOCKMODE_RW); +} + +void mali_session_add(struct mali_session_data *session); +void mali_session_remove(struct mali_session_data *session); +#define MALI_SESSION_FOREACH(session, tmp, link) \ + _MALI_OSK_LIST_FOREACHENTRY(session, tmp, &mali_sessions, struct mali_session_data, link) + +MALI_STATIC_INLINE struct mali_page_directory *mali_session_get_page_directory(struct mali_session_data *session) +{ + return session->page_directory; +} + +MALI_STATIC_INLINE void mali_session_send_notification(struct mali_session_data *session, _mali_osk_notification_t *object) +{ + _mali_osk_notification_queue_send(session->ioctl_queue, object); +} + +#endif /* __MALI_SESSION_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_ukk.h b/drivers/media/video/samsung/mali/common/mali_ukk.h new file mode 100644 index 0000000..6b018d0 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_ukk.h @@ -0,0 +1,612 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_ukk.h + * Defines the kernel-side interface of the user-kernel interface + */ + +#ifndef __MALI_UKK_H__ +#define __MALI_UKK_H__ + +#include "mali_osk.h" +#include "mali_uk_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @addtogroup uddapi Unified Device Driver (UDD) APIs + * + * @{ + */ + +/** + * @addtogroup u_k_api UDD User/Kernel Interface (U/K) APIs + * + * - The _mali_uk functions are an abstraction of the interface to the device + * driver. On certain OSs, this would be implemented via the IOCTL interface. + * On other OSs, it could be via extension of some Device Driver Class, or + * direct function call for Bare metal/RTOSs. + * - It is important to note that: + * - The Device Driver has implemented the _mali_ukk set of functions + * - The Base Driver calls the corresponding set of _mali_uku functions. + * - What requires porting is solely the calling mechanism from User-side to + * Kernel-side, and propagating back the results. + * - Each U/K function is associated with a (group, number) pair from + * \ref _mali_uk_functions to make it possible for a common function in the + * Base Driver and Device Driver to route User/Kernel calls from/to the + * correct _mali_uk function. For example, in an IOCTL system, the IOCTL number + * would be formed based on the group and number assigned to the _mali_uk + * function, as listed in \ref _mali_uk_functions. On the user-side, each + * _mali_uku function would just make an IOCTL with the IOCTL-code being an + * encoded form of the (group, number) pair. On the kernel-side, the Device + * Driver's IOCTL handler decodes the IOCTL-code back into a (group, number) + * pair, and uses this to determine which corresponding _mali_ukk should be + * called. + * - Refer to \ref _mali_uk_functions for more information about this + * (group, number) pairing. + * - In a system where there is no distinction between user and kernel-side, + * the U/K interface may be implemented as:@code + * MALI_STATIC_INLINE _mali_osk_errcode_t _mali_uku_examplefunction( _mali_uk_examplefunction_s *args ) + * { + * return mali_ukk_examplefunction( args ); + * } + * @endcode + * - Therefore, all U/K calls behave \em as \em though they were direct + * function calls (but the \b implementation \em need \em not be a direct + * function calls) + * + * @note Naming the _mali_uk functions the same on both User and Kernel sides + * on non-RTOS systems causes debugging issues when setting breakpoints. In + * this case, it is not clear which function the breakpoint is put on. + * Therefore the _mali_uk functions in user space are prefixed with \c _mali_uku + * and in kernel space with \c _mali_ukk. The naming for the argument + * structures is unaffected. + * + * - The _mali_uk functions are synchronous. + * - Arguments to the _mali_uk functions are passed in a structure. The only + * parameter passed to the _mali_uk functions is a pointer to this structure. + * This first member of this structure, ctx, is a pointer to a context returned + * by _mali_uku_open(). For example:@code + * typedef struct + * { + * void *ctx; + * u32 number_of_cores; + * } _mali_uk_get_gp_number_of_cores_s; + * @endcode + * + * - Each _mali_uk function has its own argument structure named after the + * function. The argument is distinguished by the _s suffix. + * - The argument types are defined by the base driver and user-kernel + * interface. + * - All _mali_uk functions return a standard \ref _mali_osk_errcode_t. + * - Only arguments of type input or input/output need be initialized before + * calling a _mali_uk function. + * - Arguments of type output and input/output are only valid when the + * _mali_uk function returns \ref _MALI_OSK_ERR_OK. + * - The \c ctx member is always invalid after it has been used by a + * _mali_uk function, except for the context management functions + * + * + * \b Interface \b restrictions + * + * The requirements of the interface mean that an implementation of the + * User-kernel interface may do no 'real' work. For example, the following are + * illegal in the User-kernel implementation: + * - Calling functions necessary for operation on all systems, which would + * not otherwise get called on RTOS systems. + * - For example, a U/K interface that calls multiple _mali_ukk functions + * during one particular U/K call. This could not be achieved by the same code + * which uses direct function calls for the U/K interface. + * - Writing in values to the args members, when otherwise these members would + * not hold a useful value for a direct function call U/K interface. + * - For example, U/K interface implementation that take NULL members in + * their arguments structure from the user side, but those members are + * replaced with non-NULL values in the kernel-side of the U/K interface + * implementation. A scratch area for writing data is one such example. In this + * case, a direct function call U/K interface would segfault, because no code + * would be present to replace the NULL pointer with a meaningful pointer. + * - Note that we discourage the case where the U/K implementation changes + * a NULL argument member to non-NULL, and then the Device Driver code (outside + * of the U/K layer) re-checks this member for NULL, and corrects it when + * necessary. Whilst such code works even on direct function call U/K + * intefaces, it reduces the testing coverage of the Device Driver code. This + * is because we have no way of testing the NULL == value path on an OS + * implementation. + * + * A number of allowable examples exist where U/K interfaces do 'real' work: + * - The 'pointer switching' technique for \ref _mali_ukk_get_system_info + * - In this case, without the pointer switching on direct function call + * U/K interface, the Device Driver code still sees the same thing: a pointer + * to which it can write memory. This is because such a system has no + * distinction between a user and kernel pointer. + * - Writing an OS-specific value into the ukk_private member for + * _mali_ukk_mem_mmap(). + * - In this case, this value is passed around by Device Driver code, but + * its actual value is never checked. Device Driver code simply passes it from + * the U/K layer to the OSK layer, where it can be acted upon. In this case, + * \em some OS implementations of the U/K (_mali_ukk_mem_mmap()) and OSK + * (_mali_osk_mem_mapregion_init()) functions will collaborate on the + * meaning of ukk_private member. On other OSs, it may be unused by both + * U/K and OSK layers + * - Therefore, on error inside the U/K interface implementation itself, + * it will be as though the _mali_ukk function itself had failed, and cleaned + * up after itself. + * - Compare this to a direct function call U/K implementation, where all + * error cleanup is handled by the _mali_ukk function itself. The direct + * function call U/K interface implementation is automatically atomic. + * + * The last example highlights a consequence of all U/K interface + * implementations: they must be atomic with respect to the Device Driver code. + * And therefore, should Device Driver code succeed but the U/K implementation + * fail afterwards (but before return to user-space), then the U/K + * implementation must cause appropriate cleanup actions to preserve the + * atomicity of the interface. + * + * @{ + */ + + +/** @defgroup _mali_uk_context U/K Context management + * + * These functions allow for initialisation of the user-kernel interface once per process. + * + * Generally the context will store the OS specific object to communicate with the kernel device driver and further + * state information required by the specific implementation. The context is shareable among all threads in the caller process. + * + * On IOCTL systems, this is likely to be a file descriptor as a result of opening the kernel device driver. + * + * On a bare-metal/RTOS system with no distinction between kernel and + * user-space, the U/K interface simply calls the _mali_ukk variant of the + * function by direct function call. In this case, the context returned is the + * mali_session_data from _mali_ukk_open(). + * + * The kernel side implementations of the U/K interface expect the first member of the argument structure to + * be the context created by _mali_uku_open(). On some OS implementations, the meaning of this context + * will be different between user-side and kernel-side. In which case, the kernel-side will need to replace this context + * with the kernel-side equivalent, because user-side will not have access to kernel-side data. The context parameter + * in the argument structure therefore has to be of type input/output. + * + * It should be noted that the caller cannot reuse the \c ctx member of U/K + * argument structure after a U/K call, because it may be overwritten. Instead, + * the context handle must always be stored elsewhere, and copied into + * the appropriate U/K argument structure for each user-side call to + * the U/K interface. This is not usually a problem, since U/K argument + * structures are usually placed on the stack. + * + * @{ */ + +/** @brief Begin a new Mali Device Driver session + * + * This is used to obtain a per-process context handle for all future U/K calls. + * + * @param context pointer to storage to return a (void*)context handle. + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_open( void **context ); + +/** @brief End a Mali Device Driver session + * + * This should be called when the process no longer requires use of the Mali Device Driver. + * + * The context handle must not be used after it has been closed. + * + * @param context pointer to a stored (void*)context handle. + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_close( void **context ); + +/** @} */ /* end group _mali_uk_context */ + + +/** @addtogroup _mali_uk_core U/K Core + * + * The core functions provide the following functionality: + * - verify that the user and kernel API are compatible + * - retrieve information about the cores and memory banks in the system + * - wait for the result of jobs started on a core + * + * @{ */ + +/** @brief Waits for a job notification. + * + * Sleeps until notified or a timeout occurs. Returns information about the notification. + * + * @param args see _mali_uk_wait_for_notification_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args ); + +/** @brief Post a notification to the notification queue of this application. + * + * @param args see _mali_uk_post_notification_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args ); + +/** @brief Verifies if the user and kernel side of this API are compatible. + * + * @param args see _mali_uk_get_api_version_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args ); + +/** @brief Get the user space settings applicable for calling process. + * + * @param args see _mali_uk_get_user_settings_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args); + +/** @brief Get a user space setting applicable for calling process. + * + * @param args see _mali_uk_get_user_setting_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args); + +/** @} */ /* end group _mali_uk_core */ + + +/** @addtogroup _mali_uk_memory U/K Memory + * + * The memory functions provide functionality with and without a Mali-MMU present. + * + * For Mali-MMU based systems, the following functionality is provided: + * - Initialize and terminate MALI virtual address space + * - Allocate/deallocate physical memory to a MALI virtual address range and map into/unmap from the + * current process address space + * - Map/unmap external physical memory into the MALI virtual address range + * + * For Mali-nonMMU based systems: + * - Allocate/deallocate MALI memory + * + * @{ */ + +/** + * @brief Initialize the Mali-MMU Memory system + * + * For Mali-MMU builds of the drivers, this function must be called before any + * other functions in the \ref _mali_uk_memory group are called. + * + * @note This function is for Mali-MMU builds \b only. It should not be called + * when the drivers are built without Mali-MMU support. + * + * @param args see \ref _mali_uk_init_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable + * _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args ); + +/** + * @brief Terminate the MMU Memory system + * + * For Mali-MMU builds of the drivers, this function must be called when + * functions in the \ref _mali_uk_memory group will no longer be called. This + * function must be called before the application terminates. + * + * @note This function is for Mali-MMU builds \b only. It should not be called + * when the drivers are built without Mali-MMU support. + * + * @param args see \ref _mali_uk_term_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable + * _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args ); + +/** @brief Map Mali Memory into the current user process + * + * Maps Mali memory into the current user process in a generic way. + * + * This function is to be used for Mali-MMU mode. The function is available in both Mali-MMU and Mali-nonMMU modes, + * but should not be called by a user process in Mali-nonMMU mode. + * + * The implementation and operation of _mali_ukk_mem_mmap() is dependant on whether the driver is built for Mali-MMU + * or Mali-nonMMU: + * - In the nonMMU case, _mali_ukk_mem_mmap() requires a physical address to be specified. For this reason, an OS U/K + * implementation should not allow this to be called from user-space. In any case, nonMMU implementations are + * inherently insecure, and so the overall impact is minimal. Mali-MMU mode should be used if security is desired. + * - In the MMU case, _mali_ukk_mem_mmap() the _mali_uk_mem_mmap_s::phys_addr + * member is used for the \em Mali-virtual address desired for the mapping. The + * implementation of _mali_ukk_mem_mmap() will allocate both the CPU-virtual + * and CPU-physical addresses, and can cope with mapping a contiguous virtual + * address range to a sequence of non-contiguous physical pages. In this case, + * the CPU-physical addresses are not communicated back to the user-side, as + * they are unnecsessary; the \em Mali-virtual address range must be used for + * programming Mali structures. + * + * In the second (MMU) case, _mali_ukk_mem_mmap() handles management of + * CPU-virtual and CPU-physical ranges, but the \em caller must manage the + * \em Mali-virtual address range from the user-side. + * + * @note Mali-virtual address ranges are entirely separate between processes. + * It is not possible for a process to accidentally corrupt another process' + * \em Mali-virtual address space. + * + * @param args see _mali_uk_mem_mmap_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args ); + +/** @brief Unmap Mali Memory from the current user process + * + * Unmaps Mali memory from the current user process in a generic way. This only operates on Mali memory supplied + * from _mali_ukk_mem_mmap(). + * + * @param args see _mali_uk_mem_munmap_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args ); + +/** @brief Determine the buffer size necessary for an MMU page table dump. + * @param args see _mali_uk_query_mmu_page_table_dump_size_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args ); +/** @brief Dump MMU Page tables. + * @param args see _mali_uk_dump_mmu_page_table_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args ); + +/** @brief Map a physically contiguous range of memory into Mali + * @param args see _mali_uk_map_external_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args ); + +/** @brief Unmap a physically contiguous range of memory from Mali + * @param args see _mali_uk_unmap_external_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args ); + +#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +/** @brief Map UMP memory into Mali + * @param args see _mali_uk_attach_ump_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args ); +/** @brief Unmap UMP memory from Mali + * @param args see _mali_uk_release_ump_mem_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args ); +#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */ + +/** @brief Determine virtual-to-physical mapping of a contiguous memory range + * (optional) + * + * This allows the user-side to do a virtual-to-physical address translation. + * In conjunction with _mali_uku_map_external_mem, this can be used to do + * direct rendering. + * + * This function will only succeed on a virtual range that is mapped into the + * current process, and that is contigious. + * + * If va is not page-aligned, then it is rounded down to the next page + * boundary. The remainer is added to size, such that ((u32)va)+size before + * rounding is equal to ((u32)va)+size after rounding. The rounded modified + * va and size will be written out into args on success. + * + * If the supplied size is zero, or not a multiple of the system's PAGE_SIZE, + * then size will be rounded up to the next multiple of PAGE_SIZE before + * translation occurs. The rounded up size will be written out into args on + * success. + * + * On most OSs, virtual-to-physical address translation is a priveledged + * function. Therefore, the implementer must validate the range supplied, to + * ensure they are not providing arbitrary virtual-to-physical address + * translations. While it is unlikely such a mechanism could be used to + * compromise the security of a system on its own, it is possible it could be + * combined with another small security risk to cause a much larger security + * risk. + * + * @note This is an optional part of the interface, and is only used by certain + * implementations of libEGL. If the platform layer in your libEGL + * implementation does not require Virtual-to-Physical address translation, + * then this function need not be implemented. A stub implementation should not + * be required either, as it would only be removed by the compiler's dead code + * elimination. + * + * @note if implemented, this function is entirely platform-dependant, and does + * not exist in common code. + * + * @param args see _mali_uk_va_to_mali_pa_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args ); + +/** @} */ /* end group _mali_uk_memory */ + + +/** @addtogroup _mali_uk_pp U/K Fragment Processor + * + * The Fragment Processor (aka PP (Pixel Processor)) functions provide the following functionality: + * - retrieving version of the fragment processors + * - determine number of fragment processors + * - starting a job on a fragment processor + * + * @{ */ + +/** @brief Issue a request to start a new job on a Fragment Processor. + * + * If the request fails args->status is set to _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE and you can + * try to start the job again. + * + * An existing job could be returned for requeueing if the new job has a higher priority than a previously started job + * which the hardware hasn't actually started processing yet. In this case the new job will be started instead and the + * existing one returned, otherwise the new job is started and the status field args->status is set to + * _MALI_UK_START_JOB_STARTED. + * + * Job completion can be awaited with _mali_ukk_wait_for_notification(). + * + * @param args see _mali_uk_pp_start_job_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_pp_start_job( _mali_uk_pp_start_job_s *args ); + +/** @brief Returns the number of Fragment Processors in the system + * + * @param args see _mali_uk_get_pp_number_of_cores_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores( _mali_uk_get_pp_number_of_cores_s *args ); + +/** @brief Returns the version that all Fragment Processor cores are compatible with. + * + * This function may only be called when _mali_ukk_get_pp_number_of_cores() indicated at least one Fragment + * Processor core is available. + * + * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_get_pp_core_version( _mali_uk_get_pp_core_version_s *args ); + +/** @brief Disable Write-back unit(s) on specified job + * + * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h" + */ +void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args); + + +/** @} */ /* end group _mali_uk_pp */ + + +/** @addtogroup _mali_uk_gp U/K Vertex Processor + * + * The Vertex Processor (aka GP (Geometry Processor)) functions provide the following functionality: + * - retrieving version of the Vertex Processors + * - determine number of Vertex Processors available + * - starting a job on a Vertex Processor + * + * @{ */ + +/** @brief Issue a request to start a new job on a Vertex Processor. + * + * If the request fails args->status is set to _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE and you can + * try to start the job again. + * + * An existing job could be returned for requeueing if the new job has a higher priority than a previously started job + * which the hardware hasn't actually started processing yet. In this case the new job will be started and the + * existing one returned, otherwise the new job is started and the status field args->status is set to + * _MALI_UK_START_JOB_STARTED. + * + * Job completion can be awaited with _mali_ukk_wait_for_notification(). + * + * @param args see _mali_uk_gp_start_job_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_gp_start_job( _mali_uk_gp_start_job_s *args ); + +/** @brief Returns the number of Vertex Processors in the system. + * + * @param args see _mali_uk_get_gp_number_of_cores_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores( _mali_uk_get_gp_number_of_cores_s *args ); + +/** @brief Returns the version that all Vertex Processor cores are compatible with. + * + * This function may only be called when _mali_uk_get_gp_number_of_cores() indicated at least one Vertex + * Processor core is available. + * + * @param args see _mali_uk_get_gp_core_version_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_get_gp_core_version( _mali_uk_get_gp_core_version_s *args ); + +/** @brief Resume or abort suspended Vertex Processor jobs. + * + * After receiving notification that a Vertex Processor job was suspended from + * _mali_ukk_wait_for_notification() you can use this function to resume or abort the job. + * + * @param args see _mali_uk_gp_suspend_response_s in "mali_utgard_uk_types.h" + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_gp_suspend_response( _mali_uk_gp_suspend_response_s *args ); + +/** @} */ /* end group _mali_uk_gp */ + +#if MALI_TIMELINE_PROFILING_ENABLED +/** @addtogroup _mali_uk_profiling U/K Timeline profiling module + * @{ */ + +/** @brief Start recording profiling events. + * + * @param args see _mali_uk_profiling_start_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args); + +/** @brief Add event to profiling buffer. + * + * @param args see _mali_uk_profiling_add_event_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args); + +/** @brief Stop recording profiling events. + * + * @param args see _mali_uk_profiling_stop_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args); + +/** @brief Retrieve a recorded profiling event. + * + * @param args see _mali_uk_profiling_get_event_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args); + +/** @brief Clear recorded profiling events. + * + * @param args see _mali_uk_profiling_clear_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args); + +/** @} */ /* end group _mali_uk_profiling */ +#endif + +/** @addtogroup _mali_uk_vsync U/K VSYNC reporting module + * @{ */ + +/** @brief Report events related to vsync. + * + * @note Events should be reported when starting to wait for vsync and when the + * waiting is finished. This information can then be used in kernel space to + * complement the GPU utilization metric. + * + * @param args see _mali_uk_vsync_event_report_s in "mali_utgard_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args); + +/** @} */ /* end group _mali_uk_vsync */ + +/** @addtogroup _mali_sw_counters_report U/K Software counter reporting + * @{ */ + +/** @brief Report software counters. + * + * @param args see _mali_uk_sw_counters_report_s in "mali_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args); + +/** @} */ /* end group _mali_sw_counters_report */ + +/** @} */ /* end group u_k_api */ + +/** @} */ /* end group uddapi */ + +u32 _mali_ukk_report_memory_usage(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_UKK_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_user_settings_db.c b/drivers/media/video/samsung/mali/common/mali_user_settings_db.c new file mode 100644 index 0000000..d3f1e50 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_user_settings_db.c @@ -0,0 +1,88 @@ +/** + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_uk_types.h" +#include "mali_user_settings_db.h" +#include "mali_session.h" + +static u32 mali_user_settings[_MALI_UK_USER_SETTING_MAX]; +const char *_mali_uk_user_setting_descriptions[] = _MALI_UK_USER_SETTING_DESCRIPTIONS; + +static void mali_user_settings_notify(_mali_uk_user_setting_t setting, u32 value) +{ + struct mali_session_data *session, *tmp; + + mali_session_lock(); + MALI_SESSION_FOREACH(session, tmp, link) + { + _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_SETTINGS_CHANGED, sizeof(_mali_uk_settings_changed_s)); + _mali_uk_settings_changed_s *data = notobj->result_buffer; + data->setting = setting; + data->value = value; + + mali_session_send_notification(session, notobj); + } + mali_session_unlock(); +} + +void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value) +{ + mali_bool notify = MALI_FALSE; + + MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0); + + if (mali_user_settings[setting] != value) + { + notify = MALI_TRUE; + } + + mali_user_settings[setting] = value; + + if (notify) + { + mali_user_settings_notify(setting, value); + } +} + +u32 mali_get_user_setting(_mali_uk_user_setting_t setting) +{ + MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0); + + return mali_user_settings[setting]; +} + +_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args) +{ + _mali_uk_user_setting_t setting; + MALI_DEBUG_ASSERT_POINTER(args); + + setting = args->setting; + + if (0 <= setting && _MALI_UK_USER_SETTING_MAX > setting) + { + args->value = mali_user_settings[setting]; + return _MALI_OSK_ERR_OK; + } + else + { + return _MALI_OSK_ERR_INVALID_ARGS; + } +} + +_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + + _mali_osk_memcpy(args->settings, mali_user_settings, sizeof(mali_user_settings)); + + return _MALI_OSK_ERR_OK; +} diff --git a/drivers/media/video/samsung/mali/common/mali_user_settings_db.h b/drivers/media/video/samsung/mali/common/mali_user_settings_db.h new file mode 100644 index 0000000..fbb9415 --- /dev/null +++ b/drivers/media/video/samsung/mali/common/mali_user_settings_db.h @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_USER_SETTINGS_DB_H__ +#define __MALI_USER_SETTINGS_DB_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mali_uk_types.h" + +/** @brief Set Mali user setting in DB + * + * Update the DB with a new value for \a setting. If the value is different from theprevious set value running sessions will be notified of the change. + * + * @param setting the setting to be changed + * @param value the new value to set + */ +void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value); + +/** @brief Get current Mali user setting value from DB + * + * @param setting the setting to extract + * @return the value of the selected setting + */ +u32 mali_get_user_setting(_mali_uk_user_setting_t setting); + +#ifdef __cplusplus +} +#endif +#endif /* __MALI_KERNEL_USER_SETTING__ */ diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h new file mode 100644 index 0000000..7c78947 --- /dev/null +++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_UTGARD_H__ +#define __MALI_UTGARD_H__ + +/** @brief MALI GPU power down using MALI in-built PMU + * + * called to power down all cores + */ +int mali_pmu_powerdown(void); + + +/** @brief MALI GPU power up using MALI in-built PMU + * + * called to power up all cores + */ +int mali_pmu_powerup(void); + +#endif /* __MALI_UTGARD_H__ */ + diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h new file mode 100644 index 0000000..40822f7 --- /dev/null +++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _MALI_UTGARD_COUNTERS_H_ +#define _MALI_UTGARD_COUNTERS_H_ + +typedef struct +{ + void *unused; +} mali_cinstr_counter_info; + +typedef enum +{ + MALI_CINSTR_COUNTER_SOURCE_EGL = 0, + MALI_CINSTR_COUNTER_SOURCE_OPENGLES = 1000, + MALI_CINSTR_COUNTER_SOURCE_OPENVG = 2000, + MALI_CINSTR_COUNTER_SOURCE_GP = 3000, + MALI_CINSTR_COUNTER_SOURCE_PP = 4000, +} cinstr_counter_source; + +#define MALI_CINSTR_EGL_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_EGL +#define MALI_CINSTR_EGL_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_EGL + 999) + +#define MALI_CINSTR_GLES_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_OPENGLES +#define MALI_CINSTR_GLES_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 999) + +#define MALI_CINSTR_VG_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_OPENVG +#define MALI_CINSTR_VG_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_OPENVG + 999) + +#define MALI_CINSTR_GP_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_GP +#define MALI_CINSTR_GP_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_GP + 999) + +#define MALI_CINSTR_PP_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_PP +#define MALI_CINSTR_PP_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_PP + 999) + + +typedef enum +{ + /* EGL counters */ + + MALI_CINSTR_EGL_BLIT_TIME = MALI_CINSTR_COUNTER_SOURCE_EGL + 0, + + /* Last counter in the EGL set */ + MALI_CINSTR_EGL_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_EGL + 1, + + /* GLES counters */ + + MALI_CINSTR_GLES_DRAW_ELEMENTS_CALLS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 0, + MALI_CINSTR_GLES_DRAW_ELEMENTS_NUM_INDICES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 1, + MALI_CINSTR_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 2, + MALI_CINSTR_GLES_DRAW_ARRAYS_CALLS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 3, + MALI_CINSTR_GLES_DRAW_ARRAYS_NUM_TRANSFORMED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 4, + MALI_CINSTR_GLES_DRAW_POINTS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 5, + MALI_CINSTR_GLES_DRAW_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 6, + MALI_CINSTR_GLES_DRAW_LINE_LOOP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 7, + MALI_CINSTR_GLES_DRAW_LINE_STRIP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 8, + MALI_CINSTR_GLES_DRAW_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 9, + MALI_CINSTR_GLES_DRAW_TRIANGLE_STRIP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 10, + MALI_CINSTR_GLES_DRAW_TRIANGLE_FAN = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 11, + MALI_CINSTR_GLES_NON_VBO_DATA_COPY_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 12, + MALI_CINSTR_GLES_UNIFORM_BYTES_COPIED_TO_MALI = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 13, + MALI_CINSTR_GLES_UPLOAD_TEXTURE_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 14, + MALI_CINSTR_GLES_UPLOAD_VBO_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 15, + MALI_CINSTR_GLES_NUM_FLUSHES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 16, + MALI_CINSTR_GLES_NUM_VSHADERS_GENERATED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 17, + MALI_CINSTR_GLES_NUM_FSHADERS_GENERATED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 18, + MALI_CINSTR_GLES_VSHADER_GEN_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 19, + MALI_CINSTR_GLES_FSHADER_GEN_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 20, + MALI_CINSTR_GLES_INPUT_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 21, + MALI_CINSTR_GLES_VXCACHE_HIT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 22, + MALI_CINSTR_GLES_VXCACHE_MISS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 23, + MALI_CINSTR_GLES_VXCACHE_COLLISION = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 24, + MALI_CINSTR_GLES_CULLED_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 25, + MALI_CINSTR_GLES_CULLED_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 26, + MALI_CINSTR_GLES_BACKFACE_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 27, + MALI_CINSTR_GLES_GBCLIP_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 28, + MALI_CINSTR_GLES_GBCLIP_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 29, + MALI_CINSTR_GLES_TRIANGLES_DRAWN = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 30, + MALI_CINSTR_GLES_DRAWCALL_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 31, + MALI_CINSTR_GLES_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 32, + MALI_CINSTR_GLES_INDEPENDENT_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 33, + MALI_CINSTR_GLES_STRIP_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 34, + MALI_CINSTR_GLES_FAN_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 35, + MALI_CINSTR_GLES_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 36, + MALI_CINSTR_GLES_INDEPENDENT_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 37, + MALI_CINSTR_GLES_STRIP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 38, + MALI_CINSTR_GLES_LOOP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 39, + MALI_CINSTR_GLES_POINTS_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 40, + + /* Last counter in the GLES set */ + MALI_CINSTR_GLES_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 41, + + /* OpenVG counters */ + + MALI_CINSTR_VG_MASK_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 0, + MALI_CINSTR_VG_CLEAR_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 1, + MALI_CINSTR_VG_APPEND_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 2, + MALI_CINSTR_VG_APPEND_PATH_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 3, + MALI_CINSTR_VG_MODIFY_PATH_COORDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 4, + MALI_CINSTR_VG_TRANSFORM_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 5, + MALI_CINSTR_VG_INTERPOLATE_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 6, + MALI_CINSTR_VG_PATH_LENGTH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 7, + MALI_CINSTR_VG_POINT_ALONG_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 8, + MALI_CINSTR_VG_PATH_BOUNDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 9, + MALI_CINSTR_VG_PATH_TRANSFORMED_BOUNDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 10, + MALI_CINSTR_VG_DRAW_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 11, + MALI_CINSTR_VG_CLEAR_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 12, + MALI_CINSTR_VG_IMAGE_SUB_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 13, + MALI_CINSTR_VG_GET_IMAGE_SUB_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 14, + MALI_CINSTR_VG_COPY_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 15, + MALI_CINSTR_VG_DRAW_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 16, + MALI_CINSTR_VG_SET_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 17, + MALI_CINSTR_VG_WRITE_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 18, + MALI_CINSTR_VG_GET_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 19, + MALI_CINSTR_VG_READ_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 20, + MALI_CINSTR_VG_COPY_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 21, + MALI_CINSTR_VG_COLOR_MATRIX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 22, + MALI_CINSTR_VG_CONVOLVE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 23, + MALI_CINSTR_VG_SEPARABLE_CONVOLVE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 24, + MALI_CINSTR_VG_GAUSSIAN_BLUR_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 25, + MALI_CINSTR_VG_LOOKUP_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 26, + MALI_CINSTR_VG_LOOKUP_SINGLE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 27, + MALI_CINSTR_VG_CONTEXT_CREATE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 28, + MALI_CINSTR_VG_STROKED_CUBICS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 29, + MALI_CINSTR_VG_STROKED_QUADS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 30, + MALI_CINSTR_VG_STROKED_ARCS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 31, + MALI_CINSTR_VG_STROKED_LINES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 32, + MALI_CINSTR_VG_FILLED_CUBICS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 33, + MALI_CINSTR_VG_FILLED_QUADS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 34, + MALI_CINSTR_VG_FILLED_ARCS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 35, + MALI_CINSTR_VG_FILLED_LINES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 36, + MALI_CINSTR_VG_DRAW_PATH_CALLS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 37, + MALI_CINSTR_VG_TRIANGLES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 38, + MALI_CINSTR_VG_VERTICES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 39, + MALI_CINSTR_VG_INDICES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 40, + MALI_CINSTR_VG_FILLED_PATHS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 41, + MALI_CINSTR_VG_STROKED_PATHS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 42, + MALI_CINSTR_VG_FILL_EXTRACT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 43, + MALI_CINSTR_VG_DRAW_FILLED_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 44, + MALI_CINSTR_VG_STROKE_EXTRACT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 45, + MALI_CINSTR_VG_DRAW_STROKED_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 46, + MALI_CINSTR_VG_DRAW_PAINT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 47, + MALI_CINSTR_VG_DATA_STRUCTURES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 48, + MALI_CINSTR_VG_MEM_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 49, + MALI_CINSTR_VG_RSW_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 50, + + /* Last counter in the VG set */ + MALI_CINSTR_VG_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 51, + + /* Mali GP counters */ + + MALI_CINSTR_GP_DEPRECATED_0 = MALI_CINSTR_COUNTER_SOURCE_GP + 0, + MALI_CINSTR_GP_ACTIVE_CYCLES_GP = MALI_CINSTR_COUNTER_SOURCE_GP + 1, + MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_SHADER = MALI_CINSTR_COUNTER_SOURCE_GP + 2, + MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_STORER = MALI_CINSTR_COUNTER_SOURCE_GP + 3, + MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_LOADER = MALI_CINSTR_COUNTER_SOURCE_GP + 4, + MALI_CINSTR_GP_CYCLES_VERTEX_LOADER_WAITING_FOR_VERTEX_SHADER = MALI_CINSTR_COUNTER_SOURCE_GP + 5, + MALI_CINSTR_GP_NUMBER_OF_WORDS_READ = MALI_CINSTR_COUNTER_SOURCE_GP + 6, + MALI_CINSTR_GP_NUMBER_OF_WORDS_WRITTEN = MALI_CINSTR_COUNTER_SOURCE_GP + 7, + MALI_CINSTR_GP_NUMBER_OF_READ_BURSTS = MALI_CINSTR_COUNTER_SOURCE_GP + 8, + MALI_CINSTR_GP_NUMBER_OF_WRITE_BURSTS = MALI_CINSTR_COUNTER_SOURCE_GP + 9, + MALI_CINSTR_GP_NUMBER_OF_VERTICES_PROCESSED = MALI_CINSTR_COUNTER_SOURCE_GP + 10, + MALI_CINSTR_GP_NUMBER_OF_VERTICES_FETCHED = MALI_CINSTR_COUNTER_SOURCE_GP + 11, + MALI_CINSTR_GP_NUMBER_OF_PRIMITIVES_FETCHED = MALI_CINSTR_COUNTER_SOURCE_GP + 12, + MALI_CINSTR_GP_RESERVED_13 = MALI_CINSTR_COUNTER_SOURCE_GP + 13, + MALI_CINSTR_GP_NUMBER_OF_BACKFACE_CULLINGS_DONE = MALI_CINSTR_COUNTER_SOURCE_GP + 14, + MALI_CINSTR_GP_NUMBER_OF_COMMANDS_WRITTEN_TO_TILES = MALI_CINSTR_COUNTER_SOURCE_GP + 15, + MALI_CINSTR_GP_NUMBER_OF_MEMORY_BLOCKS_ALLOCATED = MALI_CINSTR_COUNTER_SOURCE_GP + 16, + MALI_CINSTR_GP_RESERVED_17 = MALI_CINSTR_COUNTER_SOURCE_GP + 17, + MALI_CINSTR_GP_RESERVED_18 = MALI_CINSTR_COUNTER_SOURCE_GP + 18, + MALI_CINSTR_GP_NUMBER_OF_VERTEX_LOADER_CACHE_MISSES = MALI_CINSTR_COUNTER_SOURCE_GP + 19, + MALI_CINSTR_GP_RESERVED_20 = MALI_CINSTR_COUNTER_SOURCE_GP + 20, + MALI_CINSTR_GP_RESERVED_21 = MALI_CINSTR_COUNTER_SOURCE_GP + 21, + MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_SHADER_COMMAND_PROCESSOR = MALI_CINSTR_COUNTER_SOURCE_GP + 22, + MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_COMMAND_PROCESSOR = MALI_CINSTR_COUNTER_SOURCE_GP + 23, + MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_LIST_WRITER = MALI_CINSTR_COUNTER_SOURCE_GP + 24, + MALI_CINSTR_GP_ACTIVE_CYCLES_THROUGH_THE_PREPARE_LIST_COMMANDS = MALI_CINSTR_COUNTER_SOURCE_GP + 25, + MALI_CINSTR_GP_RESERVED_26 = MALI_CINSTR_COUNTER_SOURCE_GP + 26, + MALI_CINSTR_GP_ACTIVE_CYCLES_PRIMITIVE_ASSEMBLY = MALI_CINSTR_COUNTER_SOURCE_GP + 27, + MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_VERTEX_FETCHER = MALI_CINSTR_COUNTER_SOURCE_GP + 28, + MALI_CINSTR_GP_RESERVED_29 = MALI_CINSTR_COUNTER_SOURCE_GP + 29, + MALI_CINSTR_GP_ACTIVE_CYCLES_BOUNDINGBOX_AND_COMMAND_GENERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 30, + MALI_CINSTR_GP_RESERVED_31 = MALI_CINSTR_COUNTER_SOURCE_GP + 31, + MALI_CINSTR_GP_ACTIVE_CYCLES_SCISSOR_TILE_ITERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 32, + MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_TILE_ITERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 33, + MALI_CINSTR_GP_JOB_COUNT = MALI_CINSTR_COUNTER_SOURCE_GP + 900, + + /* Mali PP counters */ + + MALI_CINSTR_PP_ACTIVE_CLOCK_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 0, + MALI_CINSTR_PP_TOTAL_CLOCK_CYCLES_COUNT_REMOVED = MALI_CINSTR_COUNTER_SOURCE_PP + 1, + MALI_CINSTR_PP_TOTAL_BUS_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 2, + MALI_CINSTR_PP_TOTAL_BUS_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 3, + MALI_CINSTR_PP_BUS_READ_REQUEST_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 4, + MALI_CINSTR_PP_BUS_WRITE_REQUEST_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 5, + MALI_CINSTR_PP_BUS_READ_TRANSACTIONS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 6, + MALI_CINSTR_PP_BUS_WRITE_TRANSACTIONS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 7, + MALI_CINSTR_PP_RESERVED_08 = MALI_CINSTR_COUNTER_SOURCE_PP + 8, + MALI_CINSTR_PP_TILE_WRITEBACK_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 9, + MALI_CINSTR_PP_STORE_UNIT_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 10, + MALI_CINSTR_PP_RESERVED_11 = MALI_CINSTR_COUNTER_SOURCE_PP + 11, + MALI_CINSTR_PP_PALETTE_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 12, + MALI_CINSTR_PP_TEXTURE_CACHE_UNCOMPRESSED_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 13, + MALI_CINSTR_PP_POLYGON_LIST_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 14, + MALI_CINSTR_PP_RSW_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 15, + MALI_CINSTR_PP_VERTEX_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 16, + MALI_CINSTR_PP_UNIFORM_REMAPPING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 17, + MALI_CINSTR_PP_PROGRAM_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 19, + MALI_CINSTR_PP_VARYING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 19, + MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 20, + MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_REMAPPING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 21, + MALI_CINSTR_PP_TEXTURE_CACHE_COMPRESSED_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 22, + MALI_CINSTR_PP_LOAD_UNIT_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 23, + MALI_CINSTR_PP_POLYGON_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 24, + MALI_CINSTR_PP_PIXEL_RECTANGLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 25, + MALI_CINSTR_PP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 26, + MALI_CINSTR_PP_POINTS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 27, + MALI_CINSTR_PP_STALL_CYCLES_POLYGON_LIST_READER = MALI_CINSTR_COUNTER_SOURCE_PP + 28, + MALI_CINSTR_PP_STALL_CYCLES_TRIANGLE_SETUP = MALI_CINSTR_COUNTER_SOURCE_PP + 29, + MALI_CINSTR_PP_QUAD_RASTERIZED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 30, + MALI_CINSTR_PP_FRAGMENT_RASTERIZED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 31, + MALI_CINSTR_PP_FRAGMENT_REJECTED_FRAGMENT_KILL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 32, + MALI_CINSTR_PP_FRAGMENT_REJECTED_FWD_FRAGMENT_KILL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 33, + MALI_CINSTR_PP_FRAGMENT_PASSED_ZSTENCIL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 34, + MALI_CINSTR_PP_PATCHES_REJECTED_EARLY_Z_STENCIL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 35, + MALI_CINSTR_PP_PATCHES_EVALUATED = MALI_CINSTR_COUNTER_SOURCE_PP + 36, + MALI_CINSTR_PP_INSTRUCTION_COMPLETED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 37, + MALI_CINSTR_PP_INSTRUCTION_FAILED_RENDEZVOUS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 38, + MALI_CINSTR_PP_INSTRUCTION_FAILED_VARYING_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 39, + MALI_CINSTR_PP_INSTRUCTION_FAILED_TEXTURE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 40, + MALI_CINSTR_PP_INSTRUCTION_FAILED_LOAD_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 41, + MALI_CINSTR_PP_INSTRUCTION_FAILED_TILE_READ_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 42, + MALI_CINSTR_PP_INSTRUCTION_FAILED_STORE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 43, + MALI_CINSTR_PP_RENDEZVOUS_BREAKAGE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 44, + MALI_CINSTR_PP_PIPELINE_BUBBLES_CYCLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 45, + MALI_CINSTR_PP_TEXTURE_MAPPER_MULTIPASS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 46, + MALI_CINSTR_PP_TEXTURE_MAPPER_CYCLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 47, + MALI_CINSTR_PP_VERTEX_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 48, + MALI_CINSTR_PP_VERTEX_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 49, + MALI_CINSTR_PP_VARYING_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 50, + MALI_CINSTR_PP_VARYING_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 51, + MALI_CINSTR_PP_VARYING_CACHE_CONFLICT_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 52, + MALI_CINSTR_PP_TEXTURE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 53, + MALI_CINSTR_PP_TEXTURE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 54, + MALI_CINSTR_PP_TEXTURE_CACHE_CONFLICT_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 55, + MALI_CINSTR_PP_PALETTE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 56, /* Mali 200 only */ + MALI_CINSTR_PP_PALETTE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 57, /* Mali 200 only */ + MALI_CINSTR_PP_COMPRESSED_TEXTURE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 56, /* Mali 400 class only */ + MALI_CINSTR_PP_COMPRESSED_TEXTURE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 57, /* Mali 400 class only */ + MALI_CINSTR_PP_LOAD_STORE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 58, + MALI_CINSTR_PP_LOAD_STORE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 59, + MALI_CINSTR_PP_PROGRAM_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 60, + MALI_CINSTR_PP_PROGRAM_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 61, + MALI_CINSTR_PP_JOB_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 900, +} cinstr_counters_m200_t; + +#endif /*_MALI_UTGARD_COUNTERS_H_*/ diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h new file mode 100644 index 0000000..7935448 --- /dev/null +++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_UTGARD_IOCTL_H__ +#define __MALI_UTGARD_IOCTL_H__ + +#include +#include +#include /* file system operations */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @file mali_kernel_ioctl.h + * Interface to the Linux device driver. + * This file describes the interface needed to use the Linux device driver. + * Its interface is designed to used by the HAL implementation through a thin arch layer. + */ + +/** + * ioctl commands + */ + +#define MALI_IOC_BASE 0x82 +#define MALI_IOC_CORE_BASE (_MALI_UK_CORE_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_MEMORY_BASE (_MALI_UK_MEMORY_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_PP_BASE (_MALI_UK_PP_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_GP_BASE (_MALI_UK_GP_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_PROFILING_BASE (_MALI_UK_PROFILING_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_VSYNC_BASE (_MALI_UK_VSYNC_SUBSYSTEM + MALI_IOC_BASE) + +#define MALI_IOC_WAIT_FOR_NOTIFICATION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_WAIT_FOR_NOTIFICATION, _mali_uk_wait_for_notification_s *) +#define MALI_IOC_GET_API_VERSION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_API_VERSION, _mali_uk_get_api_version_s *) +#define MALI_IOC_POST_NOTIFICATION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_POST_NOTIFICATION, _mali_uk_post_notification_s *) +#define MALI_IOC_GET_USER_SETTING _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTING, _mali_uk_get_user_setting_s *) +#define MALI_IOC_GET_USER_SETTINGS _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTINGS, _mali_uk_get_user_settings_s *) + +#define MALI_IOC_MEM_GET_BIG_BLOCK _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, void *) +#define MALI_IOC_MEM_FREE_BIG_BLOCK _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_FREE_BIG_BLOCK, void *) +#define MALI_IOC_MEM_INIT _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_INIT_MEM, _mali_uk_init_mem_s *) +#define MALI_IOC_MEM_TERM _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_TERM_MEM, _mali_uk_term_mem_s *) +#define MALI_IOC_MEM_MAP_EXT _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MAP_EXT_MEM, _mali_uk_map_external_mem_s *) +#define MALI_IOC_MEM_UNMAP_EXT _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_UNMAP_EXT_MEM, _mali_uk_unmap_external_mem_s *) +#define MALI_IOC_MEM_ATTACH_DMA_BUF _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_ATTACH_DMA_BUF, _mali_uk_attach_dma_buf_s *) +#define MALI_IOC_MEM_RELEASE_DMA_BUF _IOW(MALI_IOC_MEMORY_BASE, _MALI_UK_RELEASE_DMA_BUF, _mali_uk_release_dma_buf_s *) +#define MALI_IOC_MEM_DMA_BUF_GET_SIZE _IOR(MALI_IOC_MEMORY_BASE, _MALI_UK_DMA_BUF_GET_SIZE, _mali_uk_dma_buf_get_size_s *) +#define MALI_IOC_MEM_ATTACH_UMP _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_ATTACH_UMP_MEM, _mali_uk_attach_ump_mem_s *) +#define MALI_IOC_MEM_RELEASE_UMP _IOW(MALI_IOC_MEMORY_BASE, _MALI_UK_RELEASE_UMP_MEM, _mali_uk_release_ump_mem_s *) +#define MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, _mali_uk_query_mmu_page_table_dump_size_s *) +#define MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_DUMP_MMU_PAGE_TABLE, _mali_uk_dump_mmu_page_table_s *) + +#define MALI_IOC_PP_START_JOB _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_START_JOB, _mali_uk_pp_start_job_s *) +#define MALI_IOC_PP_NUMBER_OF_CORES_GET _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_NUMBER_OF_CORES, _mali_uk_get_pp_number_of_cores_s *) +#define MALI_IOC_PP_CORE_VERSION_GET _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_CORE_VERSION, _mali_uk_get_pp_core_version_s * ) +#define MALI_IOC_PP_DISABLE_WB _IOW (MALI_IOC_PP_BASE, _MALI_UK_PP_DISABLE_WB, _mali_uk_pp_disable_wb_s * ) + +#define MALI_IOC_GP2_START_JOB _IOWR(MALI_IOC_GP_BASE, _MALI_UK_GP_START_JOB, _mali_uk_gp_start_job_s *) +#define MALI_IOC_GP2_NUMBER_OF_CORES_GET _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_NUMBER_OF_CORES, _mali_uk_get_gp_number_of_cores_s *) +#define MALI_IOC_GP2_CORE_VERSION_GET _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_CORE_VERSION, _mali_uk_get_gp_core_version_s *) +#define MALI_IOC_GP2_SUSPEND_RESPONSE _IOW (MALI_IOC_GP_BASE, _MALI_UK_GP_SUSPEND_RESPONSE,_mali_uk_gp_suspend_response_s *) + +#define MALI_IOC_PROFILING_START _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_START, _mali_uk_profiling_start_s *) +#define MALI_IOC_PROFILING_ADD_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_ADD_EVENT, _mali_uk_profiling_add_event_s*) +#define MALI_IOC_PROFILING_STOP _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_STOP, _mali_uk_profiling_stop_s *) +#define MALI_IOC_PROFILING_GET_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_EVENT, _mali_uk_profiling_get_event_s *) +#define MALI_IOC_PROFILING_CLEAR _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_CLEAR, _mali_uk_profiling_clear_s *) +#define MALI_IOC_PROFILING_GET_CONFIG _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_CONFIG, _mali_uk_get_user_settings_s *) +#define MALI_IOC_PROFILING_REPORT_SW_COUNTERS _IOW (MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_REPORT_SW_COUNTERS, _mali_uk_sw_counters_report_s *) + +#define MALI_IOC_VSYNC_EVENT_REPORT _IOW (MALI_IOC_VSYNC_BASE, _MALI_UK_VSYNC_EVENT_REPORT, _mali_uk_vsync_event_report_s *) + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_UTGARD_IOCTL_H__ */ diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h new file mode 100644 index 0000000..b96596e --- /dev/null +++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _MALI_UTGARD_PROFILING_EVENTS_H_ +#define _MALI_UTGARD_PROFILING_EVENTS_H_ + +/* + * The event ID is a 32 bit value consisting of different fields + * reserved, 4 bits, for future use + * event type, 4 bits, cinstr_profiling_event_type_t + * event channel, 8 bits, the source of the event. + * event data, 16 bit field, data depending on event type + */ + +/** + * Specifies what kind of event this is + */ +typedef enum +{ + MALI_PROFILING_EVENT_TYPE_SINGLE = 0 << 24, + MALI_PROFILING_EVENT_TYPE_START = 1 << 24, + MALI_PROFILING_EVENT_TYPE_STOP = 2 << 24, + MALI_PROFILING_EVENT_TYPE_SUSPEND = 3 << 24, + MALI_PROFILING_EVENT_TYPE_RESUME = 4 << 24, +} cinstr_profiling_event_type_t; + + +/** + * Secifies the channel/source of the event + */ +typedef enum +{ + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE = 0 << 16, + MALI_PROFILING_EVENT_CHANNEL_GP0 = 1 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP0 = 5 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP1 = 6 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP2 = 7 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP3 = 8 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP4 = 9 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP5 = 10 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP6 = 11 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP7 = 12 << 16, + MALI_PROFILING_EVENT_CHANNEL_GPU = 21 << 16, +} cinstr_profiling_event_channel_t; + + +#define MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(num) (((MALI_PROFILING_EVENT_CHANNEL_GP0 >> 16) + (num)) << 16) +#define MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(num) (((MALI_PROFILING_EVENT_CHANNEL_PP0 >> 16) + (num)) << 16) + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from software channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SINGLE_SW_NONE = 0, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_NEW_FRAME = 1, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_FLUSH = 2, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_SWAP_BUFFERS = 3, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_FB_EVENT = 4, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_GP_ENQUEUE = 5, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_PP_ENQUEUE = 6, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_ENTER_API_FUNC = 10, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC = 11, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_TRY_LOCK = 53, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_LOCK = 54, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_UNLOCK = 55, +} cinstr_profiling_event_reason_single_sw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE = 0, + MALI_PROFILING_EVENT_REASON_START_STOP_MALI = 1, +} cinstr_profiling_event_reason_start_stop_sw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SUSPEND/RESUME is used from software channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_NONE = 0, /* NOT used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PIPELINE_FULL = 1, /* NOT used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC = 26, /* used in some build configurations */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_WAIT = 27, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_SYNC = 28, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_FILTER_CLEANUP = 29, /* used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_TEXTURE = 30, /* used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_MIPLEVEL = 31, /* used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_READPIXELS = 32, /* used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_WAIT_SWAP_IMMEDIATE= 33, /* NOT used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_ICS_QUEUE_BUFFER = 34, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_ICS_DEQUEUE_BUFFER = 35, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_UMP_LOCK = 36, /* Not currently used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_GLOBAL_LOCK = 37, /* Not currently used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_SWAP = 38, /* Not currently used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_MALI_EGL_IMAGE_SYNC_WAIT = 39, /* USED */ +} cinstr_profiling_event_reason_suspend_resume_sw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from a HW channel (GPx+PPx) + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SINGLE_HW_NONE = 0, + MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT = 1, + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH = 2, +} cinstr_profiling_event_reason_single_hw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_NONE = 0, + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, +} cinstr_profiling_event_reason_single_gpu_t; + +#endif /*_MALI_UTGARD_PROFILING_EVENTS_H_*/ diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h new file mode 100644 index 0000000..b35a715 --- /dev/null +++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h @@ -0,0 +1,1095 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_uk_types.h + * Defines the types and constants used in the user-kernel interface + */ + +#ifndef __MALI_UTGARD_UK_TYPES_H__ +#define __MALI_UTGARD_UK_TYPES_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @addtogroup uddapi Unified Device Driver (UDD) APIs + * + * @{ + */ + +/** + * @addtogroup u_k_api UDD User/Kernel Interface (U/K) APIs + * + * @{ + */ + +/** @defgroup _mali_uk_core U/K Core + * @{ */ + +/** Definition of subsystem numbers, to assist in creating a unique identifier + * for each U/K call. + * + * @see _mali_uk_functions */ +typedef enum +{ + _MALI_UK_CORE_SUBSYSTEM, /**< Core Group of U/K calls */ + _MALI_UK_MEMORY_SUBSYSTEM, /**< Memory Group of U/K calls */ + _MALI_UK_PP_SUBSYSTEM, /**< Fragment Processor Group of U/K calls */ + _MALI_UK_GP_SUBSYSTEM, /**< Vertex Processor Group of U/K calls */ + _MALI_UK_PROFILING_SUBSYSTEM, /**< Profiling Group of U/K calls */ + _MALI_UK_PMM_SUBSYSTEM, /**< Power Management Module Group of U/K calls */ + _MALI_UK_VSYNC_SUBSYSTEM, /**< VSYNC Group of U/K calls */ +} _mali_uk_subsystem_t; + +/** Within a function group each function has its unique sequence number + * to assist in creating a unique identifier for each U/K call. + * + * An ordered pair of numbers selected from + * ( \ref _mali_uk_subsystem_t,\ref _mali_uk_functions) will uniquely identify the + * U/K call across all groups of functions, and all functions. */ +typedef enum +{ + /** Core functions */ + + _MALI_UK_OPEN = 0, /**< _mali_ukk_open() */ + _MALI_UK_CLOSE, /**< _mali_ukk_close() */ + _MALI_UK_WAIT_FOR_NOTIFICATION, /**< _mali_ukk_wait_for_notification() */ + _MALI_UK_GET_API_VERSION, /**< _mali_ukk_get_api_version() */ + _MALI_UK_POST_NOTIFICATION, /**< _mali_ukk_post_notification() */ + _MALI_UK_GET_USER_SETTING, /**< _mali_ukk_get_user_setting() *//**< [out] */ + _MALI_UK_GET_USER_SETTINGS, /**< _mali_ukk_get_user_settings() *//**< [out] */ + + /** Memory functions */ + + _MALI_UK_INIT_MEM = 0, /**< _mali_ukk_init_mem() */ + _MALI_UK_TERM_MEM, /**< _mali_ukk_term_mem() */ + _MALI_UK_GET_BIG_BLOCK, /**< _mali_ukk_get_big_block() */ + _MALI_UK_FREE_BIG_BLOCK, /**< _mali_ukk_free_big_block() */ + _MALI_UK_MAP_MEM, /**< _mali_ukk_mem_mmap() */ + _MALI_UK_UNMAP_MEM, /**< _mali_ukk_mem_munmap() */ + _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, /**< _mali_ukk_mem_get_mmu_page_table_dump_size() */ + _MALI_UK_DUMP_MMU_PAGE_TABLE, /**< _mali_ukk_mem_dump_mmu_page_table() */ + _MALI_UK_ATTACH_DMA_BUF, /**< _mali_ukk_attach_dma_buf() */ + _MALI_UK_RELEASE_DMA_BUF, /**< _mali_ukk_release_dma_buf() */ + _MALI_UK_DMA_BUF_GET_SIZE, /**< _mali_ukk_dma_buf_get_size() */ + _MALI_UK_ATTACH_UMP_MEM, /**< _mali_ukk_attach_ump_mem() */ + _MALI_UK_RELEASE_UMP_MEM, /**< _mali_ukk_release_ump_mem() */ + _MALI_UK_MAP_EXT_MEM, /**< _mali_uku_map_external_mem() */ + _MALI_UK_UNMAP_EXT_MEM, /**< _mali_uku_unmap_external_mem() */ + _MALI_UK_VA_TO_MALI_PA, /**< _mali_uku_va_to_mali_pa() */ + + /** Common functions for each core */ + + _MALI_UK_START_JOB = 0, /**< Start a Fragment/Vertex Processor Job on a core */ + _MALI_UK_GET_NUMBER_OF_CORES, /**< Get the number of Fragment/Vertex Processor cores */ + _MALI_UK_GET_CORE_VERSION, /**< Get the Fragment/Vertex Processor version compatible with all cores */ + + /** Fragment Processor Functions */ + + _MALI_UK_PP_START_JOB = _MALI_UK_START_JOB, /**< _mali_ukk_pp_start_job() */ + _MALI_UK_GET_PP_NUMBER_OF_CORES = _MALI_UK_GET_NUMBER_OF_CORES, /**< _mali_ukk_get_pp_number_of_cores() */ + _MALI_UK_GET_PP_CORE_VERSION = _MALI_UK_GET_CORE_VERSION, /**< _mali_ukk_get_pp_core_version() */ + _MALI_UK_PP_DISABLE_WB, /**< _mali_ukk_pp_job_disable_wb() */ + + /** Vertex Processor Functions */ + + _MALI_UK_GP_START_JOB = _MALI_UK_START_JOB, /**< _mali_ukk_gp_start_job() */ + _MALI_UK_GET_GP_NUMBER_OF_CORES = _MALI_UK_GET_NUMBER_OF_CORES, /**< _mali_ukk_get_gp_number_of_cores() */ + _MALI_UK_GET_GP_CORE_VERSION = _MALI_UK_GET_CORE_VERSION, /**< _mali_ukk_get_gp_core_version() */ + _MALI_UK_GP_SUSPEND_RESPONSE, /**< _mali_ukk_gp_suspend_response() */ + + /** Profiling functions */ + + _MALI_UK_PROFILING_START = 0, /**< __mali_uku_profiling_start() */ + _MALI_UK_PROFILING_ADD_EVENT, /**< __mali_uku_profiling_add_event() */ + _MALI_UK_PROFILING_STOP, /**< __mali_uku_profiling_stop() */ + _MALI_UK_PROFILING_GET_EVENT, /**< __mali_uku_profiling_get_event() */ + _MALI_UK_PROFILING_CLEAR, /**< __mali_uku_profiling_clear() */ + _MALI_UK_PROFILING_GET_CONFIG, /**< __mali_uku_profiling_get_config() */ + _MALI_UK_PROFILING_REPORT_SW_COUNTERS,/**< __mali_uku_profiling_report_sw_counters() */ + + /** VSYNC reporting fuctions */ + _MALI_UK_VSYNC_EVENT_REPORT = 0, /**< _mali_ukk_vsync_event_report() */ + +} _mali_uk_functions; + +/** @brief Get the size necessary for system info + * + * @see _mali_ukk_get_system_info_size() + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 size; /**< [out] size of buffer necessary to hold system information data, in bytes */ +} _mali_uk_get_system_info_size_s; + + +/** @defgroup _mali_uk_getsysteminfo U/K Get System Info + * @{ */ + +/** + * Type definition for the core version number. + * Used when returning the version number read from a core + * + * Its format is that of the 32-bit Version register for a particular core. + * Refer to the "Mali200 and MaliGP2 3D Graphics Processor Technical Reference + * Manual", ARM DDI 0415C, for more information. + */ +typedef u32 _mali_core_version; + +/** + * Enum values for the different modes the driver can be put in. + * Normal is the default mode. The driver then uses a job queue and takes job objects from the clients. + * Job completion is reported using the _mali_ukk_wait_for_notification call. + * The driver blocks this io command until a job has completed or failed or a timeout occurs. + * + * The 'raw' mode is reserved for future expansion. + */ +typedef enum _mali_driver_mode +{ + _MALI_DRIVER_MODE_RAW = 1, /**< Reserved for future expansion */ + _MALI_DRIVER_MODE_NORMAL = 2 /**< Normal mode of operation */ +} _mali_driver_mode; + +/** @brief List of possible cores + * + * add new entries to the end of this enum */ +typedef enum _mali_core_type +{ + _MALI_GP2 = 2, /**< MaliGP2 Programmable Vertex Processor */ + _MALI_200 = 5, /**< Mali200 Programmable Fragment Processor */ + _MALI_400_GP = 6, /**< Mali400 Programmable Vertex Processor */ + _MALI_400_PP = 7, /**< Mali400 Programmable Fragment Processor */ + /* insert new core here, do NOT alter the existing values */ +} _mali_core_type; + + +/** @brief Capabilities of Memory Banks + * + * These may be used to restrict memory banks for certain uses. They may be + * used when access is not possible (e.g. Bus does not support access to it) + * or when access is possible but not desired (e.g. Access is slow). + * + * In the case of 'possible but not desired', there is no way of specifying + * the flags as an optimization hint, so that the memory could be used as a + * last resort. + * + * @see _mali_mem_info + */ +typedef enum _mali_bus_usage +{ + + _MALI_PP_READABLE = (1<<0), /** Readable by the Fragment Processor */ + _MALI_PP_WRITEABLE = (1<<1), /** Writeable by the Fragment Processor */ + _MALI_GP_READABLE = (1<<2), /** Readable by the Vertex Processor */ + _MALI_GP_WRITEABLE = (1<<3), /** Writeable by the Vertex Processor */ + _MALI_CPU_READABLE = (1<<4), /** Readable by the CPU */ + _MALI_CPU_WRITEABLE = (1<<5), /** Writeable by the CPU */ + _MALI_GP_L2_ALLOC = (1<<6), /** GP allocate mali L2 cache lines*/ + _MALI_MMU_READABLE = _MALI_PP_READABLE | _MALI_GP_READABLE, /** Readable by the MMU (including all cores behind it) */ + _MALI_MMU_WRITEABLE = _MALI_PP_WRITEABLE | _MALI_GP_WRITEABLE, /** Writeable by the MMU (including all cores behind it) */ +} _mali_bus_usage; + +typedef enum mali_memory_cache_settings +{ + MALI_CACHE_STANDARD = 0, + MALI_CACHE_GP_READ_ALLOCATE = 1, +} mali_memory_cache_settings ; + + +/** @brief Information about the Mali Memory system + * + * Information is stored in a linked list, which is stored entirely in the + * buffer pointed to by the system_info member of the + * _mali_uk_get_system_info_s arguments provided to _mali_ukk_get_system_info() + * + * Each element of the linked list describes a single Mali Memory bank. + * Each allocation can only come from one bank, and will not cross multiple + * banks. + * + * On Mali-MMU systems, there is only one bank, which describes the maximum + * possible address range that could be allocated (which may be much less than + * the available physical memory) + * + * The flags member describes the capabilities of the memory. It is an error + * to attempt to build a job for a particular core (PP or GP) when the memory + * regions used do not have the capabilities for supporting that core. This + * would result in a job abort from the Device Driver. + * + * For example, it is correct to build a PP job where read-only data structures + * are taken from a memory with _MALI_PP_READABLE set and + * _MALI_PP_WRITEABLE clear, and a framebuffer with _MALI_PP_WRITEABLE set and + * _MALI_PP_READABLE clear. However, it would be incorrect to use a framebuffer + * where _MALI_PP_WRITEABLE is clear. + */ +typedef struct _mali_mem_info +{ + u32 size; /**< Size of the memory bank in bytes */ + _mali_bus_usage flags; /**< Capabilitiy flags of the memory */ + u32 maximum_order_supported; /**< log2 supported size */ + u32 identifier; /* mali_memory_cache_settings cache_settings; */ + struct _mali_mem_info * next; /**< Next List Link */ +} _mali_mem_info; + + + +/** @} */ /* end group _mali_uk_core */ + + +/** @defgroup _mali_uk_gp U/K Vertex Processor + * @{ */ + +/** @defgroup _mali_uk_gp_suspend_response_s Vertex Processor Suspend Response + * @{ */ + +/** @brief Arguments for _mali_ukk_gp_suspend_response() + * + * When _mali_wait_for_notification() receives notification that a + * Vertex Processor job was suspended, you need to send a response to indicate + * what needs to happen with this job. You can either abort or resume the job. + * + * - set @c code to indicate response code. This is either @c _MALIGP_JOB_ABORT or + * @c _MALIGP_JOB_RESUME_WITH_NEW_HEAP to indicate you will provide a new heap + * for the job that will resolve the out of memory condition for the job. + * - copy the @c cookie value from the @c _mali_uk_gp_job_suspended_s notification; + * this is an identifier for the suspended job + * - set @c arguments[0] and @c arguments[1] to zero if you abort the job. If + * you resume it, @c argument[0] should specify the Mali start address for the new + * heap and @c argument[1] the Mali end address of the heap. + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * + */ +typedef enum _maligp_job_suspended_response_code +{ + _MALIGP_JOB_ABORT, /**< Abort the Vertex Processor job */ + _MALIGP_JOB_RESUME_WITH_NEW_HEAP /**< Resume the Vertex Processor job with a new heap */ +} _maligp_job_suspended_response_code; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 cookie; /**< [in] cookie from the _mali_uk_gp_job_suspended_s notification */ + _maligp_job_suspended_response_code code; /**< [in] abort or resume response code, see \ref _maligp_job_suspended_response_code */ + u32 arguments[2]; /**< [in] 0 when aborting a job. When resuming a job, the Mali start and end address for a new heap to resume the job with */ +} _mali_uk_gp_suspend_response_s; + +/** @} */ /* end group _mali_uk_gp_suspend_response_s */ + +/** @defgroup _mali_uk_gpstartjob_s Vertex Processor Start Job + * @{ */ + +/** @brief Status indicating the result of starting a Vertex or Fragment processor job */ +typedef enum +{ + _MALI_UK_START_JOB_STARTED, /**< Job started */ + _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE /**< Job could not be started at this time. Try starting the job again */ +} _mali_uk_start_job_status; + +/** @brief Status indicating the result of the execution of a Vertex or Fragment processor job */ + +typedef enum +{ + _MALI_UK_JOB_STATUS_END_SUCCESS = 1<<(16+0), + _MALI_UK_JOB_STATUS_END_OOM = 1<<(16+1), + _MALI_UK_JOB_STATUS_END_ABORT = 1<<(16+2), + _MALI_UK_JOB_STATUS_END_TIMEOUT_SW = 1<<(16+3), + _MALI_UK_JOB_STATUS_END_HANG = 1<<(16+4), + _MALI_UK_JOB_STATUS_END_SEG_FAULT = 1<<(16+5), + _MALI_UK_JOB_STATUS_END_ILLEGAL_JOB = 1<<(16+6), + _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR = 1<<(16+7), + _MALI_UK_JOB_STATUS_END_SHUTDOWN = 1<<(16+8), + _MALI_UK_JOB_STATUS_END_SYSTEM_UNUSABLE = 1<<(16+9) +} _mali_uk_job_status; + +#define MALIGP2_NUM_REGS_FRAME (6) + +/** @brief Arguments for _mali_ukk_gp_start_job() + * + * To start a Vertex Processor job + * - associate the request with a reference to a @c mali_gp_job_info by setting + * user_job_ptr to the address of the @c mali_gp_job_info of the job. + * - set @c priority to the priority of the @c mali_gp_job_info + * - specify a timeout for the job by setting @c watchdog_msecs to the number of + * milliseconds the job is allowed to run. Specifying a value of 0 selects the + * default timeout in use by the device driver. + * - copy the frame registers from the @c mali_gp_job_info into @c frame_registers. + * - set the @c perf_counter_flag, @c perf_counter_src0 and @c perf_counter_src1 to zero + * for a non-instrumented build. For an instrumented build you can use up + * to two performance counters. Set the corresponding bit in @c perf_counter_flag + * to enable them. @c perf_counter_src0 and @c perf_counter_src1 specify + * the source of what needs to get counted (e.g. number of vertex loader + * cache hits). For source id values, see ARM DDI0415A, Table 3-60. + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * + * When @c _mali_ukk_gp_start_job() returns @c _MALI_OSK_ERR_OK, status contains the + * result of the request (see \ref _mali_uk_start_job_status). If the job could + * not get started (@c _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE) it should be + * tried again. + * + * After the job has started, @c _mali_wait_for_notification() will be notified + * that the job finished or got suspended. It may get suspended due to + * resource shortage. If it finished (see _mali_ukk_wait_for_notification()) + * the notification will contain a @c _mali_uk_gp_job_finished_s result. If + * it got suspended the notification will contain a @c _mali_uk_gp_job_suspended_s + * result. + * + * The @c _mali_uk_gp_job_finished_s contains the job status (see \ref _mali_uk_job_status), + * the number of milliseconds the job took to render, and values of core registers + * when the job finished (irq status, performance counters, renderer list + * address). A job has finished succesfully when its status is + * @c _MALI_UK_JOB_STATUS_FINISHED. If the hardware detected a timeout while rendering + * the job, or software detected the job is taking more than watchdog_msecs to + * complete, the status will indicate @c _MALI_UK_JOB_STATUS_HANG. + * If the hardware detected a bus error while accessing memory associated with the + * job, status will indicate @c _MALI_UK_JOB_STATUS_SEG_FAULT. + * status will indicate @c _MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to + * stop the job but the job didn't start on the hardware yet, e.g. when the + * driver shutdown. + * + * In case the job got suspended, @c _mali_uk_gp_job_suspended_s contains + * the @c user_job_ptr identifier used to start the job with, the @c reason + * why the job stalled (see \ref _maligp_job_suspended_reason) and a @c cookie + * to identify the core on which the job stalled. This @c cookie will be needed + * when responding to this nofication by means of _mali_ukk_gp_suspend_response(). + * (see _mali_ukk_gp_suspend_response()). The response is either to abort or + * resume the job. If the job got suspended due to an out of memory condition + * you may be able to resolve this by providing more memory and resuming the job. + * + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 user_job_ptr; /**< [in] identifier for the job in user space, a @c mali_gp_job_info* */ + u32 priority; /**< [in] job priority. A lower number means higher priority */ + u32 frame_registers[MALIGP2_NUM_REGS_FRAME]; /**< [in] core specific registers associated with this job */ + u32 perf_counter_flag; /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ + u32 perf_counter_src0; /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ + u32 perf_counter_src1; /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ + u32 frame_builder_id; /**< [in] id of the originating frame builder */ + u32 flush_id; /**< [in] flush id within the originating frame builder */ +} _mali_uk_gp_start_job_s; + +#define _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE (1<<0) /**< Enable performance counter SRC0 for a job */ +#define _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE (1<<1) /**< Enable performance counter SRC1 for a job */ + +/** @} */ /* end group _mali_uk_gpstartjob_s */ + +typedef struct +{ + u32 user_job_ptr; /**< [out] identifier for the job in user space */ + _mali_uk_job_status status; /**< [out] status of finished job */ + u32 heap_current_addr; /**< [out] value of the GP PLB PL heap start address register */ + u32 perf_counter0; /**< [out] value of perfomance counter 0 (see ARM DDI0415A) */ + u32 perf_counter1; /**< [out] value of perfomance counter 1 (see ARM DDI0415A) */ +} _mali_uk_gp_job_finished_s; + +typedef enum _maligp_job_suspended_reason +{ + _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY /**< Polygon list builder unit (PLBU) has run out of memory */ +} _maligp_job_suspended_reason; + +typedef struct +{ + u32 user_job_ptr; /**< [out] identifier for the job in user space */ + _maligp_job_suspended_reason reason; /**< [out] reason why the job stalled */ + u32 cookie; /**< [out] identifier for the core in kernel space on which the job stalled */ +} _mali_uk_gp_job_suspended_s; + +/** @} */ /* end group _mali_uk_gp */ + + +/** @defgroup _mali_uk_pp U/K Fragment Processor + * @{ */ + +#define _MALI_PP_MAX_SUB_JOBS 8 + +#define _MALI_PP_MAX_FRAME_REGISTERS ((0x058/4)+1) + +#define _MALI_PP_MAX_WB_REGISTERS ((0x02C/4)+1) + +/** Flag for _mali_uk_pp_start_job_s */ +#define _MALI_PP_JOB_FLAG_NO_NOTIFICATION (1<<0) +#define _MALI_PP_JOB_FLAG_BARRIER (1<<1) + +/** @defgroup _mali_uk_ppstartjob_s Fragment Processor Start Job + * @{ */ + +/** @brief Arguments for _mali_ukk_pp_start_job() + * + * To start a Fragment Processor job + * - associate the request with a reference to a mali_pp_job by setting + * @c user_job_ptr to the address of the @c mali_pp_job of the job. + * - set @c priority to the priority of the mali_pp_job + * - specify a timeout for the job by setting @c watchdog_msecs to the number of + * milliseconds the job is allowed to run. Specifying a value of 0 selects the + * default timeout in use by the device driver. + * - copy the frame registers from the @c mali_pp_job into @c frame_registers. + * For MALI200 you also need to copy the write back 0,1 and 2 registers. + * - set the @c perf_counter_flag, @c perf_counter_src0 and @c perf_counter_src1 to zero + * for a non-instrumented build. For an instrumented build you can use up + * to two performance counters. Set the corresponding bit in @c perf_counter_flag + * to enable them. @c perf_counter_src0 and @c perf_counter_src1 specify + * the source of what needs to get counted (e.g. number of vertex loader + * cache hits). For source id values, see ARM DDI0415A, Table 3-60. + * - pass in the user-kernel context in @c ctx that was returned from _mali_ukk_open() + * + * When _mali_ukk_pp_start_job() returns @c _MALI_OSK_ERR_OK, @c status contains the + * result of the request (see \ref _mali_uk_start_job_status). If the job could + * not get started (@c _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE) it should be + * tried again. + * + * After the job has started, _mali_wait_for_notification() will be notified + * when the job finished. The notification will contain a + * @c _mali_uk_pp_job_finished_s result. It contains the @c user_job_ptr + * identifier used to start the job with, the job @c status (see \ref _mali_uk_job_status), + * the number of milliseconds the job took to render, and values of core registers + * when the job finished (irq status, performance counters, renderer list + * address). A job has finished succesfully when its status is + * @c _MALI_UK_JOB_STATUS_FINISHED. If the hardware detected a timeout while rendering + * the job, or software detected the job is taking more than @c watchdog_msecs to + * complete, the status will indicate @c _MALI_UK_JOB_STATUS_HANG. + * If the hardware detected a bus error while accessing memory associated with the + * job, status will indicate @c _MALI_UK_JOB_STATUS_SEG_FAULT. + * status will indicate @c _MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to + * stop the job but the job didn't start on the hardware yet, e.g. when the + * driver shutdown. + * + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 user_job_ptr; /**< [in] identifier for the job in user space */ + u32 priority; /**< [in] job priority. A lower number means higher priority */ + u32 frame_registers[_MALI_PP_MAX_FRAME_REGISTERS]; /**< [in] core specific registers associated with first sub job, see ARM DDI0415A */ + u32 frame_registers_addr_frame[_MALI_PP_MAX_SUB_JOBS - 1]; /**< [in] ADDR_FRAME registers for sub job 1-7 */ + u32 frame_registers_addr_stack[_MALI_PP_MAX_SUB_JOBS - 1]; /**< [in] ADDR_STACK registers for sub job 1-7 */ + u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS]; + u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS]; + u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS]; + u32 num_cores; /**< [in] Number of cores to set up (valid range: 1-4) */ + u32 perf_counter_flag; /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ + u32 perf_counter_src0; /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ + u32 perf_counter_src1; /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ + u32 frame_builder_id; /**< [in] id of the originating frame builder */ + u32 flush_id; /**< [in] flush id within the originating frame builder */ + u32 flags; /**< [in] See _MALI_PP_JOB_FLAG_* for a list of avaiable flags */ +} _mali_uk_pp_start_job_s; +/** @} */ /* end group _mali_uk_ppstartjob_s */ + +typedef struct +{ + u32 user_job_ptr; /**< [out] identifier for the job in user space */ + _mali_uk_job_status status; /**< [out] status of finished job */ + u32 perf_counter0[_MALI_PP_MAX_SUB_JOBS]; /**< [out] value of perfomance counter 0 (see ARM DDI0415A), one for each sub job */ + u32 perf_counter1[_MALI_PP_MAX_SUB_JOBS]; /**< [out] value of perfomance counter 1 (see ARM DDI0415A), one for each sub job */ +} _mali_uk_pp_job_finished_s; + +/** + * Flags to indicate write-back units + */ +typedef enum +{ + _MALI_UK_PP_JOB_WB0 = 1, + _MALI_UK_PP_JOB_WB1 = 2, + _MALI_UK_PP_JOB_WB2 = 4, +} _mali_uk_pp_job_wbx_flag; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 fb_id; /**< [in] Frame builder ID of job to disable WB units for */ + u32 flush_id; /**< [in] Flush ID of job to disable WB units for */ + _mali_uk_pp_job_wbx_flag wbx; /**< [in] write-back units to disable */ +} _mali_uk_pp_disable_wb_s; + + +/** @} */ /* end group _mali_uk_pp */ + + +/** @addtogroup _mali_uk_core U/K Core + * @{ */ + +/** @defgroup _mali_uk_waitfornotification_s Wait For Notification + * @{ */ + +/** @brief Notification type encodings + * + * Each Notification type is an ordered pair of (subsystem,id), and is unique. + * + * The encoding of subsystem,id into a 32-bit word is: + * encoding = (( subsystem << _MALI_NOTIFICATION_SUBSYSTEM_SHIFT ) & _MALI_NOTIFICATION_SUBSYSTEM_MASK) + * | (( id << _MALI_NOTIFICATION_ID_SHIFT ) & _MALI_NOTIFICATION_ID_MASK) + * + * @see _mali_uk_wait_for_notification_s + */ +typedef enum +{ + /** core notifications */ + + _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x20, + _MALI_NOTIFICATION_APPLICATION_QUIT = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x40, + _MALI_NOTIFICATION_SETTINGS_CHANGED = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x80, + + /** Fragment Processor notifications */ + + _MALI_NOTIFICATION_PP_FINISHED = (_MALI_UK_PP_SUBSYSTEM << 16) | 0x10, + + /** Vertex Processor notifications */ + + _MALI_NOTIFICATION_GP_FINISHED = (_MALI_UK_GP_SUBSYSTEM << 16) | 0x10, + _MALI_NOTIFICATION_GP_STALLED = (_MALI_UK_GP_SUBSYSTEM << 16) | 0x20, + +} _mali_uk_notification_type; + +/** to assist in splitting up 32-bit notification value in subsystem and id value */ +#define _MALI_NOTIFICATION_SUBSYSTEM_MASK 0xFFFF0000 +#define _MALI_NOTIFICATION_SUBSYSTEM_SHIFT 16 +#define _MALI_NOTIFICATION_ID_MASK 0x0000FFFF +#define _MALI_NOTIFICATION_ID_SHIFT 0 + + +/** @brief Enumeration of possible settings which match mali_setting_t in user space + * + * + */ +typedef enum +{ + _MALI_UK_USER_SETTING_SW_EVENTS_ENABLE = 0, + _MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, + _MALI_UK_USER_SETTING_DEPTHBUFFER_CAPTURE_ENABLED, + _MALI_UK_USER_SETTING_STENCILBUFFER_CAPTURE_ENABLED, + _MALI_UK_USER_SETTING_PER_TILE_COUNTERS_CAPTURE_ENABLED, + _MALI_UK_USER_SETTING_BUFFER_CAPTURE_COMPOSITOR, + _MALI_UK_USER_SETTING_BUFFER_CAPTURE_WINDOW, + _MALI_UK_USER_SETTING_BUFFER_CAPTURE_OTHER, + _MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, + _MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, + _MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, + _MALI_UK_USER_SETTING_MAX, +} _mali_uk_user_setting_t; + +/* See mali_user_settings_db.c */ +extern const char *_mali_uk_user_setting_descriptions[]; +#define _MALI_UK_USER_SETTING_DESCRIPTIONS \ +{ \ + "sw_events_enable", \ + "colorbuffer_capture_enable", \ + "depthbuffer_capture_enable", \ + "stencilbuffer_capture_enable", \ + "per_tile_counters_enable", \ + "buffer_capture_compositor", \ + "buffer_capture_window", \ + "buffer_capture_other", \ + "buffer_capture_n_frames", \ + "buffer_capture_resize_factor", \ + "sw_counters_enable", \ +}; + +/** @brief struct to hold the value to a particular setting as seen in the kernel space + */ +typedef struct +{ + _mali_uk_user_setting_t setting; + u32 value; +} _mali_uk_settings_changed_s; + +/** @brief Arguments for _mali_ukk_wait_for_notification() + * + * On successful return from _mali_ukk_wait_for_notification(), the members of + * this structure will indicate the reason for notification. + * + * Specifically, the source of the notification can be identified by the + * subsystem and id fields of the mali_uk_notification_type in the code.type + * member. The type member is encoded in a way to divide up the types into a + * subsystem field, and a per-subsystem ID field. See + * _mali_uk_notification_type for more information. + * + * Interpreting the data union member depends on the notification type: + * + * - type == _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS + * - The kernel side is shutting down. No further + * _mali_uk_wait_for_notification() calls should be made. + * - In this case, the value of the data union member is undefined. + * - This is used to indicate to the user space client that it should close + * the connection to the Mali Device Driver. + * - type == _MALI_NOTIFICATION_PP_FINISHED + * - The notification data is of type _mali_uk_pp_job_finished_s. It contains the user_job_ptr + * identifier used to start the job with, the job status, the number of milliseconds the job took to render, + * and values of core registers when the job finished (irq status, performance counters, renderer list + * address). + * - A job has finished succesfully when its status member is _MALI_UK_JOB_STATUS_FINISHED. + * - If the hardware detected a timeout while rendering the job, or software detected the job is + * taking more than watchdog_msecs (see _mali_ukk_pp_start_job()) to complete, the status member will + * indicate _MALI_UK_JOB_STATUS_HANG. + * - If the hardware detected a bus error while accessing memory associated with the job, status will + * indicate _MALI_UK_JOB_STATUS_SEG_FAULT. + * - Status will indicate MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to stop the job but the job + * didn't start the hardware yet, e.g. when the driver closes. + * - type == _MALI_NOTIFICATION_GP_FINISHED + * - The notification data is of type _mali_uk_gp_job_finished_s. The notification is similar to that of + * type == _MALI_NOTIFICATION_PP_FINISHED, except that several other GP core register values are returned. + * The status values have the same meaning for type == _MALI_NOTIFICATION_PP_FINISHED. + * - type == _MALI_NOTIFICATION_GP_STALLED + * - The nofication data is of type _mali_uk_gp_job_suspended_s. It contains the user_job_ptr + * identifier used to start the job with, the reason why the job stalled and a cookie to identify the core on + * which the job stalled. + * - The reason member of gp_job_suspended is set to _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY + * when the polygon list builder unit has run out of memory. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_notification_type type; /**< [out] Type of notification available */ + union + { + _mali_uk_gp_job_suspended_s gp_job_suspended;/**< [out] Notification data for _MALI_NOTIFICATION_GP_STALLED notification type */ + _mali_uk_gp_job_finished_s gp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_GP_FINISHED notification type */ + _mali_uk_pp_job_finished_s pp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_PP_FINISHED notification type */ + _mali_uk_settings_changed_s setting_changed;/**< [out] Notification data for _MALI_NOTIFICAATION_SETTINGS_CHANGED notification type */ + } data; +} _mali_uk_wait_for_notification_s; + +/** @brief Arguments for _mali_ukk_post_notification() + * + * Posts the specified notification to the notification queue for this application. + * This is used to send a quit message to the callback thread. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_notification_type type; /**< [in] Type of notification to post */ +} _mali_uk_post_notification_s; + +/** @} */ /* end group _mali_uk_waitfornotification_s */ + +/** @defgroup _mali_uk_getapiversion_s Get API Version + * @{ */ + +/** helpers for Device Driver API version handling */ + +/** @brief Encode a version ID from a 16-bit input + * + * @note the input is assumed to be 16 bits. It must not exceed 16 bits. */ +#define _MAKE_VERSION_ID(x) (((x) << 16UL) | (x)) + +/** @brief Check whether a 32-bit value is likely to be Device Driver API + * version ID. */ +#define _IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF)) + +/** @brief Decode a 16-bit version number from a 32-bit Device Driver API version + * ID */ +#define _GET_VERSION(x) (((x) >> 16UL) & 0xFFFF) + +/** @brief Determine whether two 32-bit encoded version IDs match */ +#define _IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y)))) + +/** + * API version define. + * Indicates the version of the kernel API + * The version is a 16bit integer incremented on each API change. + * The 16bit integer is stored twice in a 32bit integer + * For example, for version 1 the value would be 0x00010001 + */ +#define _MALI_API_VERSION 17 +#define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION) + +/** + * The API version is a 16-bit integer stored in both the lower and upper 16-bits + * of a 32-bit value. The 16-bit API version value is incremented on each API + * change. Version 1 would be 0x00010001. Used in _mali_uk_get_api_version_s. + */ +typedef u32 _mali_uk_api_version; + +/** @brief Arguments for _mali_uk_get_api_version() + * + * The user-side interface version must be written into the version member, + * encoded using _MAKE_VERSION_ID(). It will be compared to the API version of + * the kernel-side interface. + * + * On successful return, the version member will be the API version of the + * kernel-side interface. _MALI_UK_API_VERSION macro defines the current version + * of the API. + * + * The compatible member must be checked to see if the version of the user-side + * interface is compatible with the kernel-side interface, since future versions + * of the interface may be backwards compatible. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_api_version version; /**< [in,out] API version of user-side interface. */ + int compatible; /**< [out] @c 1 when @version is compatible, @c 0 otherwise */ +} _mali_uk_get_api_version_s; +/** @} */ /* end group _mali_uk_getapiversion_s */ + +/** @defgroup _mali_uk_get_user_settings_s Get user space settings */ + +/** @brief struct to keep the matching values of the user space settings within certain context + * + * Each member of the settings array corresponds to a matching setting in the user space and its value is the value + * of that particular setting. + * + * All settings are given reference to the context pointed to by the ctx pointer. + * + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 settings[_MALI_UK_USER_SETTING_MAX]; /**< [out] The values for all settings */ +} _mali_uk_get_user_settings_s; + +/** @brief struct to hold the value of a particular setting from the user space within a given context + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_user_setting_t setting; /**< [in] setting to get */ + u32 value; /**< [out] value of setting */ +} _mali_uk_get_user_setting_s; + +/** @} */ /* end group _mali_uk_core */ + + +/** @defgroup _mali_uk_memory U/K Memory + * @{ */ + +/** @brief Arguments for _mali_ukk_init_mem(). */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 mali_address_base; /**< [out] start of MALI address space */ + u32 memory_size; /**< [out] total MALI address space available */ +} _mali_uk_init_mem_s; + +/** @brief Arguments for _mali_ukk_term_mem(). */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ +} _mali_uk_term_mem_s; + +/** Flag for _mali_uk_map_external_mem_s, _mali_uk_attach_ump_mem_s and _mali_uk_attach_dma_buf_s */ +#define _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE (1<<0) + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 phys_addr; /**< [in] physical address */ + u32 size; /**< [in] size */ + u32 mali_address; /**< [in] mali address to map the physical memory to */ + u32 rights; /**< [in] rights necessary for accessing memory */ + u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */ + u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ +} _mali_uk_map_external_mem_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ +} _mali_uk_unmap_external_mem_s; + +/** @note This is identical to _mali_uk_map_external_mem_s above, however phys_addr is replaced by memory descriptor */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 mem_fd; /**< [in] Memory descriptor */ + u32 size; /**< [in] size */ + u32 mali_address; /**< [in] mali address to map the physical memory to */ + u32 rights; /**< [in] rights necessary for accessing memory */ + u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */ + u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ +} _mali_uk_attach_dma_buf_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 mem_fd; /**< [in] Memory descriptor */ + u32 size; /**< [out] size */ +} _mali_uk_dma_buf_get_size_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 cookie; /**< [in] identifier for mapped memory object in kernel space */ +} _mali_uk_release_dma_buf_s; + +/** @note This is identical to _mali_uk_map_external_mem_s above, however phys_addr is replaced by secure_id */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< [in] secure id */ + u32 size; /**< [in] size */ + u32 mali_address; /**< [in] mali address to map the physical memory to */ + u32 rights; /**< [in] rights necessary for accessing memory */ + u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */ + u32 cookie; /**< [out] identifier for mapped memory object in kernel space */ +} _mali_uk_attach_ump_mem_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 cookie; /**< [in] identifier for mapped memory object in kernel space */ +} _mali_uk_release_ump_mem_s; + +/** @brief Arguments for _mali_ukk_va_to_mali_pa() + * + * if size is zero or not a multiple of the system's page size, it will be + * rounded up to the next multiple of the page size. This will occur before + * any other use of the size parameter. + * + * if va is not PAGE_SIZE aligned, it will be rounded down to the next page + * boundary. + * + * The range (va) to ((u32)va)+(size-1) inclusive will be checked for physical + * contiguity. + * + * The implementor will check that the entire physical range is allowed to be mapped + * into user-space. + * + * Failure will occur if either of the above are not satisfied. + * + * Otherwise, the physical base address of the range is returned through pa, + * va is updated to be page aligned, and size is updated to be a non-zero + * multiple of the system's pagesize. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *va; /**< [in,out] Virtual address of the start of the range */ + u32 pa; /**< [out] Physical base address of the range */ + u32 size; /**< [in,out] Size of the range, in bytes. */ +} _mali_uk_va_to_mali_pa_s; + + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 size; /**< [out] size of MMU page table information (registers + page tables) */ +} _mali_uk_query_mmu_page_table_dump_size_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 size; /**< [in] size of buffer to receive mmu page table information */ + void *buffer; /**< [in,out] buffer to receive mmu page table information */ + u32 register_writes_size; /**< [out] size of MMU register dump */ + u32 *register_writes; /**< [out] pointer within buffer where MMU register dump is stored */ + u32 page_table_dump_size; /**< [out] size of MMU page table dump */ + u32 *page_table_dump; /**< [out] pointer within buffer where MMU page table dump is stored */ +} _mali_uk_dump_mmu_page_table_s; + +/** @} */ /* end group _mali_uk_memory */ + + +/** @addtogroup _mali_uk_pp U/K Fragment Processor + * @{ */ + +/** @brief Arguments for _mali_ukk_get_pp_number_of_cores() + * + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * - Upon successful return from _mali_ukk_get_pp_number_of_cores(), @c number_of_cores + * will contain the number of Fragment Processor cores in the system. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 number_of_cores; /**< [out] number of Fragment Processor cores in the system */ +} _mali_uk_get_pp_number_of_cores_s; + +/** @brief Arguments for _mali_ukk_get_pp_core_version() + * + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * - Upon successful return from _mali_ukk_get_pp_core_version(), @c version contains + * the version that all Fragment Processor cores are compatible with. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_core_version version; /**< [out] version returned from core, see \ref _mali_core_version */ +} _mali_uk_get_pp_core_version_s; + +/** @} */ /* end group _mali_uk_pp */ + + +/** @addtogroup _mali_uk_gp U/K Vertex Processor + * @{ */ + +/** @brief Arguments for _mali_ukk_get_gp_number_of_cores() + * + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * - Upon successful return from _mali_ukk_get_gp_number_of_cores(), @c number_of_cores + * will contain the number of Vertex Processor cores in the system. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 number_of_cores; /**< [out] number of Vertex Processor cores in the system */ +} _mali_uk_get_gp_number_of_cores_s; + +/** @brief Arguments for _mali_ukk_get_gp_core_version() + * + * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open() + * - Upon successful return from _mali_ukk_get_gp_core_version(), @c version contains + * the version that all Vertex Processor cores are compatible with. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_core_version version; /**< [out] version returned from core, see \ref _mali_core_version */ +} _mali_uk_get_gp_core_version_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 limit; /**< [in,out] The desired limit for number of events to record on input, actual limit on output */ +} _mali_uk_profiling_start_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 event_id; /**< [in] event id to register (see enum mali_profiling_events for values) */ + u32 data[5]; /**< [in] event specific data */ +} _mali_uk_profiling_add_event_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 count; /**< [out] The number of events sampled */ +} _mali_uk_profiling_stop_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 index; /**< [in] which index to get (starting at zero) */ + u64 timestamp; /**< [out] timestamp of event */ + u32 event_id; /**< [out] event id of event (see enum mali_profiling_events for values) */ + u32 data[5]; /**< [out] event specific data */ +} _mali_uk_profiling_get_event_s; + +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ +} _mali_uk_profiling_clear_s; + +/** @} */ /* end group _mali_uk_gp */ + + +/** @addtogroup _mali_uk_memory U/K Memory + * @{ */ + +/** @brief Arguments to _mali_ukk_mem_mmap() + * + * Use of the phys_addr member depends on whether the driver is compiled for + * Mali-MMU or nonMMU: + * - in the nonMMU case, this is the physical address of the memory as seen by + * the CPU (which may be a constant offset from that used by Mali) + * - in the MMU case, this is the Mali Virtual base address of the memory to + * allocate, and the particular physical pages used to back the memory are + * entirely determined by _mali_ukk_mem_mmap(). The details of the physical pages + * are not reported to user-space for security reasons. + * + * The cookie member must be stored for use later when freeing the memory by + * calling _mali_ukk_mem_munmap(). In the Mali-MMU case, the cookie is secure. + * + * The ukk_private word must be set to zero when calling from user-space. On + * Kernel-side, the OS implementation of the U/K interface can use it to + * communicate data to the OS implementation of the OSK layer. In particular, + * _mali_ukk_get_big_block() directly calls _mali_ukk_mem_mmap directly, and + * will communicate its own ukk_private word through the ukk_private member + * here. The common code itself will not inspect or modify the ukk_private + * word, and so it may be safely used for whatever purposes necessary to + * integrate Mali Memory handling into the OS. + * + * The uku_private member is currently reserved for use by the user-side + * implementation of the U/K interface. Its value must be zero. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *mapping; /**< [out] Returns user-space virtual address for the mapping */ + u32 size; /**< [in] Size of the requested mapping */ + u32 phys_addr; /**< [in] Physical address - could be offset, depending on caller+callee convention */ + u32 cookie; /**< [out] Returns a cookie for use in munmap calls */ + void *uku_private; /**< [in] User-side Private word used by U/K interface */ + void *ukk_private; /**< [in] Kernel-side Private word used by U/K interface */ + mali_memory_cache_settings cache_settings; /**< [in] Option to set special cache flags, tuning L2 efficency */ +} _mali_uk_mem_mmap_s; + +/** @brief Arguments to _mali_ukk_mem_munmap() + * + * The cookie and mapping members must be that returned from the same previous + * call to _mali_ukk_mem_mmap(). The size member must correspond to cookie + * and mapping - that is, it must be the value originally supplied to a call to + * _mali_ukk_mem_mmap that returned the values of mapping and cookie. + * + * An error will be returned if an attempt is made to unmap only part of the + * originally obtained range, or to unmap more than was originally obtained. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *mapping; /**< [in] The mapping returned from mmap call */ + u32 size; /**< [in] The size passed to mmap call */ + u32 cookie; /**< [in] Cookie from mmap call */ +} _mali_uk_mem_munmap_s; +/** @} */ /* end group _mali_uk_memory */ + +/** @defgroup _mali_uk_vsync U/K VSYNC Wait Reporting Module + * @{ */ + +/** @brief VSYNC events + * + * These events are reported when DDK starts to wait for vsync and when the + * vsync has occured and the DDK can continue on the next frame. + */ +typedef enum _mali_uk_vsync_event +{ + _MALI_UK_VSYNC_EVENT_BEGIN_WAIT = 0, + _MALI_UK_VSYNC_EVENT_END_WAIT +} _mali_uk_vsync_event; + +/** @brief Arguments to _mali_ukk_vsync_event() + * + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_vsync_event event; /**< [in] VSYNCH event type */ +} _mali_uk_vsync_event_report_s; + +/** @} */ /* end group _mali_uk_vsync */ + +/** @defgroup _mali_uk_sw_counters_report U/K Software Counter Reporting + * @{ */ + +/** @brief Software counter values + * + * Values recorded for each of the software counters during a single renderpass. + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32* counters; /**< [in] The array of counter values */ + u32 num_counters; /**< [in] The number of elements in counters array */ +} _mali_uk_sw_counters_report_s; + +/** @} */ /* end group _mali_uk_sw_counters_report */ + +/** @} */ /* end group u_k_api */ + +/** @} */ /* end group uddapi */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_UTGARD_UK_TYPES_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/license/gpl/mali_kernel_license.h b/drivers/media/video/samsung/mali/linux/license/gpl/mali_kernel_license.h new file mode 100644 index 0000000..52bb5e0 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/license/gpl/mali_kernel_license.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_kernel_license.h + * Defines for the macro MODULE_LICENSE. + */ + +#ifndef __MALI_KERNEL_LICENSE_H__ +#define __MALI_KERNEL_LICENSE_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MALI_KERNEL_LINUX_LICENSE "GPL" +#define MALI_LICENSE_IS_GPL 1 + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_KERNEL_LICENSE_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_dma_buf.c b/drivers/media/video/samsung/mali/linux/mali_dma_buf.c new file mode 100644 index 0000000..4dd711f --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_dma_buf.c @@ -0,0 +1,392 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include /* file system operations */ +#include /* user space access */ +#include +#include +#include + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_kernel_linux.h" + +#include "mali_kernel_memory_engine.h" +#include "mali_memory.h" + +#include "mali_kernel_sysfs.h" + + +struct mali_dma_buf_attachment { + struct dma_buf *buf; + struct dma_buf_attachment *attachment; + struct sg_table *sgt; + _mali_osk_atomic_t ref; + struct rb_node rb_node; +}; + +static struct rb_root mali_dma_bufs = RB_ROOT; +static DEFINE_SPINLOCK(mali_dma_bufs_lock); + +static inline struct mali_dma_buf_attachment *mali_dma_buf_lookup(struct rb_root *root, struct dma_buf *target) +{ + struct rb_node *node = root->rb_node; + struct mali_dma_buf_attachment *res; + + spin_lock(&mali_dma_bufs_lock); + while (node) + { + res = rb_entry(node, struct mali_dma_buf_attachment, rb_node); + + if (target < res->buf) node = node->rb_left; + else if (target > res->buf) node = node->rb_right; + else + { + _mali_osk_atomic_inc(&res->ref); + spin_unlock(&mali_dma_bufs_lock); + return res; + } + } + spin_unlock(&mali_dma_bufs_lock); + + return NULL; +} + +static void mali_dma_buf_add(struct rb_root *root, struct mali_dma_buf_attachment *new) +{ + struct rb_node **node = &root->rb_node; + struct rb_node *parent = NULL; + struct mali_dma_buf_attachment *res; + + spin_lock(&mali_dma_bufs_lock); + while (*node) + { + parent = *node; + res = rb_entry(*node, struct mali_dma_buf_attachment, rb_node); + + if (new->buf < res->buf) node = &(*node)->rb_left; + else node = &(*node)->rb_right; + } + + rb_link_node(&new->rb_node, parent, node); + rb_insert_color(&new->rb_node, &mali_dma_bufs); + + spin_unlock(&mali_dma_bufs_lock); + + return; +} + + +static void mali_dma_buf_release(void *ctx, void *handle) +{ + struct mali_dma_buf_attachment *mem; + u32 ref; + + mem = (struct mali_dma_buf_attachment *)handle; + + MALI_DEBUG_ASSERT_POINTER(mem); + MALI_DEBUG_ASSERT_POINTER(mem->attachment); + MALI_DEBUG_ASSERT_POINTER(mem->buf); + + spin_lock(&mali_dma_bufs_lock); + ref = _mali_osk_atomic_dec_return(&mem->ref); + + MALI_DEBUG_ASSERT(ref >= 0); + + if (0 == ref) + { + rb_erase(&mem->rb_node, &mali_dma_bufs); + spin_unlock(&mali_dma_bufs_lock); + + MALI_DEBUG_ASSERT(0 == _mali_osk_atomic_read(&mem->ref)); + + dma_buf_unmap_attachment(mem->attachment, mem->sgt, DMA_BIDIRECTIONAL); + + dma_buf_detach(mem->buf, mem->attachment); + dma_buf_put(mem->buf); + + _mali_osk_free(mem); + } + else + { + spin_unlock(&mali_dma_bufs_lock); + } +} + +/* Callback from memory engine which will map into Mali virtual address space */ +static mali_physical_memory_allocation_result mali_dma_buf_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + struct mali_session_data *session; + struct mali_page_directory *pagedir; + struct mali_dma_buf_attachment *mem; + struct scatterlist *sg; + int i; + u32 virt; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(offset); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + /* Mapping dma-buf with an offset is not supported. */ + MALI_DEBUG_ASSERT(0 == *offset); + + virt = descriptor->mali_address; + session = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + pagedir = mali_session_get_page_directory(session); + + MALI_DEBUG_ASSERT_POINTER(session); + + mem = (struct mali_dma_buf_attachment *)ctx; + + MALI_DEBUG_ASSERT_POINTER(mem); + + mem->sgt = dma_buf_map_attachment(mem->attachment, DMA_BIDIRECTIONAL); + if (IS_ERR_OR_NULL(mem->sgt)) + { + MALI_PRINT_ERROR(("Failed to map dma-buf attachment\n")); + return MALI_MEM_ALLOC_INTERNAL_FAILURE; + } + + for_each_sg(mem->sgt->sgl, sg, mem->sgt->nents, i) + { + u32 size = sg_dma_len(sg); + dma_addr_t phys = sg_dma_address(sg); + + /* sg must be page aligned. */ + MALI_DEBUG_ASSERT(0 == size % MALI_MMU_PAGE_SIZE); + + mali_mmu_pagedir_update(pagedir, virt, phys, size, MALI_CACHE_STANDARD); + + virt += size; + *offset += size; + } + + if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) + { + u32 guard_phys; + MALI_DEBUG_PRINT(7, ("Mapping in extra guard page\n")); + + guard_phys = sg_dma_address(mem->sgt->sgl); + mali_mmu_pagedir_update(mali_session_get_page_directory(session), virt, guard_phys, MALI_MMU_PAGE_SIZE, MALI_CACHE_STANDARD); + } + + MALI_DEBUG_ASSERT(*offset == descriptor->size); + + alloc_info->ctx = NULL; + alloc_info->handle = mem; + alloc_info->next = NULL; + alloc_info->release = mali_dma_buf_release; + + return MALI_MEM_ALLOC_FINISHED; +} + +int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *user_arg) +{ + mali_physical_memory_allocator external_memory_allocator; + struct dma_buf *buf; + struct mali_dma_buf_attachment *mem; + _mali_uk_attach_dma_buf_s args; + mali_memory_allocation *descriptor; + int md; + int fd; + + /* Get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if (0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_attach_dma_buf_s))) + { + return -EFAULT; + } + + + fd = args.mem_fd; + + buf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(buf)) + { + MALI_DEBUG_PRINT(2, ("Failed to get dma-buf from fd: %d\n", fd)); + return PTR_RET(buf); + } + + /* Currently, mapping of the full buffer are supported. */ + if (args.size != buf->size) + { + MALI_DEBUG_PRINT(2, ("dma-buf size doesn't match mapping size.\n")); + dma_buf_put(buf); + return -EINVAL; + } + + + mem = mali_dma_buf_lookup(&mali_dma_bufs, buf); + if (NULL == mem) + { + /* dma-buf is not already attached to Mali */ + mem = _mali_osk_calloc(1, sizeof(struct mali_dma_buf_attachment)); + if (NULL == mem) + { + MALI_PRINT_ERROR(("Failed to allocate dma-buf tracing struct\n")); + dma_buf_put(mem->buf); + return -ENOMEM; + } + _mali_osk_atomic_init(&mem->ref, 1); + mem->buf = buf; + + mem->attachment = dma_buf_attach(mem->buf, mali_device); + if (NULL == mem->attachment) + { + MALI_DEBUG_PRINT(2, ("Failed to attach to dma-buf %d\n", fd)); + dma_buf_put(mem->buf); + _mali_osk_free(mem); + return -EFAULT; + } + + mali_dma_buf_add(&mali_dma_bufs, mem); + } + else + { + /* dma-buf is already attached to Mali */ + /* Give back the reference we just took, mali_dma_buf_lookup grabbed a new reference for us. */ + dma_buf_put(buf); + } + + /* Map dma-buf into this session's page tables */ + + /* Set up Mali memory descriptor */ + descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); + if (NULL == descriptor) + { + MALI_PRINT_ERROR(("Failed to allocate descriptor dma-buf %d\n", fd)); + mali_dma_buf_release(NULL, mem); + return -ENOMEM; + } + + descriptor->size = args.size; + descriptor->mapping = NULL; + descriptor->mali_address = args.mali_address; + descriptor->mali_addr_mapping_info = (void*)session; + descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ + descriptor->lock = session->memory_lock; + + if (args.flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) + { + descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; + } + _mali_osk_list_init( &descriptor->list ); + + /* Get descriptor mapping for memory. */ + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &md)) + { + MALI_PRINT_ERROR(("Failed to create descriptor mapping for dma-buf %d\n", fd)); + _mali_osk_free(descriptor); + mali_dma_buf_release(NULL, mem); + return -EFAULT; + } + + external_memory_allocator.allocate = mali_dma_buf_commit; + external_memory_allocator.allocate_page_table_block = NULL; + external_memory_allocator.ctx = mem; + external_memory_allocator.name = "DMA-BUF Memory"; + external_memory_allocator.next = NULL; + + /* Map memory into session's Mali virtual address space. */ + _mali_osk_lock_wait(session->memory_lock, _MALI_OSK_LOCKMODE_RW); + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(mali_mem_get_memory_engine(), descriptor, &external_memory_allocator, NULL)) + { + _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); + + MALI_PRINT_ERROR(("Failed to map dma-buf %d into Mali address space\n", fd)); + mali_descriptor_mapping_free(session->descriptor_mapping, md); + mali_dma_buf_release(NULL, mem); + return -ENOMEM; + } + _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); + + /* Return stuff to user space */ + if (0 != put_user(md, &user_arg->cookie)) + { + /* Roll back */ + MALI_PRINT_ERROR(("Failed to return descriptor to user space for dma-buf %d\n", fd)); + mali_descriptor_mapping_free(session->descriptor_mapping, md); + mali_dma_buf_release(NULL, mem); + return -EFAULT; + } + + return 0; +} + +int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *user_arg) +{ + _mali_uk_release_dma_buf_s args; + mali_memory_allocation *descriptor; + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_release_dma_buf_s)) ) + { + return -EFAULT; + } + + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session->descriptor_mapping, args.cookie, (void**)&descriptor)) + { + MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release dma-buf\n", args.cookie)); + return -EINVAL; + } + + descriptor = mali_descriptor_mapping_free(session->descriptor_mapping, args.cookie); + + if (NULL != descriptor) + { + _mali_osk_lock_wait( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + /* Will call back to mali_dma_buf_release() which will release the dma-buf attachment. */ + mali_allocation_engine_release_memory(mali_mem_get_memory_engine(), descriptor); + + _mali_osk_lock_signal( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + _mali_osk_free(descriptor); + } + + /* Return the error that _mali_ukk_map_external_ump_mem produced */ + return 0; +} + +int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *user_arg) +{ + _mali_uk_dma_buf_get_size_s args; + int fd; + struct dma_buf *buf; + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_dma_buf_get_size_s)) ) + { + return -EFAULT; + } + + /* Do DMA-BUF stuff */ + fd = args.mem_fd; + + buf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(buf)) + { + MALI_DEBUG_PRINT(2, ("Failed to get dma-buf from fd: %d\n", fd)); + return PTR_RET(buf); + } + + if (0 != put_user(buf->size, &user_arg->size)) + { + dma_buf_put(buf); + return -EFAULT; + } + + dma_buf_put(buf); + + return 0; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_dma_buf.h b/drivers/media/video/samsung/mali/linux/mali_dma_buf.h new file mode 100644 index 0000000..ee9a0ed --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_dma_buf.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_DMA_BUF_H__ +#define __MALI_DMA_BUF_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mali_osk.h" + +int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *arg); +int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *arg); +int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *arg); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_KERNEL_LINUX_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c new file mode 100644 index 0000000..233c0ca --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c @@ -0,0 +1,634 @@ +/** + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_kernel_linux.c + * Implementation of the Linux device driver entrypoints + */ +#include /* kernel module definitions */ +#include /* file system operations */ +#include /* character device definitions */ +#include /* memory manager definitions */ +#include +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_kernel_core.h" +#include "mali_osk.h" +#include "mali_kernel_linux.h" +#include "mali_ukk.h" +#include "mali_ukk_wrappers.h" +#include "mali_kernel_pm.h" +#include "mali_kernel_sysfs.h" +#include "mali_platform.h" +#include "mali_kernel_license.h" +#include "mali_dma_buf.h" + +/* Streamline support for the Mali driver */ +#if defined(CONFIG_TRACEPOINTS) && MALI_TIMELINE_PROFILING_ENABLED +/* Ask Linux to create the tracepoints */ +#define CREATE_TRACE_POINTS +#include "mali_linux_trace.h" +#endif /* CONFIG_TRACEPOINTS */ + +static _mali_osk_errcode_t initialize_kernel_device(void); +static int initialize_sysfs(void); +static void terminate_kernel_device(void); + + +/* from the __malidrv_build_info.c file that is generated during build */ +extern const char *__malidrv_build_info(void); + +/* Module parameter to control log level */ +int mali_debug_level = 2; +module_param(mali_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(mali_debug_level, "Higher number, more dmesg output"); + +/* By default the module uses any available major, but it's possible to set it at load time to a specific number */ +#if MALI_MAJOR_PREDEFINE +int mali_major = 244; +#else +int mali_major = 0; +#endif +module_param(mali_major, int, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(mali_major, "Device major number"); + +module_param(mali_hang_check_interval, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_hang_check_interval, "Interval at which to check for progress after the hw watchdog has been triggered"); + +module_param(mali_max_job_runtime, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_max_job_runtime, "Maximum allowed job runtime in msecs.\nJobs will be killed after this no matter what"); + +extern int mali_l2_max_reads; +module_param(mali_l2_max_reads, int, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_l2_max_reads, "Maximum reads for Mali L2 cache"); + +#if MALI_TIMELINE_PROFILING_ENABLED +extern int mali_boot_profiling; +module_param(mali_boot_profiling, int, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_boot_profiling, "Start profiling as a part of Mali driver initialization"); +#endif + +/* Export symbols from common code: mali_user_settings.c */ +#include "mali_user_settings_db.h" +EXPORT_SYMBOL(mali_set_user_setting); +EXPORT_SYMBOL(mali_get_user_setting); +#if MALI_DVFS_ENABLED +extern int mali_dvfs_control; +module_param(mali_dvfs_control, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(mali_dvfs_control, "Mali Current DVFS"); +#if defined(CONFIG_CPU_EXYNOS4210) +#else +extern int step0_clk; +module_param(step0_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step0_clk, "Mali Current step0_clk"); +#ifdef DEBUG +extern int step0_vol; +module_param(step0_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step0_vol, "Mali Current step0_vol"); +#endif + +#if (MALI_DVFS_STEPS > 1) +extern int step1_clk; +module_param(step1_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step1_clk, "Mali Current step1_clk"); + +extern int step0_up; +module_param(step0_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step0_up, "Mali Current step0_up"); + +extern int step1_down; +module_param(step1_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step1_down, "Mali Current step1_down"); +#ifdef DEBUG +extern int step1_vol; +module_param(step1_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step1_vol, "Mali Current step1_vol"); +#endif + +#if (MALI_DVFS_STEPS > 2) +extern int step2_clk; +module_param(step2_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step2_clk, "Mali Current step2_clk"); + +extern int step1_up; +module_param(step1_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step1_up, "Mali Current step1_up"); + +extern int step2_down; +module_param(step2_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step2_down, "Mali Current step2_down"); +#ifdef DEBUG +extern int step2_vol; +module_param(step2_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step2_vol, "Mali Current step2_vol"); +#endif + +#if (MALI_DVFS_STEPS > 3) +extern int step3_clk; +module_param(step3_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step3_clk, "Mali Current step3_clk"); + +extern int step2_up; +module_param(step2_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step2_up, "Mali Current step2_up"); + +extern int step3_down; +module_param(step3_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step3_down, "Mali Current step3_down"); +#ifdef DEBUG +extern int step3_vol; +module_param(step3_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step3_vol, "Mali Current step3_vol"); +#endif +#endif +#endif +#endif +#endif + +extern int mali_gpu_clk; +module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(mali_gpu_clk, "Mali Current Clock"); + +extern int mali_gpu_vol; +module_param(mali_gpu_vol, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(mali_gpu_vol, "Mali Current Voltage"); + +extern int gpu_power_state; +module_param(gpu_power_state, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(gpu_power_state, "Mali Power State"); +#endif + + +static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */ + +/* the mali device */ +static struct mali_dev device; + + +static int mali_open(struct inode *inode, struct file *filp); +static int mali_release(struct inode *inode, struct file *filp); +#ifdef HAVE_UNLOCKED_IOCTL +static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#endif + +static int mali_mmap(struct file * filp, struct vm_area_struct * vma); + +/* Linux char file operations provided by the Mali module */ +struct file_operations mali_fops = +{ + .owner = THIS_MODULE, + .open = mali_open, + .release = mali_release, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = mali_ioctl, +#else + .ioctl = mali_ioctl, +#endif + .mmap = mali_mmap +}; + + +int mali_driver_init(void) +{ + int ret = 0; + + MALI_DEBUG_PRINT(2, ("\n")); + MALI_DEBUG_PRINT(2, ("Inserting Mali v%d device driver. \n",_MALI_API_VERSION)); + MALI_DEBUG_PRINT(2, ("Compiled: %s, time: %s.\n", __DATE__, __TIME__)); + MALI_DEBUG_PRINT(2, ("Driver revision: %s\n", SVN_REV_STRING)); + + ret = _mali_dev_platform_register(); + if (0 != ret) goto platform_register_failed; + ret = map_errcode(initialize_kernel_device()); + if (0 != ret) goto initialize_kernel_device_failed; + + ret = map_errcode(mali_platform_init()); + if (0 != ret) goto platform_init_failed; + + mali_osk_low_level_mem_init(); + + ret = map_errcode(mali_initialize_subsystems()); + if (0 != ret) goto initialize_subsystems_failed; + + ret = initialize_sysfs(); + if (0 != ret) goto initialize_sysfs_failed; + + MALI_PRINT(("Mali device driver loaded\n")); + + return 0; /* Success */ + + /* Error handling */ +initialize_sysfs_failed: + mali_terminate_subsystems(); +initialize_subsystems_failed: + mali_osk_low_level_mem_term(); + mali_platform_deinit(); +platform_init_failed: + terminate_kernel_device(); +initialize_kernel_device_failed: + _mali_dev_platform_unregister(); +platform_register_failed: + return ret; +} + +void mali_driver_exit(void) +{ + MALI_DEBUG_PRINT(2, ("\n")); + MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n",_MALI_API_VERSION)); + + /* No need to terminate sysfs, this will be done automatically along with device termination */ + + mali_terminate_subsystems(); + + mali_osk_low_level_mem_term(); + + mali_platform_deinit(); + + terminate_kernel_device(); + _mali_dev_platform_unregister(); + +#if MALI_LICENSE_IS_GPL + /* @@@@ clean up the work queues! This should not be terminated here, since it isn't inited in the function above! */ + flush_workqueue(mali_wq); + destroy_workqueue(mali_wq); + mali_wq = NULL; +#endif + + MALI_PRINT(("Mali device driver unloaded\n")); +} + +static int initialize_kernel_device(void) +{ + int err; + dev_t dev = 0; + if (0 == mali_major) + { + /* auto select a major */ + err = alloc_chrdev_region(&dev, 0/*first minor*/, 1/*count*/, mali_dev_name); + mali_major = MAJOR(dev); + } + else + { + /* use load time defined major number */ + dev = MKDEV(mali_major, 0); + err = register_chrdev_region(dev, 1/*count*/, mali_dev_name); + } + + if (err) + { + goto init_chrdev_err; + } + + memset(&device, 0, sizeof(device)); + + /* initialize our char dev data */ + cdev_init(&device.cdev, &mali_fops); + device.cdev.owner = THIS_MODULE; + device.cdev.ops = &mali_fops; + + /* register char dev with the kernel */ + err = cdev_add(&device.cdev, dev, 1/*count*/); + if (err) + { + goto init_cdev_err; + } + + /* Success! */ + return 0; + +init_cdev_err: + unregister_chrdev_region(dev, 1/*count*/); +init_chrdev_err: + return err; +} + +static int initialize_sysfs(void) +{ + dev_t dev = MKDEV(mali_major, 0); + return mali_sysfs_register(&device, dev, mali_dev_name); +} + +static void terminate_kernel_device(void) +{ + dev_t dev = MKDEV(mali_major, 0); + + mali_sysfs_unregister(&device, dev, mali_dev_name); + + /* unregister char device */ + cdev_del(&device.cdev); + /* free major */ + unregister_chrdev_region(dev, 1/*count*/); + return; +} + +/** @note munmap handler is done by vma close handler */ +static int mali_mmap(struct file * filp, struct vm_area_struct * vma) +{ + struct mali_session_data * session_data; + _mali_uk_mem_mmap_s args = {0, }; + + session_data = (struct mali_session_data *)filp->private_data; + if (NULL == session_data) + { + MALI_PRINT_ERROR(("mmap called without any session data available\n")); + return -EFAULT; + } + + MALI_DEBUG_PRINT(4, ("MMap() handler: start=0x%08X, phys=0x%08X, size=0x%08X vma->flags 0x%08x\n", (unsigned int)vma->vm_start, (unsigned int)(vma->vm_pgoff << PAGE_SHIFT), (unsigned int)(vma->vm_end - vma->vm_start), vma->vm_flags)); + + /* Re-pack the arguments that mmap() packed for us */ + args.ctx = session_data; + args.phys_addr = vma->vm_pgoff << PAGE_SHIFT; + args.size = vma->vm_end - vma->vm_start; + args.ukk_private = vma; + + if ( VM_SHARED== (VM_SHARED & vma->vm_flags)) + { + args.cache_settings = MALI_CACHE_STANDARD ; + MALI_DEBUG_PRINT(3,("Allocate - Standard - Size: %d kb\n", args.size/1024)); + } + else + { + args.cache_settings = MALI_CACHE_GP_READ_ALLOCATE; + MALI_DEBUG_PRINT(3,("Allocate - GP Cached - Size: %d kb\n", args.size/1024)); + } + /* Setting it equal to VM_SHARED and not Private, which would have made the later io_remap fail for MALI_CACHE_GP_READ_ALLOCATE */ + vma->vm_flags = 0x000000fb; + + /* Call the common mmap handler */ + MALI_CHECK(_MALI_OSK_ERR_OK ==_mali_ukk_mem_mmap( &args ), -EFAULT); + + return 0; +} + +static int mali_open(struct inode *inode, struct file *filp) +{ + struct mali_session_data * session_data; + _mali_osk_errcode_t err; + + /* input validation */ + if (0 != MINOR(inode->i_rdev)) return -ENODEV; + + /* allocated struct to track this session */ + err = _mali_ukk_open((void **)&session_data); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + /* initialize file pointer */ + filp->f_pos = 0; + + /* link in our session data */ + filp->private_data = (void*)session_data; + + return 0; +} + +static int mali_release(struct inode *inode, struct file *filp) +{ + _mali_osk_errcode_t err; + + /* input validation */ + if (0 != MINOR(inode->i_rdev)) return -ENODEV; + + err = _mali_ukk_close((void **)&filp->private_data); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + return 0; +} + +int map_errcode( _mali_osk_errcode_t err ) +{ + switch(err) + { + case _MALI_OSK_ERR_OK : return 0; + case _MALI_OSK_ERR_FAULT: return -EFAULT; + case _MALI_OSK_ERR_INVALID_FUNC: return -ENOTTY; + case _MALI_OSK_ERR_INVALID_ARGS: return -EINVAL; + case _MALI_OSK_ERR_NOMEM: return -ENOMEM; + case _MALI_OSK_ERR_TIMEOUT: return -ETIMEDOUT; + case _MALI_OSK_ERR_RESTARTSYSCALL: return -ERESTARTSYS; + case _MALI_OSK_ERR_ITEM_NOT_FOUND: return -ENOENT; + default: return -EFAULT; + } +} + +#ifdef HAVE_UNLOCKED_IOCTL +static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +#else +static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +#endif +{ + int err; + struct mali_session_data *session_data; + +#ifndef HAVE_UNLOCKED_IOCTL + /* inode not used */ + (void)inode; +#endif + + MALI_DEBUG_PRINT(7, ("Ioctl received 0x%08X 0x%08lX\n", cmd, arg)); + + session_data = (struct mali_session_data *)filp->private_data; + if (NULL == session_data) + { + MALI_DEBUG_PRINT(7, ("filp->private_data was NULL\n")); + return -ENOTTY; + } + + if (NULL == (void *)arg) + { + MALI_DEBUG_PRINT(7, ("arg was NULL\n")); + return -ENOTTY; + } + + switch(cmd) + { + case MALI_IOC_WAIT_FOR_NOTIFICATION: + err = wait_for_notification_wrapper(session_data, (_mali_uk_wait_for_notification_s __user *)arg); + break; + + case MALI_IOC_GET_API_VERSION: + err = get_api_version_wrapper(session_data, (_mali_uk_get_api_version_s __user *)arg); + break; + + case MALI_IOC_POST_NOTIFICATION: + err = post_notification_wrapper(session_data, (_mali_uk_post_notification_s __user *)arg); + break; + + case MALI_IOC_GET_USER_SETTINGS: + err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg); + break; + +#if MALI_TIMELINE_PROFILING_ENABLED + case MALI_IOC_PROFILING_START: + err = profiling_start_wrapper(session_data, (_mali_uk_profiling_start_s __user *)arg); + break; + + case MALI_IOC_PROFILING_ADD_EVENT: + err = profiling_add_event_wrapper(session_data, (_mali_uk_profiling_add_event_s __user *)arg); + break; + + case MALI_IOC_PROFILING_STOP: + err = profiling_stop_wrapper(session_data, (_mali_uk_profiling_stop_s __user *)arg); + break; + + case MALI_IOC_PROFILING_GET_EVENT: + err = profiling_get_event_wrapper(session_data, (_mali_uk_profiling_get_event_s __user *)arg); + break; + + case MALI_IOC_PROFILING_CLEAR: + err = profiling_clear_wrapper(session_data, (_mali_uk_profiling_clear_s __user *)arg); + break; + + case MALI_IOC_PROFILING_GET_CONFIG: + /* Deprecated: still compatible with get_user_settings */ + err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg); + break; + + case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: + err = profiling_report_sw_counters_wrapper(session_data, (_mali_uk_sw_counters_report_s __user *)arg); + break; + +#else + + case MALI_IOC_PROFILING_START: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_ADD_EVENT: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_STOP: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_GET_EVENT: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_CLEAR: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_GET_CONFIG: /* FALL-THROUGH */ + case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: /* FALL-THROUGH */ + MALI_DEBUG_PRINT(2, ("Profiling not supported\n")); + err = -ENOTTY; + break; + +#endif + + case MALI_IOC_MEM_INIT: + err = mem_init_wrapper(session_data, (_mali_uk_init_mem_s __user *)arg); + break; + + case MALI_IOC_MEM_TERM: + err = mem_term_wrapper(session_data, (_mali_uk_term_mem_s __user *)arg); + break; + + case MALI_IOC_MEM_MAP_EXT: + err = mem_map_ext_wrapper(session_data, (_mali_uk_map_external_mem_s __user *)arg); + break; + + case MALI_IOC_MEM_UNMAP_EXT: + err = mem_unmap_ext_wrapper(session_data, (_mali_uk_unmap_external_mem_s __user *)arg); + break; + + case MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE: + err = mem_query_mmu_page_table_dump_size_wrapper(session_data, (_mali_uk_query_mmu_page_table_dump_size_s __user *)arg); + break; + + case MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE: + err = mem_dump_mmu_page_table_wrapper(session_data, (_mali_uk_dump_mmu_page_table_s __user *)arg); + break; + +#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 + + case MALI_IOC_MEM_ATTACH_UMP: + err = mem_attach_ump_wrapper(session_data, (_mali_uk_attach_ump_mem_s __user *)arg); + break; + + case MALI_IOC_MEM_RELEASE_UMP: + err = mem_release_ump_wrapper(session_data, (_mali_uk_release_ump_mem_s __user *)arg); + break; + +#else + + case MALI_IOC_MEM_ATTACH_UMP: + case MALI_IOC_MEM_RELEASE_UMP: /* FALL-THROUGH */ + MALI_DEBUG_PRINT(2, ("UMP not supported\n")); + err = -ENOTTY; + break; +#endif + +#ifdef CONFIG_DMA_SHARED_BUFFER + case MALI_IOC_MEM_ATTACH_DMA_BUF: + err = mali_attach_dma_buf(session_data, (_mali_uk_attach_dma_buf_s __user *)arg); + break; + + case MALI_IOC_MEM_RELEASE_DMA_BUF: + err = mali_release_dma_buf(session_data, (_mali_uk_release_dma_buf_s __user *)arg); + break; + + case MALI_IOC_MEM_DMA_BUF_GET_SIZE: + err = mali_dma_buf_get_size(session_data, (_mali_uk_dma_buf_get_size_s __user *)arg); + break; +#else + + case MALI_IOC_MEM_DMA_BUF_GET_SIZE: /* FALL-THROUGH */ + MALI_DEBUG_PRINT(2, ("DMA-BUF not supported\n")); + err = -ENOTTY; + break; +#endif + + case MALI_IOC_PP_START_JOB: + err = pp_start_job_wrapper(session_data, (_mali_uk_pp_start_job_s __user *)arg); + break; + + case MALI_IOC_PP_NUMBER_OF_CORES_GET: + err = pp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_pp_number_of_cores_s __user *)arg); + break; + + case MALI_IOC_PP_CORE_VERSION_GET: + err = pp_get_core_version_wrapper(session_data, (_mali_uk_get_pp_core_version_s __user *)arg); + break; + + case MALI_IOC_PP_DISABLE_WB: + err = pp_disable_wb_wrapper(session_data, (_mali_uk_pp_disable_wb_s __user *)arg); + break; + + case MALI_IOC_GP2_START_JOB: + err = gp_start_job_wrapper(session_data, (_mali_uk_gp_start_job_s __user *)arg); + break; + + case MALI_IOC_GP2_NUMBER_OF_CORES_GET: + err = gp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_gp_number_of_cores_s __user *)arg); + break; + + case MALI_IOC_GP2_CORE_VERSION_GET: + err = gp_get_core_version_wrapper(session_data, (_mali_uk_get_gp_core_version_s __user *)arg); + break; + + case MALI_IOC_GP2_SUSPEND_RESPONSE: + err = gp_suspend_response_wrapper(session_data, (_mali_uk_gp_suspend_response_s __user *)arg); + break; + + case MALI_IOC_VSYNC_EVENT_REPORT: + err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg); + break; + + case MALI_IOC_MEM_GET_BIG_BLOCK: /* Fallthrough */ + case MALI_IOC_MEM_FREE_BIG_BLOCK: + MALI_PRINT_ERROR(("Non-MMU mode is no longer supported.\n")); + err = -ENOTTY; + break; + + default: + MALI_DEBUG_PRINT(2, ("No handler for ioctl 0x%08X 0x%08lX\n", cmd, arg)); + err = -ENOTTY; + }; + + return err; +} + + +module_init(mali_driver_init); +module_exit(mali_driver_exit); + +MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION(SVN_REV_STRING); diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h new file mode 100644 index 0000000..22dc9a4 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_LINUX_H__ +#define __MALI_KERNEL_LINUX_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include /* character device definitions */ +#include "mali_kernel_license.h" +#include "mali_osk.h" + +struct mali_dev +{ + struct cdev cdev; +#if MALI_LICENSE_IS_GPL + struct class * mali_class; +#endif +}; + +#if MALI_LICENSE_IS_GPL +/* Defined in mali_osk_irq.h */ +extern struct workqueue_struct * mali_wq; +#endif + +void mali_osk_low_level_mem_init(void); +void mali_osk_low_level_mem_term(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_KERNEL_LINUX_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c new file mode 100644 index 0000000..4639d55 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c @@ -0,0 +1,268 @@ +/** + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_kernel_pm.c + * Linux Power Management integration + */ + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_PM_RUNTIME +#include +#endif +#include "mali_osk.h" +#include "mali_uk_types.h" +#include "mali_kernel_common.h" +#include "mali_kernel_license.h" +#include "mali_linux_pm.h" +#include "mali_pm.h" +#include "mali_platform.h" + +#if ! MALI_LICENSE_IS_GPL +#undef CONFIG_PM_RUNTIME +#endif + +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +extern void set_mali_parent_power_domain(struct platform_device* dev); +#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */ +static int mali_probe(struct platform_device *pdev); +static int mali_remove(struct platform_device *pdev); + +#ifdef CONFIG_PM_RUNTIME +static int mali_runtime_suspend(struct device *dev); +static int mali_runtime_resume(struct device *dev); +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) +static int mali_os_suspend(struct platform_device *pdev, pm_message_t state); +static int mali_os_resume(struct platform_device *pdev); +#else +static int mali_os_suspend(struct device *dev); +static int mali_os_resume(struct device *dev); +#endif + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) +static const struct dev_pm_ops mali_dev_pm_ops = +{ +#ifdef CONFIG_PM_RUNTIME + .runtime_suspend = mali_runtime_suspend, + .runtime_resume = mali_runtime_resume, + .runtime_idle = NULL, +#else + .suspend = mali_os_suspend, + .resume = mali_os_resume, +#endif + .freeze = mali_os_suspend, + .poweroff = mali_os_suspend, + .thaw = mali_os_resume, + .restore = mali_os_resume, +}; +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) +struct pm_ext_ops mali_ext_pm_operations = +{ + .base = + { + .freeze = mali_os_suspend, + .thaw = mali_os_resume, + .poweroff = mali_os_suspend, + .restore = mali_os_resume, + }, +}; +#endif + + +static struct platform_driver mali_plat_driver = +{ + .probe = mali_probe, + .remove = mali_remove, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) + .suspend = mali_os_suspend, + .resume = mali_os_resume, + .pm = &mali_ext_pm_operations, +#endif + + .driver = + { + .name = "mali_dev", + .owner = THIS_MODULE, +#if MALI_LICENSE_IS_GPL + .bus = &platform_bus_type, +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) + .pm = &mali_dev_pm_ops, +#endif + }, +}; + +#ifdef CONFIG_PM_RUNTIME +static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy); + +static struct notifier_block mali_pwr_notif_block = +{ + .notifier_call = mali_pwr_suspend_notifier +}; +#endif + +/** This function is called when platform device is unregistered. This function + * is necessary when the platform device is unregistered. + */ +static void _mali_release_pm(struct device *device) +{ +} +struct platform_device mali_gpu_device = +{ + .name = "mali_dev", + .id = 0, + .dev.release = _mali_release_pm +}; + +/** This function is called when the device is probed */ +static int mali_probe(struct platform_device *pdev) +{ + return 0; +} + +static int mali_remove(struct platform_device *pdev) +{ +#ifdef CONFIG_PM_RUNTIME + pm_runtime_disable(&pdev->dev); +#endif + return 0; +} + +#ifdef CONFIG_PM_RUNTIME +static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy) +{ + switch (event) + { + case PM_SUSPEND_PREPARE: + MALI_DEBUG_PRINT(2, ("mali_pwr_suspend_notifier(PM_SUSPEND_PREPARE) called\n")); + mali_pm_os_suspend(); + break; + case PM_POST_SUSPEND: + MALI_DEBUG_PRINT(2, ("mali_pwr_suspend_notifier(PM_SUSPEND_PREPARE) called\n")); + mali_pm_os_resume(); + break; + default: + break; + } + return 0; +} +#endif + + +#ifdef CONFIG_PM_RUNTIME + +static int mali_runtime_suspend(struct device *dev) +{ + MALI_DEBUG_PRINT(3, ("mali_runtime_suspend() called\n")); + mali_pm_runtime_suspend(); + return 0; /* all ok */ +} + +static int mali_runtime_resume(struct device *dev) +{ + MALI_DEBUG_PRINT(3, ("mali_runtime_resume() called\n")); + mali_pm_runtime_resume(); + return 0; /* all ok */ +} + +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) + +static int mali_os_suspend(struct platform_device *pdev, pm_message_t state) +{ + MALI_DEBUG_PRINT(3, ("mali_os_suspend(old) called\n")); + mali_pm_os_suspend(); + return 0; /* all ok */ +} + +static int mali_os_resume(struct platform_device *pdev) +{ + MALI_DEBUG_PRINT(3, ("mali_os_resume(old) called\n")); + mali_pm_os_resume(); + return 0; /* all ok */ +} + +#else + +static int mali_os_suspend(struct device *dev) +{ + MALI_DEBUG_PRINT(3, ("mali_os_suspend(new) called\n")); + mali_pm_os_suspend(); + return 0; /* all ok */ +} + +static int mali_os_resume(struct device *dev) +{ + MALI_DEBUG_PRINT(3, ("mali_os_resume(new) called\n")); + mali_pm_os_resume(); + return 0; /* all ok */ +} + +#endif + +/** This function is called when Mali GPU device is initialized + */ +int _mali_dev_platform_register(void) +{ + int err; + +#ifdef CONFIG_PM_RUNTIME + set_mali_parent_power_domain((void *)&mali_gpu_device); +#endif + +#ifdef CONFIG_PM_RUNTIME + err = register_pm_notifier(&mali_pwr_notif_block); + if (err) + { + return err; + } +#endif + +#if MALI_LICENSE_IS_GPL + err = platform_device_register(&mali_gpu_device); + if (!err) + { + err = platform_driver_register(&mali_plat_driver); + if (err) + { +#ifdef CONFIG_PM_RUNTIME + unregister_pm_notifier(&mali_pwr_notif_block); +#endif + platform_device_unregister(&mali_gpu_device); + } + } +#endif + + return err; +} + +/** This function is called when Mali GPU device is unloaded + */ +void _mali_dev_platform_unregister(void) +{ +#ifdef CONFIG_PM_RUNTIME + unregister_pm_notifier(&mali_pwr_notif_block); +#endif + +#if MALI_LICENSE_IS_GPL + platform_driver_unregister(&mali_plat_driver); + platform_device_unregister(&mali_gpu_device); +#endif +} + diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h new file mode 100644 index 0000000..6ef7270 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_PM_H__ +#define __MALI_KERNEL_PM_H__ + +int _mali_dev_platform_register(void); +void _mali_dev_platform_unregister(void); + +#endif /* __MALI_KERNEL_PM_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c new file mode 100644 index 0000000..e2dc17b --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c @@ -0,0 +1,1280 @@ +/** + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +/** + * @file mali_kernel_sysfs.c + * Implementation of some sysfs data exports + */ + +#include +#include +#include +#include +#include "mali_kernel_license.h" +#include "mali_kernel_common.h" +#include "mali_kernel_linux.h" +#include "mali_ukk.h" + +#if MALI_LICENSE_IS_GPL + +#include +#include +#include +#include +#include "mali_kernel_sysfs.h" +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +#include +#include "mali_osk_profiling.h" +#endif +#include "mali_pm.h" +#include "mali_cluster.h" +#include "mali_group.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_l2_cache.h" +#include "mali_hw_core.h" +#include "mali_kernel_core.h" +#include "mali_user_settings_db.h" +#include "mali_device_pause_resume.h" + +#define POWER_BUFFER_SIZE 3 + +struct device *mali_device; +static struct dentry *mali_debugfs_dir = NULL; + +typedef enum +{ + _MALI_DEVICE_SUSPEND, + _MALI_DEVICE_RESUME, + _MALI_DEVICE_DVFS_PAUSE, + _MALI_DEVICE_DVFS_RESUME, + _MALI_MAX_EVENTS +} _mali_device_debug_power_events; + +static const char* const mali_power_events[_MALI_MAX_EVENTS] = { + [_MALI_DEVICE_SUSPEND] = "suspend", + [_MALI_DEVICE_RESUME] = "resume", + [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause", + [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume", +}; + +static u32 virtual_power_status_register=0; +static char pwr_buf[POWER_BUFFER_SIZE]; + +static int open_copy_private_data(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->i_private; + return 0; +} + +static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) +{ + char buf[64]; + int r; + u32 val; + struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data; + + if (0 == src_id) + { + val = mali_gp_core_get_counter_src0(gp_core); + } + else + { + val = mali_gp_core_get_counter_src1(gp_core); + } + + if (MALI_HW_CORE_NO_COUNTER == val) + { + r = sprintf(buf, "-1\n"); + } + else + { + r = sprintf(buf, "%u\n", val); + } + return simple_read_from_buffer(ubuf, cnt, gpos, buf, r); +} + +static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) +{ + struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data; + char buf[64]; + long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + if (0 == src_id) + { + if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val)) + { + return 0; + } + } + + *gpos += cnt; + return cnt; +} + +static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + u32 ci; + struct mali_cluster *cluster; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + ci = 0; + cluster = mali_cluster_get_global_cluster(ci); + while (NULL != cluster) + { + u32 gi = 0; + struct mali_group *group = mali_cluster_get_group(cluster, gi); + while (NULL != group) + { + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) + { + if (0 == src_id) + { + if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val)) + { + return 0; + } + } + } + + /* try next group */ + gi++; + group = mali_cluster_get_group(cluster, gi); + } + + /* try next cluster */ + ci++; + cluster = mali_cluster_get_global_cluster(ci); + } + + *gpos += cnt; + return cnt; +} + +static ssize_t gp_gpx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 0); +} + +static ssize_t gp_gpx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 1); +} + +static ssize_t gp_gpx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 0); +} + +static ssize_t gp_gpx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 1); +} + +static ssize_t gp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 0); +} + +static ssize_t gp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 1); +} + +static const struct file_operations gp_gpx_counter_src0_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = gp_gpx_counter_src0_read, + .write = gp_gpx_counter_src0_write, +}; + +static const struct file_operations gp_gpx_counter_src1_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = gp_gpx_counter_src1_read, + .write = gp_gpx_counter_src1_write, +}; + +static const struct file_operations gp_all_counter_src0_fops = { + .owner = THIS_MODULE, + .write = gp_all_counter_src0_write, +}; + +static const struct file_operations gp_all_counter_src1_fops = { + .owner = THIS_MODULE, + .write = gp_all_counter_src1_write, +}; + +static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + int r; + u32 val; + struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data; + + if (0 == src_id) + { + val = mali_pp_core_get_counter_src0(pp_core); + } + else + { + val = mali_pp_core_get_counter_src1(pp_core); + } + + if (MALI_HW_CORE_NO_COUNTER == val) + { + r = sprintf(buf, "-1\n"); + } + else + { + r = sprintf(buf, "%u\n", val); + } + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data; + char buf[64]; + long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + if (0 == src_id) + { + if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val)) + { + return 0; + } + } + + *ppos += cnt; + return cnt; +} + +static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + u32 ci; + struct mali_cluster *cluster; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + ci = 0; + cluster = mali_cluster_get_global_cluster(ci); + while (NULL != cluster) + { + u32 gi = 0; + struct mali_group *group = mali_cluster_get_group(cluster, gi); + while (NULL != group) + { + struct mali_pp_core *pp_core = mali_group_get_pp_core(group); + if (NULL != pp_core) + { + if (0 == src_id) + { + if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val)) + { + return 0; + } + } + } + + /* try next group */ + gi++; + group = mali_cluster_get_group(cluster, gi); + } + + /* try next cluster */ + ci++; + cluster = mali_cluster_get_global_cluster(ci); + } + + *ppos += cnt; + return cnt; +} + +static ssize_t pp_ppx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t pp_ppx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t pp_ppx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t pp_ppx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t pp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t pp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static const struct file_operations pp_ppx_counter_src0_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = pp_ppx_counter_src0_read, + .write = pp_ppx_counter_src0_write, +}; + +static const struct file_operations pp_ppx_counter_src1_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = pp_ppx_counter_src1_read, + .write = pp_ppx_counter_src1_write, +}; + +static const struct file_operations pp_all_counter_src0_fops = { + .owner = THIS_MODULE, + .write = pp_all_counter_src0_write, +}; + +static const struct file_operations pp_all_counter_src1_fops = { + .owner = THIS_MODULE, + .write = pp_all_counter_src1_write, +}; + + + + + + +static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + int r; + u32 val; + struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data; + + if (0 == src_id) + { + val = mali_l2_cache_core_get_counter_src0(l2_core); + } + else + { + val = mali_l2_cache_core_get_counter_src1(l2_core); + } + + if (MALI_HW_CORE_NO_COUNTER == val) + { + r = sprintf(buf, "-1\n"); + } + else + { + r = sprintf(buf, "%u\n", val); + } + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data; + char buf[64]; + long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + if (0 == src_id) + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_core, (u32)val)) + { + return 0; + } + } + + *ppos += cnt; + return cnt; +} + +static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + u32 l2_id; + struct mali_l2_cache_core *l2_cache; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + l2_id = 0; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + while (NULL != l2_cache) + { + if (0 == src_id) + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_cache, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_cache, (u32)val)) + { + return 0; + } + } + + /* try next L2 */ + l2_id++; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + } + + *ppos += cnt; + return cnt; +} + +static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static const struct file_operations l2_l2x_counter_src0_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = l2_l2x_counter_src0_read, + .write = l2_l2x_counter_src0_write, +}; + +static const struct file_operations l2_l2x_counter_src1_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = l2_l2x_counter_src1_read, + .write = l2_l2x_counter_src1_write, +}; + +static const struct file_operations l2_all_counter_src0_fops = { + .owner = THIS_MODULE, + .write = l2_all_counter_src0_write, +}; + +static const struct file_operations l2_all_counter_src1_fops = { + .owner = THIS_MODULE, + .write = l2_all_counter_src1_write, +}; + +static ssize_t power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + + memset(pwr_buf,0,POWER_BUFFER_SIZE); + virtual_power_status_register = 0; + if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND]))) + { + mali_pm_os_suspend(); + /* @@@@ assuming currently suspend is successful later on to tune as per previous*/ + virtual_power_status_register =1; + + } + else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME]))) + { + mali_pm_os_resume(); + + /* @@@@ assuming currently resume is successful later on to tune as per previous */ + virtual_power_status_register = 1; + } + else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE]))) + { + mali_bool power_on; + mali_dev_pause(&power_on); + if (!power_on) + { + virtual_power_status_register = 2; + mali_dev_resume(); + } + else + { + /* @@@@ assuming currently resume is successful later on to tune as per previous */ + virtual_power_status_register =1; + } + } + else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME]))) + { + mali_dev_resume(); + /* @@@@ assuming currently resume is successful later on to tune as per previous */ + virtual_power_status_register = 1; + + } + *ppos += cnt; + sprintf(pwr_buf, "%d",virtual_power_status_register); + return cnt; +} + +static ssize_t power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return simple_read_from_buffer(ubuf, cnt, ppos, pwr_buf, POWER_BUFFER_SIZE); +} + +static loff_t power_events_seek(struct file *file, loff_t offset, int orig) +{ + file->f_pos = offset; + return 0; +} + +static const struct file_operations power_events_fops = { + .owner = THIS_MODULE, + .read = power_events_read, + .write = power_events_write, + .llseek = power_events_seek, +}; + + +#if MALI_STATE_TRACKING +static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v) +{ + u32 len = 0; + u32 size; + char *buf; + + size = seq_get_buf(seq_file, &buf); + + if(!size) + { + return -ENOMEM; + } + + /* Create the internal state dump. */ + len = snprintf(buf+len, size-len, "Mali device driver %s\n", SVN_REV_STRING); + len += snprintf(buf+len, size-len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE); + + len += _mali_kernel_core_dump_state(buf + len, size - len); + + seq_commit(seq_file, len); + + return 0; +} + +static int mali_seq_internal_state_open(struct inode *inode, struct file *file) +{ + return single_open(file, mali_seq_internal_state_show, NULL); +} + +static const struct file_operations mali_seq_internal_state_fops = { + .owner = THIS_MODULE, + .open = mali_seq_internal_state_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif /* MALI_STATE_TRACKING */ + + +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + int r; + + r = sprintf(buf, "%u\n", _mali_osk_profiling_is_recording() ? 1 : 0); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + unsigned long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtoul(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val != 0) + { + u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */ + + /* check if we are already recording */ + if (MALI_TRUE == _mali_osk_profiling_is_recording()) + { + MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n")); + return -EFAULT; + } + + /* check if we need to clear out an old recording first */ + if (MALI_TRUE == _mali_osk_profiling_have_recording()) + { + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_clear()) + { + MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n")); + return -EFAULT; + } + } + + /* start recording profiling data */ + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit)) + { + MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n")); + return -EFAULT; + } + + MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit)); + } + else + { + /* stop recording profiling data */ + u32 count = 0; + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_stop(&count)) + { + MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n")); + return -EFAULT; + } + + MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count)); + } + + *ppos += cnt; + return cnt; +} + +static const struct file_operations profiling_record_fops = { + .owner = THIS_MODULE, + .read = profiling_record_read, + .write = profiling_record_write, +}; + +static void *profiling_events_start(struct seq_file *s, loff_t *pos) +{ + loff_t *spos; + + /* check if we have data avaiable */ + if (MALI_TRUE != _mali_osk_profiling_have_recording()) + { + return NULL; + } + + spos = kmalloc(sizeof(loff_t), GFP_KERNEL); + if (NULL == spos) + { + return NULL; + } + + *spos = *pos; + return spos; +} + +static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos) +{ + loff_t *spos = v; + + /* check if we have data avaiable */ + if (MALI_TRUE != _mali_osk_profiling_have_recording()) + { + return NULL; + } + + /* check if the next entry actually is avaiable */ + if (_mali_osk_profiling_get_count() <= (u32)(*spos + 1)) + { + return NULL; + } + + *pos = ++*spos; + return spos; +} + +static void profiling_events_stop(struct seq_file *s, void *v) +{ + kfree(v); +} + +static int profiling_events_show(struct seq_file *seq_file, void *v) +{ + loff_t *spos = v; + u32 index; + u64 timestamp; + u32 event_id; + u32 data[5]; + + index = (u32)*spos; + + /* Retrieve all events */ + if (_MALI_OSK_ERR_OK == _mali_osk_profiling_get_event(index, ×tamp, &event_id, data)) + { + seq_printf(seq_file, "%llu %u %u %u %u %u %u\n", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]); + return 0; + } + + return 0; +} + +static const struct seq_operations profiling_events_seq_ops = { + .start = profiling_events_start, + .next = profiling_events_next, + .stop = profiling_events_stop, + .show = profiling_events_show +}; + +static int profiling_events_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &profiling_events_seq_ops); +} + +static const struct file_operations profiling_events_fops = { + .owner = THIS_MODULE, + .open = profiling_events_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; +#endif + +static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 mem = _mali_ukk_report_memory_usage(); + + r = snprintf(buf, 64, "%u\n", mem); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static const struct file_operations memory_usage_fops = { + .owner = THIS_MODULE, + .read = memory_used_read, +}; + + +static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + unsigned long val; + int ret; + _mali_uk_user_setting_t setting; + char buf[32]; + + cnt = min(cnt, sizeof(buf) - 1); + if (copy_from_user(buf, ubuf, cnt)) + { + return -EFAULT; + } + buf[cnt] = '\0'; + + ret = strict_strtoul(buf, 10, &val); + if (0 != ret) + { + return ret; + } + + /* Update setting */ + setting = (_mali_uk_user_setting_t)(filp->private_data); + mali_set_user_setting(setting, val); + + *ppos += cnt; + return cnt; +} + +static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 value; + _mali_uk_user_setting_t setting; + + setting = (_mali_uk_user_setting_t)(filp->private_data); + value = mali_get_user_setting(setting); + + r = snprintf(buf, 64, "%u\n", value); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static const struct file_operations user_settings_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = user_settings_read, + .write = user_settings_write, +}; + +static int mali_sysfs_user_settings_register(void) +{ + struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir); + + if (mali_user_settings_dir != NULL) + { + int i; + for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++) + { + debugfs_create_file(_mali_uk_user_setting_descriptions[i], 0600, mali_user_settings_dir, (void*)i, &user_settings_fops); + } + } + + return 0; +} + +int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name) +{ + int err = 0; + + device->mali_class = class_create(THIS_MODULE, mali_dev_name); + if (IS_ERR(device->mali_class)) + { + err = PTR_ERR(device->mali_class); + goto init_class_err; + } + mali_device = device_create(device->mali_class, NULL, dev, NULL, mali_dev_name); + if (IS_ERR(mali_device)) + { + err = PTR_ERR(mali_device); + goto init_mdev_err; + } + + mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL); + if(ERR_PTR(-ENODEV) == mali_debugfs_dir) + { + /* Debugfs not supported. */ + mali_debugfs_dir = NULL; + } + else + { + if(NULL != mali_debugfs_dir) + { + /* Debugfs directory created successfully; create files now */ + struct dentry *mali_power_dir; + struct dentry *mali_gp_dir; + struct dentry *mali_pp_dir; + struct dentry *mali_l2_dir; +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED + struct dentry *mali_profiling_dir; +#endif + + mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir); + if (mali_power_dir != NULL) + { + debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_events_fops); + } + + mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir); + if (mali_gp_dir != NULL) + { + struct dentry *mali_gp_all_dir; + u32 ci; + struct mali_cluster *cluster; + + mali_gp_all_dir = debugfs_create_dir("all", mali_gp_dir); + if (mali_gp_all_dir != NULL) + { + debugfs_create_file("counter_src0", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops); + } + + ci = 0; + cluster = mali_cluster_get_global_cluster(ci); + while (NULL != cluster) + { + u32 gi = 0; + struct mali_group *group = mali_cluster_get_group(cluster, gi); + while (NULL != group) + { + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) + { + struct dentry *mali_gp_gpx_dir; + mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir); + if (NULL != mali_gp_gpx_dir) + { + debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops); + } + break; /* no need to look for any other GP cores */ + } + + /* try next group */ + gi++; + group = mali_cluster_get_group(cluster, gi); + } + + /* try next cluster */ + ci++; + cluster = mali_cluster_get_global_cluster(ci); + } + } + + mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir); + if (mali_pp_dir != NULL) + { + struct dentry *mali_pp_all_dir; + u32 ci; + struct mali_cluster *cluster; + + mali_pp_all_dir = debugfs_create_dir("all", mali_pp_dir); + if (mali_pp_all_dir != NULL) + { + debugfs_create_file("counter_src0", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops); + } + + ci = 0; + cluster = mali_cluster_get_global_cluster(ci); + while (NULL != cluster) + { + u32 gi = 0; + struct mali_group *group = mali_cluster_get_group(cluster, gi); + while (NULL != group) + { + struct mali_pp_core *pp_core = mali_group_get_pp_core(group); + if (NULL != pp_core) + { + char buf[16]; + struct dentry *mali_pp_ppx_dir; + _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core)); + mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir); + if (NULL != mali_pp_ppx_dir) + { + debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops); + } + } + + /* try next group */ + gi++; + group = mali_cluster_get_group(cluster, gi); + } + + /* try next cluster */ + ci++; + cluster = mali_cluster_get_global_cluster(ci); + } + } + + mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir); + if (mali_l2_dir != NULL) + { + struct dentry *mali_l2_all_dir; + u32 l2_id; + struct mali_l2_cache_core *l2_cache; + + mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir); + if (mali_l2_all_dir != NULL) + { + debugfs_create_file("counter_src0", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops); + } + + l2_id = 0; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + while (NULL != l2_cache) + { + char buf[16]; + struct dentry *mali_l2_l2x_dir; + _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id); + mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir); + if (NULL != mali_l2_l2x_dir) + { + debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops); + } + + /* try next L2 */ + l2_id++; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + } + } + + debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops); + +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED + mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir); + if (mali_profiling_dir != NULL) + { + struct dentry *mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir); + if (mali_profiling_proc_dir != NULL) + { + struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir); + if (mali_profiling_proc_default_dir != NULL) + { + debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void*)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops); + } + } + debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops); + debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops); + } +#endif + +#if MALI_STATE_TRACKING + debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops); +#endif + + if (mali_sysfs_user_settings_register()) + { + /* Failed to create the debugfs entries for the user settings DB. */ + MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n")); + } + } + } + + /* Success! */ + return 0; + + /* Error handling */ +init_mdev_err: + class_destroy(device->mali_class); +init_class_err: + + return err; +} + +int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name) +{ + if(NULL != mali_debugfs_dir) + { + debugfs_remove_recursive(mali_debugfs_dir); + } + device_destroy(device->mali_class, dev); + class_destroy(device->mali_class); + + return 0; +} + +#else + +/* Dummy implementations for non-GPL */ + +int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name) +{ + return 0; +} + +int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name) +{ + return 0; +} + + +#endif diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h new file mode 100644 index 0000000..24acca9 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_SYSFS_H__ +#define __MALI_KERNEL_SYSFS_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#define MALI_PROC_DIR "driver/mali" + +extern struct device *mali_device; +struct mali_dev; + +int mali_sysfs_register(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name); + +int mali_sysfs_unregister(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name); + + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_KERNEL_LINUX_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_pm.h b/drivers/media/video/samsung/mali/linux/mali_linux_pm.h new file mode 100644 index 0000000..10f633e --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_linux_pm.h @@ -0,0 +1,50 @@ + +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_LINUX_PM_H__ +#define __MALI_LINUX_PM_H__ + +#ifdef CONFIG_PM +/* Number of power states supported for making power up and down */ +typedef enum +{ + _MALI_DEVICE_SUSPEND, /* Suspend */ + _MALI_DEVICE_RESUME, /* Resume */ + _MALI_DEVICE_MAX_POWER_STATES, /* Maximum power states */ +} _mali_device_power_states; + +/* Number of DVFS events */ +typedef enum +{ + _MALI_DVFS_PAUSE_EVENT = _MALI_DEVICE_MAX_POWER_STATES, /* DVFS Pause event */ + _MALI_DVFS_RESUME_EVENT, /* DVFS Resume event */ + _MALI_MAX_DEBUG_OPERATIONS, +} _mali_device_dvfs_events; + +extern _mali_device_power_states mali_device_state; +extern _mali_device_power_states mali_dvfs_device_state; +extern _mali_osk_lock_t *lock; +extern short is_wake_up_needed; +extern int timeout_fired; +extern struct platform_device mali_gpu_device; + +/* dvfs pm thread */ +extern struct task_struct *dvfs_pm_thread; + +/* Power management thread */ +extern struct task_struct *pm_thread; + +int mali_device_suspend(u32 event_id, struct task_struct **pwr_mgmt_thread); +int mali_device_resume(u32 event_id, struct task_struct **pwr_mgmt_thread); +int mali_get_ospmm_thread_state(void); + +#endif /* CONFIG_PM */ +#endif /* __MALI_LINUX_PM_H___ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h b/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h new file mode 100644 index 0000000..7d811bd --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __MALI_LINUX_PM_TESTSUITE_H__ +#define __MALI_LINUX_PM_TESTSUITE_H__ + +#if MALI_POWER_MGMT_TEST_SUITE && defined(CONFIG_PM) + +typedef enum +{ + _MALI_DEVICE_PMM_TIMEOUT_EVENT, + _MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS, + _MALI_DEVICE_PMM_REGISTERED_CORES, + _MALI_DEVICE_MAX_PMM_EVENTS + +} _mali_device_pmm_recording_events; + +extern unsigned int mali_timeout_event_recording_on; +extern unsigned int mali_job_scheduling_events_recording_on; +extern unsigned int pwr_mgmt_status_reg; +extern unsigned int is_mali_pmm_testsuite_enabled; +extern unsigned int is_mali_pmu_present; + +#endif /* MALI_POWER_MGMT_TEST_SUITE && defined(CONFIG_PM) */ + +#endif /* __MALI_LINUX_PM_TESTSUITE_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_trace.h b/drivers/media/video/samsung/mali/linux/mali_linux_trace.h new file mode 100644 index 0000000..5329ba3 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_linux_trace.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if !defined (MALI_LINUX_TRACE_H) || defined (TRACE_HEADER_MULTI_READ) +#define MALI_LINUX_TRACE_H + +#include + +#include +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali +#define TRACE_SYSTEM_STRING __stringfy(TRACE_SYSTEM) + +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE mali_linux_trace + +/** + * Define the tracepoint used to communicate the status of a GPU. Called + * when a GPU turns on or turns off. + * + * @param event_id The type of the event. This parameter is a bitfield + * encoding the type of the event. + * + * @param d0 First data parameter. + * @param d1 Second data parameter. + * @param d2 Third data parameter. + * @param d3 Fourth data parameter. + * @param d4 Fifth data parameter. + */ +TRACE_EVENT(mali_timeline_event, + + TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, + unsigned int d2, unsigned int d3, unsigned int d4), + + TP_ARGS(event_id, d0, d1, d2, d3, d4), + + TP_STRUCT__entry( + __field(unsigned int, event_id) + __field(unsigned int, d0) + __field(unsigned int, d1) + __field(unsigned int, d2) + __field(unsigned int, d3) + __field(unsigned int, d4) + ), + + TP_fast_assign( + __entry->event_id = event_id; + __entry->d0 = d0; + __entry->d1 = d1; + __entry->d2 = d2; + __entry->d3 = d3; + __entry->d4 = d4; + ), + + TP_printk("event=%d", __entry->event_id) +); + +/** + * Define a tracepoint used to regsiter the value of a hardware counter. + * Hardware counters belonging to the vertex or fragment processor are + * reported via this tracepoint each frame, whilst L2 cache hardware + * counters are reported continuously. + * + * @param counter_id The counter ID. + * @param value The value of the counter. + */ +TRACE_EVENT(mali_hw_counter, + + TP_PROTO(unsigned int counter_id, unsigned int value), + + TP_ARGS(counter_id, value), + + TP_STRUCT__entry( + __field(unsigned int, counter_id) + __field(unsigned int, value) + ), + + TP_fast_assign( + __entry->counter_id = counter_id; + ), + + TP_printk("event %d = %d", __entry->counter_id, __entry->value) +); + +/** + * Define a tracepoint used to send a bundle of software counters. + * + * @param counters The bundle of counters. + */ +TRACE_EVENT(mali_sw_counters, + + TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters), + + TP_ARGS(pid, tid, surface_id, counters), + + TP_STRUCT__entry( + __field(pid_t, pid) + __field(pid_t, tid) + __field(void *, surface_id) + __field(unsigned int *, counters) + ), + + TP_fast_assign( + __entry->pid = pid; + __entry->tid = tid; + __entry->surface_id = surface_id; + __entry->counters = counters; + ), + + TP_printk("counters were %s", __entry->counters == NULL? "NULL" : "not NULL") +); + +#endif /* MALI_LINUX_TRACE_H */ + +/* This part must exist outside the header guard. */ +#include + diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_atomics.c b/drivers/media/video/samsung/mali/linux/mali_osk_atomics.c new file mode 100644 index 0000000..32f8e6b --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_atomics.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_atomics.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include "mali_osk.h" +#include +#include "mali_kernel_common.h" + +void _mali_osk_atomic_dec( _mali_osk_atomic_t *atom ) +{ + atomic_dec((atomic_t *)&atom->u.val); +} + +u32 _mali_osk_atomic_dec_return( _mali_osk_atomic_t *atom ) +{ + return atomic_dec_return((atomic_t *)&atom->u.val); +} + +void _mali_osk_atomic_inc( _mali_osk_atomic_t *atom ) +{ + atomic_inc((atomic_t *)&atom->u.val); +} + +u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom ) +{ + return atomic_inc_return((atomic_t *)&atom->u.val); +} + +_mali_osk_errcode_t _mali_osk_atomic_init( _mali_osk_atomic_t *atom, u32 val ) +{ + MALI_CHECK_NON_NULL(atom, _MALI_OSK_ERR_INVALID_ARGS); + atomic_set((atomic_t *)&atom->u.val, val); + return _MALI_OSK_ERR_OK; +} + +u32 _mali_osk_atomic_read( _mali_osk_atomic_t *atom ) +{ + return atomic_read((atomic_t *)&atom->u.val); +} + +void _mali_osk_atomic_term( _mali_osk_atomic_t *atom ) +{ + MALI_IGNORE(atom); +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_irq.c b/drivers/media/video/samsung/mali/linux/mali_osk_irq.c new file mode 100644 index 0000000..ddfe564 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_irq.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_irq.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include /* For memory allocation */ +#include +#include + +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_kernel_license.h" +#include "mali_kernel_linux.h" +#include "linux/interrupt.h" + +typedef struct _mali_osk_irq_t_struct +{ + u32 irqnum; + void *data; + _mali_osk_irq_uhandler_t uhandler; + _mali_osk_irq_bhandler_t bhandler; + struct work_struct work_queue_irq_handle; /* Workqueue for the bottom half of the IRQ-handling. This job is activated when this core gets an IRQ.*/ +} mali_osk_irq_object_t; + +#if MALI_LICENSE_IS_GPL +static struct workqueue_struct *pmm_wq = NULL; +struct workqueue_struct *mali_wq = NULL; +#endif + +typedef void (*workqueue_func_t)(void *); +typedef irqreturn_t (*irq_handler_func_t)(int, void *, struct pt_regs *); +static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ); /* , struct pt_regs *regs*/ + +#if defined(INIT_DELAYED_WORK) +static void irq_handler_bottom_half ( struct work_struct *work ); +#else +static void irq_handler_bottom_half ( void * input ); +#endif + +/** + * Linux kernel version has marked SA_SHIRQ as deprecated, IRQF_SHARED should be used. + * This is to handle older kernels which haven't done this swap. + */ +#ifndef IRQF_SHARED +#define IRQF_SHARED SA_SHIRQ +#endif /* IRQF_SHARED */ + +_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, _mali_osk_irq_bhandler_t bhandler, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *data, const char *description ) +{ + mali_osk_irq_object_t *irq_object; + + irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL); + if (NULL == irq_object) return NULL; + +#if MALI_LICENSE_IS_GPL + if (NULL == mali_wq) + { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) + mali_wq = alloc_workqueue("mali", WQ_UNBOUND, 0); +#else + mali_wq = create_workqueue("mali"); +#endif + if(NULL == mali_wq) + { + MALI_PRINT_ERROR(("Unable to create Mali workqueue\n")); + kfree(irq_object); + return NULL; + } + } +#endif + + /* workqueue API changed in 2.6.20, support both versions: */ +#if defined(INIT_DELAYED_WORK) + /* New syntax: INIT_WORK( struct work_struct *work, void (*function)(struct work_struct *)) */ + INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half); +#else + /* Old syntax: INIT_WORK( struct work_struct *work, void (*function)(void *), void *data) */ + INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half, irq_object); +#endif /* defined(INIT_DELAYED_WORK) */ + + if (-1 == irqnum) + { + /* Probe for IRQ */ + if ( (NULL != trigger_func) && (NULL != ack_func) ) + { + unsigned long probe_count = 3; + _mali_osk_errcode_t err; + int irq; + + MALI_DEBUG_PRINT(2, ("Probing for irq\n")); + + do + { + unsigned long mask; + + mask = probe_irq_on(); + trigger_func(data); + + _mali_osk_time_ubusydelay(5); + + irq = probe_irq_off(mask); + err = ack_func(data); + } + while (irq < 0 && (err == _MALI_OSK_ERR_OK) && probe_count--); + + if (irq < 0 || (_MALI_OSK_ERR_OK != err)) irqnum = -1; + else irqnum = irq; + } + else irqnum = -1; /* no probe functions, fault */ + + if (-1 != irqnum) + { + /* found an irq */ + MALI_DEBUG_PRINT(2, ("Found irq %d\n", irqnum)); + } + else + { + MALI_DEBUG_PRINT(2, ("Probe for irq failed\n")); + } + } + + irq_object->irqnum = irqnum; + irq_object->uhandler = uhandler; + irq_object->bhandler = bhandler; + irq_object->data = data; + + /* Is this a real IRQ handler we need? */ + if (irqnum != _MALI_OSK_IRQ_NUMBER_FAKE && irqnum != _MALI_OSK_IRQ_NUMBER_PMM) + { + if (-1 == irqnum) + { + MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description)); + kfree(irq_object); + return NULL; + } + + if (0 != request_irq(irqnum, irq_handler_upper_half, IRQF_SHARED, description, irq_object)) + { + MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description)); + kfree(irq_object); + return NULL; + } + } + +#if MALI_LICENSE_IS_GPL + if ( _MALI_OSK_IRQ_NUMBER_PMM == irqnum ) + { + pmm_wq = create_singlethread_workqueue("mali-pmm-wq"); + } +#endif + + return irq_object; +} + +void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq ) +{ + mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq; +#if MALI_LICENSE_IS_GPL + if ( irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM ) + { + queue_work( pmm_wq,&irq_object->work_queue_irq_handle ); + } + else + { + queue_work(mali_wq, &irq_object->work_queue_irq_handle); + } +#else + schedule_work(&irq_object->work_queue_irq_handle); +#endif +} + +void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq ) +{ +#if MALI_LICENSE_IS_GPL + if (NULL != irq) + { + mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq; + if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM ) + { + flush_workqueue(pmm_wq); + } + else + { + flush_workqueue(mali_wq); + } + } + else + { + flush_workqueue(mali_wq); + } +#endif +} + +void _mali_osk_irq_term( _mali_osk_irq_t *irq ) +{ + mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq; + +#if MALI_LICENSE_IS_GPL + if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM ) + { + flush_workqueue(pmm_wq); + destroy_workqueue(pmm_wq); + } +#endif + free_irq(irq_object->irqnum, irq_object); + kfree(irq_object); + flush_scheduled_work(); +} + + +/** This function is called directly in interrupt context from the OS just after + * the CPU get the hw-irq from mali, or other devices on the same IRQ-channel. + * It is registered one of these function for each mali core. When an interrupt + * arrives this function will be called equal times as registered mali cores. + * That means that we only check one mali core in one function call, and the + * core we check for each turn is given by the \a dev_id variable. + * If we detect an pending interrupt on the given core, we mask the interrupt + * out by settging the core's IRQ_MASK register to zero. + * Then we schedule the mali_core_irq_handler_bottom_half to run as high priority + * work queue job. + */ +static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ) /* , struct pt_regs *regs*/ +{ + mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)dev_id; + + if (irq_object->uhandler(irq_object->data) == _MALI_OSK_ERR_OK) + { + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +/* Is executed when an interrupt occur on one core */ +/* workqueue API changed in 2.6.20, support both versions: */ +#if defined(INIT_DELAYED_WORK) +static void irq_handler_bottom_half ( struct work_struct *work ) +#else +static void irq_handler_bottom_half ( void * input ) +#endif +{ + mali_osk_irq_object_t *irq_object; + +#if defined(INIT_DELAYED_WORK) + irq_object = _MALI_OSK_CONTAINER_OF(work, mali_osk_irq_object_t, work_queue_irq_handle); +#else + if ( NULL == input ) + { + MALI_PRINT_ERROR(("IRQ: Null pointer! Illegal!")); + return; /* Error */ + } + irq_object = (mali_osk_irq_object_t *) input; +#endif + + irq_object->bhandler(irq_object->data); +} + diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_locks.c b/drivers/media/video/samsung/mali/linux/mali_osk_locks.c new file mode 100644 index 0000000..ee857d5 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_locks.c @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_locks.c + * Implemenation of the OS abstraction layer for the kernel device driver + */ + +/* needed to detect kernel version specific code */ +#include + +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else /* pre 2.6.26 the file was in the arch specific location */ +#include +#endif + +#include +#include "mali_osk.h" +#include "mali_kernel_common.h" + +/* These are all the locks we implement: */ +typedef enum +{ + _MALI_OSK_INTERNAL_LOCKTYPE_SPIN, /* Mutex, implicitly non-interruptable, use spin_lock/spin_unlock */ + _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ, /* Mutex, IRQ version of spinlock, use spin_lock_irqsave/spin_unlock_irqrestore */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX, /* Interruptable, use up()/down_interruptable() */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT, /* Non-Interruptable, use up()/down() */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW, /* Non-interruptable, Reader/Writer, use {up,down}{read,write}() */ + + /* Linux supports, but we do not support: + * Non-Interruptable Reader/Writer spinlock mutexes - RW optimization will be switched off + */ + + /* Linux does not support: + * One-locks, of any sort - no optimization for this fact will be made. + */ + +} _mali_osk_internal_locktype; + +struct _mali_osk_lock_t_struct +{ + _mali_osk_internal_locktype type; + unsigned long flags; + union + { + spinlock_t spinlock; + struct semaphore sema; + struct rw_semaphore rw_sema; + } obj; + MALI_DEBUG_CODE( + /** original flags for debug checking */ + _mali_osk_lock_flags_t orig_flags; + + /* id of the thread currently holding this lock, 0 if no + * threads hold it. */ + u32 owner; + /* number of owners this lock currently has (can be > 1 if + * taken in R/O mode. */ + u32 nOwners; + /* what mode the lock was taken in */ + _mali_osk_lock_mode_t mode; + ); /* MALI_DEBUG_CODE */ +}; + +_mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial, u32 order ) +{ + _mali_osk_lock_t *lock = NULL; + + /* Validate parameters: */ + /* Flags acceptable */ + MALI_DEBUG_ASSERT( 0 == ( flags & ~(_MALI_OSK_LOCKFLAG_SPINLOCK + | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ + | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE + | _MALI_OSK_LOCKFLAG_READERWRITER + | _MALI_OSK_LOCKFLAG_ORDERED + | _MALI_OSK_LOCKFLAG_ONELOCK )) ); + /* Spinlocks are always non-interruptable */ + MALI_DEBUG_ASSERT( (((flags & _MALI_OSK_LOCKFLAG_SPINLOCK) || (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ)) && (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE)) + || !(flags & _MALI_OSK_LOCKFLAG_SPINLOCK)); + /* Parameter initial SBZ - for future expansion */ + MALI_DEBUG_ASSERT( 0 == initial ); + + lock = kmalloc(sizeof(_mali_osk_lock_t), GFP_KERNEL); + + if ( NULL == lock ) + { + return lock; + } + + /* Determine type of mutex: */ + /* defaults to interruptable mutex if no flags are specified */ + + if ( (flags & _MALI_OSK_LOCKFLAG_SPINLOCK) ) + { + /* Non-interruptable Spinlocks override all others */ + lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_SPIN; + spin_lock_init( &lock->obj.spinlock ); + } + else if ( (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ ) ) + { + lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ; + lock->flags = 0; + spin_lock_init( &lock->obj.spinlock ); + } + else if ( (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE) + && (flags & _MALI_OSK_LOCKFLAG_READERWRITER) ) + { + lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW; + init_rwsem( &lock->obj.rw_sema ); + } + else + { + /* Usual mutex types */ + if ( (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE) ) + { + lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT; + } + else + { + lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX; + } + + /* Initially unlocked */ + sema_init( &lock->obj.sema, 1 ); + } + +#ifdef DEBUG + /* Debug tracking of flags */ + lock->orig_flags = flags; + + /* Debug tracking of lock owner */ + lock->owner = 0; + lock->nOwners = 0; +#endif /* DEBUG */ + + return lock; +} + +#ifdef DEBUG +u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock ) +{ + return lock->owner; +} + +u32 _mali_osk_lock_get_number_owners( _mali_osk_lock_t *lock ) +{ + return lock->nOwners; +} + +u32 _mali_osk_lock_get_mode( _mali_osk_lock_t *lock ) +{ + return lock->mode; +} +#endif /* DEBUG */ + +_mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; + + /* Parameter validation */ + MALI_DEBUG_ASSERT_POINTER( lock ); + + MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode + || _MALI_OSK_LOCKMODE_RO == mode ); + + /* Only allow RO locks when the initial object was a Reader/Writer lock + * Since information is lost on the internal locktype, we use the original + * information, which is only stored when built for DEBUG */ + MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode + || (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) ); + + switch ( lock->type ) + { + case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN: + spin_lock(&lock->obj.spinlock); + break; + case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ: + { + unsigned long tmp_flags; + spin_lock_irqsave(&lock->obj.spinlock, tmp_flags); + lock->flags = tmp_flags; + } + break; + + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX: + if ( down_interruptible(&lock->obj.sema) ) + { + MALI_PRINT_ERROR(("Can not lock mutex\n")); + err = _MALI_OSK_ERR_RESTARTSYSCALL; + } + break; + + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT: + down(&lock->obj.sema); + break; + + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW: + if (mode == _MALI_OSK_LOCKMODE_RO) + { + down_read(&lock->obj.rw_sema); + } + else + { + down_write(&lock->obj.rw_sema); + } + break; + + default: + /* Reaching here indicates a programming error, so you will not get here + * on non-DEBUG builds */ + MALI_DEBUG_PRINT_ERROR( ("Invalid internal lock type: %.8X", lock->type ) ); + break; + } + +#ifdef DEBUG + /* This thread is now the owner of this lock */ + if (_MALI_OSK_ERR_OK == err) + { + if (mode == _MALI_OSK_LOCKMODE_RW) + { + /*MALI_DEBUG_ASSERT(0 == lock->owner);*/ + if (0 != lock->owner) + { + printk(KERN_ERR "%d: ERROR: Lock %p already has owner %d\n", _mali_osk_get_tid(), lock, lock->owner); + dump_stack(); + } + lock->owner = _mali_osk_get_tid(); + lock->mode = mode; + ++lock->nOwners; + } + else /* mode == _MALI_OSK_LOCKMODE_RO */ + { + lock->owner |= _mali_osk_get_tid(); + lock->mode = mode; + ++lock->nOwners; + } + } +#endif + + return err; +} + +void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ) +{ + /* Parameter validation */ + MALI_DEBUG_ASSERT_POINTER( lock ); + + MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode + || _MALI_OSK_LOCKMODE_RO == mode ); + + /* Only allow RO locks when the initial object was a Reader/Writer lock + * Since information is lost on the internal locktype, we use the original + * information, which is only stored when built for DEBUG */ + MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode + || (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) ); + +#ifdef DEBUG + /* make sure the thread releasing the lock actually was the owner */ + if (mode == _MALI_OSK_LOCKMODE_RW) + { + /*MALI_DEBUG_ASSERT(_mali_osk_get_tid() == lock->owner);*/ + if (_mali_osk_get_tid() != lock->owner) + { + printk(KERN_ERR "%d: ERROR: Lock %p owner was %d\n", _mali_osk_get_tid(), lock, lock->owner); + dump_stack(); + } + /* This lock now has no owner */ + lock->owner = 0; + --lock->nOwners; + } + else /* mode == _MALI_OSK_LOCKMODE_RO */ + { + if ((_mali_osk_get_tid() & lock->owner) != _mali_osk_get_tid()) + { + printk(KERN_ERR "%d: ERROR: Not an owner of %p lock.\n", _mali_osk_get_tid(), lock); + dump_stack(); + } + + /* if this is the last thread holding this lock in R/O mode, set owner + * back to 0 */ + if (0 == --lock->nOwners) + { + lock->owner = 0; + } + } +#endif /* DEBUG */ + + switch ( lock->type ) + { + case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN: + spin_unlock(&lock->obj.spinlock); + break; + case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ: + spin_unlock_irqrestore(&lock->obj.spinlock, lock->flags); + break; + + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX: + /* FALLTHROUGH */ + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT: + up(&lock->obj.sema); + break; + + case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW: + if (mode == _MALI_OSK_LOCKMODE_RO) + { + up_read(&lock->obj.rw_sema); + } + else + { + up_write(&lock->obj.rw_sema); + } + break; + + default: + /* Reaching here indicates a programming error, so you will not get here + * on non-DEBUG builds */ + MALI_DEBUG_PRINT_ERROR( ("Invalid internal lock type: %.8X", lock->type ) ); + break; + } +} + +void _mali_osk_lock_term( _mali_osk_lock_t *lock ) +{ + /* Parameter validation */ + MALI_DEBUG_ASSERT_POINTER( lock ); + + /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */ + kfree(lock); +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c b/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c new file mode 100644 index 0000000..02558a0 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c @@ -0,0 +1,660 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_low_level_mem.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +/* needed to detect kernel version specific code */ +#include + +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) +#include +#endif + +#include "mali_osk.h" +#include "mali_ukk.h" /* required to hook in _mali_ukk_mem_mmap handling */ +#include "mali_kernel_common.h" +#include "mali_kernel_linux.h" + +static void mali_kernel_memory_vma_open(struct vm_area_struct * vma); +static void mali_kernel_memory_vma_close(struct vm_area_struct * vma); + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf); +#else +static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address); +#endif + + +typedef struct mali_vma_usage_tracker +{ + int references; + u32 cookie; +} mali_vma_usage_tracker; + + +/* Linked list structure to hold details of all OS allocations in a particular + * mapping + */ +struct AllocationList +{ + struct AllocationList *next; + u32 offset; + u32 physaddr; +}; + +typedef struct AllocationList AllocationList; + +/* Private structure to store details of a mapping region returned + * from _mali_osk_mem_mapregion_init + */ +struct MappingInfo +{ + struct vm_area_struct *vma; + struct AllocationList *list; + struct AllocationList *tail; +}; + +typedef struct MappingInfo MappingInfo; + + +static u32 _kernel_page_allocate(void); +static void _kernel_page_release(u32 physical_address); +static AllocationList * _allocation_list_item_get(void); +static void _allocation_list_item_release(AllocationList * item); + + +/* Variable declarations */ +static DEFINE_SPINLOCK(allocation_list_spinlock); +static AllocationList * pre_allocated_memory = (AllocationList*) NULL ; +static int pre_allocated_memory_size_current = 0; +#ifdef MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB + static int pre_allocated_memory_size_max = MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB * 1024 * 1024; +#else + static int pre_allocated_memory_size_max = 16 * 1024 * 1024; /* 6 MiB */ +#endif + +static struct vm_operations_struct mali_kernel_vm_ops = +{ + .open = mali_kernel_memory_vma_open, + .close = mali_kernel_memory_vma_close, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + .fault = mali_kernel_memory_cpu_page_fault_handler +#else + .nopfn = mali_kernel_memory_cpu_page_fault_handler +#endif +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) +static int mali_mem_shrink(int nr_to_scan, gfp_t gfp_mask) + #else +static int mali_mem_shrink(struct shrinker *shrinker, int nr_to_scan, gfp_t gfp_mask) + #endif +#else +static int mali_mem_shrink(struct shrinker *shrinker, struct shrink_control *sc) +#endif +{ + unsigned long flags; + AllocationList *item; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + int nr = nr_to_scan; +#else + int nr = sc->nr_to_scan; +#endif + + if (0 == nr) + { + return pre_allocated_memory_size_current / PAGE_SIZE; + } + + if (0 == pre_allocated_memory_size_current) + { + /* No pages availble */ + return 0; + } + + if (0 == spin_trylock_irqsave(&allocation_list_spinlock, flags)) + { + /* Not able to lock. */ + return -1; + } + + while (pre_allocated_memory && nr > 0) + { + item = pre_allocated_memory; + pre_allocated_memory = item->next; + + _kernel_page_release(item->physaddr); + _mali_osk_free(item); + + pre_allocated_memory_size_current -= PAGE_SIZE; + --nr; + } + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + + return pre_allocated_memory_size_current / PAGE_SIZE; +} + +struct shrinker mali_mem_shrinker = { + .shrink = mali_mem_shrink, + .seeks = DEFAULT_SEEKS, +}; + +void mali_osk_low_level_mem_init(void) +{ + pre_allocated_memory = (AllocationList*) NULL ; + + register_shrinker(&mali_mem_shrinker); +} + +void mali_osk_low_level_mem_term(void) +{ + unregister_shrinker(&mali_mem_shrinker); + + while ( NULL != pre_allocated_memory ) + { + AllocationList *item; + item = pre_allocated_memory; + pre_allocated_memory = item->next; + _kernel_page_release(item->physaddr); + _mali_osk_free( item ); + } + pre_allocated_memory_size_current = 0; +} + +static u32 _kernel_page_allocate(void) +{ + struct page *new_page; + u32 linux_phys_addr; + + new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD); + + if ( NULL == new_page ) + { + return 0; + } + + /* Ensure page is flushed from CPU caches. */ + linux_phys_addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); + + return linux_phys_addr; +} + +static void _kernel_page_release(u32 physical_address) +{ + struct page *unmap_page; + + #if 1 + dma_unmap_page(NULL, physical_address, PAGE_SIZE, DMA_BIDIRECTIONAL); + #endif + + unmap_page = pfn_to_page( physical_address >> PAGE_SHIFT ); + MALI_DEBUG_ASSERT_POINTER( unmap_page ); + __free_page( unmap_page ); +} + +static AllocationList * _allocation_list_item_get(void) +{ + AllocationList *item = NULL; + unsigned long flags; + + spin_lock_irqsave(&allocation_list_spinlock,flags); + if ( pre_allocated_memory ) + { + item = pre_allocated_memory; + pre_allocated_memory = pre_allocated_memory->next; + pre_allocated_memory_size_current -= PAGE_SIZE; + + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + return item; + } + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + + item = _mali_osk_malloc( sizeof(AllocationList) ); + if ( NULL == item) + { + return NULL; + } + + item->physaddr = _kernel_page_allocate(); + if ( 0 == item->physaddr ) + { + /* Non-fatal error condition, out of memory. Upper levels will handle this. */ + _mali_osk_free( item ); + return NULL; + } + return item; +} + +static void _allocation_list_item_release(AllocationList * item) +{ + unsigned long flags; + spin_lock_irqsave(&allocation_list_spinlock,flags); + if ( pre_allocated_memory_size_current < pre_allocated_memory_size_max) + { + item->next = pre_allocated_memory; + pre_allocated_memory = item; + pre_allocated_memory_size_current += PAGE_SIZE; + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + return; + } + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + + _kernel_page_release(item->physaddr); + _mali_osk_free( item ); +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf) +#else +static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + void __user * address; + address = vmf->virtual_address; +#endif + /* + * We always fail the call since all memory is pre-faulted when assigned to the process. + * Only the Mali cores can use page faults to extend buffers. + */ + + MALI_DEBUG_PRINT(1, ("Page-fault in Mali memory region caused by the CPU.\n")); + MALI_DEBUG_PRINT(1, ("Tried to access %p (process local virtual address) which is not currently mapped to any Mali memory.\n", (void*)address)); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + return VM_FAULT_SIGBUS; +#else + return NOPFN_SIGBUS; +#endif +} + +static void mali_kernel_memory_vma_open(struct vm_area_struct * vma) +{ + mali_vma_usage_tracker * vma_usage_tracker; + MALI_DEBUG_PRINT(4, ("Open called on vma %p\n", vma)); + + vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data; + vma_usage_tracker->references++; + + return; +} + +static void mali_kernel_memory_vma_close(struct vm_area_struct * vma) +{ + _mali_uk_mem_munmap_s args = {0, }; + mali_memory_allocation * descriptor; + mali_vma_usage_tracker * vma_usage_tracker; + MALI_DEBUG_PRINT(3, ("Close called on vma %p\n", vma)); + + vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data; + + BUG_ON(!vma_usage_tracker); + BUG_ON(0 == vma_usage_tracker->references); + + vma_usage_tracker->references--; + + if (0 != vma_usage_tracker->references) + { + MALI_DEBUG_PRINT(3, ("Ignoring this close, %d references still exists\n", vma_usage_tracker->references)); + return; + } + + /** @note args->context unused, initialized to 0. + * Instead, we use the memory_session from the cookie */ + + descriptor = (mali_memory_allocation *)vma_usage_tracker->cookie; + + args.cookie = (u32)descriptor; + args.mapping = descriptor->mapping; + args.size = descriptor->size; + + _mali_ukk_mem_munmap( &args ); + + /* vma_usage_tracker is free()d by _mali_osk_mem_mapregion_term(). + * In the case of the memory engine, it is called as the release function that has been registered with the engine*/ +} + + +void _mali_osk_mem_barrier( void ) +{ + mb(); +} + +void _mali_osk_write_mem_barrier( void ) +{ + wmb(); +} + +mali_io_address _mali_osk_mem_mapioregion( u32 phys, u32 size, const char *description ) +{ + return (mali_io_address)ioremap_nocache(phys, size); +} + +void _mali_osk_mem_unmapioregion( u32 phys, u32 size, mali_io_address virt ) +{ + iounmap((void*)virt); +} + +mali_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 size ) +{ + void * virt; + MALI_DEBUG_ASSERT_POINTER( phys ); + MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) ); + MALI_DEBUG_ASSERT( 0 != size ); + + /* dma_alloc_* uses a limited region of address space. On most arch/marchs + * 2 to 14 MiB is available. This should be enough for the page tables, which + * currently is the only user of this function. */ + virt = dma_alloc_coherent(NULL, size, phys, GFP_KERNEL | GFP_DMA ); + + MALI_DEBUG_PRINT(3, ("Page table virt: 0x%x = dma_alloc_coherent(size:%d, phys:0x%x, )\n", virt, size, phys)); + + if ( NULL == virt ) + { + MALI_DEBUG_PRINT(5, ("allocioregion: Failed to allocate Pagetable memory, size=0x%.8X\n", size )); + return 0; + } + + MALI_DEBUG_ASSERT( 0 == (*phys & ~_MALI_OSK_CPU_PAGE_MASK) ); + + return (mali_io_address)virt; +} + +void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address virt ) +{ + MALI_DEBUG_ASSERT_POINTER( (void*)virt ); + MALI_DEBUG_ASSERT( 0 != size ); + MALI_DEBUG_ASSERT( 0 == (phys & ( (1 << PAGE_SHIFT) - 1 )) ); + + dma_free_coherent(NULL, size, virt, phys); +} + +_mali_osk_errcode_t inline _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description ) +{ + return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK); +} + +void inline _mali_osk_mem_unreqregion( u32 phys, u32 size ) +{ + release_mem_region(phys, size); +} + +void inline _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val ) +{ + __raw_writel(cpu_to_le32(val),((u8*)addr) + offset); +} + +u32 inline _mali_osk_mem_ioread32( volatile mali_io_address addr, u32 offset ) +{ + return ioread32(((u8*)addr) + offset); +} + +void inline _mali_osk_mem_iowrite32( volatile mali_io_address addr, u32 offset, u32 val ) +{ + iowrite32(val, ((u8*)addr) + offset); +} + +void _mali_osk_cache_flushall( void ) +{ + /** @note Cached memory is not currently supported in this implementation */ +} + +void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size ) +{ + _mali_osk_write_mem_barrier(); +} + +_mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descriptor ) +{ + struct vm_area_struct *vma; + mali_vma_usage_tracker * vma_usage_tracker; + MappingInfo *mappingInfo; + + if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; + + MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); + + vma = (struct vm_area_struct*)descriptor->process_addr_mapping_info; + + if (NULL == vma ) return _MALI_OSK_ERR_FAULT; + + /* Re-write the process_addr_mapping_info */ + mappingInfo = _mali_osk_calloc( 1, sizeof(MappingInfo) ); + + if ( NULL == mappingInfo ) return _MALI_OSK_ERR_FAULT; + + vma_usage_tracker = _mali_osk_calloc( 1, sizeof(mali_vma_usage_tracker) ); + + if (NULL == vma_usage_tracker) + { + MALI_DEBUG_PRINT(2, ("Failed to allocate memory to track memory usage\n")); + _mali_osk_free( mappingInfo ); + return _MALI_OSK_ERR_FAULT; + } + + mappingInfo->vma = vma; + descriptor->process_addr_mapping_info = mappingInfo; + + /* Do the va range allocation - in this case, it was done earlier, so we copy in that information */ + descriptor->mapping = (void __user*)vma->vm_start; + /* list member is already NULL */ + + /* + set some bits which indicate that: + The memory is IO memory, meaning that no paging is to be performed and the memory should not be included in crash dumps + The memory is reserved, meaning that it's present and can never be paged out (see also previous entry) + */ + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED; + vma->vm_flags |= VM_DONTCOPY; + + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + vma->vm_ops = &mali_kernel_vm_ops; /* Operations used on any memory system */ + + vma_usage_tracker->references = 1; /* set initial reference count to be 1 as vma_open won't be called for the first mmap call */ + vma_usage_tracker->cookie = (u32)descriptor; /* cookie for munmap */ + + vma->vm_private_data = vma_usage_tracker; + + return _MALI_OSK_ERR_OK; +} + +void _mali_osk_mem_mapregion_term( mali_memory_allocation * descriptor ) +{ + struct vm_area_struct* vma; + mali_vma_usage_tracker * vma_usage_tracker; + MappingInfo *mappingInfo; + + if (NULL == descriptor) return; + + MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); + + mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; + + MALI_DEBUG_ASSERT_POINTER( mappingInfo ); + + /* Linux does the right thing as part of munmap to remove the mapping + * All that remains is that we remove the vma_usage_tracker setup in init() */ + vma = mappingInfo->vma; + + MALI_DEBUG_ASSERT_POINTER( vma ); + + /* ASSERT that there are no allocations on the list. Unmap should've been + * called on all OS allocations. */ + MALI_DEBUG_ASSERT( NULL == mappingInfo->list ); + + vma_usage_tracker = vma->vm_private_data; + + /* We only get called if mem_mapregion_init succeeded */ + _mali_osk_free(vma_usage_tracker); + + _mali_osk_free( mappingInfo ); + return; +} + +_mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size ) +{ + struct vm_area_struct *vma; + MappingInfo *mappingInfo; + + if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; + + MALI_DEBUG_ASSERT_POINTER( phys_addr ); + + MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); + + MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) ); + + MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK)); + + if (NULL == descriptor->mapping) return _MALI_OSK_ERR_INVALID_ARGS; + + if (size > (descriptor->size - offset)) + { + MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_map: virtual memory area not large enough to map physical 0x%x size %x into area 0x%x at offset 0x%xr\n", + *phys_addr, size, descriptor->mapping, offset)); + return _MALI_OSK_ERR_FAULT; + } + + mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; + + MALI_DEBUG_ASSERT_POINTER( mappingInfo ); + + vma = mappingInfo->vma; + + if (NULL == vma ) return _MALI_OSK_ERR_FAULT; + + MALI_DEBUG_PRINT(7, ("Process map: mapping 0x%08X to process address 0x%08lX length 0x%08X\n", *phys_addr, (long unsigned int)(descriptor->mapping + offset), size)); + + if ( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC == *phys_addr ) + { + _mali_osk_errcode_t ret; + AllocationList *alloc_item; + u32 linux_phys_frame_num; + + alloc_item = _allocation_list_item_get(); + if (NULL == alloc_item) + { + MALI_DEBUG_PRINT(1, ("Failed to allocate list item\n")); + return _MALI_OSK_ERR_NOMEM; + } + + linux_phys_frame_num = alloc_item->physaddr >> PAGE_SHIFT; + + ret = ( remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, linux_phys_frame_num, size, vma->vm_page_prot) ) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK; + + if ( ret != _MALI_OSK_ERR_OK) + { + MALI_PRINT_ERROR(("%s %d could not remap_pfn_range()\n", __FUNCTION__, __LINE__)); + _allocation_list_item_release(alloc_item); + return ret; + } + + /* Put our alloc_item into the list of allocations on success */ + if (NULL == mappingInfo->list) + { + mappingInfo->list = alloc_item; + } + else + { + mappingInfo->tail->next = alloc_item; + } + + mappingInfo->tail = alloc_item; + alloc_item->next = NULL; + alloc_item->offset = offset; + + /* Write out new physical address on success */ + *phys_addr = alloc_item->physaddr; + + return ret; + } + + /* Otherwise, Use the supplied physical address */ + + /* ASSERT that supplied phys_addr is page aligned */ + MALI_DEBUG_ASSERT( 0 == ((*phys_addr) & ~_MALI_OSK_CPU_PAGE_MASK) ); + + return ( remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, *phys_addr >> PAGE_SHIFT, size, vma->vm_page_prot) ) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK; + +} + +void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags ) +{ + MappingInfo *mappingInfo; + + if (NULL == descriptor) return; + + MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) ); + + MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) ); + + MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK) ); + + if (NULL == descriptor->mapping) return; + + if (size > (descriptor->size - offset)) + { + MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_unmap: virtual memory area not large enough to unmap size %x from area 0x%x at offset 0x%x\n", + size, descriptor->mapping, offset)); + return; + } + mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; + + MALI_DEBUG_ASSERT_POINTER( mappingInfo ); + + if ( 0 != (flags & _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR) ) + { + /* This physical RAM was allocated in _mali_osk_mem_mapregion_map and + * so needs to be unmapped + */ + while (size) + { + /* First find the allocation in the list of allocations */ + AllocationList *alloc = mappingInfo->list; + AllocationList **prev = &(mappingInfo->list); + + while (NULL != alloc && alloc->offset != offset) + { + prev = &(alloc->next); + alloc = alloc->next; + } + if (alloc == NULL) { + MALI_DEBUG_PRINT(1, ("Unmapping memory that isn't mapped\n")); + size -= _MALI_OSK_CPU_PAGE_SIZE; + offset += _MALI_OSK_CPU_PAGE_SIZE; + continue; + } + + *prev = alloc->next; + _allocation_list_item_release(alloc); + + /* Move onto the next allocation */ + size -= _MALI_OSK_CPU_PAGE_SIZE; + offset += _MALI_OSK_CPU_PAGE_SIZE; + } + } + + /* Linux does the right thing as part of munmap to remove the mapping */ + + return; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_mali.c b/drivers/media/video/samsung/mali/linux/mali_osk_mali.c new file mode 100644 index 0000000..06cb215 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_mali.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_mali.c + * Implementation of the OS abstraction layer which is specific for the Mali kernel device driver + */ +#include +#include +#include + +#include "mali_kernel_common.h" /* MALI_xxx macros */ +#include "mali_osk.h" /* kernel side OS functions */ +#include "mali_uk_types.h" +#include "arch/config.h" /* contains the configuration of the arch we are compiling for */ + +_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources ) +{ + *num_resources = sizeof(arch_configuration) / sizeof(arch_configuration[0]); + *arch_config = arch_configuration; + return _MALI_OSK_ERR_OK; +} + +void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources ) +{ + /* Nothing to do */ +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_math.c b/drivers/media/video/samsung/mali/linux/mali_osk_math.c new file mode 100644 index 0000000..bb25e7d --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_math.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_math.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include "mali_osk.h" +#include + +u32 inline _mali_osk_clz( u32 input ) +{ + return 32-fls(input); +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_memory.c b/drivers/media/video/samsung/mali/linux/mali_osk_memory.c new file mode 100644 index 0000000..5354e85 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_memory.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_memory.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include "mali_osk.h" +#include +#include + +void inline *_mali_osk_calloc( u32 n, u32 size ) +{ + return kcalloc(n, size, GFP_KERNEL); +} + +void inline *_mali_osk_malloc( u32 size ) +{ + return kmalloc(size, GFP_KERNEL); +} + +void inline _mali_osk_free( void *ptr ) +{ + kfree(ptr); +} + +void inline *_mali_osk_valloc( u32 size ) +{ + return vmalloc(size); +} + +void inline _mali_osk_vfree( void *ptr ) +{ + vfree(ptr); +} + +void inline *_mali_osk_memcpy( void *dst, const void *src, u32 len ) +{ + return memcpy(dst, src, len); +} + +void inline *_mali_osk_memset( void *s, u32 c, u32 n ) +{ + return memset(s, c, n); +} + +mali_bool _mali_osk_mem_check_allocated( u32 max_allocated ) +{ + /* No need to prevent an out-of-memory dialogue appearing on Linux, + * so we always return MALI_TRUE. + */ + return MALI_TRUE; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_misc.c b/drivers/media/video/samsung/mali/linux/mali_osk_misc.c new file mode 100644 index 0000000..ad486db --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_misc.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_misc.c + * Implementation of the OS abstraction layer for the kernel device driver + */ +#include +#include +#include +#include +#include +#include "mali_osk.h" + +void _mali_osk_dbgmsg( const char *fmt, ... ) +{ + va_list args; + va_start(args, fmt); + vprintk(fmt, args); + va_end(args); +} + +u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... ) +{ + int res; + va_list args; + va_start(args, fmt); + + res = vscnprintf(buf, (size_t)size, fmt, args); + + va_end(args); + return res; +} + +void _mali_osk_abort(void) +{ + /* make a simple fault by dereferencing a NULL pointer */ + dump_stack(); + *(int *)0 = 0; +} + +void _mali_osk_break(void) +{ + _mali_osk_abort(); +} + +u32 _mali_osk_get_pid(void) +{ + /* Thread group ID is the process ID on Linux */ + return (u32)current->tgid; +} + +u32 _mali_osk_get_tid(void) +{ + /* pid is actually identifying the thread on Linux */ + return (u32)current->pid; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c new file mode 100644 index 0000000..c14c0d5 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_notification.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include "mali_osk.h" +#include "mali_kernel_common.h" + +/* needed to detect kernel version specific code */ +#include + +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else /* pre 2.6.26 the file was in the arch specific location */ +#include +#endif + +/** + * Declaration of the notification queue object type + * Contains a linked list of notification pending delivery to user space. + * It also contains a wait queue of exclusive waiters blocked in the ioctl + * When a new notification is posted a single thread is resumed. + */ +struct _mali_osk_notification_queue_t_struct +{ + struct semaphore mutex; /**< Mutex protecting the list */ + wait_queue_head_t receive_queue; /**< Threads waiting for new entries to the queue */ + struct list_head head; /**< List of notifications waiting to be picked up */ +}; + +typedef struct _mali_osk_notification_wrapper_t_struct +{ + struct list_head list; /**< Internal linked list variable */ + _mali_osk_notification_t data; /**< Notification data */ +} _mali_osk_notification_wrapper_t; + +_mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void ) +{ + _mali_osk_notification_queue_t * result; + + result = (_mali_osk_notification_queue_t *)kmalloc(sizeof(_mali_osk_notification_queue_t), GFP_KERNEL); + if (NULL == result) return NULL; + + sema_init(&result->mutex, 1); + init_waitqueue_head(&result->receive_queue); + INIT_LIST_HEAD(&result->head); + + return result; +} + +_mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ) +{ + /* OPT Recycling of notification objects */ + _mali_osk_notification_wrapper_t *notification; + + notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size, + GFP_KERNEL | __GFP_HIGH | __GFP_REPEAT); + if (NULL == notification) + { + MALI_DEBUG_PRINT(1, ("Failed to create a notification object\n")); + return NULL; + } + + /* Init the list */ + INIT_LIST_HEAD(¬ification->list); + + if (0 != size) + { + notification->data.result_buffer = ((u8*)notification) + sizeof(_mali_osk_notification_wrapper_t); + } + else + { + notification->data.result_buffer = NULL; + } + + /* set up the non-allocating fields */ + notification->data.notification_type = type; + notification->data.result_buffer_size = size; + + /* all ok */ + return &(notification->data); +} + +void _mali_osk_notification_delete( _mali_osk_notification_t *object ) +{ + _mali_osk_notification_wrapper_t *notification; + MALI_DEBUG_ASSERT_POINTER( object ); + + notification = container_of( object, _mali_osk_notification_wrapper_t, data ); + + /* Free the container */ + kfree(notification); +} + +void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue ) +{ + MALI_DEBUG_ASSERT_POINTER( queue ); + + /* not much to do, just free the memory */ + kfree(queue); +} + +void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object ) +{ + _mali_osk_notification_wrapper_t *notification; + MALI_DEBUG_ASSERT_POINTER( queue ); + MALI_DEBUG_ASSERT_POINTER( object ); + + notification = container_of( object, _mali_osk_notification_wrapper_t, data ); + + /* lock queue access */ + down(&queue->mutex); + /* add to list */ + list_add_tail(¬ification->list, &queue->head); + /* unlock the queue */ + up(&queue->mutex); + + /* and wake up one possible exclusive waiter */ + wake_up(&queue->receive_queue); +} + +static int _mali_notification_queue_is_empty( _mali_osk_notification_queue_t *queue ) +{ + int ret; + + down(&queue->mutex); + ret = list_empty(&queue->head); + up(&queue->mutex); + return ret; +} + +#if MALI_STATE_TRACKING +mali_bool _mali_osk_notification_queue_is_empty( _mali_osk_notification_queue_t *queue ) +{ + return _mali_notification_queue_is_empty(queue) ? MALI_TRUE : MALI_FALSE; +} +#endif + +_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ) +{ + _mali_osk_errcode_t ret = _MALI_OSK_ERR_ITEM_NOT_FOUND; + _mali_osk_notification_wrapper_t *wrapper_object; + + down(&queue->mutex); + + if (!list_empty(&queue->head)) + { + wrapper_object = list_entry(queue->head.next, _mali_osk_notification_wrapper_t, list); + *result = &(wrapper_object->data); + list_del_init(&wrapper_object->list); + ret = _MALI_OSK_ERR_OK; + } + + up(&queue->mutex); + + return ret; +} + +_mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ) +{ + /* check input */ + MALI_DEBUG_ASSERT_POINTER( queue ); + MALI_DEBUG_ASSERT_POINTER( result ); + + /* default result */ + *result = NULL; + + while (_MALI_OSK_ERR_OK != _mali_osk_notification_queue_dequeue(queue, result)) + { + if (wait_event_interruptible(queue->receive_queue, !_mali_notification_queue_is_empty(queue))) + { + return _MALI_OSK_ERR_RESTARTSYSCALL; + } + } + + return _MALI_OSK_ERR_OK; /* all ok */ +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_pm.c b/drivers/media/video/samsung/mali/linux/mali_osk_pm.c new file mode 100644 index 0000000..491a603 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_pm.c @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_pm.c + * Implementation of the callback functions from common power management + */ + +#include + +#ifdef CONFIG_PM_RUNTIME +#include +#endif /* CONFIG_PM_RUNTIME */ +#include +#include "mali_platform.h" +#include "mali_osk.h" +#include "mali_uk_types.h" +#include "mali_kernel_common.h" +#include "mali_kernel_license.h" +#include "mali_linux_pm.h" +#include "mali_kernel_license.h" + +#if ! MALI_LICENSE_IS_GPL +#undef CONFIG_PM_RUNTIME +#endif + +extern struct platform_device mali_gpu_device; + +#ifdef CONFIG_PM_RUNTIME +static mali_bool have_runtime_reference = MALI_FALSE; +#endif + +void _mali_osk_pm_dev_enable(void) +{ +#ifdef CONFIG_PM_RUNTIME + pm_runtime_enable(&(mali_gpu_device.dev)); +#endif +} + +/* NB: Function is not thread safe */ +_mali_osk_errcode_t _mali_osk_pm_dev_idle(void) +{ +#ifdef CONFIG_PM_RUNTIME + if (MALI_TRUE == have_runtime_reference) + { + int err; + err = pm_runtime_put_sync(&(mali_gpu_device.dev)); + if (0 > err) + { + MALI_PRINT_ERROR(("OSK PM: pm_runtime_put_sync() returned error code %d\n", err)); + return _MALI_OSK_ERR_FAULT; + } + have_runtime_reference = MALI_FALSE; + } +#endif + return _MALI_OSK_ERR_OK; +} + +/* NB: Function is not thread safe */ +_mali_osk_errcode_t _mali_osk_pm_dev_activate(void) +{ +#ifdef CONFIG_PM_RUNTIME + if (MALI_TRUE != have_runtime_reference) + { + int err; + err = pm_runtime_get_sync(&(mali_gpu_device.dev)); + if (0 > err) + { + MALI_PRINT_ERROR(("OSK PM: pm_runtime_get_sync() returned error code %d\n", err)); + return _MALI_OSK_ERR_FAULT; + } + have_runtime_reference = MALI_TRUE; + } +#endif + return _MALI_OSK_ERR_OK; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c new file mode 100644 index 0000000..95bee53 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_ukk.h" +#include "mali_uk_types.h" +#include "mali_osk_profiling.h" +#include "mali_linux_trace.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_l2_cache.h" +#include "mali_user_settings_db.h" + +_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start) +{ + if (MALI_TRUE == auto_start) + { + mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); + } + + return _MALI_OSK_ERR_OK; +} + +void _mali_osk_profiling_term(void) +{ + /* Nothing to do */ +} + +_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_osk_profiling_stop(u32 *count) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +u32 _mali_osk_profiling_get_count(void) +{ + return 0; +} + +_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_osk_profiling_clear(void) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +mali_bool _mali_osk_profiling_is_recording(void) +{ + return MALI_FALSE; +} + +mali_bool _mali_osk_profiling_have_recording(void) +{ + return MALI_FALSE; +} + +void _mali_osk_profiling_report_sw_counters(u32 *counters) +{ + trace_mali_sw_counters(_mali_osk_get_pid(), _mali_osk_get_tid(), NULL, counters); +} + + +_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args) +{ + return _mali_osk_profiling_start(&args->limit); +} + +_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) +{ + /* Always add process and thread identificator in the first two data elements for events from user space */ + _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args) +{ + return _mali_osk_profiling_stop(&args->count); +} + +_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args) +{ + return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data); +} + +_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args) +{ + return _mali_osk_profiling_clear(); +} + +_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args) +{ + _mali_osk_profiling_report_sw_counters(args->counters); + return _MALI_OSK_ERR_OK; +} + +/** + * Called by gator.ko to set HW counters + * + * @param counter_id The counter ID. + * @param event_id Event ID that the counter should count (HW counter value from TRM). + * + * @return 1 on success, 0 on failure. + */ +int _mali_profiling_set_event(u32 counter_id, s32 event_id) +{ + + if (COUNTER_VP_C0 == counter_id) + { + struct mali_gp_core* gp_core = mali_gp_get_global_gp_core(); + if (NULL != gp_core) + { + if (MALI_TRUE == mali_gp_core_set_counter_src0(gp_core, event_id)) + { + return 1; + } + } + } + if (COUNTER_VP_C1 == counter_id) + { + struct mali_gp_core* gp_core = mali_gp_get_global_gp_core(); + if (NULL != gp_core) + { + if (MALI_TRUE == mali_gp_core_set_counter_src1(gp_core, event_id)) + { + return 1; + } + } + } + if (COUNTER_FP0_C0 <= counter_id && COUNTER_FP3_C1 >= counter_id) + { + u32 core_id = (counter_id - COUNTER_FP0_C0) >> 1; + struct mali_pp_core* pp_core = mali_pp_get_global_pp_core(core_id); + if (NULL != pp_core) + { + u32 counter_src = (counter_id - COUNTER_FP0_C0) & 1; + if (0 == counter_src) + { + if (MALI_TRUE == mali_pp_core_set_counter_src0(pp_core, event_id)) + { + return 1; + } + } + else + { + if (MALI_TRUE == mali_pp_core_set_counter_src1(pp_core, event_id)) + { + return 1; + } + } + } + } + if (COUNTER_L2_C0 <= counter_id && COUNTER_L2_C1 >= counter_id) + { + u32 core_id = (counter_id - COUNTER_L2_C0) >> 1; + struct mali_l2_cache_core* l2_cache_core = mali_l2_cache_core_get_glob_l2_core(core_id); + if (NULL != l2_cache_core) + { + u32 counter_src = (counter_id - COUNTER_L2_C0) & 1; + if (0 == counter_src) + { + if (MALI_TRUE == mali_l2_cache_core_set_counter_src0(l2_cache_core, event_id)) + { + return 1; + } + } + else + { + if (MALI_TRUE == mali_l2_cache_core_set_counter_src1(l2_cache_core, event_id)) + { + return 1; + } + } + } + } + + return 0; +} + +/** + * Called by gator.ko to retrieve the L2 cache counter values for the first L2 cache. + * The L2 cache counters are unique in that they are polled by gator, rather than being + * transmitted via the tracepoint mechanism. + * + * @param src0 First L2 cache counter ID. + * @param val0 First L2 cache counter value. + * @param src1 Second L2 cache counter ID. + * @param val1 Second L2 cache counter value. + */ +void _mali_profiling_get_counters(u32 *src0, u32 *val0, u32 *src1, u32 *val1) +{ + struct mali_l2_cache_core *l2_cache = mali_l2_cache_core_get_glob_l2_core(0); + if (NULL != l2_cache) + { + if (MALI_TRUE == mali_l2_cache_lock_power_state(l2_cache)) + { + /* It is now safe to access the L2 cache core in order to retrieve the counters */ + mali_l2_cache_core_get_counter_values(l2_cache, src0, val0, src1, val1); + } + mali_l2_cache_unlock_power_state(l2_cache); + } +} + +/* + * List of possible actions to be controlled by Streamline. + * The following numbers are used by gator to control the frame buffer dumping and s/w counter reporting. + * We cannot use the enums in mali_uk_types.h because they are unknown inside gator. + */ +#define FBDUMP_CONTROL_ENABLE (1) +#define FBDUMP_CONTROL_RATE (2) +#define SW_COUNTER_ENABLE (3) +#define FBDUMP_CONTROL_RESIZE_FACTOR (4) + +/** + * Called by gator to control the production of profiling information at runtime. + */ +void _mali_profiling_control(u32 action, u32 value) +{ + switch(action) + { + case FBDUMP_CONTROL_ENABLE: + mali_set_user_setting(_MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, (value == 0 ? MALI_FALSE : MALI_TRUE)); + break; + case FBDUMP_CONTROL_RATE: + mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, value); + break; + case SW_COUNTER_ENABLE: + mali_set_user_setting(_MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, value); + break; + case FBDUMP_CONTROL_RESIZE_FACTOR: + mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, value); + break; + default: + break; /* Ignore unimplemented actions */ + } +} + +EXPORT_SYMBOL(_mali_profiling_set_event); +EXPORT_SYMBOL(_mali_profiling_get_counters); +EXPORT_SYMBOL(_mali_profiling_control); diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c new file mode 100644 index 0000000..2df935d --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c @@ -0,0 +1,324 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_ukk.h" +#include "mali_timestamp.h" +#include "mali_osk_profiling.h" +#include "mali_user_settings_db.h" + +typedef struct mali_profiling_entry +{ + u64 timestamp; + u32 event_id; + u32 data[5]; +} mali_profiling_entry; + + +typedef enum mali_profiling_state +{ + MALI_PROFILING_STATE_UNINITIALIZED, + MALI_PROFILING_STATE_IDLE, + MALI_PROFILING_STATE_RUNNING, + MALI_PROFILING_STATE_RETURN, +} mali_profiling_state; + +static _mali_osk_lock_t *lock = NULL; +static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED; +static mali_profiling_entry* profile_entries = NULL; +static u32 profile_entry_count = 0; +static _mali_osk_atomic_t profile_insert_index; +static _mali_osk_atomic_t profile_entries_written; + +_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start) +{ + profile_entries = NULL; + profile_entry_count = 0; + _mali_osk_atomic_init(&profile_insert_index, 0); + _mali_osk_atomic_init(&profile_entries_written, 0); + + lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PROFILING); + if (NULL == lock) + { + return _MALI_OSK_ERR_FAULT; + } + + prof_state = MALI_PROFILING_STATE_IDLE; + + if (MALI_TRUE == auto_start) + { + u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* Use maximum buffer size */ + + mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit)) + { + return _MALI_OSK_ERR_FAULT; + } + } + + return _MALI_OSK_ERR_OK; +} + +void _mali_osk_profiling_term(void) +{ + prof_state = MALI_PROFILING_STATE_UNINITIALIZED; + + /* wait for all elements to be completely inserted into array */ + while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written)) + { + /* do nothing */; + } + + if (NULL != profile_entries) + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + if (NULL != lock) + { + _mali_osk_lock_term(lock); + lock = NULL; + } +} + +inline _mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit) +{ + _mali_osk_errcode_t ret; + + mali_profiling_entry *new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry)); + + if(NULL == new_profile_entries) + { + return _MALI_OSK_ERR_NOMEM; + } + + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (prof_state != MALI_PROFILING_STATE_IDLE) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_vfree(new_profile_entries); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + if (*limit > MALI_PROFILING_MAX_BUFFER_ENTRIES) + { + *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; + } + + profile_entries = new_profile_entries; + profile_entry_count = *limit; + + ret = _mali_timestamp_reset(); + + if (ret == _MALI_OSK_ERR_OK) + { + prof_state = MALI_PROFILING_STATE_RUNNING; + } + else + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return ret; +} + +inline void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4) +{ + if (prof_state == MALI_PROFILING_STATE_RUNNING) + { + u32 cur_index = (_mali_osk_atomic_inc_return(&profile_insert_index) - 1) % profile_entry_count; + + profile_entries[cur_index].timestamp = _mali_timestamp_get(); + profile_entries[cur_index].event_id = event_id; + profile_entries[cur_index].data[0] = data0; + profile_entries[cur_index].data[1] = data1; + profile_entries[cur_index].data[2] = data2; + profile_entries[cur_index].data[3] = data3; + profile_entries[cur_index].data[4] = data4; + + /* If event is "leave API function", add current memory usage to the event + * as data point 4. This is used in timeline profiling to indicate how + * much memory was used when leaving a function. */ + if (event_id == (MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC)) + { + profile_entries[cur_index].data[4] = _mali_ukk_report_memory_usage(); + } + + _mali_osk_atomic_inc(&profile_entries_written); + } +} + +inline void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value) +{ + /* Not implemented */ +} + +void _mali_osk_profiling_report_sw_counters(u32 *counters) +{ + /* Not implemented */ +} + +inline _mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count) +{ + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (prof_state != MALI_PROFILING_STATE_RUNNING) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + /* go into return state (user to retreive events), no more events will be added after this */ + prof_state = MALI_PROFILING_STATE_RETURN; + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + + /* wait for all elements to be completely inserted into array */ + while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written)) + { + /* do nothing */; + } + + *count = _mali_osk_atomic_read(&profile_insert_index); + if(*count>profile_entry_count) *count=profile_entry_count; + + return _MALI_OSK_ERR_OK; +} + +inline u32 _mali_osk_profiling_get_count(void) +{ + u32 retval = 0; + + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + if (prof_state == MALI_PROFILING_STATE_RETURN) + { + retval = _mali_osk_atomic_read(&profile_entries_written); + if(retval>profile_entry_count) retval = profile_entry_count; + } + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + + return retval; +} + +inline _mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) +{ + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if(index=profile_entry_count) + { + idx = (index + _mali_osk_atomic_read(&profile_insert_index)) % profile_entry_count; + } + + if (prof_state != MALI_PROFILING_STATE_RETURN) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + if (idx >= _mali_osk_atomic_read(&profile_entries_written)) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_FAULT; + } + + *timestamp = profile_entries[idx].timestamp; + *event_id = profile_entries[idx].event_id; + data[0] = profile_entries[idx].data[0]; + data[1] = profile_entries[idx].data[1]; + data[2] = profile_entries[idx].data[2]; + data[3] = profile_entries[idx].data[3]; + data[4] = profile_entries[idx].data[4]; + } + else + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_FAULT; + } + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_OK; +} + +inline _mali_osk_errcode_t _mali_osk_profiling_clear(void) +{ + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (prof_state != MALI_PROFILING_STATE_RETURN) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + prof_state = MALI_PROFILING_STATE_IDLE; + profile_entry_count = 0; + _mali_osk_atomic_init(&profile_insert_index, 0); + _mali_osk_atomic_init(&profile_entries_written, 0); + if (NULL != profile_entries) + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_OK; +} + +mali_bool _mali_osk_profiling_is_recording(void) +{ + return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE; +} + +mali_bool _mali_osk_profiling_have_recording(void) +{ + return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE; +} + +_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args) +{ + return _mali_osk_profiling_start(&args->limit); +} + +_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) +{ + /* Always add process and thread identificator in the first two data elements for events from user space */ + _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args) +{ + return _mali_osk_profiling_stop(&args->count); +} + +_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args) +{ + return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data); +} + +_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args) +{ + return _mali_osk_profiling_clear(); +} + +_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args) +{ + _mali_osk_profiling_report_sw_counters(args->counters); + return _MALI_OSK_ERR_OK; +} + diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_specific.h b/drivers/media/video/samsung/mali/linux/mali_osk_specific.h new file mode 100644 index 0000000..83ee906 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_specific.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_specific.h + * Defines per-OS Kernel level specifics, such as unusual workarounds for + * certain OSs. + */ + +#ifndef __MALI_OSK_SPECIFIC_H__ +#define __MALI_OSK_SPECIFIC_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MALI_STATIC_INLINE static inline +#define MALI_NON_STATIC_INLINE inline + +#ifdef __cplusplus +} +#endif + +/** The list of events supported by the Mali DDK. */ +typedef enum +{ + /* Vertex processor activity */ + ACTIVITY_VP = 0, + + /* Fragment processor activity */ + ACTIVITY_FP0, + ACTIVITY_FP1, + ACTIVITY_FP2, + ACTIVITY_FP3, + + /* L2 cache counters */ + COUNTER_L2_C0, + COUNTER_L2_C1, + + /* Vertex processor counters */ + COUNTER_VP_C0, + COUNTER_VP_C1, + + /* Fragment processor counters */ + COUNTER_FP0_C0, + COUNTER_FP0_C1, + COUNTER_FP1_C0, + COUNTER_FP1_C1, + COUNTER_FP2_C0, + COUNTER_FP2_C1, + COUNTER_FP3_C0, + COUNTER_FP3_C1, + + /* + * If more hardware counters are added, the _mali_osk_hw_counter_table + * below should also be updated. + */ + + /* EGL software counters */ + COUNTER_EGL_BLIT_TIME, + + /* GLES software counters */ + COUNTER_GLES_DRAW_ELEMENTS_CALLS, + COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, + COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_ARRAYS_CALLS, + COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_POINTS, + COUNTER_GLES_DRAW_LINES, + COUNTER_GLES_DRAW_LINE_LOOP, + COUNTER_GLES_DRAW_LINE_STRIP, + COUNTER_GLES_DRAW_TRIANGLES, + COUNTER_GLES_DRAW_TRIANGLE_STRIP, + COUNTER_GLES_DRAW_TRIANGLE_FAN, + COUNTER_GLES_NON_VBO_DATA_COPY_TIME, + COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, + COUNTER_GLES_UPLOAD_TEXTURE_TIME, + COUNTER_GLES_UPLOAD_VBO_TIME, + COUNTER_GLES_NUM_FLUSHES, + COUNTER_GLES_NUM_VSHADERS_GENERATED, + COUNTER_GLES_NUM_FSHADERS_GENERATED, + COUNTER_GLES_VSHADER_GEN_TIME, + COUNTER_GLES_FSHADER_GEN_TIME, + COUNTER_GLES_INPUT_TRIANGLES, + COUNTER_GLES_VXCACHE_HIT, + COUNTER_GLES_VXCACHE_MISS, + COUNTER_GLES_VXCACHE_COLLISION, + COUNTER_GLES_CULLED_TRIANGLES, + COUNTER_GLES_CULLED_LINES, + COUNTER_GLES_BACKFACE_TRIANGLES, + COUNTER_GLES_GBCLIP_TRIANGLES, + COUNTER_GLES_GBCLIP_LINES, + COUNTER_GLES_TRIANGLES_DRAWN, + COUNTER_GLES_DRAWCALL_TIME, + COUNTER_GLES_TRIANGLES_COUNT, + COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, + COUNTER_GLES_STRIP_TRIANGLES_COUNT, + COUNTER_GLES_FAN_TRIANGLES_COUNT, + COUNTER_GLES_LINES_COUNT, + COUNTER_GLES_INDEPENDENT_LINES_COUNT, + COUNTER_GLES_STRIP_LINES_COUNT, + COUNTER_GLES_LOOP_LINES_COUNT, + + /* Framebuffer capture pseudo-counter */ + COUNTER_FILMSTRIP, + + NUMBER_OF_EVENTS +} _mali_osk_counter_id; + +#define FIRST_ACTIVITY_EVENT ACTIVITY_VP +#define LAST_ACTIVITY_EVENT ACTIVITY_FP3 + +#define FIRST_HW_COUNTER COUNTER_L2_C0 +#define LAST_HW_COUNTER COUNTER_FP3_C1 + +#define FIRST_SW_COUNTER COUNTER_EGL_BLIT_TIME +#define LAST_SW_COUNTER COUNTER_GLES_LOOP_LINES_COUNT + +#define FIRST_SPECIAL_COUNTER COUNTER_FILMSTRIP +#define LAST_SPECIAL_COUNTER COUNTER_FILMSTRIP + +#endif /* __MALI_OSK_SPECIFIC_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_time.c b/drivers/media/video/samsung/mali/linux/mali_osk_time.c new file mode 100644 index 0000000..b399b87 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_time.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_time.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include "mali_osk.h" +#include +#include +#include + +int _mali_osk_time_after( u32 ticka, u32 tickb ) +{ + return time_after((unsigned long)ticka, (unsigned long)tickb); +} + +u32 _mali_osk_time_mstoticks( u32 ms ) +{ + return msecs_to_jiffies(ms); +} + +u32 _mali_osk_time_tickstoms( u32 ticks ) +{ + return jiffies_to_msecs(ticks); +} + +u32 _mali_osk_time_tickcount( void ) +{ + return jiffies; +} + +void _mali_osk_time_ubusydelay( u32 usecs ) +{ + udelay(usecs); +} + +u64 _mali_osk_time_get_ns( void ) +{ + struct timespec tsval; + getnstimeofday(&tsval); + return (u64)timespec_to_ns(&tsval); +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_timers.c b/drivers/media/video/samsung/mali/linux/mali_osk_timers.c new file mode 100644 index 0000000..e5829a3 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_timers.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_timers.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include +#include +#include "mali_osk.h" +#include "mali_kernel_common.h" + +struct _mali_osk_timer_t_struct +{ + struct timer_list timer; +}; + +typedef void (*timer_timeout_function_t)(unsigned long); + +_mali_osk_timer_t *_mali_osk_timer_init(void) +{ + _mali_osk_timer_t *t = (_mali_osk_timer_t*)kmalloc(sizeof(_mali_osk_timer_t), GFP_KERNEL); + if (NULL != t) init_timer(&t->timer); + return t; +} + +void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + tim->timer.expires = _mali_osk_time_tickcount() + ticks_to_expire; + add_timer(&(tim->timer)); +} + +void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + mod_timer(&(tim->timer), expiry_tick); +} + +void _mali_osk_timer_del( _mali_osk_timer_t *tim ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + del_timer_sync(&(tim->timer)); +} + +void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + tim->timer.data = (unsigned long)data; + tim->timer.function = (timer_timeout_function_t)callback; +} + +void _mali_osk_timer_term( _mali_osk_timer_t *tim ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + kfree(tim); +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c b/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c new file mode 100644 index 0000000..ce0561d --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_osk_wait_queue.c + * Implemenation of the OS abstraction layer for the kernel device driver + */ + +#include +#include +#include + +#include "mali_osk.h" +#include "mali_kernel_common.h" + +struct _mali_osk_wait_queue_t_struct +{ + wait_queue_head_t wait_queue; +}; + +_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void ) +{ + _mali_osk_wait_queue_t* ret = NULL; + + ret = kmalloc(sizeof(_mali_osk_wait_queue_t), GFP_KERNEL); + + if (NULL == ret) + { + return ret; + } + + init_waitqueue_head(&ret->wait_queue); + MALI_DEBUG_ASSERT(!waitqueue_active(&ret->wait_queue)); + + return ret; +} + +void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void) ) +{ + MALI_DEBUG_ASSERT_POINTER( queue ); + MALI_DEBUG_PRINT(6, ("Adding to wait queue %p\n", queue)); + wait_event(queue->wait_queue, condition()); +} + +void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue ) +{ + MALI_DEBUG_ASSERT_POINTER( queue ); + + /* if queue is empty, don't attempt to wake up its elements */ + if (!waitqueue_active(&queue->wait_queue)) return; + + MALI_DEBUG_PRINT(6, ("Waking up elements in wait queue %p ....\n", queue)); + + wake_up_all(&queue->wait_queue); + + MALI_DEBUG_PRINT(6, ("... elements in wait queue %p woken up\n", queue)); +} + +void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue ) +{ + /* Parameter validation */ + MALI_DEBUG_ASSERT_POINTER( queue ); + + /* Linux requires no explicit termination of wait queues */ + kfree(queue); +} diff --git a/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c b/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c new file mode 100644 index 0000000..f3b0a2c --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_pmu_power_up_down.c + */ + +#include +#include +#include +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_pmu.h" +#include "linux/mali/mali_utgard.h" + +/* Mali PMU power up/down APIs */ + +int mali_pmu_powerup(void) +{ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(5, ("Mali PMU: Power up\n")); + + if (NULL == pmu) + { + return -ENXIO; + } + + if (_MALI_OSK_ERR_OK != mali_pmu_powerup_all(pmu)) + { + return -EFAULT; + } + + return 0; +} + +EXPORT_SYMBOL(mali_pmu_powerup); + +int mali_pmu_powerdown(void) +{ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(5, ("Mali PMU: Power down\n")); + + if (NULL == pmu) + { + return -ENXIO; + } + + if (_MALI_OSK_ERR_OK != mali_pmu_powerdown_all(pmu)) + { + return -EFAULT; + } + + return 0; +} + +EXPORT_SYMBOL(mali_pmu_powerdown); diff --git a/drivers/media/video/samsung/mali/linux/mali_profiling_events.h b/drivers/media/video/samsung/mali/linux/mali_profiling_events.h new file mode 100644 index 0000000..2639a40 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_profiling_events.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_PROFILING_EVENTS_H__ +#define __MALI_PROFILING_EVENTS_H__ + +/* Simple wrapper in order to find the OS specific location of this file */ +#include + +#endif /* __MALI_PROFILING_EVENTS_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_uk_types.h b/drivers/media/video/samsung/mali/linux/mali_uk_types.h new file mode 100644 index 0000000..1a81246 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_uk_types.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_UK_TYPES_H__ +#define __MALI_UK_TYPES_H__ + +/* Simple wrapper in order to find the OS specific location of this file */ +//#include +#include "../include/linux/mali/mali_utgard_uk_types.h" + +#endif /* __MALI_UK_TYPES_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_core.c b/drivers/media/video/samsung/mali/linux/mali_ukk_core.c new file mode 100644 index 0000000..22262fe --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_ukk_core.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* memort allocation functions */ +#include /* user space access */ + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + +int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs) +{ + _mali_uk_get_api_version_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != get_user(kargs.version, &uargs->version)) return -EFAULT; + + kargs.ctx = session_data; + err = _mali_ukk_get_api_version(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT; + if (0 != put_user(kargs.compatible, &uargs->compatible)) return -EFAULT; + + return 0; +} + +int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs) +{ + _mali_uk_wait_for_notification_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_wait_for_notification(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if(_MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS != kargs.type) + { + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_wait_for_notification_s))) return -EFAULT; + } + else + { + if (0 != put_user(kargs.type, &uargs->type)) return -EFAULT; + } + + return 0; +} + +int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs) +{ + _mali_uk_post_notification_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + + if (0 != get_user(kargs.type, &uargs->type)) + { + return -EFAULT; + } + + err = _mali_ukk_post_notification(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + +int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs) +{ + _mali_uk_get_user_settings_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_get_user_settings(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_get_user_settings_s))) return -EFAULT; + + return 0; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c b/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c new file mode 100644 index 0000000..7070016 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + +int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs) +{ + _mali_uk_gp_start_job_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_gp_start_job_s))) + { + return -EFAULT; + } + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_start_job_s))) return -EFAULT; + + kargs.ctx = session_data; + err = _mali_ukk_gp_start_job(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_gp_start_job_s))) + { + /* + * If this happens, then user space will not know that the job was actually started, + * and if we return a queued job, then user space will still think that one is still queued. + * This will typically lead to a deadlock in user space. + * This could however only happen if user space deliberately passes a user buffer which + * passes the access_ok(VERIFY_WRITE) check, but isn't fully writable at the time of copy_to_user(). + * The official Mali driver will never attempt to do that, and kernel space should not be affected. + * That is why we do not bother to do a complex rollback in this very very very rare case. + */ + return -EFAULT; + } + + return 0; +} + +int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs) +{ + _mali_uk_get_gp_core_version_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_get_gp_core_version(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + /* no known transactions to roll-back */ + + if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT; + + return 0; +} + +int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs) +{ + _mali_uk_gp_suspend_response_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_suspend_response_s))) return -EFAULT; + + kargs.ctx = session_data; + err = _mali_ukk_gp_suspend_response(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if (0 != put_user(kargs.cookie, &uargs->cookie)) return -EFAULT; + + /* no known transactions to roll-back */ + return 0; +} + +int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs) +{ + _mali_uk_get_gp_number_of_cores_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_get_gp_number_of_cores(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + /* no known transactions to roll-back */ + + if (0 != put_user(kargs.number_of_cores, &uargs->number_of_cores)) return -EFAULT; + + return 0; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c b/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c new file mode 100644 index 0000000..260f257 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + +int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs) +{ + _mali_uk_init_mem_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_init_mem(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + if (0 != put_user(kargs.mali_address_base, &uargs->mali_address_base)) goto mem_init_rollback; + if (0 != put_user(kargs.memory_size, &uargs->memory_size)) goto mem_init_rollback; + + return 0; + +mem_init_rollback: + { + _mali_uk_term_mem_s kargs; + kargs.ctx = session_data; + err = _mali_ukk_term_mem(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_init_mem, as a result of failing put_user(), failed\n")); + } + } + return -EFAULT; +} + +int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs) +{ + _mali_uk_term_mem_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_term_mem(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + +int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument) +{ + _mali_uk_map_external_mem_s uk_args; + _mali_osk_errcode_t err_code; + + /* validate input */ + /* the session_data pointer was validated by caller */ + MALI_CHECK_NON_NULL( argument, -EINVAL); + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_map_external_mem_s)) ) + { + return -EFAULT; + } + + uk_args.ctx = session_data; + err_code = _mali_ukk_map_external_mem( &uk_args ); + + if (0 != put_user(uk_args.cookie, &argument->cookie)) + { + if (_MALI_OSK_ERR_OK == err_code) + { + /* Rollback */ + _mali_uk_unmap_external_mem_s uk_args_unmap; + + uk_args_unmap.ctx = session_data; + uk_args_unmap.cookie = uk_args.cookie; + err_code = _mali_ukk_unmap_external_mem( &uk_args_unmap ); + if (_MALI_OSK_ERR_OK != err_code) + { + MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_unmap_external_mem, as a result of failing put_user(), failed\n")); + } + } + return -EFAULT; + } + + /* Return the error that _mali_ukk_free_big_block produced */ + return map_errcode(err_code); +} + +int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument) +{ + _mali_uk_unmap_external_mem_s uk_args; + _mali_osk_errcode_t err_code; + + /* validate input */ + /* the session_data pointer was validated by caller */ + MALI_CHECK_NON_NULL( argument, -EINVAL); + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_unmap_external_mem_s)) ) + { + return -EFAULT; + } + + uk_args.ctx = session_data; + err_code = _mali_ukk_unmap_external_mem( &uk_args ); + + /* Return the error that _mali_ukk_free_big_block produced */ + return map_errcode(err_code); +} + +#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument) +{ + _mali_uk_release_ump_mem_s uk_args; + _mali_osk_errcode_t err_code; + + /* validate input */ + /* the session_data pointer was validated by caller */ + MALI_CHECK_NON_NULL( argument, -EINVAL); + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_release_ump_mem_s)) ) + { + return -EFAULT; + } + + uk_args.ctx = session_data; + err_code = _mali_ukk_release_ump_mem( &uk_args ); + + /* Return the error that _mali_ukk_free_big_block produced */ + return map_errcode(err_code); +} + +int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument) +{ + _mali_uk_attach_ump_mem_s uk_args; + _mali_osk_errcode_t err_code; + + /* validate input */ + /* the session_data pointer was validated by caller */ + MALI_CHECK_NON_NULL( argument, -EINVAL); + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_attach_ump_mem_s)) ) + { + return -EFAULT; + } + + uk_args.ctx = session_data; + err_code = _mali_ukk_attach_ump_mem( &uk_args ); + + if (0 != put_user(uk_args.cookie, &argument->cookie)) + { + if (_MALI_OSK_ERR_OK == err_code) + { + /* Rollback */ + _mali_uk_release_ump_mem_s uk_args_unmap; + + uk_args_unmap.ctx = session_data; + uk_args_unmap.cookie = uk_args.cookie; + err_code = _mali_ukk_release_ump_mem( &uk_args_unmap ); + if (_MALI_OSK_ERR_OK != err_code) + { + MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_attach_mem, as a result of failing put_user(), failed\n")); + } + } + return -EFAULT; + } + + /* Return the error that _mali_ukk_map_external_ump_mem produced */ + return map_errcode(err_code); +} +#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */ + +int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs) +{ + _mali_uk_query_mmu_page_table_dump_size_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + kargs.ctx = session_data; + + err = _mali_ukk_query_mmu_page_table_dump_size(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT; + + return 0; +} + +int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs) +{ + _mali_uk_dump_mmu_page_table_s kargs; + _mali_osk_errcode_t err; + void *buffer; + int rc = -EFAULT; + + /* validate input */ + MALI_CHECK_NON_NULL(uargs, -EINVAL); + /* the session_data pointer was validated by caller */ + + kargs.buffer = NULL; + + /* get location of user buffer */ + if (0 != get_user(buffer, &uargs->buffer)) goto err_exit; + /* get size of mmu page table info buffer from user space */ + if ( 0 != get_user(kargs.size, &uargs->size) ) goto err_exit; + /* verify we can access the whole of the user buffer */ + if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit; + + /* allocate temporary buffer (kernel side) to store mmu page table info */ + kargs.buffer = _mali_osk_valloc(kargs.size); + if (NULL == kargs.buffer) + { + rc = -ENOMEM; + goto err_exit; + } + + kargs.ctx = session_data; + err = _mali_ukk_dump_mmu_page_table(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + rc = map_errcode(err); + goto err_exit; + } + + /* copy mmu page table info back to user space and update pointers */ + if (0 != copy_to_user(uargs->buffer, kargs.buffer, kargs.size) ) goto err_exit; + if (0 != put_user((kargs.register_writes - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->register_writes)) goto err_exit; + if (0 != put_user((kargs.page_table_dump - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->page_table_dump)) goto err_exit; + if (0 != put_user(kargs.register_writes_size, &uargs->register_writes_size)) goto err_exit; + if (0 != put_user(kargs.page_table_dump_size, &uargs->page_table_dump_size)) goto err_exit; + rc = 0; + +err_exit: + if (kargs.buffer) _mali_osk_vfree(kargs.buffer); + return rc; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c b/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c new file mode 100644 index 0000000..c11c61b --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + +int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs) +{ + _mali_uk_pp_start_job_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_pp_start_job_s))) + { + return -EFAULT; + } + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_start_job_s))) return -EFAULT; + + kargs.ctx = session_data; + err = _mali_ukk_pp_start_job(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + return 0; +} + +int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs) +{ + _mali_uk_get_pp_number_of_cores_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_get_pp_number_of_cores(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if (0 != put_user(kargs.number_of_cores, &uargs->number_of_cores)) return -EFAULT; + + return 0; +} + +int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs) +{ + _mali_uk_get_pp_core_version_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_get_pp_core_version(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT; + + return 0; +} + +int pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs) +{ + _mali_uk_pp_disable_wb_s kargs; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_disable_wb_s))) return -EFAULT; + + kargs.ctx = session_data; + _mali_ukk_pp_job_disable_wb(&kargs); + + return 0; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c b/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c new file mode 100644 index 0000000..f4e31c9 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ +#include + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + +int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs) +{ + _mali_uk_profiling_start_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_start_s))) + { + return -EFAULT; + } + + kargs.ctx = session_data; + err = _mali_ukk_profiling_start(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + if (0 != put_user(kargs.limit, &uargs->limit)) + { + return -EFAULT; + } + + return 0; +} + +int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_add_event_s __user *uargs) +{ + _mali_uk_profiling_add_event_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_add_event_s))) + { + return -EFAULT; + } + + kargs.ctx = session_data; + err = _mali_ukk_profiling_add_event(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + +int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_stop_s __user *uargs) +{ + _mali_uk_profiling_stop_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_profiling_stop(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + if (0 != put_user(kargs.count, &uargs->count)) + { + return -EFAULT; + } + + return 0; +} + +int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs) +{ + _mali_uk_profiling_get_event_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != get_user(kargs.index, &uargs->index)) + { + return -EFAULT; + } + + kargs.ctx = session_data; + + err = _mali_ukk_profiling_get_event(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_profiling_get_event_s))) + { + return -EFAULT; + } + + return 0; +} + +int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs) +{ + _mali_uk_profiling_clear_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + kargs.ctx = session_data; + err = _mali_ukk_profiling_clear(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + +int profiling_report_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_report_s __user *uargs) +{ + _mali_uk_sw_counters_report_s kargs; + _mali_osk_errcode_t err; + u32 *counter_buffer; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_sw_counters_report_s))) + { + return -EFAULT; + } + + /* make sure that kargs.num_counters is [at least somewhat] sane */ + if (kargs.num_counters > 10000) { + MALI_DEBUG_PRINT(1, ("User space attempted to allocate too many counters.\n")); + return -EINVAL; + } + + counter_buffer = (u32*)kmalloc(sizeof(u32) * kargs.num_counters, GFP_KERNEL); + if (NULL == counter_buffer) + { + return -ENOMEM; + } + + if (0 != copy_from_user(counter_buffer, kargs.counters, sizeof(u32) * kargs.num_counters)) + { + kfree(counter_buffer); + return -EFAULT; + } + + kargs.ctx = session_data; + kargs.counters = counter_buffer; + + err = _mali_ukk_sw_counters_report(&kargs); + + kfree(counter_buffer); + + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + + diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c b/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c new file mode 100644 index 0000000..f9b5a3e --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_ukk_wrappers.h" + + +int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs) +{ + _mali_uk_vsync_event_report_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_vsync_event_report_s))) + { + return -EFAULT; + } + + kargs.ctx = session_data; + err = _mali_ukk_vsync_event_report(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h b/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h new file mode 100644 index 0000000..65857fd --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_ukk_wrappers.h + * Defines the wrapper functions for each user-kernel function + */ + +#ifndef __MALI_UKK_WRAPPERS_H__ +#define __MALI_UKK_WRAPPERS_H__ + +#include "mali_uk_types.h" +#include "mali_osk.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs); +int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs); +int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs); +int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs); +int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs); +int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs); +int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument); +int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument); +int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs); +int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs); + +#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument); +int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument); +#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */ + +int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs); +int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs); +int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs); +int pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs); +int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs); +int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs); +int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs); +int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs); + +int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs); +int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_add_event_s __user *uargs); +int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_stop_s __user *uargs); +int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs); +int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs); +int profiling_report_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_report_s __user *uargs); + +int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs); + + +int map_errcode( _mali_osk_errcode_t err ); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_UKK_WRAPPERS_H__ */ diff --git a/drivers/media/video/samsung/mali/platform/default/mali_platform.c b/drivers/media/video/samsung/mali/platform/default/mali_platform.c new file mode 100644 index 0000000..d966f25 --- /dev/null +++ b/drivers/media/video/samsung/mali/platform/default/mali_platform.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_platform.c + * Platform specific Mali driver functions for a default platform + */ +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_platform.h" + + +_mali_osk_errcode_t mali_platform_init(void) +{ + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_deinit(void) +{ + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) +{ + MALI_SUCCESS; +} + +void mali_gpu_utilization_handler(u32 utilization) +{ +} + +void set_mali_parent_power_domain(void* dev) +{ +} + + diff --git a/drivers/media/video/samsung/mali/platform/mali_platform.h b/drivers/media/video/samsung/mali/platform/mali_platform.h new file mode 100644 index 0000000..888f57a --- /dev/null +++ b/drivers/media/video/samsung/mali/platform/mali_platform.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_platform.h + * Platform specific Mali driver functions + */ + +#ifndef __MALI_PLATFORM_H__ +#define __MALI_PLATFORM_H__ + +#include "mali_osk.h" + +#ifdef CONFIG_CPU_EXYNOS4210 +#define MALI_DVFS_STEPS 3 +#else +#define MALI_DVFS_STEPS 5 +#endif + +/* @Enable or Disable Mali GPU Bottom Lock feature */ +#define MALI_GPU_BOTTOM_LOCK 1 + +#define MALI_VOLTAGE_LOCK 1 + +/* @Enable or Disable the CPU frequency lock when the GPU clock is 440 Mhz */ +#define CPUFREQ_LOCK_DURING_440 0 + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief description of power change reasons + */ +typedef enum mali_power_mode_tag +{ + MALI_POWER_MODE_ON, /**< Power Mali on */ + MALI_POWER_MODE_LIGHT_SLEEP, /**< Mali has been idle for a short time, or runtime PM suspend */ + MALI_POWER_MODE_DEEP_SLEEP, /**< Mali has been idle for a long time, or OS suspend */ +} mali_power_mode; + +/** @brief Platform specific setup and initialisation of MALI + * + * This is called from the entrypoint of the driver to initialize the platform + * + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_platform_init(void); + +/** @brief Platform specific deinitialisation of MALI + * + * This is called on the exit of the driver to terminate the platform + * + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_platform_deinit(void); + +/** @brief Platform specific powerdown sequence of MALI + * + * Notification from the Mali device driver stating the new desired power mode. + * MALI_POWER_MODE_ON must be obeyed, while the other modes are optional. + * @param power_mode defines the power modes + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode); + + +/** @brief Platform specific handling of GPU utilization data + * + * When GPU utilization data is enabled, this function will be + * periodically called. + * + * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization. + */ +void mali_gpu_utilization_handler(u32 utilization); + +/** @brief Setting the power domain of MALI + * + * This function sets the power domain of MALI if Linux run time power management is enabled + * + * @param dev Reference to struct platform_device (defined in linux) used by MALI GPU + */ +//void set_mali_parent_power_domain(void* dev); +void mali_utilization_suspend(void); + +#ifdef CONFIG_REGULATOR +int mali_regulator_get_usecount(void); +void mali_regulator_disable(void); +void mali_regulator_enable(void); +void mali_regulator_set_voltage(int min_uV, int max_uV); +#endif +mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz); +unsigned long mali_clk_get_rate(void); +void mali_clk_put(mali_bool binc_mali_clk); + +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +_mali_osk_errcode_t mali_platform_powerdown(u32 cores); +_mali_osk_errcode_t mali_platform_powerup(u32 cores); +#endif + + +#if USING_MALI_PMM +#if MALI_POWER_MGMT_TEST_SUITE +/** @brief function to get status of individual cores + * + * This function is used by power management test suite to get the status of powered up/down the number + * of cores + * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization. + */ +u32 pmu_get_power_up_down_info(void); +#endif +#endif + +#if MALI_DVFS_ENABLED +mali_bool init_mali_dvfs_status(int step); +void deinit_mali_dvfs_status(void); +mali_bool mali_dvfs_handler(u32 utilization); +int mali_dvfs_is_running(void); +void mali_dvfs_late_resume(void); +int get_mali_dvfs_control_status(void); +mali_bool set_mali_dvfs_current_step(unsigned int step); +void mali_default_step_set(int step, mali_bool boostup); +int change_dvfs_tableset(int change_clk, int change_step); +#ifdef CONFIG_CPU_EXYNOS4210 +#if MALI_GPU_BOTTOM_LOCK +int mali_dvfs_bottom_lock_push(void); +int mali_dvfs_bottom_lock_pop(void); +#endif +#else +int mali_dvfs_bottom_lock_push(int lock_step); +int mali_dvfs_bottom_lock_pop(void); +#endif +#endif + +int mali_dvfs_get_vol(int step); + +#if MALI_VOLTAGE_LOCK +int mali_voltage_lock_push(int lock_vol); +int mali_voltage_lock_pop(void); +int mali_voltage_lock_init(void); +int mali_vol_get_from_table(int vol); +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c b/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c new file mode 100644 index 0000000..cb95dc6 --- /dev/null +++ b/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_platform.c + * Platform specific Mali driver functions for a default platform + */ +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_platform.h" +#include "mali_pmu.h" +#include "linux/mali/mali_utgard.h" + +static u32 bPowerOff = 1; + +_mali_osk_errcode_t mali_platform_init(void) +{ + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_deinit(void) +{ + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) +{ + switch (power_mode) + { + case MALI_POWER_MODE_ON: + if (bPowerOff == 1) + { + mali_pmu_powerup(); + bPowerOff = 0; + } + break; + case MALI_POWER_MODE_LIGHT_SLEEP: + case MALI_POWER_MODE_DEEP_SLEEP: + + if (bPowerOff == 0) + { + mali_pmu_powerdown(); + bPowerOff = 1; + } + + break; + } + MALI_SUCCESS; +} + +void mali_gpu_utilization_handler(u32 utilization) +{ +} + +void set_mali_parent_power_domain(void* dev) +{ +} + + diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c new file mode 100644 index 0000000..119831d --- /dev/null +++ b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c @@ -0,0 +1,656 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_platform.c + * Platform specific Mali driver functions for a default platform + */ +#include +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_platform.h" +#include "mali_linux_pm.h" + +#if USING_MALI_PMM +#include "mali_pm.h" +#endif + +#include +#include +#include +#include +#include + +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +#include +#endif + +#if MALI_TIMELINE_PROFILING_ENABLED +#include "mali_kernel_profiling.h" +#endif + +#include +#include + +#define EXTXTALCLK_NAME "ext_xtal" +#define VPLLSRCCLK_NAME "vpll_src" +#define FOUTVPLLCLK_NAME "fout_vpll" +#define SCLVPLLCLK_NAME "sclk_vpll" +#define GPUMOUT1CLK_NAME "mout_g3d1" + +#define MPLLCLK_NAME "mout_mpll" +#define GPUMOUT0CLK_NAME "mout_g3d0" +#define GPUCLK_NAME "sclk_g3d" +#define CLK_DIV_STAT_G3D 0x1003C62C +#define CLK_DESC "clk-divider-status" + +static struct clk *ext_xtal_clock = 0; +static struct clk *vpll_src_clock = 0; +static struct clk *fout_vpll_clock = 0; +static struct clk *sclk_vpll_clock = 0; + +static struct clk *mpll_clock = 0; +static struct clk *mali_parent_clock = 0; +static struct clk *mali_clock = 0; + +int mali_gpu_clk = 160; +static unsigned int GPU_MHZ = 1000000; +#ifdef CONFIG_S5PV310_ASV +int mali_gpu_vol = 1100000; /* 1.10V for ASV */ +#else +int mali_gpu_vol = 1100000; /* 1.10V */ +#endif + +#if MALI_DVFS_ENABLED +#define MALI_DVFS_DEFAULT_STEP 0 // 134Mhz default +#endif + +int gpu_power_state; +static int bPoweroff; + +#ifdef CONFIG_REGULATOR +struct regulator { + struct device *dev; + struct list_head list; + int uA_load; + int min_uV; + int max_uV; + char *supply_name; + struct device_attribute dev_attr; + struct regulator_dev *rdev; +}; + +struct regulator *g3d_regulator=NULL; +#endif + +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) +extern struct platform_device s5pv310_device_pd[]; +#else +extern struct platform_device exynos4_device_pd[]; +#endif +#endif + +mali_io_address clk_register_map=0; + +#if MALI_GPU_BOTTOM_LOCK +_mali_osk_lock_t *mali_dvfs_lock; +#else +static _mali_osk_lock_t *mali_dvfs_lock; +#endif + +#ifdef CONFIG_REGULATOR +int mali_regulator_get_usecount(void) +{ + struct regulator_dev *rdev; + + if( IS_ERR_OR_NULL(g3d_regulator) ) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_get_usecount : g3d_regulator is null\n")); + return 0; + } + rdev = g3d_regulator->rdev; + return rdev->use_count; +} + +void mali_regulator_disable(void) +{ + bPoweroff = 1; + if( IS_ERR_OR_NULL(g3d_regulator) ) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n")); + return; + } + regulator_disable(g3d_regulator); + MALI_DEBUG_PRINT(1, ("regulator_disable -> use cnt: %d \n",mali_regulator_get_usecount())); +} + +void mali_regulator_enable(void) +{ + bPoweroff = 0; + if( IS_ERR_OR_NULL(g3d_regulator) ) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n")); + return; + } + regulator_enable(g3d_regulator); + MALI_DEBUG_PRINT(1, ("regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); +} + +void mali_regulator_set_voltage(int min_uV, int max_uV) +{ + int voltage; + + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + + if( IS_ERR_OR_NULL(g3d_regulator) ) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n")); + return; + } + MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS, + min_uV, max_uV, 0, 0, 0); +#endif + + regulator_set_voltage(g3d_regulator,min_uV,max_uV); + voltage = regulator_get_voltage(g3d_regulator); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS, + voltage, 0, 1, 0, 0); +#endif + mali_gpu_vol = voltage; + MALI_DEBUG_PRINT(1, ("= regulator_get_voltage: %d \n",mali_gpu_vol)); + + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); +} +#endif + +unsigned long mali_clk_get_rate(void) +{ + return clk_get_rate(mali_clock); +} + +mali_bool mali_clk_get(mali_bool bis_vpll) +{ + if (bis_vpll == MALI_TRUE) + { + if (ext_xtal_clock == NULL) + { + ext_xtal_clock = clk_get(NULL,EXTXTALCLK_NAME); + if (IS_ERR(ext_xtal_clock)) { + MALI_PRINT( ("MALI Error : failed to get source ext_xtal_clock\n")); + return MALI_FALSE; + } + } + + if (vpll_src_clock == NULL) + { + vpll_src_clock = clk_get(NULL,VPLLSRCCLK_NAME); + if (IS_ERR(vpll_src_clock)) { + MALI_PRINT( ("MALI Error : failed to get source vpll_src_clock\n")); + return MALI_FALSE; + } + } + + if (fout_vpll_clock == NULL) + { + fout_vpll_clock = clk_get(NULL,FOUTVPLLCLK_NAME); + if (IS_ERR(fout_vpll_clock)) { + MALI_PRINT( ("MALI Error : failed to get source fout_vpll_clock\n")); + return MALI_FALSE; + } + } + + if (sclk_vpll_clock == NULL) + { + sclk_vpll_clock = clk_get(NULL,SCLVPLLCLK_NAME); + if (IS_ERR(sclk_vpll_clock)) { + MALI_PRINT( ("MALI Error : failed to get source sclk_vpll_clock\n")); + return MALI_FALSE; + } + } + + if (mali_parent_clock == NULL) + { + mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME); + + if (IS_ERR(mali_parent_clock)) { + MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); + return MALI_FALSE; + } + } + } + else // mpll + { + if (mpll_clock == NULL) + { + mpll_clock = clk_get(NULL,MPLLCLK_NAME); + + if (IS_ERR(mpll_clock)) { + MALI_PRINT( ("MALI Error : failed to get source mpll clock\n")); + return MALI_FALSE; + } + } + + if (mali_parent_clock == NULL) + { + mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME); + + if (IS_ERR(mali_parent_clock)) { + MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); + return MALI_FALSE; + } + } + } + + // mali clock get always. + if (mali_clock == NULL) + { + mali_clock = clk_get(NULL, GPUCLK_NAME); + + if (IS_ERR(mali_clock)) { + MALI_PRINT( ("MALI Error : failed to get source mali clock\n")); + return MALI_FALSE; + } + } + + return MALI_TRUE; +} + +void mali_clk_put(mali_bool binc_mali_clock) +{ + if (mali_parent_clock) + { + clk_put(mali_parent_clock); + mali_parent_clock = 0; + } + + if (mpll_clock) + { + clk_put(mpll_clock); + mpll_clock = 0; + } + + if (sclk_vpll_clock) + { + clk_put(sclk_vpll_clock); + sclk_vpll_clock = 0; + } + + if (fout_vpll_clock) + { + clk_put(fout_vpll_clock); + fout_vpll_clock = 0; + } + + if (vpll_src_clock) + { + clk_put(vpll_src_clock); + vpll_src_clock = 0; + } + + if (ext_xtal_clock) + { + clk_put(ext_xtal_clock); + ext_xtal_clock = 0; + } + + if (binc_mali_clock == MALI_TRUE && mali_clock) + { + clk_put(mali_clock); + mali_clock = 0; + } + +} + + +mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz) +{ + unsigned long rate = 0; + mali_bool bis_vpll = MALI_FALSE; + +#ifdef CONFIG_VPLL_USE_FOR_TVENC + bis_vpll = MALI_TRUE; +#endif + + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + + if (mali_clk_get(bis_vpll) == MALI_FALSE) + return MALI_FALSE; + + rate = (unsigned long)clk * (unsigned long)mhz; + MALI_DEBUG_PRINT(3,("= clk_set_rate : %d , %d \n",clk, mhz )); + + if (bis_vpll) + { + clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ); + clk_set_parent(vpll_src_clock, ext_xtal_clock); + clk_set_parent(sclk_vpll_clock, fout_vpll_clock); + + clk_set_parent(mali_parent_clock, sclk_vpll_clock); + clk_set_parent(mali_clock, mali_parent_clock); + } + else + { + clk_set_parent(mali_parent_clock, mpll_clock); + clk_set_parent(mali_clock, mali_parent_clock); + } + + if (clk_enable(mali_clock) < 0) + return MALI_FALSE; + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ, + rate, 0, 0, 0, 0); +#endif + + clk_set_rate(mali_clock, rate); + rate = clk_get_rate(mali_clock); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ, + rate, 0, 0, 0, 0); +#endif + + if (bis_vpll) + mali_gpu_clk = (int)(rate / mhz); + else + mali_gpu_clk = (int)((rate + 500000) / mhz); + + GPU_MHZ = mhz; + MALI_DEBUG_PRINT(3,("= clk_get_rate: %d \n",mali_gpu_clk)); + + mali_clk_put(MALI_FALSE); + + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + + return MALI_TRUE; +} + +static mali_bool init_mali_clock(void) +{ + mali_bool ret = MALI_TRUE; + + gpu_power_state = 0; + + if (mali_clock != 0) + return ret; // already initialized + + mali_dvfs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE + | _MALI_OSK_LOCKFLAG_ONELOCK, 0, 0); + if (mali_dvfs_lock == NULL) + return _MALI_OSK_ERR_FAULT; + + if (mali_clk_set_rate(mali_gpu_clk, GPU_MHZ) == MALI_FALSE) + { + ret = MALI_FALSE; + goto err_clock_get; + } + + MALI_PRINT(("init_mali_clock mali_clock %p \n", mali_clock)); + + +#ifdef CONFIG_REGULATOR +#if USING_MALI_PMM + g3d_regulator = regulator_get(&mali_gpu_device.dev, "vdd_g3d"); +#else + g3d_regulator = regulator_get(NULL, "vdd_g3d"); +#endif + + if (IS_ERR(g3d_regulator)) + { + MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n")); + ret = MALI_FALSE; + goto err_regulator; + } + + regulator_enable(g3d_regulator); + MALI_DEBUG_PRINT(1, ("= regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); + mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol); +#endif + + MALI_DEBUG_PRINT(2, ("MALI Clock is set at mali driver\n")); + MALI_DEBUG_PRINT(3,("::clk_put:: %s mali_parent_clock - normal\n", __FUNCTION__)); + MALI_DEBUG_PRINT(3,("::clk_put:: %s mpll_clock - normal\n", __FUNCTION__)); + + mali_clk_put(MALI_FALSE); + + return MALI_TRUE; + + +#ifdef CONFIG_REGULATOR +err_regulator: + regulator_put(g3d_regulator); +#endif + +err_clock_get: + mali_clk_put(MALI_TRUE); + + return ret; +} + +static mali_bool deinit_mali_clock(void) +{ + if (mali_clock == 0) + return MALI_TRUE; + +#ifdef CONFIG_REGULATOR + if (g3d_regulator) + { + regulator_put(g3d_regulator); + g3d_regulator=NULL; + } +#endif + + mali_clk_put(MALI_TRUE); + + return MALI_TRUE; +} + + +static _mali_osk_errcode_t enable_mali_clocks(void) +{ + int err; + err = clk_enable(mali_clock); + MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err)); + + // set clock rate + mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); + + MALI_SUCCESS; +} + +static _mali_osk_errcode_t disable_mali_clocks(void) +{ + clk_disable(mali_clock); + MALI_DEBUG_PRINT(3,("disable_mali_clocks mali_clock %p \n", mali_clock)); + + MALI_SUCCESS; +} + +void set_mali_parent_power_domain(struct platform_device* dev) +{ +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) + dev->dev.parent = &s5pv310_device_pd[PD_G3D].dev; +#else + dev->dev.parent = &exynos4_device_pd[PD_G3D].dev; +#endif + +#endif +} + +_mali_osk_errcode_t g3d_power_domain_control(int bpower_on) +{ + if (bpower_on) + { +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON + MALI_DEBUG_PRINT(3,("_mali_osk_pm_dev_activate \n")); + _mali_osk_pm_dev_activate(); +#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON + void __iomem *status; + u32 timeout; + __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_PMU_G3D_CONF); + status = S5P_PMU_G3D_CONF + 0x4; + + timeout = 10; + while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) + != S5P_INT_LOCAL_PWR_EN) { + if (timeout == 0) { + MALI_PRINTF(("Power domain enable failed.\n")); + return -ETIMEDOUT; + } + timeout--; + _mali_osk_time_ubusydelay(100); + } +#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON + } + else + { +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON + MALI_DEBUG_PRINT( 4,("_mali_osk_pm_dev_idle\n")); + _mali_osk_pm_dev_idle(); + +#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON + void __iomem *status; + u32 timeout; + __raw_writel(0, S5P_PMU_G3D_CONF); + + status = S5P_PMU_G3D_CONF + 0x4; + /* Wait max 1ms */ + timeout = 10; + while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) + { + if (timeout == 0) { + MALI_PRINTF(("Power domain disable failed.\n" )); + return -ETIMEDOUT; + } + timeout--; + _mali_osk_time_ubusydelay( 100); + } +#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON + } + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_init() +{ + MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT); +#if MALI_DVFS_ENABLED + if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC ); + if(!init_mali_dvfs_status(MALI_DVFS_DEFAULT_STEP)) + MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n")); +#endif + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_deinit() +{ + deinit_mali_clock(); + +#if MALI_DVFS_ENABLED + deinit_mali_dvfs_status(); + if (clk_register_map ) + { + _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map); + clk_register_map=0; + } +#endif + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_powerdown(u32 cores) +{ + MALI_DEBUG_PRINT(3,("power down is called in mali_platform_powerdown state %x core %x \n", gpu_power_state, cores)); + + if (gpu_power_state != 0) // power down after state is 0 + { + gpu_power_state = gpu_power_state & (~cores); + if (gpu_power_state == 0) + { + MALI_DEBUG_PRINT( 3,("disable clock\n")); + disable_mali_clocks(); + } + } + else + { + MALI_PRINT(("mali_platform_powerdown gpu_power_state == 0 and cores %x \n", cores)); + } + + bPoweroff=1; + + + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_powerup(u32 cores) +{ + MALI_DEBUG_PRINT(3,("power up is called in mali_platform_powerup state %x core %x \n", gpu_power_state, cores)); + + if (gpu_power_state == 0) // power up only before state is 0 + { + gpu_power_state = gpu_power_state | cores; + + if (gpu_power_state != 0) + { + MALI_DEBUG_PRINT(4,("enable clock \n")); + enable_mali_clocks(); + } + } + else + { + gpu_power_state = gpu_power_state | cores; + } + + bPoweroff=0; + + + MALI_SUCCESS; +} + +void mali_gpu_utilization_handler(u32 utilization) +{ + if (bPoweroff==0) + { +#if MALI_DVFS_ENABLED + if(!mali_dvfs_handler(utilization)) + MALI_DEBUG_PRINT(1,( "error on mali dvfs status in utilization\n")); +#endif + } +} + +#if MALI_POWER_MGMT_TEST_SUITE +u32 pmu_get_power_up_down_info(void) +{ + return 4095; +} + +#endif +_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) +{ + MALI_SUCCESS; +} + diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c new file mode 100644 index 0000000..4efa759 --- /dev/null +++ b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c @@ -0,0 +1,448 @@ +/* * Copyright (C) 2010-2012 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_platform_dvfs.c + * Platform specific Mali driver dvfs functions + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_platform.h" + +#include +#include +#include +#include + +#include + +#ifdef CONFIG_CPU_FREQ +#include +#include +#define EXYNOS4_ASV_ENABLED +#endif + +#include "mali_device_pause_resume.h" +#include + +#define MALI_DVFS_WATING 10 // msec + +static int bMaliDvfsRun=0; + +#if MALI_GPU_BOTTOM_LOCK +static _mali_osk_atomic_t bottomlock_status; +#endif + +typedef struct mali_dvfs_tableTag{ + unsigned int clock; + unsigned int freq; + unsigned int vol; +}mali_dvfs_table; + +typedef struct mali_dvfs_statusTag{ + unsigned int currentStep; + mali_dvfs_table * pCurrentDvfs; + +}mali_dvfs_currentstatus; + +typedef struct mali_dvfs_thresholdTag{ + unsigned int downthreshold; + unsigned int upthreshold; +}mali_dvfs_threshold_table; + +typedef struct mali_dvfs_staycount{ + unsigned int staycount; +}mali_dvfs_staycount_table; + +mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={ + /*step 0*/{1}, + /*step 1*/{1}, + /*step 2*/{1} }; + +/*dvfs threshold*/ +mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={ + /*step 0*/{((int)((255*0)/100)) ,((int)((255*85)/100))}, + /*step 1*/{((int)((255*75)/100)) ,((int)((255*85)/100))}, + /*step 2*/{((int)((255*75)/100)) ,((int)((255*100)/100))} }; + +/*dvfs status*/ +mali_dvfs_currentstatus maliDvfsStatus; +int mali_dvfs_control=0; + +/*dvfs table*/ +mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ +#ifdef CONFIG_EXYNOS4210_1400MHZ_SUPPORT + /*step 0*/{134 ,1000000 , 950000}, +#else + /*step 0*/{100 ,1000000 , 950000}, +#endif + /*step 1*/{160 ,1000000 , 950000}, + /*step 2*/{267 ,1000000 ,1000000} }; + +#ifdef EXYNOS4_ASV_ENABLED + +#define ASV_8_LEVEL 8 +#define ASV_5_LEVEL 5 + +static unsigned int asv_3d_volt_5_table[ASV_5_LEVEL][MALI_DVFS_STEPS] = { + /* L3 (100/134MHz) L2(160MHz), L1(267MHz) */ + {1000000, 1000000, 1100000}, /* S */ + {1000000, 1000000, 1100000}, /* A */ + { 950000, 950000, 1000000}, /* B */ + { 950000, 950000, 1000000}, /* C */ + { 950000, 950000, 950000}, /* D */ +}; + +static unsigned int asv_3d_volt_8_table[ASV_8_LEVEL][MALI_DVFS_STEPS] = { + /* L3 (100/134MHz) L2(160MHz), L1(267MHz) */ + {1000000, 1000000, 1100000}, /* SS */ + {1000000, 1000000, 1100000}, /* A1 */ + {1000000, 1000000, 1100000}, /* A2 */ + { 950000, 950000, 1000000}, /* B1 */ + { 950000, 950000, 1000000}, /* B2 */ + { 950000, 950000, 1000000}, /* C1 */ + { 950000, 950000, 1000000}, /* C2 */ + { 950000, 950000, 950000}, /* D1 */ +}; +#endif + +static u32 mali_dvfs_utilization = 255; + +static void mali_dvfs_work_handler(struct work_struct *w); + +static struct workqueue_struct *mali_dvfs_wq = 0; +extern mali_io_address clk_register_map; + +#if MALI_GPU_BOTTOM_LOCK +extern _mali_osk_lock_t *mali_dvfs_lock; +#endif + +static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler); + +static unsigned int get_mali_dvfs_status(void) +{ + return maliDvfsStatus.currentStep; +} + +#if MALI_GPU_BOTTOM_LOCK +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +int get_mali_dvfs_control_status(void) +{ + return mali_dvfs_control; +} + +mali_bool set_mali_dvfs_current_step(unsigned int step) +{ + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + maliDvfsStatus.currentStep = step; + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + return MALI_TRUE; +} +#endif +#endif + +static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup) +{ + u32 validatedStep=step; + +#ifdef CONFIG_REGULATOR + if (mali_regulator_get_usecount()==0) { + MALI_DEBUG_PRINT(1, ("regulator use_count is 0 \n")); + return MALI_FALSE; + } +#endif + + if (boostup) { +#ifdef CONFIG_REGULATOR + /*change the voltage*/ + mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); +#endif + /*change the clock*/ + mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); + } else { + /*change the clock*/ + mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); +#ifdef CONFIG_REGULATOR + /*change the voltage*/ + mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); +#endif + } + + maliDvfsStatus.currentStep = validatedStep; + /*for future use*/ + maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep]; + + return MALI_TRUE; +} + +static void mali_platform_wating(u32 msec) +{ + /*sample wating + change this in the future with proper check routine. + */ + unsigned int read_val; + while(1) { + read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00); + if ((read_val & 0x8000)==0x0000) break; + + _mali_osk_time_ubusydelay(100); // 1000 -> 100 : 20101218 + } + /* _mali_osk_time_ubusydelay(msec*1000);*/ +} + +static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup ) +{ + + MALI_DEBUG_PRINT(1, ("> change_mali_dvfs_status: %d, %d \n",step, boostup)); + + if (!set_mali_dvfs_status(step, boostup)) { + MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup)); + return MALI_FALSE; + } + + /*wait until clock and voltage is stablized*/ + mali_platform_wating(MALI_DVFS_WATING); /*msec*/ + + return MALI_TRUE; +} + +static unsigned int decideNextStatus(unsigned int utilization) +{ + unsigned int level=0; // 0:stay, 1:up + + if (!mali_dvfs_control) { +#if MALI_GPU_BOTTOM_LOCK + if (_mali_osk_atomic_read(&bottomlock_status) > 0) + level = 1; /* or bigger */ + else +#endif + switch(maliDvfsStatus.currentStep) + { + case 0: + if( utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold) + level=1; + else + level = maliDvfsStatus.currentStep; + break; + case 1: + if( utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold) + level=2; + else if( utilization < + (mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold*mali_dvfs[maliDvfsStatus.currentStep-1].clock)/ + mali_dvfs[maliDvfsStatus.currentStep].clock) + level=0; + else + level = maliDvfsStatus.currentStep; + break; + case 2: + if( utilization < + (mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold*mali_dvfs[maliDvfsStatus.currentStep-1].clock)/ + mali_dvfs[maliDvfsStatus.currentStep].clock) + level=1; + else + level = maliDvfsStatus.currentStep; + break; + } + } + else + { + if((mali_dvfs_control == 1)||(( mali_dvfs_control > 3) && (mali_dvfs_control < mali_dvfs[0].clock+1))) + { + level=0; + } + else if((mali_dvfs_control == 2)||(( mali_dvfs_control > mali_dvfs[0].clock) && (mali_dvfs_control < mali_dvfs[1].clock+1))) + { + level=1; + } + else + { + level=2; + } + } + + return level; +} + +#ifdef EXYNOS4_ASV_ENABLED +static mali_bool mali_dvfs_table_update(void) +{ + unsigned int exynos_result_of_asv_group; + unsigned int target_asv; + unsigned int i; + exynos_result_of_asv_group = exynos_result_of_asv & 0xf; + target_asv = exynos_result_of_asv >> 28; + MALI_PRINT(("exynos_result_of_asv_group = 0x%x, target_asv = 0x%x\n", exynos_result_of_asv_group, target_asv)); + + if (target_asv == 0x8) { //SUPPORT_1400MHZ + for (i = 0; i < MALI_DVFS_STEPS; i++) { + mali_dvfs[i].vol = asv_3d_volt_5_table[exynos_result_of_asv_group][i]; + MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); + } + } else if (target_asv == 0x4){ //SUPPORT_1200MHZ + for (i = 0; i < MALI_DVFS_STEPS; i++) { + mali_dvfs[i].vol = asv_3d_volt_8_table[exynos_result_of_asv_group][i]; + MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); + } + } + + return MALI_TRUE; + +} +#endif + +static mali_bool mali_dvfs_status(u32 utilization) +{ + unsigned int nextStatus = 0; + unsigned int curStatus = 0; + mali_bool boostup = MALI_FALSE; +#ifdef EXYNOS4_ASV_ENABLED + static mali_bool asv_applied = MALI_FALSE; +#endif + static int stay_count = 0; // to prevent frequent switch + + MALI_DEBUG_PRINT(1, ("> mali_dvfs_status: %d \n",utilization)); +#ifdef EXYNOS4_ASV_ENABLED + if (asv_applied == MALI_FALSE) { + mali_dvfs_table_update(); + change_mali_dvfs_status(0,0); + asv_applied = MALI_TRUE; + + return MALI_TRUE; + } +#endif + + /*decide next step*/ + curStatus = get_mali_dvfs_status(); + nextStatus = decideNextStatus(utilization); + + MALI_DEBUG_PRINT(1, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep)); + + /*if next status is same with current status, don't change anything*/ + if ((curStatus!=nextStatus && stay_count==0)) { + /*check if boost up or not*/ + if (nextStatus > maliDvfsStatus.currentStep) + boostup = 1; + + /*change mali dvfs status*/ + if (!change_mali_dvfs_status(nextStatus,boostup)) { + MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n")); + return MALI_FALSE; + } + stay_count = mali_dvfs_staycount[maliDvfsStatus.currentStep].staycount; + } else { + if (stay_count>0) + stay_count--; + } + + return MALI_TRUE; +} + + + +int mali_dvfs_is_running(void) +{ + return bMaliDvfsRun; +} + + + +void mali_dvfs_late_resume(void) +{ + // set the init clock as low when resume + set_mali_dvfs_status(0,0); +} + + +static void mali_dvfs_work_handler(struct work_struct *w) +{ + bMaliDvfsRun=1; + + MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n")); + + if (!mali_dvfs_status(mali_dvfs_utilization)) + MALI_DEBUG_PRINT(1,( "error on mali dvfs status in mali_dvfs_work_handler")); + + bMaliDvfsRun=0; +} + + +mali_bool init_mali_dvfs_status(int step) +{ + /*default status + add here with the right function to get initilization value. + */ + if (!mali_dvfs_wq) + mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs"); + +#if MALI_GPU_BOTTOM_LOCK + _mali_osk_atomic_init(&bottomlock_status, 0); +#endif + + /*add a error handling here*/ + maliDvfsStatus.currentStep = step; + + return MALI_TRUE; +} + +void deinit_mali_dvfs_status(void) +{ +#if MALI_GPU_BOTTOM_LOCK + _mali_osk_atomic_term(&bottomlock_status); +#endif + + if (mali_dvfs_wq) + destroy_workqueue(mali_dvfs_wq); + mali_dvfs_wq = NULL; +} + +mali_bool mali_dvfs_handler(u32 utilization) +{ + mali_dvfs_utilization = utilization; + queue_work_on(0, mali_dvfs_wq,&mali_dvfs_work); + + /*add error handle here*/ + return MALI_TRUE; +} + +void mali_default_step_set(int step, mali_bool boostup) +{ + mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); + + if (maliDvfsStatus.currentStep == 1) + set_mali_dvfs_status(step, boostup); +} + +#if MALI_GPU_BOTTOM_LOCK +int mali_dvfs_bottom_lock_push(void) +{ + int prev_status = _mali_osk_atomic_read(&bottomlock_status); + + if (prev_status < 0) { + MALI_PRINT(("gpu bottom lock status is not valid for push")); + return -1; + } + + if (prev_status == 0) { + mali_regulator_set_voltage(mali_dvfs[1].vol, mali_dvfs[1].vol); + mali_clk_set_rate(mali_dvfs[1].clock, mali_dvfs[1].freq); + set_mali_dvfs_current_step(1); + } + + return _mali_osk_atomic_inc_return(&bottomlock_status); +} + +int mali_dvfs_bottom_lock_pop(void) +{ + if (_mali_osk_atomic_read(&bottomlock_status) <= 0) { + MALI_PRINT(("gpu bottom lock status is not valid for pop")); + return -1; + } + + return _mali_osk_atomic_dec_return(&bottomlock_status); +} +#endif diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c new file mode 100644 index 0000000..a08bc97 --- /dev/null +++ b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c @@ -0,0 +1,801 @@ +/* Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_platform.c + * Platform specific Mali driver functions for a default platform + */ +#include +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_platform.h" +#include "mali_linux_pm.h" + +#if USING_MALI_PMM +#include "mali_pm.h" +#endif + +#include +#include +#include +#include +#include + +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +#include +#endif + +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +#include "mali_osk_profiling.h" +unsigned long gFreq = 366; +int gVolt = 5000; +#endif + +#include +#include + +#define EXTXTALCLK_NAME "ext_xtal" +#define VPLLSRCCLK_NAME "vpll_src" +#define FOUTVPLLCLK_NAME "fout_vpll" +#define SCLVPLLCLK_NAME "sclk_vpll" +#define GPUMOUT1CLK_NAME "mout_g3d1" + +#define MPLLCLK_NAME "mout_mpll" +#define GPUMOUT0CLK_NAME "mout_g3d0" +#define GPUCLK_NAME "sclk_g3d" +#define CLK_DIV_STAT_G3D 0x1003C62C +#define CLK_DESC "clk-divider-status" + +#define MALI_BOTTOMLOCK_VOL 900000 + +typedef struct mali_runtime_resumeTag{ + int clk; + int vol; +}mali_runtime_resume_table; + +mali_runtime_resume_table mali_runtime_resume = {266, 900000}; + +/* lock/unlock CPU freq by Mali */ +extern int cpufreq_lock_by_mali(unsigned int freq); +extern void cpufreq_unlock_by_mali(void); + +/* start of modification by skkim */ +extern mali_bool init_mali_dvfs_status(int step); +extern void deinit_mali_dvfs_status(void); +extern mali_bool mali_dvfs_handler(u32 utilization); +extern int get_mali_dvfs_control_status(void); +extern mali_bool set_mali_dvfs_current_step(unsigned int step); +/* end of modification by skkim */ + +static struct clk *ext_xtal_clock = 0; +static struct clk *vpll_src_clock = 0; +static struct clk *fout_vpll_clock = 0; +static struct clk *sclk_vpll_clock = 0; + +static struct clk *mpll_clock = 0; +static struct clk *mali_parent_clock = 0; +static struct clk *mali_clock = 0; + + +static unsigned int GPU_MHZ = 1000000; + +int mali_gpu_clk = 266; +int mali_gpu_vol = 900000; + +#if MALI_DVFS_ENABLED +#define MALI_DVFS_DEFAULT_STEP 1 +#endif +#if MALI_VOLTAGE_LOCK +int mali_lock_vol = 0; +static _mali_osk_atomic_t voltage_lock_status; +static mali_bool mali_vol_lock_flag = 0; +#endif + +int gpu_power_state; +static int bPoweroff; + +#ifdef CONFIG_REGULATOR +struct regulator { + struct device *dev; + struct list_head list; + int uA_load; + int min_uV; + int max_uV; + char *supply_name; + struct device_attribute dev_attr; + struct regulator_dev *rdev; +}; + +struct regulator *g3d_regulator=NULL; +#endif + +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) +extern struct platform_device s5pv310_device_pd[]; +#else +extern struct platform_device exynos4_device_pd[]; +#endif +#endif + +mali_io_address clk_register_map=0; + +_mali_osk_lock_t *mali_dvfs_lock = 0; + +#ifdef CONFIG_REGULATOR +int mali_regulator_get_usecount(void) +{ + struct regulator_dev *rdev; + + if( IS_ERR_OR_NULL(g3d_regulator) ) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_get_usecount : g3d_regulator is null\n")); + return 0; + } + rdev = g3d_regulator->rdev; + return rdev->use_count; +} + +void mali_regulator_disable(void) +{ + if( IS_ERR_OR_NULL(g3d_regulator) ) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n")); + return; + } + regulator_disable(g3d_regulator); + MALI_DEBUG_PRINT(1, ("regulator_disable -> use cnt: %d \n",mali_regulator_get_usecount())); + bPoweroff = 1; +} + +void mali_regulator_enable(void) +{ + if( IS_ERR_OR_NULL(g3d_regulator) ) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n")); + return; + } + regulator_enable(g3d_regulator); + MALI_DEBUG_PRINT(1, ("regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); + bPoweroff = 0; +} + +void mali_regulator_set_voltage(int min_uV, int max_uV) +{ + int voltage; +#if !MALI_DVFS_ENABLED + min_uV = mali_gpu_vol; + max_uV = mali_gpu_vol; +#endif +#if MALI_VOLTAGE_LOCK + if (mali_vol_lock_flag == MALI_FALSE) { + if (min_uV < MALI_BOTTOMLOCK_VOL || max_uV < MALI_BOTTOMLOCK_VOL) { + min_uV = MALI_BOTTOMLOCK_VOL; + max_uV = MALI_BOTTOMLOCK_VOL; + } + } else if (_mali_osk_atomic_read(&voltage_lock_status) > 0 ) { + if (min_uV < mali_lock_vol || max_uV < mali_lock_vol) { +#if MALI_DVFS_ENABLED + int mali_vol_get; + mali_vol_get = mali_vol_get_from_table(mali_lock_vol); + if (mali_vol_get) { + min_uV = mali_vol_get; + max_uV = mali_vol_get; + } +#else + min_uV = mali_lock_vol; + max_uV = mali_lock_vol; +#endif + } + } +#endif + + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + + if( IS_ERR_OR_NULL(g3d_regulator) ) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n")); + return; + } + + MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); + + regulator_set_voltage(g3d_regulator,min_uV,max_uV); + voltage = regulator_get_voltage(g3d_regulator); + +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED + gVolt = voltage/1000; + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, gFreq, gVolt, + 0, 0, 0); +#endif + + mali_gpu_vol = voltage; + MALI_DEBUG_PRINT(1, ("= regulator_get_voltage: %d \n",mali_gpu_vol)); + + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); +} +#endif + +unsigned long mali_clk_get_rate(void) +{ + return clk_get_rate(mali_clock); +} + +mali_bool mali_clk_get(mali_bool bis_vpll) +{ + if (bis_vpll == MALI_TRUE) + { + if (ext_xtal_clock == NULL) + { + ext_xtal_clock = clk_get(NULL,EXTXTALCLK_NAME); + if (IS_ERR(ext_xtal_clock)) { + MALI_PRINT( ("MALI Error : failed to get source ext_xtal_clock\n")); + return MALI_FALSE; + } + } + + if (vpll_src_clock == NULL) + { + vpll_src_clock = clk_get(NULL,VPLLSRCCLK_NAME); + if (IS_ERR(vpll_src_clock)) { + MALI_PRINT( ("MALI Error : failed to get source vpll_src_clock\n")); + return MALI_FALSE; + } + } + + if (fout_vpll_clock == NULL) + { + fout_vpll_clock = clk_get(NULL,FOUTVPLLCLK_NAME); + if (IS_ERR(fout_vpll_clock)) { + MALI_PRINT( ("MALI Error : failed to get source fout_vpll_clock\n")); + return MALI_FALSE; + } + } + + if (sclk_vpll_clock == NULL) + { + sclk_vpll_clock = clk_get(NULL,SCLVPLLCLK_NAME); + if (IS_ERR(sclk_vpll_clock)) { + MALI_PRINT( ("MALI Error : failed to get source sclk_vpll_clock\n")); + return MALI_FALSE; + } + } + + if (mali_parent_clock == NULL) + { + mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME); + + if (IS_ERR(mali_parent_clock)) { + MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); + return MALI_FALSE; + } + } + } + else // mpll + { + if (mpll_clock == NULL) + { + mpll_clock = clk_get(NULL,MPLLCLK_NAME); + + if (IS_ERR(mpll_clock)) { + MALI_PRINT( ("MALI Error : failed to get source mpll clock\n")); + return MALI_FALSE; + } + } + + if (mali_parent_clock == NULL) + { + mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME); + + if (IS_ERR(mali_parent_clock)) { + MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); + return MALI_FALSE; + } + } + } + + // mali clock get always. + if (mali_clock == NULL) + { + mali_clock = clk_get(NULL, GPUCLK_NAME); + + if (IS_ERR(mali_clock)) { + MALI_PRINT( ("MALI Error : failed to get source mali clock\n")); + return MALI_FALSE; + } + } + + return MALI_TRUE; +} + +void mali_clk_put(mali_bool binc_mali_clock) +{ + if (mali_parent_clock) + { + clk_put(mali_parent_clock); + mali_parent_clock = 0; + } + + if (mpll_clock) + { + clk_put(mpll_clock); + mpll_clock = 0; + } + + if (sclk_vpll_clock) + { + clk_put(sclk_vpll_clock); + sclk_vpll_clock = 0; + } + + if (fout_vpll_clock) + { + clk_put(fout_vpll_clock); + fout_vpll_clock = 0; + } + + if (vpll_src_clock) + { + clk_put(vpll_src_clock); + vpll_src_clock = 0; + } + + if (ext_xtal_clock) + { + clk_put(ext_xtal_clock); + ext_xtal_clock = 0; + } + + if (binc_mali_clock == MALI_TRUE && mali_clock) + { + clk_put(mali_clock); + mali_clock = 0; + } + +} + + +mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz) +{ + unsigned long rate = 0; + mali_bool bis_vpll = MALI_TRUE; + +#ifndef CONFIG_VPLL_USE_FOR_TVENC + bis_vpll = MALI_TRUE; +#endif + +#if !MALI_DVFS_ENABLED + clk = mali_gpu_clk; +#endif + trace_printk("SPI_GPUFREQ_%uMHz\n", mali_gpu_clk); + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + + if (mali_clk_get(bis_vpll) == MALI_FALSE) + return MALI_FALSE; + + rate = (unsigned long)clk * (unsigned long)mhz; + MALI_DEBUG_PRINT(3,("= clk_set_rate : %d , %d \n",clk, mhz )); + + if (bis_vpll) + { + clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ); + clk_set_parent(vpll_src_clock, ext_xtal_clock); + clk_set_parent(sclk_vpll_clock, fout_vpll_clock); + + clk_set_parent(mali_parent_clock, sclk_vpll_clock); + clk_set_parent(mali_clock, mali_parent_clock); + } + else + { + clk_set_parent(mali_parent_clock, mpll_clock); + clk_set_parent(mali_clock, mali_parent_clock); + } + + if (clk_enable(mali_clock) < 0) + return MALI_FALSE; + + + clk_set_rate(mali_clock, rate); + rate = clk_get_rate(mali_clock); + +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED + gFreq = rate/1000000; + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, + gFreq, gVolt, 0, 0, 0); +#endif + + if (bis_vpll) + mali_gpu_clk = (int)(rate / mhz); + else + mali_gpu_clk = (int)((rate + 500000) / mhz); + + GPU_MHZ = mhz; + MALI_DEBUG_PRINT(3,("= clk_get_rate: %d \n",mali_gpu_clk)); + + mali_clk_put(MALI_FALSE); + + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + + return MALI_TRUE; +} + +static mali_bool init_mali_clock(void) +{ + mali_bool ret = MALI_TRUE; + + if (mali_clock != 0) + return ret; // already initialized + + mali_dvfs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE + | _MALI_OSK_LOCKFLAG_ONELOCK, 0, 0); + if (mali_dvfs_lock == NULL) + return _MALI_OSK_ERR_FAULT; + + if (mali_clk_set_rate(mali_gpu_clk, GPU_MHZ) == MALI_FALSE) + { + ret = MALI_FALSE; + goto err_clock_get; + } + + MALI_PRINT(("init_mali_clock mali_clock %p \n", mali_clock)); + + +#ifdef CONFIG_REGULATOR +#if USING_MALI_PMM + g3d_regulator = regulator_get(&mali_gpu_device.dev, "vdd_g3d"); +#else + g3d_regulator = regulator_get(NULL, "vdd_g3d"); +#endif + + if (IS_ERR(g3d_regulator)) + { + MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n")); + ret = MALI_FALSE; + goto err_regulator; + } + + regulator_enable(g3d_regulator); + + MALI_DEBUG_PRINT(1, ("= regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); + mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol); +#endif + + MALI_DEBUG_PRINT(2, ("MALI Clock is set at mali driver\n")); + + MALI_DEBUG_PRINT(3,("::clk_put:: %s mali_parent_clock - normal\n", __FUNCTION__)); + MALI_DEBUG_PRINT(3,("::clk_put:: %s mpll_clock - normal\n", __FUNCTION__)); + + mali_clk_put(MALI_FALSE); + + gpu_power_state=0; + bPoweroff=1; + + return MALI_TRUE; +#ifdef CONFIG_REGULATOR +err_regulator: + regulator_put(g3d_regulator); +#endif + +err_clock_get: + mali_clk_put(MALI_TRUE); + + return ret; +} + +static mali_bool deinit_mali_clock(void) +{ + if (mali_clock == 0) + return MALI_TRUE; + +#ifdef CONFIG_REGULATOR + if (g3d_regulator) + { + regulator_put(g3d_regulator); + g3d_regulator=NULL; + } +#endif + + mali_clk_put(MALI_TRUE); + + return MALI_TRUE; +} +static _mali_osk_errcode_t enable_mali_clocks(void) +{ + int err; + err = clk_enable(mali_clock); + MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err)); + + mali_runtime_resume.vol = mali_dvfs_get_vol(MALI_DVFS_DEFAULT_STEP); +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +#if MALI_DVFS_ENABLED + // set clock rate + if (get_mali_dvfs_control_status() != 0 || mali_gpu_clk >= mali_runtime_resume.clk) + mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); + else { + mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol); + mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ); + set_mali_dvfs_current_step(MALI_DVFS_DEFAULT_STEP); + } +#if CPUFREQ_LOCK_DURING_440 + /* lock/unlock CPU freq by Mali */ + if (mali_gpu_clk >= 440) + err = cpufreq_lock_by_mali(1200); +#endif +#else + mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol); + mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ); +#endif +#else + mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); +#endif + MALI_SUCCESS; +} + +static _mali_osk_errcode_t disable_mali_clocks(void) +{ + clk_disable(mali_clock); + MALI_DEBUG_PRINT(3,("disable_mali_clocks mali_clock %p \n", mali_clock)); + +#if MALI_DVFS_ENABLED && CPUFREQ_LOCK_DURING_440 + /* lock/unlock CPU freq by Mali */ + cpufreq_unlock_by_mali(); +#endif + MALI_SUCCESS; +} + +void set_mali_parent_power_domain(struct platform_device* dev) +{ +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) + dev->dev.parent = &s5pv310_device_pd[PD_G3D].dev; +#else + dev->dev.parent = &exynos4_device_pd[PD_G3D].dev; +#endif +#endif +} + +_mali_osk_errcode_t g3d_power_domain_control(int bpower_on) +{ + if (bpower_on) + { +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON + MALI_DEBUG_PRINT(3,("_mali_osk_pmm_dev_activate \n")); + _mali_osk_pm_dev_activate(); +#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON + void __iomem *status; + u32 timeout; + __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_PMU_G3D_CONF); + status = S5P_PMU_G3D_CONF + 0x4; + + timeout = 10; + while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) + != S5P_INT_LOCAL_PWR_EN) { + if (timeout == 0) { + MALI_PRINTF(("Power domain enable failed.\n")); + return -ETIMEDOUT; + } + timeout--; + _mali_osk_time_ubusydelay(100); + } +#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON + } + else + { +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON + MALI_DEBUG_PRINT( 4,("_mali_osk_pmm_dev_idle\n")); + _mali_osk_pm_dev_idle(); +#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON + void __iomem *status; + u32 timeout; + __raw_writel(0, S5P_PMU_G3D_CONF); + + status = S5P_PMU_G3D_CONF + 0x4; + /* Wait max 1ms */ + timeout = 10; + while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) + { + if (timeout == 0) { + MALI_PRINTF(("Power domain disable failed.\n" )); + return -ETIMEDOUT; + } + timeout--; + _mali_osk_time_ubusydelay( 100); + } +#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON + } + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_init() +{ + MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT); +#if MALI_VOLTAGE_LOCK + _mali_osk_atomic_init(&voltage_lock_status, 0); +#endif +#if MALI_DVFS_ENABLED + if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC ); + if(!init_mali_dvfs_status(MALI_DVFS_DEFAULT_STEP)) + MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n")); +#endif + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_deinit() +{ + deinit_mali_clock(); +#if MALI_VOLTAGE_LOCK + _mali_osk_atomic_term(&voltage_lock_status); +#endif +#if MALI_DVFS_ENABLED + deinit_mali_dvfs_status(); + if (clk_register_map ) + { + _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map); + clk_register_map=0; + } +#endif + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_powerdown(u32 cores) +{ + trace_printk("SPI_GPU_PWR Idle\n"); + MALI_DEBUG_PRINT(3,("power down is called in mali_platform_powerdown state %x core %x \n", gpu_power_state, cores)); + + if (gpu_power_state != 0) // power down after state is 0 + { + gpu_power_state = gpu_power_state & (~cores); + if (gpu_power_state == 0) + { + MALI_DEBUG_PRINT( 3,("disable clock\n")); + disable_mali_clocks(); + } + } + else + { + MALI_PRINT(("mali_platform_powerdown gpu_power_state == 0 and cores %x \n", cores)); + } + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_powerup(u32 cores) +{ + trace_printk("SPI_GPU_PWR Start\n"); + MALI_DEBUG_PRINT(3,("power up is called in mali_platform_powerup state %x core %x \n", gpu_power_state, cores)); + + if (gpu_power_state == 0) // power up only before state is 0 + { + gpu_power_state = gpu_power_state | cores; + + if (gpu_power_state != 0) + { + MALI_DEBUG_PRINT(4,("enable clock \n")); + enable_mali_clocks(); + } + } + else + { + gpu_power_state = gpu_power_state | cores; + } + + MALI_SUCCESS; +} + +void mali_gpu_utilization_handler(u32 utilization) +{ + if (bPoweroff==0) + { +#if MALI_DVFS_ENABLED + if(!mali_dvfs_handler(utilization)) + MALI_DEBUG_PRINT(1,( "error on mali dvfs status in utilization\n")); +#endif + } +} + +#if MALI_POWER_MGMT_TEST_SUITE +u32 pmu_get_power_up_down_info(void) +{ + return 4095; +} + +#endif + +_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) +{ + switch (power_mode) + { + case MALI_POWER_MODE_ON: + MALI_DEBUG_PRINT(1, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n", bPoweroff ? "powering on" : "already on")); + if (bPoweroff == 1) + { + /** If run time power management is used, donot call this function */ +#ifndef CONFIG_PM_RUNTIME + g3d_power_domain_control(1); +#endif + + MALI_DEBUG_PRINT(4,("enable clock \n")); + enable_mali_clocks(); +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| MALI_PROFILING_EVENT_CHANNEL_GPU|MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); +#endif + //MALI_PRINTF(("Mali Platform powered up")); + gpu_power_state=1; + bPoweroff=0; + } + break; + case MALI_POWER_MODE_LIGHT_SLEEP: + case MALI_POWER_MODE_DEEP_SLEEP: + MALI_DEBUG_PRINT(1, ("Mali platform: Got %s event, %s\n", + power_mode == MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" : "MALI_POWER_MODE_DEEP_SLEEP", + bPoweroff ? "already off" : "powering off")); + if (bPoweroff == 0) + { + disable_mali_clocks(); +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| MALI_PROFILING_EVENT_CHANNEL_GPU|MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0); +#endif + +#ifndef CONFIG_PM_RUNTIME + g3d_power_domain_control(0); +#endif + + //MALI_PRINTF(("Mali Platform powered down")); + gpu_power_state=0; + bPoweroff=1; + } + + break; + } + MALI_SUCCESS; +} + +#if MALI_VOLTAGE_LOCK +int mali_voltage_lock_push(int lock_vol) +{ + int prev_status = _mali_osk_atomic_read(&voltage_lock_status); + + if (prev_status < 0) { + MALI_PRINT(("gpu voltage lock status is not valid for push\n")); + return -1; + } + if (prev_status == 0) { + mali_lock_vol = lock_vol; + if (mali_gpu_vol < mali_lock_vol) + mali_regulator_set_voltage(mali_lock_vol, mali_lock_vol); + } else { + MALI_PRINT(("gpu voltage lock status is already pushed, current lock voltage : %d\n", mali_lock_vol)); + return -1; + } + + return _mali_osk_atomic_inc_return(&voltage_lock_status); +} + +int mali_voltage_lock_pop(void) +{ + if (_mali_osk_atomic_read(&voltage_lock_status) <= 0) { + MALI_PRINT(("gpu voltage lock status is not valid for pop\n")); + return -1; + } + return _mali_osk_atomic_dec_return(&voltage_lock_status); +} + +int mali_voltage_lock_init(void) +{ + mali_vol_lock_flag = MALI_TRUE; + + MALI_SUCCESS; +} +#endif diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c new file mode 100644 index 0000000..cc1164e --- /dev/null +++ b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c @@ -0,0 +1,847 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_platform_dvfs.c + * Platform specific Mali driver dvfs functions + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_platform.h" + +#include +#include +#include +#include + +#include + +#include "mali_device_pause_resume.h" +#include + +#define MAX_MALI_DVFS_STEPS 5 +#define MALI_DVFS_WATING 10 // msec + +#ifdef CONFIG_CPU_FREQ +#include +#define EXYNOS4_ASV_ENABLED +#endif + +#include + +static int bMaliDvfsRun=0; + +static _mali_osk_atomic_t bottomlock_status; +int bottom_lock_step = 0; + +typedef struct mali_dvfs_tableTag{ + unsigned int clock; + unsigned int freq; + unsigned int vol; +}mali_dvfs_table; + +typedef struct mali_dvfs_statusTag{ + unsigned int currentStep; + mali_dvfs_table * pCurrentDvfs; + +}mali_dvfs_currentstatus; + +typedef struct mali_dvfs_thresholdTag{ + unsigned int downthreshold; + unsigned int upthreshold; +}mali_dvfs_threshold_table; + +typedef struct mali_dvfs_staycount{ + unsigned int staycount; +}mali_dvfs_staycount_table; + +typedef struct mali_dvfs_stepTag{ + int clk; + int vol; +}mali_dvfs_step; + +mali_dvfs_step step[MALI_DVFS_STEPS]={ + /*step 0 clk*/ {160, 875000}, +#if (MALI_DVFS_STEPS > 1) + /*step 1 clk*/ {266, 900000}, +#if (MALI_DVFS_STEPS > 2) + /*step 2 clk*/ {350, 950000}, +#if (MALI_DVFS_STEPS > 3) + /*step 3 clk*/ {440, 1025000}, +#if (MALI_DVFS_STEPS > 4) + /*step 4 clk*/ {533, 1075000} +#endif +#endif +#endif +#endif +}; + +mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={ + /*step 0*/{0}, +#if (MALI_DVFS_STEPS > 1) + /*step 1*/{0}, +#if (MALI_DVFS_STEPS > 2) + /*step 2*/{0}, +#if (MALI_DVFS_STEPS > 3) + /*step 3*/{0}, +#if (MALI_DVFS_STEPS > 4) + /*step 4*/{0} +#endif +#endif +#endif +#endif +}; + +/* dvfs information */ +// L0 = 533Mhz, 1.075V +// L1 = 440Mhz, 1.025V +// L2 = 350Mhz, 0.95V +// L3 = 266Mhz, 0.90V +// L4 = 160Mhz, 0.875V + +int step0_clk = 160; +int step0_vol = 875000; +#if (MALI_DVFS_STEPS > 1) +int step1_clk = 266; +int step1_vol = 900000; +int step0_up = 70; +int step1_down = 62; +#if (MALI_DVFS_STEPS > 2) +int step2_clk = 350; +int step2_vol = 950000; +int step1_up = 90; +int step2_down = 85; +#if (MALI_DVFS_STEPS > 3) +int step3_clk = 440; +int step3_vol = 1025000; +int step2_up = 90; +int step3_down = 85; +#if (MALI_DVFS_STEPS > 4) +int step4_clk = 533; +int step4_vol = 1075000; +int step3_up = 90; +int step4_down = 95; +#endif +#endif +#endif +#endif + +mali_dvfs_table mali_dvfs_all[MAX_MALI_DVFS_STEPS]={ + {160 ,1000000 , 875000}, + {266 ,1000000 , 900000}, + {350 ,1000000 , 950000}, + {440 ,1000000 , 1025000}, + {533 ,1000000 , 1075000} }; + +mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ + {160 ,1000000 , 875000}, +#if (MALI_DVFS_STEPS > 1) + {266 ,1000000 , 900000}, +#if (MALI_DVFS_STEPS > 2) + {350 ,1000000 , 950000}, +#if (MALI_DVFS_STEPS > 3) + {440 ,1000000 ,1025000}, +#if (MALI_DVFS_STEPS > 4) + {533 ,1000000 ,1075000} +#endif +#endif +#endif +#endif +}; + +mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={ + {0 , 70}, +#if (MALI_DVFS_STEPS > 1) + {62 , 90}, +#if (MALI_DVFS_STEPS > 2) + {85 , 90}, +#if (MALI_DVFS_STEPS > 3) + {85 ,90}, +#if (MALI_DVFS_STEPS > 4) + {95 ,100} +#endif +#endif +#endif +#endif +}; + +#ifdef EXYNOS4_ASV_ENABLED +#define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */ +#define ASV_LEVEL_PRIME 13 /* ASV0, 1, 12 is reserved */ + +static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = { + { 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000, 900000, 900000, 900000, 875000}, /* L3(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 1000000, 975000, 975000, 975000, 950000, 950000, 950000, 900000, 900000, 900000, 900000, 875000}, /* L2(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1075000, 1050000, 1050000, 1050000, 1000000, 1000000, 1000000, 975000, 975000, 975000, 975000, 925000}, /* L1(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1125000, 1100000, 1100000, 1100000, 1075000, 1075000, 1075000, 1025000, 1025000, 1025000, 1025000, 975000}, /* L0(440Mhz) */ +#endif +#endif +#endif +}; + +static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS-1][ASV_LEVEL] = { + { 950000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 975000, 950000, 925000, 925000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000}, /* L2(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1050000, 1025000, 1000000, 1000000, 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000}, /* L1(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1100000, 1075000, 1050000, 1050000, 1050000, 1025000, 1025000, 1000000, 1000000, 1000000, 975000, 950000}, /* L0(440Mhz) */ +#endif +#endif +#endif +}; + +static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL_PRIME] = { + { 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 875000, 862500, 850000, 850000}, /* L4(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 900000, 887500, 875000, 862500}, /* L3(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 925000, 912500}, /* L2(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000}, /* L1(440Mhz) */ +#if (MALI_DVFS_STEPS > 4) + { 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1087500, 1075000, 1062500, 1050000}, /* L0(600Mhz) */ +#endif +#endif +#endif +#endif +}; +#endif /* ASV_LEVEL */ + +/*dvfs status*/ +mali_dvfs_currentstatus maliDvfsStatus; +int mali_dvfs_control=0; + +static u32 mali_dvfs_utilization = 255; + +static void mali_dvfs_work_handler(struct work_struct *w); + +static struct workqueue_struct *mali_dvfs_wq = 0; +extern mali_io_address clk_register_map; +extern _mali_osk_lock_t *mali_dvfs_lock; + +int mali_runtime_resumed = -1; + +static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler); + +/* lock/unlock CPU freq by Mali */ +#include +#include + +atomic_t mali_cpufreq_lock; + +int cpufreq_lock_by_mali(unsigned int freq) +{ +#ifdef CONFIG_EXYNOS4_CPUFREQ +/* #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_ARCH_EXYNOS4) */ + unsigned int level; + + if (atomic_read(&mali_cpufreq_lock) == 0) { + if (exynos_cpufreq_get_level(freq * 1000, &level)) { + printk(KERN_ERR + "Mali: failed to get cpufreq level for %dMHz", + freq); + return -EINVAL; + } + + if (exynos_cpufreq_lock(DVFS_LOCK_ID_G3D, level)) { + printk(KERN_ERR + "Mali: failed to cpufreq lock for L%d", level); + return -EINVAL; + } + + atomic_set(&mali_cpufreq_lock, 1); + printk(KERN_DEBUG "Mali: cpufreq locked on <%d>%dMHz\n", level, + freq); + } +#endif + return 0; +} + +void cpufreq_unlock_by_mali(void) +{ +#ifdef CONFIG_EXYNOS4_CPUFREQ +/* #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_ARCH_EXYNOS4) */ + if (atomic_read(&mali_cpufreq_lock) == 1) { + exynos_cpufreq_lock_free(DVFS_LOCK_ID_G3D); + atomic_set(&mali_cpufreq_lock, 0); + printk(KERN_DEBUG "Mali: cpufreq locked off\n"); + } +#endif +} + +static unsigned int get_mali_dvfs_status(void) +{ + return maliDvfsStatus.currentStep; +} +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON +int get_mali_dvfs_control_status(void) +{ + return mali_dvfs_control; +} + +mali_bool set_mali_dvfs_current_step(unsigned int step) +{ + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + maliDvfsStatus.currentStep = step % MAX_MALI_DVFS_STEPS; + if (step >= MAX_MALI_DVFS_STEPS) + mali_runtime_resumed = maliDvfsStatus.currentStep; + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + return MALI_TRUE; +} +#endif +static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup) +{ + u32 validatedStep=step; + int err; + +#ifdef CONFIG_REGULATOR + if (mali_regulator_get_usecount() == 0) { + MALI_DEBUG_PRINT(1, ("regulator use_count is 0 \n")); + return MALI_FALSE; + } +#endif + + if (boostup) { +#ifdef CONFIG_REGULATOR + /*change the voltage*/ + mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); +#endif + /*change the clock*/ + mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); + } else { + /*change the clock*/ + mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); +#ifdef CONFIG_REGULATOR + /*change the voltage*/ + mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); +#endif + } + +#ifdef EXYNOS4_ASV_ENABLED + if (samsung_rev() < EXYNOS4412_REV_2_0) { + if (mali_dvfs[step].clock == 160) + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); + else + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); + } +#endif + + + set_mali_dvfs_current_step(validatedStep); + /*for future use*/ + maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep]; + +#if CPUFREQ_LOCK_DURING_440 + /* lock/unlock CPU freq by Mali */ + if (mali_dvfs[step].clock == 440) + err = cpufreq_lock_by_mali(1200); + else + cpufreq_unlock_by_mali(); +#endif + + return MALI_TRUE; +} + +static void mali_platform_wating(u32 msec) +{ + /*sample wating + change this in the future with proper check routine. + */ + unsigned int read_val; + while(1) { + read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00); + if ((read_val & 0x8000)==0x0000) break; + _mali_osk_time_ubusydelay(100); // 1000 -> 100 : 20101218 + } + /* _mali_osk_time_ubusydelay(msec*1000);*/ +} + +static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup ) +{ + + MALI_DEBUG_PRINT(1, ("> change_mali_dvfs_status: %d, %d \n",step, boostup)); + + if (!set_mali_dvfs_status(step, boostup)) { + MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup)); + return MALI_FALSE; + } + + /*wait until clock and voltage is stablized*/ + mali_platform_wating(MALI_DVFS_WATING); /*msec*/ + + return MALI_TRUE; +} + +#ifdef EXYNOS4_ASV_ENABLED +extern unsigned int exynos_result_of_asv; + +static mali_bool mali_dvfs_table_update(void) +{ + unsigned int i; + unsigned int step_num = MALI_DVFS_STEPS; + + if(samsung_rev() < EXYNOS4412_REV_2_0) + step_num = MALI_DVFS_STEPS - 1; + + if(soc_is_exynos4412()) { + if (exynos_armclk_max == 1000000) { + MALI_PRINT(("::C::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table_1ghz_type[i][exynos_result_of_asv]; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + } + } else if(((is_special_flag() >> G3D_LOCK_FLAG) & 0x1) && (samsung_rev() >= EXYNOS4412_REV_2_0)) { + MALI_PRINT(("::L::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv] + 25000; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n ", i, mali_dvfs[i].vol)); + } + } else if (samsung_rev() >= EXYNOS4412_REV_2_0) { + MALI_PRINT(("::P::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv]; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + } + } else { + MALI_PRINT(("::Q::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv]; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + } + } + } + + return MALI_TRUE; +} +#endif + +static unsigned int decideNextStatus(unsigned int utilization) +{ + static unsigned int level = 0; // 0:stay, 1:up + static int mali_dvfs_clk = 0; + + if (mali_runtime_resumed >= 0) { + level = mali_runtime_resumed; + mali_runtime_resumed = -1; + } + + if (mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold + <= mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold) { + MALI_PRINT(("upthreadshold is smaller than downthreshold: %d < %d\n", + mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold, + mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold)); + return level; + } + + if (!mali_dvfs_control && level == maliDvfsStatus.currentStep) { + if (utilization > (int)(255 * mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold / 100) && + level < MALI_DVFS_STEPS - 1) { + level++; + if ((samsung_rev() < EXYNOS4412_REV_2_0) && (maliDvfsStatus.currentStep == 3)) { + level=get_mali_dvfs_status(); + } + } + if (utilization < (int)(255 * mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold / 100) && + level > 0) { + level--; + } + } else if (mali_dvfs_control == 999) { + int i = 0; + for (i = 0; i < MALI_DVFS_STEPS; i++) { + step[i].clk = mali_dvfs_all[i].clock; + } +#ifdef EXYNOS4_ASV_ENABLED + mali_dvfs_table_update(); +#endif + i = 0; + for (i = 0; i < MALI_DVFS_STEPS; i++) { + mali_dvfs[i].clock = step[i].clk; + } + mali_dvfs_control = 0; + level = 0; + + step0_clk = step[0].clk; + change_dvfs_tableset(step0_clk, 0); +#if (MALI_DVFS_STEPS > 1) + step1_clk = step[1].clk; + change_dvfs_tableset(step1_clk, 1); +#if (MALI_DVFS_STEPS > 2) + step2_clk = step[2].clk; + change_dvfs_tableset(step2_clk, 2); +#if (MALI_DVFS_STEPS > 3) + step3_clk = step[3].clk; + change_dvfs_tableset(step3_clk, 3); +#if (MALI_DVFS_STEPS > 4) + step4_clk = step[4].clk; + change_dvfs_tableset(step4_clk, 4); +#endif +#endif +#endif +#endif + } else if (mali_dvfs_control != mali_dvfs_clk && mali_dvfs_control != 999) { + if (mali_dvfs_control < mali_dvfs_all[1].clock && mali_dvfs_control > 0) { + int i = 0; + for (i = 0; i < MALI_DVFS_STEPS; i++) { + step[i].clk = mali_dvfs_all[0].clock; + } + maliDvfsStatus.currentStep = 0; + } else if (mali_dvfs_control < mali_dvfs_all[2].clock && mali_dvfs_control >= mali_dvfs_all[1].clock) { + int i = 0; + for (i = 0; i < MALI_DVFS_STEPS; i++) { + step[i].clk = mali_dvfs_all[1].clock; + } + maliDvfsStatus.currentStep = 1; + } else if (mali_dvfs_control < mali_dvfs_all[3].clock && mali_dvfs_control >= mali_dvfs_all[2].clock) { + int i = 0; + for (i = 0; i < MALI_DVFS_STEPS; i++) { + step[i].clk = mali_dvfs_all[2].clock; + } + maliDvfsStatus.currentStep = 2; + } else if (mali_dvfs_control < mali_dvfs_all[4].clock && mali_dvfs_control >= mali_dvfs_all[3].clock) { + int i = 0; + for (i = 0; i < MALI_DVFS_STEPS; i++) { + step[i].clk = mali_dvfs_all[3].clock; + } + maliDvfsStatus.currentStep = 3; + } else { + int i = 0; + for (i = 0; i < MALI_DVFS_STEPS; i++) { + step[i].clk = mali_dvfs_all[4].clock; + } + maliDvfsStatus.currentStep = 4; + } + step0_clk = step[0].clk; + change_dvfs_tableset(step0_clk, 0); +#if (MALI_DVFS_STEPS > 1) + step1_clk = step[1].clk; + change_dvfs_tableset(step1_clk, 1); +#if (MALI_DVFS_STEPS > 2) + step2_clk = step[2].clk; + change_dvfs_tableset(step2_clk, 2); +#if (MALI_DVFS_STEPS > 3) + step3_clk = step[3].clk; + change_dvfs_tableset(step3_clk, 3); +#if (MALI_DVFS_STEPS > 4) + step4_clk = step[4].clk; + change_dvfs_tableset(step4_clk, 4); +#endif +#endif +#endif +#endif + level = maliDvfsStatus.currentStep; + } + + mali_dvfs_clk = mali_dvfs_control; + + if (_mali_osk_atomic_read(&bottomlock_status) > 0) { + if (level < bottom_lock_step) + level = bottom_lock_step; + } + + return level; +} + +static mali_bool mali_dvfs_status(u32 utilization) +{ + unsigned int nextStatus = 0; + unsigned int curStatus = 0; + mali_bool boostup = MALI_FALSE; + static int stay_count = 0; +#ifdef EXYNOS4_ASV_ENABLED + static mali_bool asv_applied = MALI_FALSE; +#endif + + MALI_DEBUG_PRINT(1, ("> mali_dvfs_status: %d \n",utilization)); +#ifdef EXYNOS4_ASV_ENABLED + if (asv_applied == MALI_FALSE) { + mali_dvfs_table_update(); + change_mali_dvfs_status(1, 0); + asv_applied = MALI_TRUE; + + return MALI_TRUE; + } +#endif + + /*decide next step*/ + curStatus = get_mali_dvfs_status(); + nextStatus = decideNextStatus(utilization); + + MALI_DEBUG_PRINT(1, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep)); + + /*if next status is same with current status, don't change anything*/ + if ((curStatus != nextStatus && stay_count == 0)) { + /*check if boost up or not*/ + if (nextStatus > maliDvfsStatus.currentStep) boostup = 1; + + /*change mali dvfs status*/ + if (!change_mali_dvfs_status(nextStatus,boostup)) { + MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n")); + return MALI_FALSE; + } + stay_count = mali_dvfs_staycount[maliDvfsStatus.currentStep].staycount; + } else { + if (stay_count > 0) + stay_count--; + } + + return MALI_TRUE; +} + + + +int mali_dvfs_is_running(void) +{ + return bMaliDvfsRun; + +} + + + +void mali_dvfs_late_resume(void) +{ + // set the init clock as low when resume + set_mali_dvfs_status(0,0); +} + + +static void mali_dvfs_work_handler(struct work_struct *w) +{ + int change_clk = 0; + int change_step = 0; + bMaliDvfsRun=1; + + /* dvfs table change when clock was changed */ + if (step0_clk != mali_dvfs[0].clock) { + MALI_PRINT(("::: step0_clk change to %d Mhz\n", step0_clk)); + change_clk = step0_clk; + change_step = 0; + step0_clk = change_dvfs_tableset(change_clk, change_step); + } +#if (MALI_DVFS_STEPS > 1) + if (step1_clk != mali_dvfs[1].clock) { + MALI_PRINT(("::: step1_clk change to %d Mhz\n", step1_clk)); + change_clk = step1_clk; + change_step = 1; + step1_clk = change_dvfs_tableset(change_clk, change_step); + } + if (step0_up != mali_dvfs_threshold[0].upthreshold) { + MALI_PRINT(("::: step0_up change to %d %\n", step0_up)); + mali_dvfs_threshold[0].upthreshold = step0_up; + } + if (step1_down != mali_dvfs_threshold[1].downthreshold) { + MALI_PRINT((":::step1_down change to %d %\n", step1_down)); + mali_dvfs_threshold[1].downthreshold = step1_down; + } +#if (MALI_DVFS_STEPS > 2) + if (step2_clk != mali_dvfs[2].clock) { + MALI_PRINT(("::: step2_clk change to %d Mhz\n", step2_clk)); + change_clk = step2_clk; + change_step = 2; + step2_clk = change_dvfs_tableset(change_clk, change_step); + } + if (step1_up != mali_dvfs_threshold[1].upthreshold) { + MALI_PRINT((":::step1_up change to %d %\n", step1_up)); + mali_dvfs_threshold[1].upthreshold = step1_up; + } + if (step2_down != mali_dvfs_threshold[2].downthreshold) { + MALI_PRINT((":::step2_down change to %d %\n", step2_down)); + mali_dvfs_threshold[2].downthreshold = step2_down; + } +#if (MALI_DVFS_STEPS > 3) + if (step3_clk != mali_dvfs[3].clock) { + MALI_PRINT(("::: step3_clk change to %d Mhz\n", step3_clk)); + change_clk = step3_clk; + change_step = 3; + step3_clk = change_dvfs_tableset(change_clk, change_step); + } + if (step2_up != mali_dvfs_threshold[2].upthreshold) { + MALI_PRINT((":::step2_up change to %d %\n", step2_up)); + mali_dvfs_threshold[2].upthreshold = step2_up; + } + if (step3_down != mali_dvfs_threshold[3].downthreshold) { + MALI_PRINT((":::step3_down change to %d %\n", step3_down)); + mali_dvfs_threshold[3].downthreshold = step3_down; + } +#if (MALI_DVFS_STEPS > 4) + if (step4_clk != mali_dvfs[4].clock) { + MALI_PRINT(("::: step4_clk change to %d Mhz\n", step4_clk)); + change_clk = step4_clk; + change_step = 4; + step4_clk = change_dvfs_tableset(change_clk, change_step); + } + if (step3_up != mali_dvfs_threshold[3].upthreshold) { + MALI_PRINT((":::step3_up change to %d %\n", step3_up)); + mali_dvfs_threshold[3].upthreshold = step3_up; + } + if (step4_down != mali_dvfs_threshold[4].downthreshold) { + MALI_PRINT((":::step4_down change to %d %\n", step4_down)); + mali_dvfs_threshold[4].downthreshold = step4_down; + } +#endif +#endif +#endif +#endif + + +#ifdef DEBUG + mali_dvfs[0].vol = step0_vol; + mali_dvfs[1].vol = step1_vol; + mali_dvfs[2].vol = step2_vol; + mali_dvfs[3].vol = step3_vol; + mali_dvfs[4].vol = step4_vol; +#endif + MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n")); + + if (!mali_dvfs_status(mali_dvfs_utilization)) + MALI_DEBUG_PRINT(1,( "error on mali dvfs status in mali_dvfs_work_handler")); + + bMaliDvfsRun=0; +} + +mali_bool init_mali_dvfs_status(int step) +{ + /*default status + add here with the right function to get initilization value. + */ + if (!mali_dvfs_wq) + mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs"); + + _mali_osk_atomic_init(&bottomlock_status, 0); + + /*add a error handling here*/ + set_mali_dvfs_current_step(step); + + return MALI_TRUE; +} + +void deinit_mali_dvfs_status(void) +{ + if (mali_dvfs_wq) + destroy_workqueue(mali_dvfs_wq); + + _mali_osk_atomic_term(&bottomlock_status); + + mali_dvfs_wq = NULL; +} + +mali_bool mali_dvfs_handler(u32 utilization) +{ + mali_dvfs_utilization = utilization; + queue_work_on(0, mali_dvfs_wq,&mali_dvfs_work); + + /*add error handle here*/ + return MALI_TRUE; +} + +int change_dvfs_tableset(int change_clk, int change_step) +{ + int err; + + if (change_clk < mali_dvfs_all[1].clock) { + mali_dvfs[change_step].clock = mali_dvfs_all[0].clock; + } else if (change_clk < mali_dvfs_all[2].clock && change_clk >= mali_dvfs_all[1].clock) { + mali_dvfs[change_step].clock = mali_dvfs_all[1].clock; + } else if (change_clk < mali_dvfs_all[3].clock && change_clk >= mali_dvfs_all[2].clock) { + mali_dvfs[change_step].clock = mali_dvfs_all[2].clock; + } else if (change_clk < mali_dvfs_all[4].clock && change_clk >= mali_dvfs_all[3].clock) { + mali_dvfs[change_step].clock = mali_dvfs_all[3].clock; + } else { + mali_dvfs[change_step].clock = mali_dvfs_all[4].clock; + } + + MALI_PRINT((":::mali dvfs step %d clock and voltage = %d Mhz, %d V\n",change_step, mali_dvfs[change_step].clock, mali_dvfs[change_step].vol)); + + if (maliDvfsStatus.currentStep == change_step) { +#ifdef CONFIG_REGULATOR + /*change the voltage*/ + mali_regulator_set_voltage(mali_dvfs[change_step].vol, mali_dvfs[change_step].vol); +#endif + /*change the clock*/ + mali_clk_set_rate(mali_dvfs[change_step].clock, mali_dvfs[change_step].freq); + +#if CPUFREQ_LOCK_DURING_440 + /* lock/unlock CPU freq by Mali */ + if (mali_dvfs[change_step].clock == 440) + err = cpufreq_lock_by_mali(1200); + else + cpufreq_unlock_by_mali(); +#endif + } + + return mali_dvfs[change_step].clock; +} + +void mali_default_step_set(int step, mali_bool boostup) +{ + mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); + + if (maliDvfsStatus.currentStep == 1) + set_mali_dvfs_status(step, boostup); +} + +int mali_dvfs_bottom_lock_push(int lock_step) +{ + int prev_status = _mali_osk_atomic_read(&bottomlock_status); + + if (prev_status < 0) { + MALI_PRINT(("gpu bottom lock status is not valid for push\n")); + return -1; + } + if (bottom_lock_step < lock_step) { + bottom_lock_step = lock_step; + if (get_mali_dvfs_status() < lock_step) { + mali_regulator_set_voltage(mali_dvfs[lock_step].vol, mali_dvfs[lock_step].vol); + mali_clk_set_rate(mali_dvfs[lock_step].clock, mali_dvfs[lock_step].freq); + set_mali_dvfs_current_step(lock_step); + } + } + return _mali_osk_atomic_inc_return(&bottomlock_status); +} + +int mali_dvfs_bottom_lock_pop(void) +{ + int prev_status = _mali_osk_atomic_read(&bottomlock_status); + if (prev_status <= 0) { + MALI_PRINT(("gpu bottom lock status is not valid for pop\n")); + return -1; + } else if (prev_status == 1) { + bottom_lock_step = 0; + MALI_PRINT(("gpu bottom lock release\n")); + } + + return _mali_osk_atomic_dec_return(&bottomlock_status); +} + +int mali_dvfs_get_vol(int step) +{ + step = step % MAX_MALI_DVFS_STEPS; + MALI_DEBUG_ASSERT(step= vol) + return mali_dvfs[i].vol; + } + MALI_PRINT(("Failed to get voltage from mali_dvfs table, maximum voltage is %d uV\n", mali_dvfs[MALI_DVFS_STEPS-1].vol)); + return 0; +} +#endif diff --git a/drivers/media/video/samsung/mali/regs/mali_200_regs.h b/drivers/media/video/samsung/mali/regs/mali_200_regs.h new file mode 100644 index 0000000..59e92c8 --- /dev/null +++ b/drivers/media/video/samsung/mali/regs/mali_200_regs.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _MALI200_REGS_H_ +#define _MALI200_REGS_H_ + +/** + * Enum for management register addresses. + */ +enum mali200_mgmt_reg +{ + MALI200_REG_ADDR_MGMT_VERSION = 0x1000, + MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x1004, + MALI200_REG_ADDR_MGMT_STATUS = 0x1008, + MALI200_REG_ADDR_MGMT_CTRL_MGMT = 0x100c, + + MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x1020, + MALI200_REG_ADDR_MGMT_INT_CLEAR = 0x1024, + MALI200_REG_ADDR_MGMT_INT_MASK = 0x1028, + MALI200_REG_ADDR_MGMT_INT_STATUS = 0x102c, + + MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW = 0x1044, + + MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x1050, + + MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x1080, + MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x1084, + MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x108c, + + MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x10a0, + MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x10a4, + MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x10ac, + + MALI200_REG_SIZEOF_REGISTER_BANK = 0x10f0 + +}; + +#define MALI200_REG_VAL_PERF_CNT_ENABLE 1 + +enum mali200_mgmt_ctrl_mgmt { + MALI200_REG_VAL_CTRL_MGMT_STOP_BUS = (1<<0), +#if defined(USING_MALI200) + MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES = (1<<3), +#endif + MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET = (1<<5), + MALI200_REG_VAL_CTRL_MGMT_START_RENDERING = (1<<6), +#if defined(USING_MALI400) || defined(USING_MALI450) + MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET = (1<<7), +#endif +}; + +enum mali200_mgmt_irq { + MALI200_REG_VAL_IRQ_END_OF_FRAME = (1<<0), + MALI200_REG_VAL_IRQ_END_OF_TILE = (1<<1), + MALI200_REG_VAL_IRQ_HANG = (1<<2), + MALI200_REG_VAL_IRQ_FORCE_HANG = (1<<3), + MALI200_REG_VAL_IRQ_BUS_ERROR = (1<<4), + MALI200_REG_VAL_IRQ_BUS_STOP = (1<<5), + MALI200_REG_VAL_IRQ_CNT_0_LIMIT = (1<<6), + MALI200_REG_VAL_IRQ_CNT_1_LIMIT = (1<<7), + MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR = (1<<8), + MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND = (1<<9), + MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW = (1<<10), + MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW = (1<<11), + MALI400PP_REG_VAL_IRQ_RESET_COMPLETED = (1<<12), +}; + +#if defined(USING_MALI200) +#define MALI200_REG_VAL_IRQ_MASK_ALL ((enum mali200_mgmt_irq) (\ + MALI200_REG_VAL_IRQ_END_OF_FRAME |\ + MALI200_REG_VAL_IRQ_END_OF_TILE |\ + MALI200_REG_VAL_IRQ_HANG |\ + MALI200_REG_VAL_IRQ_FORCE_HANG |\ + MALI200_REG_VAL_IRQ_BUS_ERROR |\ + MALI200_REG_VAL_IRQ_BUS_STOP |\ + MALI200_REG_VAL_IRQ_CNT_0_LIMIT |\ + MALI200_REG_VAL_IRQ_CNT_1_LIMIT |\ + MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR)) +#elif defined(USING_MALI400) || defined(USING_MALI450) +#define MALI200_REG_VAL_IRQ_MASK_ALL ((enum mali200_mgmt_irq) (\ + MALI200_REG_VAL_IRQ_END_OF_FRAME |\ + MALI200_REG_VAL_IRQ_END_OF_TILE |\ + MALI200_REG_VAL_IRQ_HANG |\ + MALI200_REG_VAL_IRQ_FORCE_HANG |\ + MALI200_REG_VAL_IRQ_BUS_ERROR |\ + MALI200_REG_VAL_IRQ_BUS_STOP |\ + MALI200_REG_VAL_IRQ_CNT_0_LIMIT |\ + MALI200_REG_VAL_IRQ_CNT_1_LIMIT |\ + MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR |\ + MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND |\ + MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW |\ + MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW |\ + MALI400PP_REG_VAL_IRQ_RESET_COMPLETED)) +#else +#error "No supported mali core defined" +#endif + +#if defined(USING_MALI200) +#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\ + MALI200_REG_VAL_IRQ_END_OF_FRAME |\ + MALI200_REG_VAL_IRQ_HANG |\ + MALI200_REG_VAL_IRQ_FORCE_HANG |\ + MALI200_REG_VAL_IRQ_BUS_ERROR |\ + MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR)) +#elif defined(USING_MALI400) || defined(USING_MALI450) +#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\ + MALI200_REG_VAL_IRQ_END_OF_FRAME |\ + MALI200_REG_VAL_IRQ_HANG |\ + MALI200_REG_VAL_IRQ_FORCE_HANG |\ + MALI200_REG_VAL_IRQ_BUS_ERROR |\ + MALI200_REG_VAL_IRQ_BUS_STOP |\ + MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR |\ + MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND |\ + MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW |\ + MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW)) +#else +#error "No supported mali core defined" +#endif + +#define MALI200_REG_VAL_IRQ_MASK_NONE ((enum mali200_mgmt_irq)(0)) + +enum mali200_mgmt_status { + MALI200_REG_VAL_STATUS_RENDERING_ACTIVE = (1<<0), + MALI200_REG_VAL_STATUS_BUS_STOPPED = (1<<4), +}; + +enum mali200_render_unit +{ + MALI200_REG_ADDR_FRAME = 0x0000, + MALI200_REG_ADDR_STACK = 0x0030 +}; + +#if defined(USING_MALI200) +#define MALI200_NUM_REGS_FRAME ((0x04C/4)+1) +#elif defined(USING_MALI400) +#define MALI200_NUM_REGS_FRAME ((0x058/4)+1) +#elif defined(USING_MALI450) +#define MALI200_NUM_REGS_FRAME ((0x058/4)+1) +#else +#error "No supported mali core defined" +#endif + +enum mali200_wb_unit { + MALI200_REG_ADDR_WB0 = 0x0100, + MALI200_REG_ADDR_WB1 = 0x0200, + MALI200_REG_ADDR_WB2 = 0x0300 +}; + +enum mali200_wb_unit_regs { + MALI200_REG_ADDR_WB_SOURCE_SELECT = 0x0000, +}; + +/** The number of registers in one single writeback unit */ +#ifndef MALI200_NUM_REGS_WBx +#define MALI200_NUM_REGS_WBx ((0x02C/4)+1) +#endif + +/* This should be in the top 16 bit of the version register of Mali PP */ +#define MALI200_PP_PRODUCT_ID 0xC807 +#define MALI300_PP_PRODUCT_ID 0xCE07 +#define MALI400_PP_PRODUCT_ID 0xCD07 +#define MALI450_PP_PRODUCT_ID 0xCF07 + + +#endif /* _MALI200_REGS_H_ */ diff --git a/drivers/media/video/samsung/mali/regs/mali_gp_regs.h b/drivers/media/video/samsung/mali/regs/mali_gp_regs.h new file mode 100644 index 0000000..21c83c0 --- /dev/null +++ b/drivers/media/video/samsung/mali/regs/mali_gp_regs.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _MALIGP2_CONROL_REGS_H_ +#define _MALIGP2_CONROL_REGS_H_ + +/** + * These are the different geometry processor control registers. + * Their usage is to control and monitor the operation of the + * Vertex Shader and the Polygon List Builder in the geometry processor. + * Addresses are in 32-bit word relative sizes. + * @see [P0081] "Geometry Processor Data Structures" for details + */ + +typedef enum { + MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR = 0x00, + MALIGP2_REG_ADDR_MGMT_VSCL_END_ADDR = 0x04, + MALIGP2_REG_ADDR_MGMT_PLBUCL_START_ADDR = 0x08, + MALIGP2_REG_ADDR_MGMT_PLBUCL_END_ADDR = 0x0c, + MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR = 0x10, + MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR = 0x14, + MALIGP2_REG_ADDR_MGMT_CMD = 0x20, + MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT = 0x24, + MALIGP2_REG_ADDR_MGMT_INT_CLEAR = 0x28, + MALIGP2_REG_ADDR_MGMT_INT_MASK = 0x2C, + MALIGP2_REG_ADDR_MGMT_INT_STAT = 0x30, + MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW = 0x34, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x3C, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x40, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x44, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x48, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x4C, + MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x50, + MALIGP2_REG_ADDR_MGMT_STATUS = 0x68, + MALIGP2_REG_ADDR_MGMT_VERSION = 0x6C, + MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR_READ = 0x80, + MALIGP2_REG_ADDR_MGMT_PLBCL_START_ADDR_READ = 0x84, + MALIGP2_CONTR_AXI_BUS_ERROR_STAT = 0x94, + MALIGP2_REGISTER_ADDRESS_SPACE_SIZE = 0x98, +} maligp_reg_addr_mgmt_addr; + +#define MALIGP2_REG_VAL_PERF_CNT_ENABLE 1 + +/** + * Commands to geometry processor. + * @see MALIGP2_CTRL_REG_CMD + */ +typedef enum +{ + MALIGP2_REG_VAL_CMD_START_VS = (1<< 0), + MALIGP2_REG_VAL_CMD_START_PLBU = (1<< 1), + MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC = (1<< 4), + MALIGP2_REG_VAL_CMD_RESET = (1<< 5), + MALIGP2_REG_VAL_CMD_FORCE_HANG = (1<< 6), + MALIGP2_REG_VAL_CMD_STOP_BUS = (1<< 9), +#if defined(USING_MALI400) || defined(USING_MALI450) + MALI400GP_REG_VAL_CMD_SOFT_RESET = (1<<10), +#endif +} mgp_contr_reg_val_cmd; + + +/** @defgroup MALIGP2_IRQ + * Interrupt status of geometry processor. + * @see MALIGP2_CTRL_REG_INT_RAWSTAT, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, + * MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_ADDR_MGMT_INT_STAT + * @{ + */ +#define MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST (1 << 0) +#define MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST (1 << 1) +#define MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM (1 << 2) +#define MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ (1 << 3) +#define MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ (1 << 4) +#define MALIGP2_REG_VAL_IRQ_HANG (1 << 5) +#define MALIGP2_REG_VAL_IRQ_FORCE_HANG (1 << 6) +#define MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT (1 << 7) +#define MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT (1 << 8) +#define MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR (1 << 9) +#define MALIGP2_REG_VAL_IRQ_SYNC_ERROR (1 << 10) +#define MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR (1 << 11) +#if defined(USING_MALI400) || defined(USING_MALI450) +#define MALI400GP_REG_VAL_IRQ_AXI_BUS_STOPPED (1 << 12) +#define MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD (1 << 13) +#define MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD (1 << 14) +#define MALI400GP_REG_VAL_IRQ_RESET_COMPLETED (1 << 19) +#define MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW (1 << 20) +#define MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW (1 << 21) +#define MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS (1 << 22) +#elif !defined USING_MALI200 +#error "No supported mali core defined" +#endif + +/* Mask defining all IRQs in MaliGP2 */ +#if defined(USING_MALI200) +#define MALIGP2_REG_VAL_IRQ_MASK_ALL \ + (\ + MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ + MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ | \ + MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ | \ + MALIGP2_REG_VAL_IRQ_HANG | \ + MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ + MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT | \ + MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT | \ + MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ + MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ + MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR) +#elif defined(USING_MALI400) || defined(USING_MALI450) +#define MALIGP2_REG_VAL_IRQ_MASK_ALL \ + (\ + MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ + MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ | \ + MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ | \ + MALIGP2_REG_VAL_IRQ_HANG | \ + MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ + MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT | \ + MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT | \ + MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ + MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ + MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR | \ + MALI400GP_REG_VAL_IRQ_AXI_BUS_STOPPED | \ + MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD | \ + MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD | \ + MALI400GP_REG_VAL_IRQ_RESET_COMPLETED | \ + MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \ + MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW | \ + MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS) +#else +#error "No supported mali core defined" +#endif + +/* Mask defining the IRQs in MaliGP2 which we use*/ +#if defined(USING_MALI200) +#define MALIGP2_REG_VAL_IRQ_MASK_USED \ + (\ + MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ + MALIGP2_REG_VAL_IRQ_HANG | \ + MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ + MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ + MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ + MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR) +#elif defined(USING_MALI400) || defined(USING_MALI450) +#define MALIGP2_REG_VAL_IRQ_MASK_USED \ + (\ + MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ + MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ + MALIGP2_REG_VAL_IRQ_HANG | \ + MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ + MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ + MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ + MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR | \ + MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD | \ + MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD | \ + MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \ + MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW | \ + MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS) +#else +#error "No supported mali core defined" +#endif + +/* Mask defining non IRQs on MaliGP2*/ +#define MALIGP2_REG_VAL_IRQ_MASK_NONE 0 + +/** }@ defgroup MALIGP2_IRQ*/ + +/** @defgroup MALIGP2_STATUS + * The different Status values to the geometry processor. + * @see MALIGP2_CTRL_REG_STATUS + * @{ + */ +#define MALIGP2_REG_VAL_STATUS_VS_ACTIVE 0x0002 +#define MALIGP2_REG_VAL_STATUS_BUS_STOPPED 0x0004 +#define MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE 0x0008 +#define MALIGP2_REG_VAL_STATUS_BUS_ERROR 0x0040 +#define MALIGP2_REG_VAL_STATUS_WRITE_BOUND_ERR 0x0100 +/** }@ defgroup MALIGP2_STATUS*/ + +#define MALIGP2_REG_VAL_STATUS_MASK_ACTIVE (\ + MALIGP2_REG_VAL_STATUS_VS_ACTIVE|\ + MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE) + + +#define MALIGP2_REG_VAL_STATUS_MASK_ERROR (\ + MALIGP2_REG_VAL_STATUS_BUS_ERROR |\ + MALIGP2_REG_VAL_STATUS_WRITE_BOUND_ERR ) + +/* This should be in the top 16 bit of the version register of gp.*/ +#define MALI200_GP_PRODUCT_ID 0xA07 +#define MALI300_GP_PRODUCT_ID 0xC07 +#define MALI400_GP_PRODUCT_ID 0xB07 +#define MALI450_GP_PRODUCT_ID 0xD07 + +/** + * The different sources for instrumented on the geometry processor. + * @see MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC + */ + +enum MALIGP2_cont_reg_perf_cnt_src { + MALIGP2_REG_VAL_PERF_CNT1_SRC_NUMBER_OF_VERTICES_PROCESSED = 0x0a, +}; + +#endif diff --git a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c b/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c new file mode 100644 index 0000000..2426853 --- /dev/null +++ b/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_timestamp.h" + +/* This file is intentionally left empty, as all functions are inlined in mali_profiling_sampler.h */ diff --git a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h b/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h new file mode 100644 index 0000000..0551726 --- /dev/null +++ b/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_TIMESTAMP_H__ +#define __MALI_TIMESTAMP_H__ + +#include "mali_osk.h" + +MALI_STATIC_INLINE _mali_osk_errcode_t _mali_timestamp_reset(void) +{ + /* + * reset counters and overflow flags + */ + + u32 mask = (1 << 0) | /* enable all three counters */ + (0 << 1) | /* reset both Count Registers to 0x0 */ + (1 << 2) | /* reset the Cycle Counter Register to 0x0 */ + (0 << 3) | /* 1 = Cycle Counter Register counts every 64th processor clock cycle */ + (0 << 4) | /* Count Register 0 interrupt enable */ + (0 << 5) | /* Count Register 1 interrupt enable */ + (0 << 6) | /* Cycle Counter interrupt enable */ + (0 << 8) | /* Count Register 0 overflow flag (clear or write, flag on read) */ + (0 << 9) | /* Count Register 1 overflow flag (clear or write, flag on read) */ + (1 << 10); /* Cycle Counter Register overflow flag (clear or write, flag on read) */ + + __asm__ __volatile__ ("MCR p15, 0, %0, c15, c12, 0" : : "r" (mask) ); + + return _MALI_OSK_ERR_OK; +} + +MALI_STATIC_INLINE u64 _mali_timestamp_get(void) +{ + u32 result; + + /* this is for the clock cycles */ + __asm__ __volatile__ ("MRC p15, 0, %0, c15, c12, 1" : "=r" (result)); + + return (u64)result; +} + +#endif /* __MALI_TIMESTAMP_H__ */ diff --git a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c b/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c new file mode 100644 index 0000000..2426853 --- /dev/null +++ b/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_timestamp.h" + +/* This file is intentionally left empty, as all functions are inlined in mali_profiling_sampler.h */ diff --git a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h b/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h new file mode 100644 index 0000000..e6d3f2a --- /dev/null +++ b/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_TIMESTAMP_H__ +#define __MALI_TIMESTAMP_H__ + +#include "mali_osk.h" + +MALI_STATIC_INLINE _mali_osk_errcode_t _mali_timestamp_reset(void) +{ + return _MALI_OSK_ERR_OK; +} + +MALI_STATIC_INLINE u64 _mali_timestamp_get(void) +{ + return _mali_osk_time_get_ns(); +} + +#endif /* __MALI_TIMESTAMP_H__ */ diff --git a/drivers/media/video/samsung/ump/Kconfig b/drivers/media/video/samsung/ump/Kconfig new file mode 100644 index 0000000..09e8daf --- /dev/null +++ b/drivers/media/video/samsung/ump/Kconfig @@ -0,0 +1,58 @@ + +# +## S3C Multimedia Mali configuration +## +# +# For UMP +config VIDEO_UMP + bool "Enable UMP(Unified Memory Provider)" + default n + ---help--- + This enables UMP memory provider + +config UMP_VCM_ALLOC + depends on VIDEO_UMP && VCM + default y + bool "Enable ump-vcm(virtual contiguous memory) memory" + help + Use VCM(virtual-contiguous-memory) to allocate physical memory. + + +config UMP_R3P1_LSI + bool "Uses the R3P1 as a ump module" + depends on VIDEO_UMP + default n + ---help--- + This uses the r3p1 as a UMP kernel module + +choice +depends on VIDEO_UMP +prompt "UMP MEMEMORY OPTION" +default UMP_OSMEM_ONLY +config UMP_DED_ONLY + bool "ump dedicated memory only" + ---help--- + This enables UMP dedicated memory only option +config UMP_OSMEM_ONLY + bool "ump OS memory only" + ---help--- + This enables UMP OS memory only option +config UMP_VCM_ONLY + bool "ump VCM memory" + ---help--- + This enables UMP VCM memory only option + +endchoice +config UMP_MEM_SIZE +int "UMP Memory Size" + depends on VIDEO_UMP + default "512" + ---help--- + This value is dedicated memory size of UMP (unit is MByte). +# For UMP_DEBUG +config VIDEO_UMP_DEBUG + bool "Enables debug messages" + depends on VIDEO_UMP + default n + help + This enables UMP driver debug messages. diff --git a/drivers/media/video/samsung/ump/Kconfig_module b/drivers/media/video/samsung/ump/Kconfig_module new file mode 100644 index 0000000..3ae316c --- /dev/null +++ b/drivers/media/video/samsung/ump/Kconfig_module @@ -0,0 +1,16 @@ +config UMP + tristate "UMP support" + depends on ARM + ---help--- + This enables support for the UMP memory allocation and sharing API. + + To compile this driver as a module, choose M here: the module will be + called ump. + +config UMP_DEBUG + bool "Enable extra debug in UMP" + depends on UMP + default y + ---help--- + This enabled extra debug checks and messages in UMP. + diff --git a/drivers/media/video/samsung/ump/Makefile b/drivers/media/video/samsung/ump/Makefile new file mode 100644 index 0000000..3a1aac0 --- /dev/null +++ b/drivers/media/video/samsung/ump/Makefile @@ -0,0 +1,93 @@ +# +# Copyright (C) 2010-2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained from Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +ifeq ($(CONFIG_UMP_DED_ONLY),y) +UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) +USING_MEMORY=0 +endif + +ifeq ($(CONFIG_UMP_OSMEM_ONLY),y) +UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) +USING_MEMORY=1 +endif + +ifeq ($(CONFIG_UMP_VCM_ONLY),y) +UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) +USING_MEMORY=2 +endif + + +# For UMP Debug +ifeq ($(CONFIG_VIDEO_UMP_DEBUG),y) +DEFINES += -DDEBUG +endif + +# Set up our defines, which will be passed to gcc +DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER +DEFINES += -DUSING_MEMORY=$(USING_MEMORY) +DEFINES += -DUMP_MEM_SIZE=$(UMP_MEM_SIZE) +DEFINES += -DMALI_STATE_TRACKING=1 + +UDD_FILE_PREFIX := drivers/media/video/samsung/ump/ +KBUILDROOT = + +# linux build system integration + +obj-$(CONFIG_VIDEO_UMP) += ump.o + +# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: +# The ARM proprietary product will only include the license/proprietary directory +# The GPL product will only include the license/gpl directory + +INCLUDES += \ + -I$(UDD_FILE_PREFIX)\ + -I$(UDD_FILE_PREFIX)common\ + -I$(UDD_FILE_PREFIX)linux\ + -I$(UDD_FILE_PREFIX)include\ + -I$(UDD_FILE_PREFIX)linux/license/gpl/\ + -I$(UDD_FILE_PREFIX)../mali/common\ + -I$(UDD_FILE_PREFIX)../mali/linux + +OSKFILES+=\ + $(KBUILDROOT)../mali/linux/mali_osk_atomics.o \ + $(KBUILDROOT)../mali/linux/mali_osk_locks.o \ + $(KBUILDROOT)../mali/linux/mali_osk_math.o \ + $(KBUILDROOT)../mali/linux/mali_osk_memory.o \ + $(KBUILDROOT)../mali/linux/mali_osk_misc.o + +ump-y := \ + $(KBUILDROOT)linux/ump_kernel_linux.o \ + $(KBUILDROOT)linux/ump_kernel_memory_backend_os.o \ + $(KBUILDROOT)linux/ump_kernel_memory_backend_dedicated.o \ + $(KBUILDROOT)linux/ump_memory_backend.o \ + $(KBUILDROOT)linux/ump_ukk_wrappers.o \ + $(KBUILDROOT)linux/ump_ukk_ref_wrappers.o \ + $(KBUILDROOT)linux/ump_osk_atomics.o \ + $(KBUILDROOT)linux/ump_osk_low_level_mem.o \ + $(KBUILDROOT)linux/ump_osk_misc.o \ + $(KBUILDROOT)common/ump_kernel_common.o \ + $(KBUILDROOT)common/ump_kernel_descriptor_mapping.o \ + $(KBUILDROOT)common/ump_kernel_api.o \ + $(KBUILDROOT)common/ump_kernel_ref_drv.o\ + $(OSKFILES) + +ump-$(CONFIG_UMP_VCM_ALLOC) += \ + $(KBUILDROOT)linux/ump_kernel_memory_backend_vcm.o \ + +EXTRA_CFLAGS += $(INCLUDES) \ + $(DEFINES) + + +# Get subversion revision number, fall back to 0000 if no svn info is available +SVN_REV:=$(shell ((svnversion | grep -E "^[0-9]+" && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') + +EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV) +EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\" + diff --git a/drivers/media/video/samsung/ump/Makefile.common b/drivers/media/video/samsung/ump/Makefile.common new file mode 100644 index 0000000..26a3d6c --- /dev/null +++ b/drivers/media/video/samsung/ump/Makefile.common @@ -0,0 +1,20 @@ +# +# Copyright (C) 2010-2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained from Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +SRC = $(UMP_FILE_PREFIX)common/ump_kernel_common.c \ + $(UMP_FILE_PREFIX)common/ump_kernel_descriptor_mapping.c \ + $(UMP_FILE_PREFIX)common/ump_kernel_api.c \ + $(UMP_FILE_PREFIX)common/ump_kernel_ref_drv.c + +# Get subversion revision number, fall back to 0000 if no svn info is available +SVN_REV:=$(shell ((svnversion | grep -E "^[0-9]+" && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') + +EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV) +EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\" diff --git a/drivers/media/video/samsung/ump/arch b/drivers/media/video/samsung/ump/arch new file mode 120000 index 0000000..58ffbe7 --- /dev/null +++ b/drivers/media/video/samsung/ump/arch @@ -0,0 +1 @@ +arch-release \ No newline at end of file diff --git a/drivers/media/video/samsung/ump/arch-debug b/drivers/media/video/samsung/ump/arch-debug new file mode 120000 index 0000000..0ed0909 --- /dev/null +++ b/drivers/media/video/samsung/ump/arch-debug @@ -0,0 +1 @@ +arch-pegasus-m400/ \ No newline at end of file diff --git a/drivers/media/video/samsung/ump/arch-orion-m400/config.h b/drivers/media/video/samsung/ump/arch-orion-m400/config.h new file mode 100644 index 0000000..7afbca6 --- /dev/null +++ b/drivers/media/video/samsung/ump/arch-orion-m400/config.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_UMP_H__ +#define __ARCH_CONFIG_UMP_H__ + +#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY +#if (USING_MEMORY == 0) /* Dedicated Memory */ +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000 +#else +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0 +#endif + +#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024 +#endif /* __ARCH_CONFIG_UMP_H__ */ diff --git a/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h b/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h new file mode 100644 index 0000000..532fc94 --- /dev/null +++ b/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +#define ARCH_UMP_BACKEND_DEFAULT 0 +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0xCE000000 +#define ARCH_UMP_MEMORY_SIZE_DEFAULT 32UL * 1024UL * 1024UL + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h b/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h new file mode 100644 index 0000000..7afbca6 --- /dev/null +++ b/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ARCH_CONFIG_UMP_H__ +#define __ARCH_CONFIG_UMP_H__ + +#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY +#if (USING_MEMORY == 0) /* Dedicated Memory */ +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000 +#else +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0 +#endif + +#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024 +#endif /* __ARCH_CONFIG_UMP_H__ */ diff --git a/drivers/media/video/samsung/ump/arch-release b/drivers/media/video/samsung/ump/arch-release new file mode 120000 index 0000000..0ed0909 --- /dev/null +++ b/drivers/media/video/samsung/ump/arch-release @@ -0,0 +1 @@ +arch-pegasus-m400/ \ No newline at end of file diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_api.c b/drivers/media/video/samsung/ump/common/ump_kernel_api.c new file mode 100644 index 0000000..83f0d30 --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_kernel_api.c @@ -0,0 +1,551 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "ump_osk.h" +#include "ump_uk_types.h" +#include "ump_kernel_interface.h" +#include "ump_kernel_common.h" + + + +/* ---------------- UMP kernel space API functions follows ---------------- */ + + + +UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(ump_dd_handle memh) +{ + ump_dd_mem * mem = (ump_dd_mem *)memh; + + DEBUG_ASSERT_POINTER(mem); + + DBG_MSG(5, ("Returning secure ID. ID: %u\n", mem->secure_id)); + + return mem->secure_id; +} + + + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id) +{ + ump_dd_mem * mem; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id)); + if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id)); + return UMP_DD_HANDLE_INVALID; + } + + ump_dd_reference_add(mem); + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return (ump_dd_handle)mem; +} + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id) +{ + ump_dd_mem * mem; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id)); + if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id)); + return UMP_DD_HANDLE_INVALID; + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return (ump_dd_handle)mem; +} + +UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle memh) +{ + ump_dd_mem * mem = (ump_dd_mem*) memh; + + DEBUG_ASSERT_POINTER(mem); + + return mem->nr_blocks; +} + + + +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle memh, ump_dd_physical_block * blocks, unsigned long num_blocks) +{ + ump_dd_mem * mem = (ump_dd_mem *)memh; + + DEBUG_ASSERT_POINTER(mem); + + if (blocks == NULL) + { + DBG_MSG(1, ("NULL parameter in ump_dd_phys_blocks_get()\n")); + return UMP_DD_INVALID; + } + + if (mem->nr_blocks != num_blocks) + { + DBG_MSG(1, ("Specified number of blocks do not match actual number of blocks\n")); + return UMP_DD_INVALID; + } + + DBG_MSG(5, ("Returning physical block information. ID: %u\n", mem->secure_id)); + + _mali_osk_memcpy(blocks, mem->block_array, sizeof(ump_dd_physical_block) * mem->nr_blocks); + + return UMP_DD_SUCCESS; +} + + + +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle memh, unsigned long index, ump_dd_physical_block * block) +{ + ump_dd_mem * mem = (ump_dd_mem *)memh; + + DEBUG_ASSERT_POINTER(mem); + + if (block == NULL) + { + DBG_MSG(1, ("NULL parameter in ump_dd_phys_block_get()\n")); + return UMP_DD_INVALID; + } + + if (index >= mem->nr_blocks) + { + DBG_MSG(5, ("Invalid index specified in ump_dd_phys_block_get()\n")); + return UMP_DD_INVALID; + } + + DBG_MSG(5, ("Returning physical block information. ID: %u, index: %lu\n", mem->secure_id, index)); + + *block = mem->block_array[index]; + + return UMP_DD_SUCCESS; +} + + + +UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle memh) +{ + ump_dd_mem * mem = (ump_dd_mem*)memh; + + DEBUG_ASSERT_POINTER(mem); + + DBG_MSG(5, ("Returning size. ID: %u, size: %lu\n", mem->secure_id, mem->size_bytes)); + + return mem->size_bytes; +} + + + +UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle memh) +{ + ump_dd_mem * mem = (ump_dd_mem*)memh; + int new_ref; + + DEBUG_ASSERT_POINTER(mem); + + new_ref = _ump_osk_atomic_inc_and_read(&mem->ref_count); + + DBG_MSG(5, ("Memory reference incremented. ID: %u, new value: %d\n", mem->secure_id, new_ref)); +} + + + +UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle memh) +{ + int new_ref; + ump_dd_mem * mem = (ump_dd_mem*)memh; + + DEBUG_ASSERT_POINTER(mem); + + /* We must hold this mutex while doing the atomic_dec_and_read, to protect + that elements in the ump_descriptor_mapping table is always valid. If they + are not, userspace may accidently map in this secure_ids right before its freed + giving a mapped backdoor into unallocated memory.*/ + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + new_ref = _ump_osk_atomic_dec_and_read(&mem->ref_count); + + DBG_MSG(5, ("Memory reference decremented. ID: %u, new value: %d\n", mem->secure_id, new_ref)); + + if (0 == new_ref) + { + DBG_MSG(3, ("Final release of memory. ID: %u\n", mem->secure_id)); + + ump_descriptor_mapping_free(device.secure_id_map, (int)mem->secure_id); + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + mem->release_func(mem->ctx, mem); + _mali_osk_free(mem); + } + else + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + } +} + + + +/* --------------- Handling of user space requests follows --------------- */ + + +_mali_osk_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args ) +{ + ump_session_data * session_data; + + DEBUG_ASSERT_POINTER( args ); + DEBUG_ASSERT_POINTER( args->ctx ); + + session_data = (ump_session_data *)args->ctx; + + /* check compatability */ + if (args->version == UMP_IOCTL_API_VERSION) + { + DBG_MSG(3, ("API version set to newest %d (compatible)\n", GET_VERSION(args->version))); + args->compatible = 1; + session_data->api_version = args->version; + } + else if (args->version == MAKE_VERSION_ID(1)) + { + DBG_MSG(2, ("API version set to depricated: %d (compatible)\n", GET_VERSION(args->version))); + args->compatible = 1; + session_data->api_version = args->version; + } + else + { + DBG_MSG(2, ("API version set to %d (incompatible with client version %d)\n", GET_VERSION(UMP_IOCTL_API_VERSION), GET_VERSION(args->version))); + args->compatible = 0; + args->version = UMP_IOCTL_API_VERSION; /* report our version */ + } + + return _MALI_OSK_ERR_OK; +} + + +_mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info ) +{ + ump_session_memory_list_element * session_memory_element; + ump_session_memory_list_element * tmp; + ump_session_data * session_data; + _mali_osk_errcode_t ret = _MALI_OSK_ERR_INVALID_FUNC; + int secure_id; + + DEBUG_ASSERT_POINTER( release_info ); + DEBUG_ASSERT_POINTER( release_info->ctx ); + + /* Retreive the session data */ + session_data = (ump_session_data*)release_info->ctx; + + /* If there are many items in the memory session list we + * could be de-referencing this pointer a lot so keep a local copy + */ + secure_id = release_info->secure_id; + + DBG_MSG(4, ("Releasing memory with IOCTL, ID: %u\n", secure_id)); + + /* Iterate through the memory list looking for the requested secure ID */ + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _MALI_OSK_LIST_FOREACHENTRY(session_memory_element, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list) + { + if ( session_memory_element->mem->secure_id == secure_id) + { + ump_dd_mem *release_mem; + + release_mem = session_memory_element->mem; + _mali_osk_list_del(&session_memory_element->list); + ump_dd_reference_release(release_mem); + _mali_osk_free(session_memory_element); + + ret = _MALI_OSK_ERR_OK; + break; + } + } + + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id)); + + DBG_MSG(4, ("_ump_ukk_release() returning 0x%x\n", ret)); + return ret; +} + +_mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction ) +{ + ump_dd_mem * mem; + _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT; + + DEBUG_ASSERT_POINTER( user_interaction ); + + /* We lock the mappings so things don't get removed while we are looking for the memory */ + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)user_interaction->secure_id, (void**)&mem)) + { + user_interaction->size = mem->size_bytes; + DBG_MSG(4, ("Returning size. ID: %u, size: %lu ", (ump_secure_id)user_interaction->secure_id, (unsigned long)user_interaction->size)); + ret = _MALI_OSK_ERR_OK; + } + else + { + user_interaction->size = 0; + DBG_MSG(1, ("Failed to look up mapping in ump_ioctl_size_get(). ID: %u\n", (ump_secure_id)user_interaction->secure_id)); + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + return ret; +} + + + +void _ump_ukk_msync( _ump_uk_msync_s *args ) +{ + ump_dd_mem * mem = NULL; + void *virtual = NULL; + u32 size = 0; + u32 offset = 0; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); + + if (NULL == mem) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_msync(). ID: %u\n", (ump_secure_id)args->secure_id)); + return; + } + /* Ensure the memory doesn't dissapear when we are flushing it. */ + ump_dd_reference_add(mem); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + /* Returns the cache settings back to Userspace */ + args->is_cached=mem->is_cached; + + /* If this flag is the only one set, we should not do the actual flush, only the readout */ + if ( _UMP_UK_MSYNC_READOUT_CACHE_ENABLED==args->op ) + { + DBG_MSG(3, ("_ump_ukk_msync READOUT ID: %u Enabled: %d\n", (ump_secure_id)args->secure_id, mem->is_cached)); + goto msync_release_and_return; + } + + /* Nothing to do if the memory is not caches */ + if ( 0==mem->is_cached ) + { + DBG_MSG(3, ("_ump_ukk_msync IGNORING ID: %u Enabled: %d OP: %d\n", (ump_secure_id)args->secure_id, mem->is_cached, args->op)); + goto msync_release_and_return; + } + DBG_MSG(3, ("UMP[%02u] _ump_ukk_msync Flush OP: %d Address: 0x%08x Mapping: 0x%08x\n", + (ump_secure_id)args->secure_id, args->op, args->address, args->mapping)); + + if ( args->address ) + { + virtual = (void *)((u32)args->address); + offset = (u32)((args->address) - (args->mapping)); + } else { + /* Flush entire mapping when no address is specified. */ + virtual = args->mapping; + } + if ( args->size ) + { + size = args->size; + } else { + /* Flush entire mapping when no size is specified. */ + size = mem->size_bytes - offset; + } + + if ( (offset + size) > mem->size_bytes ) + { + DBG_MSG(1, ("Trying to flush more than the entire UMP allocation: offset: %u + size: %u > %u\n", offset, size, mem->size_bytes)); + goto msync_release_and_return; + } + + /* The actual cache flush - Implemented for each OS*/ + _ump_osk_msync( mem, virtual, offset, size, args->op, NULL); + +msync_release_and_return: + ump_dd_reference_release(mem); + return; +} + +void _ump_ukk_cache_operations_control(_ump_uk_cache_operations_control_s* args) +{ + ump_session_data * session_data; + ump_uk_cache_op_control op; + + DEBUG_ASSERT_POINTER( args ); + DEBUG_ASSERT_POINTER( args->ctx ); + + op = args->op; + session_data = (ump_session_data *)args->ctx; + + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + if ( op== _UMP_UK_CACHE_OP_START ) + { + session_data->cache_operations_ongoing++; + DBG_MSG(4, ("Cache ops start\n" )); + if ( session_data->cache_operations_ongoing != 1 ) + { + DBG_MSG(2, ("UMP: Number of simultanious cache control ops: %d\n", session_data->cache_operations_ongoing) ); + } + } + else if ( op== _UMP_UK_CACHE_OP_FINISH ) + { + DBG_MSG(4, ("Cache ops finish\n")); + session_data->cache_operations_ongoing--; + #if 0 + if ( session_data->has_pending_level1_cache_flush) + { + /* This function will set has_pending_level1_cache_flush=0 */ + _ump_osk_msync( NULL, NULL, 0, 0, _UMP_UK_MSYNC_FLUSH_L1, session_data); + } + #endif + + /* to be on the safe side: always flush l1 cache when cache operations are done */ + _ump_osk_msync( NULL, NULL, 0, 0, _UMP_UK_MSYNC_FLUSH_L1, session_data); + DBG_MSG(4, ("Cache ops finish end\n" )); + } + else + { + DBG_MSG(1, ("Illegal call to %s at line %d\n", __FUNCTION__, __LINE__)); + } + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + +} + +void _ump_ukk_switch_hw_usage(_ump_uk_switch_hw_usage_s *args ) +{ + ump_dd_mem * mem = NULL; + ump_uk_user old_user; + ump_uk_msync_op cache_op = _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE; + ump_session_data *session_data; + + DEBUG_ASSERT_POINTER( args ); + DEBUG_ASSERT_POINTER( args->ctx ); + + session_data = (ump_session_data *)args->ctx; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); + + if (NULL == mem) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_switch_hw_usage(). ID: %u\n", (ump_secure_id)args->secure_id)); + return; + } + + old_user = mem->hw_device; + mem->hw_device = args->new_user; + + DBG_MSG(3, ("UMP[%02u] Switch usage Start New: %s Prev: %s.\n", (ump_secure_id)args->secure_id, args->new_user?"MALI":"CPU",old_user?"MALI":"CPU")); + + if ( ! mem->is_cached ) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(3, ("UMP[%02u] Changing owner of uncached memory. Cache flushing not needed.\n", (ump_secure_id)args->secure_id)); + return; + } + + if ( old_user == args->new_user) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(4, ("UMP[%02u] Setting the new_user equal to previous for. Cache flushing not needed.\n", (ump_secure_id)args->secure_id)); + return; + } + if ( + /* Previous AND new is both different from CPU */ + (old_user != _UMP_UK_USED_BY_CPU) && (args->new_user != _UMP_UK_USED_BY_CPU ) + ) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(4, ("UMP[%02u] Previous and new user is not CPU. Cache flushing not needed.\n", (ump_secure_id)args->secure_id)); + return; + } + + if ( (old_user != _UMP_UK_USED_BY_CPU ) && (args->new_user==_UMP_UK_USED_BY_CPU) ) + { + cache_op =_UMP_UK_MSYNC_INVALIDATE; + DBG_MSG(4, ("UMP[%02u] Cache invalidation needed\n", (ump_secure_id)args->secure_id)); +#ifdef UMP_SKIP_INVALIDATION +#error + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(4, ("UMP[%02u] Performing Cache invalidation SKIPPED\n", (ump_secure_id)args->secure_id)); + return; +#endif + } + /* Ensure the memory doesn't dissapear when we are flushing it. */ + ump_dd_reference_add(mem); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + /* Take lock to protect: session->cache_operations_ongoing and session->has_pending_level1_cache_flush */ + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + /* Actual cache flush */ + _ump_osk_msync( mem, NULL, 0, mem->size_bytes, cache_op, session_data); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + + ump_dd_reference_release(mem); + DBG_MSG(4, ("UMP[%02u] Switch usage Finish\n", (ump_secure_id)args->secure_id)); + return; +} + +void _ump_ukk_lock(_ump_uk_lock_s *args ) +{ + ump_dd_mem * mem = NULL; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); + + if (NULL == mem) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("UMP[%02u] Failed to look up mapping in _ump_ukk_lock(). ID: %u\n", (ump_secure_id)args->secure_id)); + return; + } + ump_dd_reference_add(mem); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + DBG_MSG(1, ("UMP[%02u] Lock. New lock flag: %d. Old Lock flag:\n", (u32)args->secure_id, (u32)args->lock_usage, (u32) mem->lock_usage )); + + mem->lock_usage = (ump_lock_usage) args->lock_usage; + + /** TODO: TAKE LOCK HERE */ + + ump_dd_reference_release(mem); +} + +void _ump_ukk_unlock(_ump_uk_unlock_s *args ) +{ + ump_dd_mem * mem = NULL; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); + + if (NULL == mem) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_unlock(). ID: %u\n", (ump_secure_id)args->secure_id)); + return; + } + ump_dd_reference_add(mem); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + DBG_MSG(1, ("UMP[%02u] Unlocking. Old Lock flag:\n", (u32)args->secure_id, (u32) mem->lock_usage )); + + mem->lock_usage = (ump_lock_usage) UMP_NOT_LOCKED; + + /** TODO: RELEASE LOCK HERE */ + + ump_dd_reference_release(mem); +} diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_common.c b/drivers/media/video/samsung/ump/common/ump_kernel_common.c new file mode 100644 index 0000000..a27bc77 --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_kernel_common.c @@ -0,0 +1,414 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_bitops.h" +#include "mali_osk_list.h" +#include "ump_osk.h" +#include "ump_uk_types.h" +#include "ump_ukk.h" +#include "ump_kernel_common.h" +#include "ump_kernel_descriptor_mapping.h" +#include "ump_kernel_memory_backend.h" + + + +/** + * Define the initial and maximum size of number of secure_ids on the system + */ +#define UMP_SECURE_ID_TABLE_ENTRIES_INITIAL (128 ) +#define UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM (4096 ) + + +/** + * Define the initial and maximum size of the ump_session_data::cookies_map, + * which is a \ref ump_descriptor_mapping. This limits how many secure_ids + * may be mapped into a particular process using _ump_ukk_map_mem(). + */ + +#define UMP_COOKIES_PER_SESSION_INITIAL (UMP_SECURE_ID_TABLE_ENTRIES_INITIAL ) +#define UMP_COOKIES_PER_SESSION_MAXIMUM (UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM) + +struct ump_dev device; + +_mali_osk_errcode_t ump_kernel_constructor(void) +{ + _mali_osk_errcode_t err; + + /* Perform OS Specific initialization */ + err = _ump_osk_init(); + if( _MALI_OSK_ERR_OK != err ) + { + MSG_ERR(("Failed to initiaze the UMP Device Driver")); + return err; + } + + /* Init the global device */ + _mali_osk_memset(&device, 0, sizeof(device) ); + + /* Create the descriptor map, which will be used for mapping secure ID to ump_dd_mem structs */ + device.secure_id_map_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0 , 0); + if (NULL == device.secure_id_map_lock) + { + MSG_ERR(("Failed to create OSK lock for secure id lookup table\n")); + return _MALI_OSK_ERR_NOMEM; + } + + device.secure_id_map = ump_descriptor_mapping_create(UMP_SECURE_ID_TABLE_ENTRIES_INITIAL, UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM); + if (NULL == device.secure_id_map) + { + _mali_osk_lock_term(device.secure_id_map_lock); + MSG_ERR(("Failed to create secure id lookup table\n")); + return _MALI_OSK_ERR_NOMEM; + } + + /* Init memory backend */ + device.backend = ump_memory_backend_create(); + if (NULL == device.backend) + { + MSG_ERR(("Failed to create memory backend\n")); + _mali_osk_lock_term(device.secure_id_map_lock); + ump_descriptor_mapping_destroy(device.secure_id_map); + return _MALI_OSK_ERR_NOMEM; + } + + return _MALI_OSK_ERR_OK; +} + +void ump_kernel_destructor(void) +{ + DEBUG_ASSERT_POINTER(device.secure_id_map); + DEBUG_ASSERT_POINTER(device.secure_id_map_lock); + + _mali_osk_lock_term(device.secure_id_map_lock); + device.secure_id_map_lock = NULL; + + ump_descriptor_mapping_destroy(device.secure_id_map); + device.secure_id_map = NULL; + + device.backend->shutdown(device.backend); + device.backend = NULL; + + ump_memory_backend_destroy(); + + _ump_osk_term(); +} + +/** Creates a new UMP session + */ +_mali_osk_errcode_t _ump_ukk_open( void** context ) +{ + struct ump_session_data * session_data; + + /* allocated struct to track this session */ + session_data = (struct ump_session_data *)_mali_osk_malloc(sizeof(struct ump_session_data)); + if (NULL == session_data) + { + MSG_ERR(("Failed to allocate ump_session_data in ump_file_open()\n")); + return _MALI_OSK_ERR_NOMEM; + } + + session_data->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0); + if( NULL == session_data->lock ) + { + MSG_ERR(("Failed to initialize lock for ump_session_data in ump_file_open()\n")); + _mali_osk_free(session_data); + return _MALI_OSK_ERR_NOMEM; + } + + session_data->cookies_map = ump_descriptor_mapping_create( UMP_COOKIES_PER_SESSION_INITIAL, UMP_COOKIES_PER_SESSION_MAXIMUM ); + + if ( NULL == session_data->cookies_map ) + { + MSG_ERR(("Failed to create descriptor mapping for _ump_ukk_map_mem cookies\n")); + + _mali_osk_lock_term( session_data->lock ); + _mali_osk_free( session_data ); + return _MALI_OSK_ERR_NOMEM; + } + + _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_list); + + _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_mappings_list); + + /* Since initial version of the UMP interface did not use the API_VERSION ioctl we have to assume + that it is this version, and not the "latest" one: UMP_IOCTL_API_VERSION + Current and later API versions would do an additional call to this IOCTL and update this variable + to the correct one.*/ + session_data->api_version = MAKE_VERSION_ID(1); + + *context = (void*)session_data; + + session_data->cache_operations_ongoing = 0 ; + session_data->has_pending_level1_cache_flush = 0; + + DBG_MSG(2, ("New session opened\n")); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _ump_ukk_close( void** context ) +{ + struct ump_session_data * session_data; + ump_session_memory_list_element * item; + ump_session_memory_list_element * tmp; + + session_data = (struct ump_session_data *)*context; + if (NULL == session_data) + { + MSG_ERR(("Session data is NULL in _ump_ukk_close()\n")); + return _MALI_OSK_ERR_INVALID_ARGS; + } + + /* Unmap any descriptors mapped in. */ + if (0 == _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list)) + { + ump_memory_allocation *descriptor; + ump_memory_allocation *temp; + + DBG_MSG(1, ("Memory mappings found on session usage list during session termination\n")); + + /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */ + _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->list_head_session_memory_mappings_list, ump_memory_allocation, list) + { + _ump_uk_unmap_mem_s unmap_args; + DBG_MSG(4, ("Freeing block with phys address 0x%x size 0x%x mapped in user space at 0x%x\n", + descriptor->phys_addr, descriptor->size, descriptor->mapping)); + unmap_args.ctx = (void*)session_data; + unmap_args.mapping = descriptor->mapping; + unmap_args.size = descriptor->size; + unmap_args._ukk_private = NULL; /* NOTE: unused */ + unmap_args.cookie = descriptor->cookie; + + /* NOTE: This modifies the list_head_session_memory_mappings_list */ + _ump_ukk_unmap_mem( &unmap_args ); + } + } + + /* ASSERT that we really did free everything, because _ump_ukk_unmap_mem() + * can fail silently. */ + DEBUG_ASSERT( _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list) ); + + _MALI_OSK_LIST_FOREACHENTRY(item, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list) + { + _mali_osk_list_del(&item->list); + DBG_MSG(2, ("Releasing UMP memory %u as part of file close\n", item->mem->secure_id)); + ump_dd_reference_release(item->mem); + _mali_osk_free(item); + } + + ump_descriptor_mapping_destroy( session_data->cookies_map ); + + _mali_osk_lock_term(session_data->lock); + _mali_osk_free(session_data); + + DBG_MSG(2, ("Session closed\n")); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ) +{ + struct ump_session_data * session_data; + ump_memory_allocation * descriptor; /* Describes current mapping of memory */ + _mali_osk_errcode_t err; + unsigned long offset = 0; + unsigned long left; + ump_dd_handle handle; /* The real UMP handle for this memory. Its real datatype is ump_dd_mem* */ + ump_dd_mem * mem; /* The real UMP memory. It is equal to the handle, but with exposed struct */ + u32 block; + int map_id; + + session_data = (ump_session_data *)args->ctx; + if( NULL == session_data ) + { + MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); + return _MALI_OSK_ERR_INVALID_ARGS; + } + /* SEC kernel stability 2012-02-17 */ + if (NULL == session_data->cookies_map) + { + MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n")); + return _MALI_OSK_ERR_INVALID_ARGS; + } + descriptor = (ump_memory_allocation*) _mali_osk_calloc( 1, sizeof(ump_memory_allocation)); + if (NULL == descriptor) + { + MSG_ERR(("ump_ukk_map_mem: descriptor allocation failed\n")); + return _MALI_OSK_ERR_NOMEM; + } + + handle = ump_dd_handle_create_from_secure_id(args->secure_id); + if ( UMP_DD_HANDLE_INVALID == handle) + { + _mali_osk_free(descriptor); + DBG_MSG(1, ("Trying to map unknown secure ID %u\n", args->secure_id)); + return _MALI_OSK_ERR_FAULT; + } + + mem = (ump_dd_mem*)handle; + DEBUG_ASSERT(mem); + if (mem->size_bytes != args->size) + { + _mali_osk_free(descriptor); + ump_dd_reference_release(handle); + DBG_MSG(1, ("Trying to map too much or little. ID: %u, virtual size=%lu, UMP size: %lu\n", args->secure_id, args->size, mem->size_bytes)); + return _MALI_OSK_ERR_FAULT; + } + + map_id = ump_descriptor_mapping_allocate_mapping( session_data->cookies_map, (void*) descriptor ); + + if (map_id < 0) + { + _mali_osk_free(descriptor); + ump_dd_reference_release(handle); + DBG_MSG(1, ("ump_ukk_map_mem: unable to allocate a descriptor_mapping for return cookie\n")); + + return _MALI_OSK_ERR_NOMEM; + } + + descriptor->size = args->size; + descriptor->handle = handle; + descriptor->phys_addr = args->phys_addr; + descriptor->process_mapping_info = args->_ukk_private; + descriptor->ump_session = session_data; + descriptor->cookie = (u32)map_id; + + if ( mem->is_cached ) + { + descriptor->is_cached = 1; + args->is_cached = 1; + DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id)); + } + else if ( args->is_cached) + { + mem->is_cached = 1; + descriptor->is_cached = 1; + DBG_MSG(3, ("Warning mapping UMP secure_id: %d. As cached, while it was allocated uncached.\n", args->secure_id)); + } + else + { + descriptor->is_cached = 0; + args->is_cached = 0; + DBG_MSG(3, ("Mapping UMP secure_id: %d as Uncached.\n", args->secure_id)); + } + + _mali_osk_list_init( &descriptor->list ); + + err = _ump_osk_mem_mapregion_init( descriptor ); + if( _MALI_OSK_ERR_OK != err ) + { + DBG_MSG(1, ("Failed to initialize memory mapping in _ump_ukk_map_mem(). ID: %u\n", args->secure_id)); + ump_descriptor_mapping_free( session_data->cookies_map, map_id ); + _mali_osk_free(descriptor); + ump_dd_reference_release(mem); + return err; + } + + DBG_MSG(4, ("Mapping virtual to physical memory: ID: %u, size:%lu, first physical addr: 0x%08lx, number of regions: %lu\n", + mem->secure_id, + mem->size_bytes, + ((NULL != mem->block_array) ? mem->block_array->addr : 0), + mem->nr_blocks)); + + left = descriptor->size; + /* loop over all blocks and map them in */ + for (block = 0; block < mem->nr_blocks; block++) + { + unsigned long size_to_map; + + if (left > mem->block_array[block].size) + { + size_to_map = mem->block_array[block].size; + } + else + { + size_to_map = left; + } + + if (_MALI_OSK_ERR_OK != _ump_osk_mem_mapregion_map(descriptor, offset, (u32 *)&(mem->block_array[block].addr), size_to_map ) ) + { + DBG_MSG(1, ("WARNING: _ump_ukk_map_mem failed to map memory into userspace\n")); + ump_descriptor_mapping_free( session_data->cookies_map, map_id ); + ump_dd_reference_release(mem); + _ump_osk_mem_mapregion_term( descriptor ); + _mali_osk_free(descriptor); + return _MALI_OSK_ERR_FAULT; + } + left -= size_to_map; + offset += size_to_map; + } + + /* Add to the ump_memory_allocation tracking list */ + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_add( &descriptor->list, &session_data->list_head_session_memory_mappings_list ); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + + args->mapping = descriptor->mapping; + args->cookie = descriptor->cookie; + + return _MALI_OSK_ERR_OK; +} + +void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args ) +{ + struct ump_session_data * session_data; + ump_memory_allocation * descriptor; + ump_dd_handle handle; + + session_data = (ump_session_data *)args->ctx; + + if( NULL == session_data ) + { + MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); + return; + } + /* SEC kernel stability 2012-02-17 */ + if (NULL == session_data->cookies_map) + { + MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n")); + return; + } + if (0 != ump_descriptor_mapping_get( session_data->cookies_map, (int)args->cookie, (void**)&descriptor) ) + { + MSG_ERR(("_ump_ukk_map_mem: cookie 0x%X not found for this session\n", args->cookie )); + return; + } + + DEBUG_ASSERT_POINTER(descriptor); + + handle = descriptor->handle; + if ( UMP_DD_HANDLE_INVALID == handle) + { + DBG_MSG(1, ("WARNING: Trying to unmap unknown handle: UNKNOWN\n")); + return; + } + + /* Remove the ump_memory_allocation from the list of tracked mappings */ + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_del( &descriptor->list ); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + + ump_descriptor_mapping_free( session_data->cookies_map, (int)args->cookie ); + + ump_dd_reference_release(handle); + + _ump_osk_mem_mapregion_term( descriptor ); + _mali_osk_free(descriptor); +} + +u32 _ump_ukk_report_memory_usage( void ) +{ + if(device.backend->stat) + return device.backend->stat(device.backend); + else + return 0; +} diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_common.h b/drivers/media/video/samsung/ump/common/ump_kernel_common.h new file mode 100644 index 0000000..6e3a2e9 --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_kernel_common.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __UMP_KERNEL_COMMON_H__ +#define __UMP_KERNEL_COMMON_H__ + +#include "ump_kernel_types.h" +#include "ump_kernel_interface.h" +#include "ump_kernel_descriptor_mapping.h" +#include "ump_kernel_memory_backend.h" + + +#ifdef DEBUG + extern int ump_debug_level; + #define UMP_DEBUG_PRINT(args) _mali_osk_dbgmsg args + #define UMP_DEBUG_CODE(args) args + #define DBG_MSG(level,args) do { /* args should be in brackets */ \ + ((level) <= ump_debug_level)?\ + UMP_DEBUG_PRINT(("UMP<" #level ">: ")), \ + UMP_DEBUG_PRINT(args):0; \ + } while (0) + + #define DBG_MSG_IF(level,condition,args) /* args should be in brackets */ \ + if((condition)&&((level) <= ump_debug_level)) {\ + UMP_DEBUG_PRINT(("UMP<" #level ">: ")); \ + UMP_DEBUG_PRINT(args); \ + } + + #define DBG_MSG_ELSE(level,args) /* args should be in brackets */ \ + else if((level) <= ump_debug_level) { \ + UMP_DEBUG_PRINT(("UMP<" #level ">: ")); \ + UMP_DEBUG_PRINT(args); \ + } + + #define DEBUG_ASSERT_POINTER(pointer) do {if( (pointer)== NULL) MSG_ERR(("NULL pointer " #pointer)); } while(0) + #define DEBUG_ASSERT(condition) do {if(!(condition)) MSG_ERR(("ASSERT failed: " #condition)); } while(0) +#else /* DEBUG */ + #define UMP_DEBUG_PRINT(args) do {} while(0) + #define UMP_DEBUG_CODE(args) + #define DBG_MSG(level,args) do {} while(0) + #define DBG_MSG_IF(level,condition,args) do {} while(0) + #define DBG_MSG_ELSE(level,args) do {} while(0) + #define DEBUG_ASSERT(condition) do {} while(0) + #define DEBUG_ASSERT_POINTER(pointer) do {} while(0) +#endif /* DEBUG */ + +#define MSG_ERR(args) do{ /* args should be in brackets */ \ + _mali_osk_dbgmsg("UMP: ERR: %s\n" ,__FILE__); \ + _mali_osk_dbgmsg( " %s()%4d\n", __FUNCTION__, __LINE__) ; \ + _mali_osk_dbgmsg args ; \ + _mali_osk_dbgmsg("\n"); \ + } while(0) + +#define MSG(args) do{ /* args should be in brackets */ \ + _mali_osk_dbgmsg("UMP: "); \ + _mali_osk_dbgmsg args; \ + } while (0) + + + +/* + * This struct is used to store per session data. + * A session is created when someone open() the device, and + * closed when someone close() it or the user space application terminates. + */ +typedef struct ump_session_data +{ + _mali_osk_list_t list_head_session_memory_list; /**< List of ump allocations made by the process (elements are ump_session_memory_list_element) */ + _mali_osk_list_t list_head_session_memory_mappings_list; /**< List of ump_memory_allocations mapped in */ + int api_version; + _mali_osk_lock_t * lock; + ump_descriptor_mapping * cookies_map; /**< Secure mapping of cookies from _ump_ukk_map_mem() */ + int cache_operations_ongoing; + int has_pending_level1_cache_flush; +} ump_session_data; + + + +/* + * This struct is used to track the UMP memory references a session has. + * We need to track this in order to be able to clean up after user space processes + * which don't do it themself (e.g. due to a crash or premature termination). + */ +typedef struct ump_session_memory_list_element +{ + struct ump_dd_mem * mem; + _mali_osk_list_t list; +} ump_session_memory_list_element; + + + +/* + * Device specific data, created when device driver is loaded, and then kept as the global variable device. + */ +typedef struct ump_dev +{ + _mali_osk_lock_t * secure_id_map_lock; + ump_descriptor_mapping * secure_id_map; + ump_memory_backend * backend; +} ump_dev; + + + +extern int ump_debug_level; +extern struct ump_dev device; + +_mali_osk_errcode_t ump_kernel_constructor(void); +void ump_kernel_destructor(void); +int map_errcode( _mali_osk_errcode_t err ); + +/** + * variables from user space cannot be dereferenced from kernel space; tagging them + * with __user allows the GCC compiler to generate a warning. Other compilers may + * not support this so we define it here as an empty macro if the compiler doesn't + * define it. + */ +#ifndef __user +#define __user +#endif + +#endif /* __UMP_KERNEL_COMMON_H__ */ diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c new file mode 100644 index 0000000..cc7b8be --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_bitops.h" +#include "ump_kernel_common.h" +#include "ump_kernel_descriptor_mapping.h" + +#define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1)) + +/** + * Allocate a descriptor table capable of holding 'count' mappings + * @param count Number of mappings in the table + * @return Pointer to a new table, NULL on error + */ +static ump_descriptor_table * descriptor_table_alloc(int count); + +/** + * Free a descriptor table + * @param table The table to free + */ +static void descriptor_table_free(ump_descriptor_table * table); + +ump_descriptor_mapping * ump_descriptor_mapping_create(int init_entries, int max_entries) +{ + ump_descriptor_mapping * map = _mali_osk_calloc(1, sizeof(ump_descriptor_mapping) ); + + init_entries = MALI_PAD_INT(init_entries); + max_entries = MALI_PAD_INT(max_entries); + + if (NULL != map) + { + map->table = descriptor_table_alloc(init_entries); + if (NULL != map->table) + { + map->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_READERWRITER, 0 , 0); + if ( NULL != map->lock ) + { + _mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */ + map->max_nr_mappings_allowed = max_entries; + map->current_nr_mappings = init_entries; + return map; + } + descriptor_table_free(map->table); + } + _mali_osk_free(map); + } + return NULL; +} + +void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map) +{ + descriptor_table_free(map->table); + _mali_osk_lock_term( map->lock ); + _mali_osk_free(map); +} + +int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target) +{ + int descriptor = -1;/*-EFAULT;*/ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); + if (descriptor == map->current_nr_mappings) + { + int nr_mappings_new; + /* no free descriptor, try to expand the table */ + ump_descriptor_table * new_table; + ump_descriptor_table * old_table = map->table; + nr_mappings_new= map->current_nr_mappings *2; + + if (map->current_nr_mappings >= map->max_nr_mappings_allowed) + { + descriptor = -1; + goto unlock_and_exit; + } + + new_table = descriptor_table_alloc(nr_mappings_new); + if (NULL == new_table) + { + descriptor = -1; + goto unlock_and_exit; + } + + _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); + _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); + map->table = new_table; + map->current_nr_mappings = nr_mappings_new; + descriptor_table_free(old_table); + } + + /* we have found a valid descriptor, set the value and usage bit */ + _mali_osk_set_nonatomic_bit(descriptor, map->table->usage); + map->table->mappings[descriptor] = target; + +unlock_and_exit: + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); + return descriptor; +} + +int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target) +{ + int result = -1;/*-EFAULT;*/ + DEBUG_ASSERT(map); + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + *target = map->table->mappings[descriptor]; + result = 0; + } + else *target = NULL; + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); + return result; +} + +int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target) +{ + int result = -1;/*-EFAULT;*/ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + map->table->mappings[descriptor] = target; + result = 0; + } + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO); + return result; +} + +void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor) +{ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + { + map->table->mappings[descriptor] = NULL; + _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage); + } + _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW); +} + +static ump_descriptor_table * descriptor_table_alloc(int count) +{ + ump_descriptor_table * table; + + table = _mali_osk_calloc(1, sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count) ); + + if (NULL != table) + { + table->usage = (u32*)((u8*)table + sizeof(ump_descriptor_table)); + table->mappings = (void**)((u8*)table + sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG)); + } + + return table; +} + +static void descriptor_table_free(ump_descriptor_table * table) +{ + _mali_osk_free(table); +} diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h new file mode 100644 index 0000000..05b3982 --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_descriptor_mapping.h + */ + +#ifndef __UMP_KERNEL_DESCRIPTOR_MAPPING_H__ +#define __UMP_KERNEL_DESCRIPTOR_MAPPING_H__ + +#include "mali_osk.h" + +/** + * The actual descriptor mapping table, never directly accessed by clients + */ +typedef struct ump_descriptor_table +{ + u32 * usage; /**< Pointer to bitpattern indicating if a descriptor is valid/used or not */ + void** mappings; /**< Array of the pointers the descriptors map to */ +} ump_descriptor_table; + +/** + * The descriptor mapping object + * Provides a separate namespace where we can map an integer to a pointer + */ +typedef struct ump_descriptor_mapping +{ + _mali_osk_lock_t *lock; /**< Lock protecting access to the mapping object */ + int max_nr_mappings_allowed; /**< Max number of mappings to support in this namespace */ + int current_nr_mappings; /**< Current number of possible mappings */ + ump_descriptor_table * table; /**< Pointer to the current mapping table */ +} ump_descriptor_mapping; + +/** + * Create a descriptor mapping object + * Create a descriptor mapping capable of holding init_entries growable to max_entries + * @param init_entries Number of entries to preallocate memory for + * @param max_entries Number of entries to max support + * @return Pointer to a descriptor mapping object, NULL on failure + */ +ump_descriptor_mapping * ump_descriptor_mapping_create(int init_entries, int max_entries); + +/** + * Destroy a descriptor mapping object + * @param map The map to free + */ +void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map); + +/** + * Allocate a new mapping entry (descriptor ID) + * Allocates a new entry in the map. + * @param map The map to allocate a new entry in + * @param target The value to map to + * @return The descriptor allocated, a negative value on error + */ +int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target); + +/** + * Get the value mapped to by a descriptor ID + * @param map The map to lookup the descriptor id in + * @param descriptor The descriptor ID to lookup + * @param target Pointer to a pointer which will receive the stored value + * @return 0 on successful lookup, negative on error + */ +int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target); + +/** + * Set the value mapped to by a descriptor ID + * @param map The map to lookup the descriptor id in + * @param descriptor The descriptor ID to lookup + * @param target Pointer to replace the current value with + * @return 0 on successful lookup, negative on error + */ +int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target); + +/** + * Free the descriptor ID + * For the descriptor to be reused it has to be freed + * @param map The map to free the descriptor from + * @param descriptor The descriptor ID to free + */ +void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor); + +#endif /* __UMP_KERNEL_DESCRIPTOR_MAPPING_H__ */ diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h b/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h new file mode 100644 index 0000000..73915ee --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_memory_mapping.h + */ + +#ifndef __UMP_KERNEL_MEMORY_BACKEND_H__ +#define __UMP_KERNEL_MEMORY_BACKEND_H__ + +#include "ump_kernel_interface.h" +#include "ump_kernel_types.h" + + +typedef struct ump_memory_allocation +{ + void * phys_addr; + void * mapping; + unsigned long size; + ump_dd_handle handle; + void * process_mapping_info; + u32 cookie; /**< necessary on some U/K interface implementations */ + struct ump_session_data * ump_session; /**< Session that this allocation belongs to */ + _mali_osk_list_t list; /**< List for linking together memory allocations into the session's memory head */ + u32 is_cached; +} ump_memory_allocation; + +typedef struct ump_memory_backend +{ + int (*allocate)(void* ctx, ump_dd_mem * descriptor); + void (*release)(void* ctx, ump_dd_mem * descriptor); + void (*shutdown)(struct ump_memory_backend * backend); + u32 (*stat)(struct ump_memory_backend *backend); + int (*pre_allocate_physical_check)(void *ctx, u32 size); + u32 (*adjust_to_mali_phys)(void *ctx, u32 cpu_phys); + void *(*get)(ump_dd_mem *mem, void *args); + void (*set)(ump_dd_mem *mem, void *args); + void * ctx; +} ump_memory_backend; + +ump_memory_backend * ump_memory_backend_create ( void ); +void ump_memory_backend_destroy( void ); + +#endif /*__UMP_KERNEL_MEMORY_BACKEND_H__ */ diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c b/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c new file mode 100644 index 0000000..cb13232 --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "ump_osk.h" +#include "ump_uk_types.h" + +#include "ump_kernel_interface_ref_drv.h" +#include "ump_kernel_common.h" +#include "ump_kernel_descriptor_mapping.h" + +#define UMP_MINIMUM_SIZE 4096 +#define UMP_MINIMUM_SIZE_MASK (~(UMP_MINIMUM_SIZE-1)) +#define UMP_SIZE_ALIGN(x) (((x)+UMP_MINIMUM_SIZE-1)&UMP_MINIMUM_SIZE_MASK) +#define UMP_ADDR_ALIGN_OFFSET(x) ((x)&(UMP_MINIMUM_SIZE-1)) +static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor); + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks) +{ + ump_dd_mem * mem; + unsigned long size_total = 0; + int map_id; + u32 i; + + /* Go through the input blocks and verify that they are sane */ + for (i=0; i < num_blocks; i++) + { + unsigned long addr = blocks[i].addr; + unsigned long size = blocks[i].size; + + DBG_MSG(5, ("Adding physical memory to new handle. Address: 0x%08lx, size: %lu\n", addr, size)); + size_total += blocks[i].size; + + if (0 != UMP_ADDR_ALIGN_OFFSET(addr)) + { + MSG_ERR(("Trying to create UMP memory from unaligned physical address. Address: 0x%08lx\n", addr)); + return UMP_DD_HANDLE_INVALID; + } + + if (0 != UMP_ADDR_ALIGN_OFFSET(size)) + { + MSG_ERR(("Trying to create UMP memory with unaligned size. Size: %lu\n", size)); + return UMP_DD_HANDLE_INVALID; + } + } + + /* Allocate the ump_dd_mem struct for this allocation */ + mem = _mali_osk_malloc(sizeof(*mem)); + if (NULL == mem) + { + DBG_MSG(1, ("Could not allocate ump_dd_mem in ump_dd_handle_create_from_phys_blocks()\n")); + return UMP_DD_HANDLE_INVALID; + } + + /* Find a secure ID for this allocation */ + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*) mem); + + if (map_id < 0) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_free(mem); + DBG_MSG(1, ("Failed to allocate secure ID in ump_dd_handle_create_from_phys_blocks()\n")); + return UMP_DD_HANDLE_INVALID; + } + + /* Now, make a copy of the block information supplied by the user */ + mem->block_array = _mali_osk_malloc(sizeof(ump_dd_physical_block)* num_blocks); + if (NULL == mem->block_array) + { + ump_descriptor_mapping_free(device.secure_id_map, map_id); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_free(mem); + DBG_MSG(1, ("Could not allocate a mem handle for function ump_dd_handle_create_from_phys_blocks().\n")); + return UMP_DD_HANDLE_INVALID; + } + + _mali_osk_memcpy(mem->block_array, blocks, sizeof(ump_dd_physical_block) * num_blocks); + + /* And setup the rest of the ump_dd_mem struct */ + _mali_osk_atomic_init(&mem->ref_count, 1); + mem->secure_id = (ump_secure_id)map_id; + mem->size_bytes = size_total; + mem->nr_blocks = num_blocks; + mem->backend_info = NULL; + mem->ctx = NULL; + mem->release_func = phys_blocks_release; + /* For now UMP handles created by ump_dd_handle_create_from_phys_blocks() is forced to be Uncached */ + mem->is_cached = 0; + mem->hw_device = _UMP_UK_USED_BY_CPU; + mem->lock_usage = UMP_NOT_LOCKED; + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(3, ("UMP memory created. ID: %u, size: %lu\n", mem->secure_id, mem->size_bytes)); + + return (ump_dd_handle)mem; +} + +static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor) +{ + _mali_osk_free(descriptor->block_array); + descriptor->block_array = NULL; +} + +_mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction ) +{ + ump_session_data * session_data = NULL; + ump_dd_mem *new_allocation = NULL; + ump_session_memory_list_element * session_memory_element = NULL; + int map_id; + + DEBUG_ASSERT_POINTER( user_interaction ); + DEBUG_ASSERT_POINTER( user_interaction->ctx ); + + session_data = (ump_session_data *) user_interaction->ctx; + + session_memory_element = _mali_osk_calloc( 1, sizeof(ump_session_memory_list_element)); + if (NULL == session_memory_element) + { + DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n")); + return _MALI_OSK_ERR_NOMEM; + } + + + new_allocation = _mali_osk_calloc( 1, sizeof(ump_dd_mem)); + if (NULL==new_allocation) + { + _mali_osk_free(session_memory_element); + DBG_MSG(1, ("Failed to allocate ump_dd_mem in _ump_ukk_allocate()\n")); + return _MALI_OSK_ERR_NOMEM; + } + + /* Create a secure ID for this allocation */ + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*)new_allocation); + + if (map_id < 0) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_free(session_memory_element); + _mali_osk_free(new_allocation); + DBG_MSG(1, ("Failed to allocate secure ID in ump_ioctl_allocate()\n")); + return - _MALI_OSK_ERR_INVALID_FUNC; + } + + /* Initialize the part of the new_allocation that we know so for */ + new_allocation->secure_id = (ump_secure_id)map_id; + _mali_osk_atomic_init(&new_allocation->ref_count,1); + if ( 0==(UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE & user_interaction->constraints) ) + new_allocation->is_cached = 0; + else new_allocation->is_cached = 1; + + /* special case a size of 0, we should try to emulate what malloc does in this case, which is to return a valid pointer that must be freed, but can't be dereferences */ + if (0 == user_interaction->size) + { + user_interaction->size = 1; /* emulate by actually allocating the minimum block size */ + } + + new_allocation->size_bytes = UMP_SIZE_ALIGN(user_interaction->size); /* Page align the size */ + new_allocation->lock_usage = UMP_NOT_LOCKED; + + /* Now, ask the active memory backend to do the actual memory allocation */ + if (!device.backend->allocate( device.backend->ctx, new_allocation ) ) + { + DBG_MSG(3, ("OOM: No more UMP memory left. Failed to allocate memory in ump_ioctl_allocate(). Size: %lu, requested size: %lu\n", new_allocation->size_bytes, (unsigned long)user_interaction->size)); + ump_descriptor_mapping_free(device.secure_id_map, map_id); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_free(new_allocation); + _mali_osk_free(session_memory_element); + return _MALI_OSK_ERR_INVALID_FUNC; + } + new_allocation->hw_device = _UMP_UK_USED_BY_CPU; + new_allocation->ctx = device.backend->ctx; + new_allocation->release_func = device.backend->release; + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + /* Initialize the session_memory_element, and add it to the session object */ + session_memory_element->mem = new_allocation; + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_add(&(session_memory_element->list), &(session_data->list_head_session_memory_list)); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + + user_interaction->secure_id = new_allocation->secure_id; + user_interaction->size = new_allocation->size_bytes; + DBG_MSG(3, ("UMP memory allocated. ID: %u, size: %lu\n", new_allocation->secure_id, new_allocation->size_bytes)); + + return _MALI_OSK_ERR_OK; +} + + +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args) +{ + ump_dd_mem * mem; + ump_secure_id secure_id; + + DEBUG_ASSERT_POINTER(memh); + + secure_id = ump_dd_secure_id_get(memh); + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + device.backend->set(mem, args); + } + else + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_set(). ID: %u\n", (ump_secure_id)secure_id)); + return UMP_DD_INVALID; + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return UMP_DD_SUCCESS; +} + +UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args) +{ + ump_dd_mem * mem; + void *result; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + result = device.backend->get(mem, args); + } + else + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_get(). ID: %u\n", (ump_secure_id)secure_id)); + return UMP_DD_HANDLE_INVALID; + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return result; +} + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr) +{ + ump_dd_mem * mem; + + DBG_MSG(5, ("Getting handle from Virtual address. vaddr: %u\n", vaddr)); + + _ump_osk_mem_mapregion_get(&mem, vaddr); + + DBG_MSG(1, ("Getting handle's Handle : 0x%8lx\n", mem)); + + return (ump_dd_handle)mem; +} + diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_types.h b/drivers/media/video/samsung/ump/common/ump_kernel_types.h new file mode 100644 index 0000000..19a9755 --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_kernel_types.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __UMP_KERNEL_TYPES_H__ +#define __UMP_KERNEL_TYPES_H__ + +#include "ump_kernel_interface.h" +#include "mali_osk.h" + + +typedef enum +{ + UMP_USED_BY_CPU = 0, + UMP_USED_BY_MALI = 1, + UMP_USED_BY_UNKNOWN_DEVICE= 100, +} ump_hw_usage; + +typedef enum +{ + UMP_NOT_LOCKED = 0, + UMP_READ = 1, + UMP_READ_WRITE = 3, +} ump_lock_usage; + + +/* + * This struct is what is "behind" a ump_dd_handle + */ +typedef struct ump_dd_mem +{ + ump_secure_id secure_id; + _mali_osk_atomic_t ref_count; + unsigned long size_bytes; + unsigned long nr_blocks; + ump_dd_physical_block * block_array; + void (*release_func)(void * ctx, struct ump_dd_mem * descriptor); + void * ctx; + void * backend_info; + int is_cached; + ump_hw_usage hw_device; + ump_lock_usage lock_usage; +} ump_dd_mem; + + + +#endif /* __UMP_KERNEL_TYPES_H__ */ diff --git a/drivers/media/video/samsung/ump/common/ump_osk.h b/drivers/media/video/samsung/ump/common/ump_osk.h new file mode 100644 index 0000000..dabdc7f --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_osk.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_osk.h + * Defines the OS abstraction layer for the UMP kernel device driver (OSK) + */ + +#ifndef __UMP_OSK_H__ +#define __UMP_OSK_H__ + +#include +#include +#include "ump_uk_types.h" +#include "ump_kernel_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +_mali_osk_errcode_t _ump_osk_init( void ); + +_mali_osk_errcode_t _ump_osk_term( void ); + +int _ump_osk_atomic_inc_and_read( _mali_osk_atomic_t *atom ); + +int _ump_osk_atomic_dec_and_read( _mali_osk_atomic_t *atom ); + +_mali_osk_errcode_t _ump_osk_mem_mapregion_init( ump_memory_allocation *descriptor ); + +_mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descriptor, u32 offset, u32 * phys_addr, unsigned long size ); + +void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor ); + +void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data ); + +void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/media/video/samsung/ump/common/ump_uk_types.h b/drivers/media/video/samsung/ump/common/ump_uk_types.h new file mode 100644 index 0000000..143588d --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_uk_types.h @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_uk_types.h + * Defines the types and constants used in the user-kernel interface + */ + +#ifndef __UMP_UK_TYPES_H__ +#define __UMP_UK_TYPES_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Helpers for API version handling */ +#define MAKE_VERSION_ID(x) (((x) << 16UL) | (x)) +#define IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF)) +#define GET_VERSION(x) (((x) >> 16UL) & 0xFFFF) +#define IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y)))) + +/** + * API version define. + * Indicates the version of the kernel API + * The version is a 16bit integer incremented on each API change. + * The 16bit integer is stored twice in a 32bit integer + * So for version 1 the value would be 0x00010001 + */ +#define UMP_IOCTL_API_VERSION MAKE_VERSION_ID(2) + +typedef enum +{ + _UMP_IOC_QUERY_API_VERSION = 1, + _UMP_IOC_ALLOCATE, + _UMP_IOC_RELEASE, + _UMP_IOC_SIZE_GET, + _UMP_IOC_MAP_MEM, /* not used in Linux */ + _UMP_IOC_UNMAP_MEM, /* not used in Linux */ + _UMP_IOC_MSYNC, + _UMP_IOC_CACHE_OPERATIONS_CONTROL, + _UMP_IOC_SWITCH_HW_USAGE, + _UMP_IOC_LOCK, + _UMP_IOC_UNLOCK, +#ifdef CONFIG_ION_EXYNOS + _UMP_IOC_ION_IMPORT, +#endif +}_ump_uk_functions; + +typedef enum +{ + UMP_REF_DRV_UK_CONSTRAINT_NONE = 0, + UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR = 1, + UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE = 128, +} ump_uk_alloc_constraints; + +typedef enum +{ + _UMP_UK_MSYNC_CLEAN = 0, + _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE = 1, + _UMP_UK_MSYNC_INVALIDATE = 2, + _UMP_UK_MSYNC_FLUSH_L1 = 3, + _UMP_UK_MSYNC_READOUT_CACHE_ENABLED = 128, +} ump_uk_msync_op; + +typedef enum +{ + _UMP_UK_CACHE_OP_START = 0, + _UMP_UK_CACHE_OP_FINISH = 1, +} ump_uk_cache_op_control; + +typedef enum +{ + _UMP_UK_READ = 1, + _UMP_UK_READ_WRITE = 3, +} ump_uk_lock_usage; + +typedef enum +{ + _UMP_UK_USED_BY_CPU = 0, + _UMP_UK_USED_BY_MALI = 1, + _UMP_UK_USED_BY_UNKNOWN_DEVICE= 100, +} ump_uk_user; + +/** + * Get API version ([in,out] u32 api_version, [out] u32 compatible) + */ +typedef struct _ump_uk_api_version_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 version; /**< Set to the user space version on entry, stores the device driver version on exit */ + u32 compatible; /**< Non-null if the device is compatible with the client */ +} _ump_uk_api_version_s; + +/** + * ALLOCATE ([out] u32 secure_id, [in,out] u32 size, [in] contraints) + */ +typedef struct _ump_uk_allocate_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< Return value from DD to Userdriver */ + u32 size; /**< Input and output. Requested size; input. Returned size; output */ + ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ +} _ump_uk_allocate_s; + +#ifdef CONFIG_ION_EXYNOS +typedef struct _ump_uk_ion_import_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + int ion_fd; /**< ion_fd */ + u32 secure_id; /**< Return value from DD to Userdriver */ + u32 size; /**< Input and output. Requested size; input. Returned size; output */ + ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ +} _ump_uk_ion_import_s; +#endif + +/** + * SIZE_GET ([in] u32 secure_id, [out]size ) + */ +typedef struct _ump_uk_size_get_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< Input to DD */ + u32 size; /**< Returned size; output */ +} _ump_uk_size_get_s; + +/** + * Release ([in] u32 secure_id) + */ +typedef struct _ump_uk_release_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< Input to DD */ +} _ump_uk_release_s; + +typedef struct _ump_uk_map_mem_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *mapping; /**< [out] Returns user-space virtual address for the mapping */ + void *phys_addr; /**< [in] physical address */ + unsigned long size; /**< [in] size */ + u32 secure_id; /**< [in] secure_id to assign to mapping */ + void * _ukk_private; /**< Only used inside linux port between kernel frontend and common part to store vma */ + u32 cookie; + u32 is_cached; /**< [in,out] caching of CPU mappings */ +} _ump_uk_map_mem_s; + +typedef struct _ump_uk_unmap_mem_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *mapping; + u32 size; + void * _ukk_private; + u32 cookie; +} _ump_uk_unmap_mem_s; + +typedef struct _ump_uk_msync_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + void *mapping; /**< [in] mapping addr */ + void *address; /**< [in] flush start addr */ + u32 size; /**< [in] size to flush */ + ump_uk_msync_op op; /**< [in] flush operation */ + u32 cookie; /**< [in] cookie stored with reference to the kernel mapping internals */ + u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ + u32 is_cached; /**< [out] caching of CPU mappings */ +} _ump_uk_msync_s; + +typedef struct _ump_uk_cache_operations_control_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + ump_uk_cache_op_control op; /**< [in] cache operations start/stop */ +} _ump_uk_cache_operations_control_s; + + +typedef struct _ump_uk_switch_hw_usage_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ + ump_uk_user new_user; /**< [in] cookie stored with reference to the kernel mapping internals */ + +} _ump_uk_switch_hw_usage_s; + +typedef struct _ump_uk_lock_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ + ump_uk_lock_usage lock_usage; +} _ump_uk_lock_s; + +typedef struct _ump_uk_unlock_s +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 secure_id; /**< [in] secure_id that identifies the ump buffer */ +} _ump_uk_unlock_s; + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_UK_TYPES_H__ */ diff --git a/drivers/media/video/samsung/ump/common/ump_ukk.h b/drivers/media/video/samsung/ump/common/ump_ukk.h new file mode 100644 index 0000000..56e4be3 --- /dev/null +++ b/drivers/media/video/samsung/ump/common/ump_ukk.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_ukk.h + * Defines the kernel-side interface of the user-kernel interface + */ + +#ifndef __UMP_UKK_H__ +#define __UMP_UKK_H__ + +#include "mali_osk.h" +#include "ump_uk_types.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +_mali_osk_errcode_t _ump_ukk_open( void** context ); + +_mali_osk_errcode_t _ump_ukk_close( void** context ); + +_mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction ); + +_mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info ); + +_mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction ); + +_mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ); + +_mali_osk_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args ); + +void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args ); + +void _ump_ukk_msync( _ump_uk_msync_s *args ); + +void _ump_ukk_cache_operations_control(_ump_uk_cache_operations_control_s* args); + +void _ump_ukk_switch_hw_usage(_ump_uk_switch_hw_usage_s *args ); + +void _ump_ukk_lock(_ump_uk_lock_s *args ); + +void _ump_ukk_unlock(_ump_uk_unlock_s *args ); + +u32 _ump_ukk_report_memory_usage( void ); + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_UKK_H__ */ diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface.h b/drivers/media/video/samsung/ump/include/ump_kernel_interface.h new file mode 100644 index 0000000..042c8b1 --- /dev/null +++ b/drivers/media/video/samsung/ump/include/ump_kernel_interface.h @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_interface.h + * + * This file contains the kernel space part of the UMP API. + */ + +#ifndef __UMP_KERNEL_INTERFACE_H__ +#define __UMP_KERNEL_INTERFACE_H__ + + +/** @defgroup ump_kernel_space_api UMP Kernel Space API + * @{ */ + + +#include "ump_kernel_platform.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** + * External representation of a UMP handle in kernel space. + */ +typedef void * ump_dd_handle; + +/** + * Typedef for a secure ID, a system wide identificator for UMP memory buffers. + */ +typedef unsigned int ump_secure_id; + + +/** + * Value to indicate an invalid UMP memory handle. + */ +#define UMP_DD_HANDLE_INVALID ((ump_dd_handle)0) + + +/** + * Value to indicate an invalid secure Id. + */ +#define UMP_INVALID_SECURE_ID ((ump_secure_id)-1) + + +/** + * UMP error codes for kernel space. + */ +typedef enum +{ + UMP_DD_SUCCESS, /**< indicates success */ + UMP_DD_INVALID, /**< indicates failure */ +} ump_dd_status_code; + + +/** + * Struct used to describe a physical block used by UMP memory + */ +typedef struct ump_dd_physical_block +{ + unsigned long addr; /**< The physical address of the block */ + unsigned long size; /**< The length of the block, typically page aligned */ +} ump_dd_physical_block; + + +/** + * Retrieves the secure ID for the specified UMP memory. + * + * This identificator is unique across the entire system, and uniquely identifies + * the specified UMP memory. This identificator can later be used through the + * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id" or + * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" + * functions in order to access this UMP memory, for instance from another process. + * + * @note There is a user space equivalent function called @ref ump_secure_id_get "ump_secure_id_get" + * + * @see ump_dd_handle_create_from_secure_id + * @see ump_handle_create_from_secure_id + * @see ump_secure_id_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the secure ID for the specified UMP memory. + */ +UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(ump_dd_handle mem); + + +/** + * Retrieves a handle to allocated UMP memory. + * + * The usage of UMP memory is reference counted, so this will increment the reference + * count by one for the specified UMP memory. + * Use @ref ump_dd_reference_release "ump_dd_reference_release" when there is no longer any + * use for the retrieved handle. + * + * @note There is a user space equivalent function called @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" + * + * @see ump_dd_reference_release + * @see ump_handle_create_from_secure_id + * + * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function. + * + * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id); + + +/** + * Retrieves the number of physical blocks used by the specified UMP memory. + * + * This function retrieves the number of @ref ump_dd_physical_block "ump_dd_physical_block" structs needed + * to describe the physical memory layout of the given UMP memory. This can later be used when calling + * the functions @ref ump_dd_phys_blocks_get "ump_dd_phys_blocks_get" and + * @ref ump_dd_phys_block_get "ump_dd_phys_block_get". + * + * @see ump_dd_phys_blocks_get + * @see ump_dd_phys_block_get + * + * @param mem Handle to UMP memory. + * + * @return The number of ump_dd_physical_block structs required to describe the physical memory layout of the specified UMP memory. + */ +UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle mem); + + +/** + * Retrieves all physical memory block information for specified UMP memory. + * + * This function can be used by other device drivers in order to create MMU tables. + * + * @note This function will fail if the num_blocks parameter is either to large or to small. + * + * @see ump_dd_phys_block_get + * + * @param mem Handle to UMP memory. + * @param blocks An array of @ref ump_dd_physical_block "ump_dd_physical_block" structs that will receive the physical description. + * @param num_blocks The number of blocks to return in the blocks array. Use the function + * @ref ump_dd_phys_block_count_get "ump_dd_phys_block_count_get" first to determine the number of blocks required. + * + * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. + */ +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle mem, ump_dd_physical_block * blocks, unsigned long num_blocks); + + +/** + * Retrieves the physical memory block information for specified block for the specified UMP memory. + * + * This function can be used by other device drivers in order to create MMU tables. + * + * @note This function will return UMP_DD_INVALID if the specified index is out of range. + * + * @see ump_dd_phys_blocks_get + * + * @param mem Handle to UMP memory. + * @param index Which physical info block to retrieve. + * @param block Pointer to a @ref ump_dd_physical_block "ump_dd_physical_block" struct which will receive the requested information. + * + * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. + */ +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle mem, unsigned long index, ump_dd_physical_block * block); + + +/** + * Retrieves the actual size of the specified UMP memory. + * + * The size is reported in bytes, and is typically page aligned. + * + * @note There is a user space equivalent function called @ref ump_size_get "ump_size_get" + * + * @see ump_size_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the allocated size of the specified UMP memory, in bytes. + */ +UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle mem); + + +/** + * Adds an extra reference to the specified UMP memory. + * + * This function adds an extra reference to the specified UMP memory. This function should + * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_dd_handle + * variable. The function @ref ump_dd_reference_release "ump_dd_reference_release" must then be used + * to release each copy of the UMP memory handle. + * + * @note You are not required to call @ref ump_dd_reference_add "ump_dd_reference_add" + * for UMP handles returned from + * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id", + * because these handles are already reference counted by this function. + * + * @note There is a user space equivalent function called @ref ump_reference_add "ump_reference_add" + * + * @see ump_reference_add + * + * @param mem Handle to UMP memory. + */ +UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle mem); + + +/** + * Releases a reference from the specified UMP memory. + * + * This function should be called once for every reference to the UMP memory handle. + * When the last reference is released, all resources associated with this UMP memory + * handle are freed. + * + * @note There is a user space equivalent function called @ref ump_reference_release "ump_reference_release" + * + * @see ump_reference_release + * + * @param mem Handle to UMP memory. + */ +UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle mem); + + +#ifdef __cplusplus +} +#endif + + +/** @} */ /* end group ump_kernel_space_api */ + + +#endif /* __UMP_KERNEL_INTERFACE_H__ */ diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h b/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h new file mode 100644 index 0000000..36c5c9d --- /dev/null +++ b/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_interface.h + */ + +#ifndef __UMP_KERNEL_INTERFACE_REF_DRV_H__ +#define __UMP_KERNEL_INTERFACE_REF_DRV_H__ + +#include "ump_kernel_interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Turn specified physical memory into UMP memory. */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks); +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id); +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args); +UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args); +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr); + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_KERNEL_INTERFACE_REF_DRV_H__ */ diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_platform.h b/drivers/media/video/samsung/ump/include/ump_kernel_platform.h new file mode 100644 index 0000000..4349605 --- /dev/null +++ b/drivers/media/video/samsung/ump/include/ump_kernel_platform.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_platform.h + * + * This file should define UMP_KERNEL_API_EXPORT, + * which dictates how the UMP kernel API should be exported/imported. + * Modify this file, if needed, to match your platform setup. + */ + +#ifndef __UMP_KERNEL_PLATFORM_H__ +#define __UMP_KERNEL_PLATFORM_H__ + +/** @addtogroup ump_kernel_space_api + * @{ */ + +/** + * A define which controls how UMP kernel space API functions are imported and exported. + * This define should be set by the implementor of the UMP API. + */ + +#if defined(_WIN32) + +#if defined(UMP_BUILDING_UMP_LIBRARY) +#define UMP_KERNEL_API_EXPORT __declspec(dllexport) +#else +#define UMP_KERNEL_API_EXPORT __declspec(dllimport) +#endif + +#else + +#define UMP_KERNEL_API_EXPORT + +#endif + + +/** @} */ /* end group ump_kernel_space_api */ + + +#endif /* __UMP_KERNEL_PLATFORM_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h b/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h new file mode 100644 index 0000000..187e33b --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_license.h + * Defines for the macro MODULE_LICENSE. + */ + +#ifndef __UMP_KERNEL_LICENSE_H__ +#define __UMP_KERNEL_LICENSE_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define UMP_KERNEL_LINUX_LICENSE "GPL" +#define UMP_LICENSE_IS_GPL 1 + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_KERNEL_LICENSE_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_ioctl.h b/drivers/media/video/samsung/ump/linux/ump_ioctl.h new file mode 100644 index 0000000..83bb2a4 --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_ioctl.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __UMP_IOCTL_H__ +#define __UMP_IOCTL_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#include + +#ifndef __user +#define __user +#endif + + +/** + * @file UMP_ioctl.h + * This file describes the interface needed to use the Linux device driver. + * The interface is used by the userpace UMP driver. + */ + +#define UMP_IOCTL_NR 0x90 + + +#define UMP_IOC_QUERY_API_VERSION _IOR(UMP_IOCTL_NR, _UMP_IOC_QUERY_API_VERSION, _ump_uk_api_version_s) +#define UMP_IOC_ALLOCATE _IOWR(UMP_IOCTL_NR, _UMP_IOC_ALLOCATE, _ump_uk_allocate_s) +#define UMP_IOC_RELEASE _IOR(UMP_IOCTL_NR, _UMP_IOC_RELEASE, _ump_uk_release_s) +#define UMP_IOC_SIZE_GET _IOWR(UMP_IOCTL_NR, _UMP_IOC_SIZE_GET, _ump_uk_size_get_s) +#define UMP_IOC_MSYNC _IOW(UMP_IOCTL_NR, _UMP_IOC_MSYNC, _ump_uk_msync_s) +#ifdef CONFIG_ION_EXYNOS +#define UMP_IOC_ION_IMPORT _IOW(UMP_IOCTL_NR, _UMP_IOC_ION_IMPORT, _ump_uk_ion_import_s) +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER +#define UMP_IOC_DMABUF_IMPORT _IOW(UMP_IOCTL_NR, _UMP_IOC_DMABUF_IMPORT,\ + struct ump_uk_dmabuf) +#endif + +#define UMP_IOC_CACHE_OPERATIONS_CONTROL _IOW(UMP_IOCTL_NR, _UMP_IOC_CACHE_OPERATIONS_CONTROL, _ump_uk_cache_operations_control_s) +#define UMP_IOC_SWITCH_HW_USAGE _IOW(UMP_IOCTL_NR, _UMP_IOC_SWITCH_HW_USAGE, _ump_uk_switch_hw_usage_s) +#define UMP_IOC_LOCK _IOW(UMP_IOCTL_NR, _UMP_IOC_LOCK, _ump_uk_lock_s) +#define UMP_IOC_UNLOCK _IOW(UMP_IOCTL_NR, _UMP_IOC_UNLOCK, _ump_uk_unlock_s) + + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_IOCTL_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c new file mode 100644 index 0000000..a358a3c --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c @@ -0,0 +1,492 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include /* kernel module definitions */ +#include /* file system operations */ +#include /* character device definitions */ +#include /* request_mem_region */ +#include /* memory management functions and types */ +#include /* user space access */ +#include +#include +#include + +#include "arch/config.h" /* Configuration for current platform. The symlinc for arch is set by Makefile */ +#include "ump_ioctl.h" +#include "ump_kernel_common.h" +#include "ump_kernel_interface.h" +#include "ump_kernel_interface_ref_drv.h" +#include "ump_kernel_descriptor_mapping.h" +#include "ump_kernel_memory_backend.h" +#include "ump_kernel_memory_backend_os.h" +#include "ump_kernel_memory_backend_dedicated.h" +#include "ump_kernel_license.h" + +#include "ump_osk.h" +#include "ump_ukk.h" +#include "ump_uk_types.h" +#include "ump_ukk_wrappers.h" +#include "ump_ukk_ref_wrappers.h" + +#ifdef CONFIG_ION_EXYNOS +#include +extern struct ion_device *ion_exynos; +struct ion_client *ion_client_ump = NULL; +#endif + +/* Module parameter to control log level */ +int ump_debug_level = 2; +module_param(ump_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(ump_debug_level, "Higher number, more dmesg output"); + +/* By default the module uses any available major, but it's possible to set it at load time to a specific number */ +int ump_major = 243; +module_param(ump_major, int, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_major, "Device major number"); + +/* Name of the UMP device driver */ +static char ump_dev_name[] = "ump"; /* should be const, but the functions we call requires non-cost */ + + +#if UMP_LICENSE_IS_GPL +static struct dentry *ump_debugfs_dir = NULL; +#endif + +/* + * The data which we attached to each virtual memory mapping request we get. + * Each memory mapping has a reference to the UMP memory it maps. + * We release this reference when the last memory mapping is unmapped. + */ +typedef struct ump_vma_usage_tracker +{ + int references; + ump_dd_handle handle; +} ump_vma_usage_tracker; + +struct ump_device +{ + struct cdev cdev; +#if UMP_LICENSE_IS_GPL + struct class * ump_class; +#endif +}; + +/* The global variable containing the global device data */ +static struct ump_device ump_device; + + +/* Forward declare static functions */ +static int ump_file_open(struct inode *inode, struct file *filp); +static int ump_file_release(struct inode *inode, struct file *filp); +#ifdef HAVE_UNLOCKED_IOCTL +static long ump_file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#endif +static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma); + +#if defined(CONFIG_VIDEO_UMP) +extern int map_errcode( _mali_osk_errcode_t err ); +#endif + +/* This variable defines the file operations this UMP device driver offer */ +static struct file_operations ump_fops = +{ + .owner = THIS_MODULE, + .open = ump_file_open, + .release = ump_file_release, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = ump_file_ioctl, +#else + .ioctl = ump_file_ioctl, +#endif + .mmap = ump_file_mmap +}; + + +/* This function is called by Linux to initialize this module. + * All we do is initialize the UMP device driver. + */ +static int ump_initialize_module(void) +{ + _mali_osk_errcode_t err; + + DBG_MSG(2, ("Inserting UMP device driver. Compiled: %s, time: %s\n", __DATE__, __TIME__)); + + err = ump_kernel_constructor(); + if (_MALI_OSK_ERR_OK != err) + { + MSG_ERR(("UMP device driver init failed\n")); + return map_errcode(err); + } + + MSG(("UMP device driver %s loaded\n", SVN_REV_STRING)); + return 0; +} + + + +/* + * This function is called by Linux to unload/terminate/exit/cleanup this module. + * All we do is terminate the UMP device driver. + */ +static void ump_cleanup_module(void) +{ +#ifdef CONFIG_ION_EXYNOS + if (ion_client_ump) + ion_client_destroy(ion_client_ump); +#endif + + DBG_MSG(2, ("Unloading UMP device driver\n")); + ump_kernel_destructor(); + DBG_MSG(2, ("Module unloaded\n")); +} + + + +static ssize_t ump_memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 mem = _ump_ukk_report_memory_usage(); + + r = snprintf(buf, 64, "%u\n", mem); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static const struct file_operations ump_memory_usage_fops = { + .owner = THIS_MODULE, + .read = ump_memory_used_read, +}; + +/* + * Initialize the UMP device driver. + */ +int ump_kernel_device_initialize(void) +{ + int err; + dev_t dev = 0; +#if UMP_LICENSE_IS_GPL + ump_debugfs_dir = debugfs_create_dir(ump_dev_name, NULL); + if (ERR_PTR(-ENODEV) == ump_debugfs_dir) + { + ump_debugfs_dir = NULL; + } + else + { + debugfs_create_file("memory_usage", 0400, ump_debugfs_dir, NULL, &ump_memory_usage_fops); + } +#endif + + if (0 == ump_major) + { + /* auto select a major */ + err = alloc_chrdev_region(&dev, 0, 1, ump_dev_name); + ump_major = MAJOR(dev); + } + else + { + /* use load time defined major number */ + dev = MKDEV(ump_major, 0); + err = register_chrdev_region(dev, 1, ump_dev_name); + } + + if (0 == err) + { + memset(&ump_device, 0, sizeof(ump_device)); + + /* initialize our char dev data */ + cdev_init(&ump_device.cdev, &ump_fops); + ump_device.cdev.owner = THIS_MODULE; + ump_device.cdev.ops = &ump_fops; + + /* register char dev with the kernel */ + err = cdev_add(&ump_device.cdev, dev, 1/*count*/); + if (0 == err) + { + +#if UMP_LICENSE_IS_GPL + ump_device.ump_class = class_create(THIS_MODULE, ump_dev_name); + if (IS_ERR(ump_device.ump_class)) + { + err = PTR_ERR(ump_device.ump_class); + } + else + { + struct device * mdev; + mdev = device_create(ump_device.ump_class, NULL, dev, NULL, ump_dev_name); + if (!IS_ERR(mdev)) + { + return 0; + } + + err = PTR_ERR(mdev); + } + cdev_del(&ump_device.cdev); +#else + return 0; +#endif + } + + unregister_chrdev_region(dev, 1); + } + + return err; +} + + + +/* + * Terminate the UMP device driver + */ +void ump_kernel_device_terminate(void) +{ + dev_t dev = MKDEV(ump_major, 0); + +#if UMP_LICENSE_IS_GPL + device_destroy(ump_device.ump_class, dev); + class_destroy(ump_device.ump_class); +#endif + + /* unregister char device */ + cdev_del(&ump_device.cdev); + + /* free major */ + unregister_chrdev_region(dev, 1); + +#if UMP_LICENSE_IS_GPL + if(ump_debugfs_dir) + debugfs_remove_recursive(ump_debugfs_dir); +#endif +} + +/* + * Open a new session. User space has called open() on us. + */ +static int ump_file_open(struct inode *inode, struct file *filp) +{ + struct ump_session_data * session_data; + _mali_osk_errcode_t err; + + /* input validation */ + if (0 != MINOR(inode->i_rdev)) + { + MSG_ERR(("Minor not zero in ump_file_open()\n")); + return -ENODEV; + } + + /* Call the OS-Independent UMP Open function */ + err = _ump_ukk_open((void**) &session_data ); + if( _MALI_OSK_ERR_OK != err ) + { + MSG_ERR(("Ump failed to open a new session\n")); + return map_errcode( err ); + } + + filp->private_data = (void*)session_data; + filp->f_pos = 0; + + return 0; /* success */ +} + + + +/* + * Close a session. User space has called close() or crashed/terminated. + */ +static int ump_file_release(struct inode *inode, struct file *filp) +{ + _mali_osk_errcode_t err; + + err = _ump_ukk_close((void**) &filp->private_data ); + if( _MALI_OSK_ERR_OK != err ) + { + return map_errcode( err ); + } + + return 0; /* success */ +} + + + +/* + * Handle IOCTL requests. + */ +#ifdef HAVE_UNLOCKED_IOCTL +static long ump_file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +#else +static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +#endif +{ + int err = -ENOTTY; + void __user * argument; + struct ump_session_data * session_data; + +#ifndef HAVE_UNLOCKED_IOCTL + (void)inode; /* inode not used */ +#endif + + session_data = (struct ump_session_data *)filp->private_data; + if (NULL == session_data) + { + MSG_ERR(("No session data attached to file object\n")); + return -ENOTTY; + } + + /* interpret the argument as a user pointer to something */ + argument = (void __user *)arg; + + switch (cmd) + { + case UMP_IOC_QUERY_API_VERSION: + err = ump_get_api_version_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_ALLOCATE : + err = ump_allocate_wrapper((u32 __user *)argument, session_data); + break; +#ifdef CONFIG_ION_EXYNOS + case UMP_IOC_ION_IMPORT: + err = ump_ion_import_wrapper((u32 __user *)argument, session_data); + break; +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER + case UMP_IOC_DMABUF_IMPORT: + err = ump_dmabuf_import_wrapper((u32 __user *)argument, + session_data); + break; +#endif + case UMP_IOC_RELEASE: + err = ump_release_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_SIZE_GET: + err = ump_size_get_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_MSYNC: + err = ump_msync_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_CACHE_OPERATIONS_CONTROL: + err = ump_cache_operations_control_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_SWITCH_HW_USAGE: + err = ump_switch_hw_usage_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_LOCK: + err = ump_lock_wrapper((u32 __user *)argument, session_data); + break; + + case UMP_IOC_UNLOCK: + err = ump_unlock_wrapper((u32 __user *)argument, session_data); + break; + + default: + DBG_MSG(1, ("No handler for IOCTL. cmd: 0x%08x, arg: 0x%08lx\n", cmd, arg)); + err = -EFAULT; + break; + } + + return err; +} + +#ifndef CONFIG_VIDEO_UMP +int map_errcode( _mali_osk_errcode_t err ) +{ + switch(err) + { + case _MALI_OSK_ERR_OK : return 0; + case _MALI_OSK_ERR_FAULT: return -EFAULT; + case _MALI_OSK_ERR_INVALID_FUNC: return -ENOTTY; + case _MALI_OSK_ERR_INVALID_ARGS: return -EINVAL; + case _MALI_OSK_ERR_NOMEM: return -ENOMEM; + case _MALI_OSK_ERR_TIMEOUT: return -ETIMEDOUT; + case _MALI_OSK_ERR_RESTARTSYSCALL: return -ERESTARTSYS; + case _MALI_OSK_ERR_ITEM_NOT_FOUND: return -ENOENT; + default: return -EFAULT; + } +} +#endif + +/* + * Handle from OS to map specified virtual memory to specified UMP memory. + */ +static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma) +{ + _ump_uk_map_mem_s args; + _mali_osk_errcode_t err; + struct ump_session_data * session_data; + + /* Validate the session data */ + session_data = (struct ump_session_data *)filp->private_data; + if (NULL == session_data || NULL == session_data->cookies_map->table->mappings) + { + MSG_ERR(("mmap() called without any session data available\n")); + return -EFAULT; + } + + /* Re-pack the arguments that mmap() packed for us */ + args.ctx = session_data; + args.phys_addr = 0; + args.size = vma->vm_end - vma->vm_start; + args._ukk_private = vma; + args.secure_id = vma->vm_pgoff; + args.is_cached = 0; + + if (!(vma->vm_flags & VM_SHARED)) + { + args.is_cached = 1; + vma->vm_flags = vma->vm_flags | VM_SHARED | VM_MAYSHARE ; + DBG_MSG(3, ("UMP Map function: Forcing the CPU to use cache\n")); + } + /* By setting this flag, during a process fork; the child process will not have the parent UMP mappings */ + vma->vm_flags |= VM_DONTCOPY; + + DBG_MSG(4, ("UMP vma->flags: %x\n", vma->vm_flags )); + + /* Call the common mmap handler */ + err = _ump_ukk_map_mem( &args ); + if ( _MALI_OSK_ERR_OK != err) + { + MSG_ERR(("_ump_ukk_map_mem() failed in function ump_file_mmap()")); + return map_errcode( err ); + } + + return 0; /* success */ +} + +/* Export UMP kernel space API functions */ +EXPORT_SYMBOL(ump_dd_secure_id_get); +EXPORT_SYMBOL(ump_dd_handle_create_from_secure_id); +EXPORT_SYMBOL(ump_dd_phys_block_count_get); +EXPORT_SYMBOL(ump_dd_phys_block_get); +EXPORT_SYMBOL(ump_dd_phys_blocks_get); +EXPORT_SYMBOL(ump_dd_size_get); +EXPORT_SYMBOL(ump_dd_reference_add); +EXPORT_SYMBOL(ump_dd_reference_release); +EXPORT_SYMBOL(ump_dd_meminfo_get); +EXPORT_SYMBOL(ump_dd_meminfo_set); +EXPORT_SYMBOL(ump_dd_handle_get_from_vaddr); + +/* Export our own extended kernel space allocator */ +EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks); + +/* Setup init and exit functions for this module */ +//module_init(ump_initialize_module); +arch_initcall(ump_initialize_module); +module_exit(ump_cleanup_module); + +/* And some module informatio */ +MODULE_LICENSE(UMP_KERNEL_LINUX_LICENSE); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION(SVN_REV_STRING); diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h new file mode 100644 index 0000000..4985bb7 --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __UMP_KERNEL_LINUX_H__ +#define __UMP_KERNEL_LINUX_H__ + +int ump_kernel_device_initialize(void); +void ump_kernel_device_terminate(void); + + +#endif /* __UMP_KERNEL_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c new file mode 100644 index 0000000..82c16cc --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* needed to detect kernel version specific code */ +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else /* pre 2.6.26 the file was in the arch specific location */ +#include +#endif + +#include +#include +#include +#include +#include "ump_kernel_common.h" +#include "ump_kernel_memory_backend.h" + + + +#define UMP_BLOCK_SIZE (256UL * 1024UL) /* 256kB, remember to keep the ()s */ + + + +typedef struct block_info +{ + struct block_info * next; +} block_info; + + + +typedef struct block_allocator +{ + struct semaphore mutex; + block_info * all_blocks; + block_info * first_free; + u32 base; + u32 num_blocks; + u32 num_free; +} block_allocator; + + +static void block_allocator_shutdown(ump_memory_backend * backend); +static int block_allocator_allocate(void* ctx, ump_dd_mem * mem); +static void block_allocator_release(void * ctx, ump_dd_mem * handle); +static inline u32 get_phys(block_allocator * allocator, block_info * block); +static u32 block_allocator_stat(struct ump_memory_backend *backend); + + + +/* + * Create dedicated memory backend + */ +ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size) +{ + ump_memory_backend * backend; + block_allocator * allocator; + u32 usable_size; + u32 num_blocks; + + usable_size = (size + UMP_BLOCK_SIZE - 1) & ~(UMP_BLOCK_SIZE - 1); + num_blocks = usable_size / UMP_BLOCK_SIZE; + + if (0 == usable_size) + { + DBG_MSG(1, ("Memory block of size %u is unusable\n", size)); + return NULL; + } + + DBG_MSG(5, ("Creating dedicated UMP memory backend. Base address: 0x%08x, size: 0x%08x\n", base_address, size)); + DBG_MSG(6, ("%u usable bytes which becomes %u blocks\n", usable_size, num_blocks)); + + backend = kzalloc(sizeof(ump_memory_backend), GFP_KERNEL); + if (NULL != backend) + { + allocator = kmalloc(sizeof(block_allocator), GFP_KERNEL); + if (NULL != allocator) + { + allocator->all_blocks = kmalloc(sizeof(block_allocator) * num_blocks, GFP_KERNEL); + if (NULL != allocator->all_blocks) + { + int i; + + allocator->first_free = NULL; + allocator->num_blocks = num_blocks; + allocator->num_free = num_blocks; + allocator->base = base_address; + sema_init(&allocator->mutex, 1); + + for (i = 0; i < num_blocks; i++) + { + allocator->all_blocks[i].next = allocator->first_free; + allocator->first_free = &allocator->all_blocks[i]; + } + + backend->ctx = allocator; + backend->allocate = block_allocator_allocate; + backend->release = block_allocator_release; + backend->shutdown = block_allocator_shutdown; + backend->stat = block_allocator_stat; + backend->pre_allocate_physical_check = NULL; + backend->adjust_to_mali_phys = NULL; + backend->get = NULL; + backend->set = NULL; + + return backend; + } + kfree(allocator); + } + kfree(backend); + } + + return NULL; +} + + + +/* + * Destroy specified dedicated memory backend + */ +static void block_allocator_shutdown(ump_memory_backend * backend) +{ + block_allocator * allocator; + + BUG_ON(!backend); + BUG_ON(!backend->ctx); + + allocator = (block_allocator*)backend->ctx; + + DBG_MSG_IF(1, allocator->num_free != allocator->num_blocks, ("%u blocks still in use during shutdown\n", allocator->num_blocks - allocator->num_free)); + + kfree(allocator->all_blocks); + kfree(allocator); + kfree(backend); +} + + + +static int block_allocator_allocate(void* ctx, ump_dd_mem * mem) +{ + block_allocator * allocator; + u32 left; + block_info * last_allocated = NULL; + int i = 0; + + BUG_ON(!ctx); + BUG_ON(!mem); + + allocator = (block_allocator*)ctx; + left = mem->size_bytes; + + BUG_ON(!left); + BUG_ON(!&allocator->mutex); + + mem->nr_blocks = ((left + UMP_BLOCK_SIZE - 1) & ~(UMP_BLOCK_SIZE - 1)) / UMP_BLOCK_SIZE; + mem->block_array = (ump_dd_physical_block*)vmalloc(sizeof(ump_dd_physical_block) * mem->nr_blocks); + if (NULL == mem->block_array) + { + MSG_ERR(("Failed to allocate block array\n")); + return 0; + } + + if (down_interruptible(&allocator->mutex)) + { + MSG_ERR(("Could not get mutex to do block_allocate\n")); + return 0; + } + + mem->size_bytes = 0; + + while ((left > 0) && (allocator->first_free)) + { + block_info * block; + + block = allocator->first_free; + allocator->first_free = allocator->first_free->next; + block->next = last_allocated; + last_allocated = block; + allocator->num_free--; + + mem->block_array[i].addr = get_phys(allocator, block); + mem->block_array[i].size = UMP_BLOCK_SIZE; + mem->size_bytes += UMP_BLOCK_SIZE; + + i++; + + if (left < UMP_BLOCK_SIZE) left = 0; + else left -= UMP_BLOCK_SIZE; + } + + if (left) + { + block_info * block; + /* release all memory back to the pool */ + while (last_allocated) + { + block = last_allocated->next; + last_allocated->next = allocator->first_free; + allocator->first_free = last_allocated; + last_allocated = block; + allocator->num_free++; + } + + vfree(mem->block_array); + mem->backend_info = NULL; + mem->block_array = NULL; + + DBG_MSG(4, ("Could not find a mem-block for the allocation.\n")); + up(&allocator->mutex); + + return 0; + } + + mem->backend_info = last_allocated; + + up(&allocator->mutex); + mem->is_cached=0; + + return 1; +} + + + +static void block_allocator_release(void * ctx, ump_dd_mem * handle) +{ + block_allocator * allocator; + block_info * block, * next; + + BUG_ON(!ctx); + BUG_ON(!handle); + + allocator = (block_allocator*)ctx; + block = (block_info*)handle->backend_info; + BUG_ON(!block); + + if (down_interruptible(&allocator->mutex)) + { + MSG_ERR(("Allocator release: Failed to get mutex - memory leak\n")); + return; + } + + while (block) + { + next = block->next; + + BUG_ON( (block < allocator->all_blocks) || (block > (allocator->all_blocks + allocator->num_blocks))); + + block->next = allocator->first_free; + allocator->first_free = block; + allocator->num_free++; + + block = next; + } + DBG_MSG(3, ("%d blocks free after release call\n", allocator->num_free)); + up(&allocator->mutex); + + vfree(handle->block_array); + handle->block_array = NULL; +} + + + +/* + * Helper function for calculating the physical base adderss of a memory block + */ +static inline u32 get_phys(block_allocator * allocator, block_info * block) +{ + return allocator->base + ((block - allocator->all_blocks) * UMP_BLOCK_SIZE); +} + +static u32 block_allocator_stat(struct ump_memory_backend *backend) +{ + block_allocator *allocator; + BUG_ON(!backend); + allocator = (block_allocator*)backend->ctx; + BUG_ON(!allocator); + + return (allocator->num_blocks - allocator->num_free)* UMP_BLOCK_SIZE; +} diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h new file mode 100644 index 0000000..ca8faae --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_memory_backend_dedicated.h + */ + +#ifndef __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ +#define __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ + +#include "ump_kernel_memory_backend.h" + +ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size); + +#endif /* __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ */ + 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 new file mode 100644 index 0000000..8f6a9b3 --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* needed to detect kernel version specific code */ +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else /* pre 2.6.26 the file was in the arch specific location */ +#include +#endif + +#include +#include +#include +#include +#include +#include +#include "ump_kernel_common.h" +#include "ump_kernel_memory_backend.h" + + + +typedef struct os_allocator +{ + struct semaphore mutex; + u32 num_pages_max; /**< Maximum number of pages to allocate from the OS */ + u32 num_pages_allocated; /**< Number of pages allocated from the OS */ +} os_allocator; + + + +static void os_free(void* ctx, ump_dd_mem * descriptor); +static int os_allocate(void* ctx, ump_dd_mem * descriptor); +static void os_memory_backend_destroy(ump_memory_backend * backend); +static u32 os_stat(struct ump_memory_backend *backend); + + + +/* + * Create OS memory backend + */ +ump_memory_backend * ump_os_memory_backend_create(const int max_allocation) +{ + ump_memory_backend * backend; + os_allocator * info; + + info = kmalloc(sizeof(os_allocator), GFP_KERNEL); + if (NULL == info) + { + return NULL; + } + + info->num_pages_max = max_allocation >> PAGE_SHIFT; + info->num_pages_allocated = 0; + + sema_init(&info->mutex, 1); + + backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL); + if (NULL == backend) + { + kfree(info); + return NULL; + } + + backend->ctx = info; + backend->allocate = os_allocate; + backend->release = os_free; + backend->shutdown = os_memory_backend_destroy; + backend->stat = os_stat; + backend->pre_allocate_physical_check = NULL; + backend->adjust_to_mali_phys = NULL; + backend->get = NULL; + backend->set = NULL; + + return backend; +} + + + +/* + * Destroy specified OS memory backend + */ +static void os_memory_backend_destroy(ump_memory_backend * backend) +{ + os_allocator * info = (os_allocator*)backend->ctx; + + DBG_MSG_IF(1, 0 != info->num_pages_allocated, ("%d pages still in use during shutdown\n", info->num_pages_allocated)); + + kfree(info); + kfree(backend); +} + + + +/* + * Allocate UMP memory + */ +static int os_allocate(void* ctx, ump_dd_mem * descriptor) +{ + u32 left; + os_allocator * info; + int pages_allocated = 0; + int is_cached; + + BUG_ON(!descriptor); + BUG_ON(!ctx); + + info = (os_allocator*)ctx; + left = descriptor->size_bytes; + is_cached = descriptor->is_cached; + + if (down_interruptible(&info->mutex)) + { + DBG_MSG(1, ("Failed to get mutex in os_free\n")); + return 0; /* failure */ + } + + descriptor->backend_info = NULL; + descriptor->nr_blocks = ((left + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) >> PAGE_SHIFT; + + DBG_MSG(5, ("Allocating page array. Size: %lu\n", descriptor->nr_blocks * sizeof(ump_dd_physical_block))); + + descriptor->block_array = (ump_dd_physical_block *)vmalloc(sizeof(ump_dd_physical_block) * descriptor->nr_blocks); + if (NULL == descriptor->block_array) + { + up(&info->mutex); + DBG_MSG(1, ("Block array could not be allocated\n")); + return 0; /* failure */ + } + + while (left > 0) + { + struct page * new_page; + + if (is_cached) + { + new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN ); + } else + { + new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD); + } + if (NULL == new_page) + { + MSG_ERR(("UMP memory allocated: Out of Memory !!\n")); + break; + } + + /* Ensure page caches are flushed. */ + if ( is_cached ) + { + descriptor->block_array[pages_allocated].addr = page_to_phys(new_page); + descriptor->block_array[pages_allocated].size = PAGE_SIZE; + } else + { + descriptor->block_array[pages_allocated].addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL ); + descriptor->block_array[pages_allocated].size = PAGE_SIZE; + } + + DBG_MSG(5, ("Allocated page 0x%08lx cached: %d\n", descriptor->block_array[pages_allocated].addr, is_cached)); + + if (left < PAGE_SIZE) + { + left = 0; + } + else + { + left -= PAGE_SIZE; + } + + pages_allocated++; + } + + DBG_MSG(5, ("Alloce for ID:%2d got %d pages, cached: %d\n", descriptor->secure_id, pages_allocated)); + + if (left) + { + DBG_MSG(1, ("Failed to allocate needed pages\n")); + DBG_MSG(1, ("UMP memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", + (pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); + + while(pages_allocated) + { + pages_allocated--; + if ( !is_cached ) + { + dma_unmap_page(NULL, descriptor->block_array[pages_allocated].addr, PAGE_SIZE, DMA_BIDIRECTIONAL); + } + __free_page(pfn_to_page(descriptor->block_array[pages_allocated].addr >> PAGE_SHIFT) ); + } + + up(&info->mutex); + + return 0; /* failure */ + } + + info->num_pages_allocated += pages_allocated; + + DBG_MSG(6, ("%d out of %d pages now allocated\n", info->num_pages_allocated, info->num_pages_max)); + + up(&info->mutex); + + return 1; /* success*/ +} + + +/* + * Free specified UMP memory + */ +static void os_free(void* ctx, ump_dd_mem * descriptor) +{ + os_allocator * info; + int i; + + BUG_ON(!ctx); + BUG_ON(!descriptor); + + info = (os_allocator*)ctx; + + BUG_ON(descriptor->nr_blocks > info->num_pages_allocated); + + if (down_interruptible(&info->mutex)) + { + DBG_MSG(1, ("Failed to get mutex in os_free\n")); + return; + } + + DBG_MSG(5, ("Releasing %lu OS pages\n", descriptor->nr_blocks)); + + info->num_pages_allocated -= descriptor->nr_blocks; + + up(&info->mutex); + + for ( i = 0; i < descriptor->nr_blocks; i++) + { + DBG_MSG(6, ("Freeing physical page. Address: 0x%08lx\n", descriptor->block_array[i].addr)); + if ( ! descriptor->is_cached) + { + dma_unmap_page(NULL, descriptor->block_array[i].addr, PAGE_SIZE, DMA_BIDIRECTIONAL); + } + __free_page(pfn_to_page(descriptor->block_array[i].addr>>PAGE_SHIFT) ); + } + + vfree(descriptor->block_array); +} + + +static u32 os_stat(struct ump_memory_backend *backend) +{ + os_allocator *info; + info = (os_allocator*)backend->ctx; + return info->num_pages_allocated * _MALI_OSK_MALI_PAGE_SIZE; +} diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h new file mode 100644 index 0000000..6f7e610 --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_memory_backend_os.h + */ + +#ifndef __UMP_KERNEL_MEMORY_BACKEND_OS_H__ +#define __UMP_KERNEL_MEMORY_BACKEND_OS_H__ + +#include "ump_kernel_memory_backend.h" + +ump_memory_backend * ump_os_memory_backend_create(const int max_allocation); + +#endif /* __UMP_KERNEL_MEMORY_BACKEND_OS_H__ */ + diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c new file mode 100644 index 0000000..46797ea --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* create by boojin.kim@samsung.com */ +/* needed to detect kernel version specific code */ +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else /* pre 2.6.26 the file was in the arch specific location */ +#include +#endif + +#include +#include +#include +#include +#include +#include "ump_kernel_common.h" +#include "ump_kernel_memory_backend.h" +#include "ump_kernel_interface_ref_drv.h" +#include "ump_kernel_memory_backend_vcm.h" +#include "../common/ump_uk_types.h" +#include +#include +#include + +#define UMP_REF_DRV_UK_VCM_DEV_G2D 12 + +typedef struct ump_vcm { + struct vcm *vcm; + struct vcm_res *vcm_res; + unsigned int dev_id; +} ump_vcm; + +typedef struct vcm_allocator { + struct semaphore mutex; + u32 num_vcm_blocks; +} vcm_allocator; + +static void ump_vcm_free(void* ctx, ump_dd_mem * descriptor); +static int ump_vcm_allocate(void* ctx, ump_dd_mem * descriptor); +static void *vcm_res_get(ump_dd_mem *mem, void* args); +static void vcm_attr_set(ump_dd_mem *mem, void* args); +static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor); +static void vcm_memory_backend_destroy(ump_memory_backend * backend); + + +/* + * Create VCM memory backend + */ +ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation) +{ + ump_memory_backend * backend; + vcm_allocator * info; + + info = kmalloc(sizeof(vcm_allocator), GFP_KERNEL); + if (NULL == info) + { + return NULL; + } + + info->num_vcm_blocks = 0; + + + sema_init(&info->mutex, 1); + + backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL); + if (NULL == backend) + { + kfree(info); + return NULL; + } + + backend->ctx = info; + backend->allocate = ump_vcm_allocate; + backend->release = ump_vcm_free; + backend->shutdown = vcm_memory_backend_destroy; + backend->pre_allocate_physical_check = NULL; + backend->adjust_to_mali_phys = NULL; + + backend->get = vcm_res_get; + backend->set = vcm_attr_set; + + + return backend; +} + +/* + * Destroy specified VCM memory backend + */ +static void vcm_memory_backend_destroy(ump_memory_backend * backend) +{ + vcm_allocator * info = (vcm_allocator*)backend->ctx; +#if 0 + DBG_MSG_IF(1, 0 != info->num_pages_allocated, ("%d pages still in use during shutdown\n", info->num_pages_allocated)); +#endif + kfree(info); + kfree(backend); +} + +/* + * Allocate UMP memory + */ +static int ump_vcm_allocate(void *ctx, ump_dd_mem * descriptor) +{ + int ret; /* success */ + vcm_allocator *info; + struct ump_vcm *ump_vcm; + + BUG_ON(!descriptor); + BUG_ON(!ctx); + + info = (vcm_allocator*)ctx; + + ump_vcm = kmalloc(sizeof(struct ump_vcm), GFP_KERNEL); + if (NULL == ump_vcm) + { + return 0; + } + + ump_vcm->dev_id = (int)descriptor->backend_info & ~UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE; + + if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_NONE) { /* None */ + ump_vcm->dev_id = UMP_REF_DRV_UK_VCM_DEV_G2D; /* this ID is G2D */ + } + else if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR) { /* Physical Linear */ + return 0; + } + else { /* Other VCM */ + ump_vcm->dev_id -= 2; + } + + DBG_MSG(5, ("Device ID for VCM : %d\n", ump_vcm->dev_id)); + ump_vcm->vcm = vcm_find_vcm(ump_vcm->dev_id); + + if (!ump_vcm->vcm) + { + return 0; + } + descriptor->backend_info = (void*)ump_vcm; + + if (down_interruptible(&info->mutex)) { + DBG_MSG(1, ("Failed to get mutex in ump_vcm_allocate\n")); + return 0; /* failure */ + } + + ret = vcm_mem_allocator(info, descriptor); + up(&info->mutex); + + return ret; /* success */ +} + +static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor) +{ + unsigned long num_blocks; + int i; + struct vcm_phys *phys; + struct vcm_phys_part *part; + int size_total = 0; + struct ump_vcm *ump_vcm; + + ump_vcm = (struct ump_vcm*)descriptor->backend_info; + + ump_vcm->vcm_res = + vcm_make_binding(ump_vcm->vcm, descriptor->size_bytes, + ump_vcm->dev_id, 0); + + phys = ump_vcm->vcm_res->phys; + part = phys->parts; + num_blocks = phys->count; + + DBG_MSG(5, + ("Allocating page array. Size: %lu, VCM Reservation : 0x%x\n", + phys->count * sizeof(ump_dd_physical_block), + ump_vcm->vcm_res->start)); + + /* Now, make a copy of the block information supplied by the user */ + descriptor->block_array = + (ump_dd_physical_block *) vmalloc(sizeof(ump_dd_physical_block) * + num_blocks); + + if (NULL == descriptor->block_array) { + vfree(descriptor->block_array); + DBG_MSG(1, ("Could not allocate a mem handle for function.\n")); + return 0; /* failure */ + } + + for (i = 0; i < num_blocks; i++) { + descriptor->block_array[i].addr = part->start; + descriptor->block_array[i].size = part->size; + + dmac_unmap_area(phys_to_virt(part->start), part->size, DMA_FROM_DEVICE); + outer_inv_range(part->start, part->start + part->size); + + ++part; + size_total += descriptor->block_array[i].size; + DBG_MSG(6, + ("UMP memory created with VCM. addr 0x%x, size: 0x%x\n", + descriptor->block_array[i].addr, + descriptor->block_array[i].size)); + } + + descriptor->size_bytes = size_total; + descriptor->nr_blocks = num_blocks; + descriptor->ctx = NULL; + + info->num_vcm_blocks += num_blocks; + return 1; +} + +/* + * Free specified UMP memory + */ +static void ump_vcm_free(void *ctx, ump_dd_mem * descriptor) +{ + struct ump_vcm *ump_vcm; + vcm_allocator *info; + + BUG_ON(!descriptor); + BUG_ON(!ctx); + + ump_vcm = (struct ump_vcm*)descriptor->backend_info; + info = (vcm_allocator*)ctx; + + BUG_ON(descriptor->nr_blocks > info->num_vcm_blocks); + + if (down_interruptible(&info->mutex)) { + DBG_MSG(1, ("Failed to get mutex in ump_vcm_free\n")); + return; + } + + DBG_MSG(5, ("Releasing %lu VCM pages\n", descriptor->nr_blocks)); + + info->num_vcm_blocks -= descriptor->nr_blocks; + + up(&info->mutex); + + DBG_MSG(6, ("Freeing physical page by VCM\n")); + vcm_destroy_binding(ump_vcm->vcm_res); + ump_vcm->vcm = NULL; + ump_vcm->vcm_res = NULL; + + kfree(ump_vcm); + vfree(descriptor->block_array); +} + +static void *vcm_res_get(ump_dd_mem *mem, void *args) +{ + struct ump_vcm *ump_vcm; + enum vcm_dev_id vcm_id; + + ump_vcm = (struct ump_vcm*)mem->backend_info; + vcm_id = (enum vcm_dev_id)args; + + if (vcm_reservation_in_vcm + (vcm_find_vcm(vcm_id), ump_vcm->vcm_res) + == S5PVCM_RES_NOT_IN_VCM) + return NULL; + else + return ump_vcm->vcm_res; +} + +static void vcm_attr_set(ump_dd_mem *mem, void *args) +{ + struct ump_vcm *ump_vcm, *ump_vcmh; + + ump_vcm = (struct ump_vcm*)args; + + ump_vcmh = kmalloc(sizeof(struct ump_vcm), GFP_KERNEL); + if (NULL == ump_vcmh) + { + return; + } + + ump_vcmh->dev_id = ump_vcm->dev_id; + ump_vcmh->vcm = ump_vcm->vcm; + ump_vcmh->vcm_res = ump_vcm->vcm_res; + + mem->backend_info= (void*)ump_vcmh; + + return; +} diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h new file mode 100644 index 0000000..c1ead0d --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_kernel_memory_backend_vcm.h + */ + +#ifndef __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ +#define __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ + +#include "ump_kernel_memory_backend.h" + +ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation); + +#endif /* __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c b/drivers/media/video/samsung/ump/linux/ump_memory_backend.c new file mode 100644 index 0000000..d067cfe --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_memory_backend.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include /* kernel module definitions */ +#include /* request_mem_region */ + +#include "arch/config.h" /* Configuration for current platform. The symlink for arch is set by Makefile */ + +#include "ump_osk.h" +#include "ump_kernel_common.h" +#include "ump_kernel_memory_backend_os.h" +#include "ump_kernel_memory_backend_dedicated.h" + +/* Configure which dynamic memory allocator to use */ +int ump_backend = ARCH_UMP_BACKEND_DEFAULT; +module_param(ump_backend, int, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_backend, "0 = dedicated memory backend (default), 1 = OS memory backend"); + +/* The base address of the memory block for the dedicated memory backend */ +unsigned int ump_memory_address = ARCH_UMP_MEMORY_ADDRESS_DEFAULT; +module_param(ump_memory_address, uint, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_memory_address, "The physical address to map for the dedicated memory backend"); + +/* The size of the memory block for the dedicated memory backend */ +unsigned int ump_memory_size = ARCH_UMP_MEMORY_SIZE_DEFAULT; +module_param(ump_memory_size, uint, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_memory_size, "The size of fixed memory to map in the dedicated memory backend"); + +ump_memory_backend* ump_memory_backend_create ( void ) +{ + ump_memory_backend * backend = NULL; + + /* Create the dynamic memory allocator backend */ + if (0 == ump_backend) + { + DBG_MSG(2, ("Using dedicated memory backend\n")); + + DBG_MSG(2, ("Requesting dedicated memory: 0x%08x, size: %u\n", ump_memory_address, ump_memory_size)); + /* Ask the OS if we can use the specified physical memory */ + if (NULL == request_mem_region(ump_memory_address, ump_memory_size, "UMP Memory")) + { + MSG_ERR(("Failed to request memory region (0x%08X - 0x%08X). Is Mali DD already loaded?\n", ump_memory_address, ump_memory_address + ump_memory_size - 1)); + return NULL; + } + backend = ump_block_allocator_create(ump_memory_address, ump_memory_size); + } + else if (1 == ump_backend) + { + DBG_MSG(2, ("Using OS memory backend, allocation limit: %d\n", ump_memory_size)); + backend = ump_os_memory_backend_create(ump_memory_size); + } +#ifdef CONFIG_UMP_VCM_ALLOC + else if (2 == ump_backend) + { + DBG_MSG(2, ("Using VCM memory backend, allocation limit: %d\n", ump_memory_size)); + backend = ump_vcm_memory_backend_create(ump_memory_size); + } +#endif + + return backend; +} + +void ump_memory_backend_destroy( void ) +{ + if (0 == ump_backend) + { + DBG_MSG(2, ("Releasing dedicated memory: 0x%08x\n", ump_memory_address)); + release_mem_region(ump_memory_address, ump_memory_size); + } +} diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c b/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c new file mode 100644 index 0000000..b117d99 --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_osk_atomics.c + * Implementation of the OS abstraction layer for the UMP kernel device driver + */ + +#include "ump_osk.h" +#include + +int _ump_osk_atomic_dec_and_read( _mali_osk_atomic_t *atom ) +{ + return atomic_dec_return((atomic_t *)&atom->u.val); +} + +int _ump_osk_atomic_inc_and_read( _mali_osk_atomic_t *atom ) +{ + return atomic_inc_return((atomic_t *)&atom->u.val); +} diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c b/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c new file mode 100644 index 0000000..8ae169a --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c @@ -0,0 +1,485 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_osk_memory.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +/* needed to detect kernel version specific code */ +#include + +#include "ump_osk.h" +#include "ump_uk_types.h" +#include "ump_ukk.h" +#include "ump_kernel_common.h" +#include /* kernel module definitions */ +#include +#include +#include +#include + +#include +#include /* to verify pointers from user space */ +#include +#include + +typedef struct ump_vma_usage_tracker +{ + atomic_t references; + ump_memory_allocation *descriptor; +} ump_vma_usage_tracker; + +static void ump_vma_open(struct vm_area_struct * vma); +static void ump_vma_close(struct vm_area_struct * vma); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +static int ump_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf); +#else +static unsigned long ump_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address); +#endif + +static struct vm_operations_struct ump_vm_ops = +{ + .open = ump_vma_open, + .close = ump_vma_close, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + .fault = ump_cpu_page_fault_handler +#else + .nopfn = ump_cpu_page_fault_handler +#endif +}; + +/* + * Page fault for VMA region + * This should never happen since we always map in the entire virtual memory range. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +static int ump_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf) +#else +static unsigned long ump_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + void __user * address; + address = vmf->virtual_address; +#endif + MSG_ERR(("Page-fault in UMP memory region caused by the CPU\n")); + MSG_ERR(("VMA: 0x%08lx, virtual address: 0x%08lx\n", (unsigned long)vma, address)); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + return VM_FAULT_SIGBUS; +#else + return NOPFN_SIGBUS; +#endif +} + +static void ump_vma_open(struct vm_area_struct * vma) +{ + ump_vma_usage_tracker * vma_usage_tracker; + int new_val; + + vma_usage_tracker = (ump_vma_usage_tracker*)vma->vm_private_data; + BUG_ON(NULL == vma_usage_tracker); + + new_val = atomic_inc_return(&vma_usage_tracker->references); + + DBG_MSG(4, ("VMA open, VMA reference count incremented. VMA: 0x%08lx, reference count: %d\n", (unsigned long)vma, new_val)); +} + +static void ump_vma_close(struct vm_area_struct * vma) +{ + ump_vma_usage_tracker * vma_usage_tracker; + _ump_uk_unmap_mem_s args; + int new_val; + + vma_usage_tracker = (ump_vma_usage_tracker*)vma->vm_private_data; + BUG_ON(NULL == vma_usage_tracker); + + new_val = atomic_dec_return(&vma_usage_tracker->references); + + DBG_MSG(4, ("VMA close, VMA reference count decremented. VMA: 0x%08lx, reference count: %d\n", (unsigned long)vma, new_val)); + + if (0 == new_val) + { + ump_memory_allocation * descriptor; + + descriptor = vma_usage_tracker->descriptor; + + args.ctx = descriptor->ump_session; + args.cookie = descriptor->cookie; + args.mapping = descriptor->mapping; + args.size = descriptor->size; + + args._ukk_private = NULL; /** @note unused */ + + DBG_MSG(4, ("No more VMA references left, releasing UMP memory\n")); + _ump_ukk_unmap_mem( & args ); + + /* vma_usage_tracker is free()d by _ump_osk_mem_mapregion_term() */ + } +} + +_mali_osk_errcode_t _ump_osk_mem_mapregion_init( ump_memory_allocation * descriptor ) +{ + ump_vma_usage_tracker * vma_usage_tracker; + struct vm_area_struct *vma; + + if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; + + vma_usage_tracker = kmalloc(sizeof(ump_vma_usage_tracker), GFP_KERNEL); + if (NULL == vma_usage_tracker) + { + DBG_MSG(1, ("Failed to allocate memory for ump_vma_usage_tracker in _mali_osk_mem_mapregion_init\n")); + return -_MALI_OSK_ERR_FAULT; + } + + vma = (struct vm_area_struct*)descriptor->process_mapping_info; + if (NULL == vma ) + { + kfree(vma_usage_tracker); + return _MALI_OSK_ERR_FAULT; + } + + vma->vm_private_data = vma_usage_tracker; + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED; + + if (0==descriptor->is_cached) + { + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + } + DBG_MSG(3, ("Mapping with page_prot: 0x%x\n", vma->vm_page_prot )); + + /* Setup the functions which handle further VMA handling */ + vma->vm_ops = &ump_vm_ops; + + /* Do the va range allocation - in this case, it was done earlier, so we copy in that information */ + descriptor->mapping = (void __user*)vma->vm_start; + + atomic_set(&vma_usage_tracker->references, 1); /*this can later be increased if process is forked, see ump_vma_open() */ + vma_usage_tracker->descriptor = descriptor; + + return _MALI_OSK_ERR_OK; +} + +void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor ) +{ + struct vm_area_struct* vma; + ump_vma_usage_tracker * vma_usage_tracker; + + if (NULL == descriptor) return; + + /* Linux does the right thing as part of munmap to remove the mapping + * All that remains is that we remove the vma_usage_tracker setup in init() */ + vma = (struct vm_area_struct*)descriptor->process_mapping_info; + + vma_usage_tracker = vma->vm_private_data; + + /* We only get called if mem_mapregion_init succeeded */ + kfree(vma_usage_tracker); + return; +} + +_mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descriptor, u32 offset, u32 * phys_addr, unsigned long size ) +{ + struct vm_area_struct *vma; + _mali_osk_errcode_t retval; + + if (NULL == descriptor) return _MALI_OSK_ERR_FAULT; + + vma = (struct vm_area_struct*)descriptor->process_mapping_info; + + if (NULL == vma ) return _MALI_OSK_ERR_FAULT; + + retval = remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, (*phys_addr) >> PAGE_SHIFT, size, vma->vm_page_prot) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK;; + + DBG_MSG(4, ("Mapping virtual to physical memory. ID: %u, vma: 0x%08lx, virtual addr:0x%08lx, physical addr: 0x%08lx, size:%lu, prot:0x%x, vm_flags:0x%x RETVAL: 0x%x\n", + ump_dd_secure_id_get(descriptor->handle), + (unsigned long)vma, + (unsigned long)(vma->vm_start + offset), + (unsigned long)*phys_addr, + size, + (unsigned int)vma->vm_page_prot, vma->vm_flags, retval)); + + return retval; +} + +static u32 _ump_osk_virt_to_phys_start(ump_dd_mem * mem, u32 start, u32 address, int *index) +{ + int i; + u32 offset = address - start; + ump_dd_physical_block *block; + u32 sum = 0; + + for (i=0; inr_blocks; i++) { + block = &mem->block_array[i]; + sum += block->size; + if (sum > offset) { + *index = i; + DBG_MSG(3, ("_ump_osk_virt_to_phys : index : %d, virtual 0x%x, phys 0x%x\n", i, address, (u32)block->addr + offset - (sum -block->size))); + return (u32)block->addr + offset - (sum -block->size); + } + } + + return _MALI_OSK_ERR_FAULT; +} + +static u32 _ump_osk_virt_to_phys_end(ump_dd_mem * mem, u32 start, u32 address, int *index) +{ + int i; + u32 offset = address - start; + ump_dd_physical_block *block; + u32 sum = 0; + + for (i=0; inr_blocks; i++) { + block = &mem->block_array[i]; + sum += block->size; + if (sum >= offset) { + *index = i; + DBG_MSG(3, ("_ump_osk_virt_to_phys : index : %d, virtual 0x%x, phys 0x%x\n", i, address, (u32)block->addr + offset - (sum -block->size))); + return (u32)block->addr + offset - (sum -block->size); + } + } + + return _MALI_OSK_ERR_FAULT; +} + +static void _ump_osk_msync_with_virt(ump_dd_mem * mem, ump_uk_msync_op op, u32 start, u32 address, u32 size) +{ + int start_index, end_index; + u32 start_p, end_p; + + DBG_MSG(3, ("Cache flush with user virtual address. start : 0x%x, end : 0x%x, address 0x%x, size 0x%x\n", start, start+mem->size_bytes, address, size)); + + start_p = _ump_osk_virt_to_phys_start(mem, start, address, &start_index); + end_p = _ump_osk_virt_to_phys_end(mem, start, address+size, &end_index); + + if (start_index==end_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) + outer_flush_range(start_p, end_p); + else + outer_clean_range(start_p, end_p); + } else { + ump_dd_physical_block *block; + int i; + + for (i=start_index; i<=end_index; i++) { + block = &mem->block_array[i]; + + if (i == start_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(start_p, block->addr+block->size); + } else { + outer_clean_range(start_p, block->addr+block->size); + } + } + else if (i == end_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(block->addr, end_p); + } else { + outer_clean_range(block->addr, end_p); + } + break; + } + else { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(block->addr, block->addr+block->size); + } else { + outer_clean_range(block->addr, block->addr+block->size); + } + } + } + } + return; +} + +static void level1_cache_flush_all(void) +{ + DBG_MSG(4, ("UMP[xx] Flushing complete L1 cache\n")); + __cpuc_flush_kern_all(); +} + +void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data ) +{ + int i; + const void *start_v, *end_v; + + /* Flush L1 using virtual address, the entire range in one go. + * Only flush if user space process has a valid write mapping on given address. */ + if( (mem) && (virt!=NULL) && (access_ok(VERIFY_WRITE, virt, size)) ) + { + start_v = (void *)virt; + end_v = (void *)(start_v + size - 1); + /* There is no dmac_clean_range, so the L1 is always flushed, + * also for UMP_MSYNC_CLEAN. */ + if (size >= SZ_64K) + flush_all_cpu_caches(); + else + dmac_flush_range(start_v, end_v); + + DBG_MSG(3, ("UMP[%02u] Flushing CPU L1 Cache. Cpu address: %x-%x\n", mem->secure_id, start_v,end_v)); + } + else + { + if (session_data) + { + if (op == _UMP_UK_MSYNC_FLUSH_L1 ) + { + DBG_MSG(4, ("UMP Pending L1 cache flushes: %d\n", session_data->has_pending_level1_cache_flush)); + session_data->has_pending_level1_cache_flush = 0; + level1_cache_flush_all(); + return; + } + else + { + if (session_data->cache_operations_ongoing) + { + session_data->has_pending_level1_cache_flush++; + DBG_MSG(4, ("UMP[%02u] Defering the L1 flush. Nr pending:%d\n", mem->secure_id, session_data->has_pending_level1_cache_flush) ); + } + else + { + /* Flushing the L1 cache for each switch_user() if ump_cache_operations_control(START) is not called */ + level1_cache_flush_all(); + } + } + } + else + { + DBG_MSG(4, ("Unkown state %s %d\n", __FUNCTION__, __LINE__)); + level1_cache_flush_all(); + } + } + + if ( NULL == mem ) return; + + if ( mem->size_bytes==size) + { + DBG_MSG(3, ("UMP[%02u] Flushing CPU L2 Cache\n",mem->secure_id)); + } + else + { + DBG_MSG(3, ("UMP[%02u] Flushing CPU L2 Cache. Blocks:%u, TotalSize:%u. FlushSize:%u Offset:0x%x FirstPaddr:0x%08x\n", + mem->secure_id, mem->nr_blocks, mem->size_bytes, size, offset, mem->block_array[0].addr)); + } + + + /* Flush L2 using physical addresses, block for block. */ + if ((virt!=NULL) && (mem->size_bytes >= SZ_1M)) { + if (op == _UMP_UK_MSYNC_CLEAN) + outer_clean_all(); + else if ((op == _UMP_UK_MSYNC_INVALIDATE) || (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE)) + outer_flush_all(); + return; + } + + for (i=0 ; i < mem->nr_blocks; i++) + { + u32 start_p, end_p; + ump_dd_physical_block *block; + block = &mem->block_array[i]; + + if(offset >= block->size) + { + offset -= block->size; + continue; + } + + if(offset) + { + start_p = (u32)block->addr + offset; + /* We'll zero the offset later, after using it to calculate end_p. */ + } + else + { + start_p = (u32)block->addr; + } + + if(size < block->size - offset) + { + end_p = start_p + size - 1; + size = 0; + } + else + { + if(offset) + { + end_p = start_p + (block->size - offset - 1); + size -= block->size - offset; + offset = 0; + } + else + { + end_p = start_p + block->size - 1; + size -= block->size; + } + } + + switch(op) + { + case _UMP_UK_MSYNC_CLEAN: + outer_clean_range(start_p, end_p); + break; + case _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE: + outer_flush_range(start_p, end_p); + break; + case _UMP_UK_MSYNC_INVALIDATE: + outer_inv_range(start_p, end_p); + break; + default: + break; + } + + if(0 == size) + { + /* Nothing left to flush. */ + break; + } + } + + return; +} + +void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + ump_vma_usage_tracker * vma_usage_tracker; + ump_memory_allocation *descriptor; + ump_dd_handle handle; + + DBG_MSG(3, ("_ump_osk_mem_mapregion_get: vaddr 0x%08lx\n", vaddr)); + + down_read(&mm->mmap_sem); + vma = find_vma(mm, vaddr); + up_read(&mm->mmap_sem); + if(!vma) + { + DBG_MSG(3, ("Not found VMA\n")); + *mem = NULL; + return; + } + DBG_MSG(4, ("Get vma: 0x%08lx vma->vm_start: 0x%08lx\n", (unsigned long)vma, vma->vm_start)); + + vma_usage_tracker = (struct ump_vma_usage_tracker*)vma->vm_private_data; + if(vma_usage_tracker == NULL) + { + DBG_MSG(3, ("Not found vma_usage_tracker\n")); + *mem = NULL; + return; + } + + descriptor = (struct ump_memory_allocation*)vma_usage_tracker->descriptor; + handle = (ump_dd_handle)descriptor->handle; + + DBG_MSG(3, ("Get handle: 0x%08lx\n", handle)); + *mem = (ump_dd_mem*)handle; +} + diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_misc.c b/drivers/media/video/samsung/ump/linux/ump_osk_misc.c new file mode 100644 index 0000000..3be6fed --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_osk_misc.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_osk_misc.c + * Implementation of the OS abstraction layer for the UMP kernel device driver + */ + + +#include "ump_osk.h" + +#include +#include "ump_kernel_linux.h" + +/* is called from ump_kernel_constructor in common code */ +_mali_osk_errcode_t _ump_osk_init( void ) +{ + if (0 != ump_kernel_device_initialize()) + { + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _ump_osk_term( void ) +{ + ump_kernel_device_terminate(); + return _MALI_OSK_ERR_OK; +} diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c new file mode 100644 index 0000000..a6691ed --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_ukk_wrappers.c + * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls for the reference implementation + */ + + +#include /* user space access */ + +#include "ump_osk.h" +#include "ump_uk_types.h" +#include "ump_ukk.h" +#include "ump_kernel_common.h" + +#if defined(CONFIG_ION_EXYNOS) || defined(CONFIG_DMA_SHARED_BUFFER) +#include +#include "ump_kernel_interface_ref_drv.h" +#include "mali_osk_list.h" +#ifdef CONFIG_ION_EXYNOS +#include +#include "../../../../../gpu/ion/ion_priv.h" +extern struct ion_device *ion_exynos; +extern struct ion_client *ion_client_ump; +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER +#include +#endif +#endif + +/* + * IOCTL operation; Allocate UMP memory + */ +int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_allocate_s user_interaction; + _mali_osk_errcode_t err; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_allocate()\n")); + return -ENOTTY; + } + + /* Copy the user space memory to kernel space (so we safely can read it) */ + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_allocate()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + err = _ump_ukk_allocate( &user_interaction ); + if( _MALI_OSK_ERR_OK != err ) + { + DBG_MSG(1, ("_ump_ukk_allocate() failed in ump_ioctl_allocate()\n")); + return map_errcode(err); + } + user_interaction.ctx = NULL; + + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + /* If the copy fails then we should release the memory. We can use the IOCTL release to accomplish this */ + _ump_uk_release_s release_args; + + MSG_ERR(("copy_to_user() failed in ump_ioctl_allocate()\n")); + + release_args.ctx = (void *) session_data; + release_args.secure_id = user_interaction.secure_id; + + err = _ump_ukk_release( &release_args ); + if(_MALI_OSK_ERR_OK != err) + { + MSG_ERR(("_ump_ukk_release() also failed when trying to release newly allocated memory in ump_ioctl_allocate()\n")); + } + + return -EFAULT; + } + + return 0; /* success */ +} +#ifdef CONFIG_ION_EXYNOS +/* + * IOCTL operation; Import fd to UMP memory + */ +int ump_ion_import_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_ion_import_s user_interaction; + ump_dd_handle *ump_handle; + ump_dd_physical_block * blocks; + unsigned long num_blocks; + struct ion_handle *ion_hnd; + struct scatterlist *sg; + struct scatterlist *sg_ion; + unsigned long i = 0; + + ump_session_memory_list_element * session_memory_element = NULL; + if (ion_client_ump==NULL) + ion_client_ump = ion_client_create(ion_exynos, -1, "ump"); + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_allocate()\n")); + return -ENOTTY; + } + + /* Copy the user space memory to kernel space (so we safely can read it) */ + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_allocate()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + /* translate fd to secure ID*/ + ion_hnd = ion_import_fd(ion_client_ump, user_interaction.ion_fd); + sg_ion = ion_map_dma(ion_client_ump,ion_hnd); + + blocks = (ump_dd_physical_block*)_mali_osk_malloc(sizeof(ump_dd_physical_block)*1024); + + if (NULL == blocks) { + MSG_ERR(("Failed to allocate blocks in ump_ioctl_allocate()\n")); + return -ENOMEM; + } + + sg = sg_ion; + do { + blocks[i].addr = sg_phys(sg); + blocks[i].size = sg_dma_len(sg); + i++; + if (i>=1024) { + _mali_osk_free(blocks); + MSG_ERR(("ion_import fail() in ump_ioctl_allocate()\n")); + return -EFAULT; + } + sg = sg_next(sg); + } while(sg); + + num_blocks = i; + + /* Initialize the session_memory_element, and add it to the session object */ + session_memory_element = _mali_osk_calloc( 1, sizeof(ump_session_memory_list_element)); + + if (NULL == session_memory_element) + { + _mali_osk_free(blocks); + DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n")); + return -EFAULT; + } + + ump_handle = ump_dd_handle_create_from_phys_blocks(blocks, num_blocks); + if (UMP_DD_HANDLE_INVALID == ump_handle) + { + _mali_osk_free(session_memory_element); + _mali_osk_free(blocks); + DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n")); + return -EFAULT; + } + + session_memory_element->mem = (ump_dd_mem*)ump_handle; + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_add(&(session_memory_element->list), &(session_data->list_head_session_memory_list)); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + ion_unmap_dma(ion_client_ump,ion_hnd); + ion_free(ion_client_ump, ion_hnd); + + _mali_osk_free(blocks); + + user_interaction.secure_id = ump_dd_secure_id_get(ump_handle); + user_interaction.size = ump_dd_size_get(ump_handle); + user_interaction.ctx = NULL; + + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + /* If the copy fails then we should release the memory. We can use the IOCTL release to accomplish this */ + + MSG_ERR(("copy_to_user() failed in ump_ioctl_allocate()\n")); + + return -EFAULT; + } + return 0; /* success */ +} +#endif + +#ifdef CONFIG_DMA_SHARED_BUFFER +int ump_dmabuf_import_wrapper(u32 __user *argument, + struct ump_session_data *session_data) +{ + ump_session_memory_list_element *session = NULL; + struct ump_uk_dmabuf ump_dmabuf; + ump_dd_handle *ump_handle; + ump_dd_physical_block *blocks; + struct dma_buf_attachment *attach; + struct dma_buf *dma_buf; + struct sg_table *sgt; + struct scatterlist *sgl; + unsigned long block_size; + /* FIXME */ + struct device dev; + unsigned int i = 0, npages; + int ret; + + /* Sanity check input parameters */ + if (!argument || !session_data) { + MSG_ERR(("NULL parameter.\n")); + return -EINVAL; + } + + if (copy_from_user(&ump_dmabuf, argument, + sizeof(struct ump_uk_dmabuf))) { + MSG_ERR(("copy_from_user() failed.\n")); + return -EFAULT; + } + + dma_buf = dma_buf_get(ump_dmabuf.fd); + if (IS_ERR(dma_buf)) + return PTR_ERR(dma_buf); + + /* + * check whether dma_buf imported already exists or not. + * + * TODO + * if already imported then dma_buf_put() should be called + * and then just return dma_buf imported. + */ + + attach = dma_buf_attach(dma_buf, &dev); + if (IS_ERR(attach)) { + ret = PTR_ERR(attach); + goto err_dma_buf_put; + } + + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); + goto err_dma_buf_detach; + } + + npages = sgt->nents; + + /* really need? */ + ump_dmabuf.ctx = (void *)session_data; + + block_size = sizeof(ump_dd_physical_block) * npages; + + blocks = (ump_dd_physical_block *)_mali_osk_malloc(block_size); + sgl = sgt->sgl; + + while (i < npages) { + blocks[i].addr = sg_phys(sgl); + blocks[i].size = sg_dma_len(sgl); + sgl = sg_next(sgl); + i++; + } + + /* + * Initialize the session memory list element, and add it + * to the session object + */ + session = _mali_osk_calloc(1, sizeof(*session)); + if (!session) { + DBG_MSG(1, ("Failed to allocate session.\n")); + ret = -EFAULT; + goto err_free_block; + } + + ump_handle = ump_dd_handle_create_from_phys_blocks(blocks, i); + if (UMP_DD_HANDLE_INVALID == ump_handle) { + DBG_MSG(1, ("Failed to create ump handle.\n")); + ret = -EFAULT; + goto err_free_session; + } + + session->mem = (ump_dd_mem *)ump_handle; + + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_add(&(session->list), + &(session_data->list_head_session_memory_list)); + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_free(blocks); + + ump_dmabuf.ump_handle = (uint32_t)ump_handle; + ump_dmabuf.size = ump_dd_size_get(ump_handle); + + if (copy_to_user(argument, &ump_dmabuf, + sizeof(struct ump_uk_dmabuf))) { + MSG_ERR(("copy_to_user() failed.\n")); + ret = -EFAULT; + goto err_release_ump_handle; + } + + return 0; + +err_release_ump_handle: + ump_dd_reference_release(ump_handle); +err_free_session: + _mali_osk_free(session); +err_free_block: + _mali_osk_free(blocks); + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); +err_dma_buf_detach: + dma_buf_detach(dma_buf, attach); +err_dma_buf_put: + dma_buf_put(dma_buf); + return ret; +} +#endif diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h new file mode 100644 index 0000000..416a584 --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_ukk_wrappers.h + * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls for the reference implementation + */ + +#ifndef __UMP_UKK_REF_WRAPPERS_H__ +#define __UMP_UKK_REF_WRAPPERS_H__ + +#include +#include "ump_kernel_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data * session_data); + +#ifdef CONFIG_ION_EXYNOS +int ump_ion_import_wrapper(u32 __user * argument, struct ump_session_data * session_data); +#endif + +#ifdef CONFIG_DMA_SHARED_BUFFER +int ump_dmabuf_import_wrapper(u32 __user *argument, + struct ump_session_data *session_data); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __UMP_UKK_REF_WRAPPERS_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c b/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c new file mode 100644 index 0000000..780f311 --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_ukk_wrappers.c + * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls + */ + +#include /* user space access */ + +#include "ump_osk.h" +#include "ump_uk_types.h" +#include "ump_ukk.h" +#include "ump_kernel_common.h" + +/* + * IOCTL operation; Negotiate version of IOCTL API + */ +int ump_get_api_version_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_api_version_s version_info; + _mali_osk_errcode_t err; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_get_api_version()\n")); + return -ENOTTY; + } + + /* Copy the user space memory to kernel space (so we safely can read it) */ + if (0 != copy_from_user(&version_info, argument, sizeof(version_info))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_get_api_version()\n")); + return -EFAULT; + } + + version_info.ctx = (void*) session_data; + err = _ump_uku_get_api_version( &version_info ); + if( _MALI_OSK_ERR_OK != err ) + { + MSG_ERR(("_ump_uku_get_api_version() failed in ump_ioctl_get_api_version()\n")); + return map_errcode(err); + } + + version_info.ctx = NULL; + + /* Copy ouput data back to user space */ + if (0 != copy_to_user(argument, &version_info, sizeof(version_info))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_get_api_version()\n")); + return -EFAULT; + } + + return 0; /* success */ +} + + +/* + * IOCTL operation; Release reference to specified UMP memory. + */ +int ump_release_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_release_s release_args; + _mali_osk_errcode_t err; + + /* Sanity check input parameters */ + if (NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_release()\n")); + return -ENOTTY; + } + + /* Copy the user space memory to kernel space (so we safely can read it) */ + if (0 != copy_from_user(&release_args, argument, sizeof(release_args))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_get_api_version()\n")); + return -EFAULT; + } + + release_args.ctx = (void*) session_data; + err = _ump_ukk_release( &release_args ); + if( _MALI_OSK_ERR_OK != err ) + { + MSG_ERR(("_ump_ukk_release() failed in ump_ioctl_release()\n")); + return map_errcode(err); + } + + + return 0; /* success */ +} + +/* + * IOCTL operation; Return size for specified UMP memory. + */ +int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_size_get_s user_interaction; + _mali_osk_errcode_t err; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_size_get()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + err = _ump_ukk_size_get( &user_interaction ); + if( _MALI_OSK_ERR_OK != err ) + { + MSG_ERR(("_ump_ukk_size_get() failed in ump_ioctl_size_get()\n")); + return map_errcode(err); + } + + user_interaction.ctx = NULL; + + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_size_get()\n")); + return -EFAULT; + } + + return 0; /* success */ +} + +/* + * IOCTL operation; Do cache maintenance on specified UMP memory. + */ +int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_msync_s user_interaction; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_msync()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + _ump_ukk_msync( &user_interaction ); + + user_interaction.ctx = NULL; + + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_msync()\n")); + return -EFAULT; + } + + return 0; /* success */ +} +int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_cache_operations_control_s user_interaction; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_cache_operations_control()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + _ump_ukk_cache_operations_control((_ump_uk_cache_operations_control_s*) &user_interaction ); + + user_interaction.ctx = NULL; + +#if 0 /* No data to copy back */ + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_cache_operations_control()\n")); + return -EFAULT; + } +#endif + return 0; /* success */ +} + +int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_switch_hw_usage_s user_interaction; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + _ump_ukk_switch_hw_usage( &user_interaction ); + + user_interaction.ctx = NULL; + +#if 0 /* No data to copy back */ + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } +#endif + return 0; /* success */ +} + +int ump_lock_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_lock_s user_interaction; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + _ump_ukk_lock( &user_interaction ); + + user_interaction.ctx = NULL; + +#if 0 /* No data to copy back */ + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } +#endif + + return 0; /* success */ +} + +int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data * session_data) +{ + _ump_uk_unlock_s user_interaction; + + /* Sanity check input parameters */ + if (NULL == argument || NULL == session_data) + { + MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); + return -ENOTTY; + } + + if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) + { + MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } + + user_interaction.ctx = (void *) session_data; + + _ump_ukk_unlock( &user_interaction ); + + user_interaction.ctx = NULL; + +#if 0 /* No data to copy back */ + if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) + { + MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n")); + return -EFAULT; + } +#endif + + return 0; /* success */ +} diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h b/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h new file mode 100644 index 0000000..e87a903 --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file ump_ukk_wrappers.h + * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls + */ + +#ifndef __UMP_UKK_WRAPPERS_H__ +#define __UMP_UKK_WRAPPERS_H__ + +#include +#include "ump_kernel_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + + +int ump_get_api_version_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_release_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_lock_wrapper(u32 __user * argument, struct ump_session_data * session_data); +int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data * session_data); + + + + +#ifdef __cplusplus +} +#endif + + + +#endif /* __UMP_UKK_WRAPPERS_H__ */ -- cgit v1.1 From 60a7e62198bc5446610007533214d80c03e57d3f Mon Sep 17 00:00:00 2001 From: Ketut Putu Kumajaya Date: Fri, 26 Sep 2014 11:57:55 +0700 Subject: s3cfb_ops: Attempt to fix LPM (off charging mode) graphics issue Change-Id: I4af44a979e5ab3b9d29888ce178ea9c0f71432b3 --- drivers/video/samsung/s3cfb_ops.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/video/samsung/s3cfb_ops.c b/drivers/video/samsung/s3cfb_ops.c index 8d5739d..0bcd529 100644 --- a/drivers/video/samsung/s3cfb_ops.c +++ b/drivers/video/samsung/s3cfb_ops.c @@ -53,6 +53,10 @@ #include #endif +#if defined(CONFIG_MACH_KONA) || defined(CONFIG_MACH_TAB3) || defined(CONFIG_MACH_T0) +extern unsigned int lpcharge; +#endif + struct s3c_platform_fb *to_fb_plat(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -1078,6 +1082,15 @@ int s3cfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb) } #endif +#if defined(CONFIG_MACH_KONA) || defined(CONFIG_MACH_TAB3) || defined(CONFIG_MACH_T0) + if (lpcharge) { + /* support LPM (off charging mode) display based on FBIOPAN_DISPLAY */ + s3cfb_check_var(var, fb); + s3cfb_set_par(fb); + s3cfb_enable_window(fbdev, win->id); + } +#endif + if (var->yoffset + var->yres > var->yres_virtual) { dev_err(fbdev->dev, "invalid yoffset value\n"); if (win->id == pdata->default_win) -- cgit v1.1 From 4ca83ffe8bbf82acb088bb7af50a952c95d1d09e Mon Sep 17 00:00:00 2001 From: Ketut Putu Kumajaya Date: Fri, 26 Sep 2014 21:02:14 +0700 Subject: samsung_battery: Attemp to fix LPM (off charging mode) with KitKat bootloader Change-Id: Icbc7f7b0d6e52485eadc2d801224e01eaffe29e1 --- drivers/battery/samsung_battery.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/battery/samsung_battery.c b/drivers/battery/samsung_battery.c index 8bc5c7f..d3f45f2 100644 --- a/drivers/battery/samsung_battery.c +++ b/drivers/battery/samsung_battery.c @@ -58,15 +58,27 @@ static void battery_error_control(struct battery_info *info); unsigned int lpcharge; static int battery_get_lpm_state(char *str) { - get_option(&str, &lpcharge); + if (strncmp(str, "1", 1) == 0) + lpcharge = 1; + pr_info("%s: Low power charging mode: %d\n", __func__, lpcharge); return lpcharge; } __setup("lpcharge=", battery_get_lpm_state); -#if defined(CONFIG_RTC_ALARM_BOOT) + +/* For KitKat bootloader compatibility */ +static int bootloader_get_lpm_state(char *str) +{ + if (strncmp(str, "charger", 7) == 0) + lpcharge = 1; + + pr_info("%s: Low power charging mode: %d\n", __func__, lpcharge); + + return lpcharge; +} +__setup("androidboot.mode=", bootloader_get_lpm_state); EXPORT_SYMBOL(lpcharge); -#endif /* Cable type from charger or adc */ static int battery_get_cable(struct battery_info *info) -- cgit v1.1 From 22cbf2cfb211cef2e493c5984d237d0509bf98ce Mon Sep 17 00:00:00 2001 From: Leon Winter Date: Thu, 30 Oct 2014 11:05:03 +0100 Subject: otg: when removing ED from readyQ also set flag The driver keeps track of the "is this endpoint in the list" state with the redundant flag ".is_in_transfer_ready_q". It should therefore always be sync with the .next and .prev of the readyq_list list: struct ed *ed; otg_list_head *qlist = (typeof qlist) ed->readyq_list; (qlist->prev == LIST_POISON2 || qlist->next == LIST_POISON1) == !ed->ed_status.is_in_transfer_ready_q; Should both properties be not in sync, bad things can happen. All code paths in driver rely on the flag and then call list operations. If the flag suggests the entry is in the list, otg_list_pop () will be called. When the entry however is not in the list, the members .prev and .next are poisoned and an attempt to do list operations on them results into a NULL (or rather an invalid address which is the poison) pointer dereference. Such a fault would then trigger a kernel panic and the device rebooting. In real life this happens when disconnecting USB devices frequently, especially when in operation (transfering data while detaching). While in most positions in the code, it was taken care to keep both properties, the flag and the list entry state, consistent, one position was left out, which is addressed with this patch. Extensive testing shows that the device would crash easily and in a reproducable manner without the patch but does not show any faults with the patch applied. Change-Id: I80f3a8e7d866c699ddcd1c61b04d956e39d2197c --- drivers/usb/host/shost/shost_readyq.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/shost/shost_readyq.c b/drivers/usb/host/shost/shost_readyq.c index 9e41da5..b2ccea0 100644 --- a/drivers/usb/host/shost/shost_readyq.c +++ b/drivers/usb/host/shost/shost_readyq.c @@ -202,6 +202,7 @@ static int get_ed_from_ready_q(struct ed **get_ed, bool is_periodic) } else { otg_list_pop(qlist); periodic_trans_ready_q.entity_num--; + get_ed[0]->ed_status.is_in_transfer_ready_q = false; } return USB_ERR_SUCCESS; @@ -230,6 +231,7 @@ static int get_ed_from_ready_q(struct ed **get_ed, bool is_periodic) } else { otg_list_pop(qlist); nonperiodic_trans_ready_q.entity_num--; + get_ed[0]->ed_status.is_in_transfer_ready_q = false; } return USB_ERR_SUCCESS; } else -- cgit v1.1 From 339b2cb7d4876f4acf7389c38fc85cc5e35801ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Tue, 9 Sep 2014 11:20:19 +0200 Subject: bcmdhd wireless: Fix off by one in initialization. An sprintf in dhd_write_macaddr wrote a rogue null byte after the buffer. Found with CONFIG_CC_STACKPROTECTOR=y (idea of Lanchon at XDA Developers [1]). [1]: http://forum.xda-developers.com/showthread.php?p=55306602 Panic, on a Samsung Galaxy S2 i9100, was: <0>[ 26.412257] c1 Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: bf013a2c <0>[ 26.412315] c1 <4>[ 26.412334] c1 Backtrace: <4>[ 26.412382] c1 [] (dump_backtrace+0x0/0x10c) from [] (dump_stack+0x18/0x1c) <4>[ 26.412439] c1 r6:e211e820 r5:c0ed4760 r4:c0f5c940 r3:271aed5c <4>[ 26.412496] c1 [] (dump_stack+0x0/0x1c) from [] (panic+0x80/0x1ac) <4>[ 26.412561] c1 [] (panic+0x0/0x1ac) from [] (init_oops_id+0x0/0x58) <4>[ 26.412613] c1 r3:271aed5c r2:271aed00 r1:bf013a2c r0:c0cb8880 <4>[ 26.412663] c1 r7:e273bc32 <4>[ 26.412742] c1 [] (__stack_chk_fail+0x0/0x1c) from [] (dhd_write_macaddr+0x2e4/0x310 [dhd]) <4>[ 26.412864] c1 [] (dhd_write_macaddr+0x0/0x310 [dhd]) from [] (dhd_bus_start+0x1a4/0x2e0 [dhd]) <4>[ 26.412985] c1 [] (dhd_bus_start+0x0/0x2e0 [dhd]) from [] (dhdsdio_probe+0x4a4/0x72c [dhd]) <4>[ 26.413097] c1 [] (dhdsdio_probe+0x0/0x72c [dhd]) from [] (bcmsdh_probe+0xf8/0x150 [dhd]) <4>[ 26.413206] c1 [] (bcmsdh_probe+0x0/0x150 [dhd]) from [] (bcmsdh_sdmmc_probe+0x54/0xbc [dhd]) <4>[ 26.413304] c1 [] (bcmsdh_sdmmc_probe+0x0/0xbc [dhd]) from [] (sdio_bus_probe+0xfc/0x108) <4>[ 26.413368] c1 r5:e2d97000 r4:e2d97008 <4>[ 26.413414] c1 [] (sdio_bus_probe+0x0/0x108) from [] (driver_probe_device+0x94/0x1a8) <4>[ 26.413474] c1 r8:00000000 r7:bf067414 r6:e2d9703c r5:c0f6ddb8 r4:e2d97008 <4>[ 26.413531] c1 r3:c09a7eec <4>[ 26.413563] c1 [] (driver_probe_device+0x0/0x1a8) from [] (__driver_attach+0x94/0x98) <4>[ 26.413624] c1 r7:e2e631e0 r6:e2d9703c r5:bf067414 r4:e2d97008 <4>[ 26.413683] c1 [] (__driver_attach+0x0/0x98) from [] (bus_for_each_dev+0x4c/0x94) <4>[ 26.413742] c1 r6:c0896878 r5:bf067414 r4:00000000 r3:c0896878 <4>[ 26.413799] c1 [] (bus_for_each_dev+0x0/0x94) from [] (driver_attach+0x24/0x28) <4>[ 26.413857] c1 r6:c0f02af0 r5:bf067414 r4:bf067414 <4>[ 26.413904] c1 [] (driver_attach+0x0/0x28) from [] (bus_add_driver+0x180/0x250) <4>[ 26.413970] c1 [] (bus_add_driver+0x0/0x250) from [] (driver_register+0x80/0x150) <4>[ 26.414037] c1 [] (driver_register+0x0/0x150) from [] (sdio_register_driver+0x2c/0x30) <4>[ 26.414131] c1 [] (sdio_register_driver+0x0/0x30) from [] (sdio_function_init+0x3c/0x8c [dhd]) <4>[ 26.414244] c1 [] (sdio_function_init+0x0/0x8c [dhd]) from [] (bcmsdh_register+0x1c/0x24 [dhd]) <4>[ 26.414311] c1 r5:00000004 r4:bf06a3c4 <4>[ 26.414398] c1 [] (bcmsdh_register+0x0/0x24 [dhd]) from [] (dhd_bus_register+0x24/0x48 [dhd]) <4>[ 26.414515] c1 [] (dhd_bus_register+0x0/0x48 [dhd]) from [] (init_module+0x18c/0x284 [dhd]) <4>[ 26.414610] c1 [] (init_module+0x0/0x284 [dhd]) from [] (do_one_initcall+0x128/0x1a8) <4>[ 26.414683] c1 [] (do_one_initcall+0x0/0x1a8) from [] (sys_init_module+0xdf8/0x1b1c) <4>[ 26.414756] c1 [] (sys_init_module+0x0/0x1b1c) from [] (ret_fast_syscall+0x0/0x30) <2>[ 26.414861] c0 CPU0: stopping <4>[ 26.414886] c0 Backtrace: <4>[ 26.414920] c0 [] (dump_backtrace+0x0/0x10c) from [] (dump_stack+0x18/0x1c) <4>[ 26.414977] c0 r6:c0d54000 r5:c0eb5d08 r4:00000006 r3:271aed5c <4>[ 26.415039] c0 [] (dump_stack+0x0/0x1c) from [] (do_IPI+0x258/0x29c) <4>[ 26.415102] c0 [] (do_IPI+0x0/0x29c) from [] (__irq_svc+0x80/0x130) <4>[ 26.415156] c0 Exception stack(0xc0d55ef0 to 0xc0d55f38) <4>[ 26.415197] c0 5ee0: 3b9ac9ff 540deacd 01c99e53 00072679 <4>[ 26.415258] c0 5f00: c0f5a468 00000000 c0d54000 00000000 c1b540a8 412fc091 00000000 c0d55f64 <4>[ 26.415317] c0 5f20: 540deacd c0d55f38 c06aa768 c065bd78 20000013 ffffffff <4>[ 26.415380] c0 [] (exynos4_enter_idle+0x0/0x174) from [] (cpuidle_idle_call+0xa4/0x120) <4>[ 26.415442] c0 r7:00000000 r6:00000001 r5:c0f815ac r4:c1b540b8 <4>[ 26.415498] c0 [] (cpuidle_idle_call+0x0/0x120) from [] (cpu_idle+0xc4/0x100) <4>[ 26.415554] c0 r8:4000406a r7:c0ba09a8 r6:c0f59ec4 r5:c0ebd8c4 r4:c0d54000 <4>[ 26.415610] c0 r3:c099a7ec <4>[ 26.415641] c0 [] (cpu_idle+0x0/0x100) from [] (rest_init+0x8c/0xa4) <4>[ 26.415694] c0 r7:c1b51180 r6:c0f59e00 r5:00000002 r4:c0d54000 <4>[ 26.415752] c0 [] (rest_init+0x0/0xa4) from [] (start_kernel+0x2dc/0x330) <4>[ 26.415807] c0 r5:c063d944 r4:c0eb5d34 <4>[ 26.415845] c0 [] (start_kernel+0x0/0x330) from [<40008044>] (0x40008044) Change-Id: Iaa907383e196fdf787ae4660977b58de79212de1 --- drivers/net/wireless/bcmdhd/dhd_custom_sec.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c index be129b5..9a29891 100755 --- a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c +++ b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c @@ -324,6 +324,8 @@ void get_customized_country_code(char *country_iso_code, wl_country_t *cspec) #define CIS_BUF_SIZE 512 #endif /* BCM4330_CHIP */ +#define MACBUFFER_SZ (sizeof("00:11:22:33:44:55\n")) + #ifdef READ_MACADDR int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac) { @@ -1100,7 +1102,7 @@ int dhd_write_macaddr(struct ether_addr *mac) char *filepath_efs = MACINFO_EFS; struct file *fp_mac = NULL; - char buf[18] = {0}; + char buf[MACBUFFER_SZ] = {0}; mm_segment_t oldfs = {0}; int ret = -1; int retry_count = 0; @@ -1123,7 +1125,7 @@ startwrite: if (fp_mac->f_mode & FMODE_WRITE) { ret = fp_mac->f_op->write(fp_mac, (const char *)buf, - sizeof(buf), &fp_mac->f_pos); + sizeof(buf) - 1 /* skip null byte */, &fp_mac->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Mac address [%s] Failed to" " write into File: %s\n", buf, filepath_data)); @@ -1163,7 +1165,7 @@ startwrite: if (fp_mac->f_mode & FMODE_WRITE) { ret = fp_mac->f_op->write(fp_mac, (const char *)buf, - sizeof(buf), &fp_mac->f_pos); + sizeof(buf) - 1 /* skip null byte */, &fp_mac->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Mac address [%s] Failed to" " write into File: %s\n", buf, filepath_efs)); -- cgit v1.1 From 0ef5a06bceb576a1135770111577f7700fe1ef93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Tue, 9 Sep 2014 14:07:11 +0200 Subject: bcmdhd wireless: Fix more off by one errors. These were not detected by the stack protector, either because the functions where not called or because the corruption hits a local variable. Change-Id: I385c81b133ee09c28df56597df3fb25d9c063f43 --- drivers/net/wireless/bcmdhd/dhd_custom_sec.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c index 9a29891..3dbfc9f 100755 --- a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c +++ b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c @@ -330,10 +330,10 @@ void get_customized_country_code(char *country_iso_code, wl_country_t *cspec) int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac) { struct file *fp = NULL; - char macbuffer[18] = {0}; + char macbuffer[MACBUFFER_SZ] = {0}; mm_segment_t oldfs = {0}; char randommac[3] = {0}; - char buf[18] = {0}; + char buf[MACBUFFER_SZ] = {0}; char *filepath_efs = MACINFO_EFS; int ret = 0; @@ -358,7 +358,7 @@ start_readmac: if (fp->f_mode & FMODE_WRITE) { ret = fp->f_op->write(fp, (const char *)macbuffer, - sizeof(macbuffer), &fp->f_pos); + sizeof(macbuffer) - 1 /* skip null byte */, &fp->f_pos); if (ret < 0) DHD_ERROR(("[WIFI]MAC address [%s] Failed to write into File: %s\n", macbuffer, filepath_efs)); @@ -425,7 +425,7 @@ int dhd_write_rdwr_macaddr(struct ether_addr *mac) char *filepath_data = MACINFO; char *filepath_efs = MACINFO_EFS; struct file *fp_mac = NULL; - char buf[18] = {0}; + char buf[MACBUFFER_SZ] = {0}; mm_segment_t oldfs = {0}; int ret = -1; @@ -447,7 +447,7 @@ int dhd_write_rdwr_macaddr(struct ether_addr *mac) if (fp_mac->f_mode & FMODE_WRITE) { ret = fp_mac->f_op->write(fp_mac, (const char *)buf, - sizeof(buf), &fp_mac->f_pos); + sizeof(buf) - 1 /* skip null byte */, &fp_mac->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Mac address [%s] Failed" " to write into File: %s\n", buf, filepath_data)); @@ -469,7 +469,7 @@ int dhd_write_rdwr_macaddr(struct ether_addr *mac) if (fp_mac->f_mode & FMODE_WRITE) { ret = fp_mac->f_op->write(fp_mac, (const char *)buf, - sizeof(buf), &fp_mac->f_pos); + sizeof(buf) - 1 /* skip null byte */, &fp_mac->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Mac address [%s] Failed" " to write into File: %s\n", buf, filepath_efs)); @@ -490,9 +490,9 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, { struct file *fp_mac = NULL; struct file *fp_nvm = NULL; - char macbuffer[18] = {0}; + char macbuffer[MACBUFFER_SZ] = {0}; char randommac[3] = {0}; - char buf[18] = {0}; + char buf[MACBUFFER_SZ] = {0}; char *filepath_data = MACINFO; char *filepath_efs = MACINFO_EFS; #ifdef CONFIG_TARGET_LOCALE_NA @@ -502,7 +502,7 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, #endif char cur_mac[128] = {0}; char dummy_mac[ETHER_ADDR_LEN] = {0x00, 0x90, 0x4C, 0xC5, 0x12, 0x38}; - char cur_macbuffer[18] = {0}; + char cur_macbuffer[MACBUFFER_SZ] = {0}; int ret = -1; g_imac_flag = MACADDR_NONE; @@ -696,10 +696,10 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, int dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac) { struct file *fp = NULL; - char macbuffer[18] = {0}; + char macbuffer[MACBUFFER_SZ] = {0}; mm_segment_t oldfs = {0}; char randommac[3] = {0}; - char buf[18] = {0}; + char buf[MACBUFFER_SZ] = {0}; char *filepath_efs = MACINFO_EFS; int is_zeromac = 0; int ret = 0; @@ -732,7 +732,7 @@ int dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac) if (fp->f_mode & FMODE_WRITE) { ret = fp->f_op->write(fp, (const char *)macbuffer, - sizeof(macbuffer), &fp->f_pos); + sizeof(macbuffer) - 1 /* skip null byte */, &fp->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Mac address [%s]" " Failed to write into File:" @@ -830,7 +830,7 @@ static void dhd_dump_cis(const unsigned char *buf, int size) int i; for (i = 0; i < size; i++) { DHD_ERROR(("%02X ", buf[i])); - if ((i % 15) == 15) DHD_ERROR(("\n")); + if ((i % 15) == 15) DHD_ERROR(("\n")); /* FIXME: Will always be false */ } DHD_ERROR(("\n")); } -- cgit v1.1 From a3732c055167df76ff7afedcaa59b76be52bb567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Tue, 9 Sep 2014 14:58:30 +0200 Subject: bcmdhd wireless: Fix sprintf/sscanf format strings. %X is int. This is too wide for the chars used there, so use %hhx instead. Avoid undefined pointer casts from char* to unsigned int* in sscanf calls. Also use the already defined MACF and update it with %hhx instead of typing this long format string all over again. Add MACF_U which is the same as MACF but with uppercase hex (%hhX instead of %hhx). Change-Id: Idd2465e0d05bca9b05566abeec05a5ad59a577ad --- drivers/net/wireless/bcmdhd/bcmsdspi_linux.c | 2 +- drivers/net/wireless/bcmdhd/dhd_common.c | 2 +- drivers/net/wireless/bcmdhd/dhd_custom_sec.c | 106 +++++++++++++------------ drivers/net/wireless/bcmdhd/include/bcmutils.h | 3 +- drivers/net/wireless/bcmdhd/wl_iw.c | 2 +- 5 files changed, 60 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c index 9e3922b..6d1d495 100755 --- a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c @@ -355,7 +355,7 @@ hexdump(char *pfx, unsigned char *msg, int msglen) for (i = 0; i < msglen; i++, col++) { if (col % 16 == 0) strcpy(buf, pfx); - sprintf(buf + strlen(buf), "%02x", msg[i]); + sprintf(buf + strlen(buf), "%02hhx", msg[i]); if ((col + 1) % 16 == 0) printf("%s\n", buf); else diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index c4ac414..6a25fc2 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -760,7 +760,7 @@ wl_show_host_event(wl_event_msg_t *event, void *event_data) datalen = ntoh32(event->datalen); /* debug dump of event messages */ - snprintf(eabuf, sizeof(eabuf), "%02x:%02x:%02x:%02x:%02x:%02x", + snprintf(eabuf, sizeof(eabuf), MACF, (uchar)event->addr.octet[0]&0xff, (uchar)event->addr.octet[1]&0xff, (uchar)event->addr.octet[2]&0xff, diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c index 3dbfc9f..7fab834 100755 --- a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c +++ b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c @@ -352,7 +352,7 @@ start_readmac: /* Generating the Random Bytes for 3 last octects of the MAC address */ get_random_bytes(randommac, 3); - sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n", + sprintf(macbuffer, "%02X:%02X:%02X:%02hhX:%02hhX:%02hhX\n", 0x00, 0x12, 0x34, randommac[0], randommac[1], randommac[2]); DHD_ERROR(("[WIFI]The Random Generated MAC ID: %s\n", macbuffer)); @@ -388,10 +388,10 @@ start_readmac: } if (ret) - sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", - (unsigned int *)&(mac->octet[0]), (unsigned int *)&(mac->octet[1]), - (unsigned int *)&(mac->octet[2]), (unsigned int *)&(mac->octet[3]), - (unsigned int *)&(mac->octet[4]), (unsigned int *)&(mac->octet[5])); + sscanf(buf, MACF_U, + &(mac->octet[0]), &(mac->octet[1]), + &(mac->octet[2]), &(mac->octet[3]), + &(mac->octet[4]), &(mac->octet[5])); else DHD_ERROR(("dhd_bus_start: Reading from the '%s' returns 0 bytes\n", filepath_efs)); @@ -432,7 +432,7 @@ int dhd_write_rdwr_macaddr(struct ether_addr *mac) if ((g_imac_flag != MACADDR_COB) && (g_imac_flag != MACADDR_MOD)) return 0; - sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X\n", + sprintf(buf, MACF_U "\n", mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3], mac->octet[4], mac->octet[5]); @@ -521,11 +521,12 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, } else { DHD_ERROR(("MAC (OTP) : " "[%02X:%02X:%02X:%02X:%02X:%02X] \r\n", - cur_mac[0], cur_mac[1], cur_mac[2], cur_mac[3], - cur_mac[4], cur_mac[5])); + (unsigned)cur_mac[0], (unsigned)cur_mac[1], + (unsigned)cur_mac[2], (unsigned)cur_mac[3], + (unsigned)cur_mac[4], (unsigned)cur_mac[5])); } - sprintf(cur_macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n", + sprintf(cur_macbuffer, MACF_U "\n", cur_mac[0], cur_mac[1], cur_mac[2], cur_mac[3], cur_mac[4], cur_mac[5]); @@ -554,13 +555,13 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, " Trying Random MAC.\n")); g_imac_flag = MACADDR_MOD_RANDOM; } else { - sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", - (unsigned int *)&(mac->octet[0]), - (unsigned int *)&(mac->octet[1]), - (unsigned int *)&(mac->octet[2]), - (unsigned int *)&(mac->octet[3]), - (unsigned int *)&(mac->octet[4]), - (unsigned int *)&(mac->octet[5])); + sscanf(buf, MACF_U, + &(mac->octet[0]), + &(mac->octet[1]), + &(mac->octet[2]), + &(mac->octet[3]), + &(mac->octet[4]), + &(mac->octet[5])); /* current MAC address is same as previous one */ if (memcmp(cur_mac, mac->octet, ETHER_ADDR_LEN) == 0) { g_imac_flag = MACADDR_NONE; @@ -603,13 +604,13 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, " Trying Random MAC.\n")); g_imac_flag = MACADDR_MOD_RANDOM; } else { - sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", - (unsigned int *)&(mac->octet[0]), - (unsigned int *)&(mac->octet[1]), - (unsigned int *)&(mac->octet[2]), - (unsigned int *)&(mac->octet[3]), - (unsigned int *)&(mac->octet[4]), - (unsigned int *)&(mac->octet[5])); + sscanf(buf, MACF_U, + &(mac->octet[0]), + &(mac->octet[1]), + &(mac->octet[2]), + &(mac->octet[3]), + &(mac->octet[4]), + &(mac->octet[5])); /* current MAC address is same as previous one */ if (memcmp(cur_mac, mac->octet, ETHER_ADDR_LEN) == 0) { g_imac_flag = MACADDR_NONE; @@ -644,13 +645,13 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, (strncmp(buf, "00:00:00:00:00:00", 17) == 0)) { g_imac_flag = MACADDR_COB_RANDOM; } else { - sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", - (unsigned int *)&(mac->octet[0]), - (unsigned int *)&(mac->octet[1]), - (unsigned int *)&(mac->octet[2]), - (unsigned int *)&(mac->octet[3]), - (unsigned int *)&(mac->octet[4]), - (unsigned int *)&(mac->octet[5])); + sscanf(buf, MACF_U, + &(mac->octet[0]), + &(mac->octet[1]), + &(mac->octet[2]), + &(mac->octet[3]), + &(mac->octet[4]), + &(mac->octet[5])); /* Writing Newly generated MAC ID to the Dongle */ if (_dhd_set_mac_address(dhd, 0, mac) == 0) { DHD_INFO(("%s: MACID is overwritten\n", @@ -667,18 +668,18 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, if ((g_imac_flag == MACADDR_COB_RANDOM) || (g_imac_flag == MACADDR_MOD_RANDOM)) { get_random_bytes(randommac, 3); - sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n", + sprintf(macbuffer, "%02X:%02X:%02X:%02hhX:%02hhX:%02hhX\n", 0x60, 0xd0, 0xa9, randommac[0], randommac[1], randommac[2]); DHD_ERROR(("[WIFI] The Random Generated MAC ID : %s\n", macbuffer)); - sscanf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X", - (unsigned int *)&(mac->octet[0]), - (unsigned int *)&(mac->octet[1]), - (unsigned int *)&(mac->octet[2]), - (unsigned int *)&(mac->octet[3]), - (unsigned int *)&(mac->octet[4]), - (unsigned int *)&(mac->octet[5])); + sscanf(macbuffer, MACF_U, + &(mac->octet[0]), + &(mac->octet[1]), + &(mac->octet[2]), + &(mac->octet[3]), + &(mac->octet[4]), + &(mac->octet[5])); if (_dhd_set_mac_address(dhd, 0, mac) == 0) { DHD_INFO(("%s: MACID is overwritten\n", __FUNCTION__)); g_imac_flag = MACADDR_COB; @@ -723,7 +724,7 @@ int dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac) */ get_random_bytes(randommac, 3); - sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n", + sprintf(macbuffer, "%02X:%02X:%02X:%02hhX:%02hhX:%02hhX\n", 0x60, 0xd0, 0xa9, randommac[0], randommac[1], randommac[2]); DHD_ERROR(("[WIFI] The Random Generated MAC ID : %s\n", @@ -763,13 +764,13 @@ int dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac) } if (ret) - sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", - (unsigned int *)&(mac->octet[0]), - (unsigned int *)&(mac->octet[1]), - (unsigned int *)&(mac->octet[2]), - (unsigned int *)&(mac->octet[3]), - (unsigned int *)&(mac->octet[4]), - (unsigned int *)&(mac->octet[5])); + sscanf(buf, MACF_U, + &(mac->octet[0]), + &(mac->octet[1]), + &(mac->octet[2]), + &(mac->octet[3]), + &(mac->octet[4]), + &(mac->octet[5])); else DHD_INFO(("dhd_bus_start: Reading from the" " '%s' returns 0 bytes\n", filepath_efs)); @@ -829,7 +830,7 @@ static void dhd_dump_cis(const unsigned char *buf, int size) { int i; for (i = 0; i < size; i++) { - DHD_ERROR(("%02X ", buf[i])); + DHD_ERROR(("%02X ", (unsigned)buf[i])); if ((i % 15) == 15) DHD_ERROR(("\n")); /* FIXME: Will always be false */ } DHD_ERROR(("\n")); @@ -1056,11 +1057,14 @@ int dhd_check_module_mac(dhd_pub_t *dhd, struct ether_addr *mac) if (ret < 0) { DHD_TRACE(("%s: CIS reading failed, err=%d\n", __func__, ret)); - sprintf(otp_mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X\n", + sprintf(otp_mac_buf, MACF_U "\n", mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3], mac->octet[4], mac->octet[5]); DHD_ERROR(("%s: Check module mac by legacy FW : %02X:%02X:%02X\n", - __func__, mac->octet[0], mac->octet[4], mac->octet[5])); + __func__, + (unsigned)mac->octet[0], + (unsigned)mac->octet[4], + (unsigned)mac->octet[5])); } else { unsigned char mac_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #ifdef DUMP_CIS @@ -1073,7 +1077,7 @@ int dhd_check_module_mac(dhd_pub_t *dhd, struct ether_addr *mac) mac_id[4] = cis_buf[CIS_MAC_OFFSET + 4]; mac_id[5] = cis_buf[CIS_MAC_OFFSET + 5]; - sprintf(otp_mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X\n", + sprintf(otp_mac_buf, MACF_U "\n", mac_id[0], mac_id[1], mac_id[2], mac_id[3], mac_id[4], mac_id[5]); DHD_ERROR(("[WIFI]mac_id is setted from OTP \n")); @@ -1109,7 +1113,7 @@ int dhd_write_macaddr(struct ether_addr *mac) startwrite: - sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X\n", + sprintf(buf, MACF_U "\n", mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3], mac->octet[4], mac->octet[5]); diff --git a/drivers/net/wireless/bcmdhd/include/bcmutils.h b/drivers/net/wireless/bcmdhd/include/bcmutils.h index 1b21327..90f8f40 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmutils.h +++ b/drivers/net/wireless/bcmdhd/include/bcmutils.h @@ -669,7 +669,8 @@ extern void *_bcmutils_dummy_fn; #define CRC32_GOOD_VALUE 0xdebb20e3 -#define MACF "%02x:%02x:%02x:%02x:%02x:%02x" +#define MACF "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx" +#define MACF_U "%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX" /* upper case hex */ #define ETHERP_TO_MACF(ea) ((struct ether_addr *) (ea))->octet[0], \ ((struct ether_addr *) (ea))->octet[1], \ ((struct ether_addr *) (ea))->octet[2], \ diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index b2acd6a..16a8911 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -2423,7 +2423,7 @@ wl_iw_set_encodeext( for (j = 0; j < (WSEC_MAX_PSK_LEN / 2); j++) { - sprintf(charptr, "%02x", iwe->key[j]); + sprintf(charptr, "%02hhx", iwe->key[j]); charptr += 2; } len = strlen(keystring); -- cgit v1.1 From 24dc35886c58b4ffe52eb3f61fda20fa8b50a9d0 Mon Sep 17 00:00:00 2001 From: sbrissen Date: Tue, 24 Jun 2014 10:49:58 -0400 Subject: smdk4412: update exynos ion Taken from GT-N7100_SEA_KK_Opensource Change-Id: Ieb6da81ab9472c8e0a8114138b96b727b5f24fc7 --- drivers/gpu/ion/exynos/exynos_ion.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/ion/exynos/exynos_ion.c b/drivers/gpu/ion/exynos/exynos_ion.c index 100f055..9779777 100644 --- a/drivers/gpu/ion/exynos/exynos_ion.c +++ b/drivers/gpu/ion/exynos/exynos_ion.c @@ -487,8 +487,10 @@ static int ion_exynos_contig_heap_allocate(struct ion_heap *heap, } buffer->flags = flags; +#ifdef CONFIG_ION_EXYNOS_CONTIGHEAP_DEBUG printk(KERN_INFO "[ION] alloc: 0x%x\n", (unsigned int)buffer->priv_phys); +#endif return 0; } @@ -503,8 +505,10 @@ static void ion_exynos_contig_heap_free(struct ion_buffer *buffer) #endif ret = cma_free(buffer->priv_phys); +#ifdef CONFIG_ION_EXYNOS_CONTIGHEAP_DEBUG printk(KERN_INFO "[ION] free: 0x%x, [0x%x]\n", (unsigned int)buffer->priv_phys, ret); +#endif } static int ion_exynos_contig_heap_phys(struct ion_heap *heap, @@ -544,6 +548,8 @@ static int ion_exynos_contig_heap_map_user(struct ion_heap *heap, if (buffer->flags & ION_EXYNOS_NONCACHE_MASK) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + /* Set User Permission */ + vma->vm_page_prot = pte_mkdirty(vma->vm_page_prot); return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot); -- cgit v1.1