On register r/w macros/procedures of drivers/media/pci

2015-04-19 Thread Andrey Utkin
I am starting a work on driver for techwell tw5864 media grabberencoder.
I am basing on tw68 driver (mentorship, advising and testing by board
owners are appreciated). And here (and in some other
drivers/media/pci/ drivers) I see what confuses me:

tw68-core.c:
dev-lmmio = ioremap(pci_resource_start(pci_dev, 0),
 pci_resource_len(pci_dev, 0));
dev-bmmio = (__u8 __iomem *)dev-lmmio;

tw68.h:
#define tw_readl(reg)   readl(dev-lmmio + ((reg)  2))
#define tw_readb(reg)   readb(dev-bmmio + (reg))
#define tw_writel(reg, value)   writel((value), dev-lmmio + ((reg)  2))
#define tw_writeb(reg, value)   writeb((value), dev-bmmio + (reg))

I am mostly userland developer and I wouldn't expect bmmio pointer to
contain value numerically different from lmmio after such simple
casting.
But still, if this is correct, then how should I implement
tw_{read,write}w to operate on 2 bytes (a word)? Similarly, it would
look like this:
#define tw_readl(reg)   readl(dev-lmmio + ((reg)  1))
That looks odd.

In contrary, in drivers/media/pci/dm1105, we see no explicit shifting
of register address. It uses {in,out}{b,w,l} macros, which seem to
turn out the same {read,write}{b,w,l} (with some reservations):
http://lxr.free-electrons.com/source/include/asm-generic/io.h#L354

dm1105.c:#define dm_io_mem(reg) ((unsigned long)(dev-io_mem[reg]))
dm1105.c:#define dm_readb(reg)  inb(dm_io_mem(reg))
dm1105.c:#define dm_writeb(reg, value)  outb((value), (dm_io_mem(reg)))
dm1105.c:#define dm_readw(reg)  inw(dm_io_mem(reg))
dm1105.c:#define dm_writew(reg, value)  outw((value), (dm_io_mem(reg)))
dm1105.c:#define dm_readl(reg)  inl(dm_io_mem(reg))
dm1105.c:#define dm_writel(reg, value)  outl((value), (dm_io_mem(reg)))

This looks like contradiction to me (shifting register address vs. no
shifting), so that one practice may be even just wrong and broken
(which is hard to believe due to active maintenance of all drivers).
I highly appreciate your help me in determining the best practice to
follow in this new driver.
Thanks.

-- 
Bluecherry developer.
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] clk: change clk_ops' -round_rate() prototype

2015-04-19 Thread Heiko Stübner
Hi Boris,

Am Freitag, 17. April 2015, 09:29:28 schrieb Boris Brezillon:
 Clock rates are stored in an unsigned long field, but -round_rate()
 (which returns a rounded rate from a requested one) returns a long
 value (errors are reported using negative error codes), which can lead
 to long overflow if the clock rate exceed 2Ghz.
 
 Change -round_rate() prototype to return 0 or an error code, and pass the
 requested rate as a pointer so that it can be adjusted depending on
 hardware capabilities.
 
 Signed-off-by: Boris Brezillon boris.brezil...@free-electrons.com
 ---

On a rk3288-veyron-pinky with the fix described below:
Tested-by: Heiko Stuebner he...@sntech.de


 diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
 index fa5a00e..1462ddc 100644
 --- a/drivers/clk/clk.c
 +++ b/drivers/clk/clk.c
 @@ -1640,8 +1643,10 @@ static struct clk_core *clk_calc_new_rates(struct
 clk_core *clk, parent_hw);
   parent = parent_hw ? parent_hw-core : NULL;
   } else if (clk-ops-round_rate) {
 - new_rate = clk-ops-round_rate(clk-hw, rate,
 - best_parent_rate);
 + if (clk-ops-round_rate(clk-hw, new_rate,
 +  best_parent_rate))
 + return NULL;
 +
   if (new_rate  min_rate || new_rate  max_rate)
   return NULL;
   } else if (!parent || !(clk-flags  CLK_SET_RATE_PARENT)) {

This is using new_rate uninitialized when calling into the round_rate
callback. Which in turn pushed my PLLs up to 2.2GHz :-)

I guess you'll need something like the following:

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index db4e4b2..afc7733 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1605,6 +1605,7 @@ static struct clk_core *clk_calc_new_rates(struct 
clk_core *clk,
parent_hw);
parent = parent_hw ? parent_hw-core : NULL;
} else if (clk-ops-round_rate) {
+   new_rate = rate;
if (clk-ops-round_rate(clk-hw, new_rate,
 best_parent_rate))
return NULL;




 diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
 index f8d3baf..bd408ef 100644
 --- a/drivers/clk/rockchip/clk-pll.c
 +++ b/drivers/clk/rockchip/clk-pll.c
 @@ -63,8 +63,8 @@ static const struct rockchip_pll_rate_table
 *rockchip_get_pll_settings( return NULL;
  }
 
 -static long rockchip_pll_round_rate(struct clk_hw *hw,
 - unsigned long drate, unsigned long *prate)
 +static int rockchip_pll_round_rate(struct clk_hw *hw,
 + unsigned long *drate, unsigned long *prate)
  {
   struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
   const struct rockchip_pll_rate_table *rate_table = pll-rate_table;
 @@ -72,12 +72,15 @@ static long rockchip_pll_round_rate(struct clk_hw *hw,
 
   /* Assumming rate_table is in descending order */
   for (i = 0; i  pll-rate_count; i++) {
 - if (drate = rate_table[i].rate)
 - return rate_table[i].rate;
 + if (*drate = rate_table[i].rate) {
 + *drate = rate_table[i].rate;
 + return 0;
 + }
   }
 
   /* return minimum supported value */
 - return rate_table[i - 1].rate;
 + *drate = rate_table[i - 1].rate;
 + return 0;
  }
 
  /*

The rockchip-part:
Reviewed-by: Heiko Stuebner he...@sntech.de


And as I've stumbled onto this recently too, the clock-maintainership has
expanded to Stephen Boyd and linux-...@vger.kernel.org .


Heiko
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: On register r/w macros/procedures of drivers/media/pci

2015-04-19 Thread Hans Verkuil
On 04/19/2015 09:36 AM, Andrey Utkin wrote:
 I am starting a work on driver for techwell tw5864 media grabberencoder.
 I am basing on tw68 driver (mentorship, advising and testing by board
 owners are appreciated). And here (and in some other
 drivers/media/pci/ drivers) I see what confuses me:
 
 tw68-core.c:
 dev-lmmio = ioremap(pci_resource_start(pci_dev, 0),
  pci_resource_len(pci_dev, 0));
 dev-bmmio = (__u8 __iomem *)dev-lmmio;
 
 tw68.h:
 #define tw_readl(reg)   readl(dev-lmmio + ((reg)  2))
 #define tw_readb(reg)   readb(dev-bmmio + (reg))
 #define tw_writel(reg, value)   writel((value), dev-lmmio + ((reg)  2))
 #define tw_writeb(reg, value)   writeb((value), dev-bmmio + (reg))
 
 I am mostly userland developer and I wouldn't expect bmmio pointer to
 contain value numerically different from lmmio after such simple
 casting.

Check the types of llmio and bbmio:

u32 __iomem *lmmio;
u8  __iomem *bmmio;

So the values of the pointers are the same, but the types are not.

So 'lmmio + 1' == 'bmmio + sizeof(u32)' == 'bbmio + 4'.

Since all the registers are defined as byte offsets relative to the start
of the memory map you cannot just do 'lmmio + reg' since that would be a
factor 4 off. Instead you have to divide by 4 to get it back in line.

Frankly, I don't think lmmio is necessary at all since readl/writel don't
need a u32 pointer at all since they use void pointers. I never noticed
that when I cleaned up the tw68 driver. Using 'void __iomem *mmio' instead
of lmmio/bmmio and dropping the shifts in the tw_ macros would work just
as well.

 But still, if this is correct, then how should I implement
 tw_{read,write}w to operate on 2 bytes (a word)? Similarly, it would
 look like this:
 #define tw_readl(reg)   readl(dev-lmmio + ((reg)  1))

As suggested above, just use a single void __iomem *mmio pointer.

 That looks odd.
 
 In contrary, in drivers/media/pci/dm1105, we see no explicit shifting
 of register address. It uses {in,out}{b,w,l} macros, which seem to
 turn out the same {read,write}{b,w,l} (with some reservations):
 http://lxr.free-electrons.com/source/include/asm-generic/io.h#L354
 
 dm1105.c:#define dm_io_mem(reg) ((unsigned long)(dev-io_mem[reg]))
 dm1105.c:#define dm_readb(reg)  inb(dm_io_mem(reg))
 dm1105.c:#define dm_writeb(reg, value)  outb((value), (dm_io_mem(reg)))
 dm1105.c:#define dm_readw(reg)  inw(dm_io_mem(reg))
 dm1105.c:#define dm_writew(reg, value)  outw((value), (dm_io_mem(reg)))
 dm1105.c:#define dm_readl(reg)  inl(dm_io_mem(reg))
 dm1105.c:#define dm_writel(reg, value)  outl((value), (dm_io_mem(reg)))
 
 This looks like contradiction to me (shifting register address vs. no
 shifting), so that one practice may be even just wrong and broken
 (which is hard to believe due to active maintenance of all drivers).
 I highly appreciate your help me in determining the best practice to
 follow in this new driver.
 Thanks.
 

Hope this helps,

Hans
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: On register r/w macros/procedures of drivers/media/pci

2015-04-19 Thread Andrey Utkin
On Sun, Apr 19, 2015 at 11:28 AM, Hans Verkuil hverk...@xs4all.nl wrote:
 Check the types of llmio and bbmio:

 u32 __iomem *lmmio;
 u8  __iomem *bmmio;

 So the values of the pointers are the same, but the types are not.

 So 'lmmio + 1' == 'bmmio + sizeof(u32)' == 'bbmio + 4'.

 Since all the registers are defined as byte offsets relative to the start
 of the memory map you cannot just do 'lmmio + reg' since that would be a
 factor 4 off. Instead you have to divide by 4 to get it back in line.

 Frankly, I don't think lmmio is necessary at all since readl/writel don't
 need a u32 pointer at all since they use void pointers. I never noticed
 that when I cleaned up the tw68 driver. Using 'void __iomem *mmio' instead
 of lmmio/bmmio and dropping the shifts in the tw_ macros would work just
 as well.


 Hope this helps,

Oh, indeed, I have forgot this basic thing of pointer arithmetics.
Thanks a lot for elaboration and the proposed solution.

-- 
Bluecherry developer.
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 04/10] DT: Add documentation for the Skyworks AAT1290

2015-04-19 Thread Sakari Ailus
On Wed, Apr 15, 2015 at 08:48:34AM +0200, Jacek Anaszewski wrote:
 This patch adds device tree binding documentation for
 1.5A Step-Up Current Regulator for Flash LEDs.
 
 Signed-off-by: Jacek Anaszewski j.anaszew...@samsung.com
 Acked-by: Kyungmin Park kyungmin.p...@samsung.com
 Cc: Bryan Wu coolo...@gmail.com
 Cc: Richard Purdie rpur...@rpsys.net
 Cc: devicet...@vger.kernel.org

Acked-by: Sakari Ailus sakari.ai...@linux.intel.com

-- 
Sakari Ailus
e-mail: sakari.ai...@iki.fi XMPP: sai...@retiisi.org.uk
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] gspca: sn9c2028: Add gain and autogain controls Genius Videocam Live v2

2015-04-19 Thread Theodore Kilgore



On Sun, 19 Apr 2015, Vasily Khoruzhick wrote:


Autogain algorithm is very simple, if average luminance is low - increase gain,
if it's high - decrease gain. Gain granularity is low enough for this algo to
stabilize quickly.

Signed-off-by: Vasily Khoruzhick anars...@gmail.com
---
drivers/media/usb/gspca/sn9c2028.c | 121 +
drivers/media/usb/gspca/sn9c2028.h |  20 +-
2 files changed, 138 insertions(+), 3 deletions(-)

diff --git a/drivers/media/usb/gspca/sn9c2028.c 
b/drivers/media/usb/gspca/sn9c2028.c
index 317b02c..0ff390f 100644
--- a/drivers/media/usb/gspca/sn9c2028.c
+++ b/drivers/media/usb/gspca/sn9c2028.c
@@ -34,6 +34,16 @@ struct sd {
struct gspca_dev gspca_dev;  /* !! must be the first item */
u8 sof_read;
u16 model;
+
+#define MIN_AVG_LUM 8500
+#define MAX_AVG_LUM 1
+   int avg_lum;
+   u8 avg_lum_l;
+
+   struct { /* autogain and gain control cluster */
+   struct v4l2_ctrl *autogain;
+   struct v4l2_ctrl *gain;
+   };
};

struct init_command {
@@ -252,6 +262,77 @@ static int run_start_commands(struct gspca_dev *gspca_dev,
return 0;
}

+static void set_gain(struct gspca_dev *gspca_dev, s32 g)
+{
+   struct sd *sd = (struct sd *) gspca_dev;
+
+   struct init_command genius_vcam_live_gain_cmds[] = {
+   {{0x1d, 0x25, 0x10, 0x20, 0xab, 0x00}, 0},
+   };
+   if (!gspca_dev-streaming)
+   return;
+
+   switch (sd-model) {
+   case 0x7003:
+   genius_vcam_live_gain_cmds[0].instruction[2] = g;
+   run_start_commands(gspca_dev, genius_vcam_live_gain_cmds,
+  ARRAY_SIZE(genius_vcam_live_gain_cmds));
+   break;
+   default:
+   break;
+   }
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+   struct gspca_dev *gspca_dev =
+   container_of(ctrl-handler, struct gspca_dev, ctrl_handler);
+   struct sd *sd = (struct sd *)gspca_dev;
+
+   gspca_dev-usb_err = 0;
+
+   if (!gspca_dev-streaming)
+   return 0;
+
+   switch (ctrl-id) {
+   /* standalone gain control */
+   case V4L2_CID_GAIN:
+   set_gain(gspca_dev, ctrl-val);
+   break;
+   /* autogain */
+   case V4L2_CID_AUTOGAIN:
+   set_gain(gspca_dev, sd-gain-val);
+   break;
+   }
+   return gspca_dev-usb_err;
+}
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+   .s_ctrl = sd_s_ctrl,
+};
+
+
+static int sd_init_controls(struct gspca_dev *gspca_dev)
+{
+   struct v4l2_ctrl_handler *hdl = gspca_dev-ctrl_handler;
+   struct sd *sd = (struct sd *)gspca_dev;
+
+   gspca_dev-vdev.ctrl_handler = hdl;
+   v4l2_ctrl_handler_init(hdl, 2);
+
+   switch (sd-model) {
+   case 0x7003:
+   sd-gain = v4l2_ctrl_new_std(hdl, sd_ctrl_ops,
+   V4L2_CID_GAIN, 0, 20, 1, 0);
+   sd-autogain = v4l2_ctrl_new_std(hdl, sd_ctrl_ops,
+   V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+   break;
+   default:
+   break;
+   }
+
+   return 0;
+}
static int start_spy_cam(struct gspca_dev *gspca_dev)
{
struct init_command spy_start_commands[] = {
@@ -641,6 +722,9 @@ static int start_genius_videocam_live(struct gspca_dev 
*gspca_dev)
if (r  0)
return r;

+   if (sd-gain)
+   set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd-gain));
+
return r;
}

@@ -757,6 +841,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
return -ENXIO;
}

+   sd-avg_lum = -1;
+
return err_code;
}

@@ -776,6 +862,39 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
PERR(Camera Stop command failed);
}

+static void do_autogain(struct gspca_dev *gspca_dev, int avg_lum)
+{
+   struct sd *sd = (struct sd *) gspca_dev;
+   s32 cur_gain = v4l2_ctrl_g_ctrl(sd-gain);
+
+   if (avg_lum == -1)
+   return;
+
+   if (avg_lum  MIN_AVG_LUM) {
+   if (cur_gain == sd-gain-maximum)
+   return;
+   cur_gain++;
+   v4l2_ctrl_s_ctrl(sd-gain, cur_gain);
+   }
+   if (avg_lum  MAX_AVG_LUM) {
+   if (cur_gain == sd-gain-minimum)
+   return;
+   cur_gain--;
+   v4l2_ctrl_s_ctrl(sd-gain, cur_gain);
+   }
+
+}
+
+static void sd_dqcallback(struct gspca_dev *gspca_dev)
+{
+   struct sd *sd = (struct sd *) gspca_dev;
+
+   if (sd-autogain == NULL || !v4l2_ctrl_g_ctrl(sd-autogain))
+   return;
+
+   do_autogain(gspca_dev, sd-avg_lum);
+}
+
/* Include sn9c2028 sof detection functions */
#include sn9c2028.h

@@ -810,8 +929,10 @@ static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
.config = sd_config,
.init = sd_init,
+   .init_controls = sd_init_controls,

Re: [PATCH] Add support for TechniSat Skystar S2

2015-04-19 Thread Patrick Boettcher
Hi,

On Fri, 17 Apr 2015 11:06:30 +0200
Patrick Boettcher patrick.boettc...@posteo.de wrote:
 http://git.linuxtv.org/cgit.cgi/pb/media_tree.git/ cx24120-v2

Jannis pointed out, that my repository on linuxtv.org was not
fetchable...

I put one onto github, this should work:

https://github.com/pboettch/linux.git cx24120-v2

It is the same commits as I was pushing to the linuxtv.org .

regards,
--
Patrick.
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] gspca: sn9c2028: Add support for Genius Videocam Live v2

2015-04-19 Thread Vasily Khoruzhick
Signed-off-by: Vasily Khoruzhick anars...@gmail.com
---
 drivers/media/usb/gspca/sn9c2028.c | 120 -
 1 file changed, 119 insertions(+), 1 deletion(-)

diff --git a/drivers/media/usb/gspca/sn9c2028.c 
b/drivers/media/usb/gspca/sn9c2028.c
index 39b6b2e..317b02c 100644
--- a/drivers/media/usb/gspca/sn9c2028.c
+++ b/drivers/media/usb/gspca/sn9c2028.c
@@ -2,6 +2,7 @@
  * SN9C2028 library
  *
  * Copyright (C) 2009 Theodore Kilgore kilg...@auburn.edu
+ * Copyright (C) 2015 Vasily Khoruzhick anars...@gmail.com
  *
  * 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
@@ -128,7 +129,7 @@ static int sn9c2028_long_command(struct gspca_dev 
*gspca_dev, u8 *command)
status = -1;
for (i = 0; i  256  status  2; i++)
status = sn9c2028_read1(gspca_dev);
-   if (status != 2) {
+   if (status  0) {
pr_err(long command status read error %d\n, status);
return (status  0) ? status : -EIO;
}
@@ -178,6 +179,9 @@ static int sd_config(struct gspca_dev *gspca_dev,
case 0x7005:
PDEBUG(D_PROBE, Genius Smart 300 camera);
break;
+   case 0x7003:
+   PDEBUG(D_PROBE, Genius Videocam Live v2);
+   break;
case 0x8000:
PDEBUG(D_PROBE, DC31VC);
break;
@@ -530,6 +534,116 @@ static int start_genius_cam(struct gspca_dev *gspca_dev)
  ARRAY_SIZE(genius_start_commands));
 }
 
+static int start_genius_videocam_live(struct gspca_dev *gspca_dev)
+{
+   int r;
+   struct sd *sd = (struct sd *) gspca_dev;
+   struct init_command genius_vcam_live_start_commands[] = {
+   {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 0},
+   {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
+   {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
+   {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
+   {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
+
+   {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
+   {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
+   {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
+   {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
+   {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
+   {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
+   {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
+   {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
+   {{0x1c, 0x20, 0x00, 0x2d, 0x00, 0x00}, 4},
+   {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x13, 0x22, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
+   {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
+   {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
+   {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
+   {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
+   {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
+   {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
+   {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
+   {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
+   {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
+   {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
+   {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x01, 0x04, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x02, 0x92, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
+   {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
+ 

[PATCH 2/2] gspca: sn9c2028: Add gain and autogain controls Genius Videocam Live v2

2015-04-19 Thread Vasily Khoruzhick
Autogain algorithm is very simple, if average luminance is low - increase gain,
if it's high - decrease gain. Gain granularity is low enough for this algo to
stabilize quickly.

Signed-off-by: Vasily Khoruzhick anars...@gmail.com
---
 drivers/media/usb/gspca/sn9c2028.c | 121 +
 drivers/media/usb/gspca/sn9c2028.h |  20 +-
 2 files changed, 138 insertions(+), 3 deletions(-)

diff --git a/drivers/media/usb/gspca/sn9c2028.c 
b/drivers/media/usb/gspca/sn9c2028.c
index 317b02c..0ff390f 100644
--- a/drivers/media/usb/gspca/sn9c2028.c
+++ b/drivers/media/usb/gspca/sn9c2028.c
@@ -34,6 +34,16 @@ struct sd {
struct gspca_dev gspca_dev;  /* !! must be the first item */
u8 sof_read;
u16 model;
+
+#define MIN_AVG_LUM 8500
+#define MAX_AVG_LUM 1
+   int avg_lum;
+   u8 avg_lum_l;
+
+   struct { /* autogain and gain control cluster */
+   struct v4l2_ctrl *autogain;
+   struct v4l2_ctrl *gain;
+   };
 };
 
 struct init_command {
@@ -252,6 +262,77 @@ static int run_start_commands(struct gspca_dev *gspca_dev,
return 0;
 }
 
+static void set_gain(struct gspca_dev *gspca_dev, s32 g)
+{
+   struct sd *sd = (struct sd *) gspca_dev;
+
+   struct init_command genius_vcam_live_gain_cmds[] = {
+   {{0x1d, 0x25, 0x10, 0x20, 0xab, 0x00}, 0},
+   };
+   if (!gspca_dev-streaming)
+   return;
+
+   switch (sd-model) {
+   case 0x7003:
+   genius_vcam_live_gain_cmds[0].instruction[2] = g;
+   run_start_commands(gspca_dev, genius_vcam_live_gain_cmds,
+  ARRAY_SIZE(genius_vcam_live_gain_cmds));
+   break;
+   default:
+   break;
+   }
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+   struct gspca_dev *gspca_dev =
+   container_of(ctrl-handler, struct gspca_dev, ctrl_handler);
+   struct sd *sd = (struct sd *)gspca_dev;
+
+   gspca_dev-usb_err = 0;
+
+   if (!gspca_dev-streaming)
+   return 0;
+
+   switch (ctrl-id) {
+   /* standalone gain control */
+   case V4L2_CID_GAIN:
+   set_gain(gspca_dev, ctrl-val);
+   break;
+   /* autogain */
+   case V4L2_CID_AUTOGAIN:
+   set_gain(gspca_dev, sd-gain-val);
+   break;
+   }
+   return gspca_dev-usb_err;
+}
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+   .s_ctrl = sd_s_ctrl,
+};
+
+
+static int sd_init_controls(struct gspca_dev *gspca_dev)
+{
+   struct v4l2_ctrl_handler *hdl = gspca_dev-ctrl_handler;
+   struct sd *sd = (struct sd *)gspca_dev;
+
+   gspca_dev-vdev.ctrl_handler = hdl;
+   v4l2_ctrl_handler_init(hdl, 2);
+
+   switch (sd-model) {
+   case 0x7003:
+   sd-gain = v4l2_ctrl_new_std(hdl, sd_ctrl_ops,
+   V4L2_CID_GAIN, 0, 20, 1, 0);
+   sd-autogain = v4l2_ctrl_new_std(hdl, sd_ctrl_ops,
+   V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+   break;
+   default:
+   break;
+   }
+
+   return 0;
+}
 static int start_spy_cam(struct gspca_dev *gspca_dev)
 {
struct init_command spy_start_commands[] = {
@@ -641,6 +722,9 @@ static int start_genius_videocam_live(struct gspca_dev 
*gspca_dev)
if (r  0)
return r;
 
+   if (sd-gain)
+   set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd-gain));
+
return r;
 }
 
@@ -757,6 +841,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
return -ENXIO;
}
 
+   sd-avg_lum = -1;
+
return err_code;
 }
 
@@ -776,6 +862,39 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
PERR(Camera Stop command failed);
 }
 
+static void do_autogain(struct gspca_dev *gspca_dev, int avg_lum)
+{
+   struct sd *sd = (struct sd *) gspca_dev;
+   s32 cur_gain = v4l2_ctrl_g_ctrl(sd-gain);
+
+   if (avg_lum == -1)
+   return;
+
+   if (avg_lum  MIN_AVG_LUM) {
+   if (cur_gain == sd-gain-maximum)
+   return;
+   cur_gain++;
+   v4l2_ctrl_s_ctrl(sd-gain, cur_gain);
+   }
+   if (avg_lum  MAX_AVG_LUM) {
+   if (cur_gain == sd-gain-minimum)
+   return;
+   cur_gain--;
+   v4l2_ctrl_s_ctrl(sd-gain, cur_gain);
+   }
+
+}
+
+static void sd_dqcallback(struct gspca_dev *gspca_dev)
+{
+   struct sd *sd = (struct sd *) gspca_dev;
+
+   if (sd-autogain == NULL || !v4l2_ctrl_g_ctrl(sd-autogain))
+   return;
+
+   do_autogain(gspca_dev, sd-avg_lum);
+}
+
 /* Include sn9c2028 sof detection functions */
 #include sn9c2028.h
 
@@ -810,8 +929,10 @@ static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
.config = sd_config,
.init = sd_init,
+   .init_controls = sd_init_controls,
.start = sd_start,
   

cron job: media_tree daily build: ERRORS

2015-04-19 Thread Hans Verkuil
This message is generated daily by a cron job that builds media_tree for
the kernels and architectures in the list below.

Results of the daily build of media_tree:

date:   Mon Apr 20 04:00:15 CEST 2015
git branch: test
git hash:   e183201b9e917daf2530b637b2f34f1d5afb934d
gcc version:i686-linux-gcc (GCC) 4.9.1
sparse version: v0.5.0-44-g40791b9
smatch version: 0.4.1-3153-g7d56ab3
host hardware:  x86_64
host os:3.19.0-1.slh.1-amd64

linux-git-arm-at91: OK
linux-git-arm-davinci: OK
linux-git-arm-exynos: OK
linux-git-arm-mx: OK
linux-git-arm-omap: OK
linux-git-arm-omap1: OK
linux-git-arm-pxa: OK
linux-git-blackfin: OK
linux-git-i686: WARNINGS
linux-git-m32r: OK
linux-git-mips: WARNINGS
linux-git-powerpc64: OK
linux-git-sh: OK
linux-git-x86_64: OK
linux-2.6.32.27-i686: ERRORS
linux-2.6.33.7-i686: ERRORS
linux-2.6.34.7-i686: ERRORS
linux-2.6.35.9-i686: ERRORS
linux-2.6.36.4-i686: ERRORS
linux-2.6.37.6-i686: ERRORS
linux-2.6.38.8-i686: WARNINGS
linux-2.6.39.4-i686: WARNINGS
linux-3.0.60-i686: OK
linux-3.1.10-i686: OK
linux-3.2.37-i686: OK
linux-3.3.8-i686: OK
linux-3.4.27-i686: OK
linux-3.5.7-i686: OK
linux-3.6.11-i686: OK
linux-3.7.4-i686: OK
linux-3.8-i686: OK
linux-3.9.2-i686: OK
linux-3.10.1-i686: OK
linux-3.11.1-i686: OK
linux-3.12.23-i686: OK
linux-3.13.11-i686: ERRORS
linux-3.14.9-i686: ERRORS
linux-3.15.2-i686: ERRORS
linux-3.16.7-i686: ERRORS
linux-3.17.8-i686: WARNINGS
linux-3.18.7-i686: WARNINGS
linux-3.19-i686: WARNINGS
linux-4.0-rc1-i686: WARNINGS
linux-2.6.32.27-x86_64: ERRORS
linux-2.6.33.7-x86_64: ERRORS
linux-2.6.34.7-x86_64: ERRORS
linux-2.6.35.9-x86_64: ERRORS
linux-2.6.36.4-x86_64: ERRORS
linux-2.6.37.6-x86_64: ERRORS
linux-2.6.38.8-x86_64: WARNINGS
linux-2.6.39.4-x86_64: WARNINGS
linux-3.0.60-x86_64: OK
linux-3.1.10-x86_64: OK
linux-3.2.37-x86_64: OK
linux-3.3.8-x86_64: OK
linux-3.4.27-x86_64: OK
linux-3.5.7-x86_64: OK
linux-3.6.11-x86_64: OK
linux-3.7.4-x86_64: OK
linux-3.8-x86_64: OK
linux-3.9.2-x86_64: OK
linux-3.10.1-x86_64: OK
linux-3.11.1-x86_64: OK
linux-3.12.23-x86_64: OK
linux-3.13.11-x86_64: ERRORS
linux-3.14.9-x86_64: ERRORS
linux-3.15.2-x86_64: ERRORS
linux-3.16.7-x86_64: ERRORS
linux-3.17.8-x86_64: OK
linux-3.18.7-x86_64: OK
linux-3.19-x86_64: OK
linux-4.0-rc1-x86_64: OK
apps: OK
spec-git: OK
sparse: WARNINGS
smatch: ERRORS

Detailed results are available here:

http://www.xs4all.nl/~hverkuil/logs/Monday.log

Full logs are available here:

http://www.xs4all.nl/~hverkuil/logs/Monday.tar.bz2

The Media Infrastructure API from this daily build is here:

http://www.xs4all.nl/~hverkuil/spec/media.html
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] clk: change clk_ops' -round_rate() prototype

2015-04-19 Thread Boris Brezillon
Hi Heiko,

On Sun, 19 Apr 2015 14:13:04 +0200
Heiko Stübner he...@sntech.de wrote:

 Hi Boris,
 
 Am Freitag, 17. April 2015, 09:29:28 schrieb Boris Brezillon:
  Clock rates are stored in an unsigned long field, but -round_rate()
  (which returns a rounded rate from a requested one) returns a long
  value (errors are reported using negative error codes), which can lead
  to long overflow if the clock rate exceed 2Ghz.
  
  Change -round_rate() prototype to return 0 or an error code, and pass the
  requested rate as a pointer so that it can be adjusted depending on
  hardware capabilities.
  
  Signed-off-by: Boris Brezillon boris.brezil...@free-electrons.com
  ---
 
 On a rk3288-veyron-pinky with the fix described below:
 Tested-by: Heiko Stuebner he...@sntech.de
 
 
  diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
  index fa5a00e..1462ddc 100644
  --- a/drivers/clk/clk.c
  +++ b/drivers/clk/clk.c
  @@ -1640,8 +1643,10 @@ static struct clk_core *clk_calc_new_rates(struct
  clk_core *clk, parent_hw);
  parent = parent_hw ? parent_hw-core : NULL;
  } else if (clk-ops-round_rate) {
  -   new_rate = clk-ops-round_rate(clk-hw, rate,
  -   best_parent_rate);
  +   if (clk-ops-round_rate(clk-hw, new_rate,
  +best_parent_rate))
  +   return NULL;
  +
  if (new_rate  min_rate || new_rate  max_rate)
  return NULL;
  } else if (!parent || !(clk-flags  CLK_SET_RATE_PARENT)) {
 
 This is using new_rate uninitialized when calling into the round_rate
 callback. Which in turn pushed my PLLs up to 2.2GHz :-)

Indeed, thanks for the fix.

[...]

 
 
 And as I've stumbled onto this recently too, the clock-maintainership has
 expanded to Stephen Boyd and linux-...@vger.kernel.org .

Noted. I'll add Stephen and the new linux-clk ML in the recipient list
next time.

Best Regards,

Boris


-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html