mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
Merge commit 'b27c911206af7ad9cec2250922846cb1f3ea40cb'
* commit 'b27c911206af7ad9cec2250922846cb1f3ea40cb': arm64: dts: rockchip: rk3576-vehicle-evb: modify maxim lock gpio hwspinlock: rockchip: support to set hwlock numbers in dt dt-bindings: hwlock: rockchip: add number of hwlocks property video: rockchip: rga3: add 'reset' debug node arm64: dts: rockchip: update rk3576-ebook-color panel parameter drm/rockchip: dsi2: add connector polling connect/disconnect flags drm/bridge: attach dsi in probe according to dsi driver dt-bindings: phy: Add lvds output voltage for rockchip,px30-dsi-dphy phy: rockchip: inno-dsidphy: Add support to change lvds output voltage video: rockchip: mpp: rkvenc2: Update address trans table arm64: dts: rockchip: rk3576-vehicle-evb: support rkvpss Change-Id: I0a3c700380d14ff2d487a2db98fa735e7d9fe760
This commit is contained in:
@@ -10,6 +10,8 @@ Required properties :
|
||||
- #hwlock-cells : hwlock users only use the hwlock id to represent a specific
|
||||
hwlock, so the number of cells should be <1> here.
|
||||
|
||||
- rockchip,hwlock-num-locks :number of hwlocks provided by this device.
|
||||
|
||||
Optional properties :
|
||||
- rockchip,hwlock-user-id : Set hwlock user id (4 bit, default is 0x01).
|
||||
|
||||
@@ -21,6 +23,7 @@ Example of hwlock provider:
|
||||
compatible = "rockchip,hwspinlock";
|
||||
reg = <0 0xff040000 0 0x10000>;
|
||||
#hwlock-cells = <1>;
|
||||
rockchip,hwlock-num-locks = <64>;
|
||||
};
|
||||
|
||||
Example of hwlock users:
|
||||
|
||||
@@ -45,6 +45,18 @@ properties:
|
||||
items:
|
||||
- const: apb
|
||||
|
||||
inno,lanes:
|
||||
description: Number of MIPI DSI lanes used
|
||||
enum: [1, 2, 3, 4]
|
||||
|
||||
inno,lvds-vcom:
|
||||
description: LVDS output common-mode voltage in millivolts
|
||||
enum: [850, 900, 950, 1000]
|
||||
|
||||
inno,lvds-vod:
|
||||
description: LVDS output differential voltage in millivolts
|
||||
enum: [250, 300, 350, 400]
|
||||
|
||||
required:
|
||||
- "#phy-cells"
|
||||
- compatible
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
panel,vir_height = <1944>;
|
||||
panel,sdck = <60000000>;
|
||||
panel,lsl = <64>;
|
||||
panel,lbl = <64>;
|
||||
panel,lbl = <20>;
|
||||
panel,ldl = <312>;
|
||||
panel,lel = <22>;
|
||||
panel,gdck-sta = <1>;
|
||||
|
||||
@@ -339,6 +339,18 @@
|
||||
|
||||
};
|
||||
|
||||
&rkvpss {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rkvpss_mmu {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rkvpss_vir0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdmmc {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
reg = <0x42>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c8_serdes_pins>;
|
||||
lock-gpios = <&gpio2 RK_PC7 GPIO_ACTIVE_HIGH>;
|
||||
lock-gpios = <&gpio3 RK_PA2 GPIO_ACTIVE_HIGH>;
|
||||
sel-mipi;
|
||||
id-serdes-bridge-split = <0x01>;
|
||||
status = "okay";
|
||||
@@ -566,7 +566,7 @@
|
||||
reg = <0x42>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c5_serdes_pins>;
|
||||
lock-gpios = <&gpio2 RK_PD1 GPIO_ACTIVE_HIGH>;
|
||||
lock-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
id-serdes-bridge-split = <0x02>;
|
||||
@@ -1090,7 +1090,7 @@
|
||||
reg = <0x42>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c2_serdes_pins>;
|
||||
lock-gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_HIGH>;
|
||||
lock-gpios = <&gpio2 RK_PB0 GPIO_ACTIVE_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
id-serdes-bridge-split = <0x02>;
|
||||
@@ -1616,19 +1616,23 @@
|
||||
|
||||
&pinctrl {
|
||||
serdes {
|
||||
/*EDP*/
|
||||
i2c2_serdes_pins: i2c2-serdes-pins {
|
||||
rockchip,pins =
|
||||
<2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
<2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>,/*lock*/
|
||||
<2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;/*err*/
|
||||
};
|
||||
|
||||
/*DP*/
|
||||
i2c5_serdes_pins: i2c5-serdes-pins {
|
||||
rockchip,pins =
|
||||
<2 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
<2 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>,/*err*/
|
||||
<2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>;/*lock*/
|
||||
};
|
||||
|
||||
/*DSI*/
|
||||
i2c8_serdes_pins: i2c8-serdes-pins {
|
||||
rockchip,pins =
|
||||
<2 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
<2 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>,/*err*/
|
||||
<3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;/*lock*/
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2183,8 +2183,6 @@ static int it6161_bridge_attach(struct drm_bridge *bridge,
|
||||
goto cleanup_connector;
|
||||
}
|
||||
|
||||
DRM_INFO("%s, ret:%d", __func__, it6161_attach_dsi(it6161));
|
||||
|
||||
err = drm_connector_register(&it6161->connector);
|
||||
if (err < 0) {
|
||||
DRM_DEV_ERROR(dev, "Failed to register connector: %d", err);
|
||||
@@ -4030,7 +4028,7 @@ static void hdmi_tx_enable_hdcp(struct it6161 *it6161)
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool getHDMITX_LinkStatus()
|
||||
static bool getHDMITX_LinkStatus(void)
|
||||
{
|
||||
it6161_debug("%s reg0E:0x%02x reg0x61:0x%02x", __func__, it6161_hdmi_tx_read(it6161, REG_TX_SYS_STATUS), it6161_hdmi_tx_read(it6161, REG_TX_AFE_DRV_CTRL));//allen
|
||||
if(B_TX_RXSENDETECT & it6161_hdmi_tx_read(it6161, REG_TX_SYS_STATUS)) {
|
||||
@@ -4669,7 +4667,7 @@ static void setHDMITX_HBRAudio(u8 bAudInterface /*I2S/SPDIF/TDM*/)
|
||||
// it6161_hdmi_tx_write(it6161, REG_TX_SW_RST, rst );
|
||||
}
|
||||
|
||||
static void setHDMITX_DSDAudio()
|
||||
static void setHDMITX_DSDAudio(void)
|
||||
{
|
||||
// to be continue
|
||||
// u8 rst;
|
||||
@@ -6812,6 +6810,12 @@ static int it6161_i2c_probe(struct i2c_client *i2c_mipi_rx,
|
||||
it6161->bridge.funcs = &it6161_bridge_funcs;
|
||||
drm_bridge_add(&it6161->bridge);
|
||||
|
||||
err = it6161_attach_dsi(it6161);
|
||||
if (err) {
|
||||
DRM_DEV_ERROR(dev, "failed to attach dsi, ret: %d", err);
|
||||
goto err_cec;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_cec:
|
||||
|
||||
@@ -179,21 +179,17 @@ static int max96755f_bridge_attach(struct drm_bridge *bridge,
|
||||
|
||||
drm_connector_attach_encoder(connector, bridge->encoder);
|
||||
|
||||
ser->dsi = max96755f_attach_dsi(ser, ser->dsi_node);
|
||||
if (IS_ERR(ser->dsi))
|
||||
return PTR_ERR(ser->dsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void max96755f_bridge_detach(struct drm_bridge *bridge)
|
||||
{
|
||||
struct max96755f_bridge *ser = to_max96755f_bridge(bridge);
|
||||
}
|
||||
|
||||
if (ser->dsi) {
|
||||
mipi_dsi_detach(ser->dsi);
|
||||
mipi_dsi_device_unregister(ser->dsi);
|
||||
}
|
||||
static void max96755f_detach_dsi(struct max96755f_bridge *ser)
|
||||
{
|
||||
mipi_dsi_detach(ser->dsi);
|
||||
mipi_dsi_device_unregister(ser->dsi);
|
||||
}
|
||||
|
||||
static void max96755f_mipi_dsi_rx_config(struct max96755f_bridge *ser)
|
||||
@@ -548,13 +544,27 @@ static int max96755f_bridge_probe(struct platform_device *pdev)
|
||||
|
||||
drm_bridge_add(&ser->bridge);
|
||||
|
||||
ser->dsi = max96755f_attach_dsi(ser, ser->dsi_node);
|
||||
if (IS_ERR(ser->dsi)) {
|
||||
dev_err(ser->dev, "failed to attach dsi\n");
|
||||
ret = PTR_ERR(ser->dsi);
|
||||
goto err_remove_bridge;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_bridge:
|
||||
drm_bridge_remove(&ser->bridge);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max96755f_bridge_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max96755f_bridge *ser = platform_get_drvdata(pdev);
|
||||
|
||||
if (ser->dsi)
|
||||
max96755f_detach_dsi(ser);
|
||||
|
||||
drm_bridge_remove(&ser->bridge);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -169,13 +169,6 @@ static int bu18tl82_bridge_attach(struct drm_bridge *bridge,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bu18tl82->sel_mipi) {
|
||||
/* Attach primary DSI */
|
||||
bu18tl82->dsi = bu18tl82_attach_dsi(bu18tl82, bu18tl82->dsi_node);
|
||||
if (IS_ERR(bu18tl82->dsi))
|
||||
return PTR_ERR(bu18tl82->dsi);
|
||||
}
|
||||
|
||||
ret = drm_bridge_attach(bridge->encoder, bu18tl82->bridge,
|
||||
bridge, flags);
|
||||
if (ret) {
|
||||
@@ -191,12 +184,12 @@ static int bu18tl82_bridge_attach(struct drm_bridge *bridge,
|
||||
|
||||
static void bu18tl82_bridge_detach(struct drm_bridge *bridge)
|
||||
{
|
||||
struct bu18tl82 *bu18tl82 = bridge_to_bu18tl82(bridge);
|
||||
}
|
||||
|
||||
if (bu18tl82->sel_mipi) {
|
||||
mipi_dsi_detach(bu18tl82->dsi);
|
||||
mipi_dsi_device_unregister(bu18tl82->dsi);
|
||||
}
|
||||
static void bu18tl82_detach_dsi(struct bu18tl82 *bu18tl82)
|
||||
{
|
||||
mipi_dsi_detach(bu18tl82->dsi);
|
||||
mipi_dsi_device_unregister(bu18tl82->dsi);
|
||||
}
|
||||
|
||||
static void bu18tl82_bridge_enable(struct drm_bridge *bridge)
|
||||
@@ -301,13 +294,30 @@ static int bu18tl82_i2c_probe(struct i2c_client *client,
|
||||
|
||||
drm_bridge_add(&bu18tl82->base);
|
||||
|
||||
if (bu18tl82->sel_mipi) {
|
||||
/* Attach primary DSI */
|
||||
bu18tl82->dsi = bu18tl82_attach_dsi(bu18tl82, bu18tl82->dsi_node);
|
||||
if (IS_ERR(bu18tl82->dsi)) {
|
||||
dev_err(bu18tl82->dev, "failed to attach dsi\n");
|
||||
ret = PTR_ERR(bu18tl82->dsi);
|
||||
goto err_remove_bridge;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_bridge:
|
||||
drm_bridge_remove(&bu18tl82->base);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bu18tl82_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct bu18tl82 *bu18tl82 = i2c_get_clientdata(client);
|
||||
|
||||
if (bu18tl82->sel_mipi)
|
||||
bu18tl82_detach_dsi(bu18tl82);
|
||||
|
||||
drm_bridge_remove(&bu18tl82->base);
|
||||
}
|
||||
|
||||
|
||||
@@ -1479,6 +1479,10 @@ static int dw_mipi_dsi2_bind(struct device *dev, struct device *master,
|
||||
if (ret)
|
||||
goto encoder_cleanup;
|
||||
|
||||
if (dsi2->bridge && (dsi2->bridge->ops & DRM_BRIDGE_OP_DETECT))
|
||||
dsi2->connector.polled = DRM_CONNECTOR_POLL_CONNECT |
|
||||
DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
connector = &dsi2->connector;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,10 +67,16 @@ static int rockchip_hwspinlock_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rockchip_hwspinlock *hwspin;
|
||||
struct hwspinlock *hwlock;
|
||||
u32 num_locks = 0;
|
||||
int idx, ret;
|
||||
|
||||
ret = device_property_read_u32(&pdev->dev, "rockchip,hwlock-num-locks",
|
||||
&num_locks);
|
||||
if (ret || !num_locks)
|
||||
num_locks = HWSPINLOCK_NUMBER;
|
||||
|
||||
hwspin = devm_kzalloc(&pdev->dev,
|
||||
struct_size(hwspin, bank.lock, HWSPINLOCK_NUMBER),
|
||||
struct_size(hwspin, bank.lock, num_locks),
|
||||
GFP_KERNEL);
|
||||
if (!hwspin)
|
||||
return -ENOMEM;
|
||||
@@ -83,9 +89,9 @@ static int rockchip_hwspinlock_probe(struct platform_device *pdev)
|
||||
&hwlock_user_id);
|
||||
if (ret || !hwlock_user_id || hwlock_user_id > HWSPINLOCK_ID_MASK)
|
||||
hwlock_user_id = HWLOCK_DEFAULT_USER;
|
||||
dev_info(&pdev->dev, "hwlock user id %u\n", hwlock_user_id);
|
||||
dev_info(&pdev->dev, "hwlock user id %u, locks %u\n", hwlock_user_id, num_locks);
|
||||
|
||||
for (idx = 0; idx < HWSPINLOCK_NUMBER; idx++) {
|
||||
for (idx = 0; idx < num_locks; idx++) {
|
||||
hwlock = &hwspin->bank.lock[idx];
|
||||
hwlock->priv = hwspin->io_base + HWSPINLOCK_OFFSET(idx);
|
||||
}
|
||||
@@ -94,7 +100,7 @@ static int rockchip_hwspinlock_probe(struct platform_device *pdev)
|
||||
|
||||
return devm_hwspin_lock_register(&pdev->dev, &hwspin->bank,
|
||||
&rockchip_hwspinlock_ops, 0,
|
||||
HWSPINLOCK_NUMBER);
|
||||
num_locks);
|
||||
}
|
||||
|
||||
static const struct of_device_id rockchip_hwpinlock_ids[] = {
|
||||
|
||||
@@ -179,6 +179,11 @@
|
||||
#define TTL_MODE_ENABLE BIT(2)
|
||||
#define LVDS_MODE_ENABLE BIT(1)
|
||||
#define MIPI_MODE_ENABLE BIT(0)
|
||||
/* LVDS Register Part: reg04 */
|
||||
#define LVDS_VCOM_MASK GENMASK(5, 4)
|
||||
#define LVDS_VCOM(x) UPDATE(x, 5, 4)
|
||||
#define LVDS_VOD_MASK GENMASK(7, 6)
|
||||
#define LVDS_VOD(x) UPDATE(x, 7, 6)
|
||||
/* LVDS Register Part: reg0b */
|
||||
#define LVDS_LANE_EN_MASK GENMASK(7, 3)
|
||||
#define LVDS_DATA_LANE0_EN BIT(7)
|
||||
@@ -239,6 +244,8 @@ struct inno_dsidphy {
|
||||
u16 fbdiv;
|
||||
unsigned long rate;
|
||||
} pll;
|
||||
u32 lvds_vcom;
|
||||
u32 lvds_vod;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -638,6 +645,35 @@ static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)
|
||||
inno_mipi_dphy_lane_enable(inno);
|
||||
}
|
||||
|
||||
static void inno_dsiphy_lvds_voltage_set(struct inno_dsidphy *inno)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
/* This version of inno phy does not have voltage register, skip it. */
|
||||
if (inno->pdata->max_rate == MAX_1GHZ)
|
||||
return;
|
||||
|
||||
if (inno->lvds_vcom >= 1000)
|
||||
val |= LVDS_VCOM(3);
|
||||
else if (inno->lvds_vcom >= 950)
|
||||
val |= LVDS_VCOM(2);
|
||||
else if (inno->lvds_vcom >= 900)
|
||||
val |= LVDS_VCOM(0);
|
||||
else
|
||||
val |= LVDS_VCOM(1); /* 850mV */
|
||||
|
||||
if (inno->lvds_vod >= 400)
|
||||
val |= LVDS_VOD(3);
|
||||
else if (inno->lvds_vod >= 350)
|
||||
val |= LVDS_VOD(2);
|
||||
else if (inno->lvds_vod >= 300)
|
||||
val |= LVDS_VOD(1);
|
||||
else
|
||||
val |= LVDS_VOD(0); /* 250mV */
|
||||
|
||||
phy_update_bits(inno, REGISTER_PART_LVDS, 0x04, LVDS_VCOM_MASK | LVDS_VOD_MASK, val);
|
||||
}
|
||||
|
||||
static void inno_dsidphy_lvds_mode_enable(struct inno_dsidphy *inno)
|
||||
{
|
||||
u8 prediv = 2;
|
||||
@@ -657,7 +693,7 @@ static void inno_dsidphy_lvds_mode_enable(struct inno_dsidphy *inno)
|
||||
phy_update_bits(inno, REGISTER_PART_LVDS, 0x00,
|
||||
LVDS_DIGITAL_INTERNAL_RESET_MASK,
|
||||
LVDS_DIGITAL_INTERNAL_RESET_DISABLE);
|
||||
|
||||
inno_dsiphy_lvds_voltage_set(inno);
|
||||
/* Select LVDS mode */
|
||||
phy_update_bits(inno, REGISTER_PART_LVDS, 0x03,
|
||||
MODE_ENABLE_MASK, LVDS_MODE_ENABLE);
|
||||
@@ -956,9 +992,15 @@ static int inno_dsidphy_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(dev->of_node, "inno,lanes", &inno->lanes))
|
||||
if (device_property_read_u32(dev, "inno,lanes", &inno->lanes))
|
||||
inno->lanes = 4;
|
||||
|
||||
if (device_property_read_u32(dev, "inno,lvds-vcom", &inno->lvds_vcom))
|
||||
inno->lvds_vcom = 950;
|
||||
|
||||
if (device_property_read_u32(dev, "inno,lvds-vod", &inno->lvds_vod))
|
||||
inno->lvds_vod = 350;
|
||||
|
||||
phy_set_drvdata(phy, inno);
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
|
||||
@@ -590,6 +590,7 @@ static const u16 trans_tbl_h264e_540c[] = {
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
// /* renc and ref wrap */
|
||||
// 24, 25, 26, 27,
|
||||
28, 29, 30
|
||||
};
|
||||
|
||||
static const u16 trans_tbl_h264e_540c_osd[] = {
|
||||
@@ -599,7 +600,8 @@ static const u16 trans_tbl_h264e_540c_osd[] = {
|
||||
|
||||
static const u16 trans_tbl_h265e_540c[] = {
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
28, 29, 30
|
||||
};
|
||||
|
||||
static const u16 trans_tbl_h265e_540c_osd[] = {
|
||||
|
||||
@@ -35,6 +35,7 @@ struct rga_request *rga_request_lookup(struct rga_pending_request_manager *reque
|
||||
uint32_t id);
|
||||
|
||||
int rga_request_commit(struct rga_request *user_request);
|
||||
void rga_request_scheduler_abort(struct rga_scheduler_t *scheduler);
|
||||
void rga_request_session_destroy_abort(struct rga_session *session);
|
||||
int rga_request_put(struct rga_request *request);
|
||||
void rga_request_get(struct rga_request *request);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
@@ -21,6 +22,7 @@
|
||||
#include "rga_drv.h"
|
||||
#include "rga_mm.h"
|
||||
#include "rga_common.h"
|
||||
#include "rga_job.h"
|
||||
|
||||
#define RGA_DEBUGGER_ROOT_NAME "rkrga"
|
||||
|
||||
@@ -462,6 +464,65 @@ static int rga_hardware_show(struct seq_file *m, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rga_reset_show(struct seq_file *m, void *data)
|
||||
{
|
||||
struct rga_scheduler_t *scheduler = NULL;
|
||||
int i;
|
||||
|
||||
seq_puts(m, "help:\n");
|
||||
seq_puts(m, " 'echo <core> > reset' to reset hardware.\n");
|
||||
|
||||
seq_puts(m, "core:\n");
|
||||
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
|
||||
scheduler = rga_drvdata->scheduler[i];
|
||||
|
||||
seq_printf(m, " %s core <%d>\n",
|
||||
dev_driver_string(scheduler->dev), scheduler->core);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t rga_reset_write(struct file *file, const char __user *ubuf,
|
||||
size_t len, loff_t *offp)
|
||||
{
|
||||
char buf[14];
|
||||
int i, ret;
|
||||
int reset_core = 0;
|
||||
int reset_done = false;
|
||||
struct rga_scheduler_t *scheduler = NULL;
|
||||
|
||||
if (len > sizeof(buf) - 1)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(buf, ubuf, len))
|
||||
return -EFAULT;
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
ret = kstrtoint(buf, 10, &reset_core);
|
||||
if (ret < 0 || reset_core <= 0) {
|
||||
pr_err("invalid core! failed to reset hardware, data = %s len = %zu.\n", buf, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
|
||||
scheduler = rga_drvdata->scheduler[i];
|
||||
|
||||
if (scheduler->core == reset_core) {
|
||||
reset_done = true;
|
||||
pr_info("reset hardware core[%d]!\n", reset_core);
|
||||
|
||||
rga_request_scheduler_abort(scheduler);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!reset_done)
|
||||
pr_err("cannot find core[%d]\n", reset_core);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct rga_debugger_list rga_debugger_root_list[] = {
|
||||
{"debug", rga_debug_show, rga_debug_write, NULL},
|
||||
{"driver_version", rga_version_show, NULL, NULL},
|
||||
@@ -474,6 +535,7 @@ static struct rga_debugger_list rga_debugger_root_list[] = {
|
||||
{"dump_image", rga_dump_image_show, rga_dump_image_write, NULL},
|
||||
#endif
|
||||
{"hardware", rga_hardware_show, NULL, NULL},
|
||||
{"reset", rga_reset_show, rga_reset_write, NULL},
|
||||
};
|
||||
|
||||
static ssize_t rga_debugger_write(struct file *file, const char __user *ubuf,
|
||||
|
||||
@@ -651,6 +651,46 @@ struct rga_request *rga_request_lookup(struct rga_pending_request_manager *manag
|
||||
return request;
|
||||
}
|
||||
|
||||
void rga_request_scheduler_abort(struct rga_scheduler_t *scheduler)
|
||||
{
|
||||
struct rga_job *job;
|
||||
unsigned long flags;
|
||||
|
||||
rga_power_enable(scheduler);
|
||||
|
||||
spin_lock_irqsave(&scheduler->irq_lock, flags);
|
||||
|
||||
job = scheduler->running_job;
|
||||
if (job) {
|
||||
scheduler->running_job = NULL;
|
||||
scheduler->status = RGA_SCHEDULER_ABORT;
|
||||
scheduler->ops->soft_reset(scheduler);
|
||||
|
||||
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
|
||||
|
||||
rga_mm_unmap_job_info(job);
|
||||
|
||||
job->ret = -EBUSY;
|
||||
rga_request_release_signal(scheduler, job);
|
||||
|
||||
rga_job_next(scheduler);
|
||||
|
||||
/*
|
||||
* Since the running job was abort, turn off the power here that
|
||||
* should have been turned off after job done (corresponds to
|
||||
* power_enable in rga_job_run()).
|
||||
*/
|
||||
rga_power_disable(scheduler);
|
||||
} else {
|
||||
scheduler->status = RGA_SCHEDULER_ABORT;
|
||||
scheduler->ops->soft_reset(scheduler);
|
||||
|
||||
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
|
||||
}
|
||||
|
||||
rga_power_disable(scheduler);
|
||||
}
|
||||
|
||||
static int rga_request_scheduler_job_abort(struct rga_request *request)
|
||||
{
|
||||
int i;
|
||||
|
||||
Reference in New Issue
Block a user