[PATCH] [media] platform: Fix timberdale dependencies

2014-04-03 Thread Jean Delvare
VIDEO_TIMBERDALE selects TIMB_DMA which itself depends on
MFD_TIMBERDALE, so VIDEO_TIMBERDALE should either select or depend on
MFD_TIMBERDALE as well. I chose to make it depend on it because I
think it makes more sense and it is consistent with what other options
are doing.

Adding a "|| HAS_IOMEM" to the TIMB_DMA dependencies silenced the
kconfig warning about unmet direct dependencies but it was wrong:
without MFD_TIMBERDALE, TIMB_DMA is useless as the driver has no
device to bind to.

Signed-off-by: Jean Delvare 
Cc: Vinod Koul 
Cc: Dan Williams 
Cc: Mauro Carvalho Chehab 
---
 drivers/dma/Kconfig|2 +-
 drivers/media/platform/Kconfig |2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

--- linux-3.14.orig/drivers/dma/Kconfig 2014-04-03 09:21:03.566405827 +0200
+++ linux-3.14/drivers/dma/Kconfig  2014-04-03 09:28:32.618779030 +0200
@@ -197,7 +197,7 @@ config AMCC_PPC440SPE_ADMA
 
 config TIMB_DMA
tristate "Timberdale FPGA DMA support"
-   depends on MFD_TIMBERDALE || HAS_IOMEM
+   depends on MFD_TIMBERDALE
select DMA_ENGINE
help
  Enable support for the Timberdale FPGA DMA engine.
--- linux-3.14.orig/drivers/media/platform/Kconfig  2014-04-03 
09:21:03.566405827 +0200
+++ linux-3.14/drivers/media/platform/Kconfig   2014-04-03 09:28:32.618779030 
+0200
@@ -56,7 +56,7 @@ config VIDEO_VIU
 
 config VIDEO_TIMBERDALE
tristate "Support for timberdale Video In/LogiWIN"
-   depends on VIDEO_V4L2 && I2C && DMADEVICES
+   depends on MFD_TIMBERDALE && VIDEO_V4L2 && I2C && DMADEVICES
select DMA_ENGINE
select TIMB_DMA
select VIDEO_ADV7180


-- 
Jean Delvare
SUSE L3 Support
--
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 v2 4/6] v4l: vsp1: Add DT support

2014-04-03 Thread Sylwester Nawrocki
Hi Laurent,

On 03/04/14 01:16, Laurent Pinchart wrote:
>>> @@ -534,6 +569,7 @@ static struct platform_driver vsp1_platform_driver = {
>>> > > .owner  = THIS_MODULE,
>>> > > .name   = "vsp1",
>>> > > .pm = &vsp1_pm_ops,
>>> > > +   .of_match_table = of_match_ptr(vsp1_of_match),
>> > 
>> > Is of_match_ptr() really useful here, when vsp1_of_match[] array is always
>> > compiled in ?
>
> Would it be better to compile the vsp1_of_match[] array conditionally ? On 
> the 
> other hand the driver is only useful (at least at the moment) on ARM Renesas 
> SoCs, which are transitioning to DT anyway.

Given that #ifdefs could be soon removed anyway (when the platform becomes
dt-only) I guess it's better not to introduce it now.

-- 
Regards,
Sylwester
--
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: [ANNOUNCE] git web interface was changed to cgit

2014-04-03 Thread Enrico
On Thu, Apr 3, 2014 at 12:26 AM, Mauro Carvalho Chehab
 wrote:
> Hi all,
>
> I changed today our git web interface from gitweb to cgit, due to seveal
> reasons:
> ...
> Please ping me if you fin any problems on it.

http://git.linuxtv.org/cgit.cgi/media_build.git/tree/README

the first time i opened that link i got an internal server error, then
it shows an "empty" file (many lines, all empty).

It seems to happen for every file, even in other repos:

http://git.linuxtv.org/cgit.cgi/linux.git/tree/README

Enrico
--
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: [ANNOUNCE] git web interface was changed to cgit

2014-04-03 Thread Mauro Carvalho Chehab
Em Thu, 03 Apr 2014 14:16:51 +0200
Enrico  escreveu:

> On Thu, Apr 3, 2014 at 12:26 AM, Mauro Carvalho Chehab
>  wrote:
> > Hi all,
> >
> > I changed today our git web interface from gitweb to cgit, due to seveal
> > reasons:
> > ...
> > Please ping me if you fin any problems on it.
> 
> http://git.linuxtv.org/cgit.cgi/media_build.git/tree/README
> 
> the first time i opened that link i got an internal server error, then
> it shows an "empty" file (many lines, all empty).
> 
> It seems to happen for every file, even in other repos:
> 
> http://git.linuxtv.org/cgit.cgi/linux.git/tree/README

Fixed. A highlight filter was missing.

Regards,
Mauro
--
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: http:// and git:// repositories not in sync

2014-04-03 Thread Mauro Carvalho Chehab
Hi Yann,

Em Sat, 29 Mar 2014 23:52:37 +0100
"Yann E. MORIN"  escreveu:

> Hello!
> 
> While looking at the dtv-scan-tables repository, we noticed that we did
> get a different set of commits with the http:// or the git:// schemes to
> access the repository:
> 
> $ git clone git://linuxtv.org/dtv-scan-tables.git dtv.git
> [...]
> $ cd dtv.git
> $ git log --oneline |head
> cfc2975 Updated scan table for au-Sydney_North_Shore
> 29b0b57 UK Update for COM 7, BBC B, and Local Muxes
> 177b522 DTV scantables for FI
> 7809ca1 Update es-Alfabia
> 69a1ac5 Initial tuning data for ca-AB-Calgary
> 1850cf8 Initial scan table for au-Melbourne-Selby
> 52a7b0a update scan file for ro-DigiTV
> 75f3b39 Initial Tuning Data for Uganda
> 7d31336 Never include ~ files
> 1d6f9b5 Initial scan files for PT
> 
> $ git clone http://linuxtv.org/git/dtv-scan-tables.git dtv.http
> [...]
> $ cd dtv.http
> $ git log --oneline |head
> 7809ca1 Update es-Alfabia
> 69a1ac5 Initial tuning data for ca-AB-Calgary
> 1850cf8 Initial scan table for au-Melbourne-Selby
> 52a7b0a update scan file for ro-DigiTV
> 75f3b39 Initial Tuning Data for Uganda
> 7d31336 Never include ~ files
> 1d6f9b5 Initial scan files for PT
> f61d5ec Merge pull request #6 from silid/master
> 6213a2f Table /usr/share/dvb/dvb-t/cz-All outdated
> 832df4f Removal of excess white space
> 
> As you can see, the http:// scheme gets us three fewer changesets than
> the git:// scheme.

We changed from gitweb to cgit. One of the advantages of cgit is that
it accepts cloning via html, and I think it doesn't require to call
git update-server-info for it to work.

So, I'm hoping that this change will fix this issue once for all.

The URL for http changed, due to that. The old URL will still be supported
for a while, in order to avoid breaking for the ones that were using the
legacy URL, but, as pointed, it depends on having a recent
git update-server-info for it to work properly.

Regards,
Mauro

-- 

Regards,
Mauro
--
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: brightness units

2014-04-03 Thread Jacek Anaszewski

Hi Bryan, Milo and Sakari,

Thanks for the replies.

On 04/02/2014 05:17 PM, Sakari Ailus wrote:

Hi Bryan,

On Tue, Apr 01, 2014 at 03:09:55PM -0700, Bryan Wu wrote:

On Tue, Apr 1, 2014 at 12:21 AM, Jacek Anaszewski
 wrote:

I am currently integrating LED subsystem and V4L2 Flash API.
V4L2 Flash API defines units of torch and flash intensity
in milliampers. In the LED subsystem documentation I can't
find any reference to the brightness units. On the other
hand there is led_brightness enum defined in the 
header, with LED_FULL = 255, but not all leds drivers use it.
I am aware that there are LEDs that can be only turned on/off
without any possibility to set the current and in such cases
LED_FULL doesn't reflect the current set.



Actually led_brightness is an logic concept not like milliampers,
since different led drivers has different implementation which is
hardware related. Like PWM led driver, it will be converted to duty
cycles.

For current control I do see some specific driver like LP55xx have it
but not for every one.


So far I've assumed that brightness is expressed in milliampers
and I don't stick to the LED_FULL limit. It allows for passing
flash/torch intensity from V4L2 controls to the leds API
without conversion. I am not sure if the units should be
fixed to milliampers in the LED subsystem or not. It would
clarify the situation, but if the existing LED drivers don't
stick to this unit then it would make a confusion.



We probably need to convert those intensity to brightness numbers, for
example mapping the intensity value to 0 ~ 255 brightness level and
pass it to LED subsystem.


I think for some devices it wouldn't matter much, but on those that
generally are used as flash the current is known, and thus it should also be
visible in the interface. The conversion from mA to native units could be
done directly, or indirectly through the LED API.

There are a few things to consider though: besides minimum and maximum
values for the current, the V4L2 controls have a step parameter that would
still need to be passed to the control handler when creating the control.
That essentially tells the user space how many levels does the control have.

Care must be taken if converting to LED API units in between mA and native
units so that the values will get through unchanged. On the other hand, I
don't expect to get more levels than 256 either. But even this assumes that
the current selection would be linear.



After analyzing the problem I decided to implement it this way:

1. V4L2 Flash control will use existing LED API for setting/getting
   torch brightness
- V4L2 Flash control handler will take care of
  mA <-> enum led_brightness conversion
2. New API for flash leds will use mA with int primitive
   as its type
- min, max and step parameters will not be used on the
  LED subsystem level to keep it as simple as possible -
  instead each flash driver will align the brightness
  according to the device constraints; the adjusted value
  will be made available for the LED subsystem after calling
  led_update_flash_brightness function
- min, max and step parameters will be passed to the
  v4l2-flash in the v4l2_flash_ctrl_config structure -
  it was introduced in my RFC.
3. New API for indicator LEDs will be introduced in the led_flash
   module - it will define its units as uA with int primitive
   as the type

If you have any comments please let me know.

Thanks,
Jacek Anaszewski
--
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


How to flush v4l2 drive

2014-04-03 Thread m silverstri
I read this mail posting about flush operation.

https://www.mail-archive.com/linux-media@vger.kernel.org/msg41867.html

My user side application talks to v4l2 driver like this, as an
example, I put qbuf/dqbuf loop 10 times:

open
stream on

for (int i = 0; i < 10; i++)
qbuf
dqbuf
// process the buffer

stream off
close

>From the message, it said  "close/streamoff() does an implicit immediate stop.
"

But how can I 'flush the stream before my last dqbuf() buffer (i.e.
when i is 9)? When close/streamoff() does an implict stop/flush, I
have already dequf my last buffer, so my application won't see the
'flushed' content.

How can I fix this?

Thank you.
--
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


[GIT PULL for v3.15-rc1] media updates

2014-04-03 Thread Mauro Carvalho Chehab
Hi Linus,

Please pull from:
  git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media 
v4l_for_linus

For the main set of series of patches for media subsystem, including:
- Document RC sysfs class;
- Added an API to setup scancode to allow waking up systems using
  the Remote Controller;
- Add API for SDR devices. Drivers are still on staging;
- Some API improvements for getting EDID data from media
  inputs/outputs;
- New DVB frontend driver for drx-j (ATSC);
- One driver (it913x/it9137) got removed, in favor of an improvement
  on another driver (af9035);
- Added a skeleton V4L2 PCI driver at documentation;
- Added a dual flash driver (lm3646);
- Added a new IR driver (img-ir);
- Added an IR scancode decoder for the Sharp protocol;
- Some improvements at the usbtv driver, to allow its core to be
  reused.
- Added a new SDR driver (rtl2832u_sdr);
- Added a new tuner driver (msi001);
- Several improvements at em28xx driver to fix PM support,
  device removal and to split the V4L2 specific bits into a
  separate sub-driver.
- One driver got converted to videobuf2 (s2255drv);
- The e4000 tuner driver now follows an improved binding model;
- Some fixes at V4L2 compat32 code;
- Several fixes and enhancements at videobuf2 code;
- Some cleanups at V4L2 API documentation;
- usual driver enhancements, new board additions and misc fixups.

Thanks!
Mauro

-

PS.: You'll find some minor conflicts between this changeset and upstream,
mainly due to some code that moved from V4L2 to OF subsystem.

I have a separate topic branch with the exynos5 changes that is
more affected by this. I'll send on a separate pull request, after
this one gets merged.


The following changes since commit 0414855fdc4a40da05221fc6062cccbc0c30f169:

  Linux 3.14-rc5 (2014-03-02 18:56:16 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media 
v4l_for_linus

for you to fetch changes up to a83b93a7480441a47856dc9104bea970e84cda87:

  [media] em28xx-dvb: fix PCTV 461e tuner I2C binding (2014-03-31 08:02:16 
-0300)


Alexander Shiyan (1):
  [media] stb6100: fix buffer length check in stb6100_write_reg_range()

Alexey Khoroshilov (1):
  [media] adv7180: free an interrupt on failure paths in init_device()

Amit Grover (2):
  [media] v4l2: Add settings for Horizontal and Vertical MV Search Range
  [media] s5p-mfc: Add Horizontal and Vertical MV Search Range

Andy Shevchenko (3):
  [media] lm3560: remove FSF address from the license
  [media] lm3560: keep style for the comments
  [media] lm3560: prevent memory leak in case of pdata absence

Antonio Ospite (2):
  [media] gspca_kinect: fix kinect_read() error path
  [media] gspca_kinect: fix messages about kinect_read() return value

Antti Palosaari (75):
  [media] af9035: add ID [2040:f900] Hauppauge WinTV-MiniStick 2
  [media] em28xx-dvb: fix PCTV 461e tuner I2C binding
  [media] tda10071: do not check tuner PLL lock on read_status()
  [media] tda10071: coding style issues
  [media] af9035: use default i2c slave address for af9035 too
  [media] devices.txt: add video4linux device for Software Defined Radio
  [media] v4l: add device type for Software Defined Radio
  [media] v4l: add new tuner types for SDR
  [media] v4l: 1 Hz resolution flag for tuners
  [media] v4l: add stream format for SDR receiver
  [media] v4l: define own IOCTL ops for SDR FMT
  [media] v4l: enable some IOCTLs for SDR receiver
  [media] v4l: add device capability flag for SDR receiver
  [media] DocBook: document 1 Hz flag
  [media] DocBook: Software Defined Radio Interface
  [media] DocBook: mark SDR API as Experimental
  [media] v4l2-framework.txt: add SDR device type
  [media] xc2028: silence compiler warnings
  [media] rtl28xxu: add module parameter to disable IR
  [media] rtl2832: remove unused if_dvbt config parameter
  [media] rtl2832: style changes and minor cleanup
  [media] rtl2832: provide muxed I2C adapter
  [media] rtl2832: add muxed I2C adapter for demod itself
  [media] rtl2832: implement delayed I2C gate close
  [media] DocBook: media: document V4L2_CTRL_CLASS_RF_TUNER
  [media] DocBook: document RF tuner gain controls
  [media] v4l: add RF tuner gain controls
  [media] m88ds3103: remove dead code
  [media] m88ds3103: remove dead code 2nd part
  [media] m88ds3103: possible uninitialized scalar variable
  [media] DocBook: document RF tuner bandwidth controls
  [media] v4l: define unit for V4L2_CID_RF_TUNER_BANDWIDTH
  [media] v4l: add RF tuner channel bandwidth control
  [media] v4l: reorganize RF tuner contro

AW: v4l2_buffer with PBO mapped memory

2014-04-03 Thread Scheuermann, Mail
Hi Laurent,

the driver my device uses is the uvcvideo. I have the kernel 3.11.0-18 from 
Ubuntu 13.10 running.
It is built in in a Thinkpad X240 notebook.

Regards,

Thomas


Von: Laurent Pinchart [laurent.pinch...@ideasonboard.com]
Gesendet: Mittwoch, 2. April 2014 21:23
An: Scheuermann, Mail
Cc: linux-media@vger.kernel.org
Betreff: Re: v4l2_buffer with PBO mapped memory

Hi Thomas,

On Wednesday 02 April 2014 17:10:42 Thomas Scheuermann wrote:
> Hello,
>
> I've written a program which shows my webcam with the v4l2 interface.
> In the v4l2_buffer I use the type V4L2_BUF_TYPE_VIDEO_CAPTURE and the
> memory is V4L2_MEMORY_USERPTR.
> Everything works if I use malloced memory for frame buffers.
> Now I want to get the frames directly in OpenGL. I've mapped a pixel
> buffer object with glMapBuffer and wanted to use this as a frame buffer.
> But if I use this memory, the ioctl VIDIOC_QBUF fails with 'invalid
> argument'.
>
> What can I do to use the pixel buffer object together with the v4l2
> interface?
> I want to use as less copy steps as possible.

The use case is reasonable (although V4L2_MEMORY_DMABUF would be better, but
we're not there yet on the OpenGL side I believe), so let's try to debug this.
First of all, what webcam driver do you use ?

--
Regards,

Laurent Pinchart

This message is subject to the following terms and conditions: MAIL 
DISCLAIMER
--
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: sparse: ioctl defines and "error: bad integer constant expression"

2014-04-03 Thread Christopher Li
On Tue, Apr 1, 2014 at 10:06 AM, Hans Verkuil  wrote:
>
> For all my test cases:
>
> Signed-off-by: Hans Verkuil 
>

All 3 test cases added.

Chris
--
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: sparse and anonymous unions

2014-04-03 Thread Christopher Li
On Mon, Mar 31, 2014 at 10:17 AM, Linus Torvalds
 wrote:
> Chris, mind applying this one too? It removes more lines than it adds
> while fixing things, by removing the helper function that isn't good
> at anoymous unions, and using another one that does this all right..

The patch is applied. I add the signed off for you too, hope you don't mind.

Chris
--
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: [GIT PULL for v3.15-rc1] media updates

2014-04-03 Thread David Härdeman
On Thu, Apr 03, 2014 at 01:11:43PM -0300, Mauro Carvalho Chehab wrote:
>Hi Linus,
>
>Please pull from:
>  git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media 
> v4l_for_linus
>
...
>James Hogan (27):
...
>  [media] media: rc: add sysfs scancode filtering interface
>  [media] media: rc: change 32bit NEC scancode format
...
>  [media] rc-main: add generic scancode filtering

Umm...we (mostly James and I, but you as well) have been discussing on
the linux-media whether those patches shouldn't be reverted...this pull
request seems to have overlooked that discussion...or have I missed
something?

-- 
David Härdeman
--
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: [GIT PULL for v3.15-rc1] media updates

2014-04-03 Thread Mauro Carvalho Chehab
Em Thu, 03 Apr 2014 23:46:56 +0200
David Härdeman  escreveu:

> On Thu, Apr 03, 2014 at 01:11:43PM -0300, Mauro Carvalho Chehab wrote:
> >Hi Linus,
> >
> >Please pull from:
> >  git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media 
> > v4l_for_linus
> >
> ...
> >James Hogan (27):
> ...
> >  [media] media: rc: add sysfs scancode filtering interface
> >  [media] media: rc: change 32bit NEC scancode format
> ...
> >  [media] rc-main: add generic scancode filtering
> 
> Umm...we (mostly James and I, but you as well) have been discussing on
> the linux-media whether those patches shouldn't be reverted...this pull
> request seems to have overlooked that discussion...or have I missed
> something?

The discussions didn't finish yet. We can't hold pushing the patches
forever due to a few patches in this series, and there's another pull
request waiting for this to be merged.

We can latter send a fix for the patches that are not ok early at
-rc tests, or next week if we come on an agreement.

Regards,
Mauro
--
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 00/25] OMAP3 ISP: Move to videobuf2

2014-04-03 Thread Laurent Pinchart
Hello,

I think the subject line should be enough to get everybody excited about this
patch series (everybody being Sakari, me, and possibly one or two other
developers). The idea is pretty clear, I've tried to keep patches small and
reviewable (24/25 is a bit too big for my taste, but splitting it further
would be pretty difficult), so please look at them for details.

The patches are based on top of the latest media master branch. They also
depend at runtime on an OMAP IOMMU cleanup series. I've asked Joerg Roedel to
provide a stable branch based on v3.15-rc1 (when it will be available).

Laurent Pinchart (25):
  omap3isp: stat: Rename IS_COHERENT_BUF to ISP_STAT_USES_DMAENGINE
  omap3isp: stat: Remove impossible WARN_ON
  omap3isp: stat: Share common code for buffer allocation
  omap3isp: stat: Merge dma_addr and iommu_addr fields
  omap3isp: stat: Store sg table in ispstat_buffer
  omap3isp: stat: Use the DMA API
  omap3isp: ccdc: Use the DMA API for LSC
  omap3isp: ccdc: Use the DMA API for FPC
  omap3isp: video: Set the buffer bytesused field at completion time
  omap3isp: queue: Move IOMMU handling code to the queue
  omap3isp: queue: Use sg_table structure
  omap3isp: queue: Merge the prepare and sglist functions
  omap3isp: queue: Inline the ispmmu_v(un)map functions
  omap3isp: queue: Allocate kernel buffers with dma_alloc_coherent
  omap3isp: queue: Fix the dma_map_sg() return value check
  omap3isp: queue: Map PFNMAP buffers to device
  omap3isp: queue: Use sg_alloc_table_from_pages()
  omap3isp: Use the ARM DMA IOMMU-aware operations
  omap3isp: queue: Don't build scatterlist for kernel buffer
  omap3isp: Move queue mutex to isp_video structure
  omap3isp: Move queue irqlock to isp_video structure
  omap3isp: Move buffer irqlist to isp_buffer structure
  v4l: vb2: Add a function to discard all DONE buffers
  omap3isp: Move to videobuf2
  omap3isp: Rename isp_buffer isp_addr field to dma

 drivers/media/platform/Kconfig|4 +-
 drivers/media/platform/omap3isp/Makefile  |2 +-
 drivers/media/platform/omap3isp/isp.c |  108 ++-
 drivers/media/platform/omap3isp/isp.h |8 +-
 drivers/media/platform/omap3isp/ispccdc.c |  107 ++-
 drivers/media/platform/omap3isp/ispccdc.h |   16 +-
 drivers/media/platform/omap3isp/ispccp2.c |4 +-
 drivers/media/platform/omap3isp/ispcsi2.c |4 +-
 drivers/media/platform/omap3isp/isph3a_aewb.c |2 +-
 drivers/media/platform/omap3isp/isph3a_af.c   |2 +-
 drivers/media/platform/omap3isp/isppreview.c  |8 +-
 drivers/media/platform/omap3isp/ispqueue.c| 1161 -
 drivers/media/platform/omap3isp/ispqueue.h|  188 
 drivers/media/platform/omap3isp/ispresizer.c  |8 +-
 drivers/media/platform/omap3isp/ispstat.c |  197 ++---
 drivers/media/platform/omap3isp/ispstat.h |3 +-
 drivers/media/platform/omap3isp/ispvideo.c|  323 +++
 drivers/media/platform/omap3isp/ispvideo.h|   29 +-
 drivers/media/v4l2-core/videobuf2-core.c  |   24 +
 drivers/staging/media/omap4iss/iss_video.c|2 +-
 include/media/videobuf2-core.h|1 +
 21 files changed, 456 insertions(+), 1745 deletions(-)
 delete mode 100644 drivers/media/platform/omap3isp/ispqueue.c
 delete mode 100644 drivers/media/platform/omap3isp/ispqueue.h

-- 
Regards,

Laurent Pinchart

--
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 12/25] omap3isp: queue: Merge the prepare and sglist functions

2014-04-03 Thread Laurent Pinchart
In preparation for the switch to the DMA API merge the two functions
that handle buffer preparation for the USERPTR cases (both page-backed
and non page-backed memory).

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.c | 169 -
 drivers/media/platform/omap3isp/ispqueue.h |   4 -
 2 files changed, 69 insertions(+), 104 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index 51ec40d..a7be7d7 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -178,12 +178,12 @@ out:
 }
 
 /*
- * isp_video_buffer_sglist_kernel - Build a scatter list for a vmalloc'ed 
buffer
+ * isp_video_buffer_prepare_kernel - Build scatter list for a vmalloc'ed buffer
  *
  * Iterate over the vmalloc'ed area and create a scatter list entry for every
  * page.
  */
-static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
+static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf)
 {
struct scatterlist *sg;
unsigned int npages;
@@ -214,67 +214,6 @@ static int isp_video_buffer_sglist_kernel(struct 
isp_video_buffer *buf)
 }
 
 /*
- * isp_video_buffer_sglist_user - Build a scatter list for a userspace buffer
- *
- * Walk the buffer pages list and create a 1:1 mapping to a scatter list.
- */
-static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf)
-{
-   unsigned int offset = buf->offset;
-   struct scatterlist *sg;
-   unsigned int i;
-   int ret;
-
-   ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
-   if (ret < 0)
-   return ret;
-
-   for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i) {
-   if (PageHighMem(buf->pages[i])) {
-   sg_free_table(&buf->sgt);
-   return -EINVAL;
-   }
-
-   sg_set_page(sg, buf->pages[i], PAGE_SIZE - offset, offset);
-   sg = sg_next(sg);
-   offset = 0;
-   }
-
-   return 0;
-}
-
-/*
- * isp_video_buffer_sglist_pfnmap - Build a scatter list for a VM_PFNMAP buffer
- *
- * Create a scatter list of physically contiguous pages starting at the buffer
- * memory physical address.
- */
-static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf)
-{
-   struct scatterlist *sg;
-   unsigned int offset = buf->offset;
-   unsigned long pfn = buf->paddr >> PAGE_SHIFT;
-   unsigned int i;
-   int ret;
-
-   ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
-   if (ret < 0)
-   return ret;
-
-   for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i, ++pfn) {
-   sg_set_page(sg, pfn_to_page(pfn), PAGE_SIZE - offset, offset);
-   /* PFNMAP buffers will not get DMA-mapped, set the DMA address
-* manually.
-*/
-   sg_dma_address(sg) = (pfn << PAGE_SHIFT) + offset;
-   sg = sg_next(sg);
-   offset = 0;
-   }
-
-   return 0;
-}
-
-/*
  * isp_video_buffer_cleanup - Release pages for a userspace VMA.
  *
  * Release pages locked by a call isp_video_buffer_prepare_user and free the
@@ -316,11 +255,11 @@ static void isp_video_buffer_cleanup(struct 
isp_video_buffer *buf)
 }
 
 /*
- * isp_video_buffer_prepare_user - Pin userspace VMA pages to memory.
+ * isp_video_buffer_prepare_user - Prepare a userspace buffer.
  *
- * This function creates a list of pages for a userspace VMA. The number of
- * pages is first computed based on the buffer size, and pages are then
- * retrieved by a call to get_user_pages.
+ * This function creates a scatter list with a 1:1 mapping for a userspace VMA.
+ * The number of pages is first computed based on the buffer size, and pages 
are
+ * then retrieved by a call to get_user_pages.
  *
  * Pages are pinned to memory by get_user_pages, making them available for DMA
  * transfers. However, due to memory management optimization, it seems the
@@ -340,16 +279,19 @@ static void isp_video_buffer_cleanup(struct 
isp_video_buffer *buf)
  */
 static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
 {
+   struct scatterlist *sg;
+   unsigned int offset;
unsigned long data;
unsigned int first;
unsigned int last;
+   unsigned int i;
int ret;
 
data = buf->vbuf.m.userptr;
first = (data & PAGE_MASK) >> PAGE_SHIFT;
last = ((data + buf->vbuf.length - 1) & PAGE_MASK) >> PAGE_SHIFT;
+   offset = data & ~PAGE_MASK;
 
-   buf->offset = data & ~PAGE_MASK;
buf->npages = last - first + 1;
buf->pages = vmalloc(buf->npages * sizeof(buf->pages[0]));
if (buf->pages == NULL)
@@ -364,68 +306,104 @@ static int isp_video_buffer_prepare_user(struct 
isp_video_buffer *buf)
 
if (ret != buf->npages) {
buf->npages = ret < 0 ? 0 : ret;
-   i

[PATCH 05/25] omap3isp: stat: Store sg table in ispstat_buffer

2014-04-03 Thread Laurent Pinchart
The driver stores the IOMMU mapped iovm struct pointer in the buffer
structure but only needs the iovm sg table. Store the sg table instead
to prepare the migration to the DMA API.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispstat.c | 19 +--
 drivers/media/platform/omap3isp/ispstat.h |  2 +-
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispstat.c 
b/drivers/media/platform/omap3isp/ispstat.c
index dba713f..4cf7eb1 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -183,8 +183,8 @@ static void isp_stat_buf_sync_for_device(struct ispstat 
*stat,
if (ISP_STAT_USES_DMAENGINE(stat))
return;
 
-   dma_sync_sg_for_device(stat->isp->dev, buf->iovm->sgt->sgl,
-  buf->iovm->sgt->nents, DMA_FROM_DEVICE);
+   dma_sync_sg_for_device(stat->isp->dev, buf->sgt->sgl,
+  buf->sgt->nents, DMA_FROM_DEVICE);
 }
 
 static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
@@ -193,8 +193,8 @@ static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
if (ISP_STAT_USES_DMAENGINE(stat))
return;
 
-   dma_sync_sg_for_cpu(stat->isp->dev, buf->iovm->sgt->sgl,
-   buf->iovm->sgt->nents, DMA_FROM_DEVICE);
+   dma_sync_sg_for_cpu(stat->isp->dev, buf->sgt->sgl,
+   buf->sgt->nents, DMA_FROM_DEVICE);
 }
 
 static void isp_stat_buf_clear(struct ispstat *stat)
@@ -363,10 +363,9 @@ static void isp_stat_bufs_free(struct ispstat *stat)
if (!ISP_STAT_USES_DMAENGINE(stat)) {
if (IS_ERR_OR_NULL((void *)buf->dma_addr))
continue;
-   if (buf->iovm)
-   dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
-buf->iovm->sgt->nents,
-DMA_FROM_DEVICE);
+   if (buf->sgt)
+   dma_unmap_sg(isp->dev, buf->sgt->sgl,
+buf->sgt->nents, DMA_FROM_DEVICE);
omap_iommu_vfree(isp->domain, isp->dev, buf->dma_addr);
} else {
if (!buf->virt_addr)
@@ -374,7 +373,7 @@ static void isp_stat_bufs_free(struct ispstat *stat)
dma_free_coherent(stat->isp->dev, stat->buf_alloc_size,
  buf->virt_addr, buf->dma_addr);
}
-   buf->iovm = NULL;
+   buf->sgt = NULL;
buf->dma_addr = 0;
buf->virt_addr = NULL;
buf->empty = 1;
@@ -407,7 +406,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat,
DMA_FROM_DEVICE))
return -ENOMEM;
 
-   buf->iovm = iovm;
+   buf->sgt = iovm->sgt;
buf->virt_addr = omap_da_to_va(stat->isp->dev, buf->dma_addr);
 
return 0;
diff --git a/drivers/media/platform/omap3isp/ispstat.h 
b/drivers/media/platform/omap3isp/ispstat.h
index 8e76846..857f45e 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -46,7 +46,7 @@
 struct ispstat;
 
 struct ispstat_buffer {
-   struct iovm_struct *iovm;
+   const struct sg_table *sgt;
void *virt_addr;
dma_addr_t dma_addr;
struct timespec ts;
-- 
1.8.3.2

--
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 14/25] omap3isp: queue: Allocate kernel buffers with dma_alloc_coherent

2014-04-03 Thread Laurent Pinchart
And retrieve the related sg table using dma_get_sgtable().

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.c | 57 +-
 drivers/media/platform/omap3isp/ispqueue.h |  2 ++
 2 files changed, 27 insertions(+), 32 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index 088710b..2fd254f 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -148,39 +148,18 @@ out:
 }
 
 /*
- * isp_video_buffer_prepare_kernel - Build scatter list for a vmalloc'ed buffer
+ * isp_video_buffer_prepare_kernel - Build scatter list for a kernel-allocated
+ * buffer
  *
- * Iterate over the vmalloc'ed area and create a scatter list entry for every
- * page.
+ * Retrieve the sgtable using the DMA API.
  */
 static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf)
 {
-   struct scatterlist *sg;
-   unsigned int npages;
-   unsigned int i;
-   void *addr;
-   int ret;
-
-   addr = buf->vaddr;
-   npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT;
-
-   ret = sg_alloc_table(&buf->sgt, npages, GFP_KERNEL);
-   if (ret < 0)
-   return ret;
-
-   for (sg = buf->sgt.sgl, i = 0; i < npages; ++i, addr += PAGE_SIZE) {
-   struct page *page = vmalloc_to_page(addr);
-
-   if (page == NULL || PageHighMem(page)) {
-   sg_free_table(&buf->sgt);
-   return -EINVAL;
-   }
-
-   sg_set_page(sg, page, PAGE_SIZE, 0);
-   sg = sg_next(sg);
-   }
+   struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+   struct isp_video *video = vfh->video;
 
-   return 0;
+   return dma_get_sgtable(video->isp->dev, &buf->sgt, buf->vaddr,
+  buf->paddr, PAGE_ALIGN(buf->vbuf.length));
 }
 
 /*
@@ -601,8 +580,12 @@ static int isp_video_queue_free(struct isp_video_queue 
*queue)
 
isp_video_buffer_cleanup(buf);
 
-   vfree(buf->vaddr);
-   buf->vaddr = NULL;
+   if (buf->vaddr) {
+   dma_free_coherent(queue->dev,
+ PAGE_ALIGN(buf->vbuf.length),
+ buf->vaddr, buf->paddr);
+   buf->vaddr = NULL;
+   }
 
kfree(buf);
queue->buffers[i] = NULL;
@@ -623,6 +606,7 @@ static int isp_video_queue_alloc(struct isp_video_queue 
*queue,
 unsigned int size, enum v4l2_memory memory)
 {
struct isp_video_buffer *buf;
+   dma_addr_t dma;
unsigned int i;
void *mem;
int ret;
@@ -646,7 +630,8 @@ static int isp_video_queue_alloc(struct isp_video_queue 
*queue,
/* Allocate video buffers memory for mmap mode. Align
 * the size to the page size.
 */
-   mem = vmalloc_32_user(PAGE_ALIGN(size));
+   mem = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size),
+&dma, GFP_KERNEL);
if (mem == NULL) {
kfree(buf);
break;
@@ -654,6 +639,7 @@ static int isp_video_queue_alloc(struct isp_video_queue 
*queue,
 
buf->vbuf.m.offset = i * PAGE_ALIGN(size);
buf->vaddr = mem;
+   buf->paddr = dma;
}
 
buf->vbuf.index = i;
@@ -1094,10 +1080,17 @@ int omap3isp_video_queue_mmap(struct isp_video_queue 
*queue,
goto done;
}
 
-   ret = remap_vmalloc_range(vma, buf->vaddr, 0);
+   /* dma_mmap_coherent() uses vm_pgoff as an offset inside the buffer
+* while we used it to identify the buffer and want to map the whole
+* buffer.
+*/
+   vma->vm_pgoff = 0;
+
+   ret = dma_mmap_coherent(queue->dev, vma, buf->vaddr, buf->paddr, size);
if (ret < 0)
goto done;
 
+   vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_ops = &isp_video_queue_vm_ops;
vma->vm_private_data = buf;
isp_video_queue_vm_open(vma);
diff --git a/drivers/media/platform/omap3isp/ispqueue.h 
b/drivers/media/platform/omap3isp/ispqueue.h
index f78325d..e03af74 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -68,6 +68,7 @@ enum isp_video_buffer_state {
  * @prepared: Whether the buffer has been prepared
  * @skip_cache: Whether to skip cache management operations for this buffer
  * @vaddr: Memory virtual address (for kernel buffers)
+ * @paddr: Memory physicall address (for kernel buffers)
  * @vm_flags: Buffer VMA flags (for userspace buffers)
  * @npages: Number of pag

[PATCH 25/25] omap3isp: Rename isp_buffer isp_addr field to dma

2014-04-03 Thread Laurent Pinchart
Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispccdc.c| 4 ++--
 drivers/media/platform/omap3isp/ispccp2.c| 4 ++--
 drivers/media/platform/omap3isp/ispcsi2.c| 4 ++--
 drivers/media/platform/omap3isp/isppreview.c | 8 
 drivers/media/platform/omap3isp/ispresizer.c | 8 
 drivers/media/platform/omap3isp/ispvideo.c   | 2 +-
 drivers/media/platform/omap3isp/ispvideo.h   | 4 ++--
 7 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispccdc.c 
b/drivers/media/platform/omap3isp/ispccdc.c
index 004a4f5..9f727d2 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -1521,7 +1521,7 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
 
buffer = omap3isp_video_buffer_next(&ccdc->video_out);
if (buffer != NULL) {
-   ccdc_set_outaddr(ccdc, buffer->isp_addr);
+   ccdc_set_outaddr(ccdc, buffer->dma);
restart = 1;
}
 
@@ -1660,7 +1660,7 @@ static int ccdc_video_queue(struct isp_video *video, 
struct isp_buffer *buffer)
if (!(ccdc->output & CCDC_OUTPUT_MEMORY))
return -ENODEV;
 
-   ccdc_set_outaddr(ccdc, buffer->isp_addr);
+   ccdc_set_outaddr(ccdc, buffer->dma);
 
/* We now have a buffer queued on the output, restart the pipeline
 * on the next CCDC interrupt if running in continuous mode (or when
diff --git a/drivers/media/platform/omap3isp/ispccp2.c 
b/drivers/media/platform/omap3isp/ispccp2.c
index b30b67d..f3801db 100644
--- a/drivers/media/platform/omap3isp/ispccp2.c
+++ b/drivers/media/platform/omap3isp/ispccp2.c
@@ -549,7 +549,7 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
 
buffer = omap3isp_video_buffer_next(&ccp2->video_in);
if (buffer != NULL)
-   ccp2_set_inaddr(ccp2, buffer->isp_addr);
+   ccp2_set_inaddr(ccp2, buffer->dma);
 
pipe->state |= ISP_PIPELINE_IDLE_INPUT;
 
@@ -940,7 +940,7 @@ static int ccp2_video_queue(struct isp_video *video, struct 
isp_buffer *buffer)
 {
struct isp_ccp2_device *ccp2 = &video->isp->isp_ccp2;
 
-   ccp2_set_inaddr(ccp2, buffer->isp_addr);
+   ccp2_set_inaddr(ccp2, buffer->dma);
return 0;
 }
 
diff --git a/drivers/media/platform/omap3isp/ispcsi2.c 
b/drivers/media/platform/omap3isp/ispcsi2.c
index 6205608..5a2e47e 100644
--- a/drivers/media/platform/omap3isp/ispcsi2.c
+++ b/drivers/media/platform/omap3isp/ispcsi2.c
@@ -695,7 +695,7 @@ static void csi2_isr_buffer(struct isp_csi2_device *csi2)
if (buffer == NULL)
return;
 
-   csi2_set_outaddr(csi2, buffer->isp_addr);
+   csi2_set_outaddr(csi2, buffer->dma);
csi2_ctx_enable(isp, csi2, 0, 1);
 }
 
@@ -812,7 +812,7 @@ static int csi2_queue(struct isp_video *video, struct 
isp_buffer *buffer)
struct isp_device *isp = video->isp;
struct isp_csi2_device *csi2 = &isp->isp_csi2a;
 
-   csi2_set_outaddr(csi2, buffer->isp_addr);
+   csi2_set_outaddr(csi2, buffer->dma);
 
/*
 * If streaming was enabled before there was a buffer queued
diff --git a/drivers/media/platform/omap3isp/isppreview.c 
b/drivers/media/platform/omap3isp/isppreview.c
index 395b2b0..720809b 100644
--- a/drivers/media/platform/omap3isp/isppreview.c
+++ b/drivers/media/platform/omap3isp/isppreview.c
@@ -1499,14 +1499,14 @@ static void preview_isr_buffer(struct isp_prev_device 
*prev)
if (prev->input == PREVIEW_INPUT_MEMORY) {
buffer = omap3isp_video_buffer_next(&prev->video_in);
if (buffer != NULL)
-   preview_set_inaddr(prev, buffer->isp_addr);
+   preview_set_inaddr(prev, buffer->dma);
pipe->state |= ISP_PIPELINE_IDLE_INPUT;
}
 
if (prev->output & PREVIEW_OUTPUT_MEMORY) {
buffer = omap3isp_video_buffer_next(&prev->video_out);
if (buffer != NULL) {
-   preview_set_outaddr(prev, buffer->isp_addr);
+   preview_set_outaddr(prev, buffer->dma);
restart = 1;
}
pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
@@ -1577,10 +1577,10 @@ static int preview_video_queue(struct isp_video *video,
struct isp_prev_device *prev = &video->isp->isp_prev;
 
if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-   preview_set_inaddr(prev, buffer->isp_addr);
+   preview_set_inaddr(prev, buffer->dma);
 
if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-   preview_set_outaddr(prev, buffer->isp_addr);
+   preview_set_outaddr(prev, buffer->dma);
 
return 0;
 }
diff --git a/drivers/media/platform/omap3isp/ispresizer.c 
b/drivers/media/platform/omap3isp/ispresizer.c
index 86369df..6f077c2 100644
--- a/drivers/media/platform/omap3isp/ispresizer.c
+++ b/drivers/media/platform/

[PATCH 15/25] omap3isp: queue: Fix the dma_map_sg() return value check

2014-04-03 Thread Laurent Pinchart
dma_map_sg() can merge sglist entries, and can thus return a number of
mapped entries different than the original value. Don't consider this as
an error.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index 2fd254f..479d348 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -465,7 +465,7 @@ static int isp_video_buffer_prepare(struct isp_video_buffer 
*buf)
  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
ret = dma_map_sg(buf->queue->dev, buf->sgt.sgl,
 buf->sgt.orig_nents, direction);
-   if (ret != buf->sgt.orig_nents) {
+   if (ret <= 0) {
ret = -EFAULT;
goto done;
}
-- 
1.8.3.2

--
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 20/25] omap3isp: Move queue mutex to isp_video structure

2014-04-03 Thread Laurent Pinchart
This prepares for the move to videobuf2.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.c | 102 -
 drivers/media/platform/omap3isp/ispqueue.h |   2 -
 drivers/media/platform/omap3isp/ispvideo.c |  72 
 drivers/media/platform/omap3isp/ispvideo.h |   1 +
 4 files changed, 86 insertions(+), 91 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index 515ed94..dcd9446 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -660,7 +660,6 @@ int omap3isp_video_queue_init(struct isp_video_queue *queue,
  struct device *dev, unsigned int bufsize)
 {
INIT_LIST_HEAD(&queue->queue);
-   mutex_init(&queue->lock);
spin_lock_init(&queue->irqlock);
 
queue->type = type;
@@ -712,18 +711,12 @@ int omap3isp_video_queue_reqbufs(struct isp_video_queue 
*queue,
 
nbuffers = min_t(unsigned int, nbuffers, ISP_VIDEO_MAX_BUFFERS);
 
-   mutex_lock(&queue->lock);
-
ret = isp_video_queue_alloc(queue, nbuffers, size, rb->memory);
if (ret < 0)
-   goto done;
+   return ret;
 
rb->count = ret;
-   ret = 0;
-
-done:
-   mutex_unlock(&queue->lock);
-   return ret;
+   return 0;
 }
 
 /**
@@ -738,24 +731,17 @@ int omap3isp_video_queue_querybuf(struct isp_video_queue 
*queue,
  struct v4l2_buffer *vbuf)
 {
struct isp_video_buffer *buf;
-   int ret = 0;
 
if (vbuf->type != queue->type)
return -EINVAL;
 
-   mutex_lock(&queue->lock);
-
-   if (vbuf->index >= queue->count) {
-   ret = -EINVAL;
-   goto done;
-   }
+   if (vbuf->index >= queue->count)
+   return -EINVAL;
 
buf = queue->buffers[vbuf->index];
isp_video_buffer_query(buf, vbuf);
 
-done:
-   mutex_unlock(&queue->lock);
-   return ret;
+   return 0;
 }
 
 /**
@@ -776,27 +762,25 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue 
*queue,
 {
struct isp_video_buffer *buf;
unsigned long flags;
-   int ret = -EINVAL;
+   int ret;
 
if (vbuf->type != queue->type)
-   goto done;
-
-   mutex_lock(&queue->lock);
+   return -EINVAL;
 
if (vbuf->index >= queue->count)
-   goto done;
+   return -EINVAL;
 
buf = queue->buffers[vbuf->index];
 
if (vbuf->memory != buf->vbuf.memory)
-   goto done;
+   return -EINVAL;
 
if (buf->state != ISP_BUF_STATE_IDLE)
-   goto done;
+   return -EINVAL;
 
if (vbuf->memory == V4L2_MEMORY_USERPTR &&
vbuf->length < buf->vbuf.length)
-   goto done;
+   return -EINVAL;
 
if (vbuf->memory == V4L2_MEMORY_USERPTR &&
vbuf->m.userptr != buf->vbuf.m.userptr) {
@@ -808,7 +792,7 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
if (!buf->prepared) {
ret = isp_video_buffer_prepare(buf);
if (ret < 0)
-   goto done;
+   return ret;
buf->prepared = 1;
}
 
@@ -823,11 +807,7 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue 
*queue,
spin_unlock_irqrestore(&queue->irqlock, flags);
}
 
-   ret = 0;
-
-done:
-   mutex_unlock(&queue->lock);
-   return ret;
+   return 0;
 }
 
 /**
@@ -853,17 +833,13 @@ int omap3isp_video_queue_dqbuf(struct isp_video_queue 
*queue,
if (vbuf->type != queue->type)
return -EINVAL;
 
-   mutex_lock(&queue->lock);
-
-   if (list_empty(&queue->queue)) {
-   ret = -EINVAL;
-   goto done;
-   }
+   if (list_empty(&queue->queue))
+   return -EINVAL;
 
buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
ret = isp_video_buffer_wait(buf, nonblocking);
if (ret < 0)
-   goto done;
+   return ret;
 
list_del(&buf->stream);
 
@@ -871,9 +847,7 @@ int omap3isp_video_queue_dqbuf(struct isp_video_queue 
*queue,
buf->state = ISP_BUF_STATE_IDLE;
vbuf->flags &= ~V4L2_BUF_FLAG_QUEUED;
 
-done:
-   mutex_unlock(&queue->lock);
-   return ret;
+   return 0;
 }
 
 /**
@@ -890,10 +864,8 @@ int omap3isp_video_queue_streamon(struct isp_video_queue 
*queue)
struct isp_video_buffer *buf;
unsigned long flags;
 
-   mutex_lock(&queue->lock);
-
if (queue->streaming)
-   goto done;
+   return 0;
 
queue->streaming = 1;
 
@@ -902,8 +874,6 @@ int omap3isp_video_queue_streamon(struct isp_video_queue 
*queue)
queue->ops->buffer_queue(buf);
spin_unlock_irqrestore(&queue->irqlo

[PATCH 06/25] omap3isp: stat: Use the DMA API

2014-04-03 Thread Laurent Pinchart
Replace the OMAP-specific IOMMU API usage by the DMA API. All buffers
are now allocated using dma_alloc_coherent() and the related sg table is
retrieved using dma_get_sgtable() for sync operations.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispstat.c | 123 +-
 drivers/media/platform/omap3isp/ispstat.h |   2 +-
 2 files changed, 53 insertions(+), 72 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispstat.c 
b/drivers/media/platform/omap3isp/ispstat.c
index 4cf7eb1..e6cbc1e 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -26,7 +26,6 @@
  */
 
 #include 
-#include 
 #include 
 #include 
 
@@ -77,21 +76,10 @@ static void __isp_stat_buf_sync_magic(struct ispstat *stat,
dma_addr_t, unsigned long, size_t,
enum dma_data_direction))
 {
-   struct device *dev = stat->isp->dev;
-   struct page *pg;
-   dma_addr_t dma_addr;
-   u32 offset;
-
-   /* Initial magic words */
-   pg = vmalloc_to_page(buf->virt_addr);
-   dma_addr = pfn_to_dma(dev, page_to_pfn(pg));
-   dma_sync(dev, dma_addr, 0, MAGIC_SIZE, dir);
-
-   /* Final magic words */
-   pg = vmalloc_to_page(buf->virt_addr + buf_size);
-   dma_addr = pfn_to_dma(dev, page_to_pfn(pg));
-   offset = ((u32)buf->virt_addr + buf_size) & ~PAGE_MASK;
-   dma_sync(dev, dma_addr, offset, MAGIC_SIZE, dir);
+   /* Sync the initial and final magic words. */
+   dma_sync(stat->isp->dev, buf->dma_addr, 0, MAGIC_SIZE, dir);
+   dma_sync(stat->isp->dev, buf->dma_addr + (buf_size & PAGE_MASK),
+buf_size & ~PAGE_MASK, MAGIC_SIZE, dir);
 }
 
 static void isp_stat_buf_sync_magic_for_device(struct ispstat *stat,
@@ -183,8 +171,8 @@ static void isp_stat_buf_sync_for_device(struct ispstat 
*stat,
if (ISP_STAT_USES_DMAENGINE(stat))
return;
 
-   dma_sync_sg_for_device(stat->isp->dev, buf->sgt->sgl,
-  buf->sgt->nents, DMA_FROM_DEVICE);
+   dma_sync_sg_for_device(stat->isp->dev, buf->sgt.sgl,
+  buf->sgt.nents, DMA_FROM_DEVICE);
 }
 
 static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
@@ -193,8 +181,8 @@ static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
if (ISP_STAT_USES_DMAENGINE(stat))
return;
 
-   dma_sync_sg_for_cpu(stat->isp->dev, buf->sgt->sgl,
-   buf->sgt->nents, DMA_FROM_DEVICE);
+   dma_sync_sg_for_cpu(stat->isp->dev, buf->sgt.sgl,
+   buf->sgt.nents, DMA_FROM_DEVICE);
 }
 
 static void isp_stat_buf_clear(struct ispstat *stat)
@@ -354,26 +342,21 @@ static struct ispstat_buffer *isp_stat_buf_get(struct 
ispstat *stat,
 
 static void isp_stat_bufs_free(struct ispstat *stat)
 {
-   struct isp_device *isp = stat->isp;
-   int i;
+   struct device *dev = ISP_STAT_USES_DMAENGINE(stat)
+  ? NULL : stat->isp->dev;
+   unsigned int i;
 
for (i = 0; i < STAT_MAX_BUFS; i++) {
struct ispstat_buffer *buf = &stat->buf[i];
 
-   if (!ISP_STAT_USES_DMAENGINE(stat)) {
-   if (IS_ERR_OR_NULL((void *)buf->dma_addr))
-   continue;
-   if (buf->sgt)
-   dma_unmap_sg(isp->dev, buf->sgt->sgl,
-buf->sgt->nents, DMA_FROM_DEVICE);
-   omap_iommu_vfree(isp->domain, isp->dev, buf->dma_addr);
-   } else {
-   if (!buf->virt_addr)
-   continue;
-   dma_free_coherent(stat->isp->dev, stat->buf_alloc_size,
- buf->virt_addr, buf->dma_addr);
-   }
-   buf->sgt = NULL;
+   if (!buf->virt_addr)
+   continue;
+
+   sg_free_table(&buf->sgt);
+
+   dma_free_coherent(dev, stat->buf_alloc_size, buf->virt_addr,
+ buf->dma_addr);
+
buf->dma_addr = 0;
buf->virt_addr = NULL;
buf->empty = 1;
@@ -386,47 +369,49 @@ static void isp_stat_bufs_free(struct ispstat *stat)
stat->active_buf = NULL;
 }
 
-static int isp_stat_bufs_alloc_iommu(struct ispstat *stat,
-struct ispstat_buffer *buf,
-unsigned int size)
-{
-   struct isp_device *isp = stat->isp;
-   struct iovm_struct *iovm;
-
-   buf->dma_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
-  size, IOMMU_FLAG);
-   if (IS_ERR_VALUE(buf->dma_addr))
-   return -ENOMEM;
-
-   iovm = omap_find_iovm_area(isp->dev, buf->dma_addr);
-   if (!iovm)
- 

[PATCH 22/25] omap3isp: Move buffer irqlist to isp_buffer structure

2014-04-03 Thread Laurent Pinchart
This prepares for the move to videobuf2.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.h |  2 --
 drivers/media/platform/omap3isp/ispvideo.c | 39 +++---
 drivers/media/platform/omap3isp/ispvideo.h |  2 ++
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.h 
b/drivers/media/platform/omap3isp/ispqueue.h
index ecf3309..ff18208 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -73,7 +73,6 @@ enum isp_video_buffer_state {
  * @sgt: Scatter gather table (for userspace buffers)
  * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
  * @vbuf: V4L2 buffer
- * @irqlist: List head for insertion into IRQ queue
  * @state: Current buffer state
  * @wait: Wait queue to signal buffer completion
  */
@@ -97,7 +96,6 @@ struct isp_video_buffer {
 
/* Touched by the interrupt handler. */
struct v4l2_buffer vbuf;
-   struct list_head irqlist;
enum isp_video_buffer_state state;
wait_queue_head_t wait;
dma_addr_t dma;
diff --git a/drivers/media/platform/omap3isp/ispvideo.c 
b/drivers/media/platform/omap3isp/ispvideo.c
index 85338d3..e1f9983 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -391,7 +391,7 @@ static void isp_video_buffer_queue(struct isp_video_buffer 
*buf)
}
 
empty = list_empty(&video->dmaqueue);
-   list_add_tail(&buffer->buffer.irqlist, &video->dmaqueue);
+   list_add_tail(&buffer->irqlist, &video->dmaqueue);
 
spin_unlock_irqrestore(&video->irqlock, flags);
 
@@ -446,7 +446,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct 
isp_video *video)
struct isp_video_fh *vfh =
container_of(queue, struct isp_video_fh, queue);
enum isp_pipeline_state state;
-   struct isp_video_buffer *buf;
+   struct isp_buffer *buf;
unsigned long flags;
struct timespec ts;
 
@@ -456,16 +456,16 @@ struct isp_buffer *omap3isp_video_buffer_next(struct 
isp_video *video)
return NULL;
}
 
-   buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
+   buf = list_first_entry(&video->dmaqueue, struct isp_buffer,
   irqlist);
list_del(&buf->irqlist);
spin_unlock_irqrestore(&video->irqlock, flags);
 
-   buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
+   buf->buffer.vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
 
ktime_get_ts(&ts);
-   buf->vbuf.timestamp.tv_sec = ts.tv_sec;
-   buf->vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+   buf->buffer.vbuf.timestamp.tv_sec = ts.tv_sec;
+   buf->buffer.vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 
/* Do frame number propagation only if this is the output video node.
 * Frame number either comes from the CSI receivers or it gets
@@ -474,19 +474,20 @@ struct isp_buffer *omap3isp_video_buffer_next(struct 
isp_video *video)
 * first, so the input number might lag behind by 1 in some cases.
 */
if (video == pipe->output && !pipe->do_propagation)
-   buf->vbuf.sequence = atomic_inc_return(&pipe->frame_number);
+   buf->buffer.vbuf.sequence =
+   atomic_inc_return(&pipe->frame_number);
else
-   buf->vbuf.sequence = atomic_read(&pipe->frame_number);
+   buf->buffer.vbuf.sequence = atomic_read(&pipe->frame_number);
 
/* Report pipeline errors to userspace on the capture device side. */
if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
-   buf->state = ISP_BUF_STATE_ERROR;
+   buf->buffer.state = ISP_BUF_STATE_ERROR;
pipe->error = false;
} else {
-   buf->state = ISP_BUF_STATE_DONE;
+   buf->buffer.state = ISP_BUF_STATE_DONE;
}
 
-   wake_up(&buf->wait);
+   wake_up(&buf->buffer.wait);
 
if (list_empty(&video->dmaqueue)) {
if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -510,10 +511,10 @@ struct isp_buffer *omap3isp_video_buffer_next(struct 
isp_video *video)
spin_unlock_irqrestore(&pipe->lock, flags);
}
 
-   buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
+   buf = list_first_entry(&video->dmaqueue, struct isp_buffer,
   irqlist);
-   buf->state = ISP_BUF_STATE_ACTIVE;
-   return to_isp_buffer(buf);
+   buf->buffer.state = ISP_BUF_STATE_ACTIVE;
+   return buf;
 }
 
 /*
@@ -530,14 +531,14 @@ void omap3isp_video_cancel_stream(struct isp_video *video)
spin_lock_irqsave(&video->irqlock, flags);
 
while (!list_empty(&video->dmaqueue)) {
-   struct isp_video_buffer *buf;
+   struct isp_buffer *buf;
 
   

[PATCH 03/25] omap3isp: stat: Share common code for buffer allocation

2014-04-03 Thread Laurent Pinchart
Move code common between the isp_stat_bufs_alloc_dma() and
isp_stat_bufs_alloc_iommu() functions to isp_stat_bufs_alloc().

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispstat.c | 114 ++
 1 file changed, 54 insertions(+), 60 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispstat.c 
b/drivers/media/platform/omap3isp/ispstat.c
index c6c1290..b1eb902 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -389,74 +389,42 @@ static void isp_stat_bufs_free(struct ispstat *stat)
stat->active_buf = NULL;
 }
 
-static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
+static int isp_stat_bufs_alloc_iommu(struct ispstat *stat,
+struct ispstat_buffer *buf,
+unsigned int size)
 {
struct isp_device *isp = stat->isp;
-   int i;
+   struct iovm_struct *iovm;
 
-   stat->buf_alloc_size = size;
+   buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
+   size, IOMMU_FLAG);
+   if (IS_ERR((void *)buf->iommu_addr))
+   return -ENOMEM;
 
-   for (i = 0; i < STAT_MAX_BUFS; i++) {
-   struct ispstat_buffer *buf = &stat->buf[i];
-   struct iovm_struct *iovm;
+   iovm = omap_find_iovm_area(isp->dev, buf->iommu_addr);
+   if (!iovm)
+   return -ENOMEM;
 
-   buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
-   size, IOMMU_FLAG);
-   if (IS_ERR((void *)buf->iommu_addr)) {
-   dev_err(stat->isp->dev,
-"%s: Can't acquire memory for "
-"buffer %d\n", stat->subdev.name, i);
-   isp_stat_bufs_free(stat);
-   return -ENOMEM;
-   }
+   if (!dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
+   DMA_FROM_DEVICE))
+   return -ENOMEM;
 
-   iovm = omap_find_iovm_area(isp->dev, buf->iommu_addr);
-   if (!iovm ||
-   !dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
-   DMA_FROM_DEVICE)) {
-   isp_stat_bufs_free(stat);
-   return -ENOMEM;
-   }
-   buf->iovm = iovm;
-
-   buf->virt_addr = omap_da_to_va(stat->isp->dev,
- (u32)buf->iommu_addr);
-   buf->empty = 1;
-   dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
-   "iommu_addr=0x%08lx virt_addr=0x%08lx",
-   stat->subdev.name, i, buf->iommu_addr,
-   (unsigned long)buf->virt_addr);
-   }
+   buf->iovm = iovm;
+   buf->virt_addr = omap_da_to_va(stat->isp->dev,
+ (u32)buf->iommu_addr);
 
return 0;
 }
 
-static int isp_stat_bufs_alloc_dma(struct ispstat *stat, unsigned int size)
+static int isp_stat_bufs_alloc_dma(struct ispstat *stat,
+  struct ispstat_buffer *buf,
+  unsigned int size)
 {
-   int i;
-
-   stat->buf_alloc_size = size;
-
-   for (i = 0; i < STAT_MAX_BUFS; i++) {
-   struct ispstat_buffer *buf = &stat->buf[i];
-
-   buf->virt_addr = dma_alloc_coherent(stat->isp->dev, size,
-   &buf->dma_addr, GFP_KERNEL | GFP_DMA);
-
-   if (!buf->virt_addr || !buf->dma_addr) {
-   dev_info(stat->isp->dev,
-"%s: Can't acquire memory for "
-"DMA buffer %d\n", stat->subdev.name, i);
-   isp_stat_bufs_free(stat);
-   return -ENOMEM;
-   }
-   buf->empty = 1;
+   buf->virt_addr = dma_alloc_coherent(stat->isp->dev, size,
+   &buf->dma_addr, GFP_KERNEL | GFP_DMA);
 
-   dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
-   "dma_addr=0x%08lx virt_addr=0x%08lx\n",
-   stat->subdev.name, i, (unsigned long)buf->dma_addr,
-   (unsigned long)buf->virt_addr);
-   }
+   if (!buf->virt_addr || !buf->dma_addr)
+   return -ENOMEM;
 
return 0;
 }
@@ -464,6 +432,7 @@ static int isp_stat_bufs_alloc_dma(struct ispstat *stat, 
unsigned int size)
 static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
 {
unsigned long flags;
+   unsigned int i;
 
spin_lock_irqsave(&stat->isp->stat_lock, flags);
 
@@ -487,10 +456,35 @@ static int isp_stat_bufs_alloc(struct ispstat *stat, u32 
size)
 
isp_stat_bufs_free(stat);
 
-   if (I

[PATCH 02/25] omap3isp: stat: Remove impossible WARN_ON

2014-04-03 Thread Laurent Pinchart
The WARN_ON statements in the buffer allocation functions try to catch
conditions where buffers would have already been allocated. As the
buffers are explicitly freed right before being allocated this can't
happen.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispstat.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispstat.c 
b/drivers/media/platform/omap3isp/ispstat.c
index 48b702a..c6c1290 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -400,7 +400,6 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, 
unsigned int size)
struct ispstat_buffer *buf = &stat->buf[i];
struct iovm_struct *iovm;
 
-   WARN_ON(buf->dma_addr);
buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
size, IOMMU_FLAG);
if (IS_ERR((void *)buf->iommu_addr)) {
@@ -441,7 +440,6 @@ static int isp_stat_bufs_alloc_dma(struct ispstat *stat, 
unsigned int size)
for (i = 0; i < STAT_MAX_BUFS; i++) {
struct ispstat_buffer *buf = &stat->buf[i];
 
-   WARN_ON(buf->iommu_addr);
buf->virt_addr = dma_alloc_coherent(stat->isp->dev, size,
&buf->dma_addr, GFP_KERNEL | GFP_DMA);
 
-- 
1.8.3.2

--
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 13/25] omap3isp: queue: Inline the ispmmu_v(un)map functions

2014-04-03 Thread Laurent Pinchart
The ispmmu_vmap() and ispmmu_vunmap() functions are just wrappers around
omap_iommu_vmap() and omap_iommu_vunmap(). Inline them.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.c | 36 --
 1 file changed, 4 insertions(+), 32 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index a7be7d7..088710b 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -39,36 +39,6 @@
 #include "ispvideo.h"
 
 /* 
-
- * IOMMU management
- */
-
-#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
-
-/*
- * ispmmu_vmap - Wrapper for virtual memory mapping of a scatter gather table
- * @dev: Device pointer specific to the OMAP3 ISP.
- * @sgt: Pointer to source scatter gather table.
- *
- * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
- * we ran out of memory.
- */
-static dma_addr_t
-ispmmu_vmap(struct isp_device *isp, const struct sg_table *sgt)
-{
-   return omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
-}
-
-/*
- * ispmmu_vunmap - Unmap a device address from the ISP MMU
- * @dev: Device pointer specific to the OMAP3 ISP.
- * @da: Device address generated from a ispmmu_vmap call.
- */
-static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
-{
-   omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
-}
-
-/* 
-
  * Video buffers management
  */
 
@@ -227,7 +197,8 @@ static void isp_video_buffer_cleanup(struct 
isp_video_buffer *buf)
unsigned int i;
 
if (buf->dma) {
-   ispmmu_vunmap(video->isp, buf->dma);
+   omap_iommu_vunmap(video->isp->domain, video->isp->dev,
+ buf->dma);
buf->dma = 0;
}
 
@@ -521,7 +492,8 @@ static int isp_video_buffer_prepare(struct isp_video_buffer 
*buf)
}
}
 
-   addr = ispmmu_vmap(video->isp, &buf->sgt);
+   addr = omap_iommu_vmap(video->isp->domain, video->isp->dev, 0,
+  &buf->sgt, IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8);
if (IS_ERR_VALUE(addr)) {
ret = -EIO;
goto done;
-- 
1.8.3.2

--
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 18/25] omap3isp: Use the ARM DMA IOMMU-aware operations

2014-04-03 Thread Laurent Pinchart
Attach an ARM DMA I/O virtual address space to the ISP device. This
switches to the IOMMU-aware ARM DMA backend, we can thus remove the
explicit calls to the OMAP IOMMU map and unmap functions.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/Kconfig |   4 +-
 drivers/media/platform/omap3isp/isp.c  | 102 +
 drivers/media/platform/omap3isp/isp.h  |   8 +--
 drivers/media/platform/omap3isp/ispqueue.c |  34 ++
 drivers/media/platform/omap3isp/ispqueue.h |   2 -
 5 files changed, 89 insertions(+), 61 deletions(-)

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index c137abf..2091b2b 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -93,7 +93,9 @@ config VIDEO_M32R_AR_M64278
 
 config VIDEO_OMAP3
tristate "OMAP 3 Camera support"
-   depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && 
ARCH_OMAP3
+   depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
+   select ARM_DMA_USE_IOMMU
+   select OMAP_IOMMU
---help---
  Driver for an OMAP 3 camera controller.
 
diff --git a/drivers/media/platform/omap3isp/isp.c 
b/drivers/media/platform/omap3isp/isp.c
index 06a0df4..af8bd21 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -69,6 +69,8 @@
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 
@@ -1625,7 +1627,7 @@ struct isp_device *omap3isp_get(struct isp_device *isp)
  * Decrement the reference count on the ISP. If the last reference is released,
  * power-down all submodules, disable clocks and free temporary buffers.
  */
-void omap3isp_put(struct isp_device *isp)
+static void __omap3isp_put(struct isp_device *isp, bool save_ctx)
 {
if (isp == NULL)
return;
@@ -1634,7 +1636,7 @@ void omap3isp_put(struct isp_device *isp)
BUG_ON(isp->ref_count == 0);
if (--isp->ref_count == 0) {
isp_disable_interrupts(isp);
-   if (isp->domain) {
+   if (save_ctx) {
isp_save_ctx(isp);
isp->has_context = 1;
}
@@ -1648,6 +1650,11 @@ void omap3isp_put(struct isp_device *isp)
mutex_unlock(&isp->isp_mutex);
 }
 
+void omap3isp_put(struct isp_device *isp)
+{
+   __omap3isp_put(isp, true);
+}
+
 /* --
  * Platform device driver
  */
@@ -2120,6 +2127,61 @@ error_csiphy:
return ret;
 }
 
+static void isp_detach_iommu(struct isp_device *isp)
+{
+   arm_iommu_release_mapping(isp->mapping);
+   isp->mapping = NULL;
+   iommu_group_remove_device(isp->dev);
+}
+
+static int isp_attach_iommu(struct isp_device *isp)
+{
+   struct dma_iommu_mapping *mapping;
+   struct iommu_group *group;
+   int ret;
+
+   /* Create a device group and add the device to it. */
+   group = iommu_group_alloc();
+   if (IS_ERR(group)) {
+   dev_err(isp->dev, "failed to allocate IOMMU group\n");
+   return PTR_ERR(group);
+   }
+
+   ret = iommu_group_add_device(group, isp->dev);
+   iommu_group_put(group);
+
+   if (ret < 0) {
+   dev_err(isp->dev, "failed to add device to IPMMU group\n");
+   return ret;
+   }
+
+   /*
+* Create the ARM mapping, used by the ARM DMA mapping core to allocate
+* VAs. This will allocate a corresponding IOMMU domain.
+*/
+   mapping = arm_iommu_create_mapping(&platform_bus_type, SZ_1G, SZ_2G, 0);
+   if (IS_ERR(mapping)) {
+   dev_err(isp->dev, "failed to create ARM IOMMU mapping\n");
+   ret = PTR_ERR(mapping);
+   goto error;
+   }
+
+   isp->mapping = mapping;
+
+   /* Attach the ARM VA mapping to the device. */
+   ret = arm_iommu_attach_device(isp->dev, mapping);
+   if (ret < 0) {
+   dev_err(isp->dev, "failed to attach device to VA mapping\n");
+   goto error;
+   }
+
+   return 0;
+
+error:
+   isp_detach_iommu(isp);
+   return ret;
+}
+
 /*
  * isp_remove - Remove ISP platform device
  * @pdev: Pointer to ISP platform device
@@ -2135,10 +2197,8 @@ static int isp_remove(struct platform_device *pdev)
isp_xclk_cleanup(isp);
 
__omap3isp_get(isp, false);
-   iommu_detach_device(isp->domain, &pdev->dev);
-   iommu_domain_free(isp->domain);
-   isp->domain = NULL;
-   omap3isp_put(isp);
+   isp_detach_iommu(isp);
+   __omap3isp_put(isp, false);
 
return 0;
 }
@@ -2265,39 +2325,32 @@ static int isp_probe(struct platform_device *pdev)
}
}
 
-   isp->domain = iommu_domain_alloc(pdev->dev.bus);
-   if (!isp->domain) {
-   dev_err(isp->dev, "can't alloc iommu domain\n");
-   ret = -ENOMEM;
+   /* IOMMU */
+   ret

[PATCH 11/25] omap3isp: queue: Use sg_table structure

2014-04-03 Thread Laurent Pinchart
Replace the sglen and sglist fields stored in the buffer structure with
an sg_table. This allows using the sg table allocation helper function.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.c | 108 ++---
 drivers/media/platform/omap3isp/ispqueue.h |   6 +-
 2 files changed, 40 insertions(+), 74 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index 8623c05..51ec40d 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -45,33 +45,17 @@
 #define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
 
 /*
- * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list
+ * ispmmu_vmap - Wrapper for virtual memory mapping of a scatter gather table
  * @dev: Device pointer specific to the OMAP3 ISP.
- * @sglist: Pointer to source Scatter gather list to allocate.
- * @sglen: Number of elements of the scatter-gatter list.
+ * @sgt: Pointer to source scatter gather table.
  *
  * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
  * we ran out of memory.
  */
 static dma_addr_t
-ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int 
sglen)
+ispmmu_vmap(struct isp_device *isp, const struct sg_table *sgt)
 {
-   struct sg_table *sgt;
-   u32 da;
-
-   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-   if (sgt == NULL)
-   return -ENOMEM;
-
-   sgt->sgl = (struct scatterlist *)sglist;
-   sgt->nents = sglen;
-   sgt->orig_nents = sglen;
-
-   da = omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
-   if (IS_ERR_VALUE(da))
-   kfree(sgt);
-
-   return da;
+   return omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
 }
 
 /*
@@ -81,10 +65,7 @@ ispmmu_vmap(struct isp_device *isp, const struct scatterlist 
*sglist, int sglen)
  */
 static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
 {
-   struct sg_table *sgt;
-
-   sgt = omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
-   kfree(sgt);
+   omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
 }
 
 /* 
-
@@ -204,34 +185,31 @@ out:
  */
 static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
 {
-   struct scatterlist *sglist;
+   struct scatterlist *sg;
unsigned int npages;
unsigned int i;
void *addr;
+   int ret;
 
addr = buf->vaddr;
npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT;
 
-   sglist = vmalloc(npages * sizeof(*sglist));
-   if (sglist == NULL)
-   return -ENOMEM;
-
-   sg_init_table(sglist, npages);
+   ret = sg_alloc_table(&buf->sgt, npages, GFP_KERNEL);
+   if (ret < 0)
+   return ret;
 
-   for (i = 0; i < npages; ++i, addr += PAGE_SIZE) {
+   for (sg = buf->sgt.sgl, i = 0; i < npages; ++i, addr += PAGE_SIZE) {
struct page *page = vmalloc_to_page(addr);
 
if (page == NULL || PageHighMem(page)) {
-   vfree(sglist);
+   sg_free_table(&buf->sgt);
return -EINVAL;
}
 
-   sg_set_page(&sglist[i], page, PAGE_SIZE, 0);
+   sg_set_page(sg, page, PAGE_SIZE, 0);
+   sg = sg_next(sg);
}
 
-   buf->sglen = npages;
-   buf->sglist = sglist;
-
return 0;
 }
 
@@ -242,30 +220,26 @@ static int isp_video_buffer_sglist_kernel(struct 
isp_video_buffer *buf)
  */
 static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf)
 {
-   struct scatterlist *sglist;
unsigned int offset = buf->offset;
+   struct scatterlist *sg;
unsigned int i;
+   int ret;
 
-   sglist = vmalloc(buf->npages * sizeof(*sglist));
-   if (sglist == NULL)
-   return -ENOMEM;
-
-   sg_init_table(sglist, buf->npages);
+   ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
+   if (ret < 0)
+   return ret;
 
-   for (i = 0; i < buf->npages; ++i) {
+   for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i) {
if (PageHighMem(buf->pages[i])) {
-   vfree(sglist);
+   sg_free_table(&buf->sgt);
return -EINVAL;
}
 
-   sg_set_page(&sglist[i], buf->pages[i], PAGE_SIZE - offset,
-   offset);
+   sg_set_page(sg, buf->pages[i], PAGE_SIZE - offset, offset);
+   sg = sg_next(sg);
offset = 0;
}
 
-   buf->sglen = buf->npages;
-   buf->sglist = sglist;
-
return 0;
 }
 
@@ -277,30 +251,26 @@ static int isp_video_buffer_sglist_user(struct 
isp_video_buffer *buf)
  */
 static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf)
 {

[PATCH 23/25] v4l: vb2: Add a function to discard all DONE buffers

2014-04-03 Thread Laurent Pinchart
When suspending a device while a video stream is active all buffers
marked as done but not dequeued yet will be kept across suspend and
given back to userspace after resume. This will result in outdated
buffers being dequeued.

Introduce a new vb2 function to mark all done buffers as erroneous
instead, to be used by drivers at resume time.

Signed-off-by: Laurent Pinchart 
Acked-by: Hans Verkuil 
---
 drivers/media/v4l2-core/videobuf2-core.c | 24 
 include/media/videobuf2-core.h   |  1 +
 2 files changed, 25 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index f9059bb..6ab13b7 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1131,6 +1131,30 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum 
vb2_buffer_state state)
 EXPORT_SYMBOL_GPL(vb2_buffer_done);
 
 /**
+ * vb2_discard_done() - discard all buffers marked as DONE
+ * @q: videobuf2 queue
+ *
+ * This function is intended to be used with suspend/resume operations. It
+ * discards all 'done' buffers as they would be too old to be requested after
+ * resume.
+ *
+ * Drivers must stop the hardware and synchronize with interrupt handlers 
and/or
+ * delayed works before calling this function to make sure no buffer will be
+ * touched by the driver and/or hardware.
+ */
+void vb2_discard_done(struct vb2_queue *q)
+{
+   struct vb2_buffer *vb;
+   unsigned long flags;
+
+   spin_lock_irqsave(&q->done_lock, flags);
+   list_for_each_entry(vb, &q->done_list, done_entry)
+   vb->state = VB2_BUF_STATE_ERROR;
+   spin_unlock_irqrestore(&q->done_lock, flags);
+}
+EXPORT_SYMBOL_GPL(vb2_discard_done);
+
+/**
  * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
  * v4l2_buffer by the userspace. The caller has already verified that struct
  * v4l2_buffer has a valid number of planes.
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index af46211..2c2f23b 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -429,6 +429,7 @@ void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int 
plane_no);
 void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no);
 
 void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
+void vb2_discard_done(struct vb2_queue *q);
 int vb2_wait_for_all_buffers(struct vb2_queue *q);
 
 int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
-- 
1.8.3.2

--
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 24/25] omap3isp: Move to videobuf2

2014-04-03 Thread Laurent Pinchart
Replace the custom buffers queue implementation with a videobuf2 queue.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/Makefile   |2 +-
 drivers/media/platform/omap3isp/ispqueue.c | 1031 
 drivers/media/platform/omap3isp/ispqueue.h |  171 -
 drivers/media/platform/omap3isp/ispvideo.c |  167 +++--
 drivers/media/platform/omap3isp/ispvideo.h |   23 +-
 drivers/staging/media/omap4iss/iss_video.c |2 +-
 6 files changed, 109 insertions(+), 1287 deletions(-)
 delete mode 100644 drivers/media/platform/omap3isp/ispqueue.c
 delete mode 100644 drivers/media/platform/omap3isp/ispqueue.h

diff --git a/drivers/media/platform/omap3isp/Makefile 
b/drivers/media/platform/omap3isp/Makefile
index e8847e7..254975a 100644
--- a/drivers/media/platform/omap3isp/Makefile
+++ b/drivers/media/platform/omap3isp/Makefile
@@ -3,7 +3,7 @@
 ccflags-$(CONFIG_VIDEO_OMAP3_DEBUG) += -DDEBUG
 
 omap3-isp-objs += \
-   isp.o ispqueue.o ispvideo.o \
+   isp.o ispvideo.o \
ispcsiphy.o ispccp2.o ispcsi2.o \
ispccdc.o isppreview.o ispresizer.o \
ispstat.o isph3a_aewb.o isph3a_af.o isphist.o
diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
deleted file mode 100644
index 77afb63..000
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ /dev/null
@@ -1,1031 +0,0 @@
-/*
- * ispqueue.c
- *
- * TI OMAP3 ISP - Video buffers queue handling
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * Contacts: Laurent Pinchart 
- *  Sakari Ailus 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "isp.h"
-#include "ispqueue.h"
-#include "ispvideo.h"
-
-/* 
-
- * Video buffers management
- */
-
-/*
- * isp_video_buffer_cache_sync - Keep the buffers coherent between CPU and ISP
- *
- * The typical operation required here is Cache Invalidation across
- * the (user space) buffer address range. And this _must_ be done
- * at QBUF stage (and *only* at QBUF).
- *
- * We try to use optimal cache invalidation function:
- * - dmac_map_area:
- *- used when the number of pages are _low_.
- *- it becomes quite slow as the number of pages increase.
- *   - for 648x492 viewfinder (150 pages) it takes 1.3 ms.
- *   - for 5 Mpix buffer (2491 pages) it takes between 25-50 ms.
- *
- * - flush_cache_all:
- *- used when the number of pages are _high_.
- *- time taken in the range of 500-900 us.
- *- has a higher penalty but, as whole dcache + icache is invalidated
- */
-/*
- * FIXME: dmac_inv_range crashes randomly on the user space buffer
- *address. Fall back to flush_cache_all for now.
- */
-#define ISP_CACHE_FLUSH_PAGES_MAX   0
-
-static void isp_video_buffer_cache_sync(struct isp_video_buffer *buf)
-{
-   if (buf->skip_cache)
-   return;
-
-   if (buf->vbuf.m.userptr == 0 || buf->npages == 0 ||
-   buf->npages > ISP_CACHE_FLUSH_PAGES_MAX)
-   flush_cache_all();
-   else {
-   dmac_map_area((void *)buf->vbuf.m.userptr, buf->vbuf.length,
- DMA_FROM_DEVICE);
-   outer_inv_range(buf->vbuf.m.userptr,
-   buf->vbuf.m.userptr + buf->vbuf.length);
-   }
-}
-
-/*
- * isp_video_buffer_lock_vma - Prevent VMAs from being unmapped
- *
- * Lock the VMAs underlying the given buffer into memory. This avoids the
- * userspace buffer mapping from being swapped out, making VIPT cache handling
- * easier.
- *
- * Note that the pages will not be freed as the buffers have been locked to
- * memory using by a call to get_user_pages(), but the userspace mapping could
- * still disappear if the VMAs are not locked. This is caused by the memory
- * management code trying to be as lock-less as possible, which results in the
- * userspace mapping manager not finding out that the pages are locked under
- * some conditions.
- */
-static int isp_video_buffer_lock_vma(struct isp_video_buffer *buf, int lock)
-{
-   struct vm_area_struct *vma;
-   unsigned long start;
-   unsigned long end;
-   int ret = 0;
-
-   if (buf->vbuf.memory == V4L2_MEMORY_MMAP)
-   retu

[PATCH 19/25] omap3isp: queue: Don't build scatterlist for kernel buffer

2014-04-03 Thread Laurent Pinchart
The scatterlist is not needed for those buffers, don't build it.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.c | 24 +++-
 drivers/media/platform/omap3isp/ispqueue.h |  8 
 2 files changed, 7 insertions(+), 25 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index 9c90fb0..515ed94 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -147,21 +147,6 @@ out:
 }
 
 /*
- * isp_video_buffer_prepare_kernel - Build scatter list for a kernel-allocated
- * buffer
- *
- * Retrieve the sgtable using the DMA API.
- */
-static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf)
-{
-   struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
-   struct isp_video *video = vfh->video;
-
-   return dma_get_sgtable(video->isp->dev, &buf->sgt, buf->vaddr,
-  buf->dma, PAGE_ALIGN(buf->vbuf.length));
-}
-
-/*
  * isp_video_buffer_cleanup - Release pages for a userspace VMA.
  *
  * Release pages locked by a call isp_video_buffer_prepare_user and free the
@@ -181,10 +166,9 @@ static void isp_video_buffer_cleanup(struct 
isp_video_buffer *buf)
  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
dma_unmap_sg_attrs(buf->queue->dev, buf->sgt.sgl,
   buf->sgt.orig_nents, direction, &attrs);
+   sg_free_table(&buf->sgt);
}
 
-   sg_free_table(&buf->sgt);
-
if (buf->pages != NULL) {
isp_video_buffer_lock_vma(buf, 0);
 
@@ -400,7 +384,7 @@ done:
  *
  * - validating VMAs (userspace buffers only)
  * - locking pages and VMAs into memory (userspace buffers only)
- * - building page and scatter-gather lists
+ * - building page and scatter-gather lists (userspace buffers only)
  * - mapping buffers for DMA operation
  * - performing driver-specific preparation
  *
@@ -416,9 +400,7 @@ static int isp_video_buffer_prepare(struct isp_video_buffer 
*buf)
 
switch (buf->vbuf.memory) {
case V4L2_MEMORY_MMAP:
-   ret = isp_video_buffer_prepare_kernel(buf);
-   if (ret < 0)
-   goto done;
+   ret = 0;
break;
 
case V4L2_MEMORY_USERPTR:
diff --git a/drivers/media/platform/omap3isp/ispqueue.h 
b/drivers/media/platform/omap3isp/ispqueue.h
index ae4acb9..27189bb 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -70,8 +70,8 @@ enum isp_video_buffer_state {
  * @vaddr: Memory virtual address (for kernel buffers)
  * @vm_flags: Buffer VMA flags (for userspace buffers)
  * @npages: Number of pages (for userspace buffers)
+ * @sgt: Scatter gather table (for userspace buffers)
  * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
- * @sgt: Scatter gather table
  * @vbuf: V4L2 buffer
  * @irqlist: List head for insertion into IRQ queue
  * @state: Current buffer state
@@ -90,11 +90,11 @@ struct isp_video_buffer {
/* For userspace buffers. */
vm_flags_t vm_flags;
unsigned int npages;
-   struct page **pages;
-
-   /* For all buffers. */
struct sg_table sgt;
 
+   /* For non-VM_PFNMAP userspace buffers. */
+   struct page **pages;
+
/* Touched by the interrupt handler. */
struct v4l2_buffer vbuf;
struct list_head irqlist;
-- 
1.8.3.2

--
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 21/25] omap3isp: Move queue irqlock to isp_video structure

2014-04-03 Thread Laurent Pinchart
This prepares for the move to videobuf2.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/isp.c  |  6 +++---
 drivers/media/platform/omap3isp/ispqueue.c | 13 +
 drivers/media/platform/omap3isp/ispqueue.h |  5 +
 drivers/media/platform/omap3isp/ispvideo.c | 21 +
 drivers/media/platform/omap3isp/ispvideo.h |  1 +
 5 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/drivers/media/platform/omap3isp/isp.c 
b/drivers/media/platform/omap3isp/isp.c
index af8bd21..4395027 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -1399,14 +1399,14 @@ int omap3isp_module_sync_idle(struct media_entity *me, 
wait_queue_head_t *wait,
if (isp_pipeline_is_last(me)) {
struct isp_video *video = pipe->output;
unsigned long flags;
-   spin_lock_irqsave(&video->queue->irqlock, flags);
+   spin_lock_irqsave(&video->irqlock, flags);
if (video->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
-   spin_unlock_irqrestore(&video->queue->irqlock, flags);
+   spin_unlock_irqrestore(&video->irqlock, flags);
atomic_set(stopping, 0);
smp_mb();
return 0;
}
-   spin_unlock_irqrestore(&video->queue->irqlock, flags);
+   spin_unlock_irqrestore(&video->irqlock, flags);
if (!wait_event_timeout(*wait, !atomic_read(stopping),
msecs_to_jiffies(1000))) {
atomic_set(stopping, 0);
diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index dcd9446..77afb63 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -660,7 +660,6 @@ int omap3isp_video_queue_init(struct isp_video_queue *queue,
  struct device *dev, unsigned int bufsize)
 {
INIT_LIST_HEAD(&queue->queue);
-   spin_lock_init(&queue->irqlock);
 
queue->type = type;
queue->ops = ops;
@@ -761,7 +760,6 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
  struct v4l2_buffer *vbuf)
 {
struct isp_video_buffer *buf;
-   unsigned long flags;
int ret;
 
if (vbuf->type != queue->type)
@@ -801,11 +799,8 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue 
*queue,
buf->state = ISP_BUF_STATE_QUEUED;
list_add_tail(&buf->stream, &queue->queue);
 
-   if (queue->streaming) {
-   spin_lock_irqsave(&queue->irqlock, flags);
+   if (queue->streaming)
queue->ops->buffer_queue(buf);
-   spin_unlock_irqrestore(&queue->irqlock, flags);
-   }
 
return 0;
 }
@@ -862,17 +857,14 @@ int omap3isp_video_queue_dqbuf(struct isp_video_queue 
*queue,
 int omap3isp_video_queue_streamon(struct isp_video_queue *queue)
 {
struct isp_video_buffer *buf;
-   unsigned long flags;
 
if (queue->streaming)
return 0;
 
queue->streaming = 1;
 
-   spin_lock_irqsave(&queue->irqlock, flags);
list_for_each_entry(buf, &queue->queue, stream)
queue->ops->buffer_queue(buf);
-   spin_unlock_irqrestore(&queue->irqlock, flags);
 
return 0;
 }
@@ -890,7 +882,6 @@ int omap3isp_video_queue_streamon(struct isp_video_queue 
*queue)
 void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
 {
struct isp_video_buffer *buf;
-   unsigned long flags;
unsigned int i;
 
if (!queue->streaming)
@@ -898,7 +889,6 @@ void omap3isp_video_queue_streamoff(struct isp_video_queue 
*queue)
 
queue->streaming = 0;
 
-   spin_lock_irqsave(&queue->irqlock, flags);
for (i = 0; i < queue->count; ++i) {
buf = queue->buffers[i];
 
@@ -907,7 +897,6 @@ void omap3isp_video_queue_streamoff(struct isp_video_queue 
*queue)
 
buf->state = ISP_BUF_STATE_IDLE;
}
-   spin_unlock_irqrestore(&queue->irqlock, flags);
 
INIT_LIST_HEAD(&queue->queue);
 }
diff --git a/drivers/media/platform/omap3isp/ispqueue.h 
b/drivers/media/platform/omap3isp/ispqueue.h
index ecff055..ecf3309 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -114,8 +114,7 @@ struct isp_video_buffer {
  * the userspace memory address for a USERPTR buffer, with the queue lock
  * held. Drivers should perform device-specific buffer preparation (such as
  * mapping the buffer memory in an IOMMU). This operation is optional.
- * @buffer_queue: Called when a buffer is being added to the queue with the
- * queue irqlock spinlock held.
+ * @buffer_queue: Called when a buffer is being added.
  */
 struct isp_video_queue_operations {
void (*queue_p

[PATCH 07/25] omap3isp: ccdc: Use the DMA API for LSC

2014-04-03 Thread Laurent Pinchart
Replace the OMAP-specific IOMMU API usage by the DMA API for LSC. The
table is now allocated using dma_alloc_coherent() and the related sg
table is retrieved using dma_get_sgtable() for sync operations.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispccdc.c | 52 ++-
 drivers/media/platform/omap3isp/ispccdc.h |  8 +++--
 2 files changed, 29 insertions(+), 31 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispccdc.c 
b/drivers/media/platform/omap3isp/ispccdc.c
index 4d920c8..a907b20 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -206,7 +206,8 @@ static int ccdc_lsc_validate_config(struct isp_ccdc_device 
*ccdc,
  * ccdc_lsc_program_table - Program Lens Shading Compensation table address.
  * @ccdc: Pointer to ISP CCDC device.
  */
-static void ccdc_lsc_program_table(struct isp_ccdc_device *ccdc, u32 addr)
+static void ccdc_lsc_program_table(struct isp_ccdc_device *ccdc,
+  dma_addr_t addr)
 {
isp_reg_writel(to_isp_device(ccdc), addr,
   OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
@@ -333,7 +334,7 @@ static int __ccdc_lsc_configure(struct isp_ccdc_device 
*ccdc,
return -EBUSY;
 
ccdc_lsc_setup_regs(ccdc, &req->config);
-   ccdc_lsc_program_table(ccdc, req->table);
+   ccdc_lsc_program_table(ccdc, req->table.dma);
return 0;
 }
 
@@ -368,11 +369,12 @@ static void ccdc_lsc_free_request(struct isp_ccdc_device 
*ccdc,
if (req == NULL)
return;
 
-   if (req->iovm)
-   dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
-req->iovm->sgt->nents, DMA_TO_DEVICE);
-   if (req->table)
-   omap_iommu_vfree(isp->domain, isp->dev, req->table);
+   if (req->table.addr) {
+   sg_free_table(&req->table.sgt);
+   dma_free_coherent(isp->dev, req->config.size, req->table.addr,
+ req->table.dma);
+   }
+
kfree(req);
 }
 
@@ -416,7 +418,6 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
struct isp_device *isp = to_isp_device(ccdc);
struct ispccdc_lsc_config_req *req;
unsigned long flags;
-   void *table;
u16 update;
int ret;
 
@@ -444,38 +445,31 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
 
req->enable = 1;
 
-   req->table = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
-   req->config.size, IOMMU_FLAG);
-   if (IS_ERR_VALUE(req->table)) {
-   req->table = 0;
-   ret = -ENOMEM;
-   goto done;
-   }
-
-   req->iovm = omap_find_iovm_area(isp->dev, req->table);
-   if (req->iovm == NULL) {
+   req->table.addr = dma_alloc_coherent(isp->dev, req->config.size,
+&req->table.dma,
+GFP_KERNEL);
+   if (req->table.addr == NULL) {
ret = -ENOMEM;
goto done;
}
 
-   if (!dma_map_sg(isp->dev, req->iovm->sgt->sgl,
-   req->iovm->sgt->nents, DMA_TO_DEVICE)) {
-   ret = -ENOMEM;
-   req->iovm = NULL;
+   ret = dma_get_sgtable(isp->dev, &req->table.sgt,
+ req->table.addr, req->table.dma,
+ req->config.size);
+   if (ret < 0)
goto done;
-   }
 
-   dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl,
-   req->iovm->sgt->nents, DMA_TO_DEVICE);
+   dma_sync_sg_for_cpu(isp->dev, req->table.sgt.sgl,
+   req->table.sgt.nents, DMA_TO_DEVICE);
 
-   table = omap_da_to_va(isp->dev, req->table);
-   if (copy_from_user(table, config->lsc, req->config.size)) {
+   if (copy_from_user(req->table.addr, config->lsc,
+  req->config.size)) {
ret = -EFAULT;
goto done;
}
 
-   dma_sync_sg_for_device(isp->dev, req->iovm->sgt->sgl,
-  req->iovm->sgt->nents, DMA_TO_DEVICE);
+   dma_sync_sg_for_device(isp->dev, req->table.sgt.sgl,
+  req->table.sgt.nents, DMA_TO_DEVICE);
}
 
spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
diff --git a/drivers/media/platform/omap3isp/ispccdc.h 
b/drivers/media/platform/omap3isp/ispccdc.h
index 9d24e41..20db3a0 100644
--- a/drivers/media/platform/omap3isp/ispccdc.h
+++ b/drivers/media/platform/omap3isp/ispccdc.h
@@ -5

[PATCH 04/25] omap3isp: stat: Merge dma_addr and iommu_addr fields

2014-04-03 Thread Laurent Pinchart
The fields store buffer addresses as seen from the device. The first one
is used with an external DMA engine while the second one is used with
the ISP DMA engine. As they're never used together, merge them.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/isph3a_aewb.c |  2 +-
 drivers/media/platform/omap3isp/isph3a_af.c   |  2 +-
 drivers/media/platform/omap3isp/ispstat.c | 21 +
 drivers/media/platform/omap3isp/ispstat.h |  1 -
 4 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/drivers/media/platform/omap3isp/isph3a_aewb.c 
b/drivers/media/platform/omap3isp/isph3a_aewb.c
index 75fd82b..d6811ce 100644
--- a/drivers/media/platform/omap3isp/isph3a_aewb.c
+++ b/drivers/media/platform/omap3isp/isph3a_aewb.c
@@ -47,7 +47,7 @@ static void h3a_aewb_setup_regs(struct ispstat *aewb, void 
*priv)
if (aewb->state == ISPSTAT_DISABLED)
return;
 
-   isp_reg_writel(aewb->isp, aewb->active_buf->iommu_addr,
+   isp_reg_writel(aewb->isp, aewb->active_buf->dma_addr,
   OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST);
 
if (!aewb->update)
diff --git a/drivers/media/platform/omap3isp/isph3a_af.c 
b/drivers/media/platform/omap3isp/isph3a_af.c
index a0bf5af..6fc960c 100644
--- a/drivers/media/platform/omap3isp/isph3a_af.c
+++ b/drivers/media/platform/omap3isp/isph3a_af.c
@@ -51,7 +51,7 @@ static void h3a_af_setup_regs(struct ispstat *af, void *priv)
if (af->state == ISPSTAT_DISABLED)
return;
 
-   isp_reg_writel(af->isp, af->active_buf->iommu_addr, OMAP3_ISP_IOMEM_H3A,
+   isp_reg_writel(af->isp, af->active_buf->dma_addr, OMAP3_ISP_IOMEM_H3A,
   ISPH3A_AFBUFST);
 
if (!af->update)
diff --git a/drivers/media/platform/omap3isp/ispstat.c 
b/drivers/media/platform/omap3isp/ispstat.c
index b1eb902..dba713f 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -361,21 +361,19 @@ static void isp_stat_bufs_free(struct ispstat *stat)
struct ispstat_buffer *buf = &stat->buf[i];
 
if (!ISP_STAT_USES_DMAENGINE(stat)) {
-   if (IS_ERR_OR_NULL((void *)buf->iommu_addr))
+   if (IS_ERR_OR_NULL((void *)buf->dma_addr))
continue;
if (buf->iovm)
dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
 buf->iovm->sgt->nents,
 DMA_FROM_DEVICE);
-   omap_iommu_vfree(isp->domain, isp->dev,
-   buf->iommu_addr);
+   omap_iommu_vfree(isp->domain, isp->dev, buf->dma_addr);
} else {
if (!buf->virt_addr)
continue;
dma_free_coherent(stat->isp->dev, stat->buf_alloc_size,
  buf->virt_addr, buf->dma_addr);
}
-   buf->iommu_addr = 0;
buf->iovm = NULL;
buf->dma_addr = 0;
buf->virt_addr = NULL;
@@ -396,12 +394,12 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat,
struct isp_device *isp = stat->isp;
struct iovm_struct *iovm;
 
-   buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
-   size, IOMMU_FLAG);
-   if (IS_ERR((void *)buf->iommu_addr))
+   buf->dma_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
+  size, IOMMU_FLAG);
+   if (IS_ERR_VALUE(buf->dma_addr))
return -ENOMEM;
 
-   iovm = omap_find_iovm_area(isp->dev, buf->iommu_addr);
+   iovm = omap_find_iovm_area(isp->dev, buf->dma_addr);
if (!iovm)
return -ENOMEM;
 
@@ -410,8 +408,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat,
return -ENOMEM;
 
buf->iovm = iovm;
-   buf->virt_addr = omap_da_to_va(stat->isp->dev,
- (u32)buf->iommu_addr);
+   buf->virt_addr = omap_da_to_va(stat->isp->dev, buf->dma_addr);
 
return 0;
 }
@@ -478,8 +475,8 @@ static int isp_stat_bufs_alloc(struct ispstat *stat, u32 
size)
buf->empty = 1;
 
dev_dbg(stat->isp->dev,
-   "%s: buffer[%u] allocated. iommu=0x%08lx dma=0x%08lx 
virt=0x%08lx",
-   stat->subdev.name, i, buf->iommu_addr,
+   "%s: buffer[%u] allocated. dma=0x%08lx virt=0x%08lx",
+   stat->subdev.name, i,
(unsigned long)buf->dma_addr,
(unsigned long)buf->virt_addr);
}
diff --git a/drivers/media/platform/omap3isp/ispstat.h 
b/drivers/media/platform/omap3isp/ispstat.h
index 9a047c9..8e768

[PATCH 17/25] omap3isp: queue: Use sg_alloc_table_from_pages()

2014-04-03 Thread Laurent Pinchart
Replace the custom implementation with a call to the scatterlist helper
function.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.c | 16 ++--
 1 file changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index 4a271c7..cee1b5d 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -233,12 +233,10 @@ static void isp_video_buffer_cleanup(struct 
isp_video_buffer *buf)
  */
 static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
 {
-   struct scatterlist *sg;
unsigned int offset;
unsigned long data;
unsigned int first;
unsigned int last;
-   unsigned int i;
int ret;
 
data = buf->vbuf.m.userptr;
@@ -267,21 +265,11 @@ static int isp_video_buffer_prepare_user(struct 
isp_video_buffer *buf)
if (ret < 0)
return ret;
 
-   ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
+   ret = sg_alloc_table_from_pages(&buf->sgt, buf->pages, buf->npages,
+   offset, buf->vbuf.length, GFP_KERNEL);
if (ret < 0)
return ret;
 
-   for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i) {
-   if (PageHighMem(buf->pages[i])) {
-   sg_free_table(&buf->sgt);
-   return -EINVAL;
-   }
-
-   sg_set_page(sg, buf->pages[i], PAGE_SIZE - offset, offset);
-   sg = sg_next(sg);
-   offset = 0;
-   }
-
return 0;
 }
 
-- 
1.8.3.2

--
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 08/25] omap3isp: ccdc: Use the DMA API for FPC

2014-04-03 Thread Laurent Pinchart
Replace the OMAP-specific IOMMU API usage by the DMA API for FPC. The
table is now allocated using dma_alloc_coherent() and the related sg
table is retrieved using dma_get_sgtable() for sync operations.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispccdc.c | 51 +--
 drivers/media/platform/omap3isp/ispccdc.h |  8 -
 2 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispccdc.c 
b/drivers/media/platform/omap3isp/ispccdc.c
index a907b20..004a4f5 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -30,7 +30,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -578,7 +577,7 @@ static void ccdc_configure_fpc(struct isp_ccdc_device *ccdc)
if (!ccdc->fpc_en)
return;
 
-   isp_reg_writel(isp, ccdc->fpc.fpcaddr, OMAP3_ISP_IOMEM_CCDC,
+   isp_reg_writel(isp, ccdc->fpc.dma, OMAP3_ISP_IOMEM_CCDC,
   ISPCCDC_FPC_ADDR);
/* The FPNUM field must be set before enabling FPC. */
isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
@@ -718,8 +717,9 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
ccdc->shadow_update = 0;
 
if (OMAP3ISP_CCDC_FPC & ccdc_struct->update) {
-   u32 table_old = 0;
-   u32 table_new;
+   struct omap3isp_ccdc_fpc fpc;
+   struct ispccdc_fpc fpc_old = { .addr = NULL, };
+   struct ispccdc_fpc fpc_new;
u32 size;
 
if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED)
@@ -728,35 +728,39 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
ccdc->fpc_en = !!(OMAP3ISP_CCDC_FPC & ccdc_struct->flag);
 
if (ccdc->fpc_en) {
-   if (copy_from_user(&ccdc->fpc, ccdc_struct->fpc,
-  sizeof(ccdc->fpc)))
+   if (copy_from_user(&fpc, ccdc_struct->fpc, sizeof(fpc)))
return -EFAULT;
 
+   size = fpc.fpnum * 4;
+
/*
-* table_new must be 64-bytes aligned, but it's
-* already done by omap_iommu_vmalloc().
+* The table address must be 64-bytes aligned, which is
+* guaranteed by dma_alloc_coherent().
 */
-   size = ccdc->fpc.fpnum * 4;
-   table_new = omap_iommu_vmalloc(isp->domain, isp->dev,
-   0, size, IOMMU_FLAG);
-   if (IS_ERR_VALUE(table_new))
+   fpc_new.fpnum = fpc.fpnum;
+   fpc_new.addr = dma_alloc_coherent(isp->dev, size,
+ &fpc_new.dma,
+ GFP_KERNEL);
+   if (fpc_new.addr == NULL)
return -ENOMEM;
 
-   if (copy_from_user(omap_da_to_va(isp->dev, table_new),
-  (__force void __user *)
-  ccdc->fpc.fpcaddr, size)) {
-   omap_iommu_vfree(isp->domain, isp->dev,
-   table_new);
+   if (copy_from_user(fpc_new.addr,
+  (__force void __user *)fpc.fpcaddr,
+  size)) {
+   dma_free_coherent(isp->dev, size, fpc_new.addr,
+ fpc_new.dma);
return -EFAULT;
}
 
-   table_old = ccdc->fpc.fpcaddr;
-   ccdc->fpc.fpcaddr = table_new;
+   fpc_old = ccdc->fpc;
+   ccdc->fpc = fpc_new;
}
 
ccdc_configure_fpc(ccdc);
-   if (table_old != 0)
-   omap_iommu_vfree(isp->domain, isp->dev, table_old);
+
+   if (fpc_old.addr != NULL)
+   dma_free_coherent(isp->dev, fpc_old.fpnum * 4,
+ fpc_old.addr, fpc_old.dma);
}
 
return ccdc_lsc_config(ccdc, ccdc_struct);
@@ -2574,8 +2578,9 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp)
cancel_work_sync(&ccdc->lsc.table_work);
ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
 
-   if (ccdc->fpc.fpcaddr != 0)
-   omap_iommu_vfree(isp->domain, isp->dev, ccdc->fpc.fpcaddr);
+   if (ccdc->fpc.addr != NULL)
+   dma_free_coherent(isp->dev, ccdc->fpc.fpnum * 4, ccdc->fpc.addr,
+ ccdc->fpc.dma);
 

[PATCH 09/25] omap3isp: video: Set the buffer bytesused field at completion time

2014-04-03 Thread Laurent Pinchart
The v4l buffer bytesused field is a value that will be returned to
userspace when the buffer gets dequeued. As such it doesn't need to be
set early at buffer queue time. Move the assignment to buffer completion
in the omap3isp_video_buffer_next() function to prepare for the video
buffers queue refactoring.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispvideo.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/omap3isp/ispvideo.c 
b/drivers/media/platform/omap3isp/ispvideo.c
index 85b4036..e0f594f3 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -431,7 +431,6 @@ static int isp_video_buffer_prepare(struct isp_video_buffer 
*buf)
return -EINVAL;
}
 
-   buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
buffer->isp_addr = addr;
return 0;
 }
@@ -514,6 +513,8 @@ struct isp_buffer *omap3isp_video_buffer_next(struct 
isp_video *video)
 {
struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
struct isp_video_queue *queue = video->queue;
+   struct isp_video_fh *vfh =
+   container_of(queue, struct isp_video_fh, queue);
enum isp_pipeline_state state;
struct isp_video_buffer *buf;
unsigned long flags;
@@ -530,6 +531,8 @@ struct isp_buffer *omap3isp_video_buffer_next(struct 
isp_video *video)
list_del(&buf->irqlist);
spin_unlock_irqrestore(&queue->irqlock, flags);
 
+   buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
+
ktime_get_ts(&ts);
buf->vbuf.timestamp.tv_sec = ts.tv_sec;
buf->vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
-- 
1.8.3.2

--
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 16/25] omap3isp: queue: Map PFNMAP buffers to device

2014-04-03 Thread Laurent Pinchart
Userspace PFNMAP buffers need to be mapped to the device like the
userspace non-PFNMAP buffers in order for the DMA mapping implementation
to create IOMMU mappings when we'll switch to the IOMMU-aware DMA
mapping backend.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.c | 37 +-
 drivers/media/platform/omap3isp/ispqueue.h |  4 ++--
 2 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index 479d348..4a271c7 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -173,6 +173,7 @@ static void isp_video_buffer_cleanup(struct 
isp_video_buffer *buf)
struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
struct isp_video *video = vfh->video;
enum dma_data_direction direction;
+   DEFINE_DMA_ATTRS(attrs);
unsigned int i;
 
if (buf->dma) {
@@ -181,11 +182,14 @@ static void isp_video_buffer_cleanup(struct 
isp_video_buffer *buf)
buf->dma = 0;
}
 
-   if (!(buf->vm_flags & VM_PFNMAP)) {
+   if (buf->vbuf.memory == V4L2_MEMORY_USERPTR) {
+   if (buf->skip_cache)
+   dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
+
direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-   dma_unmap_sg(buf->queue->dev, buf->sgt.sgl, buf->sgt.orig_nents,
-direction);
+   dma_unmap_sg_attrs(buf->queue->dev, buf->sgt.sgl,
+  buf->sgt.orig_nents, direction, &attrs);
}
 
sg_free_table(&buf->sgt);
@@ -345,10 +349,6 @@ unlock:
 
for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i, ++pfn) {
sg_set_page(sg, pfn_to_page(pfn), PAGE_SIZE - offset, offset);
-   /* PFNMAP buffers will not get DMA-mapped, set the DMA address
-* manually.
-*/
-   sg_dma_address(sg) = (pfn << PAGE_SHIFT) + offset;
sg = sg_next(sg);
offset = 0;
}
@@ -434,12 +434,15 @@ static int isp_video_buffer_prepare(struct 
isp_video_buffer *buf)
struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
struct isp_video *video = vfh->video;
enum dma_data_direction direction;
+   DEFINE_DMA_ATTRS(attrs);
unsigned long addr;
int ret;
 
switch (buf->vbuf.memory) {
case V4L2_MEMORY_MMAP:
ret = isp_video_buffer_prepare_kernel(buf);
+   if (ret < 0)
+   goto done;
break;
 
case V4L2_MEMORY_USERPTR:
@@ -451,24 +454,26 @@ static int isp_video_buffer_prepare(struct 
isp_video_buffer *buf)
ret = isp_video_buffer_prepare_pfnmap(buf);
else
ret = isp_video_buffer_prepare_user(buf);
-   break;
 
-   default:
-   return -EINVAL;
-   }
+   if (ret < 0)
+   goto done;
 
-   if (ret < 0)
-   goto done;
+   if (buf->skip_cache)
+   dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 
-   if (!(buf->vm_flags & VM_PFNMAP)) {
direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-   ret = dma_map_sg(buf->queue->dev, buf->sgt.sgl,
-buf->sgt.orig_nents, direction);
+   ret = dma_map_sg_attrs(buf->queue->dev, buf->sgt.sgl,
+  buf->sgt.orig_nents, direction, &attrs);
if (ret <= 0) {
ret = -EFAULT;
goto done;
}
+
+   break;
+
+   default:
+   return -EINVAL;
}
 
addr = omap_iommu_vmap(video->isp->domain, video->isp->dev, 0,
diff --git a/drivers/media/platform/omap3isp/ispqueue.h 
b/drivers/media/platform/omap3isp/ispqueue.h
index e03af74..d580f58 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -72,7 +72,7 @@ enum isp_video_buffer_state {
  * @vm_flags: Buffer VMA flags (for userspace buffers)
  * @npages: Number of pages (for userspace buffers)
  * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
- * @sgt: Scatter gather table (for non-VM_PFNMAP buffers)
+ * @sgt: Scatter gather table
  * @vbuf: V4L2 buffer
  * @irqlist: List head for insertion into IRQ queue
  * @state: Current buffer state
@@ -94,7 +94,7 @@ struct isp_video_buffer {
unsigned int npages;
struct page **pages;
 
-   /* For all buffers except VM_PFNMAP. */
+   /* For all buffers. */
struct sg_table sgt;
 
   

[PATCH 01/25] omap3isp: stat: Rename IS_COHERENT_BUF to ISP_STAT_USES_DMAENGINE

2014-04-03 Thread Laurent Pinchart
The macro is meant to test whether the statistics engine uses an
external DMA engine to transfer data or supports DMA directly. As both
cases will be supported by DMA coherent buffers rename the macro to
ISP_STAT_USES_DMAENGINE for improved clarity.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispstat.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispstat.c 
b/drivers/media/platform/omap3isp/ispstat.c
index 5707f85..48b702a 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -32,7 +32,7 @@
 
 #include "isp.h"
 
-#define IS_COHERENT_BUF(stat)  ((stat)->dma_ch >= 0)
+#define ISP_STAT_USES_DMAENGINE(stat)  ((stat)->dma_ch >= 0)
 
 /*
  * MAGIC_SIZE must always be the greatest common divisor of
@@ -99,7 +99,7 @@ static void isp_stat_buf_sync_magic_for_device(struct ispstat 
*stat,
   u32 buf_size,
   enum dma_data_direction dir)
 {
-   if (IS_COHERENT_BUF(stat))
+   if (ISP_STAT_USES_DMAENGINE(stat))
return;
 
__isp_stat_buf_sync_magic(stat, buf, buf_size, dir,
@@ -111,7 +111,7 @@ static void isp_stat_buf_sync_magic_for_cpu(struct ispstat 
*stat,
u32 buf_size,
enum dma_data_direction dir)
 {
-   if (IS_COHERENT_BUF(stat))
+   if (ISP_STAT_USES_DMAENGINE(stat))
return;
 
__isp_stat_buf_sync_magic(stat, buf, buf_size, dir,
@@ -180,7 +180,7 @@ static void isp_stat_buf_insert_magic(struct ispstat *stat,
 static void isp_stat_buf_sync_for_device(struct ispstat *stat,
 struct ispstat_buffer *buf)
 {
-   if (IS_COHERENT_BUF(stat))
+   if (ISP_STAT_USES_DMAENGINE(stat))
return;
 
dma_sync_sg_for_device(stat->isp->dev, buf->iovm->sgt->sgl,
@@ -190,7 +190,7 @@ static void isp_stat_buf_sync_for_device(struct ispstat 
*stat,
 static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
  struct ispstat_buffer *buf)
 {
-   if (IS_COHERENT_BUF(stat))
+   if (ISP_STAT_USES_DMAENGINE(stat))
return;
 
dma_sync_sg_for_cpu(stat->isp->dev, buf->iovm->sgt->sgl,
@@ -360,7 +360,7 @@ static void isp_stat_bufs_free(struct ispstat *stat)
for (i = 0; i < STAT_MAX_BUFS; i++) {
struct ispstat_buffer *buf = &stat->buf[i];
 
-   if (!IS_COHERENT_BUF(stat)) {
+   if (!ISP_STAT_USES_DMAENGINE(stat)) {
if (IS_ERR_OR_NULL((void *)buf->iommu_addr))
continue;
if (buf->iovm)
@@ -489,7 +489,7 @@ static int isp_stat_bufs_alloc(struct ispstat *stat, u32 
size)
 
isp_stat_bufs_free(stat);
 
-   if (IS_COHERENT_BUF(stat))
+   if (ISP_STAT_USES_DMAENGINE(stat))
return isp_stat_bufs_alloc_dma(stat, size);
else
return isp_stat_bufs_alloc_iommu(stat, size);
-- 
1.8.3.2

--
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 10/25] omap3isp: queue: Move IOMMU handling code to the queue

2014-04-03 Thread Laurent Pinchart
As a preparation for the switch from the OMAP IOMMU API to the DMA API
move all IOMMU handling code from the video node implementation to the
buffers queue implementation.

Signed-off-by: Laurent Pinchart 
---
 drivers/media/platform/omap3isp/ispqueue.c | 78 +-
 drivers/media/platform/omap3isp/ispqueue.h |  6 +--
 drivers/media/platform/omap3isp/ispvideo.c | 77 +
 3 files changed, 78 insertions(+), 83 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c 
b/drivers/media/platform/omap3isp/ispqueue.c
index a5e6585..8623c05 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,7 +34,58 @@
 #include 
 #include 
 
+#include "isp.h"
 #include "ispqueue.h"
+#include "ispvideo.h"
+
+/* 
-
+ * IOMMU management
+ */
+
+#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
+
+/*
+ * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @sglist: Pointer to source Scatter gather list to allocate.
+ * @sglen: Number of elements of the scatter-gatter list.
+ *
+ * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
+ * we ran out of memory.
+ */
+static dma_addr_t
+ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int 
sglen)
+{
+   struct sg_table *sgt;
+   u32 da;
+
+   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+   if (sgt == NULL)
+   return -ENOMEM;
+
+   sgt->sgl = (struct scatterlist *)sglist;
+   sgt->nents = sglen;
+   sgt->orig_nents = sglen;
+
+   da = omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
+   if (IS_ERR_VALUE(da))
+   kfree(sgt);
+
+   return da;
+}
+
+/*
+ * ispmmu_vunmap - Unmap a device address from the ISP MMU
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @da: Device address generated from a ispmmu_vmap call.
+ */
+static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
+{
+   struct sg_table *sgt;
+
+   sgt = omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
+   kfree(sgt);
+}
 
 /* 
-
  * Video buffers management
@@ -260,11 +312,15 @@ static int isp_video_buffer_sglist_pfnmap(struct 
isp_video_buffer *buf)
  */
 static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
 {
+   struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+   struct isp_video *video = vfh->video;
enum dma_data_direction direction;
unsigned int i;
 
-   if (buf->queue->ops->buffer_cleanup)
-   buf->queue->ops->buffer_cleanup(buf);
+   if (buf->dma) {
+   ispmmu_vunmap(video->isp, buf->dma);
+   buf->dma = 0;
+   }
 
if (!(buf->vm_flags & VM_PFNMAP)) {
direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
@@ -479,7 +535,10 @@ done:
  */
 static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 {
+   struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+   struct isp_video *video = vfh->video;
enum dma_data_direction direction;
+   unsigned long addr;
int ret;
 
switch (buf->vbuf.memory) {
@@ -525,6 +584,21 @@ static int isp_video_buffer_prepare(struct 
isp_video_buffer *buf)
}
}
 
+   addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen);
+   if (IS_ERR_VALUE(addr)) {
+   ret = -EIO;
+   goto done;
+   }
+
+   buf->dma = addr;
+
+   if (!IS_ALIGNED(addr, 32)) {
+   dev_dbg(video->isp->dev,
+   "Buffer address must be aligned to 32 bytes 
boundary.\n");
+   ret = -EINVAL;
+   goto done;
+   }
+
if (buf->queue->ops->buffer_prepare)
ret = buf->queue->ops->buffer_prepare(buf);
 
diff --git a/drivers/media/platform/omap3isp/ispqueue.h 
b/drivers/media/platform/omap3isp/ispqueue.h
index 3e048ad..0899a11 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -106,6 +106,7 @@ struct isp_video_buffer {
struct list_head irqlist;
enum isp_video_buffer_state state;
wait_queue_head_t wait;
+   dma_addr_t dma;
 };
 
 #define to_isp_video_buffer(vb)container_of(vb, struct 
isp_video_buffer, vb)
@@ -121,17 +122,12 @@ struct isp_video_buffer {
  * mapping the buffer memory in an IOMMU). This operation is optional.
  * @buffer_queue: Called when a buffer is being added to the queue with the
  * queue irqlock spinlock held.
- * @buffer_cleanup: Called before freeing buffers, or before changing the
- * usersp

Re: AW: v4l2_buffer with PBO mapped memory

2014-04-03 Thread Laurent Pinchart
Hi Thomas,

On Thursday 03 April 2014 16:52:19 Scheuermann, Mail wrote:
> Hi Laurent,
> 
> the driver my device uses is the uvcvideo. I have the kernel 3.11.0-18 from
> Ubuntu 13.10 running. It is built in in a Thinkpad X240 notebook.

OK. A bit of debugging will then be needed. Could you set the videobuf2-core 
debug parameter to 3, retry your test case and send us the kernel log ?

-- 
Regards,

Laurent Pinchart

--
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: Lirc codec and starting "space" event

2014-04-03 Thread Austin Lund
On 1 April 2014 10:04, Austin Lund  wrote:
> Hi,
>
> I've been having a problem with a GPIO ir device in an i.mx6 arm
> system that I have (cubox-i).
>
> It seems to all work ok, except the output on /dev/lirc0 is not quite
> what lircd seems to expect.  Lircd wants a long space before the
> starting pulse before processing any output. However, no long space is
> sent when I check the output (doing "mode2" and a plain hexdump
> /dev/lirc0).
>
> This causes problems in detecting button presses on remotes.
> Sometimes it works if you press the buttons quick enough, but after
> waiting a while it doesn't work.
>
> I have been looking at the code for a while now, and it seems that it
> has something to do with the lirc codec ignoring reset events (just
> returns 0).
>
> I've made up this patch, but I'm travelling at the moment and haven't
> had a chance to actually test it.
>
> What I'm wondering is if this issue is known, and if my approach is
> going down the right path.
>
> The only alternative I could see is to change the way the gpio ir
> driver handles events.  It seems to just call ir_raw_event_store_edge
> which put a zeroed reset event into the queue.  I'm assuming there are
> other users of these functions and that it's probably best not to
> fiddle with that if possible.
>
> Thanks.
>
> PS Please CC me as I'm not subscribed.

Just a note that I have tested this patch now and it works.  No idea
what impact it might have on other users.
--
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 05/11] rc-core: split dev->s_filter

2014-04-03 Thread James Hogan
Hi David,

On Saturday 29 March 2014 17:11:11 David Härdeman wrote:
> Overloading dev->s_filter to do two different functions (set wakeup filters
> and generic hardware filters) makes it impossible to tell what the
> hardware actually supports, so create a separate dev->s_wakeup_filter and
> make the distinction explicit.
> 
> Signed-off-by: David Härdeman 
> ---

> @@ -1121,9 +1126,11 @@ static ssize_t store_filter(struct device *device,
>   if (ret < 0)
>   return ret;
> 
> - /* Scancode filter not supported (but still accept 0) */
> - if (!dev->s_filter && fattr->type != RC_FILTER_NORMAL)
> - return val ? -EINVAL : count;
> + /* Can the scancode filter be set? */
> + set_filter = (fattr->type == RC_FILTER_NORMAL)
> + ? dev->s_filter : dev->s_wakeup_filter;
> + if (!set_filter)
> + return -EINVAL;

Technically the removal of the "fattr->type != RC_FILTER_NORMAL" condition and 
returning -EINVAL rather than "val ? -EINVAL : count" should be in patch 6 
since it's for generic scancode filter support.


> - if (dev->s_filter) {
> - ret = dev->s_filter(dev, fattr->type, &local_filter);
> - if (ret < 0)
> - goto unlock;
> - }
> +
> + ret = set_filter(dev, &local_filter);
> + if (ret < 0)
> + goto unlock;

same here for removing the if condition.

Otherwise this patch looks okay to me.

Cheers
James

signature.asc
Description: This is a digitally signed message part.


[PATCH] omap4iss: Remove VIDEO_OMAP4_DEBUG Kconfig option

2014-04-03 Thread Laurent Pinchart
The option was supposed to control the definition of the DEBUG macro in
the Makefile but has been left unused by mistake. Given that debugging
should be enabled using dynamic printk, remote the Kconfig option.

Signed-off-by: Laurent Pinchart 
---
 drivers/staging/media/omap4iss/Kconfig | 6 --
 drivers/staging/media/omap4iss/iss.c   | 6 +++---
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/media/omap4iss/Kconfig 
b/drivers/staging/media/omap4iss/Kconfig
index b9fe753..78b0fba 100644
--- a/drivers/staging/media/omap4iss/Kconfig
+++ b/drivers/staging/media/omap4iss/Kconfig
@@ -4,9 +4,3 @@ config VIDEO_OMAP4
select VIDEOBUF2_DMA_CONTIG
---help---
  Driver for an OMAP 4 ISS controller.
-
-config VIDEO_OMAP4_DEBUG
-   bool "OMAP 4 Camera debug messages"
-   depends on VIDEO_OMAP4
-   ---help---
- Enable debug messages on OMAP 4 ISS controller driver.
diff --git a/drivers/staging/media/omap4iss/iss.c 
b/drivers/staging/media/omap4iss/iss.c
index 61fbfcd..219519d 100644
--- a/drivers/staging/media/omap4iss/iss.c
+++ b/drivers/staging/media/omap4iss/iss.c
@@ -204,7 +204,7 @@ void omap4iss_configure_bridge(struct iss_device *iss,
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, isp5ctrl_val);
 }
 
-#if defined(DEBUG) && defined(ISS_ISR_DEBUG)
+#ifdef ISS_ISR_DEBUG
 static void iss_isr_dbg(struct iss_device *iss, u32 irqstatus)
 {
static const char * const name[] = {
@@ -347,14 +347,14 @@ static irqreturn_t iss_isr(int irq, void *_iss)
omap4iss_resizer_isr(&iss->resizer,
 isp_irqstatus & resizer_events);
 
-#if defined(DEBUG) && defined(ISS_ISR_DEBUG)
+#ifdef ISS_ISR_DEBUG
iss_isp_isr_dbg(iss, isp_irqstatus);
 #endif
}
 
omap4iss_flush(iss);
 
-#if defined(DEBUG) && defined(ISS_ISR_DEBUG)
+#ifdef ISS_ISR_DEBUG
iss_isr_dbg(iss, irqstatus);
 #endif
 
-- 
Regards,

Laurent Pinchart

--
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] omap4iss: Add missing white space

2014-04-03 Thread Laurent Pinchart
The error was reported by checkpatch.pl. Fix it.

Signed-off-by: Laurent Pinchart 
---
 drivers/staging/media/omap4iss/iss_video.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/omap4iss/iss_video.h 
b/drivers/staging/media/omap4iss/iss_video.h
index 878e4a3..9dccdb1 100644
--- a/drivers/staging/media/omap4iss/iss_video.h
+++ b/drivers/staging/media/omap4iss/iss_video.h
@@ -140,7 +140,7 @@ enum iss_video_dmaqueue_flags {
  * if there was no buffer previously queued.
  */
 struct iss_video_operations {
-   int(*queue)(struct iss_video *video, struct iss_buffer *buffer);
+   int (*queue)(struct iss_video *video, struct iss_buffer *buffer);
 };
 
 struct iss_video {
-- 
Regards,

Laurent Pinchart

--
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 05/49] rc-core: split dev->s_filter

2014-04-03 Thread David Härdeman
Overloading dev->s_filter to do two different functions (set wakeup filters
and generic hardware filters) makes it impossible to tell what the
hardware actually supports, so create a separate dev->s_wakeup_filter and
make the distinction explicit.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/img-ir/img-ir-hw.c |   15 ++-
 drivers/media/rc/rc-main.c  |   31 +++
 include/media/rc-core.h |6 --
 3 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/drivers/media/rc/img-ir/img-ir-hw.c 
b/drivers/media/rc/img-ir/img-ir-hw.c
index aec79f7..871a9b3 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -504,6 +504,18 @@ unlock:
return ret;
 }
 
+static int img_ir_set_normal_filter(struct rc_dev *dev,
+   struct rc_scancode_filter *sc_filter)
+{
+   return img_ir_set_filter(dev, RC_FILTER_NORMAL, sc_filter); 
+}
+
+static int img_ir_set_wakeup_filter(struct rc_dev *dev,
+   struct rc_scancode_filter *sc_filter)
+{
+   return img_ir_set_filter(dev, RC_FILTER_WAKEUP, sc_filter);
+}
+
 /**
  * img_ir_set_decoder() - Set the current decoder.
  * @priv:  IR private data.
@@ -988,7 +1000,8 @@ int img_ir_probe_hw(struct img_ir_priv *priv)
rdev->map_name = RC_MAP_EMPTY;
rc_set_allowed_protocols(rdev, img_ir_allowed_protos(priv));
rdev->input_name = "IMG Infrared Decoder";
-   rdev->s_filter = img_ir_set_filter;
+   rdev->s_filter = img_ir_set_normal_filter;
+   rdev->s_wakeup_filter = img_ir_set_wakeup_filter;
 
/* Register hardware decoder */
error = rc_register_device(rdev);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index c0bfd50..ba955ac 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -929,6 +929,7 @@ static ssize_t store_protocols(struct device *device,
int rc, i, count = 0;
ssize_t ret;
int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
+   int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter 
*filter);
struct rc_scancode_filter local_filter, *filter;
 
/* Device is being removed */
@@ -1013,24 +1014,27 @@ static ssize_t store_protocols(struct device *device,
 * Fall back to clearing the filter.
 */
filter = &dev->scancode_filters[fattr->type];
+   set_filter = (fattr->type == RC_FILTER_NORMAL)
+   ? dev->s_filter : dev->s_wakeup_filter;
+
if (old_type != type && filter->mask) {
local_filter = *filter;
if (!type) {
/* no protocol => clear filter */
ret = -1;
-   } else if (!dev->s_filter) {
+   } else if (!set_filter) {
/* generic filtering => accept any filter */
ret = 0;
} else {
/* hardware filtering => try setting, otherwise clear */
-   ret = dev->s_filter(dev, fattr->type, &local_filter);
+   ret = set_filter(dev, &local_filter);
}
if (ret < 0) {
/* clear the filter */
local_filter.data = 0;
local_filter.mask = 0;
-   if (dev->s_filter)
-   dev->s_filter(dev, fattr->type, &local_filter);
+   if (set_filter)
+   set_filter(dev, &local_filter);
}
 
/* commit the new filter */
@@ -1112,6 +1116,7 @@ static ssize_t store_filter(struct device *device,
struct rc_scancode_filter local_filter, *filter;
int ret;
unsigned long val;
+   int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter 
*filter);
 
/* Device is being removed */
if (!dev)
@@ -1121,9 +1126,11 @@ static ssize_t store_filter(struct device *device,
if (ret < 0)
return ret;
 
-   /* Scancode filter not supported (but still accept 0) */
-   if (!dev->s_filter && fattr->type != RC_FILTER_NORMAL)
-   return val ? -EINVAL : count;
+   /* Can the scancode filter be set? */
+   set_filter = (fattr->type == RC_FILTER_NORMAL)
+   ? dev->s_filter : dev->s_wakeup_filter;
+   if (!set_filter)
+   return -EINVAL;
 
mutex_lock(&dev->lock);
 
@@ -1134,16 +1141,16 @@ static ssize_t store_filter(struct device *device,
local_filter.mask = val;
else
local_filter.data = val;
+
if (!dev->enabled_protocols[fattr->type] && local_filter.mask) {
/* refuse to set a filter unless a protocol is enabled */
ret = -EINVAL;
goto unlock;
}
-   if (dev->s_filter) {
- 

[PATCH 06/49] rc-core: remove generic scancode filter

2014-04-03 Thread David Härdeman
The generic scancode filtering has questionable value and makes it
impossible to determine from userspace if there is an actual
scancode hw filter present or not.

So revert the generic parts.

Based on a patch from James Hogan , but this
version also makes sure that only the valid sysfs files are created
in the first place.

v2: correct dev->s_filter check

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-main.c |   67 +---
 include/media/rc-core.h|2 +
 2 files changed, 46 insertions(+), 23 deletions(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index ba955ac..26c266b 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -634,7 +634,6 @@ EXPORT_SYMBOL_GPL(rc_repeat);
 static void ir_do_keydown(struct rc_dev *dev, enum rc_type protocol,
  u32 scancode, u32 keycode, u8 toggle)
 {
-   struct rc_scancode_filter *filter;
bool new_event = (!dev->keypressed   ||
  dev->last_protocol != protocol ||
  dev->last_scancode != scancode ||
@@ -643,11 +642,6 @@ static void ir_do_keydown(struct rc_dev *dev, enum rc_type 
protocol,
if (new_event && dev->keypressed)
ir_do_keyup(dev, false);
 
-   /* Generic scancode filtering */
-   filter = &dev->scancode_filters[RC_FILTER_NORMAL];
-   if (filter->mask && ((scancode ^ filter->data) & filter->mask))
-   return;
-
input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
 
if (new_event && keycode != KEY_RESERVED) {
@@ -1017,14 +1011,11 @@ static ssize_t store_protocols(struct device *device,
set_filter = (fattr->type == RC_FILTER_NORMAL)
? dev->s_filter : dev->s_wakeup_filter;
 
-   if (old_type != type && filter->mask) {
+   if (set_filter && old_type != type && filter->mask) {
local_filter = *filter;
if (!type) {
/* no protocol => clear filter */
ret = -1;
-   } else if (!set_filter) {
-   /* generic filtering => accept any filter */
-   ret = 0;
} else {
/* hardware filtering => try setting, otherwise clear */
ret = set_filter(dev, &local_filter);
@@ -1033,8 +1024,7 @@ static ssize_t store_protocols(struct device *device,
/* clear the filter */
local_filter.data = 0;
local_filter.mask = 0;
-   if (set_filter)
-   set_filter(dev, &local_filter);
+   set_filter(dev, &local_filter);
}
 
/* commit the new filter */
@@ -1078,7 +1068,10 @@ static ssize_t show_filter(struct device *device,
return -EINVAL;
 
mutex_lock(&dev->lock);
-   if (fattr->mask)
+   if ((fattr->type == RC_FILTER_NORMAL && !dev->s_filter) ||
+   (fattr->type == RC_FILTER_WAKEUP && !dev->s_wakeup_filter))
+   val = 0;
+   else if (fattr->mask)
val = dev->scancode_filters[fattr->type].mask;
else
val = dev->scancode_filters[fattr->type].data;
@@ -1202,27 +1195,45 @@ static RC_FILTER_ATTR(wakeup_filter, S_IRUGO|S_IWUSR,
 static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR,
  show_filter, store_filter, RC_FILTER_WAKEUP, true);
 
-static struct attribute *rc_dev_attrs[] = {
+static struct attribute *rc_dev_protocol_attrs[] = {
&dev_attr_protocols.attr.attr,
+   NULL,
+};
+
+static struct attribute_group rc_dev_protocol_attr_grp = {
+   .attrs  = rc_dev_protocol_attrs,
+};
+
+static struct attribute *rc_dev_wakeup_protocol_attrs[] = {
&dev_attr_wakeup_protocols.attr.attr,
+   NULL,
+};
+
+static struct attribute_group rc_dev_wakeup_protocol_attr_grp = {
+   .attrs  = rc_dev_wakeup_protocol_attrs,
+};
+
+static struct attribute *rc_dev_filter_attrs[] = {
&dev_attr_filter.attr.attr,
&dev_attr_filter_mask.attr.attr,
-   &dev_attr_wakeup_filter.attr.attr,
-   &dev_attr_wakeup_filter_mask.attr.attr,
NULL,
 };
 
-static struct attribute_group rc_dev_attr_grp = {
-   .attrs  = rc_dev_attrs,
+static struct attribute_group rc_dev_filter_attr_grp = {
+   .attrs  = rc_dev_filter_attrs,
+};
+
+static struct attribute *rc_dev_wakeup_filter_attrs[] = {
+   &dev_attr_wakeup_filter.attr.attr,
+   &dev_attr_wakeup_filter_mask.attr.attr,
+   NULL,
 };
 
-static const struct attribute_group *rc_dev_attr_groups[] = {
-   &rc_dev_attr_grp,
-   NULL
+static struct attribute_group rc_dev_wakeup_filter_attr_grp = {
+   .attrs  = rc_dev_wakeup_filter_attrs,
 };
 
 static struct device_type rc_dev_type = {
-   .groups = rc_dev_attr_groups,
.release  

[PATCH 08/49] lmedm04: NEC scancode cleanup

2014-04-03 Thread David Härdeman
This changes the keymap back to the state before commit 616a4b83
and changes the driver to use full NEC32 scancodes following the
instructions provided by Malcolm Priestley .

Signed-off-by: David Härdeman 
---
 drivers/media/rc/keymaps/rc-lme2510.c  |  132 
 drivers/media/usb/dvb-usb-v2/lmedm04.c |   21 +++--
 2 files changed, 77 insertions(+), 76 deletions(-)

diff --git a/drivers/media/rc/keymaps/rc-lme2510.c 
b/drivers/media/rc/keymaps/rc-lme2510.c
index 51f18bb..2b0027c 100644
--- a/drivers/media/rc/keymaps/rc-lme2510.c
+++ b/drivers/media/rc/keymaps/rc-lme2510.c
@@ -15,74 +15,74 @@
 
 static struct rc_map_table lme2510_rc[] = {
/* Type 1 - 26 buttons */
-   { 0x10ed45, KEY_0 },
-   { 0x10ed5f, KEY_1 },
-   { 0x10ed50, KEY_2 },
-   { 0x10ed5d, KEY_3 },
-   { 0x10ed41, KEY_4 },
-   { 0x10ed0a, KEY_5 },
-   { 0x10ed42, KEY_6 },
-   { 0x10ed47, KEY_7 },
-   { 0x10ed49, KEY_8 },
-   { 0x10ed05, KEY_9 },
-   { 0x10ed43, KEY_POWER },
-   { 0x10ed46, KEY_SUBTITLE },
-   { 0x10ed06, KEY_PAUSE },
-   { 0x10ed03, KEY_MEDIA_REPEAT},
-   { 0x10ed02, KEY_PAUSE },
-   { 0x10ed5e, KEY_VOLUMEUP },
-   { 0x10ed5c, KEY_VOLUMEDOWN },
-   { 0x10ed09, KEY_CHANNELUP },
-   { 0x10ed1a, KEY_CHANNELDOWN },
-   { 0x10ed1e, KEY_PLAY },
-   { 0x10ed1b, KEY_ZOOM },
-   { 0x10ed59, KEY_MUTE },
-   { 0x10ed5a, KEY_TV },
-   { 0x10ed18, KEY_RECORD },
-   { 0x10ed07, KEY_EPG },
-   { 0x10ed01, KEY_STOP },
+   { 0xef12ba45, KEY_0 },
+   { 0xef12a05f, KEY_1 },
+   { 0xef12af50, KEY_2 },
+   { 0xef12a25d, KEY_3 },
+   { 0xef12be41, KEY_4 },
+   { 0xef12f50a, KEY_5 },
+   { 0xef12bd42, KEY_6 },
+   { 0xef12b847, KEY_7 },
+   { 0xef12b649, KEY_8 },
+   { 0xef12fa05, KEY_9 },
+   { 0xef12bc43, KEY_POWER },
+   { 0xef12b946, KEY_SUBTITLE },
+   { 0xef12f906, KEY_PAUSE },
+   { 0xef12fc03, KEY_MEDIA_REPEAT},
+   { 0xef12fd02, KEY_PAUSE },
+   { 0xef12a15e, KEY_VOLUMEUP },
+   { 0xef12a35c, KEY_VOLUMEDOWN },
+   { 0xef12f609, KEY_CHANNELUP },
+   { 0xef12e51a, KEY_CHANNELDOWN },
+   { 0xef12e11e, KEY_PLAY },
+   { 0xef12e41b, KEY_ZOOM },
+   { 0xef12a659, KEY_MUTE },
+   { 0xef12a55a, KEY_TV },
+   { 0xef12e718, KEY_RECORD },
+   { 0xef12f807, KEY_EPG },
+   { 0xef12fe01, KEY_STOP },
/* Type 2 - 20 buttons */
-   { 0xbf15, KEY_0 },
-   { 0xbf08, KEY_1 },
-   { 0xbf09, KEY_2 },
-   { 0xbf0a, KEY_3 },
-   { 0xbf0c, KEY_4 },
-   { 0xbf0d, KEY_5 },
-   { 0xbf0e, KEY_6 },
-   { 0xbf10, KEY_7 },
-   { 0xbf11, KEY_8 },
-   { 0xbf12, KEY_9 },
-   { 0xbf00, KEY_POWER },
-   { 0xbf04, KEY_MEDIA_REPEAT}, /* Recall */
-   { 0xbf1a, KEY_PAUSE }, /* Timeshift */
-   { 0xbf02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */
-   { 0xbf06, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/
-   { 0xbf01, KEY_CHANNELUP },
-   { 0xbf05, KEY_CHANNELDOWN },
-   { 0xbf14, KEY_ZOOM },
-   { 0xbf18, KEY_RECORD },
-   { 0xbf16, KEY_STOP },
+   { 0xff40ea15, KEY_0 },
+   { 0xff40f708, KEY_1 },
+   { 0xff40f609, KEY_2 },
+   { 0xff40f50a, KEY_3 },
+   { 0xff40f30c, KEY_4 },
+   { 0xff40f20d, KEY_5 },
+   { 0xff40f10e, KEY_6 },
+   { 0xff40ef10, KEY_7 },
+   { 0xff40ee11, KEY_8 },
+   { 0xff40ed12, KEY_9 },
+   { 0xff40ff00, KEY_POWER },
+   { 0xff40fb04, KEY_MEDIA_REPEAT}, /* Recall */
+   { 0xff40e51a, KEY_PAUSE }, /* Timeshift */
+   { 0xff40fd02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */
+   { 0xff40f906, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/
+   { 0xff40fe01, KEY_CHANNELUP },
+   { 0xff40fa05, KEY_CHANNELDOWN },
+   { 0xff40eb14, KEY_ZOOM },
+   { 0xff40e718, KEY_RECORD },
+   { 0xff40e916, KEY_STOP },
/* Type 3 - 20 buttons */
-   { 0x1c, KEY_0 },
-   { 0x07, KEY_1 },
-   { 0x15, KEY_2 },
-   { 0x09, KEY_3 },
-   { 0x16, KEY_4 },
-   { 0x19, KEY_5 },
-   { 0x0d, KEY_6 },
-   { 0x0c, KEY_7 },
-   { 0x18, KEY_8 },
-   { 0x5e, KEY_9 },
-   { 0x45, KEY_POWER },
-   { 0x44, KEY_MEDIA_REPEAT}, /* Recall */
-   { 0x4a, KEY_PAUSE }, /* Timeshift */
-   { 0x47, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */
-   { 0x43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/
-   { 0x46, KEY_CHANNELUP },
-   { 0x40, KEY_CHANNELDOWN },
-   { 0x08, KEY_ZOOM },
-   { 0x42, KEY_RECORD },
-   { 0x5a, KEY_STOP },
+   { 0xff00e31c, KEY_0 },
+   { 0xff00f807, KEY_1 },
+   { 0xff00ea15, KEY_2 },
+   { 0xff00f609, KEY_3 },
+   { 0xff00e916, KEY_4 },
+   { 0xff00e619, KEY_5 },
+   { 0xff00f20d, KEY_6 },
+   { 0xff00f30c, KEY_7 },
+   { 0xff00e718, KEY_8 },
+   { 0xff00a15e, KEY_9 },
+   { 0xff00ba45, KEY_POWER },
+   { 0xff00bb44, KE

[PATCH 00/49] rc-core: my current patch queue

2014-04-03 Thread David Härdeman
The following patches is what I currenly have in my queue:

Patches 1 - 6 should be ok to be committed right now, they contain
some fixes and some reverts (of the NEC32 and generic scancode
functionality).

Patches 7 - 9 are in no hurry and can wait for 3.16, some testing
would be nice even though I believe they are ok.

Patches 10 and 11 are RFC's for the NEC32 scancode handling.

The remaining patches are more of an FYI. It's basically the same
patchset that I've posted a long time ago, but respun to apply to
the current tree. They implement a modern chardev for rc-core which
allows the functionality that has so far only been available through
the LIRC bridge to be exposed to userspace and provide a (hopefully)
sane API for taking advantage of all the features that rc-core
provides (RX, TX, ioctl) as well as some new features (multiple
keymaps is probably the most important one). Lots and lots of cleanups
as well.

Enjoy :)

---

David Härdeman (49):
  bt8xx: fixup RC5 decoding
  rc-core: improve ir-kbd-i2c get_key functions
  rc-core: document the protocol type
  rc-core: do not change 32bit NEC scancode format for now
  rc-core: split dev->s_filter
  rc-core: remove generic scancode filter
  dib0700: NEC scancode cleanup
  lmedm04: NEC scancode cleanup
  saa7134: NEC scancode fix
  [RFC] rc-core: use the full 32 bits for NEC scancodes
  [RFC] rc-core: don't throw away protocol information
  rc-core: simplify sysfs code
  rc-core: remove protocol arrays
  rc-core: rename dev->scanmask to dev->scancode_mask
  rc-core: merge rc5 and streamzap decoders
  rc-core: use an IDA rather than a bitmap
  rc-core: add chardev
  rc-core: allow chardev to be read
  rc-core: use a kfifo for TX data
  rc-core: allow chardev to be written
  rc-core: add ioctl support to the rc chardev
  rc-core: add an ioctl for getting IR RX settings
  rc-loopback: add RCIOCGIRRX ioctl support
  rc-core: add an ioctl for setting IR RX settings
  rc-loopback: add RCIOCSIRRX ioctl support
  rc-core: add an ioctl for getting IR TX settings
  rc-loopback: add RCIOCGIRTX ioctl support
  rc-core: add an ioctl for setting IR TX settings
  rc-loopback: add RCIOCSIRTX ioctl support
  rc-core: leave the internals of rc_dev alone
  rc-core: split rc-main.c into rc-main.c and rc-keytable.c
  rc-core: prepare for multiple keytables
  rc-core: make the keytable of rc_dev an array
  rc-core: add ioctls for adding/removing keytables from userspace
  rc-core: remove redundant spinlock
  rc-core: make keytable RCU-friendly
  rc-core: allow empty keymaps
  rc-core: rename ir-raw.c
  rc-core: make IR raw handling a separate module
  rc-ir-raw: simplify locking
  rc-core: rename mutex
  rc-ir-raw: atomic reads of protocols
  rc-core: fix various sparse warnings
  rc-core: don't report scancodes via input devices
  rc-ir-raw: add various rc_events
  rc-core: use struct rc_event for all rc communication
  rc-core: add keytable events
  rc-core: move remaining keytable functions
  rc-core: make rc-core.h userspace friendly


 Documentation/ioctl/ioctl-number.txt|1 
 drivers/hid/hid-picolcd_cir.c   |   20 
 drivers/media/common/siano/smsir.c  |   14 
 drivers/media/common/siano/smsir.h  |2 
 drivers/media/i2c/cx25840/cx25840-ir.c  |   96 +
 drivers/media/i2c/ir-kbd-i2c.c  |   99 +
 drivers/media/pci/bt8xx/bttv-input.c|   78 +
 drivers/media/pci/bt8xx/bttvp.h |2 
 drivers/media/pci/cx23885/cx23885-input.c   |   26 
 drivers/media/pci/cx23885/cx23888-ir.c  |   93 +
 drivers/media/pci/cx88/cx88-input.c |   75 +
 drivers/media/pci/dm1105/dm1105.c   |4 
 drivers/media/pci/ivtv/ivtv-i2c.c   |   11 
 drivers/media/pci/saa7134/saa7134-input.c   |  100 +
 drivers/media/pci/saa7134/saa7134.h |2 
 drivers/media/pci/ttpci/budget-ci.c |   10 
 drivers/media/rc/Kconfig|   12 
 drivers/media/rc/Makefile   |4 
 drivers/media/rc/ati_remote.c   |   11 
 drivers/media/rc/ene_ir.c   |   84 +
 drivers/media/rc/ene_ir.h   |9 
 drivers/media/rc/fintek-cir.c   |   34 
 drivers/media/rc/gpio-ir-recv.c |   15 
 drivers/media/rc/iguanair.c |   77 +
 drivers/media/rc/img-ir/img-ir-hw.c |   48 -
 drivers/media/rc/img-ir/img-ir-hw.h |3 
 drivers/media/rc/img-ir/img-ir-jvc.c|4 
 drivers/media/rc/img-ir/img-ir-nec.c|   80 -
 drivers/media/rc/img-ir/img-ir-raw.c|8 
 drivers/media/rc/img-ir/img-ir-sanyo.c  |4 
 drivers/media/rc/img-ir/img-ir-sharp.c  |4 
 drivers/media/rc/img-ir/img-ir-sony.c   |   12 
 drivers/media/rc/imon.c |   33 
 drivers/media/rc

[PATCH 04/49] rc-core: do not change 32bit NEC scancode format for now

2014-04-03 Thread David Härdeman
This reverts 18bc17448147e93f31cc9b1a83be49f1224657b2

The patch ignores the fact that NEC32 scancodes are generated not only in the
NEC raw decoder but also directly in some drivers. Whichever approach is chosen
it should be consistent across drivers and this patch needs more discussion.

Furthermore, I'm convinced that we have to stop playing games trying to
decipher the "meaning" of NEC scancodes (what's the customer/vendor/address,
which byte is the MSB, etc).

This patch is in preparation for the next few patches in this series.

v2: make sure img-ir scancodes are bitrev8():ed as well

Signed-off-by: David Härdeman 
---
 drivers/media/rc/img-ir/img-ir-nec.c |   27 ++-
 drivers/media/rc/ir-nec-decoder.c|5 --
 drivers/media/rc/keymaps/rc-tivo.c   |   86 +-
 3 files changed, 59 insertions(+), 59 deletions(-)

diff --git a/drivers/media/rc/img-ir/img-ir-nec.c 
b/drivers/media/rc/img-ir/img-ir-nec.c
index c0111d6..ee45795 100644
--- a/drivers/media/rc/img-ir/img-ir-nec.c
+++ b/drivers/media/rc/img-ir/img-ir-nec.c
@@ -5,6 +5,7 @@
  */
 
 #include "img-ir-hw.h"
+#include 
 
 /* Convert NEC data to a scancode */
 static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol,
@@ -23,11 +24,11 @@ static int img_ir_nec_scancode(int len, u64 raw, enum 
rc_type *protocol,
data_inv = (raw >> 24) & 0xff;
if ((data_inv ^ data) != 0xff) {
/* 32-bit NEC (used by Apple and TiVo remotes) */
-   /* scan encoding: aaAAddDD */
-   *scancode = addr_inv << 24 |
-   addr << 16 |
-   data_inv <<  8 |
-   data;
+   /* scan encoding: AAaaDDdd (LSBit first) */
+   *scancode = bitrev8(addr) << 24 |
+   bitrev8(addr_inv) << 16 |
+   bitrev8(data) <<  8 |
+   bitrev8(data_inv);
} else if ((addr_inv ^ addr) != 0xff) {
/* Extended NEC */
/* scan encoding: AAaaDD */
@@ -56,13 +57,15 @@ static int img_ir_nec_filter(const struct 
rc_scancode_filter *in,
 
if ((in->data | in->mask) & 0xff00) {
/* 32-bit NEC (used by Apple and TiVo remotes) */
-   /* scan encoding: aaAAddDD */
-   addr_inv   = (in->data >> 24) & 0xff;
-   addr_inv_m = (in->mask >> 24) & 0xff;
-   addr   = (in->data >> 16) & 0xff;
-   addr_m = (in->mask >> 16) & 0xff;
-   data_inv   = (in->data >>  8) & 0xff;
-   data_inv_m = (in->mask >>  8) & 0xff;
+   /* scan encoding: AAaaDDdd (LSBit first) */
+   addr   = bitrev8(in->data >> 24);
+   addr_m = bitrev8(in->mask >> 24);
+   addr_inv   = bitrev8(in->data >> 16);
+   addr_inv_m = bitrev8(in->mask >> 16);
+   data   = bitrev8(in->data >>  8);
+   data_m = bitrev8(in->mask >>  8);
+   data_inv   = bitrev8(in->data >>  0);
+   data_inv_m = bitrev8(in->mask >>  0);
} else if ((in->data | in->mask) & 0x00ff) {
/* Extended NEC */
/* scan encoding AAaaDD */
diff --git a/drivers/media/rc/ir-nec-decoder.c 
b/drivers/media/rc/ir-nec-decoder.c
index 735a509..c4333d5 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -172,10 +172,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct 
ir_raw_event ev)
if (send_32bits) {
/* NEC transport, but modified protocol, used by at
 * least Apple and TiVo remotes */
-   scancode = not_address << 24 |
-  address << 16 |
-  not_command <<  8 |
-  command;
+   scancode = data->bits;
IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", 
scancode);
} else if ((address ^ not_address) != 0xff) {
/* Extended NEC */
diff --git a/drivers/media/rc/keymaps/rc-tivo.c 
b/drivers/media/rc/keymaps/rc-tivo.c
index 5cc1b45..454e062 100644
--- a/drivers/media/rc/keymaps/rc-tivo.c
+++ b/drivers/media/rc/keymaps/rc-tivo.c
@@ -15,62 +15,62 @@
  * Initial mapping is for the TiVo remote included in the Nero LiquidTV bundle,
  * which also ships with a TiVo-branded IR transceiver, supported by the mceusb
  * driver. Note that the remote uses an NEC-ish protocol, but instead of having
- * a command/not_command pair, it has a vendor ID of 0x3085, but some keys, the
+ * a command/not_command pair, it has a vendor ID of 0xa10c, but some keys, the
  * NEC extended checksums do pass, so the table presently has the intended
  * values and the checksum-passed versions for those keys.
  */
 static struct rc_map_table tiv

[PATCH 03/49] rc-core: document the protocol type

2014-04-03 Thread David Härdeman
Right now the protocol information is not preserved, rc-core gets handed a
scancode but has no idea which protocol it corresponds to.

This patch (which required reading through the source/keymap for all drivers,
not fun) makes the protocol information explicit which is important
documentation and makes it easier to e.g. support multiple protocols with one
decoder (think rc5 and rc-streamzap). The information isn't used yet so there
should be no functional changes.

Signed-off-by: David Härdeman 
---
 drivers/media/i2c/ir-kbd-i2c.c  |5 +
 drivers/media/pci/bt8xx/bttv-input.c|   12 ++-
 drivers/media/pci/cx88/cx88-input.c |   26 ++-
 drivers/media/pci/dm1105/dm1105.c   |3 +
 drivers/media/pci/saa7134/saa7134-input.c   |6 +-
 drivers/media/pci/ttpci/budget-ci.c |8 +-
 drivers/media/rc/ati_remote.c   |4 +
 drivers/media/rc/img-ir/img-ir-hw.c |8 +-
 drivers/media/rc/img-ir/img-ir-hw.h |3 +
 drivers/media/rc/img-ir/img-ir-jvc.c|4 +
 drivers/media/rc/img-ir/img-ir-nec.c|4 +
 drivers/media/rc/img-ir/img-ir-sanyo.c  |4 +
 drivers/media/rc/img-ir/img-ir-sharp.c  |4 +
 drivers/media/rc/img-ir/img-ir-sony.c   |   12 ++-
 drivers/media/rc/imon.c |5 +
 drivers/media/rc/ir-jvc-decoder.c   |2 -
 drivers/media/rc/ir-nec-decoder.c   |2 -
 drivers/media/rc/ir-rc5-decoder.c   |5 +
 drivers/media/rc/ir-rc5-sz-decoder.c|2 -
 drivers/media/rc/ir-rc6-decoder.c   |   37 --
 drivers/media/rc/ir-sanyo-decoder.c |2 -
 drivers/media/rc/ir-sharp-decoder.c |2 -
 drivers/media/rc/ir-sony-decoder.c  |6 +-
 drivers/media/rc/rc-main.c  |   32 +
 drivers/media/usb/dvb-usb-v2/af9015.c   |   18 +++--
 drivers/media/usb/dvb-usb-v2/af9035.c   |9 +-
 drivers/media/usb/dvb-usb-v2/anysee.c   |3 +
 drivers/media/usb/dvb-usb-v2/az6007.c   |   25 ---
 drivers/media/usb/dvb-usb-v2/lmedm04.c  |9 +-
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c |   12 ++-
 drivers/media/usb/dvb-usb/dib0700_core.c|   16 +++-
 drivers/media/usb/dvb-usb/dib0700_devices.c |   24 ---
 drivers/media/usb/dvb-usb/dw2102.c  |7 +-
 drivers/media/usb/dvb-usb/m920x.c   |2 -
 drivers/media/usb/dvb-usb/pctv452e.c|8 +-
 drivers/media/usb/dvb-usb/ttusb2.c  |6 +-
 drivers/media/usb/em28xx/em28xx-input.c |   98 ---
 drivers/media/usb/tm6000/tm6000-input.c |   51 ++
 include/media/rc-core.h |6 +-
 39 files changed, 307 insertions(+), 185 deletions(-)

diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 143cb2b..f9c4233 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -261,8 +261,9 @@ static int ir_key_poll(struct IR_i2c *ir)
}
 
if (rc) {
-   dprintk(1, "%s: scancode = 0x%08x\n", __func__, scancode);
-   rc_keydown(ir->rc, scancode, toggle);
+   dprintk(1, "%s: proto = 0x%04x, scancode = 0x%08x\n",
+   __func__, protocol, scancode);
+   rc_keydown(ir->rc, protocol, scancode, toggle);
}
return 0;
 }
diff --git a/drivers/media/pci/bt8xx/bttv-input.c 
b/drivers/media/pci/bt8xx/bttv-input.c
index e745f5a..67c8d6b 100644
--- a/drivers/media/pci/bt8xx/bttv-input.c
+++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -73,12 +73,12 @@ static void ir_handle_key(struct bttv *btv)
 
if ((ir->mask_keydown && (gpio & ir->mask_keydown)) ||
(ir->mask_keyup   && !(gpio & ir->mask_keyup))) {
-   rc_keydown_notimeout(ir->dev, data, 0);
+   rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
} else {
/* HACK: Probably, ir->mask_keydown is missing
   for this board */
if (btv->c.type == BTTV_BOARD_WINFAST2000)
-   rc_keydown_notimeout(ir->dev, data, 0);
+   rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 
rc_keyup(ir->dev);
}
@@ -103,7 +103,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
gpio, data,
(gpio & ir->mask_keyup) ? " up" : "up/down");
 
-   rc_keydown_notimeout(ir->dev, data, 0);
+   rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
if (keyup)
rc_keyup(ir->dev);
} else {
@@ -117,7 +117,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
if (keyup)
rc_keyup(ir->dev);
else
-   rc_keydown_notimeout(ir->dev, data, 0);
+   rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
}
 
  

[PATCH 02/49] rc-core: improve ir-kbd-i2c get_key functions

2014-04-03 Thread David Härdeman
The arguments used for ir-kbd-i2c's get_key() functions are not
really suited for rc-core and the ir_raw/ir_key distinction is
just confusing.

Convert all of them to return a protocol/scancode/toggle triple instead.

Signed-off-by: David Härdeman 
---
 drivers/media/i2c/ir-kbd-i2c.c|   90 +++--
 drivers/media/pci/bt8xx/bttv-input.c  |8 ++-
 drivers/media/pci/cx88/cx88-input.c   |8 ++-
 drivers/media/pci/ivtv/ivtv-i2c.c |9 ++-
 drivers/media/pci/saa7134/saa7134-input.c |   76 +++-
 drivers/media/usb/cx231xx/cx231xx-input.c |   20 ++
 include/media/ir-kbd-i2c.h|6 +-
 include/media/rc-map.h|   10 +++
 8 files changed, 127 insertions(+), 100 deletions(-)

diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index c8fe135..143cb2b 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -62,8 +62,8 @@ module_param(debug, int, 0644);/* debug level (0,1,2) */
 
 /* --- */
 
-static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
-  int size, int offset)
+static int get_key_haup_common(struct IR_i2c *ir, enum rc_type *protocol,
+  u32 *scancode, u8 *ptoggle, int size, int offset)
 {
unsigned char buf[6];
int start, range, toggle, dev, code, ircode;
@@ -86,19 +86,10 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 
*ir_key, u32 *ir_raw,
if (!start)
/* no key pressed */
return 0;
-   /*
-* Hauppauge remotes (black/silver) always use
-* specific device ids. If we do not filter the
-* device ids then messages destined for devices
-* such as TVs (id=0) will get through causing
-* mis-fired events.
-*
-* We also filter out invalid key presses which
-* produce annoying debug log entries.
-*/
-   ircode= (start << 12) | (toggle << 11) | (dev << 6) | code;
-   if ((ircode & 0x1fff)==0x1fff)
-   /* invalid key press */
+
+   /* filter out invalid key presses */
+   ircode = (start << 12) | (toggle << 11) | (dev << 6) | code;
+   if ((ircode & 0x1fff) == 0x1fff)
return 0;
 
if (!range)
@@ -107,18 +98,20 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 
*ir_key, u32 *ir_raw,
dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n",
start, range, toggle, dev, code);
 
-   /* return key */
-   *ir_key = (dev << 8) | code;
-   *ir_raw = ircode;
+   *protocol = RC_TYPE_RC5;
+   *scancode = RC_SCANCODE_RC5(dev, code);
+   *ptoggle = toggle;
return 1;
 }
 
-static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup(struct IR_i2c *ir, enum rc_type *protocol,
+   u32 *scancode, u8 *toggle)
 {
-   return get_key_haup_common (ir, ir_key, ir_raw, 3, 0);
+   return get_key_haup_common (ir, protocol, scancode, toggle, 3, 0);
 }
 
-static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup_xvr(struct IR_i2c *ir, enum rc_type *protocol,
+   u32 *scancode, u8 *toggle)
 {
int ret;
unsigned char buf[1] = { 0 };
@@ -133,10 +126,11 @@ static int get_key_haup_xvr(struct IR_i2c *ir, u32 
*ir_key, u32 *ir_raw)
if (ret != 1)
return (ret < 0) ? ret : -EINVAL;
 
-   return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
+   return get_key_haup_common(ir, protocol, scancode, toggle, 6, 3);
 }
 
-static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pixelview(struct IR_i2c *ir, enum rc_type *protocol,
+u32 *scancode, u8 *toggle)
 {
unsigned char b;
 
@@ -145,12 +139,15 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 
*ir_key, u32 *ir_raw)
dprintk(1,"read error\n");
return -EIO;
}
-   *ir_key = b;
-   *ir_raw = b;
+
+   *protocol = RC_TYPE_OTHER;
+   *scancode = b;
+   *toggle = 0;
return 1;
 }
 
-static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_fusionhdtv(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
 {
unsigned char buf[4];
 
@@ -168,13 +165,14 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 
*ir_key, u32 *ir_raw)
if(buf[0] != 0x1 ||  buf[1] != 0xfe)
return 0;
 
-   *ir_key = buf[2];
-   *ir_raw = (buf[2] << 8) | buf[3];
-
+   *protocol = RC_TYPE_UNKNOWN;
+   *scancode = buf[2];
+   *toggle = 0;
return 1;
 }
 
-static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static 

[PATCH 09/49] saa7134: NEC scancode fix

2014-04-03 Thread David Härdeman
This driver codes the two address bytes in reverse order when compared to the
other drivers, so make it consistent (and update the keymap, note that the
result is a prefix change from 0x6b86 -> 0x866b, and the latter is pretty
common among the NECX keymaps. While not conclusive, it's still a strong hint
that the change is correct).

Signed-off-by: David Härdeman 
---
 drivers/media/pci/saa7134/saa7134-input.c |2 -
 drivers/media/rc/keymaps/rc-behold.c  |   68 +++--
 2 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-input.c 
b/drivers/media/pci/saa7134/saa7134-input.c
index 43dd8bd..887429b 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -346,7 +346,7 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, enum 
rc_type *protocol,
return 0;
 
*protocol = RC_TYPE_NEC;
-   *scancode = RC_SCANCODE_NECX(((data[10] << 8) | data[11]), data[9]);
+   *scancode = RC_SCANCODE_NECX(data[11] << 8 | data[10], data[9]);
*toggle = 0;
return 1;
 }
diff --git a/drivers/media/rc/keymaps/rc-behold.c 
b/drivers/media/rc/keymaps/rc-behold.c
index d6519f8..520a96f 100644
--- a/drivers/media/rc/keymaps/rc-behold.c
+++ b/drivers/media/rc/keymaps/rc-behold.c
@@ -30,8 +30,8 @@ static struct rc_map_table behold[] = {
/*  0x1c0x12  *
 *  TV/FM  POWER  *
 **/
-   { 0x6b861c, KEY_TUNER },/* XXX KEY_TV / KEY_RADIO */
-   { 0x6b8612, KEY_POWER },
+   { 0x866b1c, KEY_TUNER },/* XXX KEY_TV / KEY_RADIO */
+   { 0x866b12, KEY_POWER },
 
/*  0x010x020x03  *
 *   1   2   3*
@@ -42,28 +42,28 @@ static struct rc_map_table behold[] = {
 *  0x070x080x09  *
 *   7   8   9*
 **/
-   { 0x6b8601, KEY_1 },
-   { 0x6b8602, KEY_2 },
-   { 0x6b8603, KEY_3 },
-   { 0x6b8604, KEY_4 },
-   { 0x6b8605, KEY_5 },
-   { 0x6b8606, KEY_6 },
-   { 0x6b8607, KEY_7 },
-   { 0x6b8608, KEY_8 },
-   { 0x6b8609, KEY_9 },
+   { 0x866b01, KEY_1 },
+   { 0x866b02, KEY_2 },
+   { 0x866b03, KEY_3 },
+   { 0x866b04, KEY_4 },
+   { 0x866b05, KEY_5 },
+   { 0x866b06, KEY_6 },
+   { 0x866b07, KEY_7 },
+   { 0x866b08, KEY_8 },
+   { 0x866b09, KEY_9 },
 
/*  0x0a0x000x17  *
 * RECALL0  MODE  *
 **/
-   { 0x6b860a, KEY_AGAIN },
-   { 0x6b8600, KEY_0 },
-   { 0x6b8617, KEY_MODE },
+   { 0x866b0a, KEY_AGAIN },
+   { 0x866b00, KEY_0 },
+   { 0x866b17, KEY_MODE },
 
/*  0x14  0x10*
 * ASPECT  FULLSCREEN *
 **/
-   { 0x6b8614, KEY_SCREEN },
-   { 0x6b8610, KEY_ZOOM },
+   { 0x866b14, KEY_SCREEN },
+   { 0x866b10, KEY_ZOOM },
 
/*  0x0b  *
 *   Up   *
@@ -74,17 +74,17 @@ static struct rc_map_table behold[] = {
 * 0x015  *
 * Down   *
 **/
-   { 0x6b860b, KEY_CHANNELUP },
-   { 0x6b8618, KEY_VOLUMEDOWN },
-   { 0x6b8616, KEY_OK },   /* XXX KEY_ENTER */
-   { 0x6b860c, KEY_VOLUMEUP },
-   { 0x6b8615, KEY_CHANNELDOWN },
+   { 0x866b0b, KEY_CHANNELUP },
+   { 0x866b18, KEY_VOLUMEDOWN },
+   { 0x866b16, KEY_OK },   /* XXX KEY_ENTER */
+   { 0x866b0c, KEY_VOLUMEUP },
+   { 0x866b15, KEY_CHANNELDOWN },
 
/*  0x110x0d  *
 *  MUTEINFO  *
 **/
-   { 0x6b8611, KEY_MUTE },
-   { 0x6b860d, KEY_INFO },
+   { 0x866b11, KEY_MUTE },
+   { 0x866b0d, KEY_INFO },
 
/*  0x0f0x1b0x1a  *
 * RECORD PLAY/PAUSE STOP *
@@ -93,26 +93,26 @@ static struct rc_map_table behold[] = {
 *TELETEXT  AUDIO  SOURCE *
 *   RED   YELLOW *
 **/
-   { 0x6b860f, KEY_RECORD },
-   { 0x6b861b, KEY_PLAYPAUSE },
-   { 0x6b861a, KEY_STOP },
-   { 0x6b860e, KEY_TEXT },
-   { 0x6b861f, KEY_RED },  /*XXX KEY_AUDIO */
-   { 0x6b861e, KEY_VIDEO },
+   { 0x866b0f, KEY_RECORD },
+   { 0x866b1b, KEY_PLAYPAUSE },
+   { 0x866b1a, KEY_STOP },
+   { 0x866b0e, KEY_TEXT },
+   { 0x866b1f, KEY_RED },  /*XXX KEY_AUDIO */
+   { 0x866b1e, KEY_VIDEO },
 
/*  0x1d   0x13 0x19  *
 * SLEEP  PREVIEW   DVB   *
 * GREENBLUE  *
 **/
-   { 0x6b861d, KEY_SLEEP },
-   { 0x6b8613, KEY_GREEN },
-   { 0x6b8619, KEY_BLUE }, /* XXX KEY_SAT  */
+   { 0x866b1d, KEY_SLEEP },
+   { 0x866b13, KEY_GREEN },
+   { 0x866b19, KEY_BLUE }, /* XXX KEY_SAT  */
 
/*  0x58 

[PATCH 01/49] bt8xx: fixup RC5 decoding

2014-04-03 Thread David Härdeman
The bt8xx driver does RC5 decoding for Nebula digi hardware, but includes
some pointless limitations (both start bits must be one, the
device/address/system must be 0x00). Remove those limitations and update
the keymap to use the full RC5 scancode (fortunately the 0x00 address
means that this is perfectly backwards compatible).

Signed-off-by: David Härdeman 
---
 drivers/media/pci/bt8xx/bttv-input.c |   62 ++-
 drivers/media/pci/bt8xx/bttvp.h  |2 -
 drivers/media/rc/keymaps/rc-nebula.c |  112 +-
 3 files changed, 88 insertions(+), 88 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-input.c 
b/drivers/media/pci/bt8xx/bttv-input.c
index 5930bce..ffc0ee1 100644
--- a/drivers/media/pci/bt8xx/bttv-input.c
+++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -154,10 +154,10 @@ static void bttv_input_timer(unsigned long data)
  * testing.
  */
 
-#define RC5_START(x)   (((x) >> 12) & 3)
-#define RC5_TOGGLE(x)  (((x) >> 11) & 1)
-#define RC5_ADDR(x)(((x) >> 6) & 31)
-#define RC5_INSTR(x)   ((x) & 63)
+#define RC5_START(x)   (((x) >> 12) & 0x03)
+#define RC5_TOGGLE(x)  (((x) >> 11) & 0x01)
+#define RC5_ADDR(x)(((x) >> 6)  & 0x1f)
+#define RC5_INSTR(x)   (((x) >> 0)  & 0x3f)
 
 /* decode raw bit pattern to RC5 code */
 static u32 bttv_rc5_decode(unsigned int code)
@@ -195,8 +195,8 @@ static void bttv_rc5_timer_end(unsigned long data)
 {
struct bttv_ir *ir = (struct bttv_ir *)data;
struct timeval tv;
-   u32 gap;
-   u32 rc5 = 0;
+   u32 gap, rc5, scancode;
+   u8 toggle, command, system;
 
/* get time */
do_gettimeofday(&tv);
@@ -221,26 +221,29 @@ static void bttv_rc5_timer_end(unsigned long data)
if (ir->last_bit < 20) {
/* ignore spurious codes (caused by light/other remotes) */
dprintk("short code: %x\n", ir->code);
-   } else {
-   ir->code = (ir->code << ir->shift_by) | 1;
-   rc5 = bttv_rc5_decode(ir->code);
-
-   /* two start bits? */
-   if (RC5_START(rc5) != ir->start) {
-   pr_info(DEVNAME ":"
-  " rc5 start bits invalid: %u\n", RC5_START(rc5));
-
-   /* right address? */
-   } else if (RC5_ADDR(rc5) == ir->addr) {
-   u32 toggle = RC5_TOGGLE(rc5);
-   u32 instr = RC5_INSTR(rc5);
-
-   /* Good code */
-   rc_keydown(ir->dev, instr, toggle);
-   dprintk("instruction %x, toggle %x\n",
-   instr, toggle);
-   }
+   return;
}
+
+   ir->code = (ir->code << ir->shift_by) | 1;
+   rc5 = bttv_rc5_decode(ir->code);
+
+   toggle = RC5_TOGGLE(rc5);
+   system = RC5_ADDR(rc5);
+   command = RC5_INSTR(rc5);
+
+   switch (RC5_START(rc5)) {
+   case 0x3:
+   break;
+   case 0x2:
+   command += 0x40;
+   break;
+   default:
+   return;
+   }
+
+   scancode = system << 8 | command;
+   rc_keydown(ir->dev, scancode, toggle);
+   dprintk("scancode %x, toggle %x\n", scancode, toggle);
 }
 
 static int bttv_rc5_irq(struct bttv *btv)
@@ -310,8 +313,6 @@ static void bttv_ir_start(struct bttv *btv, struct bttv_ir 
*ir)
/* set timer_end for code completion */
setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir);
ir->shift_by = 1;
-   ir->start = 3;
-   ir->addr = 0x0;
ir->rc5_remote_gap = ir_rc5_remote_gap;
}
 }
@@ -490,8 +491,8 @@ int bttv_input_init(struct bttv *btv)
ir->polling  = 50; // ms
break;
case BTTV_BOARD_NEBULA_DIGITV:
-   ir_codes = RC_MAP_NEBULA;
-   ir->rc5_gpio = true;
+   ir_codes = RC_MAP_NEBULA;
+   ir->rc5_gpio = true;
break;
case BTTV_BOARD_MACHTV_MAGICTV:
ir_codes = RC_MAP_APAC_VIEWCOMP;
@@ -514,7 +515,8 @@ int bttv_input_init(struct bttv *btv)
   ir->mask_keycode);
break;
}
-   if (NULL == ir_codes) {
+
+   if (!ir_codes) {
dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
err = -ENODEV;
goto err_out_free;
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 6eefb59..9fe19488 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -133,8 +133,6 @@ struct bttv_ir {
u32 polling;
u32 last_gpio;
int shift_by;
-   int start; // What should RC5_START() be
-   int addr; // What RC5_ADDR() should be.
  

[PATCH 07/49] dib0700: NEC scancode cleanup

2014-04-03 Thread David Härdeman
the RC RX packet is defined as:

struct dib0700_rc_response {
...
u8 not_system;
u8 system;
...
u8 data;
u8 not_data;

The NEC protocol transmits in the order:
system
not_system
data
not_data

Note that the code defines the NEC extended scancode as:

scancode = be16_to_cpu(poll_reply->system16) << 8 | poll_reply->data;

i.e.

scancode = poll_reply->not_system << 16 |
   poll_reply->system << 8  |
   poll_reply->data;

Which, if the order *is* reversed, would mean that the scancode that
gets defined is in reality:

scancode = poll_reply->system << 16 |
   poll_reply->not_system << 8  |
   poll_reply->data;

Which is the same as the order used in drivers/media/rc/ir-nec-decoder.c.

This patch changes the code to match my assumption (the generated scancode
should, however, not change).

Signed-off-by: David Härdeman 
CC: Patrick Boettcher 
---
 drivers/media/usb/dvb-usb/dib0700_core.c |   28 +++-
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c 
b/drivers/media/usb/dvb-usb/dib0700_core.c
index 6afe7ea..0d881b9 100644
--- a/drivers/media/usb/dvb-usb/dib0700_core.c
+++ b/drivers/media/usb/dvb-usb/dib0700_core.c
@@ -658,13 +658,8 @@ out:
 struct dib0700_rc_response {
u8 report_id;
u8 data_state;
-   union {
-   u16 system16;
-   struct {
-   u8 not_system;
-   u8 system;
-   };
-   };
+   u8 system;
+   u8 not_system;
u8 data;
u8 not_data;
 };
@@ -712,20 +707,27 @@ static void dib0700_rc_urb_completion(struct urb *purb)
toggle = 0;
 
/* NEC protocol sends repeat code as 0 0 0 FF */
-   if ((poll_reply->system == 0x00) && (poll_reply->data == 0x00)
-   && (poll_reply->not_data == 0xff)) {
+   if (poll_reply->system == 0x00 &&
+   poll_reply->not_system == 0x00 &&
+   poll_reply->data   == 0x00 &&
+   poll_reply->not_data   == 0xff) {
poll_reply->data_state = 2;
break;
}
 
-   if ((poll_reply->system ^ poll_reply->not_system) != 0xff) {
+   if ((poll_reply->data ^ poll_reply->not_data) != 0xff) {
+   deb_data("NEC32 protocol\n");
+   scancode = RC_SCANCODE_NEC32(poll_reply->system << 
24 |
+poll_reply->not_system << 
16 |
+poll_reply->data   << 
8  |
+poll_reply->not_data);
+   } else if ((poll_reply->system ^ poll_reply->not_system) != 
0xff) {
deb_data("NEC extended protocol\n");
-   /* NEC extended code - 24 bits */
-   scancode = 
RC_SCANCODE_NECX(be16_to_cpu(poll_reply->system16),
+   scancode = RC_SCANCODE_NECX(poll_reply->system << 8 |
+   poll_reply->not_system,
poll_reply->data);
} else {
deb_data("NEC normal protocol\n");
-   /* normal NEC code - 16 bits */
scancode = RC_SCANCODE_NEC(poll_reply->system,
   poll_reply->data);
}

--
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 11/49] [RFC] rc-core: don't throw away protocol information

2014-04-03 Thread David Härdeman
Setting and getting keycodes in the input subsystem used to be done via
the EVIOC[GS]KEYCODE ioctl and "unsigned int[2]" (one int for scancode
and one for the keycode).

The interface has now been extended to use the EVIOC[GS]KEYCODE_V2 ioctl
which uses the following struct:

struct input_keymap_entry {
__u8  flags;
__u8  len;
__u16 index;
__u32 keycode;
__u8  scancode[32];
};

(scancode can of course be even bigger, thanks to the len member).

This patch changes how the "input_keymap_entry" struct is interpreted
by rc-core by casting it to "rc_keymap_entry":

struct rc_scancode {
__u16 protocol;
__u16 reserved[3];
__u64 scancode;
}

struct rc_keymap_entry {
__u8  flags;
__u8  len;
__u16 index;
__u32 keycode;
union {
struct rc_scancode rc;
__u8 raw[32];
};
};

The u64 scancode member is large enough for all current protocols and it
would be possible to extend it in the future should it be necessary for
some exotic protocol.

The main advantage with this change is that the protocol is made explicit,
which means that we're not throwing away data (the protocol type) and that
it'll be easier to support multiple protocols with one decoder (think rc5
and rc5-streamzap).

Heuristics are also added to hopefully do the right thing with older
ioctls in order to preserve backwards compatibility.

Further patches will also add the ability to communicate the protocol to
userspace.

This needs review by the input maintainer as well.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/ati_remote.c |1 
 drivers/media/rc/imon.c   |   12 ++-
 drivers/media/rc/rc-main.c|  182 +
 include/media/rc-core.h   |   20 -
 include/media/rc-map.h|8 +-
 5 files changed, 163 insertions(+), 60 deletions(-)

diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 8730b32..7098fa5 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -548,6 +548,7 @@ static void ati_remote_input_report(struct urb *urb)
 * set, assume this is a scrollwheel up/down event.
 */
wheel_keycode = rc_g_keycode_from_table(ati_remote->rdev,
+   RC_TYPE_OTHER,
scancode & 0x78);
 
if (wheel_keycode == KEY_RESERVED) {
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index d1564d1..8abbb8d 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -1166,14 +1166,20 @@ static u32 imon_remote_key_lookup(struct imon_context 
*ictx, u32 scancode)
bool is_release_code = false;
 
/* Look for the initial press of a button */
-   keycode = rc_g_keycode_from_table(ictx->rdev, scancode);
+   keycode = rc_g_keycode_from_table(ictx->rdev,
+ ictx->rc_type == RC_BIT_RC6_MCE ?
+ RC_TYPE_RC6_MCE : RC_TYPE_OTHER,
+ scancode);
ictx->rc_toggle = 0x0;
ictx->rc_scancode = scancode;
 
/* Look for the release of a button */
if (keycode == KEY_RESERVED) {
release = scancode & ~0x4000;
-   keycode = rc_g_keycode_from_table(ictx->rdev, release);
+   keycode = rc_g_keycode_from_table(ictx->rdev,
+ ictx->rc_type == 
RC_BIT_RC6_MCE ?
+ RC_TYPE_RC6_MCE : 
RC_TYPE_OTHER,
+ release);
if (keycode != KEY_RESERVED)
is_release_code = true;
}
@@ -1202,7 +1208,7 @@ static u32 imon_mce_key_lookup(struct imon_context *ictx, 
u32 scancode)
scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT;
 
ictx->rc_scancode = scancode;
-   keycode = rc_g_keycode_from_table(ictx->rdev, scancode);
+   keycode = rc_g_keycode_from_table(ictx->rdev, RC_TYPE_RC6_MCE, 
scancode);
 
/* not used in mce mode, but make sure we know its false */
ictx->release_code = false;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 00a0879..ee77ad3 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -102,7 +102,7 @@ EXPORT_SYMBOL_GPL(rc_map_unregister);
 
 
 static struct rc_map_table empty[] = {
-   { 0x2a, KEY_COFFEE },
+   { RC_TYPE_OTHER, 0x2a, KEY_COFFEE },
 };
 
 static struct rc_map_list empty_map = {
@@ -118,7 +118,6 @@ static struct rc_map_list empty_map = {
  * ir_create_table() - initializes a scancode table
  * @rc_map:the rc_map to initialize
  * @name:  name to assign to the table
- * @rc_type:   ir type to assign to the new table
  * @size:  initial size o

[PATCH 12/49] rc-core: simplify sysfs code

2014-04-03 Thread David Härdeman
Simplify and cleanup the sysfs code a bit.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/ir-raw.c  |6 +
 drivers/media/rc/rc-main.c |  265 
 2 files changed, 150 insertions(+), 121 deletions(-)

diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
index 763c9d1..f38557f 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
@@ -240,6 +240,11 @@ ir_raw_get_allowed_protocols(void)
return protocols;
 }
 
+static int change_protocol(struct rc_dev *dev, u64 *rc_type) {
+   /* the caller will update dev->enabled_protocols */
+   return 0;
+}
+
 /*
  * Used to (un)register raw event clients
  */
@@ -257,6 +262,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 
dev->raw->dev = dev;
rc_set_enabled_protocols(dev, ~0);
+   dev->change_protocol = change_protocol;
rc = kfifo_alloc(&dev->raw->kfifo,
 sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
 GFP_KERNEL);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index ee77ad3..df3175d 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -959,7 +959,7 @@ struct rc_filter_attribute {
 /**
  * show_protocols() - shows the current/wakeup IR protocol(s)
  * @device:the device descriptor
- * @mattr: the device attribute struct (unused)
+ * @mattr: the device attribute struct
  * @buf:   a pointer to the output buffer
  *
  * This routine is a callback routine for input read the IR protocol type(s).
@@ -985,20 +985,21 @@ static ssize_t show_protocols(struct device *device,
 
mutex_lock(&dev->lock);
 
-   enabled = dev->enabled_protocols[fattr->type];
-   if (dev->driver_type == RC_DRIVER_SCANCODE ||
-   fattr->type == RC_FILTER_WAKEUP)
-   allowed = dev->allowed_protocols[fattr->type];
-   else if (dev->raw)
-   allowed = ir_raw_get_allowed_protocols();
-   else {
-   mutex_unlock(&dev->lock);
-   return -ENODEV;
+   if (fattr->type == RC_FILTER_NORMAL) {
+   enabled = dev->enabled_protocols[RC_FILTER_NORMAL];
+   if (dev->raw)
+   allowed = ir_raw_get_allowed_protocols();
+   else
+   allowed = dev->allowed_protocols[RC_FILTER_NORMAL];
+   } else {
+   enabled = dev->enabled_protocols[RC_FILTER_WAKEUP];
+   allowed = dev->allowed_protocols[RC_FILTER_WAKEUP];
}
 
-   IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
-  (long long)allowed,
-  (long long)enabled);
+   mutex_unlock(&dev->lock);
+
+   IR_dprintk(1, "%s: allowed - 0x%llx, enabled - 0x%llx\n",
+  __func__, (long long)allowed, (long long)enabled);
 
for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
if (allowed & enabled & proto_names[i].type)
@@ -1014,62 +1015,29 @@ static ssize_t show_protocols(struct device *device,
tmp--;
*tmp = '\n';
 
-   mutex_unlock(&dev->lock);
-
return tmp + 1 - buf;
 }
 
 /**
- * store_protocols() - changes the current/wakeup IR protocol(s)
- * @device:the device descriptor
- * @mattr: the device attribute struct (unused)
- * @buf:   a pointer to the input buffer
- * @len:   length of the input buffer
+ * parse_protocol_change() - parses a protocol change request
+ * @protocols: pointer to the bitmask of current protocols
+ * @buf:   pointer to the buffer with a list of changes
  *
- * This routine is for changing the IR protocol type.
- * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]protocols.
- * Writing "+proto" will add a protocol to the list of enabled protocols.
- * Writing "-proto" will remove a protocol from the list of enabled protocols.
+ * Writing "+proto" will add a protocol to the protocol mask.
+ * Writing "-proto" will remove a protocol from protocol mask.
  * Writing "proto" will enable only "proto".
  * Writing "none" will disable all protocols.
- * Returns -EINVAL if an invalid protocol combination or unknown protocol name
- * is used, otherwise @len.
- *
- * dev->lock is taken to guard against races between device
- * registration, store_protocols and show_protocols.
+ * Returns the number of changes performed or a negative error code.
  */
-static ssize_t store_protocols(struct device *device,
-  struct device_attribute *mattr,
-  const char *data,
-  size_t len)
+static int parse_protocol_change(u64 *protocols, const char *buf)
 {
-   struct rc_dev *dev = to_rc_dev(device);
-   struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
-   bool enable, disable;
const char *tmp;
-   u64 old_type, type;
+   unsigned count = 0;
+   bool enable, disable;
u64 mask;
-   int

[PATCH 10/49] [RFC] rc-core: use the full 32 bits for NEC scancodes

2014-04-03 Thread David Härdeman
Using the full 32 bits for all kinds of NEC scancodes simplifies rc-core
and the nec decoder without any loss of functionality.

In order to maintain backwards compatibility, some heuristics are added
in rc-main.c to convert scancodes to NEC32 as necessary.

I plan to introduce a different ioctl later which makes the protocol
explicit (and which expects all NEC scancodes to be 32 bit, thereby
removing the need for guesswork).

Signed-off-by: David Härdeman 
---
 drivers/media/pci/saa7134/saa7134-input.c |6 +-
 drivers/media/rc/img-ir/img-ir-nec.c  |   79 ++--
 drivers/media/rc/ir-nec-decoder.c |   28 ++---
 drivers/media/rc/keymaps/rc-tivo.c|   95 ++---
 drivers/media/rc/rc-main.c|   53 
 drivers/media/usb/dvb-usb-v2/af9015.c |   22 +--
 drivers/media/usb/dvb-usb-v2/af9035.c |   15 +
 drivers/media/usb/dvb-usb-v2/az6007.c |   16 +
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c   |   16 +
 drivers/media/usb/dvb-usb/dib0700_core.c  |   21 ++
 drivers/media/usb/em28xx/em28xx-input.c   |   14 +---
 include/media/rc-map.h|   16 -
 12 files changed, 147 insertions(+), 234 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-input.c 
b/drivers/media/pci/saa7134/saa7134-input.c
index 887429b..4ba61ff 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -342,11 +342,9 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, enum 
rc_type *protocol,
return -EIO;
}
 
-   if (data[9] != (unsigned char)(~data[8]))
-   return 0;
-
*protocol = RC_TYPE_NEC;
-   *scancode = RC_SCANCODE_NECX(data[11] << 8 | data[10], data[9]);
+   *scancode = RC_SCANCODE_NEC32(data[11] << 24 | data[10] << 16 |
+ data[9]  << 8  | data[8]);
*toggle = 0;
return 1;
 }
diff --git a/drivers/media/rc/img-ir/img-ir-nec.c 
b/drivers/media/rc/img-ir/img-ir-nec.c
index ee45795..133ea45 100644
--- a/drivers/media/rc/img-ir/img-ir-nec.c
+++ b/drivers/media/rc/img-ir/img-ir-nec.c
@@ -5,42 +5,20 @@
  */
 
 #include "img-ir-hw.h"
-#include 
 
 /* Convert NEC data to a scancode */
 static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol,
   u32 *scancode, u64 enabled_protocols)
 {
-   unsigned int addr, addr_inv, data, data_inv;
/* a repeat code has no data */
if (!len)
return IMG_IR_REPEATCODE;
+
if (len != 32)
return -EINVAL;
-   /* raw encoding: ddDDaaAA */
-   addr = (raw >>  0) & 0xff;
-   addr_inv = (raw >>  8) & 0xff;
-   data = (raw >> 16) & 0xff;
-   data_inv = (raw >> 24) & 0xff;
-   if ((data_inv ^ data) != 0xff) {
-   /* 32-bit NEC (used by Apple and TiVo remotes) */
-   /* scan encoding: AAaaDDdd (LSBit first) */
-   *scancode = bitrev8(addr) << 24 |
-   bitrev8(addr_inv) << 16 |
-   bitrev8(data) <<  8 |
-   bitrev8(data_inv);
-   } else if ((addr_inv ^ addr) != 0xff) {
-   /* Extended NEC */
-   /* scan encoding: AAaaDD */
-   *scancode = addr << 16 |
-   addr_inv <<  8 |
-   data;
-   } else {
-   /* Normal NEC */
-   /* scan encoding: AADD */
-   *scancode = addr << 8 |
-   data;
-   }
+
+   /* raw encoding : ddDDaaAA -> scan encoding: AAaaDDdd */
+   *scancode = swab32((u32)raw);
*protocol = RC_TYPE_NEC;
return IMG_IR_SCANCODE;
 }
@@ -49,52 +27,9 @@ static int img_ir_nec_scancode(int len, u64 raw, enum 
rc_type *protocol,
 static int img_ir_nec_filter(const struct rc_scancode_filter *in,
 struct img_ir_filter *out, u64 protocols)
 {
-   unsigned int addr, addr_inv, data, data_inv;
-   unsigned int addr_m, addr_inv_m, data_m, data_inv_m;
-
-   data   = in->data & 0xff;
-   data_m = in->mask & 0xff;
-
-   if ((in->data | in->mask) & 0xff00) {
-   /* 32-bit NEC (used by Apple and TiVo remotes) */
-   /* scan encoding: AAaaDDdd (LSBit first) */
-   addr   = bitrev8(in->data >> 24);
-   addr_m = bitrev8(in->mask >> 24);
-   addr_inv   = bitrev8(in->data >> 16);
-   addr_inv_m = bitrev8(in->mask >> 16);
-   data   = bitrev8(in->data >>  8);
-   data_m = bitrev8(in->mask >>  8);
-   data_inv   = bitrev8(in->data >>  0);
-   data_inv_m = bitrev8(in->mask >>  0);
-   } else if ((in->data | in->mask) & 0x00ff) {
-   /* Extended NEC */
-   /* scan encoding AAaaDD */
-   addr 

[PATCH 14/49] rc-core: rename dev->scanmask to dev->scancode_mask

2014-04-03 Thread David Härdeman
We already have dev->scancode_filter and dev->scancode_wakeup_filter
so rename dev->scanmask to dev->scancode_mask for consistency.

Signed-off-by: David Härdeman 
---
 drivers/media/pci/cx88/cx88-input.c   |2 +-
 drivers/media/pci/ttpci/budget-ci.c   |2 +-
 drivers/media/rc/rc-main.c|4 ++--
 drivers/media/usb/cx231xx/cx231xx-input.c |2 +-
 drivers/media/usb/tm6000/tm6000-input.c   |2 +-
 include/media/rc-core.h   |5 +++--
 6 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/media/pci/cx88/cx88-input.c 
b/drivers/media/pci/cx88/cx88-input.c
index 93ff6a7..3f1342c 100644
--- a/drivers/media/pci/cx88/cx88-input.c
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -478,7 +478,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev 
*pci)
dev->priv = core;
dev->open = cx88_ir_open;
dev->close = cx88_ir_close;
-   dev->scanmask = hardware_mask;
+   dev->scancode_mask = hardware_mask;
 
if (ir->sampling) {
dev->driver_type = RC_DRIVER_IR_RAW;
diff --git a/drivers/media/pci/ttpci/budget-ci.c 
b/drivers/media/pci/ttpci/budget-ci.c
index 41ce7de..1feeeff 100644
--- a/drivers/media/pci/ttpci/budget-ci.c
+++ b/drivers/media/pci/ttpci/budget-ci.c
@@ -234,7 +234,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
break;
}
if (!budget_ci->ir.full_rc5)
-   dev->scanmask = 0xff;
+   dev->scancode_mask = 0xff;
 
error = rc_register_device(dev);
if (error) {
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 287191b..2788102 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -287,8 +287,8 @@ static unsigned int ir_establish_scancode(struct rc_dev 
*dev,
 * IR tables from other remotes. So, we support specifying a mask to
 * indicate the valid bits of the scancodes.
 */
-   if (dev->scanmask)
-   entry->scancode &= dev->scanmask;
+   if (dev->scancode_mask)
+   entry->scancode &= dev->scancode_mask;
 
/*
 * First check if we already have a mapping for this command.
diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c 
b/drivers/media/usb/cx231xx/cx231xx-input.c
index adcdd92..05f0434 100644
--- a/drivers/media/usb/cx231xx/cx231xx-input.c
+++ b/drivers/media/usb/cx231xx/cx231xx-input.c
@@ -91,7 +91,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
dev->init_data.get_key = get_key_isdbt;
dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name;
/* The i2c micro-controller only outputs the cmd part of NEC protocol */
-   dev->init_data.rc_dev->scanmask = 0xff;
+   dev->init_data.rc_dev->scancode_mask = 0xff;
dev->init_data.rc_dev->driver_name = "cx231xx";
dev->init_data.type = RC_BIT_NEC;
info.addr = 0x30;
diff --git a/drivers/media/usb/tm6000/tm6000-input.c 
b/drivers/media/usb/tm6000/tm6000-input.c
index 8a519f5..26b2ebb 100644
--- a/drivers/media/usb/tm6000/tm6000-input.c
+++ b/drivers/media/usb/tm6000/tm6000-input.c
@@ -443,7 +443,7 @@ int tm6000_ir_init(struct tm6000_core *dev)
/* input setup */
rc->allowed_protocols = RC_BIT_RC5 | RC_BIT_NEC;
/* Neded, in order to support NEC remotes with 24 or 32 bits */
-   rc->scanmask = 0x;
+   rc->scancode_mask = 0x;
rc->priv = ir;
rc->change_protocol = tm6000_ir_change_protocol;
if (dev->int_in.endp) {
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index e6784e8..5a082e7 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -98,11 +98,12 @@ enum rc_filter_type {
  * @enabled_wakeup_protocols: bitmask with the enabled RC_BIT_* wakeup 
protocols
  * @scancode_filter: scancode filter
  * @scancode_wakeup_filter: scancode wakeup filters
- * @scanmask: some hardware decoders are not capable of providing the full
+ * @scancode_mask: some hardware decoders are not capable of providing the full
  * scancode to the application. As this is a hardware limit, we can't do
  * anything with it. Yet, as the same keycode table can be used with other
  * devices, a mask is provided to allow its usage. Drivers should generally
  * leave this field in blank
+ * @users: number of current users of the device
  * @priv: driver-specific data
  * @keylock: protects the remaining members of the struct
  * @keypressed: whether a key is currently pressed
@@ -157,8 +158,8 @@ struct rc_dev {
u64 enabled_wakeup_protocols;
struct rc_scancode_filter   scancode_filter;
struct rc_scancode_filter   scancode_wakeup_filter;
+   u32 scancode_mask;
u32 users;
-   u32 scanmask;
void*priv;
spinlock_t

[PATCH 15/49] rc-core: merge rc5 and streamzap decoders

2014-04-03 Thread David Härdeman
Now that the protocol is part of the scancode, it is pretty easy to merge
the rc5 and streamzap decoders. An additional advantage is that the decoder
is now stricter as it waits for the trailing silence before determining that
a command is a valid rc5/streamzap command (which avoids collisions that I've
seen with e.g. Sony protocols).

Signed-off-by: David Härdeman 
---
 drivers/media/rc/Kconfig|   12 --
 drivers/media/rc/Makefile   |1 
 drivers/media/rc/ir-rc5-decoder.c   |   72 --
 drivers/media/rc/ir-rc5-sz-decoder.c|  154 ---
 drivers/media/rc/keymaps/rc-streamzap.c |4 -
 drivers/media/rc/rc-core-priv.h |8 --
 drivers/media/rc/streamzap.c|   10 --
 7 files changed, 43 insertions(+), 218 deletions(-)
 delete mode 100644 drivers/media/rc/ir-rc5-sz-decoder.c

diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 8fbd377..6097ff4 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -84,18 +84,6 @@ config IR_SONY_DECODER
   Enable this option if you have an infrared remote control which
   uses the Sony protocol, and you need software decoding support.
 
-config IR_RC5_SZ_DECODER
-   tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
-   depends on RC_CORE
-   select BITREVERSE
-   default y
-
-   ---help---
-  Enable this option if you have IR with RC-5 (streamzap) protocol,
-  and if the IR is decoded in software. (The Streamzap PC Remote
-  uses an IR protocol that is almost standard RC-5, but not quite,
-  as it uses an additional bit).
-
 config IR_SANYO_DECODER
tristate "Enable IR raw decoder for the Sanyo protocol"
depends on RC_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index f8b54ff..d326d4d 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
 obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
 obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
 obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
-obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
 obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
 obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o
 obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
diff --git a/drivers/media/rc/ir-rc5-decoder.c 
b/drivers/media/rc/ir-rc5-decoder.c
index 04ce42f..93168da 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -1,6 +1,7 @@
-/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
+/* ir-rc5-decoder.c - decoder for RC5(x) and StreamZap protocols
  *
  * Copyright (C) 2010 by Mauro Carvalho Chehab
+ * Copyright (C) 2010 by Jarod Wilson 
  *
  * 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
@@ -13,23 +14,22 @@
  */
 
 /*
- * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
- * There are other variants that use a different number of bits.
- * This is currently unsupported.
- * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
- * the first two bits are start bits, and a third one is a filing bit
+ * This decoder handles the 14 bit RC5 protocol, 15 bit "StreamZap" protocol
+ * and 20 bit RC5x protocol.
  */
 
 #include "rc-core-priv.h"
 #include 
 
 #define RC5_NBITS  14
+#define RC5_SZ_NBITS   15
 #define RC5X_NBITS 20
 #define CHECK_RC5X_NBITS   8
 #define RC5_UNIT   88 /* ns */
 #define RC5_BIT_START  (1 * RC5_UNIT)
 #define RC5_BIT_END(1 * RC5_UNIT)
 #define RC5X_SPACE (4 * RC5_UNIT)
+#define RC5_TRAILER(10 * RC5_UNIT) /* In reality, approx 100 */
 
 enum rc5_state {
STATE_INACTIVE,
@@ -66,7 +66,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct 
ir_raw_event ev)
goto out;
 
 again:
-   IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
+   IR_dprintk(2, "RC5(x/sz) decode started at state %i (%uus %s)\n",
   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 
if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
@@ -80,12 +80,15 @@ again:
 
data->state = STATE_BIT_START;
data->count = 1;
-   /* We just need enough bits to get to STATE_CHECK_RC5X */
-   data->wanted_bits = RC5X_NBITS;
decrease_duration(&ev, RC5_BIT_START);
goto again;
 
case STATE_BIT_START:
+   if (!ev.pulse && geq_margin(ev.duration, RC5_TRAILER, RC5_UNIT 
/ 2)) {
+   data->state = STATE_FINISHED;
+   goto again;
+   }
+
if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
break;
 
@@ 

[PATCH 18/49] rc-core: allow chardev to be read

2014-04-03 Thread David Härdeman
This patch is the first step towards making the rc chardev usable by adding
read functionality.

Basically the implementation mimics what evdev does. Userspace applications can
open the rc device and read rc_event structs with data. Only some basic events
are supported for now but later patches will add further events.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-main.c |  154 +++-
 include/media/rc-core.h|   40 +++
 2 files changed, 189 insertions(+), 5 deletions(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 9c7bdb8..5ce0cdb 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -22,12 +22,14 @@
 #include 
 #include 
 #include 
+#include 
 #include "rc-core-priv.h"
 
 /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
-#define IR_TAB_MIN_SIZE256
-#define IR_TAB_MAX_SIZE8192
-#define RC_DEV_MAX 256
+#define IR_TAB_MIN_SIZE256
+#define IR_TAB_MAX_SIZE8192
+#define RC_DEV_MAX 256
+#define RC_RX_BUFFER_SIZE  1024
 
 /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
 #define IR_KEYPRESS_TIMEOUT 250
@@ -44,16 +46,75 @@ static dev_t rc_devt;
 /**
  * struct rc_client - keeps track of processes which have opened a rc chardev
  * @dev: the &struct rc_dev which is being controlled
+ * @rxlock: protects the rxfifo
+ * @rxfifo: stores rx events which can be read by the process
  * @fasync: keeps track of the fasync queue
  * @node: list of current clients for the rc device (protected by client_lock
  * in &struct rc_dev)
  */
 struct rc_client {
struct rc_dev *dev;
+   spinlock_t rxlock;
+   DECLARE_KFIFO(rxfifo, struct rc_event, RC_RX_BUFFER_SIZE);
struct fasync_struct *fasync;
struct list_head node;
 };
 
+/**
+ * rc_client_event() - passes an rc event to a specific client
+ * @client:the &struct rc_client for this client
+ * @type:  the event type
+ * @code:  the event code (type specific)
+ * @val:   the event value (type and code specific)
+ *
+ * This function writes a &struct rc_event entry to the client kfifo
+ * for later reading from userspace.
+ */
+static void rc_client_event(struct rc_client *client, u16 type,
+   u16 code, u32 val)
+{
+   unsigned long flags;
+   struct rc_event ev;
+
+   ev.type = type;
+   ev.code = code;
+   ev.val = val;
+
+   spin_lock_irqsave(&client->rxlock, flags);
+   if (kfifo_is_full(&client->rxfifo)) {
+   kfifo_skip(&client->rxfifo);
+   ev.type = RC_CORE;
+   ev.code = RC_CORE_DROPPED;
+   ev.val = 1;
+   }
+
+   kfifo_in(&client->rxfifo, &ev, 1);
+   kill_fasync(&client->fasync, SIGIO, POLL_IN);
+   spin_unlock_irqrestore(&client->rxlock, flags);
+}
+
+/**
+ * rc_event() - sends an rc_event to all listeners
+ * @dev:   the struct rc_dev of the device generating the event
+ * @type:  the event type
+ * @code:  the event code (type specific)
+ * @val:   the event value (type and code specific)
+ *
+ * This function passes an rc event to all clients.
+ */
+void rc_event(struct rc_dev *dev, u16 type, u16 code, u32 val)
+{
+   struct rc_client *client;
+
+   rcu_read_lock();
+   list_for_each_entry_rcu(client, &dev->client_list, node)
+   rc_client_event(client, type, code, val);
+   rcu_read_unlock();
+
+   wake_up_interruptible(&dev->rxwait);
+}
+EXPORT_SYMBOL_GPL(rc_event);
+
 static struct rc_map_list *seek_rc_map(const char *name)
 {
struct rc_map_list *map = NULL;
@@ -753,6 +814,7 @@ void rc_repeat(struct rc_dev *dev)
 
input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode);
input_sync(dev->input_dev);
+   rc_event(dev, RC_KEY, RC_KEY_REPEAT, 1);
 
if (!dev->keypressed)
goto out;
@@ -788,6 +850,15 @@ static void ir_do_keydown(struct rc_dev *dev, enum rc_type 
protocol,
ir_do_keyup(dev, false);
 
input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
+   rc_event(dev, RC_KEY, RC_KEY_PROTOCOL, protocol);
+   /*
+* NOTE: If we ever get > 32 bit scancodes, we need to break the
+*   scancode into 32 bit pieces and feed them to userspace
+*   as one or more RC_KEY_SCANCODE_PART events followed
+*   by a final RC_KEY_SCANCODE event.
+*/
+   rc_event(dev, RC_KEY, RC_KEY_SCANCODE, scancode);
+   rc_event(dev, RC_KEY, RC_KEY_TOGGLE, toggle);
 
if (new_event && keycode != KEY_RESERVED) {
/* Register a keypress */
@@ -997,6 +1068,7 @@ static ssize_t show_protocols(struct device *device,
if (!dev)
return -EINVAL;
 
+   rc_event(dev, RC_KEY, RC_KEY_REPEAT, 1);
mutex_lock(&dev->lock);
 
if (fattr->type == RC_FILTER_NORMAL) {
@@ -1366,6 +1438,8 @@

[PATCH 16/49] rc-core: use an IDA rather than a bitmap

2014-04-03 Thread David Härdeman
This patch changes rc-core to use an IDA rather than a bitmap to assign
unique numbers to each rc device. This is in preparation for introducing
rc-core chardevs.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/ir-raw.c  |2 +-
 drivers/media/rc/rc-main.c |   40 
 include/media/rc-core.h|4 ++--
 3 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
index 2a7f858..aed2997 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
@@ -271,7 +271,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 
spin_lock_init(&dev->raw->lock);
dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
-  "rc%ld", dev->devno);
+  "rc%u", dev->minor);
 
if (IS_ERR(dev->raw->thread)) {
rc = PTR_ERR(dev->raw->thread);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 2788102..42268f3 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -18,17 +18,15 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include "rc-core-priv.h"
 
-/* Bitmap to store allocated device numbers from 0 to IRRCV_NUM_DEVICES - 1 */
-#define IRRCV_NUM_DEVICES  256
-static DECLARE_BITMAP(ir_core_dev_number, IRRCV_NUM_DEVICES);
-
 /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
 #define IR_TAB_MIN_SIZE256
 #define IR_TAB_MAX_SIZE8192
+#define RC_DEV_MAX 256
 
 /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
 #define IR_KEYPRESS_TIMEOUT 250
@@ -38,6 +36,9 @@ static LIST_HEAD(rc_map_list);
 static DEFINE_SPINLOCK(rc_map_lock);
 static struct led_trigger *led_feedback;
 
+/* Used to keep track of rc devices */
+static DEFINE_IDA(rc_ida);
+
 static struct rc_map_list *seek_rc_map(const char *name)
 {
struct rc_map_list *map = NULL;
@@ -1442,7 +1443,9 @@ int rc_register_device(struct rc_dev *dev)
static bool raw_init = false; /* raw decoders loaded? */
struct rc_map *rc_map;
const char *path;
-   int rc, devno, attr = 0;
+   int attr = 0;
+   int minor;
+   int rc;
 
if (!dev || !dev->map_name)
return -EINVAL;
@@ -1462,13 +1465,13 @@ int rc_register_device(struct rc_dev *dev)
if (dev->close)
dev->input_dev->close = ir_close;
 
-   do {
-   devno = find_first_zero_bit(ir_core_dev_number,
-   IRRCV_NUM_DEVICES);
-   /* No free device slots */
-   if (devno >= IRRCV_NUM_DEVICES)
-   return -ENOMEM;
-   } while (test_and_set_bit(devno, ir_core_dev_number));
+   minor = ida_simple_get(&rc_ida, 0, RC_DEV_MAX, GFP_KERNEL);
+   if (minor < 0)
+   return minor;
+
+   dev->minor = minor;
+   dev_set_name(&dev->dev, "rc%u", dev->minor);
+   dev_set_drvdata(&dev->dev, dev);
 
dev->dev.groups = dev->sysfs_groups;
dev->sysfs_groups[attr++] = &rc_dev_protocol_attr_grp;
@@ -1488,9 +1491,6 @@ int rc_register_device(struct rc_dev *dev)
 */
mutex_lock(&dev->lock);
 
-   dev->devno = devno;
-   dev_set_name(&dev->dev, "rc%ld", dev->devno);
-   dev_set_drvdata(&dev->dev, dev);
rc = device_add(&dev->dev);
if (rc)
goto out_unlock;
@@ -1558,8 +1558,8 @@ int rc_register_device(struct rc_dev *dev)
 
mutex_unlock(&dev->lock);
 
-   IR_dprintk(1, "Registered rc%ld (driver: %s, remote: %s, mode %s)\n",
-  dev->devno,
+   IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n",
+  dev->minor,
   dev->driver_name ? dev->driver_name : "unknown",
   rc_map->name ? rc_map->name : "unknown",
   dev->driver_type == RC_DRIVER_IR_RAW ? "raw" : "cooked");
@@ -1578,7 +1578,7 @@ out_dev:
device_del(&dev->dev);
 out_unlock:
mutex_unlock(&dev->lock);
-   clear_bit(dev->devno, ir_core_dev_number);
+   ida_simple_remove(&rc_ida, minor);
return rc;
 }
 EXPORT_SYMBOL_GPL(rc_register_device);
@@ -1590,8 +1590,6 @@ void rc_unregister_device(struct rc_dev *dev)
 
del_timer_sync(&dev->timer_keyup);
 
-   clear_bit(dev->devno, ir_core_dev_number);
-
if (dev->driver_type == RC_DRIVER_IR_RAW)
ir_raw_event_unregister(dev);
 
@@ -1604,6 +1602,8 @@ void rc_unregister_device(struct rc_dev *dev)
 
device_del(&dev->dev);
 
+   ida_simple_remove(&rc_ida, dev->minor);
+
rc_free_device(dev);
 }
 
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 5a082e7..ca3d836 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -87,7 +87,7 @@ enum rc_filter_type {
  * @rc_map: current scan/key table
  * @lock: used to ensure we've filled in al

[PATCH 19/49] rc-core: use a kfifo for TX data

2014-04-03 Thread David Härdeman
Using a per rc_dev TX kfifo for TX data simplifies the device drivers and lays
the ground for the next patch.

This means that every driver with TX capabilities need to be changed at the
same time.

It should be noted that the TX functionality in nuvoton-cir.c is, and was,
probably broken before and after this patch.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/ene_ir.c|   61 +
 drivers/media/rc/ene_ir.h|9 +--
 drivers/media/rc/iguanair.c  |   51 -
 drivers/media/rc/ir-lirc-codec.c |  100 ++
 drivers/media/rc/ir-raw.c|   41 ++
 drivers/media/rc/ite-cir.c   |   35 +---
 drivers/media/rc/mceusb.c|   43 --
 drivers/media/rc/nuvoton-cir.c   |   57 +++
 drivers/media/rc/nuvoton-cir.h   |9 ---
 drivers/media/rc/rc-loopback.c   |   25 +---
 drivers/media/rc/rc-main.c   |9 +++
 drivers/media/rc/redrat3.c   |  113 ++
 drivers/media/rc/winbond-cir.c   |   79 +++
 include/media/rc-core.h  |9 +++
 14 files changed, 363 insertions(+), 278 deletions(-)

diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index d16d9b4..cab5da9 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -615,7 +615,8 @@ static void ene_tx_enable(struct ene_device *dev)
 static void ene_tx_disable(struct ene_device *dev)
 {
ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1);
-   dev->tx_buffer = NULL;
+   dev->tx_ev.val = 0;
+   kfifo_reset_out(&dev->rdev->txfifo);
 }
 
 
@@ -623,18 +624,16 @@ static void ene_tx_disable(struct ene_device *dev)
 static void ene_tx_sample(struct ene_device *dev)
 {
u8 raw_tx;
-   u32 sample;
-   bool pulse = dev->tx_sample_pulse;
-
-   if (!dev->tx_buffer) {
-   pr_warn("TX: BUG: attempt to transmit NULL buffer\n");
-   return;
-   }
 
/* Grab next TX sample */
-   if (!dev->tx_sample) {
+   while (!dev->tx_ev.val) {
+   int tmp;
 
-   if (dev->tx_pos == dev->tx_len) {
+   tmp = ir_raw_get_tx_event(dev->rdev, &dev->tx_ev);
+   if (tmp < 0) {
+   dev->tx_ev.val = 0;
+   continue;
+   } else if (tmp == 0) {
if (!dev->tx_done) {
dbg("TX: no more data to send");
dev->tx_done = true;
@@ -647,25 +646,23 @@ static void ene_tx_sample(struct ene_device *dev)
}
}
 
-   sample = dev->tx_buffer[dev->tx_pos++];
-   dev->tx_sample_pulse = !dev->tx_sample_pulse;
-
-   dev->tx_sample = DIV_ROUND_CLOSEST(sample, sample_period);
-
-   if (!dev->tx_sample)
-   dev->tx_sample = 1;
+   dev->tx_ev.val = DIV_ROUND_CLOSEST(dev->tx_ev.val,
+  US_TO_NS(sample_period));
+   if (!dev->tx_ev.val)
+   dev->tx_ev.val = 1;
}
 
-   raw_tx = min(dev->tx_sample , (unsigned int)ENE_CIRRLC_OUT_MASK);
-   dev->tx_sample -= raw_tx;
+   raw_tx = min_t(unsigned, dev->tx_ev.val, ENE_CIRRLC_OUT_MASK);
+   dev->tx_ev.val -= raw_tx;
 
dbg("TX: sample %8d (%s)", raw_tx * sample_period,
-   pulse ? "pulse" : "space");
-   if (pulse)
+   dev->tx_ev.code == RC_IR_PULSE ? "pulse" : "space");
+
+   if (dev->tx_ev.code == RC_IR_PULSE)
raw_tx |= ENE_CIRRLC_OUT_PULSE;
 
ene_write_reg(dev,
-   dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx);
+ dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx);
 
dev->tx_reg = !dev->tx_reg;
 exit:
@@ -968,20 +965,16 @@ static void ene_set_idle(struct rc_dev *rdev, bool idle)
 }
 
 /* outside interface: transmit */
-static int ene_transmit(struct rc_dev *rdev, unsigned *buf, unsigned n)
+static int ene_transmit(struct rc_dev *rdev, unsigned count)
 {
struct ene_device *dev = rdev->priv;
unsigned long flags;
 
-   dev->tx_buffer = buf;
-   dev->tx_len = n;
-   dev->tx_pos = 0;
dev->tx_reg = 0;
-   dev->tx_done = 0;
-   dev->tx_sample = 0;
-   dev->tx_sample_pulse = 0;
+   dev->tx_done = false;
 
-   dbg("TX: %d samples", dev->tx_len);
+   dev->tx_ev.val = 0;
+   dbg("TX: %d samples", count);
 
spin_lock_irqsave(&dev->hw_lock, flags);
 
@@ -998,9 +991,11 @@ static int ene_transmit(struct rc_dev *rdev, unsigned 
*buf, unsigned n)
spin_lock_irqsave(&dev->hw_lock, flags);
ene_tx_disable(dev);
spin_unlock_irqrestore(&dev->hw_lock, flags);
-   } else
-   dbg("TX: done");
-   return n;

[PATCH 17/49] rc-core: add chardev

2014-04-03 Thread David Härdeman
This patch lays the groundwork for adding a rc-core chardev.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/ir-raw.c  |2 
 drivers/media/rc/rc-main.c |  284 +++-
 include/media/rc-core.h|   11 +-
 3 files changed, 238 insertions(+), 59 deletions(-)

diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
index aed2997..7eb347a 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
@@ -271,7 +271,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 
spin_lock_init(&dev->raw->lock);
dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
-  "rc%u", dev->minor);
+  dev_name(&dev->dev));
 
if (IS_ERR(dev->raw->thread)) {
rc = PTR_ERR(dev->raw->thread);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 42268f3..9c7bdb8 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -38,6 +39,20 @@ static struct led_trigger *led_feedback;
 
 /* Used to keep track of rc devices */
 static DEFINE_IDA(rc_ida);
+static dev_t rc_devt;
+
+/**
+ * struct rc_client - keeps track of processes which have opened a rc chardev
+ * @dev: the &struct rc_dev which is being controlled
+ * @fasync: keeps track of the fasync queue
+ * @node: list of current clients for the rc device (protected by client_lock
+ * in &struct rc_dev)
+ */
+struct rc_client {
+   struct rc_dev *dev;
+   struct fasync_struct *fasync;
+   struct list_head node;
+};
 
 static struct rc_map_list *seek_rc_map(const char *name)
 {
@@ -844,47 +859,45 @@ void rc_keydown_notimeout(struct rc_dev *dev, enum 
rc_type protocol,
 }
 EXPORT_SYMBOL_GPL(rc_keydown_notimeout);
 
-int rc_open(struct rc_dev *rdev)
+int rc_open(struct rc_dev *dev)
 {
-   int rval = 0;
-
-   if (!rdev)
-   return -EINVAL;
+   int err = 0;
 
-   mutex_lock(&rdev->lock);
-   if (!rdev->users++ && rdev->open != NULL)
-   rval = rdev->open(rdev);
+   mutex_lock(&dev->lock);
 
-   if (rval)
-   rdev->users--;
+   if (dev->dead)
+   err = -ENODEV;
+   else if (!dev->users++ && dev->open) {
+   err = dev->open(dev);
+   if (err)
+   dev->users--;
+   }
 
-   mutex_unlock(&rdev->lock);
+   mutex_unlock(&dev->lock);
 
-   return rval;
+   return err;
 }
 EXPORT_SYMBOL_GPL(rc_open);
 
-static int ir_open(struct input_dev *idev)
+static int rc_input_open(struct input_dev *idev)
 {
struct rc_dev *rdev = input_get_drvdata(idev);
 
return rc_open(rdev);
 }
 
-void rc_close(struct rc_dev *rdev)
+void rc_close(struct rc_dev *dev)
 {
-   if (rdev) {
-   mutex_lock(&rdev->lock);
+   mutex_lock(&dev->lock);
 
-if (!--rdev->users && rdev->close != NULL)
-   rdev->close(rdev);
+   if (!dev->dead && !--dev->users && dev->close)
+   dev->close(dev);
 
-   mutex_unlock(&rdev->lock);
-   }
+   mutex_unlock(&dev->lock);
 }
 EXPORT_SYMBOL_GPL(rc_close);
 
-static void ir_close(struct input_dev *idev)
+static void rc_input_close(struct input_dev *idev)
 {
struct rc_dev *rdev = input_get_drvdata(idev);
rc_close(rdev);
@@ -1306,8 +1319,136 @@ unlock:
return (ret < 0) ? ret : len;
 }
 
+/**
+ * rc_attach_client() - attaches a new userspace client to a rc device
+ * @dev:   the rc device
+ * @client:the client to attach
+ */
+static void rc_attach_client(struct rc_dev *dev, struct rc_client *client)
+{
+   spin_lock(&dev->client_lock);
+   list_add_tail_rcu(&client->node, &dev->client_list);
+   spin_unlock(&dev->client_lock);
+}
+
+/**
+ * rc_detach_client() - detaches a userspace client from a rc device
+ * @dev:   the rc device
+ * @client:the client to detach
+ */
+static void rc_detach_client(struct rc_dev *dev, struct rc_client *client)
+{
+   spin_lock(&dev->client_lock);
+   list_del_rcu(&client->node);
+   spin_unlock(&dev->client_lock);
+   synchronize_rcu();
+}
+   
+/**
+ * rc_dev_open() - allows userspace to open() a rc device file
+ * @inode: the &struct inode corresponding to the device file
+ * @file:  the &struct file corresponding to the open() attempt
+ * @return:zero on success, or a negative error code
+ *
+ * This function (which implements open in &struct file_operations)
+ * allows userspace to open() a rc device file.
+ */
+static int rc_dev_open(struct inode *inode, struct file *file)
+{
+   struct rc_dev *dev = container_of(inode->i_cdev, struct rc_dev, cdev);
+   struct rc_client *client;
+   int err;
+
+   IR_dprintk(2, "Open attempt on %u\n", iminor(inode));
+
+   client = kzalloc(sizeof(*client), 

[PATCH 13/49] rc-core: remove protocol arrays

2014-04-03 Thread David Härdeman
The basic API of rc-core used to be:

dev = rc_allocate_device();
dev->x = a;
dev->y = b;
dev->z = c;
rc_register_device();

which is a pretty common pattern in the kernel, after the introduction of
protocol arrays the API looks something like:

dev = rc_allocate_device();
dev->x = a;
rc_set_allowed_protocols(dev, RC_BIT_X);
dev->z = c;
rc_register_device();

There's no real need for the protocols to be an array, so change it
back to be consistent (and in preparation for the following patches).

Signed-off-by: David Härdeman 
---
 drivers/hid/hid-picolcd_cir.c   |2 -
 drivers/media/common/siano/smsir.c  |2 -
 drivers/media/i2c/ir-kbd-i2c.c  |4 +-
 drivers/media/pci/cx23885/cx23885-input.c   |2 -
 drivers/media/pci/cx88/cx88-input.c |2 -
 drivers/media/rc/ati_remote.c   |2 -
 drivers/media/rc/ene_ir.c   |2 -
 drivers/media/rc/fintek-cir.c   |2 -
 drivers/media/rc/gpio-ir-recv.c |4 +-
 drivers/media/rc/iguanair.c |2 -
 drivers/media/rc/img-ir/img-ir-hw.c |   16 
 drivers/media/rc/imon.c |7 +--
 drivers/media/rc/ir-jvc-decoder.c   |2 -
 drivers/media/rc/ir-lirc-codec.c|2 -
 drivers/media/rc/ir-mce_kbd-decoder.c   |2 -
 drivers/media/rc/ir-nec-decoder.c   |2 -
 drivers/media/rc/ir-raw.c   |2 -
 drivers/media/rc/ir-rc5-decoder.c   |6 +--
 drivers/media/rc/ir-rc5-sz-decoder.c|2 -
 drivers/media/rc/ir-rc6-decoder.c   |6 +--
 drivers/media/rc/ir-sanyo-decoder.c |2 -
 drivers/media/rc/ir-sharp-decoder.c |2 -
 drivers/media/rc/ir-sony-decoder.c  |   10 ++---
 drivers/media/rc/ite-cir.c  |2 -
 drivers/media/rc/mceusb.c   |2 -
 drivers/media/rc/nuvoton-cir.c  |2 -
 drivers/media/rc/rc-loopback.c  |2 -
 drivers/media/rc/rc-main.c  |   38 +-
 drivers/media/rc/redrat3.c  |2 -
 drivers/media/rc/st_rc.c|2 -
 drivers/media/rc/streamzap.c|2 -
 drivers/media/rc/ttusbir.c  |2 -
 drivers/media/rc/winbond-cir.c  |2 -
 drivers/media/usb/dvb-usb-v2/dvb_usb_core.c |2 -
 drivers/media/usb/dvb-usb/dvb-usb-remote.c  |2 -
 drivers/media/usb/em28xx/em28xx-input.c |8 ++--
 drivers/media/usb/tm6000/tm6000-input.c |2 -
 include/media/rc-core.h |   56 ++-
 38 files changed, 89 insertions(+), 122 deletions(-)

diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
index cf1a9f1..59d5eb1 100644
--- a/drivers/hid/hid-picolcd_cir.c
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -114,7 +114,7 @@ int picolcd_init_cir(struct picolcd_data *data, struct 
hid_report *report)
 
rdev->priv = data;
rdev->driver_type  = RC_DRIVER_IR_RAW;
-   rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+   rdev->allowed_protos   = RC_BIT_ALL;
rdev->open = picolcd_cir_open;
rdev->close= picolcd_cir_close;
rdev->input_name   = data->hdev->name;
diff --git a/drivers/media/common/siano/smsir.c 
b/drivers/media/common/siano/smsir.c
index 6d7c0c8..273043e 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
 
dev->priv = coredev;
dev->driver_type = RC_DRIVER_IR_RAW;
-   rc_set_allowed_protocols(dev, RC_BIT_ALL);
+   dev->allowed_protocols = RC_BIT_ALL;
dev->map_name = sms_get_board(board_id)->rc_codes;
dev->driver_name = MODULE_NAME;
 
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index f9c4233..8311f1a 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -432,8 +432,8 @@ static int ir_probe(struct i2c_client *client, const struct 
i2c_device_id *id)
 * Initialize the other fields of rc_dev
 */
rc->map_name   = ir->ir_codes;
-   rc_set_allowed_protocols(rc, rc_type);
-   rc_set_enabled_protocols(rc, rc_type);
+   rc->allowed_protocols = rc_type;
+   rc->enabled_protocols = rc_type;
if (!rc->driver_name)
rc->driver_name = MODULE_NAME;
 
diff --git a/drivers/media/pci/cx23885/cx23885-input.c 
b/drivers/media/pci/cx23885/cx23885-input.c
index 097d0a0..1940c18 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -346,7 +346,7 @@ int cx23885_input_init(struct cx23885_dev *dev)
}
rc->dev.parent = &dev->pci->dev;
rc->driver_type = driver_type;
-   rc_set_allowed_protocols

[PATCH 20/49] rc-core: allow chardev to be written

2014-04-03 Thread David Härdeman
Add write functionality to the rc chardev (for use in transmitting remote
control commands on capable hardware).

The data format of the TX data is probably going to have to be dependent
on the rc_driver_type.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-main.c |   71 
 include/media/rc-core.h|2 +
 2 files changed, 73 insertions(+)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 43789b4..d7b24a1 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1531,6 +1531,72 @@ static ssize_t rc_read(struct file *file, char __user 
*buffer,
 }
 
 /**
+ * rc_write() - allows userspace to write data to transmit
+ * @file:  the &struct file corresponding to the previous open()
+ * @buffer:the userspace buffer to read data from
+ * @count: the number of bytes to read
+ * @ppos:  the file offset
+ * @return:the number of bytes written, or a negative error code
+ *
+ * This function (which implements write in &struct file_operations)
+ * allows userspace to transmit data using a suitable rc device
+ */
+static ssize_t rc_write(struct file *file, const char __user *buffer,
+   size_t count, loff_t *ppos)
+{
+   struct rc_client *client = file->private_data;
+   struct rc_dev *dev = client->dev;
+   ssize_t ret;
+   struct rc_event ev;
+
+   if (!dev->tx_ir)
+   return -ENOSYS;
+
+   if (count < sizeof(ev) || count % sizeof(ev))
+   return -EINVAL;
+
+again:
+   if (kfifo_is_full(&dev->txfifo) && !dev->dead &&
+   (file->f_flags & O_NONBLOCK))
+   return -EAGAIN;
+
+   ret = wait_event_interruptible(dev->txwait,
+  !kfifo_is_full(&dev->txfifo) ||
+  dev->dead);
+   if (ret)
+   return ret;
+
+   if (dev->dead)
+   return -ENODEV;
+
+   mutex_lock(&dev->txmutex);
+   for (ret = 0; ret + sizeof(ev) <= count; ret += sizeof(ev)) {
+   if (copy_from_user(&ev, buffer + ret, sizeof(ev))) {
+   kfifo_reset_out(&dev->txfifo);
+   mutex_unlock(&dev->txmutex);
+   return -EFAULT;
+   }
+
+   if (kfifo_in(&dev->txfifo, &ev, 1) != 1)
+   break;
+   }
+
+   if (ret == 0) {
+   mutex_unlock(&dev->txmutex);
+   goto again;
+   }
+
+   ret = dev->tx_ir(dev, ret / sizeof(ev));
+   mutex_unlock(&dev->txmutex);
+   wake_up_interruptible(&dev->txwait);
+
+   if (ret > 0)
+   ret *= sizeof(ev);
+
+   return ret;
+}
+
+/**
  * rc_poll() - allows userspace to poll rc device files
  * @file:  the &struct file corresponding to the previous open()
  * @wait:  used to keep track of processes waiting for poll events
@@ -1544,8 +1610,10 @@ static unsigned int rc_poll(struct file *file, 
poll_table *wait)
struct rc_client *client = file->private_data;
struct rc_dev *dev = client->dev;
 
+   poll_wait(file, &dev->txwait, wait);
poll_wait(file, &dev->rxwait, wait);
return ((kfifo_is_empty(&client->rxfifo) ? 0 : (POLLIN | POLLRDNORM)) |
+   (kfifo_is_full(&dev->txfifo) ? 0 : (POLLOUT | POLLWRNORM)) |
(!dev->dead ? 0 : (POLLHUP | POLLERR)));
 }
 
@@ -1572,6 +1640,7 @@ static const struct file_operations rc_fops = {
.open   = rc_dev_open,
.release= rc_release,
.read   = rc_read,
+   .write  = rc_write,
.poll   = rc_poll,
.fasync = rc_fasync,
.llseek = no_llseek,
@@ -1698,6 +1767,7 @@ struct rc_dev *rc_allocate_device(void)
INIT_LIST_HEAD(&dev->client_list);
spin_lock_init(&dev->client_lock);
mutex_init(&dev->txmutex);
+   init_waitqueue_head(&dev->txwait);
init_waitqueue_head(&dev->rxwait);
spin_lock_init(&dev->rc_map.lock);
spin_lock_init(&dev->keylock);
@@ -1904,6 +1974,7 @@ void rc_unregister_device(struct rc_dev *dev)
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
spin_unlock(&dev->client_lock);
wake_up_interruptible_all(&dev->rxwait);
+   wake_up_interruptible_all(&dev->txwait);
 
cdev_del(&dev->cdev);
 
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index ca22cf7..39f3794 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -133,6 +133,7 @@ enum rc_filter_type {
  * @client_lock: protects client_list
  * @txfifo: fifo with tx data to transmit
  * @txmutex: protects txfifo and serializes calls to @tx_ir
+ * @txwait: waitqueue for processes waiting to write data to the txfifo
  * @rxwait: waitqueue for processes waiting for data to read
  * @raw: additional data for raw pulse/space devices
  * @input_dev: the input child device used to 

[PATCH 21/49] rc-core: add ioctl support to the rc chardev

2014-04-03 Thread David Härdeman
Add basic support for ioctl operations on the rc chardev.

Only two ioctl's are defined for now: one to get the rc-core
version and one to get the driver type of a given chardev.

Userspace is expected to make sure that both match the expected
values before proceeding with any ioctl/read/write ops.

Signed-off-by: David Härdeman 
---
 Documentation/ioctl/ioctl-number.txt |1 +
 drivers/media/rc/rc-main.c   |   65 ++
 include/media/rc-core.h  |   19 ++
 3 files changed, 85 insertions(+)

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index d7e43fa..2868bc8 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -270,6 +270,7 @@ Code  Seq#(hex) Include FileComments
 'v'00-0F   linux/sonypi.h  conflict!
 'v'C0-FF   linux/meye.hconflict!
 'w'all CERN SCI driver
+'x'all media/rc-core.h Remote Control drivers
 'y'00-1F   packet based user level communications

 'z'00-3F   CAN bus cardconflict!
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index d7b24a1..477ad49 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1635,6 +1635,67 @@ static int rc_fasync(int fd, struct file *file, int on)
return fasync_helper(fd, file, on, &client->fasync);
 }
 
+/**
+ * rc_do_ioctl() - internal implementation of ioctl handling
+ * @dev:   the &struct rc_dev to perform the command on
+ * @cmd:   the ioctl command to perform
+ * @arg:   the argument to the ioctl cmd
+ * @return:zero on success, or a negative error code
+ *
+ * This function (which is called with the @dev mutex held) performs
+ * the actual processing of ioctl commands.
+ */
+static long rc_do_ioctl(struct rc_dev *dev, unsigned int cmd, unsigned long 
arg)
+{
+   void __user *p = (void __user *)arg;
+   unsigned int __user *ip = (unsigned int __user *)p;
+
+   switch (cmd) {
+
+   case RCIOCGVERSION:
+   return put_user(RC_VERSION, ip);
+
+   case RCIOCGTYPE:
+   return put_user(dev->driver_type, ip);
+   }
+
+   return -EINVAL;
+}
+
+/**
+ * rc_ioctl() - allows userspace to do ioctl operations on the rc device file
+ * @fd:the file descriptor corresponding to the opened rc 
device
+ * @file:  the &struct file corresponding to the previous open()
+ * @cmd:   the ioctl command to perform
+ * @arg:   the argument to the ioctl cmd
+ * @return:zero on success, or a negative error code
+ *
+ * This function (which implements the ioctl functionality in
+ * &struct file_operations) allows userspace to perform various ioctl
+ * operations on a rc device file.
+ */
+static long rc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+   struct rc_client *client = file->private_data;
+   struct rc_dev *dev = client->dev;
+   int ret;
+
+   ret = mutex_lock_interruptible(&dev->lock);
+   if (ret)
+   return ret;
+
+   if (dev->dead) {
+   ret = -ENODEV;
+   goto out;
+   }
+
+   ret = rc_do_ioctl(dev, cmd, arg);
+
+out:
+   mutex_unlock(&dev->lock);
+   return ret;
+}
+
 static const struct file_operations rc_fops = {
.owner  = THIS_MODULE,
.open   = rc_dev_open,
@@ -1644,6 +1705,10 @@ static const struct file_operations rc_fops = {
.poll   = rc_poll,
.fasync = rc_fasync,
.llseek = no_llseek,
+   .unlocked_ioctl = rc_ioctl,
+#ifdef CONFIG_COMPAT
+   .compat_ioctl   = rc_ioctl,
+#endif
 };
 
 /**
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 39f3794..660a331 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -30,6 +30,25 @@ do { 
\
pr_debug("%s: " fmt, __func__, ##__VA_ARGS__);  \
 } while (0)
 
+#define RC_VERSION 0x01
+
+/*
+ * ioctl definitions
+ *
+ * Note: userspace programs which wish to interact with /dev/rc/rc? devices
+ *  should make sure that the RC version and driver type is known
+ *  (by using RCIOCGVERSION and RCIOCGTYPE) before continuing with any
+ *  read/write/ioctl ops.
+ */
+#define RC_IOC_MAGIC   'x'
+
+/* get rc version */
+#define RCIOCGVERSION  _IOR(RC_IOC_MAGIC, 0x01, unsigned int)
+
+/* get driver/hardware type */
+#define RCIOCGTYPE _IOR(RC_IOC_MAGIC, 0x02, unsigned int)
+
+
 enum rc_driver_type {
RC_DRIVER_SCANCODE = 0, /* Driver or hardware generates a scancode */
RC_DRIVER_IR_RAW,   /* Needs a Infra-Red pulse/space decoder */

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body o

[PATCH 22/49] rc-core: add an ioctl for getting IR RX settings

2014-04-03 Thread David Härdeman
LIRC currently supports quite a number of ioctl's for getting/setting
various TX and RX parameters. One problem with the one-ioctl-per-parameter
approach is that it might be quite elaborate to reprogram the hardware
(an operation which will have to be done once for every parameter change).

LIRC has approached this problem by providing something similar to
database transactions (ioctl commands LIRC_SETUP_START and LIRC_SETUP_END)
which is one (complicated) way of doing it.

The proposed approach for rc-core instead uses a struct with all known
parameters defined in one go. Drivers are expected to fill in the struct
with all the parameters that apply to them while leaving the rest intact.

I've looked at parameters defined in: LIRC, current rc-core, and in Microsoft
CIRClass drivers. The current struct rc_ir_rx should be a superset of all
three and also has room for further additions. Hopefully this should be fairly
complete and future-proof, please check carefully that you favourite
parameter is supported to satisfy your OCD.

Also, it would be interesting to know if carrier reporting is actually an
expensive operation (which should be explicitly enabled by setting the
appropriate flag as now) or not (in which case it should always be on).

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-main.c |   28 +++
 include/media/rc-core.h|   65 
 2 files changed, 93 insertions(+)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 477ad49..c391518 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1649,6 +1649,7 @@ static long rc_do_ioctl(struct rc_dev *dev, unsigned int 
cmd, unsigned long arg)
 {
void __user *p = (void __user *)arg;
unsigned int __user *ip = (unsigned int __user *)p;
+   struct rc_ir_rx rx;
 
switch (cmd) {
 
@@ -1657,6 +1658,33 @@ static long rc_do_ioctl(struct rc_dev *dev, unsigned int 
cmd, unsigned long arg)
 
case RCIOCGTYPE:
return put_user(dev->driver_type, ip);
+
+   case RCIOCGIRPSIZE:
+   return put_user(ARRAY_SIZE(rx.protocols_supported), ip);
+
+   case RCIOCGIRRX:
+   memset(&rx, 0, sizeof(rx));
+   rx.rx_supported = 0x1;
+   rx.rx_enabled = 0x1;
+   rx.rx_connected = 0x1;
+   rx.protocols_enabled[0] = dev->enabled_protocols;
+   if (dev->driver_type == RC_DRIVER_SCANCODE)
+   rx.protocols_supported[0] = dev->allowed_protocols;
+   else
+   rx.protocols_supported[0] = 
ir_raw_get_allowed_protocols();
+   rx.timeout = dev->timeout;
+   rx.timeout_min = dev->min_timeout;
+   rx.timeout_max = dev->max_timeout;
+   rx.resolution = dev->rx_resolution;
+
+   /* See if the driver wishes to override anything */
+   if (dev->get_ir_rx)
+   dev->get_ir_rx(dev, &rx);
+
+   if (copy_to_user(p, &rx, sizeof(rx)))
+   return -EFAULT;
+
+   return 0;
}
 
return -EINVAL;
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 660a331..7392258 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -48,6 +48,69 @@ do { 
\
 /* get driver/hardware type */
 #define RCIOCGTYPE _IOR(RC_IOC_MAGIC, 0x02, unsigned int)
 
+/* get size of protocols array (i.e. multiples of u64) for struct rc_ir_rx */
+#define RCIOCGIRPSIZE  _IOR(RC_IOC_MAGIC, 0x03, unsigned int)
+
+/* get ir rx parameters */
+#define RCIOCGIRRX _IOC(_IOC_READ, RC_IOC_MAGIC, 0x04, sizeof(struct 
rc_ir_rx))
+
+/**
+ * struct rc_ir_rx - used to get all IR RX parameters in one go
+ * @flags: device specific flags (only %RC_IR_RX_MEASURE_CARRIER is
+ * currently defined)
+ * @rx_supported: bitmask of supported (i.e. possible) receivers
+ * @rx_enabled: bitmask of enabled receivers
+ * @rx_connected: bitmask of connected receivers
+ * @rx_learning: bitmask of learning receivers
+ * @protocols_supported: bitmask of supported protocols
+ * @protocols_enabled: bitmask of enabled protocols
+ * @freq_min: min carrier frequency
+ * @freq_max: max carrier frequency
+ * @duty_min: min duty cycle
+ * @duty_max: max duty cycle
+ * @timeout: current timeout (i.e. silence-before-idle)
+ * @timeout_min: min timeout
+ * @timeout_max: max timeout
+ * @filter_space: shorter spaces may be filtered
+ * @filter_space_min: min space filter value
+ * @filter_space_max: max space filter value
+ * @filter_pulse: shorter pulses may be filtered
+ * @filter_pulse_min: min pulse filter value
+ * @filter_pulse_max: max pulse filter value
+ * @resolution: current pulse/space resolution
+ * @resolution_min: min resolution
+ * @resolution_max: max resolution
+ * @reserved: for future use, set to zero
+ */
+struct rc_ir_rx {
+ 

[PATCH 24/49] rc-core: add an ioctl for setting IR RX settings

2014-04-03 Thread David Härdeman
This adds a complementary ioctl to allow IR RX settings to be
changed.

Userspace is expected to first call RCIOCGIRRX, change the relevant parameters
in struct rc_ir_rx and then call RCIOCSIRRX.

The struct will be updated to reflect what the driver actually set the
parameters to (as all values may not be possible and some might have
to be approximated, e.g. because the hardware only supports some fixed
values) so that userspace knows the end result.

The LIRC driver is also changed to use the new RCIOCGIRRX and RCIOCSIRRX
methods as an alternative to the old functionality. This allows several
operations in struct rc_dev to be deprecated.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/ir-lirc-codec.c |   53 +-
 drivers/media/rc/rc-core-priv.h  |3 ++
 drivers/media/rc/rc-main.c   |   53 +-
 include/media/rc-core.h  |9 +-
 4 files changed, 90 insertions(+), 28 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 7d58eea..6e31c83 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -188,6 +188,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int 
cmd,
u32 __user *argp = (u32 __user *)(arg);
int ret = 0;
__u32 val = 0, tmp;
+   struct rc_ir_rx rx;
 
lirc = lirc_get_pdata(filep);
if (!lirc)
@@ -239,15 +240,23 @@ static long ir_lirc_ioctl(struct file *filep, unsigned 
int cmd,
 
/* RX settings */
case LIRC_SET_REC_CARRIER:
-   if (!dev->s_rx_carrier_range)
-   return -ENOSYS;
-
-   if (val <= 0)
+   if (val <= 0 || val < dev->raw->lirc.carrier_low)
return -EINVAL;
 
-   return dev->s_rx_carrier_range(dev,
-  dev->raw->lirc.carrier_low,
-  val);
+   if (dev->s_rx_carrier_range)
+   return dev->s_rx_carrier_range(dev,
+  
dev->raw->lirc.carrier_low,
+  val);
+
+   if (dev->get_ir_rx && dev->set_ir_rx) {
+   rc_init_ir_rx(dev, &rx);
+   dev->get_ir_rx(dev, &rx);
+   rx.freq_min = dev->raw->lirc.carrier_low;
+   rx.freq_max = val;
+   return dev->set_ir_rx(dev, &rx);
+   }
+
+   return -ENOSYS;
 
case LIRC_SET_REC_CARRIER_RANGE:
if (val <= 0)
@@ -261,16 +270,34 @@ static long ir_lirc_ioctl(struct file *filep, unsigned 
int cmd,
break;
 
case LIRC_SET_WIDEBAND_RECEIVER:
-   if (!dev->s_learning_mode)
-   return -ENOSYS;
+   if (dev->s_learning_mode)
+   return dev->s_learning_mode(dev, !!val);
+
+   if (dev->get_ir_rx && dev->set_ir_rx) {
+   rc_init_ir_rx(dev, &rx);
+   dev->get_ir_rx(dev, &rx);
+   rx.rx_enabled = (!!val) ? rx.rx_learning : 
~rx.rx_learning;
+   rx.rx_enabled &= rx.rx_supported;
+   return dev->set_ir_rx(dev, &rx);
+   }
 
-   return dev->s_learning_mode(dev, !!val);
+   return -ENOSYS;
 
case LIRC_SET_MEASURE_CARRIER_MODE:
-   if (!dev->s_carrier_report)
-   return -ENOSYS;
+   if (dev->s_carrier_report)
+   return dev->s_carrier_report(dev, !!val);
+
+   if (dev->get_ir_rx && dev->set_ir_rx) {
+   rc_init_ir_rx(dev, &rx);
+   dev->get_ir_rx(dev, &rx);
+   if (!!val)
+   rx.flags |= RC_IR_RX_MEASURE_CARRIER;
+   else
+   rx.flags &= ~RC_IR_RX_MEASURE_CARRIER;
+   return dev->set_ir_rx(dev, &rx);
+   }
 
-   return dev->s_carrier_report(dev, !!val);
+   return -ENOSYS;
 
/* Generic timeout support */
case LIRC_GET_MIN_TIMEOUT:
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index dea7aff..aacc192 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -155,6 +155,9 @@ int ir_raw_handler_register(struct ir_raw_handler 
*ir_raw_handler);
 void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
 void ir_raw_init(void);
 
+/* Only to be used by rc-core and ir-lirc-codec */
+void rc_init_ir_rx(struct rc_dev *dev, struct rc_ir_rx *rx);
+
 /*
  * Decoder initialization code
  *
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index c391518..3ad565f 100644
--- a/drivers/medi

[PATCH 29/49] rc-loopback: add RCIOCSIRTX ioctl support

2014-04-03 Thread David Härdeman
As an example, this patch adds support for the new RCIOCSIRTX ioctl
to rc-loopback and removes deprecated functions without a loss in
functionality (as LIRC will automatically use the new functions).

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-loopback.c |   59 +---
 1 file changed, 19 insertions(+), 40 deletions(-)

diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index ba36fbe..628e834 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -49,43 +49,6 @@ struct loopback_dev {
 
 static struct loopback_dev loopdev;
 
-static int loop_set_tx_mask(struct rc_dev *dev, u32 mask)
-{
-   struct loopback_dev *lodev = dev->priv;
-
-   if ((mask & (RXMASK_REGULAR | RXMASK_LEARNING)) != mask) {
-   dprintk("invalid tx mask: %u\n", mask);
-   return -EINVAL;
-   }
-
-   dprintk("setting tx mask: %u\n", mask);
-   lodev->txmask = mask;
-   return 0;
-}
-
-static int loop_set_tx_carrier(struct rc_dev *dev, u32 carrier)
-{
-   struct loopback_dev *lodev = dev->priv;
-
-   dprintk("setting tx carrier: %u\n", carrier);
-   lodev->txcarrier = carrier;
-   return 0;
-}
-
-static int loop_set_tx_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
-{
-   struct loopback_dev *lodev = dev->priv;
-
-   if (duty_cycle < 1 || duty_cycle > 99) {
-   dprintk("invalid duty cycle: %u\n", duty_cycle);
-   return -EINVAL;
-   }
-
-   dprintk("setting duty cycle: %u\n", duty_cycle);
-   lodev->txduty = duty_cycle;
-   return 0;
-}
-
 static int loop_tx_ir(struct rc_dev *dev, unsigned count)
 {
struct loopback_dev *lodev = dev->priv;
@@ -229,6 +192,24 @@ static void loop_get_ir_tx(struct rc_dev *dev, struct 
rc_ir_tx *tx)
tx->resolution_max = 1;
 }
 
+/**
+ * loop_set_ir_tx() - changes and returns the current TX settings
+ * @dev: the &struct rc_dev to change the settings for
+ * @tx: the &struct rc_ir_tx with the new settings
+ *
+ * This function is used to change and return the current TX settings.
+ */
+static int loop_set_ir_tx(struct rc_dev *dev, struct rc_ir_tx *tx)
+{
+   struct loopback_dev *lodev = dev->priv;
+
+   lodev->txmask = tx->tx_enabled & (RXMASK_REGULAR | RXMASK_LEARNING);
+   lodev->txcarrier = tx->freq;
+   lodev->txduty = tx->duty;
+
+   return 0;
+}
+
 static int __init loop_init(void)
 {
struct rc_dev *rc;
@@ -254,14 +235,12 @@ static int __init loop_init(void)
rc->max_timeout = UINT_MAX;
rc->rx_resolution   = 1000;
rc->tx_resolution   = 1000;
-   rc->s_tx_mask   = loop_set_tx_mask;
-   rc->s_tx_carrier= loop_set_tx_carrier;
-   rc->s_tx_duty_cycle = loop_set_tx_duty_cycle;
rc->tx_ir   = loop_tx_ir;
rc->s_idle  = loop_set_idle;
rc->get_ir_rx   = loop_get_ir_rx;
rc->set_ir_rx   = loop_set_ir_rx;
rc->get_ir_tx   = loop_get_ir_tx;
+   rc->set_ir_tx   = loop_set_ir_tx;
 
loopdev.txmask  = RXMASK_REGULAR;
loopdev.txcarrier   = 36000;

--
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 30/49] rc-core: leave the internals of rc_dev alone

2014-04-03 Thread David Härdeman
Several drivers poke around in the internals of rc_dev, try to
fix them up in preparation for the next round of patches.

drivers/media/rc/ati_remote.c:
Removing the REP_DELAY setting on the input device should not
change how to driver works (as it does a keydown/keyup and has
no real repeat handling).

drivers/media/rc/img-ir/img-ir-hw.c
Changing the protocol does not imply that the keymap changes.

drivers/media/rc/ir-nec-decoder.c
Obvious fix, leave repeat handling to rc-core

drivers/media/rc/ir-raw.c
Replaced the REP_DELAY value with a static value, which makes more
sense anyway. Why should the time before automatic repeat handling
kicks in define the drivers idea of "a long time"?

drivers/media/rc/ir-sanyo-decoder.c
Obvious fix, leave repeat handling to rc-core

drivers/media/video/cx231xx/cx231xx-input.c
Just some debug statements to change

drivers/media/video/tm6000/tm6000-input.c
Not sure what the driver is trying to do, however, IR
handling seems incomplete ATM so deleting the offending
parts shouldn't affect functionality

Signed-off-by: David Härdeman 
---
 drivers/media/rc/ati_remote.c |3 ---
 drivers/media/rc/img-ir/img-ir-hw.c   |4 
 drivers/media/rc/ir-nec-decoder.c |   10 +++---
 drivers/media/rc/ir-raw.c |4 +---
 drivers/media/rc/ir-sanyo-decoder.c   |   10 +++---
 drivers/media/usb/cx231xx/cx231xx-input.c |5 ++---
 drivers/media/usb/tm6000/tm6000-input.c   |4 
 7 files changed, 9 insertions(+), 31 deletions(-)

diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 3ada4dc..6ef5716 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -932,9 +932,6 @@ static int ati_remote_probe(struct usb_interface *interface,
if (err)
goto exit_kill_urbs;
 
-   /* use our delay for rc_dev */
-   ati_remote->rdev->input_dev->rep[REP_DELAY] = repeat_delay;
-
/* Set up and register mouse input device */
if (mouse) {
input_dev = input_allocate_device();
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c 
b/drivers/media/rc/img-ir/img-ir-hw.c
index 9fc41780..3bb6a32 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -666,10 +666,6 @@ static void img_ir_set_protocol(struct img_ir_priv *priv, 
u64 proto)
 {
struct rc_dev *rdev = priv->hw.rdev;
 
-   spin_lock_irq(&rdev->rc_map.lock);
-   rdev->rc_map.rc_type = __ffs64(proto);
-   spin_unlock_irq(&rdev->rc_map.lock);
-
mutex_lock(&rdev->lock);
rdev->enabled_protocols = proto;
rdev->allowed_wakeup_protocols = proto;
diff --git a/drivers/media/rc/ir-nec-decoder.c 
b/drivers/media/rc/ir-nec-decoder.c
index 1683aaa..861fd86 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -89,13 +89,9 @@ static int ir_nec_decode(struct rc_dev *dev, struct 
ir_raw_event ev)
data->state = STATE_BIT_PULSE;
return 0;
} else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 
2)) {
-   if (!dev->keypressed) {
-   IR_dprintk(1, "Discarding last key repeat: 
event after key up\n");
-   } else {
-   rc_repeat(dev);
-   IR_dprintk(1, "Repeat last key\n");
-   data->state = STATE_TRAILER_PULSE;
-   }
+   rc_repeat(dev);
+   IR_dprintk(1, "Repeat last key\n");
+   data->state = STATE_TRAILER_PULSE;
return 0;
}
 
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
index af23f4d..aa2503d 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
@@ -109,20 +109,18 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum 
raw_event_type type)
s64 delta; /* ns */
DEFINE_IR_RAW_EVENT(ev);
int rc = 0;
-   int delay;
 
if (!dev->raw)
return -EINVAL;
 
now = ktime_get();
delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event));
-   delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]);
 
/* Check for a long duration since last event or if we're
 * being called for the first time, note that delta can't
 * possibly be negative.
 */
-   if (delta > delay || !dev->raw->last_type)
+   if (delta > MS_TO_NS(500) || !dev->raw->last_type)
type |= IR_START_EVENT;
else
ev.duration = delta;
diff --git a/drivers/media/rc/ir-sanyo-decoder.c 
b/drivers/media/rc/ir-sanyo-decoder.c
index ad1dc6a..9f97648 100644
--- a/drivers/media

[PATCH 23/49] rc-loopback: add RCIOCGIRRX ioctl support

2014-04-03 Thread David Härdeman
As an example, this patch adds support for the new RCIOCGIRRX ioctl
to rc-loopback.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-loopback.c |   22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index bc67d2f..565318c 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -181,6 +181,27 @@ static int loop_set_carrier_report(struct rc_dev *dev, int 
enable)
return 0;
 }
 
+/**
+ * loop_get_ir_rx() - returns the current RX settings
+ * @dev: the &struct rc_dev to get the settings for
+ * @rx: the &struct rc_ir_rx to fill in with the current settings
+ *
+ * This function is used to return the current RX settings.
+ */
+static void loop_get_ir_rx(struct rc_dev *dev, struct rc_ir_rx *rx)
+{
+   struct loopback_dev *lodev = dev->priv;
+
+   rx->rx_supported = RXMASK_REGULAR | RXMASK_LEARNING;
+   rx->rx_connected = RXMASK_REGULAR | RXMASK_LEARNING;
+   rx->rx_enabled = lodev->learning ? RXMASK_LEARNING : RXMASK_REGULAR;
+   rx->rx_learning = RXMASK_LEARNING;
+   rx->freq_min = lodev->rxcarriermin;
+   rx->freq_max = lodev->rxcarriermax;
+   rx->duty_min = 1;
+   rx->duty_max = 99;
+}
+
 static int __init loop_init(void)
 {
struct rc_dev *rc;
@@ -214,6 +235,7 @@ static int __init loop_init(void)
rc->s_idle  = loop_set_idle;
rc->s_learning_mode = loop_set_learning_mode;
rc->s_carrier_report= loop_set_carrier_report;
+   rc->get_ir_rx   = loop_get_ir_rx;
 
loopdev.txmask  = RXMASK_REGULAR;
loopdev.txcarrier   = 36000;

--
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 27/49] rc-loopback: add RCIOCGIRTX ioctl support

2014-04-03 Thread David Härdeman
As an example, this patch adds support for the new RCIOCGIRRX ioctl
to rc-loopback.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-loopback.c |   26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index 2ae1b5a..ba36fbe 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -204,6 +204,31 @@ static int loop_set_ir_rx(struct rc_dev *dev, struct 
rc_ir_rx *rx)
return 0;
 }
 
+/**
+ * loop_get_ir_tx() - returns the current TX settings
+ * @dev: the &struct rc_dev to get the settings for
+ * @tx: the &struct rc_ir_tx to fill in with the current settings
+ *
+ * This function is used to return the current TX settings.
+ */
+static void loop_get_ir_tx(struct rc_dev *dev, struct rc_ir_tx *tx)
+{
+   struct loopback_dev *lodev = dev->priv;
+
+   tx->tx_supported = RXMASK_REGULAR | RXMASK_LEARNING;
+   tx->tx_connected = RXMASK_REGULAR | RXMASK_LEARNING;
+   tx->tx_enabled = lodev->txmask;
+   tx->freq = lodev->txcarrier;
+   tx->freq_min = 1;
+   tx->freq_max = UINT_MAX;
+   tx->duty = lodev->txduty;
+   tx->duty_min = 1;
+   tx->duty_max = 99;
+   tx->resolution = 1;
+   tx->resolution_min = 1;
+   tx->resolution_max = 1;
+}
+
 static int __init loop_init(void)
 {
struct rc_dev *rc;
@@ -236,6 +261,7 @@ static int __init loop_init(void)
rc->s_idle  = loop_set_idle;
rc->get_ir_rx   = loop_get_ir_rx;
rc->set_ir_rx   = loop_set_ir_rx;
+   rc->get_ir_tx   = loop_get_ir_tx;
 
loopdev.txmask  = RXMASK_REGULAR;
loopdev.txcarrier   = 36000;

--
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 26/49] rc-core: add an ioctl for getting IR TX settings

2014-04-03 Thread David Härdeman
This ioctl follows the same rationale and structure as the ioctl for
getting IR RX settings (RCIOCGIRRX) but it works on TX settings instead.

As with the RX ioctl, it would be nice if people could check struct
rc_ir_tx carefully to make sure that their favourite parameter
hasn't been left out.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-main.c |   12 
 include/media/rc-core.h|   38 ++
 2 files changed, 50 insertions(+)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 3ad565f..611d24d 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1675,6 +1675,7 @@ static long rc_do_ioctl(struct rc_dev *dev, unsigned int 
cmd, unsigned long arg)
void __user *p = (void __user *)arg;
unsigned int __user *ip = (unsigned int __user *)p;
struct rc_ir_rx rx;
+   struct rc_ir_tx tx;
int error;
 
switch (cmd) {
@@ -1712,6 +1713,17 @@ static long rc_do_ioctl(struct rc_dev *dev, unsigned int 
cmd, unsigned long arg)
return -EFAULT;
 
return 0;
+
+   case RCIOCGIRTX:
+   memset(&tx, 0, sizeof(tx));
+
+   if (dev->get_ir_tx)
+   dev->get_ir_tx(dev, &tx);
+
+   if (copy_to_user(p, &tx, sizeof(tx)))
+   return -EFAULT;
+
+   return 0;
}
 
return -EINVAL;
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 09bf8b5..566ae7d 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -113,6 +113,42 @@ struct rc_ir_rx {
__u32 reserved[9];
 } __packed;
 
+/* get ir tx parameters */
+#define RCIOCGIRTX _IOC(_IOC_READ, RC_IOC_MAGIC, 0x05, sizeof(struct 
rc_ir_tx))
+
+/**
+ * struct rc_ir_tx - used to get all IR TX parameters in one go
+ * @flags: device specific flags
+ * @tx_supported: bitmask of supported transmitters
+ * @tx_enabled: bitmask of enabled transmitters
+ * @tx_connected: bitmask of connected transmitters
+ * @freq: current carrier frequency
+ * @freq_min: min carrier frequency
+ * @freq_max: max carrier frequency
+ * @duty: current duty cycle
+ * @duty_min: min duty cycle
+ * @duty_max: max duty cycle
+ * @resolution: current resolution
+ * @resolution_min: min resolution
+ * @resolution_max: max resolution
+ * @reserved: for future use, set to zero
+ */
+struct rc_ir_tx {
+   __u32 flags;
+   __u32 tx_supported;
+   __u32 tx_enabled;
+   __u32 tx_connected;
+   __u32 freq;
+   __u32 freq_min;
+   __u32 freq_max;
+   __u32 duty;
+   __u32 duty_min;
+   __u32 duty_max;
+   __u32 resolution;
+   __u32 resolution_min;
+   __u32 resolution_max;
+   __u32 reserved[9];
+} __packed;
 
 
 enum rc_driver_type {
@@ -270,6 +306,7 @@ enum rc_filter_type {
  * @s_wakeup_filter: set the wakeup scancode filter
  * @get_ir_rx: allow driver to provide rx settings
  * @set_ir_rx: allow driver to change rx settings
+ * @get_ir_tx: allow driver to provide tx settings
  */
 struct rc_dev {
struct device   dev;
@@ -333,6 +370,7 @@ struct rc_dev {
   struct 
rc_scancode_filter *filter);
void(*get_ir_rx)(struct rc_dev *dev, struct 
rc_ir_rx *rx);
int (*set_ir_rx)(struct rc_dev *dev, struct 
rc_ir_rx *rx);
+   void(*get_ir_tx)(struct rc_dev *dev, struct 
rc_ir_tx *tx);
 };
 
 #define to_rc_dev(d) container_of(d, struct rc_dev, dev)

--
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 31/49] rc-core: split rc-main.c into rc-main.c and rc-keytable.c

2014-04-03 Thread David Härdeman
rc-main.c is getting quite large and contains two distinct parts, one
related to the chardev (fops, sysfs, etc) and one related to all
key functionality. Split off the key functionality to a separate file in
preparation for the coming patches.

I've done the splitting as a separate patch with the absolute minimum changes
(making some methods non-static) because it's nigh impossible to review
code changes and this code of split in the same patch.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/Makefile   |2 
 drivers/media/rc/rc-core-priv.h |   17 +
 drivers/media/rc/rc-keytable.c  |  851 +++
 drivers/media/rc/rc-main.c  |  853 +--
 4 files changed, 883 insertions(+), 840 deletions(-)
 create mode 100644 drivers/media/rc/rc-keytable.c

diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index d326d4d..de08ee6 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -1,4 +1,4 @@
-rc-core-objs   := rc-main.o ir-raw.o
+rc-core-objs   := rc-main.o rc-keytable.o ir-raw.o
 
 obj-y += keymaps/
 
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index aacc192..6da8a0d 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -155,9 +155,26 @@ int ir_raw_handler_register(struct ir_raw_handler 
*ir_raw_handler);
 void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
 void ir_raw_init(void);
 
+/*
+ * Methods from rc-keytable.c to be used internally
+ */
+void ir_timer_keyup(unsigned long cookie);
+int rc_input_open(struct input_dev *idev);
+void rc_input_close(struct input_dev *idev);
+int ir_setkeytable(struct rc_dev *dev, const struct rc_map *from);
+void ir_free_table(struct rc_map *rc_map);
+int ir_getkeycode(struct input_dev *idev,
+ struct input_keymap_entry *ke);
+int ir_setkeycode(struct input_dev *idev,
+ const struct input_keymap_entry *ke,
+ unsigned int *old_keycode);
+
 /* Only to be used by rc-core and ir-lirc-codec */
 void rc_init_ir_rx(struct rc_dev *dev, struct rc_ir_rx *rx);
 
+/* Only to be used by rc-keytable.c */
+extern struct led_trigger *led_feedback;
+
 /*
  * Decoder initialization code
  *
diff --git a/drivers/media/rc/rc-keytable.c b/drivers/media/rc/rc-keytable.c
new file mode 100644
index 000..25faeba
--- /dev/null
+++ b/drivers/media/rc/rc-keytable.c
@@ -0,0 +1,851 @@
+/* rc-keytable.c - Remote Controller keytable handling
+ *
+ * Copyright (C) 2009-2010 by Mauro Carvalho Chehab
+ *
+ * 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 version 2 of the License.
+ *
+ *  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 "rc-core-priv.h"
+
+/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
+#define IR_TAB_MIN_SIZE256
+#define IR_TAB_MAX_SIZE8192
+
+/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
+#define IR_KEYPRESS_TIMEOUT 250
+
+/* Used to keep track of known keymaps */
+static LIST_HEAD(rc_map_list);
+static DEFINE_SPINLOCK(rc_map_lock);
+
+static struct rc_map_list *seek_rc_map(const char *name)
+{
+   struct rc_map_list *map = NULL;
+
+   spin_lock(&rc_map_lock);
+   list_for_each_entry(map, &rc_map_list, list) {
+   if (!strcmp(name, map->map.name)) {
+   spin_unlock(&rc_map_lock);
+   return map;
+   }
+   }
+   spin_unlock(&rc_map_lock);
+
+   return NULL;
+}
+
+struct rc_map *rc_map_get(const char *name)
+{
+
+   struct rc_map_list *map;
+
+   map = seek_rc_map(name);
+#ifdef MODULE
+   if (!map) {
+   int rc = request_module("%s", name);
+   if (rc < 0) {
+   printk(KERN_ERR "Couldn't load IR keymap %s\n", name);
+   return NULL;
+   }
+   msleep(20); /* Give some time for IR to register */
+
+   map = seek_rc_map(name);
+   }
+#endif
+   if (!map) {
+   printk(KERN_ERR "IR keymap %s not found\n", name);
+   return NULL;
+   }
+
+   printk(KERN_INFO "Registered IR keymap %s\n", map->map.name);
+
+   return &map->map;
+}
+EXPORT_SYMBOL_GPL(rc_map_get);
+
+int rc_map_register(struct rc_map_list *map)
+{
+   spin_lock(&rc_map_lock);
+   list_add_tail(&map->list, &rc_map_list);
+   spin_unlock(&rc_map_lock);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(rc_map_register);
+
+v

[PATCH 28/49] rc-core: add an ioctl for setting IR TX settings

2014-04-03 Thread David Härdeman
This adds a complementary ioctl to allow IR TX settings to be
changed.

Much like the RCIOCSIRRX functionality, userspace is expected to call
RCIOCGIRTX, change values and then call RCIOCSIRTX and finally inspect
the struct rc_ir_tx to see the results.

Also, LIRC is changed to use the new functionality as an alternative to the
old one and another bunch of operations in struct rc_dev are now deprecated.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/ir-lirc-codec.c |   42 +-
 drivers/media/rc/rc-main.c   |   13 
 include/media/rc-core.h  |   13 
 3 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 6e31c83..7b56f21 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -189,6 +189,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int 
cmd,
int ret = 0;
__u32 val = 0, tmp;
struct rc_ir_rx rx;
+   struct rc_ir_tx tx;
 
lirc = lirc_get_pdata(filep);
if (!lirc)
@@ -218,25 +219,46 @@ static long ir_lirc_ioctl(struct file *filep, unsigned 
int cmd,
 
/* TX settings */
case LIRC_SET_TRANSMITTER_MASK:
-   if (!dev->s_tx_mask)
-   return -ENOSYS;
+   if (dev->s_tx_mask)
+   return dev->s_tx_mask(dev, val);
 
-   return dev->s_tx_mask(dev, val);
+   if (dev->get_ir_tx && dev->set_ir_tx) {
+   memset(&tx, 0, sizeof(tx));
+   dev->get_ir_tx(dev, &tx);
+   tx.tx_enabled = val;
+   return dev->set_ir_tx(dev, &tx);
+   }
+
+   return -ENOSYS;
 
case LIRC_SET_SEND_CARRIER:
-   if (!dev->s_tx_carrier)
-   return -ENOSYS;
+   if (dev->s_tx_carrier)
+   return dev->s_tx_carrier(dev, val);
 
-   return dev->s_tx_carrier(dev, val);
+   if (dev->get_ir_tx && dev->set_ir_tx) {
+   memset(&tx, 0, sizeof(tx));
+   dev->get_ir_tx(dev, &tx);
+   tx.freq = val;
+   return dev->set_ir_tx(dev, &tx);
+   }
 
-   case LIRC_SET_SEND_DUTY_CYCLE:
-   if (!dev->s_tx_duty_cycle)
-   return -ENOSYS;
+   return -ENOSYS;
 
+   case LIRC_SET_SEND_DUTY_CYCLE:
if (val <= 0 || val >= 100)
return -EINVAL;
 
-   return dev->s_tx_duty_cycle(dev, val);
+   if (dev->s_tx_duty_cycle)
+   return dev->s_tx_duty_cycle(dev, val);
+
+   if (dev->get_ir_tx && dev->set_ir_tx) {
+   memset(&tx, 0, sizeof(tx));
+   dev->get_ir_tx(dev, &tx);
+   tx.duty = val;
+   return dev->set_ir_tx(dev, &tx);
+   }
+
+   return -ENOSYS;
 
/* RX settings */
case LIRC_SET_REC_CARRIER:
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 611d24d..cc2f713 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1714,6 +1714,19 @@ static long rc_do_ioctl(struct rc_dev *dev, unsigned int 
cmd, unsigned long arg)
 
return 0;
 
+   case RCIOCSIRTX:
+   if (!dev->set_ir_tx)
+   return -ENOSYS;
+
+   if (copy_from_user(&tx, p, sizeof(tx)))
+   return -EFAULT;
+
+   error = dev->set_ir_tx(dev, &tx);
+   if (error)
+   return error;
+
+   /* Fall through */
+
case RCIOCGIRTX:
memset(&tx, 0, sizeof(tx));
 
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 566ae7d..eacb735 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -116,8 +116,11 @@ struct rc_ir_rx {
 /* get ir tx parameters */
 #define RCIOCGIRTX _IOC(_IOC_READ, RC_IOC_MAGIC, 0x05, sizeof(struct 
rc_ir_tx))
 
+/* set ir tx parameters */
+#define RCIOCSIRTX _IOC(_IOC_WRITE, RC_IOC_MAGIC, 0x05, sizeof(struct 
rc_ir_tx))
+
 /**
- * struct rc_ir_tx - used to get all IR TX parameters in one go
+ * struct rc_ir_tx - used to get/set all IR TX parameters in one go
  * @flags: device specific flags
  * @tx_supported: bitmask of supported transmitters
  * @tx_enabled: bitmask of enabled transmitters
@@ -293,9 +296,9 @@ enum rc_filter_type {
  * is opened.
  * @close: callback to allow drivers to disable polling/irq when IR input 
device
  * is opened.
- * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs)
- * @s_tx_carrier: set transmit carrier frequency
- * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%)
+ * @s_tx_mask: set transmitter mask (for devices with mul

[PATCH 25/49] rc-loopback: add RCIOCSIRRX ioctl support

2014-04-03 Thread David Härdeman
As an example, this patch adds support for the new RCIOCSIRRX ioctl
to rc-loopback and removes deprecated functions without a loss in
functionality (as LIRC will automatically use the new functions).

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-loopback.c |   84 
 1 file changed, 42 insertions(+), 42 deletions(-)

diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index 565318c..2ae1b5a 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -86,21 +86,6 @@ static int loop_set_tx_duty_cycle(struct rc_dev *dev, u32 
duty_cycle)
return 0;
 }
 
-static int loop_set_rx_carrier_range(struct rc_dev *dev, u32 min, u32 max)
-{
-   struct loopback_dev *lodev = dev->priv;
-
-   if (min < 1 || min > max) {
-   dprintk("invalid rx carrier range %u to %u\n", min, max);
-   return -EINVAL;
-   }
-
-   dprintk("setting rx carrier range %u to %u\n", min, max);
-   lodev->rxcarriermin = min;
-   lodev->rxcarriermax = max;
-   return 0;
-}
-
 static int loop_tx_ir(struct rc_dev *dev, unsigned count)
 {
struct loopback_dev *lodev = dev->priv;
@@ -157,30 +142,6 @@ static void loop_set_idle(struct rc_dev *dev, bool enable)
}
 }
 
-static int loop_set_learning_mode(struct rc_dev *dev, int enable)
-{
-   struct loopback_dev *lodev = dev->priv;
-
-   if (lodev->learning != enable) {
-   dprintk("%sing learning mode\n", enable ? "enter" : "exit");
-   lodev->learning = !!enable;
-   }
-
-   return 0;
-}
-
-static int loop_set_carrier_report(struct rc_dev *dev, int enable)
-{
-   struct loopback_dev *lodev = dev->priv;
-
-   if (lodev->carrierreport != enable) {
-   dprintk("%sabling carrier reports\n", enable ? "en" : "dis");
-   lodev->carrierreport = !!enable;
-   }
-
-   return 0;
-}
-
 /**
  * loop_get_ir_rx() - returns the current RX settings
  * @dev: the &struct rc_dev to get the settings for
@@ -202,6 +163,47 @@ static void loop_get_ir_rx(struct rc_dev *dev, struct 
rc_ir_rx *rx)
rx->duty_max = 99;
 }
 
+/**
+ * loop_set_ir_rx() - changes and returns the current RX settings
+ * @dev: the &struct rc_dev to change the settings for
+ * @rx: the &struct rc_ir_rx with the new settings
+ *
+ * This function is used to change and return the current RX settings.
+ */
+static int loop_set_ir_rx(struct rc_dev *dev, struct rc_ir_rx *rx)
+{
+   struct loopback_dev *lodev = dev->priv;
+
+   dprintk("%s called\n", __func__);
+   if (lodev->rxcarriermin != rx->freq_min) {
+   dprintk("changing rx carrier min to %u\n", rx->freq_min);
+   lodev->rxcarriermin = rx->freq_min;
+   }
+
+   if (lodev->rxcarriermax != rx->freq_max) {
+   dprintk("changing rx carrier max to %u\n", rx->freq_max);
+   lodev->rxcarriermax = rx->freq_max;
+   }
+
+   if (lodev->carrierreport == !(rx->flags & RC_IR_RX_MEASURE_CARRIER)) {
+   lodev->carrierreport = !!(rx->flags & RC_IR_RX_MEASURE_CARRIER);
+   dprintk("%sabling carrier reports\n",
+   lodev->carrierreport ? "en" : "dis");
+   }
+
+   if ((rx->rx_enabled == RXMASK_LEARNING) && !lodev->learning) {
+   dprintk("enabling learning mode\n");
+   lodev->learning = true;
+   } else if ((rx->rx_enabled == RXMASK_REGULAR) && lodev->learning) {
+   dprintk("disabling learning mode\n");
+   lodev->learning = false;
+   }
+
+   /* Fill in the correct values after the changes */
+   loop_get_ir_rx(dev, rx);
+   return 0;
+}
+
 static int __init loop_init(void)
 {
struct rc_dev *rc;
@@ -230,12 +232,10 @@ static int __init loop_init(void)
rc->s_tx_mask   = loop_set_tx_mask;
rc->s_tx_carrier= loop_set_tx_carrier;
rc->s_tx_duty_cycle = loop_set_tx_duty_cycle;
-   rc->s_rx_carrier_range  = loop_set_rx_carrier_range;
rc->tx_ir   = loop_tx_ir;
rc->s_idle  = loop_set_idle;
-   rc->s_learning_mode = loop_set_learning_mode;
-   rc->s_carrier_report= loop_set_carrier_report;
rc->get_ir_rx   = loop_get_ir_rx;
+   rc->set_ir_rx   = loop_set_ir_rx;
 
loopdev.txmask  = RXMASK_REGULAR;
loopdev.txcarrier   = 36000;

--
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 32/49] rc-core: prepare for multiple keytables

2014-04-03 Thread David Härdeman
Introduce struct rc_keytable which essentially maintains an input device
and a table with scancode,protocol <-> keycode mappings. Move the relevant
members from struct rc_dev into struct rc_keytable.

This is in preparation for supporting multiple keytables, where each
keytable would correspond to one physical remote controller, each with
its own keymap and input device for reporting events to userspace.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-core-priv.h |   16 +-
 drivers/media/rc/rc-keytable.c  |  341 ++-
 drivers/media/rc/rc-main.c  |  224 +++---
 include/media/rc-core.h |   62 +--
 4 files changed, 338 insertions(+), 305 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 6da8a0d..7a7770e 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -158,16 +158,12 @@ void ir_raw_init(void);
 /*
  * Methods from rc-keytable.c to be used internally
  */
-void ir_timer_keyup(unsigned long cookie);
-int rc_input_open(struct input_dev *idev);
-void rc_input_close(struct input_dev *idev);
-int ir_setkeytable(struct rc_dev *dev, const struct rc_map *from);
-void ir_free_table(struct rc_map *rc_map);
-int ir_getkeycode(struct input_dev *idev,
- struct input_keymap_entry *ke);
-int ir_setkeycode(struct input_dev *idev,
- const struct input_keymap_entry *ke,
- unsigned int *old_keycode);
+void rc_keytable_keyup(struct rc_keytable *kt);
+void rc_keytable_repeat(struct rc_keytable *kt);
+void rc_keytable_keydown(struct rc_keytable *kt, enum rc_type protocol,
+u32 scancode, u8 toggle, bool autokeyup);
+int rc_keytable_add(struct rc_dev *dev, struct rc_map *rc_map);
+void rc_keytable_del(struct rc_dev *dev);
 
 /* Only to be used by rc-core and ir-lirc-codec */
 void rc_init_ir_rx(struct rc_dev *dev, struct rc_ir_rx *rx);
diff --git a/drivers/media/rc/rc-keytable.c b/drivers/media/rc/rc-keytable.c
index 25faeba..0f1b817 100644
--- a/drivers/media/rc/rc-keytable.c
+++ b/drivers/media/rc/rc-keytable.c
@@ -187,7 +187,7 @@ static int ir_resize_table(struct rc_map *rc_map, gfp_t 
gfp_flags)
 
 /**
  * ir_update_mapping() - set a keycode in the scancode->keycode table
- * @dev:   the struct rc_dev device descriptor
+ * @kt:the struct rc_keytable
  * @rc_map:scancode table to be adjusted
  * @index: index of the mapping that needs to be updated
  * @keycode:   the desired keycode
@@ -196,7 +196,7 @@ static int ir_resize_table(struct rc_map *rc_map, gfp_t 
gfp_flags)
  * This routine is used to update scancode->keycode mapping at given
  * position.
  */
-static unsigned int ir_update_mapping(struct rc_dev *dev,
+static unsigned int ir_update_mapping(struct rc_keytable *kt,
  struct rc_map *rc_map,
  unsigned int index,
  unsigned int new_keycode)
@@ -221,16 +221,16 @@ static unsigned int ir_update_mapping(struct rc_dev *dev,
   (unsigned long long)rc_map->scan[index].scancode,
   new_keycode);
rc_map->scan[index].keycode = new_keycode;
-   __set_bit(new_keycode, dev->input_dev->keybit);
+   __set_bit(new_keycode, kt->idev->keybit);
}
 
if (old_keycode != KEY_RESERVED) {
/* A previous mapping was updated... */
-   __clear_bit(old_keycode, dev->input_dev->keybit);
+   __clear_bit(old_keycode, kt->idev->keybit);
/* ... but another scancode might use the same keycode */
for (i = 0; i < rc_map->len; i++) {
if (rc_map->scan[i].keycode == old_keycode) {
-   __set_bit(old_keycode, dev->input_dev->keybit);
+   __set_bit(old_keycode, kt->idev->keybit);
break;
}
}
@@ -244,7 +244,7 @@ static unsigned int ir_update_mapping(struct rc_dev *dev,
 
 /**
  * ir_establish_scancode() - set a keycode in the scancode->keycode table
- * @dev:   the struct rc_dev device descriptor
+ * @kt:the struct rc_keytable descriptor
  * @rc_map:scancode table to be searched
  * @entry: the entry to be added to the table
  * @resize:controls whether we are allowed to resize the table to
@@ -256,7 +256,7 @@ static unsigned int ir_update_mapping(struct rc_dev *dev,
  * If scancode is not yet present the routine will allocate a new slot
  * for it.
  */
-static unsigned int ir_establish_scancode(struct rc_dev *dev,
+static unsigned int ir_establish_scancode(struct rc_keytable *kt,
  struct rc_map *rc_map,
  struct rc_map_table *entry,

[PATCH 33/49] rc-core: make the keytable of rc_dev an array

2014-04-03 Thread David Härdeman
This is another step towards allowing multiple keytables per rc_dev.

struct rc_dev is changed to hold an array of keytables (used later for
indexed access to keytables) as well as a list of the same keytables
(used for iteration in fast paths).

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-core-priv.h |4 +-
 drivers/media/rc/rc-keytable.c  |   95 ---
 drivers/media/rc/rc-main.c  |   74 --
 include/media/rc-core.h |6 ++
 4 files changed, 134 insertions(+), 45 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 7a7770e..02b538c 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -162,8 +162,8 @@ void rc_keytable_keyup(struct rc_keytable *kt);
 void rc_keytable_repeat(struct rc_keytable *kt);
 void rc_keytable_keydown(struct rc_keytable *kt, enum rc_type protocol,
 u32 scancode, u8 toggle, bool autokeyup);
-int rc_keytable_add(struct rc_dev *dev, struct rc_map *rc_map);
-void rc_keytable_del(struct rc_dev *dev);
+struct rc_keytable *rc_keytable_create(struct rc_dev *dev, struct rc_map 
*rc_map);
+void rc_keytable_destroy(struct rc_keytable *kt);
 
 /* Only to be used by rc-core and ir-lirc-codec */
 void rc_init_ir_rx(struct rc_dev *dev, struct rc_ir_rx *rx);
diff --git a/drivers/media/rc/rc-keytable.c b/drivers/media/rc/rc-keytable.c
index 0f1b817..412d342 100644
--- a/drivers/media/rc/rc-keytable.c
+++ b/drivers/media/rc/rc-keytable.c
@@ -322,7 +322,7 @@ static unsigned int ir_establish_scancode(struct 
rc_keytable *kt,
  */
 static inline enum rc_type guess_protocol(struct rc_dev *rdev)
 {
-   struct rc_map *rc_map = &rdev->kt->rc_map;
+   struct rc_map *rc_map = &rdev->keytables[0]->rc_map;
 
if (hweight64(rdev->enabled_protocols) == 1)
return rc_bitmap_to_type(rdev->enabled_protocols);
@@ -604,40 +604,63 @@ out:
return retval;
 }
 
-/**
- * rc_g_keycode_from_table() - gets the keycode that corresponds to a scancode
- * @dev:   the struct rc_dev descriptor of the device
- * @protocol:  the protocol to look for
- * @scancode:  the scancode to look for
- * @return:the corresponding keycode, or KEY_RESERVED
- *
- * This routine is used by drivers which need to convert a scancode to a
- * keycode. Normally it should not be used since drivers should have no
- * interest in keycodes.
- */
-u32 rc_g_keycode_from_table(struct rc_dev *dev,
-   enum rc_type protocol, u64 scancode)
+static u32 rc_get_keycode(struct rc_keytable *kt,
+ enum rc_type protocol, u64 scancode)
 {
-   struct rc_map *rc_map = &dev->kt->rc_map;
-   unsigned int keycode;
+   struct rc_map *rc_map;
+   unsigned int keycode = KEY_RESERVED;
unsigned int index;
unsigned long flags;
 
+   rc_map = &kt->rc_map;
+   if (!rc_map)
+   return KEY_RESERVED;
+
spin_lock_irqsave(&rc_map->lock, flags);
 
index = ir_lookup_by_scancode(rc_map, protocol, scancode);
-   keycode = index < rc_map->len ?
-   rc_map->scan[index].keycode : KEY_RESERVED;
+   if (index < rc_map->len)
+   keycode = rc_map->scan[index].keycode;
 
spin_unlock_irqrestore(&rc_map->lock, flags);
 
if (keycode != KEY_RESERVED)
IR_dprintk(1, "%s: protocol 0x%04x scancode 0x%08llx keycode 
0x%02x\n",
-  dev->input_name, protocol,
+  kt->dev->input_name, protocol,
   (unsigned long long)scancode, keycode);
 
return keycode;
 }
+
+
+/**
+ * rc_g_keycode_from_table() - gets the keycode that corresponds to a scancode
+ * @dev:   the struct rc_dev descriptor of the device
+ * @protocol:  the protocol to look for
+ * @scancode:  the scancode to look for
+ * @return:the corresponding keycode, or KEY_RESERVED
+ *
+ * This routine is used by drivers which need to convert a scancode to a
+ * keycode. It should not be used since drivers should have no
+ * interest in keycodes. (deprecated)
+ */
+u32 rc_g_keycode_from_table(struct rc_dev *dev,
+   enum rc_type protocol, u64 scancode)
+{
+   struct rc_keytable *kt;
+   unsigned int keycode = KEY_RESERVED;
+
+   /* FIXME: This entire function is a hack. Remove it */
+   rcu_read_lock();
+   kt = rcu_dereference(dev->keytables[0]);
+   if (!kt)
+   goto out;
+   keycode = rc_get_keycode(kt, protocol, scancode);
+
+out:
+   rcu_read_unlock();
+   return keycode;
+}
 EXPORT_SYMBOL_GPL(rc_g_keycode_from_table);
 
 /**
@@ -751,7 +774,7 @@ void rc_keytable_keydown(struct rc_keytable *kt, enum 
rc_type protocol,
 
spin_lock_irqsave(&kt->keylock, flags);
 
-   keycode = rc_g_keycode_from_table(kt->dev, protocol, scancode);
+   keycode = rc_get_keycode(kt, protocol

[PATCH 35/49] rc-core: remove redundant spinlock

2014-04-03 Thread David Härdeman
Remove a redundant spinlock from struct rc_map.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-keytable.c |   43 +---
 include/media/rc-core.h|4 ++--
 include/media/rc-map.h |1 -
 3 files changed, 20 insertions(+), 28 deletions(-)

diff --git a/drivers/media/rc/rc-keytable.c b/drivers/media/rc/rc-keytable.c
index 6d04b8f..f4d03d2 100644
--- a/drivers/media/rc/rc-keytable.c
+++ b/drivers/media/rc/rc-keytable.c
@@ -381,7 +381,7 @@ static int ir_setkeycode(struct input_dev *idev,
 
entry.keycode = ke->keycode;
 
-   spin_lock_irqsave(&rc_map->lock, flags);
+   spin_lock_irqsave(&kt->lock, flags);
 
if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
index = ke->index;
@@ -430,7 +430,7 @@ static int ir_setkeycode(struct input_dev *idev,
*old_keycode = ir_update_mapping(kt, rc_map, index, ke->keycode);
 
 out:
-   spin_unlock_irqrestore(&rc_map->lock, flags);
+   spin_unlock_irqrestore(&kt->lock, flags);
return retval;
 }
 
@@ -537,7 +537,7 @@ int ir_getkeycode(struct input_dev *idev,
unsigned int index;
int retval;
 
-   spin_lock_irqsave(&rc_map->lock, flags);
+   spin_lock_irqsave(&kt->lock, flags);
 
if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
index = ke->index;
@@ -600,7 +600,7 @@ int ir_getkeycode(struct input_dev *idev,
retval = 0;
 
 out:
-   spin_unlock_irqrestore(&rc_map->lock, flags);
+   spin_unlock_irqrestore(&kt->lock, flags);
return retval;
 }
 
@@ -610,25 +610,15 @@ static u32 rc_get_keycode(struct rc_keytable *kt,
struct rc_map *rc_map;
unsigned int keycode = KEY_RESERVED;
unsigned int index;
-   unsigned long flags;
 
rc_map = &kt->rc_map;
if (!rc_map)
return KEY_RESERVED;
 
-   spin_lock_irqsave(&rc_map->lock, flags);
-
index = ir_lookup_by_scancode(rc_map, protocol, scancode);
if (index < rc_map->len)
keycode = rc_map->scan[index].keycode;
 
-   spin_unlock_irqrestore(&rc_map->lock, flags);
-
-   if (keycode != KEY_RESERVED)
-   IR_dprintk(1, "%s: protocol 0x%04x scancode 0x%08llx keycode 
0x%02x\n",
-  kt->dev->input_name, protocol,
-  (unsigned long long)scancode, keycode);
-
return keycode;
 }
 
@@ -649,13 +639,17 @@ u32 rc_g_keycode_from_table(struct rc_dev *dev,
 {
struct rc_keytable *kt;
unsigned int keycode = KEY_RESERVED;
+   unsigned long flags;
 
/* FIXME: This entire function is a hack. Remove it */
rcu_read_lock();
kt = rcu_dereference(dev->keytables[0]);
if (!kt)
goto out;
+
+   spin_lock_irqsave(&kt->lock, flags);
keycode = rc_get_keycode(kt, protocol, scancode);
+   spin_unlock_irqrestore(&kt->lock, flags);
 
 out:
rcu_read_unlock();
@@ -669,7 +663,7 @@ EXPORT_SYMBOL_GPL(rc_g_keycode_from_table);
  * @sync:  whether or not to call input_sync
  *
  * This function is used internally to release a keypress, it must be
- * called with keylock held.
+ * called with kt->lock held.
  */
 static void rc_do_keyup(struct rc_keytable *kt, bool sync)
 {
@@ -694,9 +688,9 @@ void rc_keytable_keyup(struct rc_keytable *kt)
 {
unsigned long flags;
 
-   spin_lock_irqsave(&kt->keylock, flags);
+   spin_lock_irqsave(&kt->lock, flags);
rc_do_keyup(kt, true);
-   spin_unlock_irqrestore(&kt->keylock, flags);
+   spin_unlock_irqrestore(&kt->lock, flags);
 }
 
 /**
@@ -721,10 +715,10 @@ static void rc_timer_keyup(unsigned long cookie)
 * to allow the input subsystem to do its auto-repeat magic or
 * a keyup event might follow immediately after the keydown.
 */
-   spin_lock_irqsave(&kt->keylock, flags);
+   spin_lock_irqsave(&kt->lock, flags);
if (time_is_before_eq_jiffies(kt->keyup_jiffies))
rc_do_keyup(kt, true);
-   spin_unlock_irqrestore(&kt->keylock, flags);
+   spin_unlock_irqrestore(&kt->lock, flags);
 }
 
 /**
@@ -739,7 +733,7 @@ void rc_keytable_repeat(struct rc_keytable *kt)
 {
unsigned long flags;
 
-   spin_lock_irqsave(&kt->keylock, flags);
+   spin_lock_irqsave(&kt->lock, flags);
 
input_event(kt->idev, EV_MSC, MSC_SCAN, kt->last_scancode);
input_sync(kt->idev);
@@ -751,7 +745,7 @@ void rc_keytable_repeat(struct rc_keytable *kt)
mod_timer(&kt->timer_keyup, kt->keyup_jiffies);
 
 out:
-   spin_unlock_irqrestore(&kt->keylock, flags);
+   spin_unlock_irqrestore(&kt->lock, flags);
 }
 
 /**
@@ -772,7 +766,7 @@ void rc_keytable_keydown(struct rc_keytable *kt, enum 
rc_type protocol,
u32 keycode;
bool new_event;
 
-   spin_lock_irqsave(&kt->keylock, flags);
+   spin_lock_irqsave(&kt->lock, flags);
 
keycode = rc_get_keycode(kt, protocol, scancode);
new_event = 

[PATCH 40/49] rc-ir-raw: simplify locking

2014-04-03 Thread David Härdeman
Simplify and improve the locking in rc-ir-raw by making better use of
the existing kfifo functionality and by using RCU where possible.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-core-priv.h |6 +-
 drivers/media/rc/rc-ir-raw.c|  124 ---
 2 files changed, 55 insertions(+), 75 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 0b32ef8..c3de26b 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -37,11 +37,13 @@ struct ir_raw_handler {
int (*raw_unregister)(struct rc_dev *dev);
 };
 
+/* max number of pulse/space transitions to buffer */
+#define RC_MAX_IR_EVENTS   512
+
 struct ir_raw_event_ctrl {
struct list_headlist;   /* to keep track of raw 
clients */
struct task_struct  *thread;
-   spinlock_t  lock;
-   struct kfifo_rec_ptr_1  kfifo;  /* fifo for the 
pulse/space durations */
+   DECLARE_KFIFO(kfifo, struct ir_raw_event, RC_MAX_IR_EVENTS); /* for 
pulse/space durations */
ktime_t last_event; /* when last event 
occurred */
enum raw_event_type last_type;  /* last event type */
struct rc_dev   *dev;   /* pointer to the 
parent rc_dev */
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 86f5aa7..9631825 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -21,15 +21,12 @@
 #include 
 #include "rc-core-priv.h"
 
-/* Define the max number of pulse/space transitions to buffer */
-#define MAX_IR_EVENT_SIZE  512
-
-/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
+/* IR raw clients/handlers, writers synchronize with ir_raw_mutex */
+static DEFINE_MUTEX(ir_raw_mutex);
 static LIST_HEAD(ir_raw_client_list);
-
-/* Used to handle IR raw handler extensions */
-static DEFINE_MUTEX(ir_raw_handler_lock);
 static LIST_HEAD(ir_raw_handler_list);
+
+/* protocols supported by the currently loaded decoders */
 static u64 available_protocols;
 
 static int ir_raw_event_thread(void *data)
@@ -37,32 +34,19 @@ static int ir_raw_event_thread(void *data)
struct ir_raw_event ev;
struct ir_raw_handler *handler;
struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
-   int retval;
 
while (!kthread_should_stop()) {
-
-   spin_lock_irq(&raw->lock);
-   retval = kfifo_len(&raw->kfifo);
-
-   if (retval < sizeof(ev)) {
+   if (kfifo_out(&raw->kfifo, &ev, 1) == 0) {
set_current_state(TASK_INTERRUPTIBLE);
-
-   if (kthread_should_stop())
-   set_current_state(TASK_RUNNING);
-
-   spin_unlock_irq(&raw->lock);
schedule();
continue;
}
 
-   retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
-   spin_unlock_irq(&raw->lock);
-
-   mutex_lock(&ir_raw_handler_lock);
-   list_for_each_entry(handler, &ir_raw_handler_list, list)
+   rcu_read_lock();
+   list_for_each_entry_rcu(handler, &ir_raw_handler_list, list)
handler->decode(raw->dev, ev);
+   rcu_read_unlock();
raw->prev_ev = ev;
-   mutex_unlock(&ir_raw_handler_lock);
}
 
return 0;
@@ -76,7 +60,8 @@ static int ir_raw_event_thread(void *data)
  * This routine (which may be called from an interrupt context) stores a
  * pulse/space duration for the raw ir decoding state machines. Pulses are
  * signalled as positive values and spaces as negative values. A zero value
- * will reset the decoding state machines.
+ * will reset the decoding state machines. Drivers are responsible for
+ * synchronizing calls to this function.
  */
 int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev)
 {
@@ -86,7 +71,7 @@ int ir_raw_event_store(struct rc_dev *dev, struct 
ir_raw_event *ev)
IR_dprintk(2, "sample: (%05dus %s)\n",
   TO_US(ev->duration), TO_STR(ev->pulse));
 
-   if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
+   if (kfifo_in(&dev->raw->kfifo, ev, 1) != 1)
return -ENOMEM;
 
return 0;
@@ -258,14 +243,8 @@ EXPORT_SYMBOL_GPL(ir_raw_get_tx_event);
  */
 void ir_raw_event_handle(struct rc_dev *dev)
 {
-   unsigned long flags;
-
-   if (!dev->raw)
-   return;
-
-   spin_lock_irqsave(&dev->raw->lock, flags);
-   wake_up_process(dev->raw->thread);
-   spin_unlock_irqrestore(&dev->raw->lock, flags);
+   if (dev->raw)
+   wake_up_process(dev->raw->thread);
 }
 EXPORT_SYMBOL_GPL(ir_raw_event_handle);
 
@@ -273,9 +252,9 @@ EXPORT_SYMBOL_GPL(ir_raw_event_handle

[PATCH 36/49] rc-core: make keytable RCU-friendly

2014-04-03 Thread David Härdeman
Change struct rc_keytable to be RCU-friendly by kmalloc():ing an
entire new scancode,protocol <-> keycode table every time the table
is changed (i.e. via EVIOCSKEYCODE(_V2)).

The advantage is that the performance-critical keycode lookup path
can be made entirely lock-free and that GFP_ATOMIC allocations
can be avoided entirely at the cost of a couple of extra kmalloc()
calls when changing a keytable (which is normally done once during
boot).

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-keytable.c |  668 +++-
 include/media/rc-core.h|   32 +-
 2 files changed, 332 insertions(+), 368 deletions(-)

diff --git a/drivers/media/rc/rc-keytable.c b/drivers/media/rc/rc-keytable.c
index f4d03d2..89295f3 100644
--- a/drivers/media/rc/rc-keytable.c
+++ b/drivers/media/rc/rc-keytable.c
@@ -25,12 +25,10 @@
 #include 
 #include "rc-core-priv.h"
 
-/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
-#define IR_TAB_MIN_SIZE256
-#define IR_TAB_MAX_SIZE8192
+#define RC_TAB_MAX_SIZE1024 /* entries */
 
-/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
-#define IR_KEYPRESS_TIMEOUT 250
+/* FIXME: RC_KEYPRESS_TIMEOUT should be protocol specific */
+#define RC_KEYPRESS_TIMEOUT 250
 
 /* Used to keep track of known keymaps */
 static LIST_HEAD(rc_map_list);
@@ -99,237 +97,189 @@ void rc_map_unregister(struct rc_map_list *map)
 EXPORT_SYMBOL_GPL(rc_map_unregister);
 
 /**
- * ir_create_table() - initializes a scancode table
- * @rc_map:the rc_map to initialize
- * @name:  name to assign to the table
- * @size:  initial size of the table
- * @return:zero on success or a negative error code
- *
- * This routine will initialize the rc_map and will allocate
- * memory to hold at least the specified number of elements.
+ * rc_scan_size() - determine the necessary size for a rc_scan struct
+ * @len:   the number of keytable entries the struct should hold
+ * @return:the size of the struct in bytes
  */
-static int ir_create_table(struct rc_map *rc_map,
-  const char *name, size_t size)
+static inline size_t rc_scan_size(unsigned len)
 {
-   rc_map->name = name;
-   rc_map->alloc = roundup_pow_of_two(size * sizeof(struct rc_map_table));
-   rc_map->size = rc_map->alloc / sizeof(struct rc_map_table);
-   rc_map->scan = kmalloc(rc_map->alloc, GFP_KERNEL);
-   if (!rc_map->scan)
-   return -ENOMEM;
-
-   IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
-  rc_map->size, rc_map->alloc);
-   return 0;
+   return sizeof(struct rc_scan) + len * sizeof(struct rc_map_table);
 }
 
 /**
- * ir_free_table() - frees memory allocated by a scancode table
- * @rc_map:the table whose mappings need to be freed
+ * rc_keytable_update_entry() - update an existing entry in the keytable
+ * @kt:the keytable to update
+ * @i: the index of the entry to update
+ * @entry: the new values for the entry
+ * @return:the old rc_scan struct, NULL if memory could not be allocated
  *
- * This routine will free memory alloctaed for key mappings used by given
- * scancode table.
+ * Updates a keytable by replacing an existing entry at the given index.
+ * The old rc_scan struct is returned so that it can be freed at a
+ * later stage.
  */
-void ir_free_table(struct rc_map *rc_map)
+static struct rc_scan *rc_keytable_update_entry(struct rc_keytable *kt,
+   unsigned i,
+   struct rc_map_table *entry)
 {
-   rc_map->size = 0;
-   kfree(rc_map->scan);
-   rc_map->scan = NULL;
-}
+   struct rc_scan *old_scan = kt->scan;
+   struct rc_scan *new_scan = kt->scan;
+   u32 old_keycode;
 
-/**
- * ir_resize_table() - resizes a scancode table if necessary
- * @rc_map:the rc_map to resize
- * @gfp_flags: gfp flags to use when allocating memory
- * @return:zero on success or a negative error code
- *
- * This routine will shrink the rc_map if it has lots of
- * unused entries and grow it if it is full.
- */
-static int ir_resize_table(struct rc_map *rc_map, gfp_t gfp_flags)
-{
-   unsigned int oldalloc = rc_map->alloc;
-   unsigned int newalloc = oldalloc;
-   struct rc_map_table *oldscan = rc_map->scan;
-   struct rc_map_table *newscan;
-
-   if (rc_map->size == rc_map->len) {
-   /* All entries in use -> grow keytable */
-   if (rc_map->alloc >= IR_TAB_MAX_SIZE)
-   return -ENOMEM;
-
-   newalloc *= 2;
-   IR_dprintk(1, "Growing table to %u bytes\n", newalloc);
-   }
+   if (i >= old_scan->len)
+   return NULL;
 
-   if ((rc_map->len * 3 < rc_map->size) && (oldalloc > IR_TAB_MIN_SIZE)) {
-   /* Less than 1/3 of entries in use -> shrink keytable */
- 

[PATCH 37/49] rc-core: allow empty keymaps

2014-04-03 Thread David Härdeman
Remove the RC_MAP_EMPTY hack and instead allow for empty keymaps.

Signed-off-by: David Härdeman 
---
 drivers/media/i2c/ir-kbd-i2c.c |4 +--
 drivers/media/pci/cx88/cx88-input.c|6 -
 drivers/media/pci/ivtv/ivtv-i2c.c  |2 +-
 drivers/media/rc/gpio-ir-recv.c|2 +-
 drivers/media/rc/img-ir/img-ir-hw.c|1 -
 drivers/media/rc/img-ir/img-ir-raw.c   |1 -
 drivers/media/rc/rc-keytable.c |3 +++
 drivers/media/rc/rc-loopback.c |1 -
 drivers/media/rc/rc-main.c |   33 ++--
 drivers/media/usb/dvb-usb-v2/af9015.c  |4 ---
 drivers/media/usb/dvb-usb-v2/af9035.c  |4 ---
 drivers/media/usb/dvb-usb-v2/az6007.c  |4 ++-
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c|4 ---
 drivers/media/usb/dvb-usb/dvb-usb-remote.c |4 +--
 drivers/media/usb/em28xx/em28xx-cards.c|1 -
 include/media/rc-map.h |1 -
 16 files changed, 11 insertions(+), 64 deletions(-)

diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 8311f1a..5393558 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -309,7 +309,6 @@ static int ir_probe(struct i2c_client *client, const struct 
i2c_device_id *id)
name= "Pixelview";
ir->get_key = get_key_pixelview;
rc_type = RC_BIT_OTHER;
-   ir_codes= RC_MAP_EMPTY;
break;
case 0x18:
case 0x1f:
@@ -323,7 +322,6 @@ static int ir_probe(struct i2c_client *client, const struct 
i2c_device_id *id)
name= "KNC One";
ir->get_key = get_key_knc1;
rc_type = RC_BIT_OTHER;
-   ir_codes= RC_MAP_EMPTY;
break;
case 0x6b:
name= "FusionHDTV";
@@ -405,7 +403,7 @@ static int ir_probe(struct i2c_client *client, const struct 
i2c_device_id *id)
ir->rc = rc;
 
/* Make sure we are all setup before going on */
-   if (!name || !ir->get_key || !rc_type || !ir_codes) {
+   if (!name || !ir->get_key || !rc_type) {
dprintk(1, ": Unsupported device at address 0x%02x\n",
addr);
err = -ENODEV;
diff --git a/drivers/media/pci/cx88/cx88-input.c 
b/drivers/media/pci/cx88/cx88-input.c
index 3f1342c..cb587ce 100644
--- a/drivers/media/pci/cx88/cx88-input.c
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -437,11 +437,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev 
*pci)
break;
}
 
-   if (!ir_codes) {
-   err = -ENODEV;
-   goto err_out_free;
-   }
-
/*
 * The usage of mask_keycode were very convenient, due to several
 * reasons. Among others, the scancode tables were using the scancode
@@ -612,7 +607,6 @@ void cx88_i2c_init_ir(struct cx88_core *core)
core->init_data.name = "cx88 Leadtek PVR 2000 remote";
core->init_data.type = RC_BIT_UNKNOWN;
core->init_data.get_key = get_key_pvr2000;
-   core->init_data.ir_codes = RC_MAP_EMPTY;
break;
}
 
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c 
b/drivers/media/pci/ivtv/ivtv-i2c.c
index 1a41ba5..846bb51 100644
--- a/drivers/media/pci/ivtv/ivtv-i2c.c
+++ b/drivers/media/pci/ivtv/ivtv-i2c.c
@@ -222,7 +222,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const 
char *type, u8 addr)
init_data->get_key = get_key_adaptec;
init_data->name = itv->card_name;
/* FIXME: The protocol and RC_MAP needs to be corrected */
-   init_data->ir_codes = RC_MAP_EMPTY;
+   /* init_data->ir_codes = RC_MAP_? */
init_data->type = RC_BIT_UNKNOWN;
break;
}
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 5985308..7d01560 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -148,7 +148,7 @@ static int gpio_ir_recv_probe(struct platform_device *pdev)
rcdev->allowed_protocols = pdata->allowed_protos;
else
rcdev->allowed_protocols = RC_BIT_ALL;
-   rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
+   rcdev->map_name = pdata->map_name;
 
gpio_dev->rcdev = rcdev;
gpio_dev->gpio_nr = pdata->gpio_nr;
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c 
b/drivers/media/rc/img-ir/img-ir-hw.c
index 3bb6a32..5bc7903 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -993,7 +993,6 @@ int img_ir_probe_hw(struct img_ir_priv *priv)
goto err_alloc_rc;
}
rdev->priv = priv;
-   rdev->map_name = RC_MAP_EMPTY;
rdev->allowed_protocols = img_ir_allowed_protos(priv);
rdev->input_name = "I

[PATCH 42/49] rc-ir-raw: atomic reads of protocols

2014-04-03 Thread David Härdeman
Use atomic reads to avoid having to take a mutex when getting
the bitmask of supported protocols.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-core-priv.h |2 +-
 drivers/media/rc/rc-ir-raw.c|   12 
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index c3de26b..04776e8 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -29,7 +29,7 @@ enum rc_driver_type {
 struct ir_raw_handler {
struct list_head list;
 
-   u64 protocols; /* which are handled by this handler */
+   unsigned protocols; /* which are handled by this handler */
int (*decode)(struct rc_dev *dev, struct ir_raw_event event);
 
/* These two should only be used by the lirc decoder */
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 9631825..bf5215b 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -27,7 +27,7 @@ static LIST_HEAD(ir_raw_client_list);
 static LIST_HEAD(ir_raw_handler_list);
 
 /* protocols supported by the currently loaded decoders */
-static u64 available_protocols;
+static atomic_t available_protocols = ATOMIC_INIT(0);
 
 static int ir_raw_event_thread(void *data)
 {
@@ -251,11 +251,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_handle);
 /* used internally by the sysfs interface */
 static u64 ir_raw_get_allowed_protocols(struct rc_dev *dev)
 {
-   u64 protocols;
-   mutex_lock(&ir_raw_mutex);
-   protocols = available_protocols;
-   mutex_unlock(&ir_raw_mutex);
-   return protocols;
+   return atomic_read(&available_protocols);
 }
 
 static int change_protocol(struct rc_dev *dev, u64 *rc_type) {
@@ -353,7 +349,7 @@ int ir_raw_handler_register(struct ir_raw_handler 
*ir_raw_handler)
if (ir_raw_handler->raw_register)
list_for_each_entry_rcu(raw, &ir_raw_client_list, list)
ir_raw_handler->raw_register(raw->dev);
-   available_protocols |= ir_raw_handler->protocols;
+   atomic_set_mask(ir_raw_handler->protocols, &available_protocols);
mutex_unlock(&ir_raw_mutex);
synchronize_rcu();
 
@@ -370,7 +366,7 @@ void ir_raw_handler_unregister(struct ir_raw_handler 
*ir_raw_handler)
if (ir_raw_handler->raw_unregister)
list_for_each_entry_rcu(raw, &ir_raw_client_list, list)
ir_raw_handler->raw_unregister(raw->dev);
-   available_protocols &= ~ir_raw_handler->protocols;
+   atomic_clear_mask(ir_raw_handler->protocols, &available_protocols);
mutex_unlock(&ir_raw_mutex);
synchronize_rcu();
 }

--
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 41/49] rc-core: rename mutex

2014-04-03 Thread David Härdeman
Having a mutex named "lock" is a bit misleading.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/img-ir/img-ir-hw.c |4 ++-
 drivers/media/rc/rc-main.c  |   42 ++-
 include/media/rc-core.h |5 ++--
 3 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/drivers/media/rc/img-ir/img-ir-hw.c 
b/drivers/media/rc/img-ir/img-ir-hw.c
index 5bc7903..a9abbb4 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -666,11 +666,11 @@ static void img_ir_set_protocol(struct img_ir_priv *priv, 
u64 proto)
 {
struct rc_dev *rdev = priv->hw.rdev;
 
-   mutex_lock(&rdev->lock);
+   mutex_lock(&rdev->mutex);
rdev->enabled_protocols = proto;
rdev->allowed_wakeup_protocols = proto;
rdev->enabled_wakeup_protocols = proto;
-   mutex_unlock(&rdev->lock);
+   mutex_unlock(&rdev->mutex);
 }
 
 /* Set up IR decoders */
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 7caca4f..bd4dfab 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -109,7 +109,7 @@ int rc_open(struct rc_dev *dev)
 {
int err = 0;
 
-   mutex_lock(&dev->lock);
+   mutex_lock(&dev->mutex);
 
if (dev->dead)
err = -ENODEV;
@@ -119,7 +119,7 @@ int rc_open(struct rc_dev *dev)
dev->users--;
}
 
-   mutex_unlock(&dev->lock);
+   mutex_unlock(&dev->mutex);
 
return err;
 }
@@ -127,12 +127,12 @@ EXPORT_SYMBOL_GPL(rc_open);
 
 void rc_close(struct rc_dev *dev)
 {
-   mutex_lock(&dev->lock);
+   mutex_lock(&dev->mutex);
 
if (!dev->dead && !--dev->users && dev->close)
dev->close(dev);
 
-   mutex_unlock(&dev->lock);
+   mutex_unlock(&dev->mutex);
 }
 EXPORT_SYMBOL_GPL(rc_close);
 
@@ -322,7 +322,7 @@ struct rc_filter_attribute {
  * It returns the protocol names of supported protocols.
  * Enabled protocols are printed in brackets.
  *
- * dev->lock is taken to guard against races between store_protocols and
+ * dev->mutex is taken to guard against races between store_protocols and
  * show_protocols.
  */
 static ssize_t show_protocols(struct device *device,
@@ -339,7 +339,7 @@ static ssize_t show_protocols(struct device *device,
return -EINVAL;
 
rc_event(dev, RC_KEY, RC_KEY_REPEAT, 1);
-   mutex_lock(&dev->lock);
+   mutex_lock(&dev->mutex);
 
if (fattr->type == RC_FILTER_NORMAL) {
enabled = dev->enabled_protocols;
@@ -349,7 +349,7 @@ static ssize_t show_protocols(struct device *device,
allowed = dev->allowed_wakeup_protocols;
}
 
-   mutex_unlock(&dev->lock);
+   mutex_unlock(&dev->mutex);
 
IR_dprintk(1, "%s: allowed - 0x%llx, enabled - 0x%llx\n",
   __func__, (long long)allowed, (long long)enabled);
@@ -449,7 +449,7 @@ static int parse_protocol_change(u64 *protocols, const char 
*buf)
  * See parse_protocol_change() for the valid commands.
  * Returns @len on success or a negative error code.
  *
- * dev->lock is taken to guard against races between store_protocols and
+ * dev->mutex is taken to guard against races between store_protocols and
  * show_protocols.
  */
 static ssize_t store_protocols(struct device *device,
@@ -488,7 +488,7 @@ static ssize_t store_protocols(struct device *device,
return -EINVAL;
}
 
-   mutex_lock(&dev->lock);
+   mutex_lock(&dev->mutex);
 
old_protocols = *current_protocols;
new_protocols = old_protocols;
@@ -532,7 +532,7 @@ static ssize_t store_protocols(struct device *device,
rc = len;
 
 out:
-   mutex_unlock(&dev->lock);
+   mutex_unlock(&dev->mutex);
return rc;
 }
 
@@ -550,7 +550,7 @@ out:
  * Bits of the filter value corresponding to set bits in the filter mask are
  * compared against input scancodes and non-matching scancodes are discarded.
  *
- * dev->lock is taken to guard against races between store_filter and
+ * dev->mutex is taken to guard against races between store_filter and
  * show_filter.
  */
 static ssize_t show_filter(struct device *device,
@@ -571,12 +571,12 @@ static ssize_t show_filter(struct device *device,
else
filter = &dev->scancode_wakeup_filter;
 
-   mutex_lock(&dev->lock);
+   mutex_lock(&dev->mutex);
if (fattr->mask)
val = filter->mask;
else
val = filter->data;
-   mutex_unlock(&dev->lock);
+   mutex_unlock(&dev->mutex);
 
return sprintf(buf, "%#x\n", val);
 }
@@ -597,7 +597,7 @@ static ssize_t show_filter(struct device *device,
  * Bits of the filter value corresponding to set bits in the filter mask are
  * compared against input scancodes and non-matching scancodes are discarded.
  *
- * dev->lock is taken to guard against races between store_filter and
+ * dev->mutex is taken to guard agains

[PATCH 38/49] rc-core: rename ir-raw.c

2014-04-03 Thread David Härdeman
Move drivers/media/rc/ir-raw.c to drivers/media/rc/rc-ir-raw.c in
preparation for the next patch.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/Makefile|2 +-
 drivers/media/rc/rc-ir-raw.c |2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
 rename drivers/media/rc/{ir-raw.c => rc-ir-raw.c} (99%)

diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index de08ee6..661f449 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -1,4 +1,4 @@
-rc-core-objs   := rc-main.o rc-keytable.o ir-raw.o
+rc-core-objs   := rc-main.o rc-keytable.o rc-ir-raw.o
 
 obj-y += keymaps/
 
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/rc-ir-raw.c
similarity index 99%
rename from drivers/media/rc/ir-raw.c
rename to drivers/media/rc/rc-ir-raw.c
index aa2503d..5ed8007 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -1,4 +1,4 @@
-/* ir-raw.c - handle IR pulse/space events
+/* rc-ir-raw.c - handle IR pulse/space events
  *
  * Copyright (C) 2010 by Mauro Carvalho Chehab
  *

--
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 39/49] rc-core: make IR raw handling a separate module

2014-04-03 Thread David Härdeman
Make drivers/media/rc/rc-ir-raw.c a separate kernel module.

Drivers which use IR decoding must use these functions:
rc_register_ir_raw_device()
rc_unregister_ir_raw_device()
instead of:
rc_register_device()
rc_unregister_device()

This allows scancode drivers to skip lots of unnecessary functionality.

Signed-off-by: David Härdeman 
---
 drivers/media/common/siano/smsir.c  |5 +-
 drivers/media/common/siano/smsir.h  |2 -
 drivers/media/i2c/cx25840/cx25840-ir.c  |2 -
 drivers/media/pci/cx23885/cx23885-input.c   |   13 +---
 drivers/media/pci/cx23885/cx23888-ir.c  |2 -
 drivers/media/pci/cx88/cx88-input.c |   18 +++---
 drivers/media/pci/dm1105/dm1105.c   |1 
 drivers/media/pci/saa7134/saa7134-input.c   |   14 +++--
 drivers/media/pci/saa7134/saa7134.h |2 -
 drivers/media/rc/Makefile   |3 +
 drivers/media/rc/ati_remote.c   |1 
 drivers/media/rc/ene_ir.c   |9 +--
 drivers/media/rc/fintek-cir.c   |7 +-
 drivers/media/rc/gpio-ir-recv.c |9 +--
 drivers/media/rc/iguanair.c |7 +-
 drivers/media/rc/img-ir/img-ir-raw.c|7 +-
 drivers/media/rc/imon.c |1 
 drivers/media/rc/ite-cir.c  |9 +--
 drivers/media/rc/mceusb.c   |7 +-
 drivers/media/rc/nuvoton-cir.c  |7 +-
 drivers/media/rc/rc-core-priv.h |   10 ++-
 drivers/media/rc/rc-ir-raw.c|   39 +
 drivers/media/rc/rc-loopback.c  |7 +-
 drivers/media/rc/rc-main.c  |   36 +---
 drivers/media/rc/redrat3.c  |7 +-
 drivers/media/rc/streamzap.c|7 +-
 drivers/media/rc/ttusbir.c  |9 +--
 drivers/media/rc/winbond-cir.c  |9 +--
 drivers/media/usb/dvb-usb-v2/dvb_usb.h  |5 +-
 drivers/media/usb/dvb-usb-v2/dvb_usb_core.c |   12 +++-
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c |2 -
 drivers/media/usb/dvb-usb/dvb-usb-remote.c  |9 ++-
 drivers/media/usb/dvb-usb/dvb-usb.h |5 +-
 drivers/media/usb/dvb-usb/technisat-usb2.c  |2 -
 drivers/media/usb/em28xx/em28xx-input.c |5 --
 drivers/media/usb/tm6000/tm6000-input.c |1 
 include/media/rc-core.h |   73 +---
 include/media/rc-ir-raw.h   |   83 +++
 38 files changed, 222 insertions(+), 225 deletions(-)
 create mode 100644 include/media/rc-ir-raw.h

diff --git a/drivers/media/common/siano/smsir.c 
b/drivers/media/common/siano/smsir.c
index 273043e..f6938f4 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -87,14 +87,13 @@ int sms_ir_init(struct smscore_device_t *coredev)
 #endif
 
dev->priv = coredev;
-   dev->driver_type = RC_DRIVER_IR_RAW;
dev->allowed_protocols = RC_BIT_ALL;
dev->map_name = sms_get_board(board_id)->rc_codes;
dev->driver_name = MODULE_NAME;
 
sms_log("Input device (IR) %s is set for key events", dev->input_name);
 
-   err = rc_register_device(dev);
+   err = rc_register_ir_raw_device(dev);
if (err < 0) {
sms_err("Failed to register device");
rc_free_device(dev);
@@ -108,7 +107,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
 void sms_ir_exit(struct smscore_device_t *coredev)
 {
if (coredev->ir.dev)
-   rc_unregister_device(coredev->ir.dev);
+   rc_unregister_ir_raw_device(coredev->ir.dev);
 
sms_log("");
 }
diff --git a/drivers/media/common/siano/smsir.h 
b/drivers/media/common/siano/smsir.h
index fc8b792..05a2b01 100644
--- a/drivers/media/common/siano/smsir.h
+++ b/drivers/media/common/siano/smsir.h
@@ -28,7 +28,7 @@ along with this program.  If not, see 
.
 #define __SMS_IR_H__
 
 #include 
-#include 
+#include 
 
 #define IR_DEFAULT_TIMEOUT 100
 
diff --git a/drivers/media/i2c/cx25840/cx25840-ir.c 
b/drivers/media/i2c/cx25840/cx25840-ir.c
index e6588ee..119d4e8 100644
--- a/drivers/media/i2c/cx25840/cx25840-ir.c
+++ b/drivers/media/i2c/cx25840/cx25840-ir.c
@@ -25,7 +25,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #include "cx25840-core.h"
 
diff --git a/drivers/media/pci/cx23885/cx23885-input.c 
b/drivers/media/pci/cx23885/cx23885-input.c
index 1940c18..e2ba28d 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -36,7 +36,7 @@
  */
 
 #include 
-#include 
+#include 
 #include 
 
 #include "cx23885.h"
@@ -258,7 +258,6 @@ int cx23885_input_init(struct cx23885_dev *dev)
struct cx23885_kernel_ir *kernel_ir;
struct rc_dev *rc;
char *rc_map;
-   enum rc_driver_type driver_type;
unsigned long allowed_protos;
 
int ret;

[PATCH 34/49] rc-core: add ioctls for adding/removing keytables from userspace

2014-04-03 Thread David Härdeman
As all the basics are now in place, we can finally add the ioctls
for adding/removing keytables from userspace.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-core-priv.h |2 -
 drivers/media/rc/rc-keytable.c  |5 ++
 drivers/media/rc/rc-main.c  |   81 ---
 include/media/rc-core.h |   27 +
 4 files changed, 106 insertions(+), 9 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 02b538c..0159836 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -162,7 +162,7 @@ void rc_keytable_keyup(struct rc_keytable *kt);
 void rc_keytable_repeat(struct rc_keytable *kt);
 void rc_keytable_keydown(struct rc_keytable *kt, enum rc_type protocol,
 u32 scancode, u8 toggle, bool autokeyup);
-struct rc_keytable *rc_keytable_create(struct rc_dev *dev, struct rc_map 
*rc_map);
+struct rc_keytable *rc_keytable_create(struct rc_dev *dev, const char *name, 
struct rc_map *rc_map);
 void rc_keytable_destroy(struct rc_keytable *kt);
 
 /* Only to be used by rc-core and ir-lirc-codec */
diff --git a/drivers/media/rc/rc-keytable.c b/drivers/media/rc/rc-keytable.c
index 412d342..6d04b8f 100644
--- a/drivers/media/rc/rc-keytable.c
+++ b/drivers/media/rc/rc-keytable.c
@@ -825,6 +825,7 @@ static void rc_input_close(struct input_dev *idev)
 /**
  * rc_keytable_create() - create a new keytable
  * @dev:   the struct rc_dev device this keytable should belong to
+ * @name:  the userfriendly name of this keymap
  * @rc_map:the keymap to use for the new keytable
  * @return:zero on success or a negative error code
  *
@@ -832,7 +833,8 @@ static void rc_input_close(struct input_dev *idev)
  * keytable and an input device along with some state (whether a key is
  * currently pressed or not, etc).
  */
-struct rc_keytable *rc_keytable_create(struct rc_dev *dev, struct rc_map 
*rc_map)
+struct rc_keytable *rc_keytable_create(struct rc_dev *dev, const char *name,
+  struct rc_map *rc_map)
 {
struct rc_keytable *kt;
struct input_dev *idev = NULL;
@@ -854,6 +856,7 @@ struct rc_keytable *rc_keytable_create(struct rc_dev *dev, 
struct rc_map *rc_map
kt->dev = dev;
spin_lock_init(&kt->keylock);
spin_lock_init(&kt->rc_map.lock);
+   snprintf(kt->name, sizeof(*kt->name), name ? name : "undefined");
idev->getkeycode = ir_getkeycode;
idev->setkeycode = ir_setkeycode;
idev->open = rc_input_open;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index bc2d479..ad784c8 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -201,7 +201,8 @@ void rc_repeat(struct rc_dev *dev)
 }
 EXPORT_SYMBOL_GPL(rc_repeat);
 
-static int rc_add_keytable(struct rc_dev *dev, struct rc_map *rc_map)
+static int rc_add_keytable(struct rc_dev *dev, const char *name,
+  struct rc_map *rc_map)
 {
struct rc_keytable *kt;
unsigned i;
@@ -219,7 +220,7 @@ static int rc_add_keytable(struct rc_dev *dev, struct 
rc_map *rc_map)
if (i >= ARRAY_SIZE(dev->keytables))
return -ENFILE;
 
-   kt = rc_keytable_create(dev, rc_map);
+   kt = rc_keytable_create(dev, name, rc_map);
if (IS_ERR(kt))
return PTR_ERR(kt);
 
@@ -229,19 +230,24 @@ static int rc_add_keytable(struct rc_dev *dev, struct 
rc_map *rc_map)
return 0;
 }
 
-static void rc_remove_keytable(struct rc_dev *dev, unsigned i)
+static int rc_remove_keytable(struct rc_dev *dev, unsigned i)
 {
struct rc_keytable *kt;
 
if (i >= ARRAY_SIZE(dev->keytables))
-   return;
+   return -EINVAL;
 
kt = dev->keytables[i];
rcu_assign_pointer(dev->keytables[i], NULL);
if (kt)
list_del_rcu(&kt->node);
synchronize_rcu();
+
+   if (!kt)
+   return -EINVAL;
+
rc_keytable_destroy(kt);
+   return 0;
 }
 
 /* class for /sys/class/rc */
@@ -946,6 +952,8 @@ static long rc_do_ioctl(struct rc_dev *dev, unsigned int 
cmd, unsigned long arg)
unsigned int __user *ip = (unsigned int __user *)p;
struct rc_ir_rx rx;
struct rc_ir_tx tx;
+   struct rc_keytable_ioctl ktio;
+   struct rc_keytable *kt;
int error;
 
switch (cmd) {
@@ -1007,8 +1015,69 @@ static long rc_do_ioctl(struct rc_dev *dev, unsigned int 
cmd, unsigned long arg)
return -EFAULT;
 
return 0;
-   }
 
+   case RCIOCADDTABLE:
+   if (copy_from_user(&ktio, p, sizeof(ktio)))
+   return -EFAULT;
+
+   if (ktio.id >= RC_MAX_KEYTABLES)
+   return -EINVAL;
+
+   if (ktio.flags)
+   return -EINVAL;
+
+   ktio.name[sizeof(ktio.name) - 1] = '\0';
+   if (strl

[PATCH 47/49] rc-core: add keytable events

2014-04-03 Thread David Härdeman
Add separe rc device events on keytable addition/removal.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-main.c |2 ++
 include/media/rc-core.h|2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index bd4dfab..b3db1dd 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -221,6 +221,7 @@ static int rc_add_keytable(struct rc_dev *dev, const char 
*name,
rcu_assign_pointer(dev->keytables[i], kt);
list_add_rcu(&kt->node, &dev->keytable_list);
synchronize_rcu();
+   rc_event(dev, RC_CORE, RC_CORE_KT_ADDED, i);
return 0;
 }
 
@@ -241,6 +242,7 @@ static int rc_remove_keytable(struct rc_dev *dev, unsigned 
i)
return -EINVAL;
 
rc_keytable_destroy(kt);
+   rc_event(dev, RC_CORE, RC_CORE_KT_REMOVED, i);
return 0;
 }
 
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index a310e5b..a7354b7 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -203,6 +203,8 @@ struct rc_keymap_entry {
 
 /* RC_CORE codes */
 #define RC_CORE_DROPPED0x0
+#define RC_CORE_KT_ADDED   0x1
+#define RC_CORE_KT_REMOVED 0x2
 
 /* RC_KEY codes */
 #define RC_KEY_REPEAT  0x0

--
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 49/49] rc-core: make rc-core.h userspace friendly

2014-04-03 Thread David Härdeman
A few ifdef __KERNEL__ and some reorganisation to make rc-core.h usable from
userspace programs. A split into include/uapi/ might be a good idea later.

Signed-off-by: David Härdeman 
---
 include/media/rc-core.h |   71 ---
 1 file changed, 48 insertions(+), 23 deletions(-)

diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index aff3bdd..caa159f 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -16,21 +16,22 @@
 #ifndef _RC_CORE
 #define _RC_CORE
 
+#ifdef __KERNEL__
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#else
+#include 
+#include 
+#include 
+#include 
+#endif
 
-extern int rc_core_debug;
-#define IR_dprintk(level, fmt, ...)\
-do {   \
-   if (rc_core_debug >= level) \
-   pr_debug("%s: " fmt, __func__, ##__VA_ARGS__);  \
-} while (0)
-
-#define RC_VERSION 0x01
+#define RC_VERSION 0x01
+#define RC_MAX_KEYTABLES   32
 
 /*
  * ioctl definitions
@@ -177,13 +178,27 @@ struct rc_keytable_ioctl {
char name[RC_KEYTABLE_NAME_SIZE];
 } __packed;
 
-/* This is used for the input EVIOC[SG]KEYCODE_V2 ioctls */
+/**
+ * struct rc_scancode - protocol/scancode pair
+ * @protocol:  the protocol of the rc command
+ * @reserved:  for future use and padding, set to zero
+ * @scancode:  the scancode of the command
+ */
 struct rc_scancode {
__u16 protocol;
__u16 reserved[3];
__u64 scancode;
 };
 
+/**
+ * struct rc_keymap_entry - used in EVIOC[SG]KEYCODE_V2 ioctls
+ * @flags: see &struct input_keymap_entry
+ * @len:   see &struct input_keymap_entry
+ * @index: see &struct input_keymap_entry
+ * @keycode:   see &struct input_keymap_entry
+ * @rc:the scancode/protocol definition, see &struct 
rc_scancode
+ * @raw:   alternative representation of @rc
+ */
 struct rc_keymap_entry {
__u8  flags;
__u8  len;
@@ -236,6 +251,9 @@ struct rc_event {
 
 #define RC_TX_KFIFO_SIZE   1024
 
+#ifdef __KERNEL__
+/* The rest is implementational details which shouldn't concern userspace */
+
 /**
  * struct rc_scancode_filter - Filter scan codes.
  * @data:  Scancode data to match.
@@ -323,7 +341,6 @@ enum rc_filter_type {
  * @get_ir_tx: allow driver to provide tx settings
  * @set_ir_tx: allow driver to change tx settings
  */
-#define RC_MAX_KEYTABLES   32
 struct rc_dev {
struct device   dev;
struct cdev cdev;
@@ -382,31 +399,23 @@ struct rc_dev {
void(*get_ir_tx)(struct rc_dev *dev, struct 
rc_ir_tx *tx);
int (*set_ir_tx)(struct rc_dev *dev, struct 
rc_ir_tx *tx);
 };
-
 #define to_rc_dev(d) container_of(d, struct rc_dev, dev)
 
-/*
- * From rc-main.c
- * Those functions can be used on any type of Remote Controller. They
- * basically creates an input_dev and properly reports the device as a
- * Remote Controller, at sys/class/rc.
- */
-
+/* From rc-main.c - see inline kerneldoc */
 struct rc_dev *rc_allocate_device(void);
 void rc_free_device(struct rc_dev *dev);
 int rc_register_device(struct rc_dev *dev);
 void rc_unregister_device(struct rc_dev *dev);
 void rc_event(struct rc_dev *dev, u16 type, u16 code, u32 val);
-
 int rc_open(struct rc_dev *rdev);
 void rc_close(struct rc_dev *rdev);
 
+/* From rc-keytable.c - see inline kerneldoc */
 void rc_repeat(struct rc_dev *dev);
-void rc_do_keydown(struct rc_dev *dev, enum rc_type protocol,
-  u32 scancode, u8 toggle, bool autoup);
 void rc_keyup(struct rc_dev *dev);
 u32 rc_g_keycode_from_table(struct rc_dev *dev, enum rc_type protocol, u64 
scancode);
-
+void rc_do_keydown(struct rc_dev *dev, enum rc_type protocol,
+  u32 scancode, u8 toggle, bool autoup);
 static inline void rc_keydown(struct rc_dev *dev, enum rc_type protocol, u32 
scancode, u8 toggle) {
rc_do_keydown(dev, protocol, scancode, toggle, true);
 }
@@ -415,7 +424,22 @@ static inline void rc_keydown_notimeout(struct rc_dev 
*dev, enum rc_type protoco
rc_do_keydown(dev, protocol, scancode, toggle, false);
 }
 
-/* extract mask bits out of data and pack them into the result */
+extern int rc_core_debug;
+#define IR_dprintk(level, fmt, ...)\
+do {   \
+   if (rc_core_debug >= level) \
+   pr_debug("%s: " fmt, __func__, ##__VA_ARGS__);  \
+} while (0)
+
+/**
+ * ir_extract_bits() - extract bits of data according to a mask
+ * @data:  the data to extract bits from
+ * @mask:  the mask of bits to extract
+ * @return:the extracted bits packed together
+ *
+ * This helper function is used by some drivers to extract the relevant
+ * (masked) bits of data.
+ */
 static inline 

[PATCH 43/49] rc-core: fix various sparse warnings

2014-04-03 Thread David Härdeman
Fix various sparse warnings under drivers/media/rc/*.c, mostly
by making functions static.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/fintek-cir.c  |4 ++--
 drivers/media/rc/imon.c|8 
 drivers/media/rc/ite-cir.c |4 ++--
 drivers/media/rc/nuvoton-cir.c |4 ++--
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
index ce2db15..dd49c28 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
@@ -685,12 +685,12 @@ static struct pnp_driver fintek_driver = {
.shutdown   = fintek_shutdown,
 };
 
-static int fintek_init(void)
+static int __init fintek_init(void)
 {
return pnp_register_driver(&fintek_driver);
 }
 
-static void fintek_exit(void)
+static void __exit fintek_exit(void)
 {
pnp_unregister_driver(&fintek_driver);
 }
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 1aa2ac0..287edf6 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -78,11 +78,11 @@ static int display_open(struct inode *inode, struct file 
*file);
 static int display_close(struct inode *inode, struct file *file);
 
 /* VFD write operation */
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
 size_t n_bytes, loff_t *pos);
 
 /* LCD file_operations override function prototypes */
-static ssize_t lcd_write(struct file *file, const char *buf,
+static ssize_t lcd_write(struct file *file, const char __user *buf,
 size_t n_bytes, loff_t *pos);
 
 /*** G L O B A L S ***/
@@ -825,7 +825,7 @@ static struct attribute_group imon_rf_attr_group = {
  * than 32 bytes are provided spaces will be appended to
  * generate a full screen.
  */
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
 size_t n_bytes, loff_t *pos)
 {
int i;
@@ -912,7 +912,7 @@ exit:
  * display whatever diacritics you need, and so on), but it's also
  * a lot more complicated than most LCDs...
  */
-static ssize_t lcd_write(struct file *file, const char *buf,
+static ssize_t lcd_write(struct file *file, const char __user *buf,
 size_t n_bytes, loff_t *pos)
 {
int retval = 0;
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index 795fbc6..2755e06 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1703,12 +1703,12 @@ static struct pnp_driver ite_driver = {
.shutdown   = ite_shutdown,
 };
 
-static int ite_init(void)
+static int __init ite_init(void)
 {
return pnp_register_driver(&ite_driver);
 }
 
-static void ite_exit(void)
+static void __exit ite_exit(void)
 {
pnp_unregister_driver(&ite_driver);
 }
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index a8c9b5f..9e63ee6 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1231,12 +1231,12 @@ static struct pnp_driver nvt_driver = {
.shutdown   = nvt_shutdown,
 };
 
-static int nvt_init(void)
+static int __init nvt_init(void)
 {
return pnp_register_driver(&nvt_driver);
 }
 
-static void nvt_exit(void)
+static void __exit nvt_exit(void)
 {
pnp_unregister_driver(&nvt_driver);
 }

--
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 45/49] rc-ir-raw: add various rc_events

2014-04-03 Thread David Härdeman
Reporting pulse/space events via the /dev/rc/rcX device node is an
important step towards having feature parity with LIRC.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-ir-raw.c |   11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index bf5215b..3b68975 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -71,6 +71,17 @@ int ir_raw_event_store(struct rc_dev *dev, struct 
ir_raw_event *ev)
IR_dprintk(2, "sample: (%05dus %s)\n",
   TO_US(ev->duration), TO_STR(ev->pulse));
 
+   if (ev->reset)
+   rc_event(dev, RC_IR, RC_IR_RESET, 1);
+   else if (ev->carrier_report)
+   rc_event(dev, RC_IR, RC_IR_CARRIER, ev->carrier);
+   else if (ev->timeout)
+   rc_event(dev, RC_IR, RC_IR_STOP, 1);
+   else if (ev->pulse)
+   rc_event(dev, RC_IR, RC_IR_PULSE, ev->duration);
+   else
+   rc_event(dev, RC_IR, RC_IR_SPACE, ev->duration);
+
if (kfifo_in(&dev->raw->kfifo, ev, 1) != 1)
return -ENOMEM;
 

--
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 48/49] rc-core: move remaining keytable functions

2014-04-03 Thread David Härdeman
Move some more keytable related functionality over to rc-keytable.c which
allows more implementational details to be obscured away.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-core-priv.h |   54 +++-
 drivers/media/rc/rc-keytable.c  |  169 +++
 drivers/media/rc/rc-main.c  |  136 ++-
 include/media/rc-core.h |   44 --
 4 files changed, 191 insertions(+), 212 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 4945727..1c6c066 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -168,12 +168,54 @@ void ir_raw_handler_unregister(struct ir_raw_handler 
*ir_raw_handler);
 /*
  * Methods from rc-keytable.c to be used internally
  */
-void rc_keytable_keyup(struct rc_keytable *kt);
-void rc_keytable_repeat(struct rc_keytable *kt);
-void rc_keytable_keydown(struct rc_keytable *kt, enum rc_type protocol,
-u32 scancode, u8 toggle, bool autokeyup);
-struct rc_keytable *rc_keytable_create(struct rc_dev *dev, const char *name, 
struct rc_map *rc_map);
-void rc_keytable_destroy(struct rc_keytable *kt);
+int rc_keytable_add(struct rc_dev *dev, const char *name, struct rc_map 
*rc_map);
+int rc_keytable_del(struct rc_dev *dev, unsigned i);
+int rc_keytable_get_name(struct rc_dev *dev, unsigned i,
+char *buf, size_t bufsize);
+
+/**
+ * struct rc_scan - rcu-friendly scancode<->keycode table
+ * @len:   number of elements in the table array
+ * @table: array of struct rc_map_table elements
+ */
+struct rc_scan {
+   unsigned len;
+   struct rc_map_table table[];
+};
+
+/**
+ * struct rc_keytable - represents one keytable for a rc_dev device
+ * @node:  used to iterate over all keytables for a rc_dev device
+ * @dev:   the rc_dev device this keytable belongs to
+ * @idev:  the input_dev device which belongs to this keytable
+ * @name:  the user-friendly name of this keytable
+ * @scan_mutex:protects @scan against concurrent writers
+ * @scan:  the current scancode<->keycode table
+ * @key_lock:  protects the key state
+ * @key_pressed:   whether a key is currently pressed or not
+ * @last_keycode:  keycode of the last keypress
+ * @last_protocol: protocol of the last keypress
+ * @last_scancode: scancode of the last keypress
+ * @last_toggle:   toggle of the last keypress
+ * @timer_keyup:   responsible for the auto-release of keys
+ * @keyup_jiffies: when the key should be auto-released
+ */
+struct rc_keytable {
+   struct list_headnode;
+   struct rc_dev   *dev;
+   struct input_dev*idev;
+   charname[RC_KEYTABLE_NAME_SIZE];
+   struct mutexscan_mutex;
+   struct rc_scan __rcu*scan;
+   spinlock_t  key_lock;
+   boolkey_pressed;
+   u32 last_keycode;
+   enum rc_typelast_protocol;
+   u32 last_scancode;
+   u8  last_toggle;
+   struct timer_list   timer_keyup;
+   unsigned long   keyup_jiffies;
+};
 
 /* Only to be used by rc-core and ir-lirc-codec */
 void rc_init_ir_rx(struct rc_dev *dev, struct rc_ir_rx *rx);
diff --git a/drivers/media/rc/rc-keytable.c b/drivers/media/rc/rc-keytable.c
index 23a66c7..1dd75e2 100644
--- a/drivers/media/rc/rc-keytable.c
+++ b/drivers/media/rc/rc-keytable.c
@@ -591,19 +591,25 @@ static void rc_do_keyup(struct rc_keytable *kt, bool sync)
 }
 
 /**
- * rc_keytable_keyup() - signals the release of a keypress
- * @kt:the keytable
+ * rc_keyup() - signals the release of a keypress
+ * @dev:   the struct rc_dev descriptor of the device
  *
- * This routine is used to generate input keyup events.
+ * Report that a key is no longer pressed.
  */
-void rc_keytable_keyup(struct rc_keytable *kt)
+void rc_keyup(struct rc_dev *dev)
 {
+   struct rc_keytable *kt;
unsigned long flags;
 
-   spin_lock_irqsave(&kt->key_lock, flags);
-   rc_do_keyup(kt, true);
-   spin_unlock_irqrestore(&kt->key_lock, flags);
+   rcu_read_lock();
+   list_for_each_entry_rcu(kt, &dev->keytable_list, node) {
+   spin_lock_irqsave(&kt->key_lock, flags);
+   rc_do_keyup(kt, true);
+   spin_unlock_irqrestore(&kt->key_lock, flags);
+   }
+   rcu_read_unlock();
 }
+EXPORT_SYMBOL_GPL(rc_keyup);
 
 /**
  * rc_timer_keyup() - generates a keyup event after a timeout
@@ -634,23 +640,31 @@ static void rc_timer_keyup(unsigned long cookie)
 }
 
 /**
- * rc_keytable_repeat() - signals that a key is still pressed
- * @kt:the keytable
+ * r

[PATCH 44/49] rc-core: don't report scancodes via input devices

2014-04-03 Thread David Härdeman
The scancode that is reported via the input device(s) is now incomplete
(missing the protocol) and redundant.

Signed-off-by: David Härdeman 
---
 drivers/media/rc/rc-keytable.c |   21 +
 1 file changed, 5 insertions(+), 16 deletions(-)

diff --git a/drivers/media/rc/rc-keytable.c b/drivers/media/rc/rc-keytable.c
index 5709ae6..23a66c7 100644
--- a/drivers/media/rc/rc-keytable.c
+++ b/drivers/media/rc/rc-keytable.c
@@ -645,17 +645,10 @@ void rc_keytable_repeat(struct rc_keytable *kt)
unsigned long flags;
 
spin_lock_irqsave(&kt->key_lock, flags);
-
-   input_event(kt->idev, EV_MSC, MSC_SCAN, kt->last_scancode);
-   input_sync(kt->idev);
-
-   if (!kt->key_pressed)
-   goto out;
-
-   kt->keyup_jiffies = jiffies + msecs_to_jiffies(RC_KEYPRESS_TIMEOUT);
-   mod_timer(&kt->timer_keyup, kt->keyup_jiffies);
-
-out:
+   if (kt->key_pressed) {
+   kt->keyup_jiffies = jiffies + 
msecs_to_jiffies(RC_KEYPRESS_TIMEOUT);
+   mod_timer(&kt->timer_keyup, kt->keyup_jiffies);
+   }
spin_unlock_irqrestore(&kt->key_lock, flags);
 }
 
@@ -695,8 +688,6 @@ void rc_keytable_keydown(struct rc_keytable *kt, enum 
rc_type protocol,
if (new_event)
rc_do_keyup(kt, false);
 
-   input_event(kt->idev, EV_MSC, MSC_SCAN, scancode);
-
if (new_event && keycode != KEY_RESERVED) {
/* Register a keypress */
kt->key_pressed = true;
@@ -710,8 +701,8 @@ void rc_keytable_keydown(struct rc_keytable *kt, enum 
rc_type protocol,
   kt->dev->input_name, keycode, protocol,
   (long long unsigned)scancode);
input_report_key(kt->idev, keycode, 1);
+   input_sync(kt->idev);
}
-   input_sync(kt->idev);
 
if (autoup && kt->key_pressed) {
kt->keyup_jiffies = jiffies + 
msecs_to_jiffies(RC_KEYPRESS_TIMEOUT);
@@ -811,8 +802,6 @@ struct rc_keytable *rc_keytable_create(struct rc_dev *dev, 
const char *name,
idev->close = rc_input_close;
set_bit(EV_KEY, idev->evbit);
set_bit(EV_REP, idev->evbit);
-   set_bit(EV_MSC, idev->evbit);
-   set_bit(MSC_SCAN, idev->mscbit);
input_set_drvdata(idev, kt);
setup_timer(&kt->timer_keyup, rc_timer_keyup, (unsigned long)kt);
 

--
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 00/49] rc-core: my current patch queue

2014-04-03 Thread Mauro Carvalho Chehab
Em Fri, 04 Apr 2014 01:31:15 +0200
David Härdeman  escreveu:

> The following patches is what I currenly have in my queue:
> 
> Patches 1 - 6 should be ok to be committed right now, they contain
> some fixes and some reverts (of the NEC32 and generic scancode
> functionality).

I did just a very quick look in this series, so my comments
here are subject to changes.

Patch 4 is obviously OK for 3.15, as it fixes a regression.

With regards to patch 6, yes, if we need to change the API,
it should be sent for 3.15, before becoming too late.
Of course, if we change it, we'll also need to patch the
DocBook and the sysfs ABI descriptions accordingly.
I'll review it carefully latter.

The patches that touch on img-ir (patch 5) can also be applied
during -rc, as this is a new driver. So, no regressions. Of
course, we need James ack on such changes.

It sounds likely too late for the other patches for 3.15
(patches 1, 2 and 3), as they're not so obvious, and
some may require tests on those devices they're supposing
to fix.

> Patches 7 - 9 are in no hurry and can wait for 3.16, some testing
> would be nice even though I believe they are ok.
> 
> Patches 10 and 11 are RFC's for the NEC32 scancode handling.
> 
> The remaining patches are more of an FYI. It's basically the same
> patchset that I've posted a long time ago, but respun to apply to
> the current tree. They implement a modern chardev for rc-core which
> allows the functionality that has so far only been available through
> the LIRC bridge to be exposed to userspace and provide a (hopefully)
> sane API for taking advantage of all the features that rc-core
> provides (RX, TX, ioctl) as well as some new features (multiple
> keymaps is probably the most important one). Lots and lots of cleanups
> as well.

Ok, I'll review the remaining patches after the merge window.

> 
> Enjoy :)

Thanks!
> 
> ---
> 
> David Härdeman (49):
>   bt8xx: fixup RC5 decoding
>   rc-core: improve ir-kbd-i2c get_key functions
>   rc-core: document the protocol type
>   rc-core: do not change 32bit NEC scancode format for now
>   rc-core: split dev->s_filter
>   rc-core: remove generic scancode filter
>   dib0700: NEC scancode cleanup
>   lmedm04: NEC scancode cleanup
>   saa7134: NEC scancode fix
>   [RFC] rc-core: use the full 32 bits for NEC scancodes
>   [RFC] rc-core: don't throw away protocol information
>   rc-core: simplify sysfs code
>   rc-core: remove protocol arrays
>   rc-core: rename dev->scanmask to dev->scancode_mask
>   rc-core: merge rc5 and streamzap decoders
>   rc-core: use an IDA rather than a bitmap
>   rc-core: add chardev
>   rc-core: allow chardev to be read
>   rc-core: use a kfifo for TX data
>   rc-core: allow chardev to be written
>   rc-core: add ioctl support to the rc chardev
>   rc-core: add an ioctl for getting IR RX settings
>   rc-loopback: add RCIOCGIRRX ioctl support
>   rc-core: add an ioctl for setting IR RX settings
>   rc-loopback: add RCIOCSIRRX ioctl support
>   rc-core: add an ioctl for getting IR TX settings
>   rc-loopback: add RCIOCGIRTX ioctl support
>   rc-core: add an ioctl for setting IR TX settings
>   rc-loopback: add RCIOCSIRTX ioctl support
>   rc-core: leave the internals of rc_dev alone
>   rc-core: split rc-main.c into rc-main.c and rc-keytable.c
>   rc-core: prepare for multiple keytables
>   rc-core: make the keytable of rc_dev an array
>   rc-core: add ioctls for adding/removing keytables from userspace
>   rc-core: remove redundant spinlock
>   rc-core: make keytable RCU-friendly
>   rc-core: allow empty keymaps
>   rc-core: rename ir-raw.c
>   rc-core: make IR raw handling a separate module
>   rc-ir-raw: simplify locking
>   rc-core: rename mutex
>   rc-ir-raw: atomic reads of protocols
>   rc-core: fix various sparse warnings
>   rc-core: don't report scancodes via input devices
>   rc-ir-raw: add various rc_events
>   rc-core: use struct rc_event for all rc communication
>   rc-core: add keytable events
>   rc-core: move remaining keytable functions
>   rc-core: make rc-core.h userspace friendly
> 
> 
>  Documentation/ioctl/ioctl-number.txt|1 
>  drivers/hid/hid-picolcd_cir.c   |   20 
>  drivers/media/common/siano/smsir.c  |   14 
>  drivers/media/common/siano/smsir.h  |2 
>  drivers/media/i2c/cx25840/cx25840-ir.c  |   96 +
>  drivers/media/i2c/ir-kbd-i2c.c  |   99 +
>  drivers/media/pci/bt8xx/bttv-input.c|   78 +
>  drivers/media/pci/bt8xx/bttvp.h |2 
>  drivers/media/pci/cx23885/cx23885-input.c   |   26 
>  drivers/media/pci/cx23885/cx23888-ir.c  |   93 +
>  drivers/media/pci/cx88/cx88-input.c |   75 +
>  drivers/media/pci/dm1105/dm1105.c   |4 
>  drivers/media/pci/ivtv/ivtv-i2c.c   |   11 
>  drivers/media/

cron job: media_tree daily build: OK

2014-04-03 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:   Fri Apr  4 04:01:16 CEST 2014
git branch: test
git hash:   a83b93a7480441a47856dc9104bea970e84cda87
gcc version:i686-linux-gcc (GCC) 4.8.2
sparse version: v0.5.0
host hardware:  x86_64
host os:3.13-7.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: OK
linux-git-m32r: OK
linux-git-mips: OK
linux-git-powerpc64: OK
linux-git-sh: OK
linux-git-x86_64: OK
linux-2.6.31.14-i686: OK
linux-2.6.32.27-i686: OK
linux-2.6.33.7-i686: OK
linux-2.6.34.7-i686: OK
linux-2.6.35.9-i686: OK
linux-2.6.36.4-i686: OK
linux-2.6.37.6-i686: OK
linux-2.6.38.8-i686: OK
linux-2.6.39.4-i686: OK
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-i686: OK
linux-3.13-i686: OK
linux-3.14-i686: OK
linux-2.6.31.14-x86_64: OK
linux-2.6.32.27-x86_64: OK
linux-2.6.33.7-x86_64: OK
linux-2.6.34.7-x86_64: OK
linux-2.6.35.9-x86_64: OK
linux-2.6.36.4-x86_64: OK
linux-2.6.37.6-x86_64: OK
linux-2.6.38.8-x86_64: OK
linux-2.6.39.4-x86_64: OK
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-x86_64: OK
linux-3.13-x86_64: OK
linux-3.14-x86_64: OK
apps: OK
spec-git: OK
sparse version: v0.5.0
sparse: ERRORS

Detailed results are available here:

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

Full logs are available here:

http://www.xs4all.nl/~hverkuil/logs/Friday.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


[PATCH v2 0/2] DaVinci: VPIF: upgrade with v4l helpers

2014-04-03 Thread Lad, Prabhakar
From: "Lad, Prabhakar" 

Hi All,

This patch series upgrades the vpif capture & display
driver with the all the helpers provided by v4l, this makes
the driver much simpler and cleaner. This also includes few
checkpatch issues.

Sending them as single patch one for capture and another for
display, splitting them would have caused a huge number small
patches.

Changes for v2:
a> Added a copyright.
b> Dropped buf_init() callback from vb2_ops.
c> Fixed enabling & disabling of interrupts in case of HD formats.


Lad, Prabhakar (2):
  media: davinci: vpif capture: upgrade the driver with v4l offerings
  media: davinci: vpif display: upgrade the driver with v4l offerings

 drivers/media/platform/davinci/vpif_capture.c |  931 +++--
 drivers/media/platform/davinci/vpif_capture.h |   32 +-
 drivers/media/platform/davinci/vpif_display.c |  800 ++---
 drivers/media/platform/davinci/vpif_display.h |   31 +-
 4 files changed, 455 insertions(+), 1339 deletions(-)

-- 
1.7.9.5

--
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 v2 1/2] media: davinci: vpif capture: upgrade the driver with v4l offerings

2014-04-03 Thread Lad, Prabhakar
From: "Lad, Prabhakar" 

This patch upgrades the vpif display driver with
v4l helpers, this patch does the following,

1: initialize the vb2 queue and context at the time of probe
and removes context at remove() callback.
2: uses vb2_ioctl_*() helpers.
3: uses vb2_fop_*() helpers.
4: uses SIMPLE_DEV_PM_OPS.
5: uses vb2_ioctl_*() helpers.
6: vidioc_g/s_priority is now handled by v4l core.
7: removed driver specific fh and now using one provided by v4l.
8: fixes checkpatch warnings.

Signed-off-by: Lad, Prabhakar 
---
 drivers/media/platform/davinci/vpif_capture.c |  931 +++--
 drivers/media/platform/davinci/vpif_capture.h |   32 +-
 2 files changed, 234 insertions(+), 729 deletions(-)

diff --git a/drivers/media/platform/davinci/vpif_capture.c 
b/drivers/media/platform/davinci/vpif_capture.c
index 8dea0b8..e4046f5 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Texas Instruments Inc
+ * Copyright (C) 2014 Lad, Prabhakar 
  *
  * 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
@@ -37,6 +38,8 @@ MODULE_VERSION(VPIF_CAPTURE_VERSION);
 #define vpif_dbg(level, debug, fmt, arg...)\
v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg)
 
+#define VPIF_DRIVER_NAME   "vpif_capture"
+
 static int debug = 1;
 static u32 ch0_numbuffers = 3;
 static u32 ch1_numbuffers = 3;
@@ -65,11 +68,25 @@ static struct vpif_config_params config_params = {
.channel_bufsize[1] = 720 * 576 * 2,
 };
 
+static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = { {1, 1} };
+
 /* global variables */
 static struct vpif_device vpif_obj = { {NULL} };
 static struct device *vpif_dev;
 static void vpif_calculate_offsets(struct channel_obj *ch);
 static void vpif_config_addr(struct channel_obj *ch, int muxmode);
+static int vpif_check_format(struct channel_obj *ch,
+struct v4l2_pix_format *pixfmt, int update);
+
+/*
+ * Is set to 1 in case of SDTV formats, 2 in case of HDTV formats.
+ */
+static int ycmux_mode;
+
+static inline struct vpif_cap_buffer *to_vpif_buffer(struct vb2_buffer *vb)
+{
+   return container_of(vb, struct vpif_cap_buffer, vb);
+}
 
 /**
  * buffer_prepare :  callback function for buffer prepare
@@ -81,10 +98,8 @@ static void vpif_config_addr(struct channel_obj *ch, int 
muxmode);
  */
 static int vpif_buffer_prepare(struct vb2_buffer *vb)
 {
-   /* Get the file handle object and channel object */
-   struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
struct vb2_queue *q = vb->vb2_queue;
-   struct channel_obj *ch = fh->channel;
+   struct channel_obj *ch = vb2_get_drv_priv(q);
struct common_obj *common;
unsigned long addr;
 
@@ -100,7 +115,7 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
goto exit;
addr = vb2_dma_contig_plane_dma_addr(vb, 0);
 
-   if (q->streaming) {
+   if (vb2_is_streaming(q)) {
if (!IS_ALIGNED((addr + common->ytop_off), 8) ||
!IS_ALIGNED((addr + common->ybtm_off), 8) ||
!IS_ALIGNED((addr + common->ctop_off), 8) ||
@@ -131,9 +146,7 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
 {
-   /* Get the file handle object and channel object */
-   struct vpif_fh *fh = vb2_get_drv_priv(vq);
-   struct channel_obj *ch = fh->channel;
+   struct channel_obj *ch = vb2_get_drv_priv(vq);
struct common_obj *common;
unsigned long size;
 
@@ -141,8 +154,7 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq,
 
vpif_dbg(2, debug, "vpif_buffer_setup\n");
 
-   /* If memory type is not mmap, return */
-   if (V4L2_MEMORY_MMAP == common->memory) {
+   if (vq->memory == V4L2_MEMORY_MMAP) {
/* Calculate the size of the buffer */
size = config_params.channel_bufsize[ch->channel_id];
/*
@@ -183,11 +195,8 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq,
  */
 static void vpif_buffer_queue(struct vb2_buffer *vb)
 {
-   /* Get the file handle object and channel object */
-   struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
-   struct channel_obj *ch = fh->channel;
-   struct vpif_cap_buffer *buf = container_of(vb,
-   struct vpif_cap_buffer, vb);
+   struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue);
+   struct vpif_cap_buffer *buf = to_vpif_buffer(vb);
struct common_obj *common;
unsigned long flags;
 
@@ -210,11 +219,8 @@ static void vpif_buffer_queue(struct vb2_buffer *vb)
  */
 static void vpi

[PATCH v2 2/2] media: davinci: vpif display: upgrade the driver with v4l offerings

2014-04-03 Thread Lad, Prabhakar
From: "Lad, Prabhakar" 

This patch upgrades the vpif display driver with
v4l helpers, this patch does the following,

1: initialize the vb2 queue and context at the time of probe
and removes context at remove() callback.
2: uses vb2_ioctl_*() helpers.
3: uses vb2_fop_*() helpers.
4: uses SIMPLE_DEV_PM_OPS.
5: uses vb2_ioctl_*() helpers.
6: vidioc_g/s_priority is now handled by v4l core.
7: removed driver specific fh and now using one provided by v4l.
8: fixes checkpatch warnings.

Signed-off-by: Lad, Prabhakar 
---
 drivers/media/platform/davinci/vpif_display.c |  800 +++--
 drivers/media/platform/davinci/vpif_display.h |   31 +-
 2 files changed, 221 insertions(+), 610 deletions(-)

diff --git a/drivers/media/platform/davinci/vpif_display.c 
b/drivers/media/platform/davinci/vpif_display.c
index aed41ed..f3ae946 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -3,6 +3,7 @@
  * Display driver for TI DaVinci VPIF
  *
  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2014 Lad, Prabhakar 
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -34,6 +35,8 @@ MODULE_VERSION(VPIF_DISPLAY_VERSION);
 #define vpif_dbg(level, debug, fmt, arg...)\
v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg)
 
+#define VPIF_DRIVER_NAME   "vpif_display"
+
 static int debug = 1;
 static u32 ch2_numbuffers = 3;
 static u32 ch3_numbuffers = 3;
@@ -64,9 +67,21 @@ static struct vpif_config_params config_params = {
 
 static struct vpif_device vpif_obj = { {NULL} };
 static struct device *vpif_dev;
+static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} };
+
+/*
+ * Is set to 1 in case of SDTV formats, 2 in case of HDTV formats.
+ */
+static int ycmux_mode;
+
 static void vpif_calculate_offsets(struct channel_obj *ch);
 static void vpif_config_addr(struct channel_obj *ch, int muxmode);
 
+static inline struct vpif_disp_buffer *to_vpif_buffer(struct vb2_buffer *vb)
+{
+   return container_of(vb, struct vpif_disp_buffer, vb);
+}
+
 /*
  * buffer_prepare: This is the callback function called from vb2_qbuf()
  * function the buffer is prepared and user space virtual address is converted
@@ -74,12 +89,12 @@ static void vpif_config_addr(struct channel_obj *ch, int 
muxmode);
  */
 static int vpif_buffer_prepare(struct vb2_buffer *vb)
 {
-   struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
struct vb2_queue *q = vb->vb2_queue;
+   struct channel_obj *ch = vb2_get_drv_priv(q);
struct common_obj *common;
unsigned long addr;
 
-   common = &fh->channel->common[VPIF_VIDEO_INDEX];
+   common = &ch->common[VPIF_VIDEO_INDEX];
if (vb->state != VB2_BUF_STATE_ACTIVE &&
vb->state != VB2_BUF_STATE_PREPARED) {
vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage);
@@ -88,7 +103,7 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
goto buf_align_exit;
 
addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-   if (q->streaming &&
+   if (vb2_is_streaming(q) &&
(V4L2_BUF_TYPE_SLICED_VBI_OUTPUT != q->type)) {
if (!ISALIGNED(addr + common->ytop_off) ||
!ISALIGNED(addr + common->ybtm_off) ||
@@ -112,12 +127,11 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
 {
-   struct vpif_fh *fh = vb2_get_drv_priv(vq);
-   struct channel_obj *ch = fh->channel;
+   struct channel_obj *ch = vb2_get_drv_priv(vq);
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
unsigned long size;
 
-   if (V4L2_MEMORY_MMAP == common->memory) {
+   if (vq->memory == V4L2_MEMORY_MMAP) {
size = config_params.channel_bufsize[ch->channel_id];
/*
* Checking if the buffer size exceeds the available buffer
@@ -154,15 +168,12 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq,
  */
 static void vpif_buffer_queue(struct vb2_buffer *vb)
 {
-   struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
-   struct vpif_disp_buffer *buf = container_of(vb,
-   struct vpif_disp_buffer, vb);
-   struct channel_obj *ch = fh->channel;
+   struct vpif_disp_buffer *buf = to_vpif_buffer(vb);
+   struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue);
struct common_obj *common;
unsigned long flags;
 
common = &ch->common[VPIF_VIDEO_INDEX];
-
/* add the buffer to the DMA queue */
spin_lock_irqsave(&common->irqlock, flags);
list_add_tail(&buf->list, &common->dma_queue);
@@ -175,10 +186,8 @@ static