Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 61 additions & 1 deletion drivers/auxdisplay/lcd-vk2c21.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,23 @@
#define VK2C21_SYS_OFF_LCD_OFF 0x00 /* System + LCD off */
#define VK2C21_FRAME_80HZ 0x00 /* 80 Hz frame rate */
#define VK2C21_BLINK_OFF 0x00 /* Blinking off */
#define VK2C21_IVA_DEFAULT 0x0F /* VLCD selected, IVA off, R1 */
#define VK2C21_IVA_DEFAULT 0x0F /* VLCD selected, IVA off, R1 (external VR) */

/*
* IVA on, SEG mode: 16 internal bias-voltage levels.
* 0x30 = level 0 = 1.000 x VDD (highest contrast / "brightest")
* 0x3F = level 15 = 0.529 x VDD (lowest contrast / "dimmest")
* SEG mode (vs. VLCD-output mode at 0x10..0x1F) is used because the R58X-Pro
* has an external resistor on the VLCD pin: in VLCD-output mode the external
* resistor dominates the chip's internal driver and the brightness register
* has no visible effect. SEG mode tells the chip to ignore the VLCD pin and
* generate the bias voltage purely internally.
* Userspace brightness is inverted (0 = dimmest, 15 = brightest) so that
* higher numbers look brighter, matching the usual convention.
*/
#define VK2C21_IVA_ON_BASE 0x30
#define VK2C21_BRIGHTNESS_MAX 15
#define VK2C21_BRIGHTNESS_DEFAULT (-1) /* IVA off, external VR in use */

/* Display RAM has 10 addressable bytes (SEG/COM matrix) */
#define VK2C21_RAM_SIZE 10
Expand Down Expand Up @@ -185,6 +201,7 @@ struct vk2c21_data {
unsigned int half_period_ns;
u8 dispram[VK2C21_RAM_SIZE];
char display_text[VK2C21_MAX_DIGITS + 1];
int brightness; /* -1 = IVA off / "default", 0..15 = IVA level */
};

/* ------------------------------------------------------------------ */
Expand Down Expand Up @@ -414,9 +431,51 @@ static ssize_t clear_store(struct device *dev,
}
static DEVICE_ATTR_WO(clear);

static ssize_t brightness_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct vk2c21_data *d = dev_get_drvdata(dev);

if (d->brightness == VK2C21_BRIGHTNESS_DEFAULT)
return sysfs_emit(buf, "default\n");
return sysfs_emit(buf, "%d\n", d->brightness);
}

static ssize_t brightness_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct vk2c21_data *d = dev_get_drvdata(dev);
int ret, level;
u8 iva;

if (sysfs_streq(buf, "default")) {
level = VK2C21_BRIGHTNESS_DEFAULT;
iva = VK2C21_IVA_DEFAULT;
} else {
ret = kstrtoint(buf, 0, &level);
if (ret)
return ret;
if (level < 0 || level > VK2C21_BRIGHTNESS_MAX)
return -EINVAL;
/* Invert: userspace 15 = brightest = IVA level 0 = 0x30 */
iva = VK2C21_IVA_ON_BASE + (VK2C21_BRIGHTNESS_MAX - level);
}

mutex_lock(&d->lock);
ret = vk2c21_send_cmd(d, VK2C21_IVASET, iva);
if (!ret)
d->brightness = level;
mutex_unlock(&d->lock);

return ret ? ret : count;
}
static DEVICE_ATTR_RW(brightness);

static struct attribute *vk2c21_sysfs_attrs[] = {
&dev_attr_display.attr,
&dev_attr_clear.attr,
&dev_attr_brightness.attr,
NULL,
};

Expand Down Expand Up @@ -445,6 +504,7 @@ static int vk2c21_probe(struct platform_device *pdev)
return -ENOMEM;

d->dev = dev;
d->brightness = VK2C21_BRIGHTNESS_DEFAULT;
mutex_init(&d->lock);
platform_set_drvdata(pdev, d);

Expand Down
12 changes: 11 additions & 1 deletion drivers/input/remotectl/rockchip_pwm_remotectl.c
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,17 @@ static int rk_pwm_probe(struct platform_device *pdev)
input->id.product = 0x0006;
input->id.version = 0x0100;
ddata->input = input;
irq = platform_get_irq(pdev, 0);
/*
* On PWM v4 (RK3588), channel 3 has a dedicated capture IRQ at
* index 1, separate from the group IRQ at index 0 that is shared
* with the other channels in the same PWM controller. Prefer the
* dedicated one so we don't collide with the pwm-rockchip driver
* bound to another channel (which claims the group IRQ without
* IRQF_SHARED on v4). Fall back to index 0 for older PWM v1-v3.
*/
irq = platform_get_irq(pdev, 1);
if (irq < 0)
irq = platform_get_irq(pdev, 0);
Comment on lines +943 to +945

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

platform_c="$(rg --files | rg '(^|/)drivers/base/platform\.c$' | head -n1)"
test -n "$platform_c"

rg -n -A35 'int platform_get_irq_optional' "$platform_c" |
  rg -- '-EPROBE_DEFER|-ENXIO|platform_get_irq'

Repository: armbian/linux-rockchip

Length of output: 2137


Don’t fall back on all IRQ errors here. platform_get_irq(pdev, 1) can return -EPROBE_DEFER; this "< 0" check would drop to IRQ 0 instead of deferring probe. Use platform_get_irq_optional(pdev, 1) and fall back only on -ENXIO.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@drivers/input/remotectl/rockchip_pwm_remotectl.c` around lines 943 - 945,
Update the IRQ lookup around platform_get_irq in the probe path to use
platform_get_irq_optional(pdev, 1), preserving -EPROBE_DEFER and other errors.
Fall back to platform_get_irq_optional(pdev, 0) only when the first lookup
returns -ENXIO, rather than for every negative result.

Source: MCP tools

if (irq < 0) {
dev_err(&pdev->dev, "cannot find IRQ\n");
goto error_pclk;
Expand Down
24 changes: 22 additions & 2 deletions drivers/video/rockchip/mpp/mpp_service.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,13 +329,33 @@ static int mpp_show_device_load(struct seq_file *file, void *v)

for (j = 0; j < MPP_MAX_CORE_NUM; j++) {
struct mpp_dev *mpp = queue->cores[j];
struct mpp_load_info *load_info;
u32 load, load_frac, util, util_frac;

if (!mpp)
continue;

load_info = &mpp->load_info;
load = load_info->load;
load_frac = load_info->load_frac;
util = load_info->utilization;
util_frac = load_info->utilization_frac;

/*
* load_info is only refreshed by mpp_dev_load() on task
* completion, so an idle device keeps reporting the last
* busy interval forever. If no task has updated the stats
* for more than one load_interval, the device has gone
* idle: report zero instead of the stale snapshot.
*/
if (!mpp->load_en ||
ktime_us_delta(ktime_get(), load_info->load_time) >
(s64)srv->load_interval * 1000 * 2)
load = load_frac = util = util_frac = 0;

seq_printf(file, "%-25s load: %3d.%02d%% utilization: %3d.%02d%%\n",
dev_name(mpp->dev),
mpp->load_info.load, mpp->load_info.load_frac,
mpp->load_info.utilization, mpp->load_info.utilization_frac);
load, load_frac, util, util_frac);
}
}

Expand Down
Loading