Received: by 10.223.176.5 with SMTP id f5csp760651wra; Wed, 7 Feb 2018 07:08:25 -0800 (PST) X-Google-Smtp-Source: AH8x224GJm5JyYXA734zhMESUJRFG7MYbXRB9Z8KsCiLRrSQC8Uh9WK1V3YNN3uD6o2aJu1I9aM5 X-Received: by 2002:a17:902:8f8a:: with SMTP id z10-v6mr6173689plo.395.1518016105355; Wed, 07 Feb 2018 07:08:25 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518016105; cv=none; d=google.com; s=arc-20160816; b=EicY/s26jp+MpsoRdnBqivgn88fWuCeI8k1BqC4Ru4hG2JddUXuGfbyjd+M4mEK5NY xkSiNpuo/HsQkHvYmXqhth0dZDipePo57AYq/RtqoggE1wepYkGu44mxucLL/OmEkC8K Yk43Desauc2ltOkbG1nOjglarYzu//fNROBuT7aCZGOgOFaKjvyLEP7HOoF41cPvaanX imf/S6/cdGpV97wJBF5ijXX7TZX3xMUaAo1N48fKk6cG0VfbEgQo2NMhvzJXUyBIlDZG WLEze0wUA12paS6YMgfve4DnjjUcyQBC8DX6CuBUPMW4Gt2IGi3B6qu+GXQlAcwHZcK7 XI6g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature:arc-authentication-results; bh=RHto4Qir2c0vq2J2kKFeEnU2mKZDGcD9V91c1Qud9Co=; b=maiEbuL4jF+g18uKkx2UwXGdTKxJhcWpXT31AcCtJbvs9XkskXaTVLMjHAlCCoyERt DdUSJZTFCjjk+yyHQ+1KE8IvTBOSwg5vArFfio2cNsLCAUKVorOYQ2rtvBZXup8zTpVN HXAuoaszzHuqSiO6UDT0V3L8BTobcvI6XzoQnrfBx4S/IruyWJFUXMWowt2OSNv5xGoR mix1qZ0YgtS0v0YDJNyMa5NULjo8QiWeZwkqUiEpNxSwuRDmmc4ZW75CiRSkBmtalcHK hojuPXEw/vviUkpw5D5AhVpO3xi0nt1LpikwSBu2/wMWczqN07ruOze5Vroib1MZ0y81 bpfw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=fovqQ7fb; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p15si1031415pgr.423.2018.02.07.07.08.09; Wed, 07 Feb 2018 07:08:25 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=fovqQ7fb; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754286AbeBGPH3 (ORCPT + 99 others); Wed, 7 Feb 2018 10:07:29 -0500 Received: from mail-wm0-f67.google.com ([74.125.82.67]:56233 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754108AbeBGPH1 (ORCPT ); Wed, 7 Feb 2018 10:07:27 -0500 Received: by mail-wm0-f67.google.com with SMTP id 143so3711814wma.5 for ; Wed, 07 Feb 2018 07:07:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=RHto4Qir2c0vq2J2kKFeEnU2mKZDGcD9V91c1Qud9Co=; b=fovqQ7fbdV2SvHBCL82AsrWuqaApnyU0uyaoGHO9CCUPDb0hoyrZLYis8F9C+V4JRV oLLxkTfXbLnzpX7Rh5dfImh6NLk0h/w5k/b/6qKDKiacipfNPU92Frgd3Px9m/Ol0hDp nw9PeUAi0jss6HevNIl7lYEJrlWQo1cPS1ATM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=RHto4Qir2c0vq2J2kKFeEnU2mKZDGcD9V91c1Qud9Co=; b=sl0cs+1M1a9SQxtXckbb+L8kescR9PiQqC/dSi4r5gGTFwcgX9LRFv2I1aHYPsLZqI eb/YT4gWu+7OFcKKvy5zPA+N858dTDqXqvZtriL3x1bVP531sE5o8SbvZsu2PSTqerVy vd2N1/Gga02zHjxobd8AsyN5YBQjCXosvfb3+lvY7+V2LZnksYRPk0EHHXmK/sHnRpFx yxQ/GcoRXIeVEWK3j/YbLOs4wmose1jBcbNuNEAN6ousEOCjkGIgGF2cvDvlxrnNVvse J2umfuD+54Kq+vmSc3SoZf+cCnIQvHA87UnV7YFknq+wLFndEzri3NYmNlIBlg1EZqyY 5AJA== X-Gm-Message-State: APf1xPCkukOoBUEPjp8WUoJl8LYQcIMcpnhL1xy5i8zGcnMRlMm+dV8E xlvxKWK+EpYKFUNBY3uTSAv51w== X-Received: by 10.28.64.67 with SMTP id n64mr4450054wma.147.1518016045268; Wed, 07 Feb 2018 07:07:25 -0800 (PST) Received: from oak.lan (cpc141214-aztw34-2-0-cust773.18-1.cable.virginm.net. [86.9.19.6]) by smtp.gmail.com with ESMTPSA id d17sm1496511wrc.38.2018.02.07.07.07.23 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 07 Feb 2018 07:07:24 -0800 (PST) Date: Wed, 7 Feb 2018 15:07:22 +0000 From: Daniel Thompson To: Enric Balletbo i Serra Cc: Doug Anderson , Pavel Machek , Rob Herring , Jingoo Han , Richard Purdie , Jacek Anaszewski , Brian Norris , Guenter Roeck , Lee Jones , Alexandru Stan , linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v2 1/4] backlight: pwm_bl: linear interpolation between brightness-levels Message-ID: <20180207150722.zblz6dnfcmrvlxa4@oak.lan> References: <20180207141337.22247-1-enric.balletbo@collabora.com> <20180207141337.22247-2-enric.balletbo@collabora.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20180207141337.22247-2-enric.balletbo@collabora.com> User-Agent: NeoMutt/20170113 (1.7.2) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Feb 07, 2018 at 03:13:34PM +0100, Enric Balletbo i Serra wrote: > Setting num-interpolated-steps in the dts will allow you to have linear > interpolation between values of brightness-levels. This way a high > resolution pwm duty cycle can be used without having to list out every > possible value in the dts. This system also allows for gamma corrected > values. > > The most simple example is interpolate between two brightness values a > number of steps, this can be done setting the following in the dts: > > brightness-levels = <0 65535>; > num-interpolated-steps = <1024>; > default-brightness-level = <512>; > > This will create a brightness-level table with the following values: > > <0 63 126 189 252 315 378 441 ... 64260 64323 64386 64449 65535> > > Another use case can be describe a gamma corrected curve, as we have > better sensitivity at low luminance than high luminance we probably > want have smaller steps for low brightness levels values and bigger > steps for high brightness levels values. This can be achieved with > the following in the dts: > > brightness-levels = <0 4096 65535>; > num-interpolated-steps = <1024>; > default-brightness-level = <512>; > > This will create a brightness-levels table with the following values: > > <0 4 8 12 16 20 ... 4096 4156 4216 4276 ... 65535> > > Signed-off-by: Enric Balletbo i Serra I'd really like to ack this one (especially so given I'm extremely late with a review) but unfortunately... > --- > Changes since v1: > - None. > > drivers/video/backlight/pwm_bl.c | 86 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 86 insertions(+) > > diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c > index 8e3f1245f5c5..9dbf0b3e806f 100644 > --- a/drivers/video/backlight/pwm_bl.c > +++ b/drivers/video/backlight/pwm_bl.c > @@ -147,7 +147,11 @@ static int pwm_backlight_parse_dt(struct device *dev, > struct platform_pwm_backlight_data *data) > { > struct device_node *node = dev->of_node; > + unsigned int num_levels = 0; > + unsigned int levels_count; > + unsigned int num_steps; > struct property *prop; > + unsigned int *table; > int length; > u32 value; > int ret; > @@ -167,6 +171,7 @@ static int pwm_backlight_parse_dt(struct device *dev, > /* read brightness levels from DT property */ > if (data->max_brightness > 0) { > size_t size = sizeof(*data->levels) * data->max_brightness; > + unsigned int i, j, n = 0; > > data->levels = devm_kzalloc(dev, size, GFP_KERNEL); > if (!data->levels) > @@ -184,6 +189,87 @@ static int pwm_backlight_parse_dt(struct device *dev, > return ret; > > data->dft_brightness = value; > + > + /* > + * This property is optional, if is set enables linear > + * interpolation between each of the values of brightness levels > + * and creates a new pre-computed table. > + */ > + of_property_read_u32(node, "num-interpolated-steps", > + &num_steps); > + > + /* > + * Make sure that there is at least two entries in the > + * brightness-levels table, otherwise we can't interpolate > + * between two points. > + */ > + if (num_steps) { > + if (data->max_brightness < 2) { > + dev_err(dev, "can't interpolate\n"); > + return -EINVAL; > + } > + > + /* > + * Recalculate the number of brightness levels, now > + * taking in consideration the number of interpolated > + * steps between two levels. > + */ > + for (i = 0; i < data->max_brightness - 1; i++) { > + if ((data->levels[i + 1] - data->levels[i]) / > + num_steps) > + num_levels += num_steps; > + else > + num_levels++; > + } > + num_levels++; > + dev_dbg(dev, "new number of brightness levels: %d\n", > + num_levels); > + > + /* > + * Create a new table of brightness levels with all the > + * interpolated steps. > + */ > + table = kcalloc(num_levels, sizeof(*table), GFP_KERNEL); > + if (!table) > + return -ENOMEM; > + > + /* Fill the interpolated table. */ > + levels_count = 0; > + for (i = 0; i < data->max_brightness - 1; i++) { > + value = data->levels[i]; > + n = (data->levels[i + 1] - value) / num_steps; > + if (n > 0) { > + for (j = 0; j < num_steps; j++) { > + table[levels_count] = value; > + value += n; > + levels_count++; > + } > + } else { > + table[levels_count] = data->levels[i]; > + levels_count++; > + } > + } > + table[levels_count] = data->levels[i]; > + > + /* > + * As we use interpolation lets remove current > + * brightness levels table for the new interpolated > + * table. > + */ > + devm_kfree(dev, data->levels); > + data->levels = devm_kcalloc(dev, num_levels, > + sizeof(*data->levels), > + GFP_KERNEL); > + memcpy(data->levels, table, > + num_levels * sizeof(*table)); ... this looks a bit too odd. I think I can live we a pre-calculated table (not my preference... but I can live with it). However the way table is allocated, then allocated again and copied without a NULL check isn't OK. Can't we just switch the first allocation over to a devres alloc and then just swap pointers here? And a minor nit: do we need calloc? The loop should initialize every element anyway. Daniel. > + kfree(table); > + /* > + * Reassign max_brightness value to the new total number > + * of brightness levels. > + */ > + data->max_brightness = num_levels; > + } > + > data->max_brightness--; > } > > -- > 2.15.1 >