From 3d14fed9bfc96722202fd9c0bc6f9733d10a0def Mon Sep 17 00:00:00 2001 From: James Chambers <05jchambers@gmail.com> Date: Sat, 24 Sep 2022 17:04:48 -0600 Subject: [PATCH] Fix high-speed SD mode, trim support, faster boot --- .../kernel/arch/arm/mach-rda/devices.c | 6 +- .../kernel/drivers/video/backlight/rda_bl.c | 383 ++++++++++++++++++ .../kernel/include/rda/tgt_ap_board_config.h | 108 +++++ OrangePiRDA/scripts/lib/build_image.sh | 2 +- OrangePiRDA/scripts/lib/distributions.sh | 281 +++++++------ .../kernel/include/rda/tgt_ap_board_config.h | 108 +++++ README.md | 9 +- 7 files changed, 757 insertions(+), 140 deletions(-) create mode 100755 OrangePiRDA/kernel/drivers/video/backlight/rda_bl.c create mode 100755 OrangePiRDA/kernel/include/rda/tgt_ap_board_config.h create mode 100644 OrangePiRDA/uboot/kernel/include/rda/tgt_ap_board_config.h diff --git a/OrangePiRDA/kernel/arch/arm/mach-rda/devices.c b/OrangePiRDA/kernel/arch/arm/mach-rda/devices.c index 51216b7..0725505 100755 --- a/OrangePiRDA/kernel/arch/arm/mach-rda/devices.c +++ b/OrangePiRDA/kernel/arch/arm/mach-rda/devices.c @@ -394,11 +394,7 @@ static struct rda_mmc_device_data rda_mmc0_data[] = { .mclk_adj = _TGT_AP_SDMMC1_MCLK_ADJ, .ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34, -#ifdef CONFIG_MACH_RDA8850E - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED, -#else - .caps = MMC_CAP_4_BIT_DATA, -#endif /* CONFIG_MACH_RDA8850E */ + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_UHS_DDR50 | MMC_CAP_SD_HIGHSPEED | MMC_CAP_ERASE | MMC_CAP_1_8V_DDR, #ifdef _TGT_AP_GPIO_MMC_HOTPLUG .det_pin = _TGT_AP_GPIO_MMC_HOTPLUG, diff --git a/OrangePiRDA/kernel/drivers/video/backlight/rda_bl.c b/OrangePiRDA/kernel/drivers/video/backlight/rda_bl.c new file mode 100755 index 0000000..56e724b --- /dev/null +++ b/OrangePiRDA/kernel/drivers/video/backlight/rda_bl.c @@ -0,0 +1,383 @@ +/* + * rda_bl.c - A driver for controlling backlight of RDA + * + * Copyright (C) 2013-2014 RDA Microelectronics Inc. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif /* CONFIG_HAS_EARLYSUSPEND */ + + +extern int rda_fb_register_client(struct notifier_block * nb); +extern int rda_fb_unregister_client(struct notifier_block *nb); + +#define RDA_FB_TIMEOUT 1000 + +struct rda_bl { + struct backlight_device *bldev; + struct platform_device *pdev; + + struct regulator *bl_reg; + + struct rda_bl_device_data *pdata; + + int sleep_level; + +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_ops; +#endif /* CONFIG_HAS_EARLYSUSPEND */ + struct mutex pending_lock; + int fb_count; + + struct notifier_block fb_notifier; + struct completion fb_done; + + struct work_struct bl_work; +}; + +/* + * The current table of backlight is a sub-table of its regulator. + * It can be as same as table of its regulator. + */ +static int bl_table[POWER_BL_NUM] = {0}; + +static int rda_bl_notifier_cb(struct notifier_block *self, unsigned long event, void *data) +{ + struct rda_bl *rda_bl = container_of(self, struct rda_bl, fb_notifier); + + if (event) { + mutex_lock(&rda_bl->pending_lock); + + if (rda_bl->fb_count < 0) { + mutex_unlock(&rda_bl->pending_lock); + return 0; + } + ++rda_bl->fb_count; + if (rda_bl->fb_count == 1) { + int boot_mode = rda_get_boot_mode(); + + if (boot_mode == BM_NORMAL) { + /* Waiting for LCD is ready. */ + msleep(200); + } + mutex_unlock(&rda_bl->pending_lock); + complete(&rda_bl->fb_done); + + return 0; + } + mutex_unlock(&rda_bl->pending_lock); + } else { + INIT_COMPLETION(rda_bl->fb_done); + rda_bl->fb_count = 0; + } + + return 0; +} + +static int rda_bl_set_intensity(struct backlight_device *bd) +{ + struct rda_bl *rda_bl = bl_get_data(bd); + int intensity = bd->props.brightness; + int tsize = ARRAY_SIZE(bl_table); + int index; + int ret; + unsigned long fb_timeout = 0; + unsigned long timeout_ret = 0; + int boot_mode = rda_get_boot_mode(); + + if (intensity < 0) { + index = 0; + } else { + if (rda_bl->pdata->min + intensity > rda_bl->pdata->max) { + index = rda_bl->pdata->max; + } else { + index = rda_bl->pdata->min + intensity; + } + + if (bd->props.state & BL_CORE_FBBLANK) { + index = 0; + } + } + + mutex_lock(&rda_bl->pending_lock); + if (rda_bl->fb_count == 0) { + mutex_unlock(&rda_bl->pending_lock); + if (boot_mode == BM_CHARGER) { + schedule_work(&rda_bl->bl_work); + return 0; + } + + fb_timeout = RDA_FB_TIMEOUT; + timeout_ret = wait_for_completion_timeout(&rda_bl->fb_done, + msecs_to_jiffies(fb_timeout)); + if (timeout_ret == 0) { + pr_err(" : fb doesn't transit frame, timeout(%ld ms)\n", fb_timeout); + } + mutex_lock(&rda_bl->pending_lock); + } else if (rda_bl->fb_count < 0) { + /* Do not enable backlight after suspend. */ + mutex_unlock(&rda_bl->pending_lock); + return 0; + } + mutex_unlock(&rda_bl->pending_lock); + + pr_debug("%s : write val = %d\n", __func__, index); + + if (boot_mode == BM_CHARGER) { + /* + * We need to wait for ready of lcd as charger mode. + */ + msleep(30); + } + + ret = regulator_set_voltage(rda_bl->bl_reg, bl_table[index], bl_table[tsize - 1]); + + return ret; +} + +static int rda_bl_get_intensity(struct backlight_device *bd) +{ + struct rda_bl *rda_bl = bl_get_data(bd); + int intensity; + int i; + int tsize = ARRAY_SIZE(bl_table); + int value; + + value = regulator_get_voltage(rda_bl->bl_reg); + + for (i = 0; i < tsize - 1; i++) { + if (bl_table[i] == value) { + break; + } + } + + intensity = i - rda_bl->pdata->min; + + pr_debug("%s : read val = %d\n", __func__, value); + + return intensity; +} + +static void rda_bl_work(struct work_struct *work) +{ + struct rda_bl *rda_bl = container_of(work, struct rda_bl, bl_work); + + rda_bl_set_intensity(rda_bl->bldev); +} + +static const struct backlight_ops rda_bl_ops = { + .get_brightness = rda_bl_get_intensity, + .update_status = rda_bl_set_intensity, +}; + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void rda_bl_early_suspend(struct early_suspend *h); +static void rda_bl_late_resume(struct early_suspend *h); +#endif /* CONFIG_HAS_EARLYSUSPEND */ + +static int rda_bl_probe(struct platform_device *pdev) +{ + struct backlight_properties props; + struct backlight_device *bldev; + struct rda_bl *rda_bl; + struct rda_bl_device_data *pdata; + int retval; + int i; + + pr_debug("call %s\n", __func__); + + /* Init table of voltage of backlight */ + for (i = 0; i < POWER_BL_NUM; i++) { + bl_table[i] = (i + 1) * 10000; + } + + rda_bl = kzalloc(sizeof(struct rda_bl), GFP_KERNEL); + if (!rda_bl) { + return -ENOMEM; + } + + rda_bl->pdev = pdev; + + pdata = (struct rda_bl_device_data *)pdev->dev.platform_data; + if (!pdata) { + retval = -ENODEV; + goto err_free_mem; + } + rda_bl->pdata = pdata; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = pdata->max - pdata->min; + + bldev = backlight_device_register(RDA_BL_DRV_NAME, + &pdev->dev, + rda_bl, + &rda_bl_ops, + &props); + if (IS_ERR(bldev)) { + retval = PTR_ERR(bldev); + goto err_free_mem; + } + + init_completion(&rda_bl->fb_done); + INIT_WORK(&rda_bl->bl_work, rda_bl_work); + + rda_bl->bldev = bldev; + + rda_bl->bl_reg = regulator_get(NULL, LDO_BACKLIGHT); + if (IS_ERR(rda_bl->bl_reg)) { + dev_err(&pdev->dev, "could not find regulator devices\n"); + retval = PTR_ERR(rda_bl->bl_reg); + goto err_free_bl_dev; + } + +#ifdef CONFIG_HAS_EARLYSUSPEND + rda_bl->early_ops.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 3; + rda_bl->early_ops.suspend = rda_bl_early_suspend; + rda_bl->early_ops.resume = rda_bl_late_resume; + + register_early_suspend(&rda_bl->early_ops); +#endif /* CONFIG_HAS_EARLYSUSPEND */ + + rda_bl->fb_notifier.notifier_call = rda_bl_notifier_cb; + rda_fb_register_client(&rda_bl->fb_notifier); + + platform_set_drvdata(pdev, rda_bl); + + /* Power up the backlight by default at middle intesity. */ + bldev->props.power = FB_BLANK_UNBLANK; + bldev->props.brightness = bldev->props.max_brightness / 2; + + mutex_init(&rda_bl->pending_lock); + rda_bl->fb_count = 0; + + /* Deferred to turn on backlight */ + schedule_work(&rda_bl->bl_work); + + return 0; + +err_free_bl_dev: + platform_set_drvdata(pdev, NULL); + backlight_device_unregister(bldev); + +err_free_mem: + if (rda_bl) { + kfree(rda_bl); + } + + return retval; +} + +static int __exit rda_bl_remove(struct platform_device *pdev) +{ + struct rda_bl *rda_bl = platform_get_drvdata(pdev); + + if (!rda_bl) { + return -EINVAL; + } + + regulator_put(rda_bl->bl_reg); + + rda_fb_unregister_client(&rda_bl->fb_notifier); + +#ifdef CONFIG_HAS_EARLYSUSPEND + unregister_early_suspend(&rda_bl->early_ops); +#endif /* CONFIG_HAS_EARLYSUSPEND */ + + backlight_device_unregister(rda_bl->bldev); + platform_set_drvdata(pdev, NULL); + + kfree(rda_bl); + + return 0; +} + +static void rda_bl_shutdown(struct platform_device *pdev) +{ + struct rda_bl *rda_bl = platform_get_drvdata(pdev); + int tsize = ARRAY_SIZE(bl_table); + + if (!rda_bl) { + return; + } + + regulator_set_voltage(rda_bl->bl_reg, bl_table[0], bl_table[tsize - 1]); + + return; +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void rda_bl_early_suspend(struct early_suspend *h) +{ + struct rda_bl *rda_bl = container_of(h, struct rda_bl, early_ops); + int tsize = ARRAY_SIZE(bl_table); + + if (!rda_bl) { + return; + } + + mutex_lock(&rda_bl->pending_lock); + rda_bl->fb_count = -1; + mutex_unlock(&rda_bl->pending_lock); + + regulator_set_voltage(rda_bl->bl_reg, bl_table[0], bl_table[tsize - 1]); +} + +static void rda_bl_late_resume(struct early_suspend *h) +{ + return; +} +#endif /* CONFIG_HAS_EARLYSUSPEND */ + +static struct platform_driver rda_bl_driver = { + .driver = { + .name = RDA_BL_DRV_NAME, + }, + .remove = __exit_p(rda_bl_remove), + .shutdown = rda_bl_shutdown, +}; + +static int __init rda_bl_init(void) +{ + return platform_driver_probe(&rda_bl_driver, rda_bl_probe); +} + +module_init(rda_bl_init); + +MODULE_AUTHOR("Tao Lei "); +MODULE_DESCRIPTION("RDA backlight driver"); +MODULE_LICENSE("GPL"); + diff --git a/OrangePiRDA/kernel/include/rda/tgt_ap_board_config.h b/OrangePiRDA/kernel/include/rda/tgt_ap_board_config.h new file mode 100755 index 0000000..307583a --- /dev/null +++ b/OrangePiRDA/kernel/include/rda/tgt_ap_board_config.h @@ -0,0 +1,108 @@ +#ifndef _TGT_AP_BOARD_CFG_H_ +#define _TGT_AP_BOARD_CFG_H_ + +#define EXTRA_BOOTCOMMAND "selinux=1 androidboot.selinux=permissive" + +/* MEM Size, in MBytes */ +#define _TGT_AP_MEM_SIZE 256 +#define _TGT_AP_VPU_MEM_SIZE 16 +#define _TGT_AP_CAM_MEM_SIZE 4 +#define _TGT_AP_GFX_MEM_SIZE 0 +#define _TGT_AP_OS_MEM_SIZE 236 + +#define _TGT_AP_GFX_MEM_BASE (_TGT_AP_OS_MEM_SIZE) +#define _TGT_AP_CAM_MEM_BASE (_TGT_AP_GFX_MEM_BASE + _TGT_AP_GFX_MEM_SIZE) +#define _TGT_AP_VPU_MEM_BASE (_TGT_AP_CAM_MEM_BASE + _TGT_AP_CAM_MEM_SIZE) + +#if ((_TGT_AP_VPU_MEM_BASE + _TGT_AP_VPU_MEM_SIZE) != _TGT_AP_MEM_SIZE) +#error "Invalid memory size configuration" +#endif + +/* usb otg function */ +#define _TGT_AP_USB_OTG_ENABLE + +/* NAND clock in MHz */ +#define _TGT_AP_NAND_CLOCK (30000000) + +/* SPI NAND clock in MHz: 64000000/80000000/100000000*/ +#define _TGT_AP_SPI_NAND_CLOCK (80000000) +/* SPI NAND read delay from flash to controller */ +/* need change according different HW board */ +#define _TGT_AP_SPI_NAND_READDELAY (4) + +/* ADMMC clock */ +#define _TGT_AP_SDMMC1_MAX_FREQ (50000000)/*3*/ +#define _TGT_AP_SDMMC1_MCLK_INV (1) +#define _TGT_AP_SDMMC1_MCLK_ADJ (1) +#define _TGT_AP_SDMMC2_MAX_FREQ (20000000)/*2*/ +#define _TGT_AP_SDMMC2_MCLK_INV (1) +#define _TGT_AP_SDMMC2_MCLK_ADJ (3) +#define _TGT_AP_SDMMC3_MAX_FREQ (30000000)/*3*/ +#define _TGT_AP_SDMMC3_MCLK_ADJ (0) + +/* I2C clocks */ +#define _TGT_AP_I2C0_CLOCK (100000) +#define _TGT_AP_I2C1_CLOCK (400000) +#define _TGT_AP_I2C2_CLOCK (200000) + +/* + * I2C addresses (Only keep non-RDA peripherals ) + */ +#define _TGT_AP_I2C_BUS_ID_TS (2) +# define _DEF_I2C_ADDR_TS_GSL168X (0x40) +# define _DEF_I2C_ADDR_TS_MSG2133 (0x26) + +# define _DEF_I2C_ADDR_TS_FT6x06 (0x38) +# define _DEF_I2C_ADDR_TS_IT7252 (0x46) +# define _DEF_I2C_ADDR_TS_GTP868 (0x5d) +# define _DEF_I2C_ADDR_TS_ICN831X (0x40) +/* NO need to define ADDR, this is determined by customer driver */ +/* #define _TGT_AP_I2C_ADDR_TS */ + +#define _TGT_AP_I2C_BUS_ID_GSENSOR (2) +# define _DEF_I2C_ADDR_GSENSOR_MMA7760 (0x4c) +# define _DEF_I2C_ADDR_GSENSOR_STK8312 (0x3d) +# define _DEF_I2C_ADDR_GSENSOR_MMA865X (0x1D) +/* Notice : when SA0=1, the MMA8452 slave address is 0x1D, and when SA0 = 0, + the address is 0x1C */ +# define _DEF_I2C_ADDR_GSENSOR_MMA845X (0x1D) +# define _DEF_I2C_ADDR_GSENSOR_MXC622X (0x15) + +/* gsensor position to lcd */ +#define _TGT_AP_GSENSOR_POSITION 1 + +/* NO need to define ADDR, this is determined by customer driver */ +/* #define _TGT_AP_I2C_ADDR_GSENSOR */ + +#define _TGT_AP_I2C_BUS_ID_LSENSOR (2) +# define _DEF_I2C_ADDR_LSENSOR_STK3x1x (0x48) +/* NO need to define ADDR, this is determined by customer driver */ +/* #define _TGT_AP_I2C_ADDR_LSENSOR */ + +#define _TGT_AP_I2C_BUS_ID_WIFI (0) +/* No Address defination, as rda5990 address is not changable */ + +#define _TGT_AP_I2C_BUS_ID_ATV (0) +/* No Address defination, as rda5888 address is not changable */ + +#define _TGT_AP_I2C_BUS_ID_CAM (0) + +/* LED defination */ +#define _TGT_AP_LED_RED (1) +/* # define _TGT_AP_LED_RED_KB (1) */ +# define _TGT_AP_LED_RED_FLASH (1) +/* #define _TGT_AP_LED_GREEN (1)*/ +/* # define _TGT_AP_LED_GREEN_KB (1) */ +/* # define _TGT_AP_LED_GREEN_FLASH (1) */ +#define _TGT_AP_LED_BLUE (1) +# define _TGT_AP_LED_BLUE_KB (1) +/*# define _TGT_AP_LED_BLUE_FLASH (1) */ + +/*#define _TGT_AP_BOARD_HAS_ATV*/ + +#define CONFIG_SDMMC_BOOT 1 +#define _TGT_AP_VIBRATOR_POWER_ON (1) +# define _TGT_AP_VIBRATOR_TIME (300) + +#endif /*_TGT_AP_BOARD_CFG_H_*/ + diff --git a/OrangePiRDA/scripts/lib/build_image.sh b/OrangePiRDA/scripts/lib/build_image.sh index c387944..236bf84 100755 --- a/OrangePiRDA/scripts/lib/build_image.sh +++ b/OrangePiRDA/scripts/lib/build_image.sh @@ -5,7 +5,7 @@ build_rk_image() { } build_rda_image() { - VER="v1.19" + VER="v1.20" IMAGENAME="Legendary_OrangePi_${BOARD}_${OS}_${DISTRO}_${IMAGETYPE}_${VER}" IMAGE="${BUILD}/images/$IMAGENAME.img" diff --git a/OrangePiRDA/scripts/lib/distributions.sh b/OrangePiRDA/scripts/lib/distributions.sh index c0dd6ff..8439b28 100755 --- a/OrangePiRDA/scripts/lib/distributions.sh +++ b/OrangePiRDA/scripts/lib/distributions.sh @@ -236,19 +236,159 @@ EOF do_chroot systemctl enable ssh-keygen } -add_bt_service() { - cat >"$DEST/lib/systemd/system/bt.service" <"$DEST/lib/systemd/system/rc-local.service" <"$DEST/etc/rc.local" <"$DEST/type-phase" <"$DEST/etc/fstab" <>${DEST}/etc/modules-load.d/modules.conf + # Remove default eth0 interface + rm -rf $DEST/etc/network/interfaces.d/eth0 + + cat >"$DEST/type-phase" <"$DEST/usr/sbin/bt_fixup.sh" <"$DEST/lib/systemd/system/bluetooth_fixup.service" <"$DEST/type-phase" <"$DEST/lib/systemd/system/gpio_fixup.service" <"$DEST/type-phase" <"$DEST/etc/udev/rules.d/99-gpio.rules" <"$DEST/etc/fstab" <>${DEST}/etc/modules-load.d/modules.conf - rm -rf $DEST/etc/network/interfaces.d/eth0 - cat >"$DEST/lib/systemd/system/rc-local.service" <"$DEST/etc/rc.local" <"$DEST/type-phase" <"$DEST/lib/systemd/system/gpio_fixup.service" <"$DEST/type-phase" <"$DEST/etc/udev/rules.d/99-gpio.rules" <"$DEST/usr/sbin/bt_fixup.sh" <"$DEST/lib/systemd/system/bluetooth_fixup.service" <"$DEST/type-phase" <
  • Adds ability to use the i96 as a HID device (mouse/keyboard emulation)
  • +
  • Fixed SD card port to support "High Speed" timing mode and 1.8V voltage (can be seen with sudo cat /sys/kernel/debug/mmc0/ios)
  • +
  • Fixed TRIM support (sudo fstrim -av)
  • Fixed notorious WiFi issues caused by missing crda package and no regulatory domain set (see first startup instructions to set REGDOMAIN)
  • Fixed Bluetooth and set it up to work at startup using bluetooth patchram utility
  • -
  • Fixed wireless MAC address changing each startup
  • +
  • Fixed wireless and bluetooth MAC addresses changing each startup
  • Fixed USB port to allow "High Speed" USB devices instead of locking them to "Full Speed"
  • Fixed buggy UART not resetting properly which often breaks copying/pasting through a serial terminal
  • Fixed sound issues that would prevent rebooting the system successfully after first startup
  • Fixed GPIO permissions errors on startup
  • -
  • Fixed orangepi user missing groups audio, bluetooth and netdev
  • +
  • Fixed orangepi user missing group membership for audio, bluetooth, netdev, gpio
  • First Startup Instructions

    @@ -39,7 +41,7 @@ You should first clone the OrangePi_Build repository:
    git clone https://github.com/orangepi-xunlong/OrangePi_Build.git
     cd OrangePi_Build
     ./Build_OrangePi.sh

    -Choose the "Orange Pi I96" option which will create the "OrangePiRDA" folder.
    +Choose the "Orange Pi i96" option which will create the "OrangePiRDA" folder.

    The files in this repository are meant to replace the stock OrangePiRDA ones that are generated (specifically in the scripts folder). You simply copy them over the top of your generated folder like this:
    cd ..
    @@ -50,6 +52,7 @@ Ubuntu is not building correctly yet.

    Version History

      +
    1. September 24th 2022 - V1.20 - Fixed SD card driver to correctly support high-speed mode, fixed TRIM support, decreased boot time by about 10 seconds by reducing rda-backlight timeout, cleaned up distributions.sh into organized functions
    2. September 23rd 2022 - V1.19 - Add OPi.GPIO library (supports devices such as the Waveshare e-paper display (thanks Michael, OPi.GPIO fork), add orangepi user to gpio group, general cleanup/removal of script portions related to other platforms than RDA
    3. September 22nd 2022 - V1.18 - Enable CONFIG_SND_USB to allow for USB soundcard use
    4. September 20th 2022 - V1.17 - Add further spidev fixes (thanks MZA, OrangePi-I96-Work)