From 0143c722956ef20eee1a2d0e7f347357a8cab074 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 7 Feb 2025 20:11:08 +0800 Subject: [PATCH 01/16] Revert "misc: add usb camera pd pin control driver" This reverts commit 3344984bec2e94392987af0ae6498a92ccea169e. Signed-off-by: Tao Huang Change-Id: Ic45376d824f855353960f8969f3073c606b38599 --- .../devicetree/bindings/misc/usb_cam_gpio.txt | 16 -- drivers/misc/usb_cam_gpio.c | 192 ------------------ 2 files changed, 208 deletions(-) delete mode 100644 Documentation/devicetree/bindings/misc/usb_cam_gpio.txt delete mode 100644 drivers/misc/usb_cam_gpio.c diff --git a/Documentation/devicetree/bindings/misc/usb_cam_gpio.txt b/Documentation/devicetree/bindings/misc/usb_cam_gpio.txt deleted file mode 100644 index 2e7a44ed65de..000000000000 --- a/Documentation/devicetree/bindings/misc/usb_cam_gpio.txt +++ /dev/null @@ -1,16 +0,0 @@ -* Rockchip USB camera GPIO control driver - -Required properties: -- compatible: should be "usb-cam-gpio" -- hd-cam-pin: HD camera on gpio pin -- ir-cam-pin: IR camera on gpio pin - -Example: - usb_cam_gpio: usb-cam-gpio { - compatible = "usb-cam-gpio"; - pinctrl-names = "default"; - pinctrl-0 = <&usb_cam_on_gpio>; - hd-cam-pin = <&gpio3 GPIO_A1 GPIO_ACTIVE_LOW>; - ir-cam-pin = <&gpio3 GPIO_A2 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; diff --git a/drivers/misc/usb_cam_gpio.c b/drivers/misc/usb_cam_gpio.c deleted file mode 100644 index 320c1ed67945..000000000000 --- a/drivers/misc/usb_cam_gpio.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * drivers/misc/usb_cam_gpio.c - * - * Copyright (C) 2012-2016 Rockchip Electronics Co., Ltd. - * Author: Bin Yang - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 - -static struct class *usb_cam_gpio_class; - -struct usb_cam_gpio { - struct device *dev; - struct device sys_dev; - - struct gpio_desc *gpio_cam_hd; - struct gpio_desc *gpio_cam_ir; -}; - -static ssize_t hd_camera_on_show(struct device *sys_dev, - struct device_attribute *attr, - char *buf) -{ - struct usb_cam_gpio *gpiod = container_of(sys_dev, struct usb_cam_gpio, - sys_dev); - - return sprintf(buf, "%d\n", gpiod_get_value(gpiod->gpio_cam_hd)); -} - -static ssize_t hd_camera_on_store(struct device *sys_dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct usb_cam_gpio *gpiod = container_of(sys_dev, struct usb_cam_gpio, - sys_dev); - int val = 0; - int ret = 0; - - ret = kstrtoint(buf, 0, &val); - if (ret < 0) - return ret; - if (val) - val = 1; - gpiod_set_value(gpiod->gpio_cam_hd, val); - - return count; -} -static DEVICE_ATTR_RW(hd_camera_on); - -static ssize_t ir_camera_on_show(struct device *sys_dev, - struct device_attribute *attr, - char *buf) -{ - struct usb_cam_gpio *gpiod = container_of(sys_dev, - struct usb_cam_gpio, sys_dev); - - return sprintf(buf, "%d\n", gpiod_get_value(gpiod->gpio_cam_ir)); -} - -static ssize_t ir_camera_on_store(struct device *sys_dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct usb_cam_gpio *gpiod = container_of(sys_dev, - struct usb_cam_gpio, sys_dev); - int val; - int ret; - - ret = kstrtoint(buf, 0, &val); - if (ret < 0) - return ret; - if (val) - val = 1; - gpiod_set_value(gpiod->gpio_cam_ir, val); - - return count; -} -static DEVICE_ATTR_RW(ir_camera_on); - -static struct attribute *usb_cam_gpio_attrs[] = { - &dev_attr_hd_camera_on.attr, - &dev_attr_ir_camera_on.attr, - NULL, -}; -ATTRIBUTE_GROUPS(usb_cam_gpio); - -static int usb_cam_gpio_device_register(struct usb_cam_gpio *gpiod) -{ - int ret; - struct device *dev = &gpiod->sys_dev; - const char *name = {"usb_camera_on"}; - - dev->class = usb_cam_gpio_class; - dev_set_name(dev, "%s", name); - dev_set_drvdata(dev, gpiod); - ret = device_register(dev); - - return ret; -} - -static int usb_cam_gpio_probe(struct platform_device *pdev) -{ - struct usb_cam_gpio *gpiod; - int ret = 0; - - usb_cam_gpio_class = class_create(THIS_MODULE, "usb_cam_gpio"); - if (IS_ERR(usb_cam_gpio_class)) { - pr_err("create uvc_detection class failed (%ld)\n", - PTR_ERR(usb_cam_gpio_class)); - return PTR_ERR(usb_cam_gpio_class); - } - usb_cam_gpio_class->dev_groups = usb_cam_gpio_groups; - - gpiod = devm_kzalloc(&pdev->dev, sizeof(*gpiod), GFP_KERNEL); - if (!gpiod) - return -ENOMEM; - - gpiod->dev = &pdev->dev; - - gpiod->gpio_cam_hd = devm_gpiod_get_optional(gpiod->dev, - "hd-cam", GPIOD_OUT_LOW); - if (IS_ERR(gpiod->gpio_cam_hd)) { - dev_warn(gpiod->dev, "Could not get hd-cam-gpios!\n"); - gpiod->gpio_cam_hd = NULL; - } - - gpiod->gpio_cam_ir = devm_gpiod_get_optional(gpiod->dev, - "ir-cam", GPIOD_OUT_HIGH); - if (IS_ERR(gpiod->gpio_cam_ir)) { - dev_warn(gpiod->dev, "Could not get ir-cam-gpios!\n"); - gpiod->gpio_cam_ir = NULL; - } - - ret = usb_cam_gpio_device_register(gpiod); - if (ret < 0) { - dev_err(gpiod->dev, "usb_cam_gpio device register fail\n"); - return ret; - } - - dev_info(gpiod->dev, "usb_cam_gpio_probe success\n"); - - return 0; -} - -static const struct of_device_id usb_cam_gpio_match[] = { - { .compatible = "usb-cam-gpio" }, - { /* Sentinel */ } -}; - -static int usb_cam_gpio_remove(struct platform_device *pdev) -{ - if (!IS_ERR(usb_cam_gpio_class)) - class_destroy(usb_cam_gpio_class); - - return 0; -} - -static struct platform_driver usb_cam_gpio_driver = { - .probe = usb_cam_gpio_probe, - .remove = usb_cam_gpio_remove, - .driver = { - .name = "usb_cam_gpio", - .owner = THIS_MODULE, - .of_match_table = usb_cam_gpio_match, - }, -}; - -module_platform_driver(usb_cam_gpio_driver); - -MODULE_ALIAS("platform:usb_cam_gpio"); -MODULE_AUTHOR("Bin Yang "); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("usb camera gpio driver"); From ecd317b0bde1782ac287015d9b49e88bb13a0e7a Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 7 Feb 2025 20:00:12 +0800 Subject: [PATCH 02/16] Revert "power: add ec battery driver" This reverts commit 620a4f67a445f83304c3ca8d2224eee1607bfa0c. Signed-off-by: Tao Huang Change-Id: I5bfeb24fdda20fb2b0ff93cebdc9d7dd878841dc --- .../devicetree/bindings/power/ec_battery.txt | 20 - drivers/power/ec_battery.c | 466 ------------------ 2 files changed, 486 deletions(-) delete mode 100644 Documentation/devicetree/bindings/power/ec_battery.txt delete mode 100644 drivers/power/ec_battery.c diff --git a/Documentation/devicetree/bindings/power/ec_battery.txt b/Documentation/devicetree/bindings/power/ec_battery.txt deleted file mode 100644 index 5d761d9fc532..000000000000 --- a/Documentation/devicetree/bindings/power/ec_battery.txt +++ /dev/null @@ -1,20 +0,0 @@ -Binding for EC Battery - -Required properties: -- compatible: Should contain one of the following: - * "rockchip,ec-battery" -- reg: integer, smbus address of the device. -- tvirtual_power: integer, test power, if battery is not exist; -- monitor_sec: integer, delay time of queue_delayed_work (s); - - -Optional properties: - -Example: - -ec_battery: ec_battery09 { - compatible = "rockchip,ec-battery"; - reg = <0x76>; - virtual_power = <0>; - monitor_sec = <5>; -}; diff --git a/drivers/power/ec_battery.c b/drivers/power/ec_battery.c deleted file mode 100644 index 38db43507bee..000000000000 --- a/drivers/power/ec_battery.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * ec battery driver - * - * Copyright (C) 2016 Rockchip Electronics Co., Ltd. - * Shunqing Chen - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 - -static int dbg_enable; -module_param_named(dbg_level, dbg_enable, int, 0644); - -#define DBG(args...) \ - do { \ - if (dbg_enable) { \ - printk(args); \ - } \ - } while (0) - -struct ec_battery { - struct i2c_client *i2c; - struct device *dev; - struct regmap *regmap; - struct power_supply *bat; - struct workqueue_struct *bat_monitor_wq; - struct delayed_work bat_delay_work; - u32 monitor_sec; - u32 bat_mode; - u16 status; - int current_now; - u16 voltage_now; - u16 rem_capacity; - u16 full_charge_capacity; - u16 design_capacity; - int temperature_now; - int soc; - bool is_charge; - bool dis_charge; - bool is_ctitical; - bool is_battery_low; - bool is_battery_in; - bool is_ac_in; - struct gpio_desc *ec_notify_io; -}; - -enum bat_mode { - MODE_BATTARY = 0, - MODE_VIRTUAL, -}; - -/* virtual params */ -#define VIRTUAL_CURRENT 1000 -#define VIRTUAL_VOLTAGE 3888 -#define VIRTUAL_SOC 66 -#define VIRTUAL_PRESET 1 -#define VIRTUAL_TEMPERATURE 188 -#define VIRTUAL_STATUS POWER_SUPPLY_STATUS_CHARGING - -#define TIMER_MS_COUNTS 1000 -#define DEFAULT_MONITOR_SEC 5 - -#define EC_GET_VERSION_COMMOND 0x10 -#define EC_GET_VERSION_INFO_NUM (5) -#define EC_GET_BATTERY_INFO_COMMOND 0x07 -#define EC_GET_PARAMETER_NUM (13) -#define EC_GET_BATTERY_OTHER_COMMOND 0x08 -#define EC_GET_BATTERYINFO_NUM (7) - -#define EC_GET_BIT(a, b) (((a) & (1 << (b))) ? 1 : 0) -#define EC_DIS_CHARGE(a) EC_GET_BIT(a, 0) -#define EC_IS_CHARGE(a) EC_GET_BIT(a, 1) -#define EC_IS_CRITICAL(a) EC_GET_BIT(a, 2) -#define EC_IS_BATTERY_LOW(a) EC_GET_BIT(a, 3) -#define EC_IS_BATTERY_IN(a) EC_GET_BIT(a, 6) -#define EC_IS_AC_IN(a) EC_GET_BIT(a, 7) - -static int ec_i2c_read(struct ec_battery *bat, u8 cmd, u8 *dest, u16 len) -{ - struct i2c_client *i2c = bat->i2c; - int ret; - struct i2c_msg msg[2]; - u8 buf[2]; - - buf[0] = cmd; /* EC_GET_BATTERY_INFO_COMMOND; */ - msg[0].addr = i2c->addr; - msg[0].flags = i2c->flags & I2C_M_TEN; - msg[0].len = 1; - msg[0].buf = buf; - - msg[1].addr = i2c->addr; - msg[1].flags = i2c->flags & I2C_M_TEN; - msg[1].flags |= I2C_M_RD; - msg[1].len = len; - msg[1].buf = dest; - - ret = i2c_transfer(i2c->adapter, msg, 2); - - return ret; -} - -static void ec_dump_info(struct ec_battery *bat) -{ - int temp; - - DBG("==========================================\n"); - DBG("battery status: %x\n", bat->status); - temp = bat->temperature_now / 10; - DBG("Temp: %d K (%d C))\n", temp, (temp - 272)); - DBG("current_now: %d ma\n", bat->current_now); - DBG("voltage_now: %d mv\n", bat->voltage_now); - DBG("Charge: %d %%\n", bat->soc); - DBG("Remaining: %d mAh\n", bat->rem_capacity); - DBG("Cap-full: %d mAh\n", bat->full_charge_capacity); - DBG("Design: %d mAh\n", bat->design_capacity); - DBG("==========================================\n"); -} - -static int ec_get_battery_info(struct ec_battery *bat) -{ - u8 buf[13] = {0}; - u16 voltage2; - u16 full_charge_capacity_1; - u16 design_capacity; - u16 cur; - int ret; - int soc; - - ret = ec_i2c_read(bat, EC_GET_BATTERY_INFO_COMMOND, buf, - EC_GET_PARAMETER_NUM); - if ((EC_GET_PARAMETER_NUM - 1) == buf[0]) { - bat->status = buf[2] << 8 | buf[1]; - cur = (buf[4] << 8 | buf[3]); - bat->current_now = cur; - if (buf[4] & 0x80) { - bat->current_now = (~cur) & 0xffff; - bat->current_now = -(bat->current_now); - } - - bat->rem_capacity = buf[6] << 8 | buf[5]; - bat->voltage_now = buf[8] << 8 | buf[7]; - bat->full_charge_capacity = buf[10] << 8 | buf[9]; - bat->temperature_now = buf[12] << 8 | buf[11]; - soc = (bat->rem_capacity + bat->full_charge_capacity / 101) * - 100 / bat->full_charge_capacity; - if (soc > 100) - bat->soc = 100; - else if (soc < 0) - bat->soc = 0; - else - bat->soc = soc; - } else { - dev_err(bat->dev, "get battery info from 0x07 erro\n"); - } - - ret = ec_i2c_read(bat, EC_GET_BATTERY_OTHER_COMMOND, buf, - EC_GET_BATTERYINFO_NUM); - if ((EC_GET_BATTERYINFO_NUM - 1) == buf[0]) { - full_charge_capacity_1 = buf[2] << 8 | buf[1]; - voltage2 = buf[4] << 8 | buf[3]; /* the same to uppo */ - design_capacity = buf[6] << 8 | buf[5]; /* the same to uppo */ - bat->design_capacity = design_capacity; - } - - ec_dump_info(bat); - - return 0; -} - -static int ec_get_current(struct ec_battery *bat) -{ - return bat->current_now * 1000; -} - -static int ec_get_voltage(struct ec_battery *bat) -{ - return bat->voltage_now * 1000; -} - -static int is_ec_bat_exist(struct ec_battery *bat) -{ - int is_exist; - - is_exist = EC_IS_BATTERY_IN(bat->status); - return is_exist; -} - -static int ec_get_capacity(struct ec_battery *bat) -{ - return bat->soc; -} - -static int ec_get_temperature(struct ec_battery *bat) -{ - int temp; - - temp = bat->temperature_now - 2722; - return temp; -} - -static int ec_bat_chrg_online(struct ec_battery *bat) -{ - return EC_IS_CHARGE(bat->status); -} - -#ifdef CONFIG_OF -static int ec_bat_parse_dt(struct ec_battery *bat) -{ - int ret; - u32 out_value; - struct device_node *np = bat->dev->of_node; - - bat->bat_mode = MODE_BATTARY; - bat->monitor_sec = DEFAULT_MONITOR_SEC * TIMER_MS_COUNTS; - - ret = of_property_read_u32(np, "virtual_power", &bat->bat_mode); - if (ret < 0) - dev_err(bat->dev, "virtual_power missing!\n"); - - ret = of_property_read_u32(np, "monitor_sec", &out_value); - if (ret < 0) - dev_err(bat->dev, "monitor_sec missing!\n"); - else - bat->monitor_sec = out_value * TIMER_MS_COUNTS; - - bat->ec_notify_io = - devm_gpiod_get_optional(bat->dev, "ec-notify", - GPIOD_IN); - if (!IS_ERR_OR_NULL(bat->ec_notify_io)) - gpiod_direction_output(bat->ec_notify_io, 0); - - return 0; -} -#else -static int ec_bat_parse_dt(struct ec_battery *bat) -{ - return -ENODEV; -} -#endif - -static enum power_supply_property ec_bat_props[] = { - POWER_SUPPLY_PROP_CURRENT_NOW, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_STATUS, -}; - -static int ec_battery_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct ec_battery *bat = power_supply_get_drvdata(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = ec_get_current(bat);/*uA*/ - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_CURRENT * 1000; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = ec_get_voltage(bat);/*uV*/ - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_VOLTAGE * 1000; - break; - case POWER_SUPPLY_PROP_PRESENT: - val->intval = is_ec_bat_exist(bat); - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_PRESET; - break; - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = ec_get_capacity(bat); - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_SOC; - break; - case POWER_SUPPLY_PROP_HEALTH: - val->intval = POWER_SUPPLY_HEALTH_GOOD; - break; - case POWER_SUPPLY_PROP_TEMP: - val->intval = ec_get_temperature(bat); - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_TEMPERATURE; - break; - case POWER_SUPPLY_PROP_STATUS: - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_STATUS; - else if (ec_get_capacity(bat) == 100) - val->intval = POWER_SUPPLY_STATUS_FULL; - else if (ec_bat_chrg_online(bat)) - val->intval = POWER_SUPPLY_STATUS_CHARGING; - else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - break; - default: - return -EINVAL; - } - - return 0; -} - -static const struct power_supply_desc ec_bat_desc = { - .name = "battery", - .type = POWER_SUPPLY_TYPE_BATTERY, - .properties = ec_bat_props, - .num_properties = ARRAY_SIZE(ec_bat_props), - .get_property = ec_battery_get_property, -}; - -static int ec_bat_init_power_supply(struct ec_battery *bat) -{ - struct power_supply_config psy_cfg = { .drv_data = bat, }; - - bat->bat = power_supply_register(bat->dev, &ec_bat_desc, &psy_cfg); - if (IS_ERR(bat->bat)) { - dev_err(bat->dev, "register bat power supply fail\n"); - return PTR_ERR(bat->bat); - } - - return 0; -} - -static void ec_bat_power_supply_changed(struct ec_battery *ec_bat) -{ - bool state_changed; - static int old_cap = -1; - static int old_temperature; - - state_changed = false; - if (ec_get_capacity(ec_bat) != old_cap) - state_changed = true; - else if (ec_get_temperature(ec_bat) != old_temperature) - state_changed = true; - - if (state_changed) { - power_supply_changed(ec_bat->bat); - old_cap = ec_get_capacity(ec_bat); - old_temperature = ec_get_temperature(ec_bat); - } -} - -static void ec_battery_work(struct work_struct *work) -{ - struct ec_battery *ec_bat = - container_of(work, struct ec_battery, bat_delay_work.work); - - ec_get_battery_info(ec_bat); - ec_bat_power_supply_changed(ec_bat); - - queue_delayed_work(ec_bat->bat_monitor_wq, &ec_bat->bat_delay_work, - msecs_to_jiffies(ec_bat->monitor_sec)); -} - -static int ec_charger_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ec_battery *ec_bat; - int ret; - - ec_bat = devm_kzalloc(&client->dev, sizeof(*ec_bat), GFP_KERNEL); - if (!ec_bat) - return -ENOMEM; - ec_bat->dev = &client->dev; - ec_bat->i2c = client; - i2c_set_clientdata(client, ec_bat); - - ret = ec_bat_parse_dt(ec_bat); - if (ret < 0) { - dev_err(ec_bat->dev, "parse dt failed!\n"); - return ret; - } - - ret = ec_bat_init_power_supply(ec_bat); - if (ret) { - dev_err(ec_bat->dev, "init power supply fail!\n"); - return ret; - } - - ec_bat->bat_monitor_wq = - alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - "ec-bat-monitor-wq"); - INIT_DELAYED_WORK(&ec_bat->bat_delay_work, ec_battery_work); - queue_delayed_work(ec_bat->bat_monitor_wq, &ec_bat->bat_delay_work, - msecs_to_jiffies(TIMER_MS_COUNTS * 5)); - - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static int ec_bat_pm_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ec_battery *ec_bat = i2c_get_clientdata(client); - - cancel_delayed_work_sync(&ec_bat->bat_delay_work); - - if (!IS_ERR_OR_NULL(ec_bat->ec_notify_io)) - gpiod_direction_output(ec_bat->ec_notify_io, 1); - - return 0; -} - -static int ec_bat_pm_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ec_battery *ec_bat = i2c_get_clientdata(client); - - if (!IS_ERR_OR_NULL(ec_bat->ec_notify_io)) - gpiod_direction_output(ec_bat->ec_notify_io, 0); - - queue_delayed_work(ec_bat->bat_monitor_wq, &ec_bat->bat_delay_work, - msecs_to_jiffies(TIMER_MS_COUNTS * 1)); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(ec_bat_pm_ops, ec_bat_pm_suspend, ec_bat_pm_resume); - -static const struct i2c_device_id ec_battery_i2c_ids[] = { - { "ec_battery" }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, ec_battery_i2c_ids); - -#ifdef CONFIG_OF -static const struct of_device_id ec_of_match[] = { - { .compatible = "rockchip,ec-battery" }, - { }, -}; -MODULE_DEVICE_TABLE(of, ec_of_match); -#else -static const struct of_device_id ec_of_match[] = { - { }, -}; -#endif - -static struct i2c_driver ec_i2c_driver = { - .driver = { - .name = "ec_battery", - .pm = &ec_bat_pm_ops, - .of_match_table = ec_of_match, - }, - .id_table = ec_battery_i2c_ids, - .probe = ec_charger_probe, -}; - -module_i2c_driver(ec_i2c_driver); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ec-charger"); -MODULE_AUTHOR("Shunqing Chen"); From 0d5f21d790797f4217574d68138be8323834415e Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Fri, 12 Jan 2024 11:32:36 +0800 Subject: [PATCH 03/16] video: rockchip: dvbm: sync code from 5.10 Merge from kernel 5.10 video: rockchip: dvbm: support dual dvbm wrap config video: rockchip: dvbm: simplify the dvbm module codes video: rockchip: dvbm: modify api to adapt rv1103b Change-Id: Idd1e0e98392cc1314d6dc67e512cfe1f660d691c Signed-off-by: Yandong Lin --- .../media/platform/rockchip/isp/isp_dvbm.c | 5 +- drivers/video/rockchip/dvbm/Kconfig | 11 - drivers/video/rockchip/dvbm/rockchip_dvbm.c | 508 +++--------------- drivers/video/rockchip/dvbm/rockchip_dvbm.h | 214 -------- include/soc/rockchip/rockchip_dvbm.h | 34 +- 5 files changed, 84 insertions(+), 688 deletions(-) delete mode 100644 drivers/video/rockchip/dvbm/rockchip_dvbm.h diff --git a/drivers/media/platform/rockchip/isp/isp_dvbm.c b/drivers/media/platform/rockchip/isp/isp_dvbm.c index 472e6ef96ac0..6cb5569796f3 100644 --- a/drivers/media/platform/rockchip/isp/isp_dvbm.c +++ b/drivers/media/platform/rockchip/isp/isp_dvbm.c @@ -55,9 +55,10 @@ int rkisp_dvbm_init(struct rkisp_stream *stream) dvbm_cfg.cbuf_top = dvbm_cfg.cbuf_bot + (width * wrap_line / 2); dvbm_cfg.cbuf_lstd = width; dvbm_cfg.cbuf_fstd = dvbm_cfg.ybuf_fstd / 2; + dvbm_cfg.chan_id = dev->dev_id; rk_dvbm_ctrl(g_dvbm, DVBM_ISP_SET_CFG, &dvbm_cfg); - rk_dvbm_link(g_dvbm); + rk_dvbm_link(g_dvbm, dev->dev_id); return 0; } @@ -67,7 +68,7 @@ void rkisp_dvbm_deinit(struct rkisp_device *dev) pr_err("g_dvbm %p or devv %p is NULL\n", g_dvbm, dev); return; } - rk_dvbm_unlink(g_dvbm); + rk_dvbm_unlink(g_dvbm, dev->dev_id); } int rkisp_dvbm_event(struct rkisp_device *dev, u32 event) diff --git a/drivers/video/rockchip/dvbm/Kconfig b/drivers/video/rockchip/dvbm/Kconfig index bfbd396b2706..480027e3bd1e 100644 --- a/drivers/video/rockchip/dvbm/Kconfig +++ b/drivers/video/rockchip/dvbm/Kconfig @@ -5,14 +5,3 @@ menuconfig ROCKCHIP_DVBM depends on ARCH_ROCKCHIP help rockchip dvbm module. - -if ROCKCHIP_DVBM - -config ROCKCHIP_DVBM_PROC_FS - bool "enable dvbm procfs" - depends on PROC_FS - default y - help - rockchip dvbm procfs. - -endif diff --git a/drivers/video/rockchip/dvbm/rockchip_dvbm.c b/drivers/video/rockchip/dvbm/rockchip_dvbm.c index 2e40a7e78e78..93760d3f3f48 100644 --- a/drivers/video/rockchip/dvbm/rockchip_dvbm.c +++ b/drivers/video/rockchip/dvbm/rockchip_dvbm.c @@ -7,17 +7,10 @@ */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include #include #include -#include -#include -#include -#include #include -#include "rockchip_dvbm.h" - #define RK_DVBM "rk_dvbm" unsigned int dvbm_debug; @@ -27,9 +20,6 @@ MODULE_PARM_DESC(dvbm_debug, "bit switch for dvbm debug information"); static struct dvbm_ctx *g_ctx; #define DVBM_DEBUG 0x00000001 -#define DVBM_DEBUG_IRQ 0x00000002 -#define DVBM_DEBUG_REG 0x00000004 -#define DVBM_DEBUG_DUMP 0x00000008 #define DVBM_DEBUG_FRM 0x00000010 #define dvbm_debug(fmt, args...) \ @@ -38,106 +28,45 @@ static struct dvbm_ctx *g_ctx; pr_info(fmt, ##args); \ } while (0) -#define dvbm_debug_reg(fmt, args...) \ - do { \ - if (unlikely(dvbm_debug & (DVBM_DEBUG_REG))) \ - pr_info(fmt, ##args); \ - } while (0) - -#define dvbm_debug_irq(fmt, args...) \ - do { \ - if (unlikely(dvbm_debug & (DVBM_DEBUG_IRQ))) \ - pr_info(fmt, ##args); \ - } while (0) - -#define dvbm_debug_dump(fmt, args...) \ - do { \ - if (unlikely(dvbm_debug & (DVBM_DEBUG_DUMP))) \ - pr_info(fmt, ##args); \ - } while (0) - #define dvbm_debug_frm(fmt, args...) \ do { \ if (unlikely(dvbm_debug & (DVBM_DEBUG_FRM))) \ pr_info(fmt, ##args); \ } while (0) -#define dvbm_err(fmt, args...) \ - pr_err(fmt, ##args) +#define dvbm_err(fmt, args...) \ + pr_err("%s:%d: " fmt, __func__, __LINE__, ##args) -enum dvbm_flow { - ISP_CFG = 1, - ISP_CONNECT = 2, - VEPU_CFG = 3, - VEPU_CONNECT = 4, -}; -/* dvbm status reg bit value define */ -#define BUF_OVERFLOW BIT(0) -#define RESYNC_FINISH BIT(1) -#define ISP_CNCT_TIMEOUT BIT(2) -#define VEPU_CNCT_TIMEOUT BIT(3) -#define VEPU_HANDSHAKE_TIMEOUT BIT(4) -#define ISP_CNCT BIT(5) -#define ISP_DISCNCT BIT(6) -#define VEPU_CNCT BIT(7) -#define VEPU_DISCNCT BIT(8) - -/* dvbm reg addr define */ -#define DVBM_VERSION 0x0 -#define DVBM_ISP_CNCT 0x4 -#define DVBM_VEPU_CNCT 0x8 -/* cfg regs */ -#define DVBM_CFG 0xC -#define DVBM_WDG_CFG0 0x10 -#define DVBM_WDG_CFG1 0x14 -#define DVBM_WDG_CFG2 0x18 -/* interrupt regs */ -#define DVBM_INT_EN 0x1c -#define DVBM_INT_MSK 0x20 -#define DVBM_INT_CLR 0x24 -#define DVBM_INT_ST 0x28 -/* addr regs */ -#define DVBM_YBUF_BOT 0x2c -#define DVBM_YBUF_TOP 0x30 -#define DVBM_YBUF_SADR 0x34 -#define DVBM_YBUF_LSTD 0x38 -#define DVBM_YBUF_FSTD 0x3c -#define DVBM_CBUF_BOT 0x40 -#define DVBM_CBUF_TOP 0x44 -#define DVBM_CBUF_SADR 0x48 -#define DVBM_CBUF_LSTD 0x4c -#define DVBM_CBUF_FSTD 0x50 -#define DVBM_AFUL_THDY 0x54 -#define DVBM_AFUL_THDC 0x58 -#define DVBM_OVFL_THDY 0x5c -#define DVBM_OVFL_THDC 0x60 -/* status regs */ -#define DVBM_ST 0x80 -#define DVBM_OVFL_ST 0x84 - -#define DVBM_REG_OFFSET 0x2c - -#define SOFT_DVBM 1 #define UPDATE_LINE_CNT 0 -static void rk_dvbm_set_reg(struct dvbm_ctx *ctx, u32 offset, u32 val) -{ - if (!SOFT_DVBM) { - dvbm_debug_reg("write reg[%d] 0x%x = 0x%08x\n", offset >> 2, offset, val); - writel(val, ctx->reg_base + offset); - } -} +#define DVBM_CHANNEL_NUM (3) -static u32 rk_dvbm_read_reg(struct dvbm_ctx *ctx, u32 offset) -{ - u32 val = 0; +struct dvbm_ctx { + struct device *dev; - if (!SOFT_DVBM) { - val = readl(ctx->reg_base + offset); - dvbm_debug_reg("read reg[%d] 0x%x = 0x%08x\n", offset >> 2, offset, val); - } - return val; -} + u32 isp_connet; + u32 vepu_connet; + + /* vepu infos */ + struct dvbm_port port_vepu; + atomic_t vepu_link; + struct dvbm_cb vepu_cb; + struct dvbm_addr_cfg vepu_cfg; + + /* isp infos */ + struct dvbm_port port_isp; + struct dvbm_cb isp_cb; + struct dvbm_isp_cfg_t isp_cfg[DVBM_CHANNEL_NUM]; + struct dvbm_addr_cfg dvbm_addr[DVBM_CHANNEL_NUM]; + u32 chan_id; + struct dvbm_isp_frm_info isp_frm_info; + atomic_t isp_link; + u32 isp_max_lcnt; + u32 isp_frm_start; + u32 isp_frm_end; + ktime_t isp_frm_time; + u32 wrap_line; +}; static struct dvbm_ctx *port_to_ctx(struct dvbm_port *port) { @@ -158,39 +87,12 @@ static void dvbm2enc_callback(struct dvbm_ctx *ctx, enum dvbm_cb_event event, vo struct dvbm_cb *callback = &ctx->vepu_cb; dvbm_callback cb = callback->cb; - if (!ctx->port_vepu.linked) + if (!cb) { + dvbm_err("vepu callback is null\n"); return; - if (cb) - cb(callback->ctx, event, arg); -} + } -static void rk_dvbm_dump_regs(struct dvbm_ctx *ctx) -{ - u32 start = ctx->dump_s;//0x80; - u32 end = ctx->dump_e;//0xb8; - u32 i; - dvbm_debug_dump("=== %s ===\n", __func__); - for (i = start; i <= end; i += 4) - dvbm_debug_dump("reg[0x%0x] = 0x%08x\n", i, readl(ctx->reg_base + i)); - dvbm_debug_dump("=== %s ===\n", __func__); -} - -static int rk_dvbm_clk_on(struct dvbm_ctx *ctx) -{ - int ret = 0; - - if (ctx->clk) - ret = clk_prepare_enable(ctx->clk); - if (ret) - dev_err(ctx->dev, "clk on failed\n"); - return ret; -} - -static int rk_dvbm_clk_off(struct dvbm_ctx *ctx) -{ - if (ctx->clk) - clk_disable_unprepare(ctx->clk); - return 0; + cb(callback->ctx, event, arg); } static void init_isp_infos(struct dvbm_ctx *ctx) @@ -222,84 +124,6 @@ static void rk_dvbm_update_isp_frm_info(struct dvbm_ctx *ctx, u32 line_cnt) #endif } -static int rk_dvbm_setup_iobuf(struct dvbm_ctx *ctx) -{ - u32 *data; - u32 i; - struct rk_dvbm_base *addr_base = &ctx->regs.addr_base; - struct dvbm_isp_cfg_t *cfg = &ctx->isp_cfg; - - addr_base->ybuf_bot = cfg->dma_addr + cfg->ybuf_bot; - addr_base->ybuf_top = cfg->dma_addr + cfg->ybuf_top; - addr_base->ybuf_sadr = cfg->dma_addr + cfg->ybuf_bot; - addr_base->ybuf_fstd = cfg->ybuf_fstd; - addr_base->ybuf_lstd = cfg->ybuf_lstd; - - addr_base->cbuf_bot = cfg->dma_addr + cfg->cbuf_bot; - addr_base->cbuf_top = cfg->dma_addr + cfg->cbuf_top; - addr_base->cbuf_sadr = cfg->dma_addr + cfg->cbuf_bot; - addr_base->cbuf_fstd = cfg->cbuf_fstd; - addr_base->cbuf_lstd = cfg->cbuf_lstd; - - addr_base->aful_thdy = cfg->ybuf_lstd; - addr_base->aful_thdc = cfg->ybuf_lstd; - addr_base->oful_thdy = cfg->ybuf_lstd; - addr_base->oful_thdc = cfg->ybuf_lstd; - - ctx->isp_max_lcnt = cfg->ybuf_fstd / cfg->ybuf_lstd; - ctx->wrap_line = (cfg->ybuf_top - cfg->ybuf_bot) / cfg->ybuf_lstd; - ctx->isp_frm_info.frame_cnt = 0; - ctx->isp_frm_info.line_cnt = 0; - ctx->isp_frm_info.max_line_cnt = ALIGN(ctx->isp_max_lcnt, 32); - ctx->isp_frm_info.wrap_line = ctx->wrap_line; - dvbm_debug("dma_addr %pad y_lstd %d y_fstd %d\n", - &cfg->dma_addr, cfg->ybuf_lstd, cfg->ybuf_fstd); - dvbm_debug("ybot 0x%x top 0x%x cbuf bot 0x%x top 0x%x\n", - addr_base->ybuf_bot, addr_base->ybuf_top, - addr_base->cbuf_bot, addr_base->cbuf_top); - - data = (u32 *)addr_base; - for (i = 0; i < sizeof(struct rk_dvbm_base) / sizeof(u32); i++) - rk_dvbm_set_reg(ctx, i * sizeof(u32) + DVBM_REG_OFFSET, data[i]); - - for (i = 1; i < 65536; i++) - if (!((addr_base->ybuf_fstd * i) % (cfg->ybuf_top - cfg->ybuf_bot))) - break; - ctx->loopcnt = i; - return 0; -} - -static void rk_dvbm_reg_init(struct dvbm_ctx *ctx) -{ - struct rk_dvbm_regs *reg = &ctx->regs; - u32 *val = (u32 *)reg; - - reg->int_en.buf_ovfl = 1; - reg->int_en.isp_cnct = 1; - reg->int_en.vepu_cnct = 1; - reg->int_en.vepu_discnct = 1; - reg->int_en.isp_discnct = 1; - reg->int_en.resync_finish = 1; - reg->int_en.isp_cnct_timeout = 1; - reg->int_en.vepu_cnct_timeout = 1; - reg->int_en.vepu_handshake_timeout = 1; - - reg->dvbm_cfg.fmt = 0; - reg->dvbm_cfg.auto_resyn = 0; - reg->dvbm_cfg.ignore_vepu_cnct_ack = 0; - reg->dvbm_cfg.start_point_after_vepu_cnct = 0; - - reg->wdg_cfg0.wdg_isp_cnct_timeout = 0xfffff; - reg->wdg_cfg1.wdg_vepu_cnct_timeout = 0xfffff; - reg->wdg_cfg2.wdg_vepu_handshake_timeout = 0xfffff; - - rk_dvbm_set_reg(ctx, DVBM_WDG_CFG0, val[DVBM_WDG_CFG0 >> 2]); - rk_dvbm_set_reg(ctx, DVBM_WDG_CFG1, val[DVBM_WDG_CFG1 >> 2]); - rk_dvbm_set_reg(ctx, DVBM_WDG_CFG2, val[DVBM_WDG_CFG2 >> 2]); - rk_dvbm_set_reg(ctx, DVBM_CFG, val[DVBM_CFG >> 2]); - rk_dvbm_set_reg(ctx, DVBM_INT_EN, val[DVBM_INT_EN >> 2]); -} - struct dvbm_port *rk_dvbm_get_port(struct platform_device *pdev, enum dvbm_port_dir dir) { @@ -329,18 +153,17 @@ int rk_dvbm_put(struct dvbm_port *port) return -EINVAL; ctx = port_to_ctx(port); - if (!ctx) return -EINVAL; + return 0; } EXPORT_SYMBOL(rk_dvbm_put); -int rk_dvbm_link(struct dvbm_port *port) +int rk_dvbm_link(struct dvbm_port *port, int id) { struct dvbm_ctx *ctx; enum dvbm_port_dir dir; - struct rk_dvbm_regs *reg; int ret = 0; if (WARN_ON(!port)) @@ -348,59 +171,40 @@ int rk_dvbm_link(struct dvbm_port *port) ctx = port_to_ctx(port); dir = port->dir; - reg = &ctx->regs; if (dir == DVBM_ISP_PORT) { - if (port->linked) { - rk_dvbm_unlink(port); - udelay(5); - } - reg->isp_cnct.isp_cnct = 1; - rk_dvbm_set_reg(ctx, DVBM_ISP_CNCT, 0x1); + if (id >= DVBM_CHANNEL_NUM) + dvbm_err("id %d is invalid\n", id); + + dvbm2enc_callback(ctx, DVBM_ISP_REQ_CONNECT, &id); } else if (dir == DVBM_VEPU_PORT) { - if (!port->linked) { - reg->vepu_cnct.vepu_cnct = 1; - rk_dvbm_set_reg(ctx, DVBM_VEPU_CNCT, 0x1); - } - port->linked = 1; - dvbm_debug_dump("=== vepu link ===\n"); - rk_dvbm_dump_regs(ctx); - dvbm_debug_dump("=== vepu link ===\n"); } - dvbm_debug("%s connect frm_cnt[%d : %d]\n", - dir == DVBM_ISP_PORT ? "isp" : "vepu", + dvbm_debug("%s %d connect frm_cnt[%d : %d]\n", + dir == DVBM_ISP_PORT ? "isp" : "vepu", id, ctx->isp_frm_start, ctx->isp_frm_end); return ret; } EXPORT_SYMBOL(rk_dvbm_link); -int rk_dvbm_unlink(struct dvbm_port *port) +int rk_dvbm_unlink(struct dvbm_port *port, int id) { struct dvbm_ctx *ctx; enum dvbm_port_dir dir; - struct rk_dvbm_regs *reg; if (WARN_ON(!port)) return -EINVAL; ctx = port_to_ctx(port); dir = port->dir; - reg = &ctx->regs; if (dir == DVBM_ISP_PORT) { - reg->isp_cnct.isp_cnct = 0; - rk_dvbm_set_reg(ctx, DVBM_ISP_CNCT, 0); - } else if (dir == DVBM_VEPU_PORT) { - reg->vepu_cnct.vepu_cnct = 0; - port->linked = 0; - rk_dvbm_set_reg(ctx, DVBM_VEPU_CNCT, 0); - if (!ctx->regs.dvbm_cfg.auto_resyn) { - u32 connect = 0; + if (id >= DVBM_CHANNEL_NUM) + dvbm_err("id %d is invalid\n", id); - dvbm2enc_callback(ctx, DVBM_VEPU_REQ_CONNECT, &connect); - } + dvbm2enc_callback(ctx, DVBM_ISP_REQ_DISCONNECT, &id); + } else if (dir == DVBM_VEPU_PORT) { } dvbm_debug("%s disconnect\n", dir == DVBM_ISP_PORT ? "isp" : "vepu"); @@ -430,27 +234,9 @@ int rk_dvbm_set_cb(struct dvbm_port *port, struct dvbm_cb *cb) } EXPORT_SYMBOL(rk_dvbm_set_cb); -static void rk_dvbm_update_next_adr(struct dvbm_ctx *ctx) -{ - u32 frame_cnt = ctx->isp_frm_start; - struct dvbm_isp_cfg_t *isp_cfg = &ctx->isp_cfg; - struct dvbm_addr_cfg *vepu_cfg = &ctx->vepu_cfg; - u32 y_wrap_size = isp_cfg->ybuf_top - isp_cfg->ybuf_bot; - u32 c_wrap_size = isp_cfg->cbuf_top - isp_cfg->cbuf_bot; - u32 s_off; - - frame_cnt = (frame_cnt + 1) % (ctx->loopcnt); - s_off = (frame_cnt * isp_cfg->ybuf_fstd) % y_wrap_size; - vepu_cfg->ybuf_sadr = isp_cfg->dma_addr + isp_cfg->ybuf_bot + s_off; - - s_off = (frame_cnt * isp_cfg->cbuf_fstd) % c_wrap_size; - vepu_cfg->cbuf_sadr = isp_cfg->dma_addr + isp_cfg->cbuf_bot + s_off; -} - int rk_dvbm_ctrl(struct dvbm_port *port, enum dvbm_cmd cmd, void *arg) { struct dvbm_ctx *ctx; - struct rk_dvbm_regs *reg; if ((cmd < DVBM_ISP_CMD_BASE) || (cmd > DVBM_VEPU_CMD_BUTT)) { dvbm_err("%s input cmd invalid\n", __func__); @@ -458,28 +244,43 @@ int rk_dvbm_ctrl(struct dvbm_port *port, enum dvbm_cmd cmd, void *arg) } ctx = port_to_ctx(port); - reg = &ctx->regs; switch (cmd) { case DVBM_ISP_SET_CFG: { struct dvbm_isp_cfg_t *cfg = (struct dvbm_isp_cfg_t *)arg; + struct dvbm_addr_cfg *dvbm_adr; + u32 chan_id = cfg->chan_id; - memcpy(&ctx->isp_cfg, cfg, sizeof(struct dvbm_isp_cfg_t)); - rk_dvbm_setup_iobuf(ctx); + if (chan_id >= DVBM_CHANNEL_NUM) { + dvbm_err("%s cmd %d chan id %d is invalid\n", __func__, cmd, chan_id); + return -EINVAL; + } + + memcpy(&ctx->isp_cfg[chan_id], cfg, sizeof(struct dvbm_isp_cfg_t)); init_isp_infos(ctx); - rk_dvbm_update_next_adr(ctx); + + dvbm_adr = &ctx->dvbm_addr[chan_id]; + dvbm_adr->chan_id = chan_id; + dvbm_adr->ybuf_bot = cfg->dma_addr + cfg->ybuf_bot; + dvbm_adr->ybuf_top = cfg->dma_addr + cfg->ybuf_top; + dvbm_adr->ybuf_sadr = cfg->dma_addr + cfg->ybuf_bot; + dvbm_adr->cbuf_bot = cfg->dma_addr + cfg->cbuf_bot; + dvbm_adr->cbuf_top = cfg->dma_addr + cfg->cbuf_top; + dvbm_adr->cbuf_sadr = cfg->dma_addr + cfg->cbuf_bot; + dvbm2enc_callback(ctx, DVBM_ISP_SET_DVBM_CFG, cfg); } break; case DVBM_ISP_FRM_START: { + dvbm2enc_callback(ctx, DVBM_VEPU_NOTIFY_FRM_STR, arg); rk_dvbm_update_isp_frm_info(ctx, 0); rk_dvbm_show_time(ctx); } break; case DVBM_ISP_FRM_END: { u32 line_cnt = ctx->isp_max_lcnt; + dvbm2enc_callback(ctx, DVBM_VEPU_NOTIFY_FRM_END, arg); ctx->isp_frm_end = *(u32 *)arg; /* wrap frame_cnt 0 - 255 */ ctx->isp_frm_info.frame_cnt = (ctx->isp_frm_start + 1) % 256; - rk_dvbm_update_next_adr(ctx); rk_dvbm_update_isp_frm_info(ctx, line_cnt); ctx->isp_frm_start++; dvbm_debug("isp frame end[%d : %d]\n", ctx->isp_frm_start, ctx->isp_frm_end); @@ -504,38 +305,14 @@ int rk_dvbm_ctrl(struct dvbm_port *port, enum dvbm_cmd cmd, void *arg) } break; case DVBM_VEPU_GET_ADR: { struct dvbm_addr_cfg *dvbm_adr = (struct dvbm_addr_cfg *)arg; - struct rk_dvbm_base *addr_base = ®->addr_base; + u32 chan_id = dvbm_adr->chan_id; - dvbm_adr->ybuf_top = addr_base->ybuf_top; - dvbm_adr->ybuf_bot = addr_base->ybuf_bot; - dvbm_adr->cbuf_top = addr_base->cbuf_top; - dvbm_adr->cbuf_bot = addr_base->cbuf_bot; - dvbm_adr->cbuf_sadr = ctx->vepu_cfg.cbuf_sadr; - dvbm_adr->ybuf_sadr = ctx->vepu_cfg.ybuf_sadr; - dvbm_adr->overflow = ctx->isp_frm_info.line_cnt >= ctx->wrap_line; - dvbm_adr->frame_id = ctx->isp_frm_info.frame_cnt; - dvbm_adr->line_cnt = ctx->isp_frm_info.line_cnt; - } break; - case DVBM_VEPU_GET_FRAME_INFO: { - memcpy(arg, &ctx->isp_frm_info, sizeof(struct dvbm_isp_frm_info)); - } break; - case DVBM_VEPU_SET_RESYNC: { - reg->dvbm_cfg.auto_resyn = *(u32 *)arg; - dev_info(ctx->dev, "change resync %s\n", - reg->dvbm_cfg.auto_resyn ? "auto" : "soft"); - rk_dvbm_set_reg(ctx, DVBM_CFG, ((u32 *)®->dvbm_cfg)[0]); - } break; - case DVBM_VEPU_SET_CFG: { - struct dvbm_vepu_cfg *cfg = (struct dvbm_vepu_cfg *)arg; + if (chan_id >= DVBM_CHANNEL_NUM) { + dvbm_err("%s cmd %d chan id %d is invalid\n", __func__, cmd, chan_id); + return -EINVAL; + } - reg->dvbm_cfg.auto_resyn = cfg->auto_resyn; - reg->dvbm_cfg.ignore_vepu_cnct_ack = cfg->ignore_vepu_cnct_ack; - reg->dvbm_cfg.start_point_after_vepu_cnct = cfg->start_point_after_vepu_cnct; - - rk_dvbm_set_reg(ctx, DVBM_CFG, ((u32 *)®->dvbm_cfg)[0]); - } break; - case DVBM_VEPU_DUMP_REGS: { - rk_dvbm_dump_regs(ctx); + *dvbm_adr = ctx->dvbm_addr[chan_id]; } break; default: { } break; @@ -545,163 +322,27 @@ int rk_dvbm_ctrl(struct dvbm_port *port, enum dvbm_cmd cmd, void *arg) } EXPORT_SYMBOL(rk_dvbm_ctrl); -static void dvbm_check_irq(struct dvbm_ctx *ctx) -{ - u32 irq_st = ctx->irq_status; - u32 cur_st = ctx->dvbm_status; - - if (irq_st & ISP_CNCT) { - dvbm_debug_irq("%s isp connect success! st 0x%08x\n", - __func__, cur_st); - ctx->port_isp.linked = 1; - } - if (irq_st & ISP_DISCNCT) { - dvbm_debug_irq("%s isp disconnect success!\n", __func__); - ctx->port_isp.linked = 0; - } - if (irq_st & VEPU_CNCT) { - dvbm_debug_irq("%s vepu connect success! st 0x%08x\n", - __func__, cur_st); - ctx->port_vepu.linked = 1; - } - if (irq_st & VEPU_DISCNCT) { - dvbm_debug_irq("%s vepu disconnect success! st 0x%08x\n", __func__, cur_st); - ctx->port_vepu.linked = 0; - } - if (irq_st & BUF_OVERFLOW) { - dvbm_debug_irq("%s buf overflow st 0x%08x auto_resync %d ignore %d\n", - __func__, cur_st, ctx->regs.dvbm_cfg.auto_resyn, ctx->ignore_ovfl); - - if (!ctx->regs.dvbm_cfg.auto_resyn && !ctx->ignore_ovfl) - rk_dvbm_unlink(&ctx->port_vepu); - } - if (irq_st & (ISP_CNCT_TIMEOUT | VEPU_CNCT_TIMEOUT)) - rk_dvbm_dump_regs(ctx); -} - -static irqreturn_t rk_dvbm_irq(int irq, void *param) -{ - struct dvbm_ctx *ctx = param; - u32 irq_st = 0; - u32 cur_st = 0; - - if (ctx->reg_base) { - /* read irq st */ - irq_st = rk_dvbm_read_reg(ctx, DVBM_INT_ST); - cur_st = rk_dvbm_read_reg(ctx, DVBM_ST); - if (irq_st & BUF_OVERFLOW) { - dvbm_debug_dump("=== dvbm overflow! dump reg st: 0x%08x===\n", irq_st); - rk_dvbm_dump_regs(ctx); - dvbm2enc_callback(ctx, DVBM_VEPU_NOTIFY_DUMP, NULL); - dvbm_debug_dump("=== dvbm overflow! dump reg end===\n"); - } - /* clr irq */ - rk_dvbm_set_reg(ctx, DVBM_INT_CLR, irq_st); - rk_dvbm_set_reg(ctx, DVBM_INT_ST, 0); - } - ctx->irq_status = irq_st; - ctx->dvbm_status = cur_st; - - dvbm_debug_irq("%s irq status 0x%08x\n", __func__, irq_st); - - return IRQ_WAKE_THREAD; -} - -static irqreturn_t rk_dvbm_isr(int irq, void *param) -{ - struct dvbm_ctx *ctx = param; - - dvbm_check_irq(ctx); - - return IRQ_HANDLED; -} - static int rk_dvbm_probe(struct platform_device *pdev) { - int ret; struct dvbm_ctx *ctx = NULL; struct device *dev = &pdev->dev; - struct resource *res = NULL; dev_info(dev, "probe start\n"); ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; - dev_info(dev, "dvbm ctx %p\n", ctx); ctx->dev = dev; - - atomic_set(&ctx->isp_ref, 0); - atomic_set(&ctx->vepu_ref, 0); ctx->port_isp.dir = DVBM_ISP_PORT; ctx->port_vepu.dir = DVBM_VEPU_PORT; platform_set_drvdata(pdev, ctx); - pm_runtime_enable(dev); - - /* get irq */ - ctx->irq = platform_get_irq(pdev, 0); - if (ctx->irq < 0) { - dev_err(&pdev->dev, "no interrupt resource found\n"); - ret = -ENODEV; - goto failed; - } - /* get mem resource */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no memory resource defined\n"); - ret = -ENODEV; - goto failed; - } - - ctx->reg_base = devm_ioremap_resource(dev, res); - if (IS_ERR_OR_NULL(ctx->reg_base)) { - dev_err(dev, "ioremap failed for resource %pR\n", res); - ret = -ENODEV; - goto failed; - } - - ctx->clk = devm_clk_get(ctx->dev, "clk_core"); - if (IS_ERR_OR_NULL(ctx->clk)) { - dev_err(dev, "clk_get failed for resource %pR\n", res); - ret = -ENODEV; - goto failed; - } - ctx->rst = devm_reset_control_get(ctx->dev, "dvbm_rst"); - if (IS_ERR_OR_NULL(ctx->rst)) { - dev_err(dev, "clk_rst failed for resource %pR\n", res); - ret = -ENODEV; - goto failed; - } - if (!SOFT_DVBM) { - ret = pm_runtime_get_sync(dev); - if (ret) - dev_err(dev, "pm get failed!\n"); - ret = rk_dvbm_clk_on(ctx); - if (ret) - goto failed; - } g_ctx = ctx; - rk_dvbm_reg_init(ctx); - ctx->ignore_ovfl = 1; - ctx->dump_s = 0x80; - ctx->dump_e = 0xb8; - ret = devm_request_threaded_irq(dev, ctx->irq, - rk_dvbm_irq, rk_dvbm_isr, - IRQF_ONESHOT, dev_name(dev), ctx); - if (ret) { - dev_err(dev, "register interrupter failed\n"); - goto failed; - } + dev_info(dev, "probe success\n"); return 0; - -failed: - pm_runtime_disable(dev); - - return ret; } static int rk_dvbm_remove(struct platform_device *pdev) @@ -709,11 +350,6 @@ static int rk_dvbm_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; dev_info(dev, "remove device\n"); - if (!SOFT_DVBM) { - rk_dvbm_clk_off(g_ctx); - pm_runtime_put(dev); - } - pm_runtime_disable(dev); return 0; } diff --git a/drivers/video/rockchip/dvbm/rockchip_dvbm.h b/drivers/video/rockchip/dvbm/rockchip_dvbm.h deleted file mode 100644 index 9df38b8cbd58..000000000000 --- a/drivers/video/rockchip/dvbm/rockchip_dvbm.h +++ /dev/null @@ -1,214 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2022 Rockchip Electronics Co., Ltd. - */ -#ifndef __ROCKCHIP_DVBM_H__ -#define __ROCKCHIP_DVBM_H__ - -#include -#include - -struct rk_dvbm_base { - /* 0x2c */ - u32 ybuf_bot; - /* 0x30 */ - u32 ybuf_top; - /* 0x34 */ - u32 ybuf_sadr; - /* 0x38 */ - u32 ybuf_lstd; - /* 0x3c */ - u32 ybuf_fstd; - /* 0x40 */ - u32 cbuf_bot; - /* 0x44 */ - u32 cbuf_top; - /* 0x48 */ - u32 cbuf_sadr; - /* 0x4c */ - u32 cbuf_lstd; - /* 0x50 */ - u32 cbuf_fstd; - /* 0x54 */ - u32 aful_thdy; - /* 0x58 */ - u32 aful_thdc; - /* 0x5c */ - u32 oful_thdy; - /* 0x60 */ - u32 oful_thdc; -}; - -struct rk_dvbm_regs { - /* 0x0 */ - u32 version; - - /* 0x4 */ - struct { - u32 isp_cnct : 1; - u32 reserved : 31; - } isp_cnct; - - /* 0x8 */ - struct { - u32 vepu_cnct : 1; - u32 reserved : 31; - } vepu_cnct; - - /* 0xc */ - struct { - u32 auto_resyn : 1; - u32 ignore_vepu_cnct_ack : 1; - /* - * 1’b0 : the current ISP frame - * 1’b1 : the next ISP frame - */ - u32 start_point_after_vepu_cnct : 1; - u32 reserved0 : 5; - /* only support yuv420sp 4'h0 */ - u32 fmt : 4; - u32 reserved1 : 20; - } dvbm_cfg; - - /* 0x10 */ - struct { - u32 wdg_isp_cnct_timeout : 22; - u32 reserved : 10; - } wdg_cfg0; - - /* 0x14 */ - struct { - u32 wdg_vepu_cnct_timeout : 22; - u32 reserved : 10; - } wdg_cfg1; - - /* 0x18 */ - struct { - u32 wdg_vepu_handshake_timeout : 22; - u32 reserved : 10; - } wdg_cfg2; - - /* 0x1c */ - struct { - u32 buf_ovfl : 1; - u32 resync_finish : 1; - u32 isp_cnct_timeout : 1; - u32 vepu_cnct_timeout : 1; - - u32 vepu_handshake_timeout : 1; - u32 isp_cnct : 1; - u32 isp_discnct : 1; - u32 vepu_cnct : 1; - - u32 vepu_discnct : 1; - u32 reserved : 23; - } int_en; - - /* 0x20 */ - struct { - u32 buf_ovfl : 1; - u32 resync_finish : 1; - u32 isp_cnct_timeout : 1; - u32 vepu_cnct_timeout : 1; - - u32 vepu_handshake_timeout : 1; - u32 isp_cnct : 1; - u32 isp_discnct : 1; - u32 vepu_cnct : 1; - - u32 vepu_discnct : 1; - u32 reserved : 23; - } int_msk; - - /* 0x24 */ - struct { - u32 buf_ovfl : 1; - u32 resync_finish : 1; - u32 isp_cnct_timeout : 1; - u32 vepu_cnct_timeout : 1; - - u32 vepu_handshake_timeout : 1; - u32 isp_cnct : 1; - u32 isp_discnct : 1; - u32 vepu_cnct : 1; - - u32 vepu_discnct : 1; - u32 reserved : 23; - } int_clr; - - /* 0x28 */ - struct { - u32 buf_ovfl : 1; - u32 resync_finish : 1; - u32 isp_cnct_timeout : 1; - u32 vepu_cnct_timeout : 1; - - u32 vepu_handshake_timeout : 1; - u32 isp_cnct : 1; - u32 isp_discnct : 1; - u32 vepu_cnct : 1; - - u32 vepu_discnct : 1; - u32 reserved : 23; - } int_st; - struct rk_dvbm_base addr_base; - /* 0x64 - 0x7c */ - u32 reserved[7]; - - /* 0x80 */ - struct { - u32 isp_connection : 1; - u32 vepu_connection : 1; - u32 resynchronization : 1; - u32 y_buf_ovfl : 1; - - u32 c_buf_ovfl : 1; - u32 reserved : 27; - } dvbm_st; - - /* 0x84 */ - u32 ovfl_st; -}; - -struct dvbm_ctx { - struct clk *clk; - struct device *dev; - void __iomem *reg_base; - struct rk_dvbm_regs regs; - struct reset_control *rst; - - u32 isp_connet; - u32 vepu_connet; - u32 buf_overflow; - u32 irq_status; - u32 dvbm_status; - int irq; - - /* vepu infos */ - struct dvbm_port port_vepu; - atomic_t vepu_ref; - atomic_t vepu_link; - struct dvbm_cb vepu_cb; - struct dvbm_addr_cfg vepu_cfg; - - /* isp infos */ - struct dvbm_port port_isp; - struct dvbm_cb isp_cb; - struct dvbm_isp_cfg_t isp_cfg; - struct dvbm_isp_frm_info isp_frm_info; - atomic_t isp_link; - atomic_t isp_ref; - u32 isp_max_lcnt; - u32 isp_frm_start; - u32 isp_frm_end; - ktime_t isp_frm_time; - u32 wrap_line; - - /* debug infos */ - u32 dump_s; - u32 dump_e; - u32 ignore_ovfl; - u32 loopcnt; -}; - -#endif diff --git a/include/soc/rockchip/rockchip_dvbm.h b/include/soc/rockchip/rockchip_dvbm.h index dd69047a26d4..07b000f48212 100644 --- a/include/soc/rockchip/rockchip_dvbm.h +++ b/include/soc/rockchip/rockchip_dvbm.h @@ -24,11 +24,7 @@ enum dvbm_cmd { DVBM_ISP_CMD_BUTT, DVBM_VEPU_CMD_BASE = 0x10, - DVBM_VEPU_SET_RESYNC, - DVBM_VEPU_SET_CFG, DVBM_VEPU_GET_ADR, - DVBM_VEPU_GET_FRAME_INFO, - DVBM_VEPU_DUMP_REGS, DVBM_VEPU_CMD_BUTT, }; @@ -42,6 +38,9 @@ enum isp_frame_status { enum dvbm_cb_event { DVBM_ISP_EVENT_BASE = 0, + DVBM_ISP_REQ_CONNECT, + DVBM_ISP_REQ_DISCONNECT, + DVBM_ISP_SET_DVBM_CFG, DVBM_ISP_EVENT_BUTT, DVBM_VEPU_EVENT_BASE = 0x10, @@ -60,9 +59,7 @@ struct dvbm_port { }; struct dvbm_isp_cfg_t { - u32 fmt; - u32 timeout; - + u32 chan_id; struct dmabuf *buf; dma_addr_t dma_addr; u32 ybuf_top; @@ -75,12 +72,6 @@ struct dvbm_isp_cfg_t { u32 cbuf_fstd; }; -struct dvbm_isp_frm_cfg { - s32 frm_idx; - u32 ybuf_start; - u32 cbuf_start; -}; - struct dvbm_isp_frm_info { u32 frame_cnt; u32 line_cnt; @@ -96,14 +87,7 @@ struct dvbm_addr_cfg { u32 cbuf_bot; u32 cbuf_sadr; u32 frame_id; - u32 line_cnt; - u32 overflow; -}; - -struct dvbm_vepu_cfg { - u32 auto_resyn; - u32 ignore_vepu_cnct_ack; - u32 start_point_after_vepu_cnct; + u32 chan_id; }; typedef int (*dvbm_callback)(void *ctx, enum dvbm_cb_event event, void *arg); @@ -119,8 +103,8 @@ struct dvbm_cb { struct dvbm_port *rk_dvbm_get_port(struct platform_device *pdev, enum dvbm_port_dir dir); int rk_dvbm_put(struct dvbm_port *port); -int rk_dvbm_link(struct dvbm_port *port); -int rk_dvbm_unlink(struct dvbm_port *port); +int rk_dvbm_link(struct dvbm_port *port, int id); +int rk_dvbm_unlink(struct dvbm_port *port, int id); int rk_dvbm_set_cb(struct dvbm_port *port, struct dvbm_cb *cb); int rk_dvbm_ctrl(struct dvbm_port *port, enum dvbm_cmd cmd, void *arg); @@ -137,11 +121,11 @@ static inline int rk_dvbm_put(struct dvbm_port *port) return -ENODEV; } -static inline int rk_dvbm_link(struct dvbm_port *port) +static inline int rk_dvbm_link(struct dvbm_port *port, int id) { return -ENODEV; } -static inline int rk_dvbm_unlink(struct dvbm_port *port) +static inline int rk_dvbm_unlink(struct dvbm_port *port, int id) { return -ENODEV; } From fdce2e1ee055d9b9b9f9b376c929b9f51c78126a Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 7 Feb 2025 20:02:43 +0800 Subject: [PATCH 04/16] Revert "power: charger: add new sy6982c/sy6982e driver" This reverts commit 38c57424d483a2b17f36e73c8e031119ddfec76c. Signed-off-by: Tao Huang Change-Id: Ibad478fd393cb69fa78a00020eebc65d43c5ac5d --- .../bindings/power/sy6982c-charger.txt | 14 - drivers/power/sy6982c_charger.c | 401 ------------------ 2 files changed, 415 deletions(-) delete mode 100644 Documentation/devicetree/bindings/power/sy6982c-charger.txt delete mode 100644 drivers/power/sy6982c_charger.c diff --git a/Documentation/devicetree/bindings/power/sy6982c-charger.txt b/Documentation/devicetree/bindings/power/sy6982c-charger.txt deleted file mode 100644 index 9ec4d54b24de..000000000000 --- a/Documentation/devicetree/bindings/power/sy6982c-charger.txt +++ /dev/null @@ -1,14 +0,0 @@ -Binding for sy6982c Charger - -Required properties: -- compatible: Should contain one of the following: - * "sy6982c-charger" -- extcon: extcon specifier for the Charger. - -Example: - - sy6982c { - status = "okay"; - compatible = "sy6982c-charger"; - extcon = <&u2phy0>; - }; diff --git a/drivers/power/sy6982c_charger.c b/drivers/power/sy6982c_charger.c deleted file mode 100644 index dfa82c3f8d27..000000000000 --- a/drivers/power/sy6982c_charger.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * sy6982c/sy6982e charger driver - * - * Copyright (C) 2016 Fuzhou Rockchip 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 -#include -#include - -enum charger_t { - USB_TYPE_UNKNOWN_CHARGER, - USB_TYPE_NONE_CHARGER, - USB_TYPE_USB_CHARGER, - USB_TYPE_AC_CHARGER, - USB_TYPE_CDP_CHARGER, - DC_TYPE_DC_CHARGER, - DC_TYPE_NONE_CHARGER, -}; - -struct sy6982c_charger { - struct device *dev; - struct power_supply *usb_psy; - struct workqueue_struct *usb_charger_wq; - struct delayed_work usb_work; - struct workqueue_struct *dc_charger_wq; - struct delayed_work dc_work; - struct delayed_work discnt_work; - struct notifier_block cable_cg_nb; - struct notifier_block cable_discnt_nb; - unsigned int bc_event; - enum charger_t usb_charger; - enum charger_t dc_charger; - bool extcon; - struct extcon_dev *cable_edev; - struct gpio_desc *dc_det_pin; - bool support_dc_det; -}; - -static void sy6982c_cg_bc_evt_worker(struct work_struct *work) -{ - struct sy6982c_charger *cg = container_of(work, - struct sy6982c_charger, usb_work.work); - struct extcon_dev *edev = cg->cable_edev; - enum charger_t charger = USB_TYPE_UNKNOWN_CHARGER; - const char *event[5] = {"UN", "NONE", "USB", "AC", "CDP1.5A"}; - - /* Determine cable/charger type */ - if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_SDP) > 0) - charger = USB_TYPE_USB_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_DCP) > 0) - charger = USB_TYPE_AC_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_CDP) > 0) - charger = USB_TYPE_CDP_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_DCP) == 0) - charger = USB_TYPE_NONE_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_CDP) == 0) - charger = USB_TYPE_NONE_CHARGER; - - if (charger != USB_TYPE_UNKNOWN_CHARGER) { - dev_info(cg->dev, "receive type-c notifier event: %s...\n", - event[charger]); - cg->usb_charger = charger; - } -} - -static int sy6982c_cg_charger_evt_notifier(struct notifier_block *nb, - unsigned long event, - void *ptr) -{ - struct sy6982c_charger *cg = - container_of(nb, struct sy6982c_charger, cable_cg_nb); - - queue_delayed_work(cg->usb_charger_wq, &cg->usb_work, - msecs_to_jiffies(10)); - - return NOTIFY_DONE; -} - -static void sy6982c_cg_discnt_evt_worker(struct work_struct *work) -{ - struct sy6982c_charger *cg = container_of(work, - struct sy6982c_charger, discnt_work.work); - - if (extcon_get_cable_state_(cg->cable_edev, EXTCON_USB) == 0) { - dev_info(cg->dev, "receive type-c notifier event: DISCNT...\n"); - cg->usb_charger = USB_TYPE_NONE_CHARGER; - } -} - -static int sy6982c_cg_discnt_evt_notfier(struct notifier_block *nb, - unsigned long event, void *ptr) -{ - struct sy6982c_charger *cg = - container_of(nb, struct sy6982c_charger, cable_discnt_nb); - - queue_delayed_work(cg->usb_charger_wq, &cg->discnt_work, - msecs_to_jiffies(10)); - - return NOTIFY_DONE; -} - -static int sy6982c_cg_init_usb(struct sy6982c_charger *cg) -{ - struct device *dev = cg->dev; - int ret; - struct extcon_dev *edev; - - if (!cg->extcon) - return -1; - - edev = extcon_get_edev_by_phandle(dev, 0); - if (IS_ERR(edev)) { - if (PTR_ERR(edev) != -EPROBE_DEFER) - dev_err(dev, "Invalid or missing extcon\n"); - return PTR_ERR(edev); - } - - cg->usb_charger_wq = alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - "sy6982c-usb-wq"); - cg->usb_charger = USB_TYPE_NONE_CHARGER; - - /* Register chargers */ - INIT_DELAYED_WORK(&cg->usb_work, sy6982c_cg_bc_evt_worker); - cg->cable_cg_nb.notifier_call = sy6982c_cg_charger_evt_notifier; - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_SDP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for SDP\n"); - goto __fail; - } - - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_DCP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for DCP\n"); - goto __fail; - } - - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_CDP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for CDP\n"); - goto __fail; - } - - /* Register discnt usb */ - INIT_DELAYED_WORK(&cg->discnt_work, sy6982c_cg_discnt_evt_worker); - cg->cable_discnt_nb.notifier_call = sy6982c_cg_discnt_evt_notfier; - ret = devm_extcon_register_notifier(dev, edev, EXTCON_USB, - &cg->cable_discnt_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for HOST\n"); - goto __fail; - } - - cg->cable_edev = edev; - schedule_delayed_work(&cg->usb_work, 0); - dev_info(cg->dev, "register extcon evt notifier\n"); - - return 0; - -__fail: - destroy_workqueue(cg->usb_charger_wq); - return ret; -} - -static enum power_supply_property sy6982c_usb_props[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_STATUS, -}; - -static int sy6982c_cg_usb_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct sy6982c_charger *cg = power_supply_get_drvdata(psy); - int online = 0; - int ret = 0; - - if (cg->usb_charger != USB_TYPE_UNKNOWN_CHARGER && - cg->usb_charger != USB_TYPE_NONE_CHARGER) - online = 1; - if (cg->dc_charger != DC_TYPE_NONE_CHARGER) - online = 1; - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = online; - - dev_dbg(cg->dev, "report online: %d\n", val->intval); - break; - case POWER_SUPPLY_PROP_STATUS: - if (online) - val->intval = POWER_SUPPLY_STATUS_CHARGING; - else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - - dev_dbg(cg->dev, "report prop: %d\n", val->intval); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct power_supply_desc sy6982c_usb_desc = { - .name = "sy6982c_usb", - .type = POWER_SUPPLY_TYPE_USB, - .properties = sy6982c_usb_props, - .num_properties = ARRAY_SIZE(sy6982c_usb_props), - .get_property = sy6982c_cg_usb_get_property, -}; - -static int sy6982c_cg_init_power_supply(struct sy6982c_charger *cg) -{ - struct power_supply_config psy_cfg = { .drv_data = cg, }; - - cg->usb_psy = devm_power_supply_register(cg->dev, &sy6982c_usb_desc, - &psy_cfg); - if (IS_ERR(cg->usb_psy)) { - dev_err(cg->dev, "register usb power supply fail\n"); - return PTR_ERR(cg->usb_psy); - } - - return 0; -} - -#ifdef CONFIG_OF -static int sy6982c_charger_parse_dt(struct sy6982c_charger *cg) -{ - struct device *dev = cg->dev; - - cg->dc_det_pin = devm_gpiod_get_optional(dev, "dc-det", - GPIOD_IN); - if (!IS_ERR_OR_NULL(cg->dc_det_pin)) { - cg->support_dc_det = true; - } else { - dev_err(dev, "invalid dc det gpio!\n"); - cg->support_dc_det = false; - } - - return 0; -} -#else -static int sy6982c_charger_parse_dt(struct sy6982c_charger *cg) -{ - return -ENODEV; -} -#endif - -static enum charger_t sy6982c_charger_get_dc_state(struct sy6982c_charger *cg) -{ - return (gpiod_get_value(cg->dc_det_pin)) ? - DC_TYPE_DC_CHARGER : DC_TYPE_NONE_CHARGER; -} - -static void sy6982c_charger_dc_det_worker(struct work_struct *work) -{ - enum charger_t charger; - struct sy6982c_charger *cg = container_of(work, - struct sy6982c_charger, dc_work.work); - - charger = sy6982c_charger_get_dc_state(cg); - if (charger == DC_TYPE_DC_CHARGER) - cg->dc_charger = charger; - else - cg->dc_charger = DC_TYPE_NONE_CHARGER; - - rk_send_wakeup_key(); -} - -static irqreturn_t sy6982c_charger_dc_det_isr(int irq, void *charger) -{ - struct sy6982c_charger *cg = (struct sy6982c_charger *)charger; - - queue_delayed_work(cg->dc_charger_wq, &cg->dc_work, - msecs_to_jiffies(10)); - - return IRQ_HANDLED; -} - -static int sy6982c_charger_init_dc(struct sy6982c_charger *cg) -{ - int ret; - unsigned long irq_flags; - unsigned int dc_det_irq; - - if (!cg->support_dc_det) - return 0; - - cg->dc_charger_wq = alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - "sy6982c-dc-wq"); - if (!cg->dc_charger_wq) - return -EINVAL; - - INIT_DELAYED_WORK(&cg->dc_work, sy6982c_charger_dc_det_worker); - cg->dc_charger = DC_TYPE_NONE_CHARGER; - - if (gpiod_get_value(cg->dc_det_pin)) - cg->dc_charger = DC_TYPE_DC_CHARGER; - else - cg->dc_charger = DC_TYPE_NONE_CHARGER; - - irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - dc_det_irq = gpiod_to_irq(cg->dc_det_pin); - ret = devm_request_irq(cg->dev, dc_det_irq, sy6982c_charger_dc_det_isr, - irq_flags, "sy6982c_dc_det", cg); - if (ret != 0) { - dev_err(cg->dev, "sy6982c_dc_det_irq request failed!\n"); - return ret; - } - - enable_irq_wake(dc_det_irq); - - return 0; -} - -static int sy6982c_charger_probe(struct platform_device *pdev) -{ - struct sy6982c_charger *cg; - int ret; - - cg = devm_kzalloc(&pdev->dev, sizeof(*cg), GFP_KERNEL); - if (!cg) - return -ENOMEM; - - cg->dev = &pdev->dev; - sy6982c_charger_parse_dt(cg); - sy6982c_charger_init_dc(cg); - cg->extcon = device_property_read_bool(cg->dev, "extcon"); - ret = sy6982c_cg_init_usb(cg); - if (ret) { - dev_err(cg->dev, "init usb failed!\n"); - return ret; - } - - ret = sy6982c_cg_init_power_supply(cg); - if (ret) { - dev_err(cg->dev, "init power supply fail!\n"); - return ret; - } - - dev_info(cg->dev, "driver registered\n"); - - return 0; -} - -static int sy6982c_charger_remove(struct platform_device *pdev) -{ - struct sy6982c_charger *cg = platform_get_drvdata(pdev); - - if (cg->usb_charger_wq) - destroy_workqueue(cg->usb_charger_wq); - - return 0; -} - -static const struct of_device_id sy6982c_charger_match[] = { - { - .compatible = "sy6982c-charger", - }, - {}, -}; - -static struct platform_driver sy6982c_charger_driver = { - .probe = sy6982c_charger_probe, - .remove = sy6982c_charger_remove, - .driver = { - .name = "sy6982c-charger", - .of_match_table = sy6982c_charger_match, - }, -}; - -module_platform_driver(sy6982c_charger_driver); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:sy6982c-charger"); -MODULE_AUTHOR("chen Shunqing"); From aa897b8ab2577b6a401aed712bb7e126fb7ce85f Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 7 Feb 2025 20:09:31 +0800 Subject: [PATCH 05/16] Revert "misc: add gpio-detection driver" This reverts commit d0d2368bf80e798523843e8388bf164ee99e2495. Signed-off-by: Tao Huang Change-Id: I5d38c29967a7a284fd1bb048fdd96247931a0b0d --- .../bindings/gpio/gpio-detection.txt | 37 -- drivers/misc/gpio-detection.c | 442 ------------------ include/linux/gpio_detection.h | 51 -- 3 files changed, 530 deletions(-) delete mode 100644 Documentation/devicetree/bindings/gpio/gpio-detection.txt delete mode 100644 drivers/misc/gpio-detection.c delete mode 100644 include/linux/gpio_detection.h diff --git a/Documentation/devicetree/bindings/gpio/gpio-detection.txt b/Documentation/devicetree/bindings/gpio/gpio-detection.txt deleted file mode 100644 index 78bd530c8290..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-detection.txt +++ /dev/null @@ -1,37 +0,0 @@ -Required properties: -- compatible: should be "gpio-detection" -- status: -- pinctrl-0 : phandle referencing pin configuration of the gpio controller -- pinctrl-names : a pinctrl state named "default" must be defined -- car-reverse : a describtion to show the gpio will be use to car reverse -- car-acc : a describtion to show the gpio will be use to car accelerate -- gpios : The GPIO to set high/low, see "gpios property" in - Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be - low to power down the board set it to "Active Low", otherwise set - gpio to "Active High". -- linux,debounce-ms: interrupt debounce time. (u32) -- label : The label / name for this partition. If omitted, the label is taken -- gpio,wakeup : To enable the wakeup comparator in probe - -Example: - - gpio_det: gpio-det { - compatible = "gpio-detection"; - status = "okay"; - - pinctrl-0 = <&gpio3_b1 &gpio3_b2>; - pinctrl-names = "default"; - car-reverse { - car-reverse-gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>; - linux,debounce-ms = <5>; - label = "car-reverse"; - gpio,wakeup; - }; - - car-acc { - car-acc-gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>; - linux,debounce-ms = <5>; - label = "car-acc"; - gpio,wakeup; - }; - }; diff --git a/drivers/misc/gpio-detection.c b/drivers/misc/gpio-detection.c deleted file mode 100644 index 69eda8e5e0ef..000000000000 --- a/drivers/misc/gpio-detection.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * gpio detection driver - * - * Copyright (C) 2015 Rockchip Electronics Co., Ltd. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 - -#define WAKE_LOCK_TIMEOUT_MS (5000) - -struct gpio_data { - struct gpio_detection *parent; - const char *name; - struct device dev; - int notify; - struct gpio_desc *gpio; - int val; - int irq; - struct delayed_work work; - unsigned int debounce_ms; - int wakeup; -}; - -struct gpio_detection { - struct class_attribute cls_attr; - struct device *dev; - int num; - struct gpio_data *data; - struct pinctrl *pinctrl; - struct pinctrl_state *pins_default; - struct notifier_block fb_notifier; - struct wake_lock wake_lock; - int mirror; - int type; - int info; -}; - -static struct class *gpio_detection_class; -static BLOCKING_NOTIFIER_HEAD(gpio_det_notifier_list); -static int system_suspend; - -#if IS_ENABLED(CONFIG_GPIO_DET) - -/* - * gpio_det_notifier_call_chain - notify clients of gpio_det_events - * - */ -int gpio_det_notifier_call_chain(unsigned long val, void *v) -{ - return blocking_notifier_call_chain(&gpio_det_notifier_list, val, v); -} -EXPORT_SYMBOL_GPL(gpio_det_notifier_call_chain); - -/* - * gpio_det_register_notifier - register a client notifier - * @nb: notifier block to callback on events - */ -int gpio_det_register_notifier(struct notifier_block *nb) -{ - int ret = blocking_notifier_chain_register(&gpio_det_notifier_list, nb); - - return ret; -} -EXPORT_SYMBOL(gpio_det_register_notifier); - -/* - * gpio_det_unregister_client - unregister a client notifier - * @nb: notifier block to callback on events - */ -int gpio_det_unregister_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&gpio_det_notifier_list, nb); -} -EXPORT_SYMBOL(gpio_det_unregister_notifier); - -#endif - -static void gpio_det_report_event(struct gpio_data *gpiod) -{ - struct gpio_event event; - struct gpio_detection *gpio_det = gpiod->parent; - char *status = NULL; - char *envp[2]; - - event.val = gpiod->val; - event.name = gpiod->name; - status = kasprintf(GFP_KERNEL, "GPIO_NAME=%s GPIO_STATE=%s", - gpiod->name, event.val ? "over" : "on"); - envp[0] = status; - envp[1] = NULL; - wake_lock_timeout(&gpio_det->wake_lock, - msecs_to_jiffies(WAKE_LOCK_TIMEOUT_MS)); - kobject_uevent_env(&gpiod->dev.kobj, KOBJ_CHANGE, envp); - if (gpiod->notify) - gpio_det_notifier_call_chain(GPIO_EVENT, &event); - kfree(status); -} - -static void gpio_det_work_func(struct work_struct *work) -{ - struct gpio_data *gpiod = container_of(work, struct gpio_data, - work.work); - int val = gpiod_get_value(gpiod->gpio); - - if (gpiod->val != val) { - gpiod->val = val; - gpio_det_report_event(gpiod); - if (system_suspend && gpiod->wakeup) { - rk_send_power_key(1); - rk_send_power_key(0); - } - } -} - -static irqreturn_t gpio_det_interrupt(int irq, void *dev_id) -{ - struct gpio_data *gpiod = dev_id; - int val = gpiod_get_raw_value(gpiod->gpio); - unsigned int irqflags = IRQF_ONESHOT; - - if (val) - irqflags |= IRQ_TYPE_EDGE_FALLING; - else - irqflags |= IRQ_TYPE_EDGE_RISING; - irq_set_irq_type(gpiod->irq, irqflags); - - mod_delayed_work(system_wq, &gpiod->work, - msecs_to_jiffies(gpiod->debounce_ms)); - - return IRQ_HANDLED; -} - -static int gpio_det_init_status_check(struct gpio_detection *gpio_det) -{ - struct gpio_data *gpiod; - int i; - - for (i = 0; i < gpio_det->num; i++) { - gpiod = &gpio_det->data[i]; - gpiod->val = gpiod_get_value(gpiod->gpio); - if (gpiod->val) - gpio_det_report_event(gpiod); - } - - return 0; -} - -static int gpio_det_fb_notifier_callback(struct notifier_block *self, - unsigned long event, - void *data) -{ - struct gpio_detection *gpio_det; - struct fb_event *evdata = data; - int fb_blank; - - if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) - return 0; - - gpio_det = container_of(self, struct gpio_detection, fb_notifier); - fb_blank = *(int *)evdata->data; - if (fb_blank == FB_BLANK_UNBLANK) - system_suspend = 0; - else - system_suspend = 1; - - return 0; -} - -static int gpio_det_fb_notifier_register(struct gpio_detection *gpio) -{ - gpio->fb_notifier.notifier_call = gpio_det_fb_notifier_callback; - - return fb_register_client(&gpio->fb_notifier); -} - -static ssize_t gpio_detection_info_show(struct class *class, - struct class_attribute *attr, - char *buf) -{ - struct gpio_detection *gpio_det; - - gpio_det = container_of(attr, struct gpio_detection, cls_attr); - - return sprintf(buf, "%d\n", gpio_det->info); -} - -static ssize_t status_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gpio_data *gpiod = container_of(dev, struct gpio_data, dev); - unsigned int val = gpiod_get_value(gpiod->gpio); - - return sprintf(buf, "%d\n", val); -} - -static ssize_t status_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gpio_data *gpiod; - int val; - int ret; - struct gpio_event event; - - gpiod = container_of(dev, struct gpio_data, dev); - ret = kstrtoint(buf, 0, &val); - if (ret < 0) - return ret; - if (val >= 0) { - event.val = val; - event.name = gpiod->name; - gpio_det_notifier_call_chain(GPIO_EVENT, &event); - } else { - gpiod->notify = 0; - } - - return count; -} - -static DEVICE_ATTR_RW(status); - -static struct attribute *gpio_detection_attrs[] = { - &dev_attr_status.attr, - NULL, -}; -ATTRIBUTE_GROUPS(gpio_detection); - -static int __init gpio_deteciton_class_init(void) -{ - gpio_detection_class = class_create(THIS_MODULE, "gpio-detection"); - if (IS_ERR(gpio_detection_class)) { - pr_err("create gpio_detection class failed (%ld)\n", - PTR_ERR(gpio_detection_class)); - return PTR_ERR(gpio_detection_class); - } - - return 0; -} - -static int gpio_detection_class_register(struct gpio_detection *gpio_det, - struct gpio_data *gpiod) -{ - int ret; - - gpiod->dev.class = gpio_detection_class; - dev_set_name(&gpiod->dev, "%s", gpiod->name); - dev_set_drvdata(&gpiod->dev, gpio_det); - ret = device_register(&gpiod->dev); - ret = sysfs_create_groups(&gpiod->dev.kobj, gpio_detection_groups); - - return ret; -} - -static int gpio_det_parse_dt(struct gpio_detection *gpio_det, - struct platform_device *pdev) -{ - struct gpio_data *data; - struct device *dev = &pdev->dev; - struct device_node *node; - struct gpio_data *gpiod; - struct fwnode_handle *child; - int count = 0; - int i = 0; - int num = 0; - - num = of_get_child_count(gpio_det->dev->of_node); - count = device_get_child_node_count(dev); - if (!count || !num) - return -ENODEV; - data = devm_kzalloc(gpio_det->dev, num * sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - of_property_read_u32(gpio_det->dev->of_node, "rockchip,camcap-type", - &gpio_det->type); - of_property_read_u32(gpio_det->dev->of_node, "rockchip,camcap-mirror", - &gpio_det->mirror); - gpio_det->info = (gpio_det->mirror << 4) | gpio_det->type; - device_for_each_child_node(dev, child) { - node = to_of_node(child); - gpiod = &data[i++]; - gpiod->parent = gpio_det; - gpiod->notify = 1; - gpiod->name = of_get_property(node, "label", NULL); - gpiod->wakeup = !!of_get_property(node, "gpio,wakeup", NULL); - of_property_read_u32(node, "linux,debounce-ms", - &gpiod->debounce_ms); - if (!strcmp(gpiod->name, "car-reverse")) - gpiod->gpio = devm_get_gpiod_from_child(dev, - "car-reverse", child); - else - gpiod->gpio = devm_get_gpiod_from_child(dev, - "car-acc", child); - } - gpio_det->num = num; - gpio_det->data = data; - - return 0; -} - -static int gpio_det_probe(struct platform_device *pdev) -{ - struct gpio_detection *gpio_det; - struct gpio_data *gpiod; - unsigned long irqflags = IRQF_ONESHOT; - int i; - int ret; - - gpio_det = devm_kzalloc(&pdev->dev, sizeof(*gpio_det), GFP_KERNEL); - if (!gpio_det) - return -ENOMEM; - gpio_det->dev = &pdev->dev; - gpio_det->cls_attr.attr.name = "info"; - gpio_det->cls_attr.attr.mode = S_IRUGO; - gpio_det->cls_attr.show = gpio_detection_info_show; - dev_set_name(gpio_det->dev, "gpio_detection"); - if (!pdev->dev.of_node) - return -EINVAL; - gpio_det->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR(gpio_det->pinctrl)) { - dev_err(&pdev->dev, "pinctrl get failed\n"); - return PTR_ERR(gpio_det->pinctrl); - } - gpio_det->pins_default = pinctrl_lookup_state(gpio_det->pinctrl, - PINCTRL_STATE_DEFAULT); - if (IS_ERR(gpio_det->pins_default)) - dev_err(gpio_det->dev, "get default pinstate failed\n"); - else - pinctrl_select_state(gpio_det->pinctrl, gpio_det->pins_default); - if (gpio_det_parse_dt(gpio_det, pdev)) - return -ENODEV; - wake_lock_init(&gpio_det->wake_lock, WAKE_LOCK_SUSPEND, - "gpio_detection"); - for (i = 0; i < gpio_det->num; i++) { - gpiod = &gpio_det->data[i]; - gpiod_direction_input(gpiod->gpio); - - gpiod->irq = gpiod_to_irq(gpiod->gpio); - if (gpiod->irq < 0) { - dev_err(gpio_det->dev, "failed to get irq number for GPIO %s\n", - gpiod->name); - continue; - } - - ret = gpio_detection_class_register(gpio_det, gpiod); - if (ret < 0) - return ret; - INIT_DELAYED_WORK(&gpiod->work, gpio_det_work_func); - gpiod->val = gpiod_get_raw_value(gpiod->gpio); - if (gpiod->val) - irqflags |= IRQ_TYPE_EDGE_FALLING; - else - irqflags |= IRQ_TYPE_EDGE_RISING; - ret = devm_request_threaded_irq(gpio_det->dev, gpiod->irq, - NULL, gpio_det_interrupt, - irqflags | IRQF_ONESHOT, - gpiod->name, gpiod); - if (ret < 0) - dev_err(gpio_det->dev, "request irq(%s) failed:%d\n", - gpiod->name, ret); - else - if (gpiod->wakeup) - enable_irq_wake(gpiod->irq); - } - - if (gpio_det->info) { - ret = class_create_file(gpio_detection_class, - &gpio_det->cls_attr); - if (ret) - dev_warn(gpio_det->dev, "create class file failed:%d\n", - ret); - } - - gpio_det_fb_notifier_register(gpio_det); - gpio_det_init_status_check(gpio_det); - - dev_info(gpio_det->dev, "gpio detection driver probe success\n"); - - return 0; -} - -#if defined(CONFIG_OF) -static const struct of_device_id gpio_det_of_match[] = { - { - .compatible = "gpio-detection" - }, - {}, -}; -#endif - -static struct platform_driver gpio_det_driver = { - .driver = { - .name = "gpio-detection", - .of_match_table = of_match_ptr(gpio_det_of_match), - }, - .probe = gpio_det_probe, -}; - -#ifdef CONFIG_VIDEO_REVERSE_IMAGE -int gpio_det_init(void) -#else -static int __init gpio_det_init(void) -#endif -{ - if (!gpio_deteciton_class_init()) - return platform_driver_register(&gpio_det_driver); - else - return -1; -} - -#ifndef CONFIG_VIDEO_REVERSE_IMAGE -fs_initcall_sync(gpio_det_init); -#endif -static void __exit gpio_det_exit(void) -{ - platform_driver_unregister(&gpio_det_driver); -} - -module_exit(gpio_det_exit); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:gpio-detection"); -MODULE_AUTHOR("ROCKCHIP"); diff --git a/include/linux/gpio_detection.h b/include/linux/gpio_detection.h deleted file mode 100644 index 57b2ff92bc50..000000000000 --- a/include/linux/gpio_detection.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * include/linux/gpio_detection.h - * - * Platform data structure for GPIO detection driver - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ -#ifndef __GPIO_DETECTION_H -#define __GPIO_DETECTION_H - -#define GPIO_EVENT 1 - -/* - * gpio event - * @val: 0 event active, 1 event over - * @name: event name - */ - -struct gpio_event { - int val; - const char *name; -}; - -#if IS_ENABLED(CONFIG_GPIO_DET) - -int gpio_det_register_notifier(struct notifier_block *nb); -int gpio_det_unregister_notifier(struct notifier_block *nb); -int gpio_det_notifier_call_chain(unsigned long val, void *v); - -#else - -static inline int gpio_det_register_notifier(struct notifier_block *nb) -{ - return -EINVAL; -}; - -static inline int gpio_det_unregister_notifier(struct notifier_block *nb) -{ - return -EINVAL; -}; - -static inline int gpio_det_notifier_call_chain(unsigned long val, void *v) -{ - return -EINVAL; -}; - -#endif - -#endif From 668a142bfbe9c576a08be8e29bfe8a74c936396b Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Tue, 21 Jan 2025 17:51:40 +0800 Subject: [PATCH 06/16] drm/rockchip: dsi2: update for dsi timing limit rk3576: max_vfp:8191, max_vsync:1023, max_vbp:1023 rk3588: max_vfp:1023, max_vsync:1023, max_vbp:1023 Signed-off-by: Sandy Huang Change-Id: I0f7777c1dbbd7de6f4b86bf6a0647ef1a1a46516 --- .../gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c index f9b8632a280a..d7a67bc80a20 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -151,7 +151,7 @@ #define DSI2_IPI_VID_VACT_MAN_CFG 0X0334 #define VID_VACT_LINES(x) UPDATE(x, 13, 0) #define DSI2_IPI_VID_VFP_MAN_CFG 0X033C -#define VID_VFP_LINES(x) UPDATE(x, 9, 0) +#define VID_VFP_LINES(x) UPDATE(x, 12, 0) #define DSI2_IPI_PIX_PKT_CFG 0x0344 #define MAX_PIX_PKT(x) UPDATE(x, 15, 0) @@ -227,7 +227,9 @@ struct dw_mipi_dsi2_plat_data { const u32 *dsi1_grf_reg_fields; unsigned long long dphy_max_bit_rate_per_lane; unsigned long long cphy_max_symbol_rate_per_lane; - + const u32 max_vfp; + const u32 max_vsync; + const u32 max_vbp; }; struct dw_mipi_dsi2 { @@ -1213,10 +1215,11 @@ dw_mipi_dsi2_connector_mode_valid(struct drm_connector *connector, if (vm.vactive > 16383) return MODE_VIRTUAL_Y; - if (vm.vsync_len > 1023) + if (vm.vsync_len > dsi2->pdata->max_vsync) return MODE_VSYNC_WIDE; - if (vm.vback_porch > 1023 || vm.vfront_porch > 1023) + if (vm.vback_porch > dsi2->pdata->max_vbp || + vm.vfront_porch > dsi2->pdata->max_vfp) return MODE_VBLANK_WIDE; /* @@ -2056,6 +2059,9 @@ static const struct dw_mipi_dsi2_plat_data rk3576_mipi_dsi2_plat_data = { .dsi0_grf_reg_fields = rk3576_dsi_grf_reg_fields, .dphy_max_bit_rate_per_lane = 2500000000ULL, .cphy_max_symbol_rate_per_lane = 1700000000ULL, + .max_vfp = 8191, + .max_vsync = 1023, + .max_vbp = 1023, }; static const struct dw_mipi_dsi2_plat_data rk3588_mipi_dsi2_plat_data = { @@ -2064,6 +2070,9 @@ static const struct dw_mipi_dsi2_plat_data rk3588_mipi_dsi2_plat_data = { .dsi1_grf_reg_fields = rk3588_dsi1_grf_reg_fields, .dphy_max_bit_rate_per_lane = 4500000000ULL, .cphy_max_symbol_rate_per_lane = 2000000000ULL, + .max_vfp = 1023, + .max_vsync = 1023, + .max_vbp = 1023, }; static const struct of_device_id dw_mipi_dsi2_dt_ids[] = { From 60e3a3147953abdb1cd8e31310854f2d19e412b4 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Sat, 8 Feb 2025 09:49:06 +0800 Subject: [PATCH 07/16] video: rockchip: rga3: fix boundary protection for RGA2 average Change-Id: Id646a2c5fd1a4e5335cbb049a8263ca9c25deabc Signed-off-by: Yu Qiaowei --- drivers/video/rockchip/rga3/rga2_reg_info.c | 22 +++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 7a35594e7926..d0595babc50b 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -133,6 +133,22 @@ static void rga2_scale_down_bilinear_protect(u32 *param_fix, u32 *src_fix, *src_fix = final_steps + 1; } +static void rag2_scale_down_average_protect(u32 *param_fix, u32 param, + u32 src, u32 dst) +{ + /* division Loss */ + param = param + 1; + + /* + * Ensure that the (src - 1) drop point is to the left of the last + * point of the dst. + */ + while ((param * (src - 1)) > (dst << 16)) + param--; + + *param_fix = param; +} + static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg) { u32 *bRGA_SRC_X_FACTOR; @@ -182,7 +198,8 @@ static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg) ((*bRGA_SRC_ACT_INFO & (~m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH)) | s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH((src_fix - 1))); } else { - param_x = ((dw << 16) + (sw / 2)) / sw; + param_x = (dw << 16) / sw; + rag2_scale_down_average_protect(¶m_x, param_x, sw, dw); *bRGA_SRC_X_FACTOR |= ((param_x & 0xffff) << 0); } @@ -219,7 +236,8 @@ static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg) ((*bRGA_SRC_ACT_INFO & (~m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT)) | s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT((src_fix - 1))); } else { - param_y = ((dh << 16) + (sh / 2)) / sh; + param_y = (dh << 16) / sh; + rag2_scale_down_average_protect(¶m_y, param_y, sh, dh); *bRGA_SRC_Y_FACTOR |= ((param_y & 0xffff) << 0); } From 2f5b41f4aa0cf1a8cd48f3743a4b54ff3b9e52fb Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Sat, 8 Feb 2025 15:02:51 +0800 Subject: [PATCH 08/16] video: rockchip: rga3: enable scale/FBC-in error intr Update driver version to 1.3.8 Change-Id: I40371f680c4d67e4a78338dad84f73b268e8877d Signed-off-by: Yu Qiaowei --- .../rockchip/rga3/include/rga2_reg_info.h | 22 +++++++++++++++---- drivers/video/rockchip/rga3/include/rga_drv.h | 2 +- drivers/video/rockchip/rga3/rga2_reg_info.c | 6 +++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/video/rockchip/rga3/include/rga2_reg_info.h b/drivers/video/rockchip/rga3/include/rga2_reg_info.h index 4afac19b0a16..5571c6e40a28 100644 --- a/drivers/video/rockchip/rga3/include/rga2_reg_info.h +++ b/drivers/video/rockchip/rga3/include/rga2_reg_info.h @@ -132,6 +132,14 @@ #define m_RGA2_STATUS1_SW_RGA_STA (0x1 << 0) /*RGA_INT*/ +#define m_RGA2_INT_FBCIN_DEC_ERROR_CLEAR (1 << 24) +#define m_RGA2_INT_FBCIN_DEC_ERROR_EN (1 << 23) +#define m_RGA2_INT_FBCIN_DEC_ERROR (1 << 22) +#define m_RGA2_INT_PREFETCH_TH_INTR (1 << 21) +#define m_RGA2_INT_PRE_TH_CLEAR (1 << 20) +#define m_RGA2_INT_SCL_ERROR_CLEAR (1 << 19) +#define m_RGA2_INT_SCL_ERROR_EN (1 << 18) +#define m_RGA2_INT_SCL_ERROR_INTR (1 << 17) #define m_RGA2_INT_LINE_WR_CLEAR (1 << 16) #define m_RGA2_INT_LINE_RD_CLEAR (1 << 15) #define m_RGA2_INT_LINE_WR_EN (1 << 14) @@ -153,17 +161,23 @@ #define m_RGA2_INT_ERROR_FLAG_MASK \ ( \ m_RGA2_INT_MMU_INT_FLAG | \ - m_RGA2_INT_ERROR_INT_FLAG \ + m_RGA2_INT_ERROR_INT_FLAG | \ + m_RGA2_INT_SCL_ERROR_INTR | \ + m_RGA2_INT_FBCIN_DEC_ERROR \ ) #define m_RGA2_INT_ERROR_CLEAR_MASK \ ( \ - m_RGA2_INT_MMU_INT_CLEAR | \ - m_RGA2_INT_ERROR_INT_CLEAR \ + m_RGA2_INT_MMU_INT_CLEAR | \ + m_RGA2_INT_ERROR_INT_CLEAR | \ + m_RGA2_INT_SCL_ERROR_CLEAR | \ + m_RGA2_INT_FBCIN_DEC_ERROR_CLEAR \ ) #define m_RGA2_INT_ERROR_ENABLE_MASK \ ( \ m_RGA2_INT_MMU_INT_EN | \ - m_RGA2_INT_ERROR_INT_EN \ + m_RGA2_INT_ERROR_INT_EN | \ + m_RGA2_INT_SCL_ERROR_EN | \ + m_RGA2_INT_FBCIN_DEC_ERROR_EN \ ) #define s_RGA2_INT_LINE_WR_CLEAR(x) ((x & 0x1) << 16) diff --git a/drivers/video/rockchip/rga3/include/rga_drv.h b/drivers/video/rockchip/rga3/include/rga_drv.h index e0c34bb4aa7e..334955e73b81 100644 --- a/drivers/video/rockchip/rga3/include/rga_drv.h +++ b/drivers/video/rockchip/rga3/include/rga_drv.h @@ -88,7 +88,7 @@ #define DRIVER_MAJOR_VERISON 1 #define DRIVER_MINOR_VERSION 3 -#define DRIVER_REVISION_VERSION 7 +#define DRIVER_REVISION_VERSION 8 #define DRIVER_PATCH_VERSION #define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_VERSION) \ diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index d0595babc50b..e0bddaaba2af 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -3268,6 +3268,12 @@ static int rga2_isr_thread(struct rga_job *job, struct rga_scheduler_t *schedule } else if (job->intr_status & m_RGA2_INT_MMU_INT_FLAG) { rga_job_err(job, "mmu failed, please check size of the buffer or whether the buffer has been freed.\n"); job->ret = -EACCES; + } else if (job->intr_status & m_RGA2_INT_SCL_ERROR_INTR) { + rga_job_err(job, "scale failed, check scale config or formula.\n"); + job->ret = -EACCES; + } else if (job->intr_status & m_RGA2_INT_FBCIN_DEC_ERROR) { + rga_job_err(job, "FBC decode failed, please check if the source data is FBC data.\n"); + job->ret = -EACCES; } if (job->ret == 0) { From 8281b215f42c624cd78b14975da147801b4ac4ae Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Sun, 24 Mar 2024 20:50:17 +0200 Subject: [PATCH 09/16] UPSTREAM: phy: Add Embedded DisplayPort and DisplayPort submodes In some cases, a DP PHY needs to be configured to work in eDP mode. So add submodes for both DP and eDP so they can be used by the controllers for specifying the mode the PHY should be configured in. Change-Id: I130b491edcf2624697489b18a3ab24add535840f Signed-off-by: Abel Vesa Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240324-x1e80100-phy-edp-compatible-refactor-v5-1-a0db5f3150bc@linaro.org Signed-off-by: Vinod Koul Signed-off-by: Damon Ding (cherry picked from commit 368d67dab4cc4a3ffd39fbd062b2f5796cdbb37b) --- include/linux/phy/phy-dp.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/phy/phy-dp.h b/include/linux/phy/phy-dp.h index 18cad23642cd..9cce5766bc0b 100644 --- a/include/linux/phy/phy-dp.h +++ b/include/linux/phy/phy-dp.h @@ -8,6 +8,9 @@ #include +#define PHY_SUBMODE_DP 0 +#define PHY_SUBMODE_EDP 1 + /** * struct phy_configure_opts_dp - DisplayPort PHY configuration set * From 3ae279210eeff7d31db38e77b3b75053f5bef0d4 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Wed, 15 Jan 2025 11:57:34 +0800 Subject: [PATCH 10/16] drm/bridge: analogix_dp: add support for ASSR mode According to the eDP v1.3 chapter 3.6 Table 3-15, Alternative Scramble Seed Reset(ASSR) is a recommended way for eDP Sink devices to support Display Authentication and Content Protection as Method 3a, while Method 1 HDCP is normally not expected in an eDP Sink device. In addition, the ASSR support capability should be the bit 0 of DPCD register 0000Dh according to the eDP v1.4 'Revision History' table 2: ...... Table 3-4: Corrected reference to DPCD Address 0000Dh, bit 0 (was bit 4) ...... Change-Id: Iafad97755fd4c9e688c47164d099b290af905036 Signed-off-by: Damon Ding --- .../drm/bridge/analogix/analogix_dp_core.c | 46 +++++++++++++++++++ .../drm/bridge/analogix/analogix_dp_core.h | 3 ++ .../gpu/drm/bridge/analogix/analogix_dp_reg.c | 24 ++++++++++ .../gpu/drm/bridge/analogix/analogix_dp_reg.h | 5 ++ 4 files changed, 78 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 6ac47ad2cc36..d253ebcf3ce4 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -341,6 +341,43 @@ static bool analogix_dp_get_vrr_capable(struct analogix_dp_device *dp) return true; } +static int analogix_dp_enable_sink_to_assr_mode(struct analogix_dp_device *dp, bool enable) +{ + u8 data; + int ret; + + ret = drm_dp_dpcd_readb(&dp->aux, DP_EDP_CONFIGURATION_SET, &data); + if (ret != 1) + return ret; + + if (enable) + ret = drm_dp_dpcd_writeb(&dp->aux, DP_EDP_CONFIGURATION_SET, + data | DP_ALTERNATE_SCRAMBLER_RESET_ENABLE); + else + ret = drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET, + data & ~DP_ALTERNATE_SCRAMBLER_RESET_ENABLE); + + return ret < 0 ? ret : 0; +} + +static int analogix_dp_set_assr_mode(struct analogix_dp_device *dp) +{ + bool assr_en; + int ret; + + assr_en = drm_dp_alternate_scrambler_reset_cap(dp->dpcd); + + ret = analogix_dp_enable_sink_to_assr_mode(dp, assr_en); + if (ret < 0) + return ret; + + analogix_dp_enable_assr_mode(dp, assr_en); + + dp->link_train.assr = assr_en; + + return 0; +} + static int analogix_dp_link_start(struct analogix_dp_device *dp) { u8 buf[4]; @@ -380,6 +417,13 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp) if (retval < 0) return retval; + /* set ASSR if available */ + retval = analogix_dp_set_assr_mode(dp); + if (retval < 0) { + dev_err(dp->dev, "failed to set assr mode\n"); + return retval; + } + /* set enhanced mode if available */ retval = analogix_dp_set_enhanced_mode(dp); if (retval < 0) { @@ -908,6 +952,7 @@ static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); analogix_dp_set_lane_count(dp, dp->link_train.lane_count); analogix_dp_set_lane_link_training(dp); + analogix_dp_enable_assr_mode(dp, dp->link_train.assr); analogix_dp_enable_enhanced_mode(dp, dp->link_train.enhanced_framing); /* source Set training pattern 1 */ @@ -2392,6 +2437,7 @@ static void analogix_dp_link_train_restore(struct analogix_dp_device *dp) dp->link_train.link_rate = link_rate; dp->link_train.lane_count = lane_count; + dp->link_train.assr = analogix_dp_get_assr_mode(dp); dp->link_train.enhanced_framing = analogix_dp_get_enhanced_mode(dp); dp->link_train.ssc = !!(spread & DP_MAX_DOWNSPREAD_0_5); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 2b2883029c5b..915bf6969ca1 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -160,6 +160,7 @@ struct link_train { u8 training_lane[4]; bool ssc; bool enhanced_framing; + bool assr; enum link_training_state lt_state; }; @@ -279,5 +280,7 @@ void analogix_dp_init(struct analogix_dp_device *dp); void analogix_dp_irq_handler(struct analogix_dp_device *dp); void analogix_dp_phy_test(struct analogix_dp_device *dp); void analogix_dp_check_device_service_irq(struct analogix_dp_device *dp); +void analogix_dp_enable_assr_mode(struct analogix_dp_device *dp, bool enable); +bool analogix_dp_get_assr_mode(struct analogix_dp_device *dp); #endif /* _ANALOGIX_DP_CORE_H */ diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index e72524eab4c2..5b58f8219ccc 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -1390,3 +1390,27 @@ void analogix_dp_init(struct analogix_dp_device *dp) analogix_dp_init_hpd(dp); analogix_dp_init_aux(dp); } + +void analogix_dp_enable_assr_mode(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY); + reg |= ALTERNATE_SR_ENABLE; + analogix_dp_write(dp, ANALOGIX_DP_LINK_POLICY, reg); + } else { + reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY); + reg &= ~ALTERNATE_SR_ENABLE; + analogix_dp_write(dp, ANALOGIX_DP_LINK_POLICY, reg); + } +} + +bool analogix_dp_get_assr_mode(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY); + + return !!(reg & ALTERNATE_SR_ENABLE); +} diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h index 0a368b1722ec..a14305148ce5 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h @@ -146,6 +146,8 @@ #define ANALOGIX_DP_CRC_CON 0x890 #define ANALOGIX_DP_I2S_CTRL 0x9C8 +#define ANALOGIX_DP_LINK_POLICY 0x9D8 + /* ANALOGIX_DP_TX_SW_RESET */ #define RESET_DP_TX (0x1 << 0) @@ -515,4 +517,7 @@ /* ANALOGIX_DP_I2S_CTRL */ #define I2S_EN (0x1 << 4) +/* ANALOGIX_DP_LINK_POLICY */ +#define ALTERNATE_SR_ENABLE (0x1 << 7) + #endif /* _ANALOGIX_DP_REG_H */ From bb5e238d4fa0a2e06cdddaeb8c5357719a80750a Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Mon, 10 Feb 2025 10:28:47 +0800 Subject: [PATCH 11/16] iio: adc: rockchip_saradc: fix the variable naming conflict fix the variable naming conflict with "lock" when CONFIG_ROCKCHIP_SARADC_TEST_CHN enabled Change-Id: I9f2925fb6e4be642cacf8e5d5c764e33d13b9cc4 Signed-off-by: Simon Xue --- drivers/iio/adc/rockchip_saradc.c | 44 ++++++++++++++++--------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index bd47d9d2c67f..f1050ef5fb05 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -80,10 +80,10 @@ struct rockchip_saradc { bool suspended; #ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN bool test; - u32 chn; - spinlock_t lock; - struct workqueue_struct *wq; - struct delayed_work work; + u32 test_chn; + spinlock_t test_lock; + struct workqueue_struct *test_wq; + struct delayed_work test_work; #endif }; @@ -138,7 +138,7 @@ static int rockchip_saradc_read_v2(struct rockchip_saradc *info) writel_relaxed(0x1, info->regs + SARADC2_END_INT_ST); #ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN - channel = info->chn; + channel = info->test_chn; #else channel = info->last_chan->channel; #endif @@ -239,12 +239,13 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) complete(&info->completion); #ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN - spin_lock_irqsave(&info->lock, flags); + spin_lock_irqsave(&info->test_lock, flags); if (info->test) { - pr_info("chn[%d] val = %d\n", info->chn, info->last_val); - mod_delayed_work(info->wq, &info->work, msecs_to_jiffies(100)); + pr_info("chn[%d] val = %d\n", info->test_chn, info->last_val); + mod_delayed_work(info->test_wq, &info->test_work, + msecs_to_jiffies(100)); } - spin_unlock_irqrestore(&info->lock, flags); + spin_unlock_irqrestore(&info->test_lock, flags); #endif return IRQ_HANDLED; } @@ -538,22 +539,23 @@ static ssize_t saradc_test_chn_store(struct device *dev, if (err) return err; - spin_lock_irqsave(&info->lock, flags); + spin_lock_irqsave(&info->test_lock, flags); if (val > SARADC_CTRL_CHN_MASK && info->test) { info->test = false; - spin_unlock_irqrestore(&info->lock, flags); - cancel_delayed_work_sync(&info->work); + spin_unlock_irqrestore(&info->test_lock, flags); + cancel_delayed_work_sync(&info->test_work); return size; } if (!info->test && val <= SARADC_CTRL_CHN_MASK) { info->test = true; - info->chn = val; - mod_delayed_work(info->wq, &info->work, msecs_to_jiffies(100)); + info->test_chn = val; + mod_delayed_work(info->test_wq, &info->test_work, + msecs_to_jiffies(100)); } - spin_unlock_irqrestore(&info->lock, flags); + spin_unlock_irqrestore(&info->test_lock, flags); return size; } @@ -580,15 +582,15 @@ static void rockchip_saradc_destroy_wq(void *data) { struct rockchip_saradc *info = data; - destroy_workqueue(info->wq); + destroy_workqueue(info->test_wq); } static void rockchip_saradc_test_work(struct work_struct *work) { struct rockchip_saradc *info = container_of(work, - struct rockchip_saradc, work.work); + struct rockchip_saradc, test_work.work); - rockchip_saradc_start(info, info->chn); + rockchip_saradc_start(info, info->test_chn); } #endif @@ -748,9 +750,9 @@ static int rockchip_saradc_probe(struct platform_device *pdev) return ret; #ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN - info->wq = create_singlethread_workqueue("adc_wq"); - INIT_DELAYED_WORK(&info->work, rockchip_saradc_test_work); - spin_lock_init(&info->lock); + info->test_wq = create_singlethread_workqueue("adc_wq"); + INIT_DELAYED_WORK(&info->test_work, rockchip_saradc_test_work); + spin_lock_init(&info->test_lock); ret = sysfs_create_group(&pdev->dev.kobj, &rockchip_saradc_attr_group); if (ret) return ret; From e5ecfb7289cd9675333a5d2c1c39fd6f2c55706e Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Mon, 10 Feb 2025 11:24:39 +0800 Subject: [PATCH 12/16] iio: adc: rockchip_saradc: fix crash cause by saradc fix the crash caused by interrupt occurring before info->last_chan is ready Change-Id: I6a57d49d5af6fb35708e009c33422ad936af0d3f Signed-off-by: Simon Xue --- drivers/iio/adc/rockchip_saradc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index f1050ef5fb05..a0091aaaf0f1 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -229,6 +229,10 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) unsigned long flags; #endif + /* Nothing need to do if info->last_chan not ready */ + if (!info->last_chan) + return IRQ_HANDLED; + /* Read value */ info->last_val = rockchip_saradc_read(info); #ifndef CONFIG_ROCKCHIP_SARADC_TEST_CHN From f346f25228e5abb8234a3f5a781989efd1af3904 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 7 Feb 2025 20:04:34 +0800 Subject: [PATCH 13/16] Revert "power: add universal charger driver support" This reverts commit 9f2ddf5a0c7dd942dcfa8db3bbf766cc02639c89. Signed-off-by: Tao Huang Change-Id: I56ad273f1da0a8d55a0e53a010a3b3c680212e7f --- .../bindings/power/universal_charger.txt | 16 - drivers/power/universal_charger.c | 419 ------------------ 2 files changed, 435 deletions(-) delete mode 100644 Documentation/devicetree/bindings/power/universal_charger.txt delete mode 100644 drivers/power/universal_charger.c diff --git a/Documentation/devicetree/bindings/power/universal_charger.txt b/Documentation/devicetree/bindings/power/universal_charger.txt deleted file mode 100644 index a328ecf1e3d7..000000000000 --- a/Documentation/devicetree/bindings/power/universal_charger.txt +++ /dev/null @@ -1,16 +0,0 @@ -Binding for UNIVERSAL Charger - -Required properties: -- compatible: Should contain one of the following: - * "universal-charger" -- extcon: extcon specifier for the Charger. -- dc-det-gpio: gpio for dc detect. - -Example: - - universal_charger { - status = "okay"; - compatible = "universal-charger"; - extcon = <&u2phy0>; - dc-det-gpio = <&gpio3 1 GPIO_ACTIVE_HIGH>; - }; diff --git a/drivers/power/universal_charger.c b/drivers/power/universal_charger.c deleted file mode 100644 index 0f7b4c9e8003..000000000000 --- a/drivers/power/universal_charger.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * universal charger driver - * - * Copyright (C) 2016 Fuzhou Rockchip 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 -#include - -enum charger_t { - USB_TYPE_UNKNOWN_CHARGER, - USB_TYPE_NONE_CHARGER, - USB_TYPE_USB_CHARGER, - USB_TYPE_AC_CHARGER, - USB_TYPE_CDP_CHARGER, - DC_TYPE_DC_CHARGER, - DC_TYPE_NONE_CHARGER, -}; - -struct universal_charger { - struct device *dev; - struct power_supply *usb_psy; - struct workqueue_struct *usb_charger_wq; - struct delayed_work usb_work; - struct workqueue_struct *dc_charger_wq; - struct delayed_work dc_work; - struct delayed_work discnt_work; - struct notifier_block cable_cg_nb; - struct notifier_block cable_discnt_nb; - unsigned int bc_event; - enum charger_t usb_charger; - enum charger_t dc_charger; - bool extcon; - struct extcon_dev *cable_edev; - struct gpio_desc *dc_det_pin; - bool support_dc_det; -}; - -static void universal_cg_bc_evt_worker(struct work_struct *work) -{ - struct universal_charger *cg = - container_of(work, struct universal_charger, usb_work.work); - struct extcon_dev *edev = cg->cable_edev; - enum charger_t charger = USB_TYPE_UNKNOWN_CHARGER; - const char *event[5] = {"UN", "NONE", "USB", "AC", "CDP1.5A"}; - - /* Determine cable/charger type */ - if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_SDP) > 0) - charger = USB_TYPE_USB_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_DCP) > 0) - charger = USB_TYPE_AC_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_CDP) > 0) - charger = USB_TYPE_CDP_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_DCP) == 0) - charger = USB_TYPE_NONE_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_CDP) == 0) - charger = USB_TYPE_NONE_CHARGER; - - if (charger != USB_TYPE_UNKNOWN_CHARGER) { - dev_info(cg->dev, "receive usb notifier event: %s...\n", - event[charger]); - cg->usb_charger = charger; - } -} - -static int universal_cg_charger_evt_notifier(struct notifier_block *nb, - unsigned long event, - void *ptr) -{ - struct universal_charger *cg = - container_of(nb, struct universal_charger, cable_cg_nb); - - queue_delayed_work(cg->usb_charger_wq, &cg->usb_work, - msecs_to_jiffies(10)); - - return NOTIFY_DONE; -} - -static void universal_cg_discnt_evt_worker(struct work_struct *work) -{ - struct universal_charger *cg = container_of(work, - struct universal_charger, discnt_work.work); - - if (extcon_get_cable_state_(cg->cable_edev, EXTCON_USB) == 0) { - dev_info(cg->dev, "receive usb notifier event: DISCNT...\n"); - cg->usb_charger = USB_TYPE_NONE_CHARGER; - } -} - -static int universal_cg_discnt_evt_notfier(struct notifier_block *nb, - unsigned long event, void *ptr) -{ - struct universal_charger *cg = - container_of(nb, struct universal_charger, cable_discnt_nb); - - queue_delayed_work(cg->usb_charger_wq, &cg->discnt_work, - msecs_to_jiffies(10)); - - return NOTIFY_DONE; -} - -static int universal_cg_init_usb(struct universal_charger *cg) -{ - struct device *dev = cg->dev; - int ret; - struct extcon_dev *edev; - - if (!cg->extcon) - return 0; - - edev = extcon_get_edev_by_phandle(dev, 0); - if (IS_ERR(edev)) { - if (PTR_ERR(edev) != -EPROBE_DEFER) - dev_err(dev, "Invalid or missing extcon\n"); - return PTR_ERR(edev); - } - - cg->usb_charger_wq = alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - "universal-usb-wq"); - if (!cg->usb_charger_wq) - return -ENOMEM; - - cg->usb_charger = USB_TYPE_NONE_CHARGER; - - /* Register chargers */ - INIT_DELAYED_WORK(&cg->usb_work, universal_cg_bc_evt_worker); - cg->cable_cg_nb.notifier_call = universal_cg_charger_evt_notifier; - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_SDP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for SDP\n"); - goto __fail; - } - - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_DCP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for DCP\n"); - goto __fail; - } - - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_CDP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for CDP\n"); - goto __fail; - } - - /* Register discnt usb */ - INIT_DELAYED_WORK(&cg->discnt_work, universal_cg_discnt_evt_worker); - cg->cable_discnt_nb.notifier_call = universal_cg_discnt_evt_notfier; - ret = devm_extcon_register_notifier(dev, edev, EXTCON_USB, - &cg->cable_discnt_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for HOST\n"); - goto __fail; - } - - cg->cable_edev = edev; - schedule_delayed_work(&cg->usb_work, 0); - dev_info(cg->dev, "register extcon evt notifier\n"); - - return 0; - -__fail: - destroy_workqueue(cg->usb_charger_wq); - return ret; -} - -static enum power_supply_property universal_usb_props[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_STATUS, -}; - -static int universal_cg_usb_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct universal_charger *cg = power_supply_get_drvdata(psy); - int online = 0; - int ret = 0; - - if (cg->usb_charger != USB_TYPE_UNKNOWN_CHARGER && - cg->usb_charger != USB_TYPE_NONE_CHARGER) - online = 1; - if (cg->dc_charger != DC_TYPE_NONE_CHARGER) - online = 1; - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = online; - - dev_dbg(cg->dev, "report online: %d\n", val->intval); - break; - case POWER_SUPPLY_PROP_STATUS: - if (online) - val->intval = POWER_SUPPLY_STATUS_CHARGING; - else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - - dev_dbg(cg->dev, "report prop: %d\n", val->intval); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct power_supply_desc universal_usb_desc = { - .name = "universal_usb", - .type = POWER_SUPPLY_TYPE_USB, - .properties = universal_usb_props, - .num_properties = ARRAY_SIZE(universal_usb_props), - .get_property = universal_cg_usb_get_property, -}; - -static int universal_cg_init_power_supply(struct universal_charger *cg) -{ - struct power_supply_config psy_cfg = { .drv_data = cg, }; - - cg->usb_psy = devm_power_supply_register(cg->dev, &universal_usb_desc, - &psy_cfg); - if (IS_ERR(cg->usb_psy)) { - dev_err(cg->dev, "register usb power supply fail\n"); - return PTR_ERR(cg->usb_psy); - } - - return 0; -} - -#ifdef CONFIG_OF -static int universal_charger_parse_dt(struct universal_charger *cg) -{ - struct device *dev = cg->dev; - - cg->dc_det_pin = devm_gpiod_get_optional(dev, "dc-det", - GPIOD_IN); - if (!IS_ERR_OR_NULL(cg->dc_det_pin)) { - cg->support_dc_det = true; - } else { - dev_err(dev, "invalid dc det gpio!\n"); - cg->support_dc_det = false; - } - - return 0; -} -#else -static int universal_charger_parse_dt(struct universal_charger *cg) -{ - return -ENODEV; -} -#endif - -static enum -charger_t universal_charger_get_dc_state(struct universal_charger *cg) -{ - return (gpiod_get_value(cg->dc_det_pin)) ? - DC_TYPE_DC_CHARGER : DC_TYPE_NONE_CHARGER; -} - -static void universal_charger_dc_det_worker(struct work_struct *work) -{ - enum charger_t charger; - struct universal_charger *cg = container_of(work, - struct universal_charger, dc_work.work); - - charger = universal_charger_get_dc_state(cg); - if (charger == DC_TYPE_DC_CHARGER) - cg->dc_charger = charger; - else - cg->dc_charger = DC_TYPE_NONE_CHARGER; -} - -static irqreturn_t universal_charger_dc_det_isr(int irq, void *charger) -{ - struct universal_charger *cg = (struct universal_charger *)charger; - - queue_delayed_work(cg->dc_charger_wq, &cg->dc_work, - msecs_to_jiffies(10)); - - return IRQ_HANDLED; -} - -static int universal_charger_init_dc(struct universal_charger *cg) -{ - int ret; - unsigned long irq_flags; - unsigned int dc_det_irq; - - if (!cg->support_dc_det) - return 0; - - cg->dc_charger_wq = alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - "universal-dc-wq"); - if (!cg->dc_charger_wq) - return -ENOMEM; - - INIT_DELAYED_WORK(&cg->dc_work, universal_charger_dc_det_worker); - cg->dc_charger = DC_TYPE_NONE_CHARGER; - - if (gpiod_get_value(cg->dc_det_pin)) - cg->dc_charger = DC_TYPE_DC_CHARGER; - else - cg->dc_charger = DC_TYPE_NONE_CHARGER; - - irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - dc_det_irq = gpiod_to_irq(cg->dc_det_pin); - ret = devm_request_irq(cg->dev, dc_det_irq, - universal_charger_dc_det_isr, - irq_flags, "universal_dc_det", cg); - if (ret != 0) { - destroy_workqueue(cg->dc_charger_wq); - dev_err(cg->dev, "universal_dc_det_irq request failed!\n"); - return ret; - } - - enable_irq_wake(dc_det_irq); - - return 0; -} - -static int universal_charger_probe(struct platform_device *pdev) -{ - struct universal_charger *cg; - int ret; - - cg = devm_kzalloc(&pdev->dev, sizeof(*cg), GFP_KERNEL); - if (!cg) - return -ENOMEM; - - cg->dev = &pdev->dev; - universal_charger_parse_dt(cg); - ret = universal_charger_init_dc(cg); - if (ret) { - dev_err(cg->dev, "init dc failed!\n"); - return ret; - } - cg->extcon = device_property_read_bool(cg->dev, "extcon"); - ret = universal_cg_init_usb(cg); - if (ret) { - dev_err(cg->dev, "init usb failed!\n"); - goto __init_usb_fail; - } - - ret = universal_cg_init_power_supply(cg); - if (ret) { - dev_err(cg->dev, "init power supply fail!\n"); - goto ___init_psy_fail; - } - - dev_info(cg->dev, "driver registered\n"); - - return 0; - -___init_psy_fail: - if (cg->usb_charger_wq) - destroy_workqueue(cg->usb_charger_wq); -__init_usb_fail: - if (cg->dc_charger_wq) - destroy_workqueue(cg->dc_charger_wq); - - return ret; -} - -static int universal_charger_remove(struct platform_device *pdev) -{ - struct universal_charger *cg = platform_get_drvdata(pdev); - - if (cg->usb_charger_wq) - destroy_workqueue(cg->usb_charger_wq); - if (cg->dc_charger_wq) - destroy_workqueue(cg->dc_charger_wq); - - return 0; -} - -static const struct of_device_id universal_charger_match[] = { - { - .compatible = "universal-charger", - }, - {}, -}; - -static struct platform_driver universal_charger_driver = { - .probe = universal_charger_probe, - .remove = universal_charger_remove, - .driver = { - .name = "universal-charger", - .of_match_table = universal_charger_match, - }, -}; - -module_platform_driver(universal_charger_driver); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:universal-charger"); -MODULE_AUTHOR("chen Shunqing"); From a6943befb99d8f8b32c26e7ec0922bca8c54dace Mon Sep 17 00:00:00 2001 From: Ding Wei Date: Mon, 10 Feb 2025 11:18:30 +0800 Subject: [PATCH 14/16] video: rockchip: mpp: fix share iommu issue for rk3528 on Arch32 Issue: 1. On arm32 platform iommu use the mapping->domain, while use the group->domain on arm64 platform. 2. __iommu_attach_group use group->default to judge whether new device in kernel 5.10 branch, while use group->domain in kernel 6.1 branch. For this change, when two devices share the iommu, the first device attach success, while the second device failed in kernel 6.1 branch. Method: 1. Set driver_managed_dma=true to ensure that during the IOMMU probe phase, even if attach group failed, the mapping will not be released. 2. After the IOMMU probe succeeds, record info->domain=mapping->domain and detach it, ensuring that group->domain is set to NULL. This prevents the next device which sharing the IOMMU, not return -EBUSY when attach the group. 3. Before hardware running, the shared IOMMU should check whether the device has been switched. If so, it needs to attach the current device's info->domain. 4. When removing a shared IOMMU, it must also ensure that group->domain corresponds to the current device. Change-Id: If0fec01a0bcf9c49850129bfa5ac28484fece9a2 Signed-off-by: Ding Wei --- drivers/video/rockchip/mpp/mpp_common.c | 3 +++ drivers/video/rockchip/mpp/mpp_common.h | 6 ++++++ drivers/video/rockchip/mpp/mpp_iommu.c | 24 ++++++++++++++++++++++++ drivers/video/rockchip/mpp/mpp_iommu.h | 3 +++ drivers/video/rockchip/mpp/mpp_service.c | 6 ++++++ 5 files changed, 42 insertions(+) diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index ab02cea09f17..80c263ac081e 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -2239,7 +2239,10 @@ int mpp_dev_probe(struct mpp_dev *mpp, if (IS_ERR(mpp->iommu_info)) { dev_err(dev, "failed to attach iommu\n"); mpp->iommu_info = NULL; + } else { + mpp->iommu_info->queue = mpp->queue; } + if (mpp->hw_ops->init) { ret = mpp->hw_ops->init(mpp); if (ret) diff --git a/drivers/video/rockchip/mpp/mpp_common.h b/drivers/video/rockchip/mpp/mpp_common.h index d60d69970f56..e88243e78617 100644 --- a/drivers/video/rockchip/mpp/mpp_common.h +++ b/drivers/video/rockchip/mpp/mpp_common.h @@ -507,6 +507,9 @@ struct mpp_taskqueue { u32 core_id_max; u32 core_count; unsigned long dev_active_flags; + + /* for devices which share iommu, record last attach device */ + struct mpp_iommu_info *last_iommu_info; }; struct mpp_reset_group { @@ -547,6 +550,9 @@ struct mpp_service { /* global timing record flag */ u32 timing_en; u32 load_interval; + + /* bit mask for iommu shared */ + u32 iommu_shared_mask; }; /* diff --git a/drivers/video/rockchip/mpp/mpp_iommu.c b/drivers/video/rockchip/mpp/mpp_iommu.c index 9a3589314e0e..ff93d7f75e6c 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.c +++ b/drivers/video/rockchip/mpp/mpp_iommu.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef CONFIG_ARM_DMA_USE_IOMMU #include @@ -451,9 +452,19 @@ int mpp_iommu_detach(struct mpp_iommu_info *info) int mpp_iommu_attach(struct mpp_iommu_info *info) { + struct mpp_iommu_info *last_info; + if (!info) return 0; + /* if device changed, detach last first */ + last_info = info->queue->last_iommu_info; + if (info->shared && last_info && last_info->shared + && (info->dev != last_info->dev)) { + iommu_detach_group(last_info->domain, last_info->group); + } + info->queue->last_iommu_info = info; + if (info->domain == iommu_get_domain_for_dev(info->dev)) return 0; @@ -561,6 +572,15 @@ mpp_iommu_probe(struct device *dev) info->irq = platform_get_irq(pdev, 0); info->got_irq = (info->irq < 0) ? false : true; + /* get shared flag, if true detach */ + if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) { + struct platform_driver *drv = to_platform_driver(dev->driver); + + info->shared = drv->driver_managed_dma; + if (info->shared) + iommu_detach_group(info->domain, info->group); + } + return info; err_put_group: @@ -578,6 +598,10 @@ int mpp_iommu_remove(struct mpp_iommu_info *info) if (!info) return 0; + /* if iommu shared, ensure current device's domain, then remove correctly */ + if (info->shared) + mpp_iommu_attach(info); + iommu_group_put(info->group); platform_device_put(info->pdev); diff --git a/drivers/video/rockchip/mpp/mpp_iommu.h b/drivers/video/rockchip/mpp/mpp_iommu.h index 265f276de281..bf51e0ee4de3 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.h +++ b/drivers/video/rockchip/mpp/mpp_iommu.h @@ -102,6 +102,9 @@ struct mpp_iommu_info { int irq; int got_irq; + /* flag for mark iommu whether shared */ + bool shared; + struct mpp_taskqueue *queue; }; struct mpp_dma_session * diff --git a/drivers/video/rockchip/mpp/mpp_service.c b/drivers/video/rockchip/mpp/mpp_service.c index 882002e20097..4ae409738685 100644 --- a/drivers/video/rockchip/mpp/mpp_service.c +++ b/drivers/video/rockchip/mpp/mpp_service.c @@ -100,6 +100,9 @@ static int mpp_add_driver(struct mpp_service *srv, &srv->grf_infos[type], grf_name); + if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) + driver->driver_managed_dma = (srv->iommu_shared_mask & BIT(type)) ? true : false; + ret = platform_driver_register(driver); if (ret) return ret; @@ -444,6 +447,9 @@ static int mpp_service_probe(struct platform_device *pdev) } } + of_property_read_u32(np, "rockchip,iommu-shared-mask", + &srv->iommu_shared_mask); + ret = mpp_register_service(srv, MPP_SERVICE_NAME); if (ret) { dev_err(dev, "register %s device\n", MPP_SERVICE_NAME); From 8f25f9d7c3c9360e78861649eb3c4c82cdd022f2 Mon Sep 17 00:00:00 2001 From: Ding Wei Date: Mon, 10 Feb 2025 11:44:51 +0800 Subject: [PATCH 15/16] arm64: dts: rockchip: rk3528: Add iommu shared bitmask for avsd and vdpu Change-Id: I42807997f85e9e43c2a7f490fd9af7c87b30fec6 Signed-off-by: Ding Wei --- arch/arm64/boot/dts/rockchip/rk3528.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi index a8ff558a524f..2993e406fc91 100644 --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi @@ -452,6 +452,7 @@ compatible = "rockchip,mpp-service"; rockchip,taskqueue-count = <5>; rockchip,resetgroup-count = <5>; + rockchip,iommu-shared-mask = <0xa>; /* 0x2: avsd, 0x8: vdpu */ status = "disabled"; }; From cbb33e40aadf1f6a766ba3d63121c7b766a9f2f4 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Thu, 6 Feb 2025 17:17:36 +0800 Subject: [PATCH 16/16] drm/rockchip: vop2: Ensure rk3576 sharp/post-scaler/split are mutually exclusive VOP sharp/post-scaler/split use the same line buffer. They must be mutually exclusive, otherwise the picture will display abnormally. Change-Id: Ia8e7877826bf2a4484a4060ea4d704a2edc611c3 Signed-off-by: Algea Cao --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 78 +++++++++++++++++++- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 1c0d3c4df190..949da8ff3066 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -858,6 +858,11 @@ struct vop2_video_port { * @irq: independent irq for each vp */ int irq; + /** + * @sharp_disabled: Sharp is mutually exclusive with post-scaler and split, + * we configure whether sharp is disabled in dts + */ + bool sharp_disabled; }; struct vop2_extend_pll { @@ -4578,7 +4583,7 @@ static void vop2_initial(struct drm_crtc *crtc) * After vop initialization, keep sw_sharp_enable always on. * Only enable/disable sharp submodule to avoid black screen. */ - if (vp_data->feature & VOP_FEATURE_POST_SHARP) + if (vp_data->feature & VOP_FEATURE_POST_SHARP && vp->sharp_disabled) writel(0x1, vop2->sharp_res.regs); /* disable immediately enable bit for dp */ @@ -9507,6 +9512,27 @@ static void vop2_setup_dual_channel_if(struct drm_crtc *crtc) struct vop2_video_port *vp = to_vop2_video_port(crtc); struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); struct vop2 *vop2 = vp->vop2; + const struct vop2_data *vop2_data = vop2->data; + const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; + + /* + * RK3576 VOP split and post-scaler use the same line buffer. + * If enable split, post-scaler must be disabled. + */ + if (vop2->version == VOP_VERSION_RK3576) { + DRM_ERROR("split is enabled, post-scaler shouldn't be set\n"); + vcstate->left_margin = 100; + vcstate->right_margin = 100; + vcstate->top_margin = 100; + vcstate->bottom_margin = 100; + } + + /* + * VOP split and sharp use the same line buffer. If enable + * split, sharp must be disabled completely. + */ + if (vp_data->feature & VOP_FEATURE_POST_SHARP) + writel(0, vop2->sharp_res.regs); if (output_if_is_lvds(vcstate->output_if) && (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)) { @@ -9818,6 +9844,15 @@ static inline char *vop2_output_if_to_string(unsigned long inf) ARRAY_SIZE(vop2_output_if_name_list)); } +static bool vop2_is_left_right_or_odd_even_mode(struct rockchip_crtc_state *vcstate) +{ + if (!(vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) && + !(vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)) + return false; + + return true; +} + static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) { struct vop2_video_port *vp = to_vop2_video_port(crtc); @@ -10038,8 +10073,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta } } - if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || - vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) + if (vop2_is_left_right_or_odd_even_mode(vcstate)) vop2_setup_dual_channel_if(crtc); if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) { @@ -12470,6 +12504,17 @@ static void vop2_post_sharp_config(struct drm_crtc *crtc) struct post_sharp *post_sharp; int i; + if (vp->sharp_disabled) + return; + + if (vop2_is_left_right_or_odd_even_mode(vcstate)) { + if (post_sharp_enabled(crtc)) + DRM_WARN("split is enabled, can't enable sharp\n"); + + vcstate->sharp_en = false; + return; + } + /* sharp work in yuv color space, if it is rgb overlay sharp shouldn't be enabled */ if (!vcstate->yuv_overlay || !post_sharp_enabled(crtc)) { /* @@ -13089,6 +13134,7 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state); struct drm_mode_config *mode_config = &drm_dev->mode_config; struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; bool replaced = false; int ret; @@ -13097,6 +13143,12 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, DRM_ERROR("sharp is enabled, failed to set %s\n", property->name); return 0; } + + if (vop2_is_left_right_or_odd_even_mode(vcstate) && + vop2->version == VOP_VERSION_RK3576) { + DRM_ERROR("split is enabled, failed to set %s\n", property->name); + return 0; + } vcstate->left_margin = val; return 0; } @@ -13106,6 +13158,12 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, DRM_ERROR("sharp is enabled, failed to set %s\n", property->name); return 0; } + + if (vop2_is_left_right_or_odd_even_mode(vcstate) && + vop2->version == VOP_VERSION_RK3576) { + DRM_ERROR("split is enabled, failed to set %s\n", property->name); + return 0; + } vcstate->right_margin = val; return 0; } @@ -13115,6 +13173,12 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, DRM_ERROR("sharp is enabled, failed to set %s\n", property->name); return 0; } + + if (vop2_is_left_right_or_odd_even_mode(vcstate) && + vop2->version == VOP_VERSION_RK3576) { + DRM_ERROR("split is enabled, failed to set %s\n", property->name); + return 0; + } vcstate->top_margin = val; return 0; } @@ -13124,6 +13188,12 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, DRM_ERROR("sharp is enabled, failed to set %s\n", property->name); return 0; } + + if (vop2_is_left_right_or_odd_even_mode(vcstate) && + vop2->version == VOP_VERSION_RK3576) { + DRM_ERROR("split is enabled, failed to set %s\n", property->name); + return 0; + } vcstate->bottom_margin = val; return 0; } @@ -14319,6 +14389,8 @@ static int vop2_create_crtc(struct vop2 *vop2, uint8_t enabled_vp_mask) crtc->port = port; of_property_read_u32(port, "cursor-win-id", &vp->cursor_win_id); + vp->sharp_disabled = of_property_read_bool(port, "sharp-disabled"); + plane_mask = vp->plane_mask; if (vop2_soc_is_rk3566()) { if ((vp->plane_mask & RK3566_MIRROR_PLANE_MASK) &&