diff --git a/[refs] b/[refs]
index 77f437d1624b..56e181b7c249 100644
--- a/[refs]
+++ b/[refs]
@@ -1,2 +1,2 @@
---
-refs/heads/master: e317234975cb7463b8ca21a93bb6862d9dcf113f
+refs/heads/master: 6629326b89b6e69cc44276e1649a31158bb2c819
diff --git a/trunk/Documentation/DocBook/media/v4l/biblio.xml b/trunk/Documentation/DocBook/media/v4l/biblio.xml
index 7dc65c592a87..cea6fd3ed428 100644
--- a/trunk/Documentation/DocBook/media/v4l/biblio.xml
+++ b/trunk/Documentation/DocBook/media/v4l/biblio.xml
@@ -128,26 +128,6 @@ url="http://www.ijg.org">http://www.ijg.org)
Version 1.02
-
- ITU-T.81
-
- International Telecommunication Union
-(http://www.itu.int)
-
- ITU-T Recommendation T.81
-"Information Technology — Digital Compression and Coding of Continous-Tone
-Still Images — Requirements and Guidelines"
-
-
-
- W3C JPEG JFIF
-
- The World Wide Web Consortium (http://www.w3.org)
-
- JPEG JFIF
-
-
SMPTE 12M
diff --git a/trunk/Documentation/DocBook/media/v4l/compat.xml b/trunk/Documentation/DocBook/media/v4l/compat.xml
index bce97c50391b..a2485b3ff3d2 100644
--- a/trunk/Documentation/DocBook/media/v4l/compat.xml
+++ b/trunk/Documentation/DocBook/media/v4l/compat.xml
@@ -2393,20 +2393,6 @@ details.
to the User controls class.
-
- Added the device_caps field to struct v4l2_capabilities and added the new
- V4L2_CAP_DEVICE_CAPS capability.
-
-
-
-
-
- V4L2 in Linux 3.4
-
-
- Added JPEG compression control
- class.
-
diff --git a/trunk/Documentation/DocBook/media/v4l/controls.xml b/trunk/Documentation/DocBook/media/v4l/controls.xml
index b84f25e9cc87..a1be37897ad7 100644
--- a/trunk/Documentation/DocBook/media/v4l/controls.xml
+++ b/trunk/Documentation/DocBook/media/v4l/controls.xml
@@ -1284,49 +1284,6 @@ values are:
capturing. This is not done by muting audio hardware, which can still
produce a slight hiss, but in the encoder itself, guaranteeing a fixed
and reproducible audio bitstream. 0 = unmuted, 1 = muted.
-
-
-
- V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK
- enum v4l2_mpeg_audio_dec_playback
- Determines how monolingual audio should be played back.
-Possible values are:
-
-
-
-
-
- V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO
- Automatically determines the best playback mode.
-
-
- V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO
- Stereo playback.
-
-
- V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT
- Left channel playback.
-
-
- V4L2_MPEG_AUDIO_DEC_PLAYBACK_RIGHT
- Right channel playback.
-
-
- V4L2_MPEG_AUDIO_DEC_PLAYBACK_MONO
- Mono playback.
-
-
- V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO
- Stereo playback with swapped left and right channels.
-
-
-
-
-
-
- V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK
- enum v4l2_mpeg_audio_dec_playback
- Determines how multilingual audio should be played back.
@@ -1490,22 +1447,6 @@ of the video. The supplied 32-bit integer is interpreted as follows (bit
-
-
- V4L2_CID_MPEG_VIDEO_DEC_PTS
- integer64
- This read-only control returns the
-33-bit video Presentation Time Stamp as defined in ITU T-REC-H.222.0 and ISO/IEC 13818-1 of
-the currently displayed frame. This is the same PTS as is used in &VIDIOC-DECODER-CMD;.
-
-
-
- V4L2_CID_MPEG_VIDEO_DEC_FRAME
- integer64
- This read-only control returns the
-frame counter of the frame that is currently displayed (decoded). This value is reset to 0 whenever
-the decoder is started.
-
@@ -3436,167 +3377,6 @@ interface and may change in the future.
-
-
-
- JPEG Control Reference
- The JPEG class includes controls for common features of JPEG
- encoders and decoders. Currently it includes features for codecs
- implementing progressive baseline DCT compression process with
- Huffman entrophy coding.
-
- JPEG Control IDs
-
-
-
-
-
-
-
-
-
- ID
- Type
- Description
-
-
-
-
-
- V4L2_CID_JPEG_CLASS
- class
- The JPEG class descriptor. Calling
- &VIDIOC-QUERYCTRL; for this control will return a description of this
- control class.
-
-
-
-
- V4L2_CID_JPEG_CHROMA_SUBSAMPLING
- menu
-
-
- The chroma subsampling factors describe how
- each component of an input image is sampled, in respect to maximum
- sample rate in each spatial dimension. See ,
- clause A.1.1. for more details. The
- V4L2_CID_JPEG_CHROMA_SUBSAMPLING control determines how
- Cb and Cr components are downsampled after coverting an input image
- from RGB to Y'CbCr color space.
-
-
-
-
-
-
- V4L2_JPEG_CHROMA_SUBSAMPLING_444
- No chroma subsampling, each pixel has
- Y, Cr and Cb values.
-
-
- V4L2_JPEG_CHROMA_SUBSAMPLING_422
- Horizontally subsample Cr, Cb components
- by a factor of 2.
-
-
- V4L2_JPEG_CHROMA_SUBSAMPLING_420
- Subsample Cr, Cb components horizontally
- and vertically by 2.
-
-
- V4L2_JPEG_CHROMA_SUBSAMPLING_411
- Horizontally subsample Cr, Cb components
- by a factor of 4.
-
-
- V4L2_JPEG_CHROMA_SUBSAMPLING_410
- Subsample Cr, Cb components horizontally
- by 4 and vertically by 2.
-
-
- V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY
- Use only luminance component.
-
-
-
-
-
- V4L2_CID_JPEG_RESTART_INTERVAL
- integer
-
-
- The restart interval determines an interval of inserting RSTm
- markers (m = 0..7). The purpose of these markers is to additionally
- reinitialize the encoder process, in order to process blocks of
- an image independently.
- For the lossy compression processes the restart interval unit is
- MCU (Minimum Coded Unit) and its value is contained in DRI
- (Define Restart Interval) marker. If
- V4L2_CID_JPEG_RESTART_INTERVAL control is set to 0,
- DRI and RSTm markers will not be inserted.
-
-
-
- V4L2_CID_JPEG_COMPRESION_QUALITY
- integer
-
-
-
- V4L2_CID_JPEG_COMPRESION_QUALITY control
- determines trade-off between image quality and size.
- It provides simpler method for applications to control image quality,
- without a need for direct reconfiguration of luminance and chrominance
- quantization tables.
-
- In cases where a driver uses quantization tables configured directly
- by an application, using interfaces defined elsewhere,
- V4L2_CID_JPEG_COMPRESION_QUALITY control should be set
- by driver to 0.
-
- The value range of this control is driver-specific. Only
- positive, non-zero values are meaningful. The recommended range
- is 1 - 100, where larger values correspond to better image quality.
-
-
-
-
- V4L2_CID_JPEG_ACTIVE_MARKER
- bitmask
-
-
- Specify which JPEG markers are included
- in compressed stream. This control is valid only for encoders.
-
-
-
-
-
-
- V4L2_JPEG_ACTIVE_MARKER_APP0
- Application data segment APP0.
-
- V4L2_JPEG_ACTIVE_MARKER_APP1
- Application data segment APP1.
-
- V4L2_JPEG_ACTIVE_MARKER_COM
- Comment segment.
-
- V4L2_JPEG_ACTIVE_MARKER_DQT
- Quantization tables segment.
-
- V4L2_JPEG_ACTIVE_MARKER_DHT
- Huffman tables segment.
-
-
-
-
-
-
-
-
- For more details about JPEG specification, refer
- to , ,
- .
diff --git a/trunk/Documentation/DocBook/media/v4l/selection-api.xml b/trunk/Documentation/DocBook/media/v4l/selection-api.xml
index b299e4779354..2f0bdb4d5551 100644
--- a/trunk/Documentation/DocBook/media/v4l/selection-api.xml
+++ b/trunk/Documentation/DocBook/media/v4l/selection-api.xml
@@ -52,10 +52,6 @@ cropping and composing rectangles have the same size.
-
-For complete list of the available selection targets see table
-
@@ -190,7 +186,7 @@ V4L2_SEL_TGT_COMPOSE_ACTIVE target.
- Scaling control
+ Scaling control.An application can detect if scaling is performed by comparing the width
and the height of rectangles obtained using V4L2_SEL_TGT_CROP_ACTIVE
@@ -204,7 +200,7 @@ the scaling ratios using these values.
- Comparison with old cropping API
+ Comparison with old cropping API.The selection API was introduced to cope with deficiencies of previous
API , that was designed to control simple capture
diff --git a/trunk/Documentation/DocBook/media/v4l/v4l2.xml b/trunk/Documentation/DocBook/media/v4l/v4l2.xml
index 8ae38876172e..e97c512861bb 100644
--- a/trunk/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/trunk/Documentation/DocBook/media/v4l/v4l2.xml
@@ -127,22 +127,6 @@ structs, ioctls) must be noted in more detail in the history chapter
(compat.xml), along with the possible impact on existing drivers and
applications. -->
-
- 3.4
- 2012-01-25
- sn
- Added JPEG compression
- control class.
-
-
-
-
- 3.3
- 2012-01-11
- hv
- Added device_caps field to struct v4l2_capabilities.
-
-
3.22011-08-26
@@ -433,7 +417,7 @@ and discussions on the V4L mailing list.
Video for Linux Two API Specification
- Revision 3.3
+ Revision 3.2
&sub-common;
@@ -489,7 +473,6 @@ and discussions on the V4L mailing list.
&sub-cropcap;
&sub-dbg-g-chip-ident;
&sub-dbg-g-register;
- &sub-decoder-cmd;
&sub-dqevent;
&sub-encoder-cmd;
&sub-enumaudio;
diff --git a/trunk/Documentation/DocBook/media/v4l/vidioc-decoder-cmd.xml b/trunk/Documentation/DocBook/media/v4l/vidioc-decoder-cmd.xml
deleted file mode 100644
index 74b87f6e480a..000000000000
--- a/trunk/Documentation/DocBook/media/v4l/vidioc-decoder-cmd.xml
+++ /dev/null
@@ -1,256 +0,0 @@
-
-
- ioctl VIDIOC_DECODER_CMD, VIDIOC_TRY_DECODER_CMD
- &manvol;
-
-
-
- VIDIOC_DECODER_CMD
- VIDIOC_TRY_DECODER_CMD
- Execute an decoder command
-
-
-
-
-
- int ioctl
- int fd
- int request
- struct v4l2_decoder_cmd *argp
-
-
-
-
-
- Arguments
-
-
-
- fd
-
- &fd;
-
-
-
- request
-
- VIDIOC_DECODER_CMD, VIDIOC_TRY_DECODER_CMD
-
-
-
- argp
-
-
-
-
-
-
-
-
- Description
-
-
- Experimental
-
- This is an experimental
-interface and may change in the future.
-
-
- These ioctls control an audio/video (usually MPEG-) decoder.
-VIDIOC_DECODER_CMD sends a command to the
-decoder, VIDIOC_TRY_DECODER_CMD can be used to
-try a command without actually executing it. To send a command applications
-must initialize all fields of a &v4l2-decoder-cmd; and call
-VIDIOC_DECODER_CMD or VIDIOC_TRY_DECODER_CMD
-with a pointer to this structure.
-
- The cmd field must contain the
-command code. Some commands use the flags field for
-additional information.
-
-
- A write() or &VIDIOC-STREAMON; call sends an implicit
-START command to the decoder if it has not been started yet.
-
-
- A close() or &VIDIOC-STREAMOFF; call of a streaming
-file descriptor sends an implicit immediate STOP command to the decoder, and all
-buffered data is discarded.
-
- These ioctls are optional, not all drivers may support
-them. They were introduced in Linux 3.3.
-
-
- struct v4l2_decoder_cmd
-
- &cs-str;
-
-
- __u32
- cmd
-
-
- The decoder command, see .
-
-
- __u32
- flags
-
-
- Flags to go with the command. If no flags are defined for
-this command, drivers and applications must set this field to zero.
-
-
- union
- (anonymous)
-
-
-
-
-
-
- struct
- start
-
- Structure containing additional data for the
-V4L2_DEC_CMD_START command.
-
-
-
-
- __s32
- speed
- Playback speed and direction. The playback speed is defined as
-speed/1000 of the normal speed. So 1000 is normal playback.
-Negative numbers denote reverse playback, so -1000 does reverse playback at normal
-speed. Speeds -1, 0 and 1 have special meanings: speed 0 is shorthand for 1000
-(normal playback). A speed of 1 steps just one frame forward, a speed of -1 steps
-just one frame back.
-
-
-
-
-
- __u32
- format
- Format restrictions. This field is set by the driver, not the
-application. Possible values are V4L2_DEC_START_FMT_NONE if
-there are no format restrictions or V4L2_DEC_START_FMT_GOP
-if the decoder operates on full GOPs (Group Of Pictures).
-This is usually the case for reverse playback: the decoder needs full GOPs, which
-it can then play in reverse order. So to implement reverse playback the application
-must feed the decoder the last GOP in the video file, then the GOP before that, etc. etc.
-
-
-
-
- struct
- stop
-
- Structure containing additional data for the
-V4L2_DEC_CMD_STOP command.
-
-
-
-
- __u64
- pts
- Stop playback at this pts or immediately
-if the playback is already past that timestamp. Leave to 0 if you want to stop after the
-last frame was decoded.
-
-
-
-
- struct
- raw
-
-
-
-
-
-
- __u32
- data[16]
- Reserved for future extensions. Drivers and
-applications must set the array to zero.
-
-
-
-
-
-
- Decoder Commands
-
- &cs-def;
-
-
- V4L2_DEC_CMD_START
- 0
- Start the decoder. When the decoder is already
-running or paused, this command will just change the playback speed.
-That means that calling V4L2_DEC_CMD_START when
-the decoder was paused will not resume the decoder.
-You have to explicitly call V4L2_DEC_CMD_RESUME for that.
-This command has one flag:
-V4L2_DEC_CMD_START_MUTE_AUDIO. If set, then audio will
-be muted when playing back at a non-standard speed.
-
-
-
- V4L2_DEC_CMD_STOP
- 1
- Stop the decoder. When the decoder is already stopped,
-this command does nothing. This command has two flags:
-if V4L2_DEC_CMD_STOP_TO_BLACK is set, then the decoder will
-set the picture to black after it stopped decoding. Otherwise the last image will
-repeat. If V4L2_DEC_CMD_STOP_IMMEDIATELY is set, then the decoder
-stops immediately (ignoring the pts value), otherwise it
-will keep decoding until timestamp >= pts or until the last of the pending data from
-its internal buffers was decoded.
-
-
-
- V4L2_DEC_CMD_PAUSE
- 2
- Pause the decoder. When the decoder has not been
-started yet, the driver will return an &EPERM;. When the decoder is
-already paused, this command does nothing. This command has one flag:
-if V4L2_DEC_CMD_PAUSE_TO_BLACK is set, then set the
-decoder output to black when paused.
-
-
-
- V4L2_DEC_CMD_RESUME
- 3
- Resume decoding after a PAUSE command. When the
-decoder has not been started yet, the driver will return an &EPERM;.
-When the decoder is already running, this command does nothing. No
-flags are defined for this command.
-
-
-
-
-
-
-
-
- &return-value;
-
-
-
- EINVAL
-
- The cmd field is invalid.
-
-
-
- EPERM
-
- The application sent a PAUSE or RESUME command when
-the decoder was not running.
-
-
-
-
-
diff --git a/trunk/Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml b/trunk/Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml
index f431b3ba79bd..af7f3f2a36dd 100644
--- a/trunk/Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml
+++ b/trunk/Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml
@@ -74,16 +74,15 @@ only used by the STOP command and contains one bit: If the
encoding will continue until the end of the current Group
Of Pictures, otherwise it will stop immediately.
- A read() or &VIDIOC-STREAMON; call sends an implicit
-START command to the encoder if it has not been started yet. After a STOP command,
+ A read() call sends a START command to
+the encoder if it has not been started yet. After a STOP command,
read() calls will read the remaining data
buffered by the driver. When the buffer is empty,
read() will return zero and the next
read() call will restart the encoder.
- A close() or &VIDIOC-STREAMOFF; call of a streaming
-file descriptor sends an implicit immediate STOP to the encoder, and all buffered
-data is discarded.
+ A close() call sends an immediate STOP
+to the encoder, and all buffered data is discarded.These ioctls are optional, not all drivers may support
them. They were introduced in Linux 2.6.21.
diff --git a/trunk/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml b/trunk/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml
index 48748499c097..01ea24b84385 100644
--- a/trunk/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml
+++ b/trunk/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml
@@ -57,11 +57,6 @@
Description
- These ioctls are deprecated.
- New drivers and applications should use
- JPEG class controls for image quality and JPEG markers control.
-
-
[to do]Ronald Bultje elaborates:
@@ -91,10 +86,7 @@ to add them.intquality
- Deprecated. If
- V4L2_CID_JPEG_IMAGE_QUALITY control is exposed by
- a driver applications should use it instead and ignore this field.
-
+ int
@@ -124,11 +116,7 @@ to add them.
__u32jpeg_markers
- See . Deprecated.
- If
- V4L2_CID_JPEG_ACTIVE_MARKER control
- is exposed by a driver applications should use it instead
- and ignore this field.
+ See .
diff --git a/trunk/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/trunk/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
index bb04eff75f45..a9d36e0c090e 100644
--- a/trunk/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
+++ b/trunk/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
@@ -58,43 +58,43 @@
The ioctls are used to query and configure selection rectangles.
- To query the cropping (composing) rectangle set &v4l2-selection;
- type field to the respective buffer type.
-Do not use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE
+ To query the cropping (composing) rectangle set
+&v4l2-selection;::type to the respective buffer type. Do not
+use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE
instead of V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
. Use V4L2_BUF_TYPE_VIDEO_OUTPUT instead of
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE . The next step is
-setting the value of &v4l2-selection; target field
-to V4L2_SEL_TGT_CROP_ACTIVE (
+setting &v4l2-selection;::target to value
+ V4L2_SEL_TGT_CROP_ACTIVE (
V4L2_SEL_TGT_COMPOSE_ACTIVE ). Please refer to table or for additional
-targets. The flags and reserved
- fields of &v4l2-selection; are ignored and they must be filled
-with zeros. The driver fills the rest of the structure or
+targets. Fields &v4l2-selection;::flags and
+ &v4l2-selection;::reserved are ignored and they
+must be filled with zeros. The driver fills the rest of the structure or
returns &EINVAL; if incorrect buffer type or target was used. If cropping
(composing) is not supported then the active rectangle is not mutable and it is
-always equal to the bounds rectangle. Finally, the &v4l2-rect;
-r rectangle is filled with the current cropping
+always equal to the bounds rectangle. Finally, structure
+&v4l2-selection;::r is filled with the current cropping
(composing) coordinates. The coordinates are expressed in driver-dependent
units. The only exception are rectangles for images in raw formats, whose
coordinates are always expressed in pixels.
- To change the cropping (composing) rectangle set the &v4l2-selection;
-type field to the respective buffer type. Do not
+ To change the cropping (composing) rectangle set
+&v4l2-selection;::type to the respective buffer type. Do not
use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE
instead of V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
. Use V4L2_BUF_TYPE_VIDEO_OUTPUT instead of
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE . The next step is
-setting the value of &v4l2-selection; target to
-V4L2_SEL_TGT_CROP_ACTIVE (
+setting &v4l2-selection;::target to value
+ V4L2_SEL_TGT_CROP_ACTIVE (
V4L2_SEL_TGT_COMPOSE_ACTIVE ). Please refer to table or for additional
-targets. The &v4l2-rect; r rectangle need to be
-set to the desired active area. Field &v4l2-selection; reserved
- is ignored and must be filled with zeros. The driver may adjust
-coordinates of the requested rectangle. An application may
-introduce constraints to control rounding behaviour. The &v4l2-selection;
-flags field must be set to one of the following:
+targets. Set desired active area into the field
+&v4l2-selection;::r . Field
+&v4l2-selection;::reserved is ignored and must be filled with
+zeros. The driver may adjust the rectangle coordinates. An application may
+introduce constraints to control rounding behaviour. Set the field
+ &v4l2-selection;::flags to one of values:
@@ -129,7 +129,7 @@ and vertical offset and sizes are chosen according to following priority:
- Satisfy constraints from &v4l2-selection; flags.
+ Satisfy constraints from &v4l2-selection;::flags.Adjust width, height, left, and top to hardware limits and alignments.
@@ -145,7 +145,7 @@ and vertical offset and sizes are chosen according to following priority:
-On success the &v4l2-rect; r field contains
+On success the field &v4l2-selection;::r contains
the adjusted rectangle. When the parameters are unsuitable the application may
modify the cropping (composing) or image parameters and repeat the cycle until
satisfactory parameters have been negotiated. If constraints flags have to be
@@ -162,38 +162,38 @@ exist no rectangle that satisfies the constraints.V4L2_SEL_TGT_CROP_ACTIVE
- 0x0000
- The area that is currently cropped by hardware.
+ 0
+ area that is currently cropped by hardwareV4L2_SEL_TGT_CROP_DEFAULT
- 0x0001
- Suggested cropping rectangle that covers the "whole picture".
+ 1
+ suggested cropping rectangle that covers the "whole picture"V4L2_SEL_TGT_CROP_BOUNDS
- 0x0002
- Limits for the cropping rectangle.
+ 2
+ limits for the cropping rectangleV4L2_SEL_TGT_COMPOSE_ACTIVE
- 0x0100
- The area to which data is composed by hardware.
+ 256
+ area to which data are composed by hardwareV4L2_SEL_TGT_COMPOSE_DEFAULT
- 0x0101
- Suggested composing rectangle that covers the "whole picture".
+ 257
+ suggested composing rectangle that covers the "whole picture"V4L2_SEL_TGT_COMPOSE_BOUNDS
- 0x0102
- Limits for the composing rectangle.
+ 258
+ limits for the composing rectangleV4L2_SEL_TGT_COMPOSE_PADDED
- 0x0103
- The active area and all padding pixels that are inserted or modified by hardware.
+ 259
+ the active area and all padding pixels that are inserted or modified by the hardware
@@ -209,14 +209,12 @@ exist no rectangle that satisfies the constraints.V4L2_SEL_FLAG_GE0x00000001
- Indicates that the adjusted rectangle must contain the original
- &v4l2-selection; r rectangle.
+ indicate that adjusted rectangle must contain a rectangle from &v4l2-selection;::rV4L2_SEL_FLAG_LE0x00000002
- Indicates that the adjusted rectangle must be inside the original
- &v4l2-rect; r rectangle.
+ indicate that adjusted rectangle must be inside a rectangle from &v4l2-selection;::r
@@ -247,29 +245,27 @@ exist no rectangle that satisfies the constraints.__u32type
- Type of the buffer (from &v4l2-buf-type;).
+ Type of the buffer (from &v4l2-buf-type;)__u32target
- Used to select between cropping
- and composing rectangles.
+ used to select between cropping and composing rectangles __u32flags
- Flags controlling the selection rectangle adjustments, refer to
- selection flags.
+ control over coordinates adjustments, refer to selection flags&v4l2-rect;r
- The selection rectangle.
+ selection rectangle__u32reserved[9]
- Reserved fields for future use.
+ Reserved fields for future use
@@ -282,24 +278,24 @@ exist no rectangle that satisfies the constraints.
EINVAL
- Given buffer type type or
-the selection target target is not supported,
-or the flags argument is not valid.
+ The buffer &v4l2-selection;::type
+or &v4l2-selection;::target is not supported, or
+the &v4l2-selection;::flags are invalid.ERANGE
- It is not possible to adjust &v4l2-rect;
-r rectangle to satisfy all contraints given in the
-flags argument.
+ it is not possible to adjust a rectangle
+&v4l2-selection;::r that satisfies all contraints from
+ &v4l2-selection;::flags .EBUSY
- It is not possible to apply change of the selection rectangle
-at the moment. Usually because streaming is in progress.
+ it is not possible to apply change of selection rectangle at the moment.
+Usually because streaming is in progress.
diff --git a/trunk/Documentation/DocBook/media/v4l/vidioc-querycap.xml b/trunk/Documentation/DocBook/media/v4l/vidioc-querycap.xml
index 4643505cd4ca..e3664d6f2de4 100644
--- a/trunk/Documentation/DocBook/media/v4l/vidioc-querycap.xml
+++ b/trunk/Documentation/DocBook/media/v4l/vidioc-querycap.xml
@@ -124,35 +124,12 @@ printf ("Version: %u.%u.%u\n",
__u32capabilities
- Available capabilities of the physical device as a whole, see . The same physical device can export
- multiple devices in /dev (e.g. /dev/videoX, /dev/vbiY and /dev/radioZ).
- The capabilities field should contain a union
- of all capabilities available around the several V4L2 devices exported
- to userspace.
- For all those devices the capabilities field
- returns the same set of capabilities. This allows applications to open
- just one of the devices (typically the video device) and discover whether
- video, vbi and/or radio are also supported.
-
+ Device capabilities, see .__u32
- device_caps
- Device capabilities of the opened device, see . Should contain the available capabilities
- of that specific device node. So, for example, device_caps
- of a radio device will only contain radio related capabilities and
- no video or vbi capabilities. This field is only set if the capabilities
- field contains the V4L2_CAP_DEVICE_CAPS capability.
- Only the capabilities field can have the
- V4L2_CAP_DEVICE_CAPS capability, device_caps
- will never set V4L2_CAP_DEVICE_CAPS.
-
-
-
- __u32
- reserved[3]
+ reserved[4]Reserved for future extensions. Drivers must set
this array to zero.
@@ -299,13 +276,6 @@ linkend="async">asynchronous I/O methods.
The device supports the streaming I/O method.
-
- V4L2_CAP_DEVICE_CAPS
- 0x80000000
- The driver fills the device_caps
- field. This capability can only appear in the capabilities
- field and never in the device_caps field.
-
diff --git a/trunk/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml b/trunk/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml
index 18b1a8266f7c..e013da845b11 100644
--- a/trunk/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml
+++ b/trunk/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml
@@ -96,8 +96,8 @@ field and the &v4l2-tuner; index field.
__u32reserved[7]
- Reserved for future extensions. Applications
- must set the array to zero.
+ Reserved for future extensions. Drivers and
+ applications must set the array to zero.
@@ -112,7 +112,7 @@ field and the &v4l2-tuner; index field.
EINVALThe tuner index is out of
-bounds, the wrap_around value is not supported or the value in the type field is
+bounds or the value in the type field is
wrong.
diff --git a/trunk/Documentation/devicetree/bindings/i2c/sirf-i2c.txt b/trunk/Documentation/devicetree/bindings/i2c/sirf-i2c.txt
deleted file mode 100644
index 7baf9e133fa8..000000000000
--- a/trunk/Documentation/devicetree/bindings/i2c/sirf-i2c.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-I2C for SiRFprimaII platforms
-
-Required properties :
-- compatible : Must be "sirf,prima2-i2c"
-- reg: physical base address of the controller and length of memory mapped
- region.
-- interrupts: interrupt number to the cpu.
-
-Optional properties:
-- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
- The absence of the propoerty indicates the default frequency 100 kHz.
-
-Examples :
-
-i2c0: i2c@b00e0000 {
- compatible = "sirf,prima2-i2c";
- reg = <0xb00e0000 0x10000>;
- interrupts = <24>;
-};
diff --git a/trunk/Documentation/dvb/cards.txt b/trunk/Documentation/dvb/cards.txt
index 97709e9a3076..cc09187a5db7 100644
--- a/trunk/Documentation/dvb/cards.txt
+++ b/trunk/Documentation/dvb/cards.txt
@@ -119,5 +119,4 @@ o Cards based on the Phillips saa7134 PCI bridge:
- Compro Videomate DVB-T300
- Compro Videomate DVB-T200
- AVerMedia AVerTVHD MCE A180
- - KWorld PC150-U ATSC Hybrid
diff --git a/trunk/Documentation/dvb/lmedm04.txt b/trunk/Documentation/dvb/lmedm04.txt
index f4b720a14675..10b5f0411386 100644
--- a/trunk/Documentation/dvb/lmedm04.txt
+++ b/trunk/Documentation/dvb/lmedm04.txt
@@ -66,16 +66,5 @@ dd if=US290D.sys ibs=1 skip=36856 count=3976 of=dvb-usb-lme2510-s0194.fw
For LME2510C
dd if=US290D.sys ibs=1 skip=33152 count=3697 of=dvb-usb-lme2510c-s0194.fw
----------------------------------------------------------------------
-
-The m88rs2000 tuner driver can be found in windows/system32/drivers
-
-US2B0D.sys (dated 29 Jun 2010)
-
-dd if=US2B0D.sys ibs=1 skip=34432 count=3871 of=dvb-usb-lme2510c-rs2000.fw
-
-We need to modify id of rs2000 firmware or it will warm boot id 3344:1120.
-
-echo -ne \\xF0\\x22 | dd conv=notrunc bs=1 count=2 seek=266 of=dvb-usb-lme2510c-rs2000.fw
Copy the firmware file(s) to /lib/firmware
diff --git a/trunk/Documentation/hwmon/lm90 b/trunk/Documentation/hwmon/lm90
index b466974e142f..9cd14cfe6515 100644
--- a/trunk/Documentation/hwmon/lm90
+++ b/trunk/Documentation/hwmon/lm90
@@ -118,10 +118,6 @@ Supported chips:
Addresses scanned: I2C 0x48 through 0x4F
Datasheet: Publicly available at NXP website
http://ics.nxp.com/products/interface/datasheet/sa56004x.pdf
- * GMT G781
- Prefix: 'g781'
- Addresses scanned: I2C 0x4c, 0x4d
- Datasheet: Not publicly available from GMT
Author: Jean Delvare
diff --git a/trunk/Documentation/hwmon/mc13783-adc b/trunk/Documentation/hwmon/mc13783-adc
index d0e7b3fa9e75..044531a86405 100644
--- a/trunk/Documentation/hwmon/mc13783-adc
+++ b/trunk/Documentation/hwmon/mc13783-adc
@@ -3,11 +3,8 @@ Kernel driver mc13783-adc
Supported chips:
* Freescale Atlas MC13783
- Prefix: 'mc13783'
+ Prefix: 'mc13783_adc'
Datasheet: http://www.freescale.com/files/rf_if/doc/data_sheet/MC13783.pdf?fsrch=1
- * Freescale Atlas MC13892
- Prefix: 'mc13892'
- Datasheet: http://cache.freescale.com/files/analog/doc/data_sheet/MC13892.pdf?fsrch=1&sr=1
Authors:
Sascha Hauer
@@ -16,21 +13,20 @@ Authors:
Description
-----------
-The Freescale MC13783 and MC13892 are Power Management and Audio Circuits.
-Among other things they contain a 10-bit A/D converter. The converter has 16
-(MC13783) resp. 12 (MC13892) channels which can be used in different modes. The
-A/D converter has a resolution of 2.25mV.
+The Freescale MC13783 is a Power Management and Audio Circuit. Among
+other things it contains a 10-bit A/D converter. The converter has 16
+channels which can be used in different modes.
+The A/D converter has a resolution of 2.25mV. Channels 0-4 have
+a dedicated meaning with chip internal scaling applied. Channels 5-7
+can be used as general purpose inputs or alternatively in a dedicated
+mode. Channels 12-15 are occupied by the touchscreen if it's active.
-Some channels can be used as General Purpose inputs or in a dedicated mode with
-a chip internal scaling applied .
+Currently the driver only supports channels 2 and 5-15 with no alternative
+modes for channels 5-7.
-Currently the driver only supports the Application Supply channel (BP / BPSNS),
-the General Purpose inputs and touchscreen.
+See this table for the meaning of the different channels and their chip
+internal scaling:
-See the following tables for the meaning of the different channels and their
-chip internal scaling:
-
-MC13783:
Channel Signal Input Range Scaling
-------------------------------------------------------------------------------
0 Battery Voltage (BATT) 2.50 - 4.65V -2.40V
@@ -38,7 +34,7 @@ Channel Signal Input Range Scaling
2 Application Supply (BP) 2.50 - 4.65V -2.40V
3 Charger Voltage (CHRGRAW) 0 - 10V / /5
0 - 20V /10
-4 Charger Current (CHRGISNSP-CHRGISNSN) -0.25 - 0.25V x4
+4 Charger Current (CHRGISNSP-CHRGISNSN) -0.25V - 0.25V x4
5 General Purpose ADIN5 / Battery Pack Thermistor 0 - 2.30V No
6 General Purpose ADIN6 / Backup Voltage (LICELL) 0 - 2.30V / No /
1.50 - 3.50V -1.20V
@@ -52,23 +48,3 @@ Channel Signal Input Range Scaling
13 General Purpose TSX2 / Touchscreen X-plate 2 0 - 2.30V No
14 General Purpose TSY1 / Touchscreen Y-plate 1 0 - 2.30V No
15 General Purpose TSY2 / Touchscreen Y-plate 2 0 - 2.30V No
-
-MC13892:
-Channel Signal Input Range Scaling
--------------------------------------------------------------------------------
-0 Battery Voltage (BATT) 0 - 4.8V /2
-1 Battery Current (BATT - BATTISNSCC) -60 - 60 mV x20
-2 Application Supply (BPSNS) 0 - 4.8V /2
-3 Charger Voltage (CHRGRAW) 0 - 12V / /5
- 0 - 20V /10
-4 Charger Current (CHRGISNS-BPSNS) / -0.3 - 0.3V / x4 /
- Touchscreen X-plate 1 0 - 2.4V No
-5 General Purpose ADIN5 / Battery Pack Thermistor 0 - 2.4V No
-6 General Purpose ADIN6 / Backup Voltage (LICELL) 0 - 2.4V / No
- Backup Voltage (LICELL) 0 - 3.6V x2/3
-7 General Purpose ADIN7 / UID / Die Temperature 0 - 2.4V / No /
- 0 - 4.8V /2
-12 General Purpose TSX1 / Touchscreen X-plate 1 0 - 2.4V No
-13 General Purpose TSX2 / Touchscreen X-plate 2 0 - 2.4V No
-14 General Purpose TSY1 / Touchscreen Y-plate 1 0 - 2.4V No
-15 General Purpose TSY2 / Touchscreen Y-plate 2 0 - 2.4V No
diff --git a/trunk/Documentation/hwmon/mcp3021 b/trunk/Documentation/hwmon/mcp3021
deleted file mode 100644
index 325fd87e81b2..000000000000
--- a/trunk/Documentation/hwmon/mcp3021
+++ /dev/null
@@ -1,22 +0,0 @@
-Kernel driver MCP3021
-======================
-
-Supported chips:
- * Microchip Technology MCP3021
- Prefix: 'mcp3021'
- Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21805a.pdf
-
-Author: Mingkai Hu
-
-Description
------------
-
-This driver implements support for the Microchip Technology MCP3021 chip.
-
-The Microchip Technology Inc. MCP3021 is a successive approximation A/D
-converter (ADC) with 10-bit resolution.
-This device provides one single-ended input with very low power consumption.
-Communication to the MCP3021 is performed using a 2-wire I2C compatible
-interface. Standard (100 kHz) and Fast (400 kHz) I2C modes are available.
-The default I2C device address is 0x4d (contact the Microchip factory for
-additional address options).
diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt
index 1c9a348548dc..7c33ef8a1ba9 100644
--- a/trunk/Documentation/kernel-parameters.txt
+++ b/trunk/Documentation/kernel-parameters.txt
@@ -2147,14 +2147,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
the default.
off: Turn ECRC off
on: Turn ECRC on.
- realloc= Enable/disable reallocating PCI bridge resources
- if allocations done by BIOS are too small to
- accommodate resources required by all child
- devices.
- off: Turn realloc off
- on: Turn realloc on
- realloc same as realloc=on
- noari do not use PCIe ARI.
+ realloc reallocate PCI resources if allocations done by BIOS
+ are erroneous.
pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power
Management.
@@ -2162,10 +2156,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
force Enable ASPM even on devices that claim not to support it.
WARNING: Forcing ASPM on may cause system lockups.
- pcie_hp= [PCIE] PCI Express Hotplug driver options:
- nomsi Do not use MSI for PCI Express Native Hotplug (this
- makes all PCIe ports use INTx for hotplug services).
-
pcie_ports= [PCIE] PCIe ports handling:
auto Ask the BIOS whether or not to use native PCIe services
associated with PCIe ports (PME, hot-plug, AER). Use
diff --git a/trunk/Documentation/video4linux/CARDLIST.cx23885 b/trunk/Documentation/video4linux/CARDLIST.cx23885
index f316d1816fcd..23584d0c6a75 100644
--- a/trunk/Documentation/video4linux/CARDLIST.cx23885
+++ b/trunk/Documentation/video4linux/CARDLIST.cx23885
@@ -32,4 +32,3 @@
31 -> Leadtek Winfast PxDVR3200 H XC4000 [107d:6f39]
32 -> MPX-885
33 -> Mygica X8507 [14f1:8502]
- 34 -> TerraTec Cinergy T PCIe Dual [153b:117e]
diff --git a/trunk/Documentation/video4linux/CARDLIST.cx88 b/trunk/Documentation/video4linux/CARDLIST.cx88
index fa4b3f947468..eee18e6962b6 100644
--- a/trunk/Documentation/video4linux/CARDLIST.cx88
+++ b/trunk/Documentation/video4linux/CARDLIST.cx88
@@ -59,7 +59,7 @@
58 -> Pinnacle PCTV HD 800i [11bd:0051]
59 -> DViCO FusionHDTV 5 PCI nano [18ac:d530]
60 -> Pinnacle Hybrid PCTV [12ab:1788]
- 61 -> Leadtek TV2000 XP Global [107d:6f18,107d:6618,107d:6619]
+ 61 -> Leadtek TV2000 XP Global [107d:6f18,107d:6618]
62 -> PowerColor RA330 [14f1:ea3d]
63 -> Geniatech X8000-MT DVBT [14f1:8852]
64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30]
@@ -87,5 +87,3 @@
86 -> TeVii S464 DVB-S/S2 [d464:9022]
87 -> Leadtek WinFast DTV2000 H PLUS [107d:6f42]
88 -> Leadtek WinFast DTV1800 H (XC4000) [107d:6f38]
- 89 -> Leadtek TV2000 XP Global (SC4100) [107d:6f36]
- 90 -> Leadtek TV2000 XP Global (XC4100) [107d:6f43]
diff --git a/trunk/Documentation/video4linux/CARDLIST.em28xx b/trunk/Documentation/video4linux/CARDLIST.em28xx
index d99262dda533..e7be3ac49ead 100644
--- a/trunk/Documentation/video4linux/CARDLIST.em28xx
+++ b/trunk/Documentation/video4linux/CARDLIST.em28xx
@@ -7,7 +7,7 @@
6 -> Terratec Cinergy 200 USB (em2800)
7 -> Leadtek Winfast USB II (em2800) [0413:6023]
8 -> Kworld USB2800 (em2800)
- 9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,1b80:e304,2304:0207,2304:021a,093b:a003]
+ 9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,1b80:e304,2304:0207,2304:021a]
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
11 -> Terratec Hybrid XS (em2880)
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
@@ -61,7 +61,7 @@
61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840)
62 -> Gadmei TVR200 (em2820/em2840)
63 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303]
- 64 -> Easy Cap Capture DC-60 (em2860) [1b80:e309]
+ 64 -> Easy Cap Capture DC-60 (em2860)
65 -> IO-DATA GV-MVP/SZ (em2820/em2840) [04bb:0515]
66 -> Empire dual TV (em2880)
67 -> Terratec Grabby (em2860) [0ccd:0096,0ccd:10AF]
@@ -76,11 +76,7 @@
76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340]
77 -> EM2874 Leadership ISDBT (em2874)
78 -> PCTV nanoStick T2 290e (em28174)
- 79 -> Terratec Cinergy H5 (em2884) [0ccd:008e,0ccd:00ac,0ccd:10a2,0ccd:10ad]
+ 79 -> Terratec Cinergy H5 (em2884) [0ccd:10a2,0ccd:10ad]
80 -> PCTV DVB-S2 Stick (460e) (em28174)
81 -> Hauppauge WinTV HVR 930C (em2884) [2040:1605]
82 -> Terratec Cinergy HTC Stick (em2884) [0ccd:00b2]
- 83 -> Honestech Vidbox NW03 (em2860) [eb1a:5006]
- 84 -> MaxMedia UB425-TC (em2874) [1b80:e425]
- 85 -> PCTV QuatroStick (510e) (em2884) [2304:0242]
- 86 -> PCTV QuatroStick nano (520e) (em2884) [2013:0251]
diff --git a/trunk/Documentation/video4linux/CARDLIST.saa7134 b/trunk/Documentation/video4linux/CARDLIST.saa7134
index 34f3b330e5f4..e7ef38a19859 100644
--- a/trunk/Documentation/video4linux/CARDLIST.saa7134
+++ b/trunk/Documentation/video4linux/CARDLIST.saa7134
@@ -187,4 +187,3 @@
186 -> Beholder BeholdTV 501 [5ace:5010]
187 -> Beholder BeholdTV 503 FM [5ace:5030]
188 -> Sensoray 811/911 [6000:0811,6000:0911]
-189 -> Kworld PC150-U [17de:a134]
diff --git a/trunk/Documentation/video4linux/CARDLIST.tuner b/trunk/Documentation/video4linux/CARDLIST.tuner
index c83f6e418879..6323b7a20719 100644
--- a/trunk/Documentation/video4linux/CARDLIST.tuner
+++ b/trunk/Documentation/video4linux/CARDLIST.tuner
@@ -78,11 +78,10 @@ tuner=77 - TCL tuner MF02GIP-5N-E
tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner
tuner=79 - Philips PAL/SECAM multi (FM1216 MK5)
tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
+tuner=81 - Xceive 4000 tuner
tuner=81 - Partsnic (Daewoo) PTI-5NF05
tuner=82 - Philips CU1216L
tuner=83 - NXP TDA18271
tuner=84 - Sony BTF-Pxn01Z
tuner=85 - Philips FQ1236 MK5
tuner=86 - Tena TNF5337 MFD
-tuner=87 - Xceive 4000 tuner
-tuner=88 - Xceive 5000C tuner
diff --git a/trunk/Documentation/video4linux/fimc.txt b/trunk/Documentation/video4linux/fimc.txt
deleted file mode 100644
index eb049708f3e4..000000000000
--- a/trunk/Documentation/video4linux/fimc.txt
+++ /dev/null
@@ -1,178 +0,0 @@
-Samsung S5P/EXYNOS4 FIMC driver
-
-Copyright (C) 2012 Samsung Electronics Co., Ltd.
----------------------------------------------------------------------------
-
-The FIMC (Fully Interactive Mobile Camera) device available in Samsung
-SoC Application Processors is an integrated camera host interface, color
-space converter, image resizer and rotator. It's also capable of capturing
-data from LCD controller (FIMD) through the SoC internal writeback data
-path. There are multiple FIMC instances in the SoCs (up to 4), having
-slightly different capabilities, like pixel alignment constraints, rotator
-availability, LCD writeback support, etc. The driver is located at
-drivers/media/video/s5p-fimc directory.
-
-1. Supported SoCs
-=================
-
-S5PC100 (mem-to-mem only), S5PV210, EXYNOS4210
-
-2. Supported features
-=====================
-
- - camera parallel interface capture (ITU-R.BT601/565);
- - camera serial interface capture (MIPI-CSI2);
- - memory-to-memory processing (color space conversion, scaling, mirror
- and rotation);
- - dynamic pipeline re-configuration at runtime (re-attachment of any FIMC
- instance to any parallel video input or any MIPI-CSI front-end);
- - runtime PM and system wide suspend/resume
-
-Not currently supported:
- - LCD writeback input
- - per frame clock gating (mem-to-mem)
-
-3. Files partitioning
-=====================
-
-- media device driver
- drivers/media/video/s5p-fimc/fimc-mdevice.[ch]
-
- - camera capture video device driver
- drivers/media/video/s5p-fimc/fimc-capture.c
-
- - MIPI-CSI2 receiver subdev
- drivers/media/video/s5p-fimc/mipi-csis.[ch]
-
- - video post-processor (mem-to-mem)
- drivers/media/video/s5p-fimc/fimc-core.c
-
- - common files
- drivers/media/video/s5p-fimc/fimc-core.h
- drivers/media/video/s5p-fimc/fimc-reg.h
- drivers/media/video/s5p-fimc/regs-fimc.h
-
-4. User space interfaces
-========================
-
-4.1. Media device interface
-
-The driver supports Media Controller API as defined at
-http://http://linuxtv.org/downloads/v4l-dvb-apis/media_common.html
-The media device driver name is "SAMSUNG S5P FIMC".
-
-The purpose of this interface is to allow changing assignment of FIMC instances
-to the SoC peripheral camera input at runtime and optionally to control internal
-connections of the MIPI-CSIS device(s) to the FIMC entities.
-
-The media device interface allows to configure the SoC for capturing image
-data from the sensor through more than one FIMC instance (e.g. for simultaneous
-viewfinder and still capture setup).
-Reconfiguration is done by enabling/disabling media links created by the driver
-during initialization. The internal device topology can be easily discovered
-through media entity and links enumeration.
-
-4.2. Memory-to-memory video node
-
-V4L2 memory-to-memory interface at /dev/video? device node. This is standalone
-video device, it has no media pads. However please note the mem-to-mem and
-capture video node operation on same FIMC instance is not allowed. The driver
-detects such cases but the applications should prevent them to avoid an
-undefined behaviour.
-
-4.3. Capture video node
-
-The driver supports V4L2 Video Capture Interface as defined at:
-http://linuxtv.org/downloads/v4l-dvb-apis/devices.html
-
-At the capture and mem-to-mem video nodes only the multi-planar API is
-supported. For more details see:
-http://linuxtv.org/downloads/v4l-dvb-apis/planar-apis.html
-
-4.4. Camera capture subdevs
-
-Each FIMC instance exports a sub-device node (/dev/v4l-subdev?), a sub-device
-node is also created per each available and enabled at the platform level
-MIPI-CSI receiver device (currently up to two).
-
-4.5. sysfs
-
-In order to enable more precise camera pipeline control through the sub-device
-API the driver creates a sysfs entry associated with "s5p-fimc-md" platform
-device. The entry path is: /sys/platform/devices/s5p-fimc-md/subdev_conf_mode.
-
-In typical use case there could be a following capture pipeline configuration:
-sensor subdev -> mipi-csi subdev -> fimc subdev -> video node
-
-When we configure these devices through sub-device API at user space, the
-configuration flow must be from left to right, and the video node is
-configured as last one.
-When we don't use sub-device user space API the whole configuration of all
-devices belonging to the pipeline is done at the video node driver.
-The sysfs entry allows to instruct the capture node driver not to configure
-the sub-devices (format, crop), to avoid resetting the subdevs' configuration
-when the last configuration steps at the video node is performed.
-
-For full sub-device control support (subdevs configured at user space before
-starting streaming):
-# echo "sub-dev" > /sys/platform/devices/s5p-fimc-md/subdev_conf_mode
-
-For V4L2 video node control only (subdevs configured internally by the host
-driver):
-# echo "vid-dev" > /sys/platform/devices/s5p-fimc-md/subdev_conf_mode
-This is a default option.
-
-5. Device mapping to video and subdev device nodes
-==================================================
-
-There are associated two video device nodes with each device instance in
-hardware - video capture and mem-to-mem and additionally a subdev node for
-more precise FIMC capture subsystem control. In addition a separate v4l2
-sub-device node is created per each MIPI-CSIS device.
-
-How to find out which /dev/video? or /dev/v4l-subdev? is assigned to which
-device?
-
-You can either grep through the kernel log to find relevant information, i.e.
-# dmesg | grep -i fimc
-(note that udev, if present, might still have rearranged the video nodes),
-
-or retrieve the information from /dev/media? with help of the media-ctl tool:
-# media-ctl -p
-
-6. Platform support
-===================
-
-The machine code (plat-s5p and arch/arm/mach-*) must select following options
-
-CONFIG_S5P_DEV_FIMC0 mandatory
-CONFIG_S5P_DEV_FIMC1 \
-CONFIG_S5P_DEV_FIMC2 | optional
-CONFIG_S5P_DEV_FIMC3 |
-CONFIG_S5P_SETUP_FIMC /
-CONFIG_S5P_SETUP_MIPIPHY \
-CONFIG_S5P_DEV_CSIS0 | optional for MIPI-CSI interface
-CONFIG_S5P_DEV_CSIS1 /
-
-Except that, relevant s5p_device_fimc? should be registered in the machine code
-in addition to a "s5p-fimc-md" platform device to which the media device driver
-is bound. The "s5p-fimc-md" device instance is required even if only mem-to-mem
-operation is used.
-
-The description of sensor(s) attached to FIMC/MIPI-CSIS camera inputs should be
-passed as the "s5p-fimc-md" device platform_data. The platform data structure
-is defined in file include/media/s5p_fimc.h.
-
-7. Build
-========
-
-This driver depends on following config options:
-PLAT_S5P,
-PM_RUNTIME,
-I2C,
-REGULATOR,
-VIDEO_V4L2_SUBDEV_API,
-
-If the driver is built as a loadable kernel module (CONFIG_VIDEO_SAMSUNG_S5P_FIMC=m)
-two modules are created (in addition to the core v4l2 modules): s5p-fimc.ko and
-optional s5p-csis.ko (MIPI-CSI receiver subdev).
diff --git a/trunk/Documentation/video4linux/gspca.txt b/trunk/Documentation/video4linux/gspca.txt
index e6c2842407a4..f2060f0dc02c 100644
--- a/trunk/Documentation/video4linux/gspca.txt
+++ b/trunk/Documentation/video4linux/gspca.txt
@@ -217,7 +217,6 @@ ov534_9 06f8:3003 Hercules Dualpix HD Weblog
sonixj 06f8:3004 Hercules Classic Silver
sonixj 06f8:3008 Hercules Deluxe Optical Glass
pac7302 06f8:3009 Hercules Classic Link
-pac7302 06f8:301b Hercules Link
nw80x 0728:d001 AVerMedia Camguard
spca508 0733:0110 ViewQuest VQ110
spca501 0733:0401 Intel Create and Share
diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS
index ec9bcb17c572..95eba3135018 100644
--- a/trunk/MAINTAINERS
+++ b/trunk/MAINTAINERS
@@ -503,7 +503,7 @@ F: arch/x86/include/asm/geode.h
AMD IOMMU (AMD-VI)
M: Joerg Roedel
L: iommu@lists.linux-foundation.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git
S: Supported
F: drivers/iommu/amd_iommu*.[ch]
F: include/linux/amd-iommu.h
@@ -5120,7 +5120,7 @@ F: Documentation/PCI/pci-error-recovery.txt
F: Documentation/powerpc/eeh-pci-error-recovery.txt
PCI SUBSYSTEM
-M: Bjorn Helgaas
+M: Jesse Barnes
L: linux-pci@vger.kernel.org
Q: http://patchwork.kernel.org/project/linux-pci/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
@@ -5130,7 +5130,7 @@ F: drivers/pci/
F: include/linux/pci*
PCI HOTPLUG
-M: Bjorn Helgaas
+M: Jesse Barnes
L: linux-pci@vger.kernel.org
S: Supported
F: drivers/pci/hotplug
diff --git a/trunk/arch/alpha/include/asm/pci.h b/trunk/arch/alpha/include/asm/pci.h
index d01afb78919c..28d0497fd3c7 100644
--- a/trunk/arch/alpha/include/asm/pci.h
+++ b/trunk/arch/alpha/include/asm/pci.h
@@ -7,7 +7,6 @@
#include
#include
#include
-#include
/*
* The following structure is used to manage multiple PCI busses.
@@ -100,6 +99,12 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
return channel ? 15 : 14;
}
+extern void pcibios_resource_to_bus(struct pci_dev *, struct pci_bus_region *,
+ struct resource *);
+
+extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region);
+
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
static inline int pci_proc_domain(struct pci_bus *bus)
diff --git a/trunk/arch/alpha/kernel/pci.c b/trunk/arch/alpha/kernel/pci.c
index 1a629636cc16..8c723c1b086a 100644
--- a/trunk/arch/alpha/kernel/pci.c
+++ b/trunk/arch/alpha/kernel/pci.c
@@ -43,10 +43,12 @@ const char *const pci_mem_names[] = {
const char pci_hae0_name[] = "HAE0";
+/* Indicate whether we respect the PCI setup left by console. */
/*
- * If PCI_PROBE_ONLY in pci_flags is set, we don't change any PCI resource
- * assignments.
+ * Make this long-lived so that we know when shutting down
+ * whether we probed only or not.
*/
+int pci_probe_only;
/*
* The PCI controller list.
@@ -213,7 +215,7 @@ pdev_save_srm_config(struct pci_dev *dev)
struct pdev_srm_saved_conf *tmp;
static int printed = 0;
- if (!alpha_using_srm || pci_has_flag(PCI_PROBE_ONLY))
+ if (!alpha_using_srm || pci_probe_only)
return;
if (!printed) {
@@ -240,7 +242,7 @@ pci_restore_srm_config(void)
struct pdev_srm_saved_conf *tmp;
/* No need to restore if probed only. */
- if (pci_has_flag(PCI_PROBE_ONLY))
+ if (pci_probe_only)
return;
/* Restore SRM config. */
@@ -250,18 +252,47 @@ pci_restore_srm_config(void)
}
#endif
+void __devinit
+pcibios_fixup_resource(struct resource *res, struct resource *root)
+{
+ res->start += root->start;
+ res->end += root->start;
+}
+
+void __devinit
+pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
+{
+ /* Update device resources. */
+ struct pci_controller *hose = (struct pci_controller *)bus->sysdata;
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ if (!dev->resource[i].start)
+ continue;
+ if (dev->resource[i].flags & IORESOURCE_IO)
+ pcibios_fixup_resource(&dev->resource[i],
+ hose->io_space);
+ else if (dev->resource[i].flags & IORESOURCE_MEM)
+ pcibios_fixup_resource(&dev->resource[i],
+ hose->mem_space);
+ }
+}
+
void __devinit
pcibios_fixup_bus(struct pci_bus *bus)
{
struct pci_dev *dev = bus->self;
- if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
+ if (pci_probe_only && dev &&
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
pci_read_bridge_bases(bus);
+ pcibios_fixup_device_resources(dev, bus);
}
list_for_each_entry(dev, &bus->devices, bus_list) {
pdev_save_srm_config(dev);
+ if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ pcibios_fixup_device_resources(dev, bus);
}
}
@@ -271,6 +302,42 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
+void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_space->start;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_space->start;
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_space->start;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_space->start;
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
+}
+
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+#endif
+
int
pcibios_enable_device(struct pci_dev *dev, int mask)
{
@@ -307,8 +374,7 @@ pcibios_claim_one_bus(struct pci_bus *b)
if (r->parent || !r->start || !r->flags)
continue;
- if (pci_has_flag(PCI_PROBE_ONLY) ||
- (r->flags & IORESOURCE_PCI_FIXED))
+ if (pci_probe_only || (r->flags & IORESOURCE_PCI_FIXED))
pci_claim_resource(dev, i);
}
}
@@ -350,10 +416,8 @@ common_init_pci(void)
hose->mem_space->end = end;
INIT_LIST_HEAD(&resources);
- pci_add_resource_offset(&resources, hose->io_space,
- hose->io_space->start);
- pci_add_resource_offset(&resources, hose->mem_space,
- hose->mem_space->start);
+ pci_add_resource(&resources, hose->io_space);
+ pci_add_resource(&resources, hose->mem_space);
bus = pci_scan_root_bus(NULL, next_busno, alpha_mv.pci_ops,
hose, &resources);
diff --git a/trunk/arch/alpha/kernel/pci_impl.h b/trunk/arch/alpha/kernel/pci_impl.h
index 2b0ac429f5eb..85457b2d4516 100644
--- a/trunk/arch/alpha/kernel/pci_impl.h
+++ b/trunk/arch/alpha/kernel/pci_impl.h
@@ -173,6 +173,9 @@ extern void pci_restore_srm_config(void);
extern struct pci_controller *hose_head, **hose_tail;
extern struct pci_controller *pci_isa_hose;
+/* Indicate that we trust the console to configure things properly. */
+extern int pci_probe_only;
+
extern unsigned long alpha_agpgart_size;
extern void common_init_pci(void);
diff --git a/trunk/arch/alpha/kernel/sys_marvel.c b/trunk/arch/alpha/kernel/sys_marvel.c
index fc8b12508611..95cfc83ece8f 100644
--- a/trunk/arch/alpha/kernel/sys_marvel.c
+++ b/trunk/arch/alpha/kernel/sys_marvel.c
@@ -384,8 +384,7 @@ marvel_init_pci(void)
marvel_register_error_handlers();
- /* Indicate that we trust the console to configure things properly */
- pci_set_flags(PCI_PROBE_ONLY);
+ pci_probe_only = 1;
common_init_pci();
locate_and_init_vga(NULL);
diff --git a/trunk/arch/alpha/kernel/sys_titan.c b/trunk/arch/alpha/kernel/sys_titan.c
index b8eafa053539..f47b30a2a117 100644
--- a/trunk/arch/alpha/kernel/sys_titan.c
+++ b/trunk/arch/alpha/kernel/sys_titan.c
@@ -331,8 +331,7 @@ titan_init_pci(void)
*/
titan_late_init();
- /* Indicate that we trust the console to configure things properly */
- pci_set_flags(PCI_PROBE_ONLY);
+ pci_probe_only = 1;
common_init_pci();
SMC669_Init(0);
locate_and_init_vga(NULL);
diff --git a/trunk/arch/arm/common/it8152.c b/trunk/arch/arm/common/it8152.c
index dcb13494ca0d..fb1f1cfce60c 100644
--- a/trunk/arch/arm/common/it8152.c
+++ b/trunk/arch/arm/common/it8152.c
@@ -299,8 +299,8 @@ int __init it8152_pci_setup(int nr, struct pci_sys_data *sys)
goto err1;
}
- pci_add_resource_offset(&sys->resources, &it8152_io, sys->io_offset);
- pci_add_resource_offset(&sys->resources, &it8152_mem, sys->mem_offset);
+ pci_add_resource(&sys->resources, &it8152_io);
+ pci_add_resource(&sys->resources, &it8152_mem);
if (platform_notify || platform_notify_remove) {
printk(KERN_ERR "PCI: Can't use platform_notify\n");
diff --git a/trunk/arch/arm/include/asm/pci.h b/trunk/arch/arm/include/asm/pci.h
index a98a2e112fae..da337ba57ffd 100644
--- a/trunk/arch/arm/include/asm/pci.h
+++ b/trunk/arch/arm/include/asm/pci.h
@@ -57,6 +57,14 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res);
+
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region);
+
/*
* Dummy implementation; always return 0.
*/
diff --git a/trunk/arch/arm/kernel/bios32.c b/trunk/arch/arm/kernel/bios32.c
index 632df9a66f8c..f58ba3589908 100644
--- a/trunk/arch/arm/kernel/bios32.c
+++ b/trunk/arch/arm/kernel/bios32.c
@@ -16,6 +16,7 @@
#include
static int debug_pci;
+static int use_firmware;
/*
* We can't use pci_find_device() here since we are
@@ -293,6 +294,28 @@ static inline int pdev_bad_for_parity(struct pci_dev *dev)
}
+/*
+ * Adjust the device resources from bus-centric to Linux-centric.
+ */
+static void __devinit
+pdev_fixup_device_resources(struct pci_sys_data *root, struct pci_dev *dev)
+{
+ resource_size_t offset;
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ if (dev->resource[i].start == 0)
+ continue;
+ if (dev->resource[i].flags & IORESOURCE_MEM)
+ offset = root->mem_offset;
+ else
+ offset = root->io_offset;
+
+ dev->resource[i].start += offset;
+ dev->resource[i].end += offset;
+ }
+}
+
/*
* pcibios_fixup_bus - Called after each bus is probed,
* but before its children are examined.
@@ -310,6 +333,8 @@ void pcibios_fixup_bus(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) {
u16 status;
+ pdev_fixup_device_resources(root, dev);
+
pci_read_config_word(dev, PCI_STATUS, &status);
/*
@@ -374,6 +399,43 @@ void pcibios_fixup_bus(struct pci_bus *bus)
EXPORT_SYMBOL(pcibios_fixup_bus);
#endif
+/*
+ * Convert from Linux-centric to bus-centric addresses for bridge devices.
+ */
+void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_sys_data *root = dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = root->io_offset;
+ if (res->flags & IORESOURCE_MEM)
+ offset = root->mem_offset;
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+void __devinit
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_sys_data *root = dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = root->io_offset;
+ if (res->flags & IORESOURCE_MEM)
+ offset = root->mem_offset;
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
/*
* Swizzle the device pin each time we cross a bridge.
* This might update pin and returns the slot number.
@@ -435,10 +497,10 @@ static void __init pcibios_init_hw(struct hw_pci *hw)
if (ret > 0) {
if (list_empty(&sys->resources)) {
- pci_add_resource_offset(&sys->resources,
- &ioport_resource, sys->io_offset);
- pci_add_resource_offset(&sys->resources,
- &iomem_resource, sys->mem_offset);
+ pci_add_resource(&sys->resources,
+ &ioport_resource);
+ pci_add_resource(&sys->resources,
+ &iomem_resource);
}
sys->bus = hw->scan(nr, sys);
@@ -463,7 +525,6 @@ void __init pci_common_init(struct hw_pci *hw)
INIT_LIST_HEAD(&hw->buses);
- pci_add_flags(PCI_REASSIGN_ALL_RSRC);
if (hw->preinit)
hw->preinit();
pcibios_init_hw(hw);
@@ -475,7 +536,7 @@ void __init pci_common_init(struct hw_pci *hw)
list_for_each_entry(sys, &hw->buses, node) {
struct pci_bus *bus = sys->bus;
- if (!pci_has_flag(PCI_PROBE_ONLY)) {
+ if (!use_firmware) {
/*
* Size the bridge windows.
*/
@@ -512,7 +573,7 @@ char * __init pcibios_setup(char *str)
debug_pci = 1;
return NULL;
} else if (!strcmp(str, "firmware")) {
- pci_add_flags(PCI_PROBE_ONLY);
+ use_firmware = 1;
return NULL;
}
return str;
diff --git a/trunk/arch/arm/mach-cns3xxx/pcie.c b/trunk/arch/arm/mach-cns3xxx/pcie.c
index 79d001f831e0..e159d69967c9 100644
--- a/trunk/arch/arm/mach-cns3xxx/pcie.c
+++ b/trunk/arch/arm/mach-cns3xxx/pcie.c
@@ -155,8 +155,8 @@ static int cns3xxx_pci_setup(int nr, struct pci_sys_data *sys)
BUG_ON(request_resource(&iomem_resource, res_io) ||
request_resource(&iomem_resource, res_mem));
- pci_add_resource_offset(&sys->resources, res_io, sys->io_offset);
- pci_add_resource_offset(&sys->resources, res_mem, sys->mem_offset);
+ pci_add_resource(&sys->resources, res_io);
+ pci_add_resource(&sys->resources, res_mem);
return 1;
}
diff --git a/trunk/arch/arm/mach-dove/pcie.c b/trunk/arch/arm/mach-dove/pcie.c
index 48a032005ea3..52e96d397ba8 100644
--- a/trunk/arch/arm/mach-dove/pcie.c
+++ b/trunk/arch/arm/mach-dove/pcie.c
@@ -69,7 +69,7 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[0].flags = IORESOURCE_IO;
if (request_resource(&ioport_resource, &pp->res[0]))
panic("Request PCIe IO resource failed\n");
- pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
+ pci_add_resource(&sys->resources, &pp->res[0]);
/*
* IORESOURCE_MEM
@@ -88,7 +88,7 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[1].flags = IORESOURCE_MEM;
if (request_resource(&iomem_resource, &pp->res[1]))
panic("Request PCIe Memory resource failed\n");
- pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
+ pci_add_resource(&sys->resources, &pp->res[1]);
return 1;
}
diff --git a/trunk/arch/arm/mach-footbridge/dc21285.c b/trunk/arch/arm/mach-footbridge/dc21285.c
index 3194d3f73503..f685650c25d7 100644
--- a/trunk/arch/arm/mach-footbridge/dc21285.c
+++ b/trunk/arch/arm/mach-footbridge/dc21285.c
@@ -275,13 +275,11 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
allocate_resource(&iomem_resource, &res[0], 0x40000000,
0x80000000, 0xffffffff, 0x40000000, NULL, NULL);
+ pci_add_resource(&sys->resources, &ioport_resource);
+ pci_add_resource(&sys->resources, &res[0]);
+ pci_add_resource(&sys->resources, &res[1]);
sys->mem_offset = DC21285_PCI_MEM;
- pci_add_resource_offset(&sys->resources,
- &ioport_resource, sys->io_offset);
- pci_add_resource_offset(&sys->resources, &res[0], sys->mem_offset);
- pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
-
return 1;
}
diff --git a/trunk/arch/arm/mach-imx/clock-imx27.c b/trunk/arch/arm/mach-imx/clock-imx27.c
index dc2d7a511d9b..88fe00a146e3 100644
--- a/trunk/arch/arm/mach-imx/clock-imx27.c
+++ b/trunk/arch/arm/mach-imx/clock-imx27.c
@@ -661,7 +661,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "dma", dma_clk)
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
_REGISTER_CLOCK(NULL, "brom", brom_clk)
- _REGISTER_CLOCK("m2m-emmaprp.0", NULL, emma_clk)
+ _REGISTER_CLOCK(NULL, "emma", emma_clk)
_REGISTER_CLOCK(NULL, "slcdc", slcdc_clk)
_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
_REGISTER_CLOCK(NULL, "emi", emi_clk)
diff --git a/trunk/arch/arm/mach-imx/devices-imx27.h b/trunk/arch/arm/mach-imx/devices-imx27.h
index 28537a5d9048..2f727d7c380c 100644
--- a/trunk/arch/arm/mach-imx/devices-imx27.h
+++ b/trunk/arch/arm/mach-imx/devices-imx27.h
@@ -50,8 +50,6 @@ extern const struct imx_imx_uart_1irq_data imx27_imx_uart_data[];
extern const struct imx_mx2_camera_data imx27_mx2_camera_data;
#define imx27_add_mx2_camera(pdata) \
imx_add_mx2_camera(&imx27_mx2_camera_data, pdata)
-#define imx27_add_mx2_emmaprp(pdata) \
- imx_add_mx2_emmaprp(&imx27_mx2_camera_data)
extern const struct imx_mxc_ehci_data imx27_mxc_ehci_otg_data;
#define imx27_add_mxc_ehci_otg(pdata) \
diff --git a/trunk/arch/arm/mach-integrator/pci_v3.c b/trunk/arch/arm/mach-integrator/pci_v3.c
index 015be770c1d8..3c82566acece 100644
--- a/trunk/arch/arm/mach-integrator/pci_v3.c
+++ b/trunk/arch/arm/mach-integrator/pci_v3.c
@@ -378,10 +378,9 @@ static int __init pci_v3_setup_resources(struct pci_sys_data *sys)
* the mem resource for this bus
* the prefetch mem resource for this bus
*/
- pci_add_resource_offset(&sys->resources,
- &ioport_resource, sys->io_offset);
- pci_add_resource_offset(&sys->resources, &non_mem, sys->mem_offset);
- pci_add_resource_offset(&sys->resources, &pre_mem, sys->mem_offset);
+ pci_add_resource(&sys->resources, &ioport_resource);
+ pci_add_resource(&sys->resources, &non_mem);
+ pci_add_resource(&sys->resources, &pre_mem);
return 1;
}
diff --git a/trunk/arch/arm/mach-iop13xx/pci.c b/trunk/arch/arm/mach-iop13xx/pci.c
index 861cb12ef436..b8f5a8736511 100644
--- a/trunk/arch/arm/mach-iop13xx/pci.c
+++ b/trunk/arch/arm/mach-iop13xx/pci.c
@@ -1084,8 +1084,8 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
request_resource(&ioport_resource, &res[0]);
request_resource(&iomem_resource, &res[1]);
- pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
- pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+ pci_add_resource(&sys->resources, &res[0]);
+ pci_add_resource(&sys->resources, &res[1]);
return 1;
}
diff --git a/trunk/arch/arm/mach-ixp2000/ixdp2400.c b/trunk/arch/arm/mach-ixp2000/ixdp2400.c
index d519944653ad..f53e911ec94a 100644
--- a/trunk/arch/arm/mach-ixp2000/ixdp2400.c
+++ b/trunk/arch/arm/mach-ixp2000/ixdp2400.c
@@ -134,11 +134,11 @@ static void ixdp2400_pci_postinit(void)
if (ixdp2x00_master_npu()) {
dev = pci_get_bus_and_slot(1, IXDP2400_SLAVE_ENET_DEVFN);
- pci_stop_and_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
pci_dev_put(dev);
} else {
dev = pci_get_bus_and_slot(1, IXDP2400_MASTER_ENET_DEVFN);
- pci_stop_and_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
pci_dev_put(dev);
ixdp2x00_slave_pci_postinit();
diff --git a/trunk/arch/arm/mach-ixp2000/ixdp2800.c b/trunk/arch/arm/mach-ixp2000/ixdp2800.c
index b415febd2025..a2e7c393e74f 100644
--- a/trunk/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/trunk/arch/arm/mach-ixp2000/ixdp2800.c
@@ -262,14 +262,14 @@ int __init ixdp2800_pci_init(void)
pci_common_init(&ixdp2800_pci);
if (ixdp2x00_master_npu()) {
dev = pci_get_bus_and_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
- pci_stop_and_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
pci_dev_put(dev);
ixdp2800_master_enable_slave();
ixdp2800_master_wait_for_slave_bus_scan();
} else {
dev = pci_get_bus_and_slot(1, IXDP2800_MASTER_ENET_DEVFN);
- pci_stop_and_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
pci_dev_put(dev);
}
}
diff --git a/trunk/arch/arm/mach-ixp2000/ixdp2x00.c b/trunk/arch/arm/mach-ixp2000/ixdp2x00.c
index dd9838299068..634b6c852f68 100644
--- a/trunk/arch/arm/mach-ixp2000/ixdp2x00.c
+++ b/trunk/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -239,12 +239,12 @@ void ixdp2x00_slave_pci_postinit(void)
* Remove PMC device is there is one
*/
if((dev = pci_get_bus_and_slot(1, IXDP2X00_PMC_DEVFN))) {
- pci_stop_and_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
pci_dev_put(dev);
}
dev = pci_get_bus_and_slot(0, IXDP2X00_21555_DEVFN);
- pci_stop_and_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
pci_dev_put(dev);
}
diff --git a/trunk/arch/arm/mach-ixp2000/pci.c b/trunk/arch/arm/mach-ixp2000/pci.c
index 49c36f3cd602..626fda435aa9 100644
--- a/trunk/arch/arm/mach-ixp2000/pci.c
+++ b/trunk/arch/arm/mach-ixp2000/pci.c
@@ -243,10 +243,8 @@ int ixp2000_pci_setup(int nr, struct pci_sys_data *sys)
if (nr >= 1)
return 0;
- pci_add_resource_offset(&sys->resources,
- &ixp2000_pci_io_space, sys->io_offset);
- pci_add_resource_offset(&sys->resources,
- &ixp2000_pci_mem_space, sys->mem_offset);
+ pci_add_resource(&sys->resources, &ixp2000_pci_io_space);
+ pci_add_resource(&sys->resources, &ixp2000_pci_mem_space);
return 1;
}
diff --git a/trunk/arch/arm/mach-ixp23xx/pci.c b/trunk/arch/arm/mach-ixp23xx/pci.c
index 3cbbd3208fa8..25b5c462cea2 100644
--- a/trunk/arch/arm/mach-ixp23xx/pci.c
+++ b/trunk/arch/arm/mach-ixp23xx/pci.c
@@ -281,10 +281,8 @@ int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
if (nr >= 1)
return 0;
- pci_add_resource_offset(&sys->resources,
- &ixp23xx_pci_io_space, sys->io_offset);
- pci_add_resource_offset(&sys->resources,
- &ixp23xx_pci_mem_space, sys->mem_offset);
+ pci_add_resource(&sys->resources, &ixp23xx_pci_io_space);
+ pci_add_resource(&sys->resources, &ixp23xx_pci_mem_space);
return 1;
}
diff --git a/trunk/arch/arm/mach-ixp4xx/common-pci.c b/trunk/arch/arm/mach-ixp4xx/common-pci.c
index 8508882b13f0..5eff15f24bc2 100644
--- a/trunk/arch/arm/mach-ixp4xx/common-pci.c
+++ b/trunk/arch/arm/mach-ixp4xx/common-pci.c
@@ -472,8 +472,8 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys)
request_resource(&ioport_resource, &res[0]);
request_resource(&iomem_resource, &res[1]);
- pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
- pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+ pci_add_resource(&sys->resources, &res[0]);
+ pci_add_resource(&sys->resources, &res[1]);
platform_notify = ixp4xx_pci_platform_notify;
platform_notify_remove = ixp4xx_pci_platform_notify_remove;
diff --git a/trunk/arch/arm/mach-kirkwood/pcie.c b/trunk/arch/arm/mach-kirkwood/pcie.c
index f56a0118c1bb..a066a6d8d9d2 100644
--- a/trunk/arch/arm/mach-kirkwood/pcie.c
+++ b/trunk/arch/arm/mach-kirkwood/pcie.c
@@ -198,9 +198,9 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
if (request_resource(&iomem_resource, &pp->res[1]))
panic("Request PCIe%d Memory resource failed\n", index);
+ pci_add_resource(&sys->resources, &pp->res[0]);
+ pci_add_resource(&sys->resources, &pp->res[1]);
sys->io_offset = 0;
- pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
- pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
/*
* Generic PCIe unit setup.
diff --git a/trunk/arch/arm/mach-ks8695/pci.c b/trunk/arch/arm/mach-ks8695/pci.c
index acc701435817..b26f992071df 100644
--- a/trunk/arch/arm/mach-ks8695/pci.c
+++ b/trunk/arch/arm/mach-ks8695/pci.c
@@ -169,8 +169,8 @@ static int __init ks8695_pci_setup(int nr, struct pci_sys_data *sys)
request_resource(&iomem_resource, &pci_mem);
request_resource(&ioport_resource, &pci_io);
- pci_add_resource_offset(&sys->resources, &pci_io, sys->io_offset);
- pci_add_resource_offset(&sys->resources, &pci_mem, sys->mem_offset);
+ pci_add_resource(&sys->resources, &pci_io);
+ pci_add_resource(&sys->resources, &pci_mem);
/* Assign and enable processor bridge */
ks8695_local_writeconfig(PCI_BASE_ADDRESS_0, KS8695_PCIMEM_PA);
diff --git a/trunk/arch/arm/mach-mv78xx0/pcie.c b/trunk/arch/arm/mach-mv78xx0/pcie.c
index df3e38055a24..8459f6d7d8ca 100644
--- a/trunk/arch/arm/mach-mv78xx0/pcie.c
+++ b/trunk/arch/arm/mach-mv78xx0/pcie.c
@@ -155,8 +155,8 @@ static int __init mv78xx0_pcie_setup(int nr, struct pci_sys_data *sys)
orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
orion_pcie_setup(pp->base);
- pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
- pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
+ pci_add_resource(&sys->resources, &pp->res[0]);
+ pci_add_resource(&sys->resources, &pp->res[1]);
return 1;
}
diff --git a/trunk/arch/arm/mach-orion5x/pci.c b/trunk/arch/arm/mach-orion5x/pci.c
index d6a91948e4dc..09a045f0c406 100644
--- a/trunk/arch/arm/mach-orion5x/pci.c
+++ b/trunk/arch/arm/mach-orion5x/pci.c
@@ -171,14 +171,13 @@ static int __init pcie_setup(struct pci_sys_data *sys)
/*
* IORESOURCE_IO
*/
- sys->io_offset = 0;
res[0].name = "PCIe I/O Space";
res[0].flags = IORESOURCE_IO;
res[0].start = ORION5X_PCIE_IO_BUS_BASE;
res[0].end = res[0].start + ORION5X_PCIE_IO_SIZE - 1;
if (request_resource(&ioport_resource, &res[0]))
panic("Request PCIe IO resource failed\n");
- pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
+ pci_add_resource(&sys->resources, &res[0]);
/*
* IORESOURCE_MEM
@@ -189,7 +188,9 @@ static int __init pcie_setup(struct pci_sys_data *sys)
res[1].end = res[1].start + ORION5X_PCIE_MEM_SIZE - 1;
if (request_resource(&iomem_resource, &res[1]))
panic("Request PCIe Memory resource failed\n");
- pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+ pci_add_resource(&sys->resources, &res[1]);
+
+ sys->io_offset = 0;
return 1;
}
@@ -498,14 +499,13 @@ static int __init pci_setup(struct pci_sys_data *sys)
/*
* IORESOURCE_IO
*/
- sys->io_offset = 0;
res[0].name = "PCI I/O Space";
res[0].flags = IORESOURCE_IO;
res[0].start = ORION5X_PCI_IO_BUS_BASE;
res[0].end = res[0].start + ORION5X_PCI_IO_SIZE - 1;
if (request_resource(&ioport_resource, &res[0]))
panic("Request PCI IO resource failed\n");
- pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
+ pci_add_resource(&sys->resources, &res[0]);
/*
* IORESOURCE_MEM
@@ -516,7 +516,9 @@ static int __init pci_setup(struct pci_sys_data *sys)
res[1].end = res[1].start + ORION5X_PCI_MEM_SIZE - 1;
if (request_resource(&iomem_resource, &res[1]))
panic("Request PCI Memory resource failed\n");
- pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+ pci_add_resource(&sys->resources, &res[1]);
+
+ sys->io_offset = 0;
return 1;
}
diff --git a/trunk/arch/arm/mach-sa1100/pci-nanoengine.c b/trunk/arch/arm/mach-sa1100/pci-nanoengine.c
index b466bca9c651..0d01ca788922 100644
--- a/trunk/arch/arm/mach-sa1100/pci-nanoengine.c
+++ b/trunk/arch/arm/mach-sa1100/pci-nanoengine.c
@@ -244,11 +244,9 @@ static int __init pci_nanoengine_setup_resources(struct pci_sys_data *sys)
printk(KERN_ERR "PCI: unable to allocate prefetchable\n");
return -EBUSY;
}
- pci_add_resource_offset(&sys->resources, &pci_io_ports, sys->io_offset);
- pci_add_resource_offset(&sys->resources,
- &pci_non_prefetchable_memory, sys->mem_offset);
- pci_add_resource_offset(&sys->resources,
- &pci_prefetchable_memory, sys->mem_offset);
+ pci_add_resource(&sys->resources, &pci_io_ports);
+ pci_add_resource(&sys->resources, &pci_non_prefetchable_memory);
+ pci_add_resource(&sys->resources, &pci_prefetchable_memory);
return 1;
}
diff --git a/trunk/arch/arm/mach-tegra/include/mach/smmu.h b/trunk/arch/arm/mach-tegra/include/mach/smmu.h
deleted file mode 100644
index dad403a9cf00..000000000000
--- a/trunk/arch/arm/mach-tegra/include/mach/smmu.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * IOMMU API for SMMU in Tegra30
- *
- * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- */
-
-#ifndef MACH_SMMU_H
-#define MACH_SMMU_H
-
-enum smmu_hwgrp {
- HWGRP_AFI,
- HWGRP_AVPC,
- HWGRP_DC,
- HWGRP_DCB,
- HWGRP_EPP,
- HWGRP_G2,
- HWGRP_HC,
- HWGRP_HDA,
- HWGRP_ISP,
- HWGRP_MPE,
- HWGRP_NV,
- HWGRP_NV2,
- HWGRP_PPCS,
- HWGRP_SATA,
- HWGRP_VDE,
- HWGRP_VI,
-
- HWGRP_COUNT,
-
- HWGRP_END = ~0,
-};
-
-#define HWG_AFI (1 << HWGRP_AFI)
-#define HWG_AVPC (1 << HWGRP_AVPC)
-#define HWG_DC (1 << HWGRP_DC)
-#define HWG_DCB (1 << HWGRP_DCB)
-#define HWG_EPP (1 << HWGRP_EPP)
-#define HWG_G2 (1 << HWGRP_G2)
-#define HWG_HC (1 << HWGRP_HC)
-#define HWG_HDA (1 << HWGRP_HDA)
-#define HWG_ISP (1 << HWGRP_ISP)
-#define HWG_MPE (1 << HWGRP_MPE)
-#define HWG_NV (1 << HWGRP_NV)
-#define HWG_NV2 (1 << HWGRP_NV2)
-#define HWG_PPCS (1 << HWGRP_PPCS)
-#define HWG_SATA (1 << HWGRP_SATA)
-#define HWG_VDE (1 << HWGRP_VDE)
-#define HWG_VI (1 << HWGRP_VI)
-
-#endif /* MACH_SMMU_H */
diff --git a/trunk/arch/arm/mach-tegra/pcie.c b/trunk/arch/arm/mach-tegra/pcie.c
index 14b29ab5d8f0..af8b63435727 100644
--- a/trunk/arch/arm/mach-tegra/pcie.c
+++ b/trunk/arch/arm/mach-tegra/pcie.c
@@ -408,7 +408,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[0].flags = IORESOURCE_IO;
if (request_resource(&ioport_resource, &pp->res[0]))
panic("Request PCIe IO resource failed\n");
- pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
+ pci_add_resource(&sys->resources, &pp->res[0]);
/*
* IORESOURCE_MEM
@@ -427,7 +427,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[1].flags = IORESOURCE_MEM;
if (request_resource(&iomem_resource, &pp->res[1]))
panic("Request PCIe Memory resource failed\n");
- pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
+ pci_add_resource(&sys->resources, &pp->res[1]);
/*
* IORESOURCE_MEM | IORESOURCE_PREFETCH
@@ -446,7 +446,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[2].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
if (request_resource(&iomem_resource, &pp->res[2]))
panic("Request PCIe Prefetch Memory resource failed\n");
- pci_add_resource_offset(&sys->resources, &pp->res[2], sys->mem_offset);
+ pci_add_resource(&sys->resources, &pp->res[2]);
return 1;
}
diff --git a/trunk/arch/arm/mach-versatile/pci.c b/trunk/arch/arm/mach-versatile/pci.c
index 51733b022d04..90069bce23bc 100644
--- a/trunk/arch/arm/mach-versatile/pci.c
+++ b/trunk/arch/arm/mach-versatile/pci.c
@@ -219,9 +219,9 @@ static int __init pci_versatile_setup_resources(struct list_head *resources)
* the mem resource for this bus
* the prefetch mem resource for this bus
*/
- pci_add_resource_offset(resources, &io_mem, sys->io_offset);
- pci_add_resource_offset(resources, &non_mem, sys->mem_offset);
- pci_add_resource_offset(resources, &pre_mem, sys->mem_offset);
+ pci_add_resource(resources, &io_mem);
+ pci_add_resource(resources, &non_mem);
+ pci_add_resource(resources, &pre_mem);
goto out;
diff --git a/trunk/arch/arm/mm/iomap.c b/trunk/arch/arm/mm/iomap.c
index 4614208369f1..e62956e12030 100644
--- a/trunk/arch/arm/mm/iomap.c
+++ b/trunk/arch/arm/mm/iomap.c
@@ -32,6 +32,9 @@ EXPORT_SYMBOL(pcibios_min_io);
unsigned long pcibios_min_mem = 0x01000000;
EXPORT_SYMBOL(pcibios_min_mem);
+unsigned int pci_flags = PCI_REASSIGN_ALL_RSRC;
+EXPORT_SYMBOL(pci_flags);
+
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
{
if ((unsigned long)addr >= VMALLOC_START &&
diff --git a/trunk/arch/arm/plat-iop/pci.c b/trunk/arch/arm/plat-iop/pci.c
index 72768356447a..f4d40a27111e 100644
--- a/trunk/arch/arm/plat-iop/pci.c
+++ b/trunk/arch/arm/plat-iop/pci.c
@@ -215,8 +215,8 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0;
sys->io_offset = IOP3XX_PCI_LOWER_IO_PA - *IOP3XX_OIOWTVR;
- pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
- pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+ pci_add_resource(&sys->resources, &res[0]);
+ pci_add_resource(&sys->resources, &res[1]);
return 1;
}
diff --git a/trunk/arch/arm/plat-mxc/devices/platform-mx2-camera.c b/trunk/arch/arm/plat-mxc/devices/platform-mx2-camera.c
index 11eace953a09..b3f4828dc447 100644
--- a/trunk/arch/arm/plat-mxc/devices/platform-mx2-camera.c
+++ b/trunk/arch/arm/plat-mxc/devices/platform-mx2-camera.c
@@ -62,21 +62,3 @@ struct platform_device *__init imx_add_mx2_camera(
res, data->iobaseemmaprp ? 4 : 2,
pdata, sizeof(*pdata), DMA_BIT_MASK(32));
}
-
-struct platform_device *__init imx_add_mx2_emmaprp(
- const struct imx_mx2_camera_data *data)
-{
- struct resource res[] = {
- {
- .start = data->iobaseemmaprp,
- .end = data->iobaseemmaprp + data->iosizeemmaprp - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = data->irqemmaprp,
- .end = data->irqemmaprp,
- .flags = IORESOURCE_IRQ,
- },
- };
- return imx_add_platform_device_dmamask("m2m-emmaprp", 0,
- res, 2, NULL, 0, DMA_BIT_MASK(32));
-}
diff --git a/trunk/arch/arm/plat-mxc/include/mach/devices-common.h b/trunk/arch/arm/plat-mxc/include/mach/devices-common.h
index 1b2258daa05b..def9ba53e23a 100644
--- a/trunk/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/trunk/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -223,8 +223,6 @@ struct imx_mx2_camera_data {
struct platform_device *__init imx_add_mx2_camera(
const struct imx_mx2_camera_data *data,
const struct mx2_camera_platform_data *pdata);
-struct platform_device *__init imx_add_mx2_emmaprp(
- const struct imx_mx2_camera_data *data);
#include
struct imx_mxc_ehci_data {
diff --git a/trunk/arch/ia64/include/asm/pci.h b/trunk/arch/ia64/include/asm/pci.h
index b22e5f5fa593..279b38ae74aa 100644
--- a/trunk/arch/ia64/include/asm/pci.h
+++ b/trunk/arch/ia64/include/asm/pci.h
@@ -108,6 +108,12 @@ static inline int pci_proc_domain(struct pci_bus *bus)
return (pci_domain_nr(bus) != 0);
}
+extern void pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region, struct resource *res);
+
+extern void pcibios_bus_to_resource(struct pci_dev *dev,
+ struct resource *res, struct pci_bus_region *region);
+
static inline struct resource *
pcibios_select_root(struct pci_dev *pdev, struct resource *res)
{
diff --git a/trunk/arch/ia64/pci/pci.c b/trunk/arch/ia64/pci/pci.c
index d1ce3200147c..f82f5d4b65fd 100644
--- a/trunk/arch/ia64/pci/pci.c
+++ b/trunk/arch/ia64/pci/pci.c
@@ -320,8 +320,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
* Ignore these tiny memory ranges */
if (!((window->resource.flags & IORESOURCE_MEM) &&
(window->resource.end - window->resource.start < 16)))
- pci_add_resource_offset(&info->resources, &window->resource,
- window->offset);
+ pci_add_resource(&info->resources, &window->resource);
return AE_OK;
}
@@ -396,6 +395,54 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
return NULL;
}
+void pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region, struct resource *res)
+{
+ struct pci_controller *controller = PCI_CONTROLLER(dev);
+ unsigned long offset = 0;
+ int i;
+
+ for (i = 0; i < controller->windows; i++) {
+ struct pci_window *window = &controller->window[i];
+ if (!(window->resource.flags & res->flags))
+ continue;
+ if (window->resource.start > res->start)
+ continue;
+ if (window->resource.end < res->end)
+ continue;
+ offset = window->offset;
+ break;
+ }
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+void pcibios_bus_to_resource(struct pci_dev *dev,
+ struct resource *res, struct pci_bus_region *region)
+{
+ struct pci_controller *controller = PCI_CONTROLLER(dev);
+ unsigned long offset = 0;
+ int i;
+
+ for (i = 0; i < controller->windows; i++) {
+ struct pci_window *window = &controller->window[i];
+ if (!(window->resource.flags & res->flags))
+ continue;
+ if (window->resource.start - window->offset > region->start)
+ continue;
+ if (window->resource.end - window->offset < region->end)
+ continue;
+ offset = window->offset;
+ break;
+ }
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
{
unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;
@@ -417,11 +464,15 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
static void __devinit
pcibios_fixup_resources(struct pci_dev *dev, int start, int limit)
{
+ struct pci_bus_region region;
int i;
for (i = start; i < limit; i++) {
if (!dev->resource[i].flags)
continue;
+ region.start = dev->resource[i].start;
+ region.end = dev->resource[i].end;
+ pcibios_bus_to_resource(dev, &dev->resource[i], ®ion);
if ((is_valid_resource(dev, i)))
pci_claim_resource(dev, i);
}
diff --git a/trunk/arch/ia64/sn/kernel/io_init.c b/trunk/arch/ia64/sn/kernel/io_init.c
index 238e2c511d94..0a36f082eaf1 100644
--- a/trunk/arch/ia64/sn/kernel/io_init.c
+++ b/trunk/arch/ia64/sn/kernel/io_init.c
@@ -297,8 +297,7 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
s64 status = 0;
struct pci_controller *controller;
struct pcibus_bussoft *prom_bussoft_ptr;
- LIST_HEAD(resources);
- int i;
+
status = sal_get_pcibus_info((u64) segment, (u64) busnum,
(u64) ia64_tpa(&prom_bussoft_ptr));
@@ -316,15 +315,7 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
*/
controller->platform_data = prom_bussoft_ptr;
- sn_legacy_pci_window_fixup(controller,
- prom_bussoft_ptr->bs_legacy_io,
- prom_bussoft_ptr->bs_legacy_mem);
- for (i = 0; i < controller->windows; i++)
- pci_add_resource_offset(&resources,
- &controller->window[i].resource,
- controller->window[i].offset);
- bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, controller,
- &resources);
+ bus = pci_scan_bus(busnum, &pci_root_ops, controller);
if (bus == NULL)
goto error_return; /* error, or bus already scanned */
@@ -357,6 +348,9 @@ sn_bus_fixup(struct pci_bus *bus)
return;
}
sn_common_bus_fixup(bus, prom_bussoft_ptr);
+ sn_legacy_pci_window_fixup(PCI_CONTROLLER(bus),
+ prom_bussoft_ptr->bs_legacy_io,
+ prom_bussoft_ptr->bs_legacy_mem);
}
list_for_each_entry(pci_dev, &bus->devices, bus_list) {
sn_io_slot_fixup(pci_dev);
diff --git a/trunk/arch/microblaze/include/asm/pci-bridge.h b/trunk/arch/microblaze/include/asm/pci-bridge.h
index cb5d39794800..e9834b2991d0 100644
--- a/trunk/arch/microblaze/include/asm/pci-bridge.h
+++ b/trunk/arch/microblaze/include/asm/pci-bridge.h
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
struct device_node;
diff --git a/trunk/arch/microblaze/include/asm/pci.h b/trunk/arch/microblaze/include/asm/pci.h
index a0da88bf70c5..033137628e8a 100644
--- a/trunk/arch/microblaze/include/asm/pci.h
+++ b/trunk/arch/microblaze/include/asm/pci.h
@@ -94,6 +94,14 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
*/
#define PCI_DMA_BUS_IS_PHYS (1)
+extern void pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region,
+ struct resource *res);
+
+extern void pcibios_bus_to_resource(struct pci_dev *dev,
+ struct resource *res,
+ struct pci_bus_region *region);
+
static inline struct resource *pcibios_select_root(struct pci_dev *pdev,
struct resource *res)
{
diff --git a/trunk/arch/microblaze/pci/pci-common.c b/trunk/arch/microblaze/pci/pci-common.c
index d10403dadd2b..85f2ac1230a8 100644
--- a/trunk/arch/microblaze/pci/pci-common.c
+++ b/trunk/arch/microblaze/pci/pci-common.c
@@ -46,6 +46,9 @@ static int global_phb_number; /* Global phb counter */
/* ISA Memory physical address */
resource_size_t isa_mem_base;
+/* Default PCI flags is 0 on ppc32, modified at boot on ppc64 */
+unsigned int pci_flags;
+
static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
unsigned long isa_io_base;
@@ -830,7 +833,64 @@ int pci_proc_domain(struct pci_bus *bus)
{
struct pci_controller *hose = pci_bus_to_host(bus);
- return 0;
+ if (!(pci_flags & PCI_ENABLE_PROC_DOMAINS))
+ return 0;
+ if (pci_flags & PCI_COMPAT_DOMAIN_0)
+ return hose->global_number != 0;
+ return 1;
+}
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ resource_size_t offset = 0, mask = (resource_size_t)-1;
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+ if (!hose)
+ return;
+ if (res->flags & IORESOURCE_IO) {
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+ mask = 0xffffffffu;
+ } else if (res->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+
+ region->start = (res->start - offset) & mask;
+ region->end = (res->end - offset) & mask;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ resource_size_t offset = 0, mask = (resource_size_t)-1;
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+ if (!hose)
+ return;
+ if (res->flags & IORESOURCE_IO) {
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+ mask = 0xffffffffu;
+ } else if (res->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+ res->start = (region->start + offset) & mask;
+ res->end = (region->end + offset) & mask;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
+/* Fixup a bus resource into a linux resource */
+static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ resource_size_t offset = 0, mask = (resource_size_t)-1;
+
+ if (res->flags & IORESOURCE_IO) {
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+ mask = 0xffffffffu;
+ } else if (res->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+
+ res->start = (res->start + offset) & mask;
+ res->end = (res->end + offset) & mask;
}
/* This header fixup will do the resource fixup for all devices as they are
@@ -850,7 +910,13 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
struct resource *res = dev->resource + i;
if (!res->flags)
continue;
- if (res->start == 0) {
+ /* On platforms that have PCI_PROBE_ONLY set, we don't
+ * consider 0 as an unassigned BAR value. It's technically
+ * a valid value, but linux doesn't like it... so when we can
+ * re-assign things, we do so, but if we can't, we keep it
+ * around and hope for the best...
+ */
+ if (res->start == 0 && !(pci_flags & PCI_PROBE_ONLY)) {
pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]" \
"is unassigned\n",
pci_name(dev), i,
@@ -863,11 +929,18 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
continue;
}
- pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]\n",
+ pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] fixup...\n",
pci_name(dev), i,
(unsigned long long)res->start,\
(unsigned long long)res->end,
(unsigned int)res->flags);
+
+ fixup_resource(res, dev);
+
+ pr_debug("PCI:%s %016llx-%016llx\n",
+ pci_name(dev),
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
@@ -886,6 +959,10 @@ static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
u16 command;
int i;
+ /* We don't do anything if PCI_PROBE_ONLY is set */
+ if (pci_flags & PCI_PROBE_ONLY)
+ return 0;
+
/* Job is a bit different between memory and IO */
if (res->flags & IORESOURCE_MEM) {
/* If the BAR is non-0 (res != pci_mem_offset) then it's
@@ -960,6 +1037,9 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
(unsigned long long)res->end,
(unsigned int)res->flags);
+ /* Perform fixup */
+ fixup_resource(res, dev);
+
/* Try to detect uninitialized P2P bridge resources,
* and clear them out so they get re-assigned later
*/
@@ -1027,6 +1107,9 @@ EXPORT_SYMBOL(pcibios_fixup_bus);
static int skip_isa_ioresource_align(struct pci_dev *dev)
{
+ if ((pci_flags & PCI_CAN_SKIP_ISA_ALIGN) &&
+ !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
+ return 1;
return 0;
}
@@ -1153,6 +1236,8 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
* and as such ensure proper re-allocation
* later.
*/
+ if (pci_flags & PCI_REASSIGN_ALL_RSRC)
+ goto clear_resource;
pr = pci_find_parent_resource(bus->self, res);
if (pr == res) {
/* this happens when the generic PCI
@@ -1337,19 +1422,27 @@ void __init pcibios_resource_survey(void)
list_for_each_entry(b, &pci_root_buses, node)
pcibios_allocate_bus_resources(b);
- pcibios_allocate_resources(0);
- pcibios_allocate_resources(1);
+ if (!(pci_flags & PCI_REASSIGN_ALL_RSRC)) {
+ pcibios_allocate_resources(0);
+ pcibios_allocate_resources(1);
+ }
/* Before we start assigning unassigned resource, we try to reserve
* the low IO area and the VGA memory area if they intersect the
* bus available resources to avoid allocating things on top of them
*/
- list_for_each_entry(b, &pci_root_buses, node)
- pcibios_reserve_legacy_regions(b);
+ if (!(pci_flags & PCI_PROBE_ONLY)) {
+ list_for_each_entry(b, &pci_root_buses, node)
+ pcibios_reserve_legacy_regions(b);
+ }
- /* Now proceed to assigning things that were left unassigned */
- pr_debug("PCI: Assigning unassigned resources...\n");
- pci_assign_unassigned_resources();
+ /* Now, if the platform didn't decide to blindly trust the firmware,
+ * we proceed to assigning things that were left unassigned
+ */
+ if (!(pci_flags & PCI_PROBE_ONLY)) {
+ pr_debug("PCI: Assigning unassigned resources...\n");
+ pci_assign_unassigned_resources();
+ }
}
#ifdef CONFIG_HOTPLUG
@@ -1442,7 +1535,7 @@ static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, s
res->end = res->start + IO_SPACE_LIMIT;
res->flags = IORESOURCE_IO;
}
- pci_add_resource_offset(resources, res, hose->io_base_virt - _IO_BASE);
+ pci_add_resource(resources, res);
pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n",
(unsigned long long)res->start,
@@ -1465,7 +1558,7 @@ static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, s
res->flags = IORESOURCE_MEM;
}
- pci_add_resource_offset(resources, res, hose->pci_mem_offset);
+ pci_add_resource(resources, res);
pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n",
i, (unsigned long long)res->start,
diff --git a/trunk/arch/mips/include/asm/pci.h b/trunk/arch/mips/include/asm/pci.h
index fcd4060f6421..576397c69920 100644
--- a/trunk/arch/mips/include/asm/pci.h
+++ b/trunk/arch/mips/include/asm/pci.h
@@ -92,7 +92,6 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
#include
#include
#include
-#include
struct pci_dev;
@@ -113,6 +112,12 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
}
#endif
+extern void pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region, struct resource *res);
+
+extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region);
+
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
static inline int pci_proc_domain(struct pci_bus *bus)
@@ -140,6 +145,8 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
#define arch_setup_msi_irqs arch_setup_msi_irqs
#endif
+extern int pci_probe_only;
+
extern char * (*pcibios_plat_setup)(char *str);
#endif /* _ASM_PCI_H */
diff --git a/trunk/arch/mips/pci/fixup-cobalt.c b/trunk/arch/mips/pci/fixup-cobalt.c
index 9553b14002dd..acacd1407c63 100644
--- a/trunk/arch/mips/pci/fixup-cobalt.c
+++ b/trunk/arch/mips/pci/fixup-cobalt.c
@@ -51,6 +51,67 @@ static void qube_raq_galileo_early_fixup(struct pci_dev *dev)
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
qube_raq_galileo_early_fixup);
+static void __devinit cobalt_legacy_ide_resource_fixup(struct pci_dev *dev,
+ struct resource *res)
+{
+ struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+ unsigned long offset = hose->io_offset;
+ struct resource orig = *res;
+
+ if (!(res->flags & IORESOURCE_IO) ||
+ !(res->flags & IORESOURCE_PCI_FIXED))
+ return;
+
+ res->start -= offset;
+ res->end -= offset;
+ dev_printk(KERN_DEBUG, &dev->dev, "converted legacy %pR to bus %pR\n",
+ &orig, res);
+}
+
+static void __devinit cobalt_legacy_ide_fixup(struct pci_dev *dev)
+{
+ u32 class;
+ u8 progif;
+
+ /*
+ * If the IDE controller is in legacy mode, pci_setup_device() fills in
+ * the resources with the legacy addresses that normally appear on the
+ * PCI bus, just as if we had read them from a BAR.
+ *
+ * However, with the GT-64111, those legacy addresses, e.g., 0x1f0,
+ * will never appear on the PCI bus because it converts memory accesses
+ * in the PCI I/O region (which is never at address zero) into I/O port
+ * accesses with no address translation.
+ *
+ * For example, if GT_DEF_PCI0_IO_BASE is 0x10000000, a load or store
+ * to physical address 0x100001f0 will become a PCI access to I/O port
+ * 0x100001f0. There's no way to generate an access to I/O port 0x1f0,
+ * but the VT82C586 IDE controller does respond at 0x100001f0 because
+ * it only decodes the low 24 bits of the address.
+ *
+ * When this quirk runs, the pci_dev resources should contain bus
+ * addresses, not Linux I/O port numbers, so convert legacy addresses
+ * like 0x1f0 to bus addresses like 0x100001f0. Later, we'll convert
+ * them back with pcibios_fixup_bus() or pcibios_bus_to_resource().
+ */
+ class = dev->class >> 8;
+ if (class != PCI_CLASS_STORAGE_IDE)
+ return;
+
+ pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+ if ((progif & 1) == 0) {
+ cobalt_legacy_ide_resource_fixup(dev, &dev->resource[0]);
+ cobalt_legacy_ide_resource_fixup(dev, &dev->resource[1]);
+ }
+ if ((progif & 4) == 0) {
+ cobalt_legacy_ide_resource_fixup(dev, &dev->resource[2]);
+ cobalt_legacy_ide_resource_fixup(dev, &dev->resource[3]);
+ }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+ cobalt_legacy_ide_fixup);
+
static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
{
unsigned short cfgword;
diff --git a/trunk/arch/mips/pci/pci-bcm1480.c b/trunk/arch/mips/pci/pci-bcm1480.c
index 37b52dc3d27e..af8c31996965 100644
--- a/trunk/arch/mips/pci/pci-bcm1480.c
+++ b/trunk/arch/mips/pci/pci-bcm1480.c
@@ -204,7 +204,7 @@ static int __init bcm1480_pcibios_init(void)
uint64_t reg;
/* CFE will assign PCI resources */
- pci_set_flags(PCI_PROBE_ONLY);
+ pci_probe_only = 1;
/* Avoid ISA compat ranges. */
PCIBIOS_MIN_IO = 0x00008000UL;
diff --git a/trunk/arch/mips/pci/pci-ip27.c b/trunk/arch/mips/pci/pci-ip27.c
index 0fbe4c0c170a..193e9494f98e 100644
--- a/trunk/arch/mips/pci/pci-ip27.c
+++ b/trunk/arch/mips/pci/pci-ip27.c
@@ -50,7 +50,7 @@ int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid)
bridge_t *bridge;
int slot;
- pci_set_flags(PCI_PROBE_ONLY);
+ pci_probe_only = 1;
printk("a bridge\n");
diff --git a/trunk/arch/mips/pci/pci-lantiq.c b/trunk/arch/mips/pci/pci-lantiq.c
index 030c77e7926e..be1e1afe12c3 100644
--- a/trunk/arch/mips/pci/pci-lantiq.c
+++ b/trunk/arch/mips/pci/pci-lantiq.c
@@ -270,8 +270,7 @@ static int __devinit ltq_pci_probe(struct platform_device *pdev)
{
struct ltq_pci_data *ltq_pci_data =
(struct ltq_pci_data *) pdev->dev.platform_data;
-
- pci_clear_flags(PCI_PROBE_ONLY);
+ pci_probe_only = 0;
ltq_pci_irq_map = ltq_pci_data->irq;
ltq_pci_membase = ioremap_nocache(PCI_CR_BASE_ADDR, PCI_CR_SIZE);
ltq_pci_mapped_cfg =
diff --git a/trunk/arch/mips/pci/pci-sb1250.c b/trunk/arch/mips/pci/pci-sb1250.c
index dd97f3a83baa..1711e8e101bc 100644
--- a/trunk/arch/mips/pci/pci-sb1250.c
+++ b/trunk/arch/mips/pci/pci-sb1250.c
@@ -213,7 +213,7 @@ static int __init sb1250_pcibios_init(void)
uint64_t reg;
/* CFE will assign PCI resources */
- pci_set_flags(PCI_PROBE_ONLY);
+ pci_probe_only = 1;
/* Avoid ISA compat ranges. */
PCIBIOS_MIN_IO = 0x00008000UL;
diff --git a/trunk/arch/mips/pci/pci-xlr.c b/trunk/arch/mips/pci/pci-xlr.c
index 1644805a6730..3d701a962ef4 100644
--- a/trunk/arch/mips/pci/pci-xlr.c
+++ b/trunk/arch/mips/pci/pci-xlr.c
@@ -292,7 +292,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
static int __init pcibios_init(void)
{
/* PSB assigns PCI resources */
- pci_set_flags(PCI_PROBE_ONLY);
+ pci_probe_only = 1;
pci_config_base = ioremap(DEFAULT_PCI_CONFIG_BASE, 16 << 20);
/* Extend IO port for memory mapped io */
diff --git a/trunk/arch/mips/pci/pci.c b/trunk/arch/mips/pci/pci.c
index 0514866fa925..15521505ebe8 100644
--- a/trunk/arch/mips/pci/pci.c
+++ b/trunk/arch/mips/pci/pci.c
@@ -20,9 +20,16 @@
#include
/*
- * If PCI_PROBE_ONLY in pci_flags is set, we don't change any PCI resource
- * assignments.
+ * Indicate whether we respect the PCI setup left by the firmware.
+ *
+ * Make this long-lived so that we know when shutting down
+ * whether we probed only or not.
*/
+int pci_probe_only;
+
+#define PCI_ASSIGN_ALL_BUSSES 1
+
+unsigned int pci_probe = PCI_ASSIGN_ALL_BUSSES;
/*
* The PCI controller list.
@@ -85,12 +92,11 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose)
if (!hose->iommu)
PCI_DMA_BUS_IS_PHYS = 1;
- if (hose->get_busno && pci_has_flag(PCI_PROBE_ONLY))
+ if (hose->get_busno && pci_probe_only)
next_busno = (*hose->get_busno)();
- pci_add_resource_offset(&resources,
- hose->mem_resource, hose->mem_offset);
- pci_add_resource_offset(&resources, hose->io_resource, hose->io_offset);
+ pci_add_resource(&resources, hose->mem_resource);
+ pci_add_resource(&resources, hose->io_resource);
bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
&resources);
if (!bus)
@@ -109,7 +115,7 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose)
need_domain_info = 1;
}
- if (!pci_has_flag(PCI_PROBE_ONLY)) {
+ if (!pci_probe_only) {
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
pci_enable_bridges(bus);
@@ -235,7 +241,7 @@ static int pcibios_enable_resources(struct pci_dev *dev, int mask)
unsigned int pcibios_assign_all_busses(void)
{
- return 1;
+ return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
@@ -248,13 +254,42 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return pcibios_plat_dev_init(dev);
}
+static void pcibios_fixup_device_resources(struct pci_dev *dev,
+ struct pci_bus *bus)
+{
+ /* Update device resources. */
+ struct pci_controller *hose = (struct pci_controller *)bus->sysdata;
+ unsigned long offset = 0;
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ if (!dev->resource[i].start)
+ continue;
+ if (dev->resource[i].flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (dev->resource[i].flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ dev->resource[i].start += offset;
+ dev->resource[i].end += offset;
+ }
+}
+
void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{
+ /* Propagate hose info into the subordinate devices. */
+
struct pci_dev *dev = bus->self;
- if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
+ if (pci_probe_only && dev &&
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
pci_read_bridge_bases(bus);
+ pcibios_fixup_device_resources(dev, bus);
+ }
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ pcibios_fixup_device_resources(dev, bus);
}
}
@@ -264,7 +299,40 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+
+void __devinit
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
+}
+
#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
EXPORT_SYMBOL(PCIBIOS_MIN_IO);
EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
#endif
diff --git a/trunk/arch/mn10300/include/asm/pci.h b/trunk/arch/mn10300/include/asm/pci.h
index 8137c25c4e15..6095a28561dd 100644
--- a/trunk/arch/mn10300/include/asm/pci.h
+++ b/trunk/arch/mn10300/include/asm/pci.h
@@ -85,6 +85,22 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
/* implement the pci_ DMA API in terms of the generic device dma_ one */
#include
+/**
+ * pcibios_resource_to_bus - convert resource to PCI bus address
+ * @dev: device which owns this resource
+ * @region: converted bus-centric region (start,end)
+ * @res: resource to convert
+ *
+ * Convert a resource to a PCI device bus address or bus window.
+ */
+extern void pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region,
+ struct resource *res);
+
+extern void pcibios_bus_to_resource(struct pci_dev *dev,
+ struct resource *res,
+ struct pci_bus_region *region);
+
static inline struct resource *
pcibios_select_root(struct pci_dev *pdev, struct resource *res)
{
diff --git a/trunk/arch/mn10300/unit-asb2305/pci.c b/trunk/arch/mn10300/unit-asb2305/pci.c
index 6dce9fc2cf3c..a7c5f08ca9f5 100644
--- a/trunk/arch/mn10300/unit-asb2305/pci.c
+++ b/trunk/arch/mn10300/unit-asb2305/pci.c
@@ -32,7 +32,8 @@ struct pci_ops *pci_root_ops;
* insert specific PCI bus resources instead of using the platform-level bus
* resources directly for the PCI root bus.
*
- * These are configured and inserted by pcibios_init().
+ * These are configured and inserted by pcibios_init() and are attached to the
+ * root bus by pcibios_fixup_bus().
*/
static struct resource pci_ioport_resource = {
.name = "PCI IO",
@@ -76,6 +77,52 @@ static inline int __query(const struct pci_bus *bus, unsigned int devfn)
return 1;
}
+/*
+ * translate Linuxcentric addresses to PCI bus addresses
+ */
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ if (res->flags & IORESOURCE_IO) {
+ region->start = (res->start & 0x00ffffff);
+ region->end = (res->end & 0x00ffffff);
+ }
+
+ if (res->flags & IORESOURCE_MEM) {
+ region->start = (res->start & 0x03ffffff) | MEM_PAGING_REG;
+ region->end = (res->end & 0x03ffffff) | MEM_PAGING_REG;
+ }
+
+#if 0
+ printk(KERN_DEBUG "RES->BUS: %lx-%lx => %lx-%lx\n",
+ res->start, res->end, region->start, region->end);
+#endif
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+/*
+ * translate PCI bus addresses to Linuxcentric addresses
+ */
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ if (res->flags & IORESOURCE_IO) {
+ res->start = (region->start & 0x00ffffff) | 0xbe000000;
+ res->end = (region->end & 0x00ffffff) | 0xbe000000;
+ }
+
+ if (res->flags & IORESOURCE_MEM) {
+ res->start = (region->start & 0x03ffffff) | 0xb8000000;
+ res->end = (region->end & 0x03ffffff) | 0xb8000000;
+ }
+
+#if 0
+ printk(KERN_INFO "BUS->RES: %lx-%lx => %lx-%lx\n",
+ region->start, region->end, res->start, res->end);
+#endif
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
/*
*
*/
@@ -317,6 +364,9 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
if (!dev->resource[i].flags)
continue;
+ region.start = dev->resource[i].start;
+ region.end = dev->resource[i].end;
+ pcibios_bus_to_resource(dev, &dev->resource[i], ®ion);
if (is_valid_resource(dev, i))
pci_claim_resource(dev, i);
}
@@ -347,7 +397,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
*/
static int __init pcibios_init(void)
{
- resource_size_t io_offset, mem_offset;
LIST_HEAD(resources);
ioport_resource.start = 0xA0000000;
@@ -371,13 +420,8 @@ static int __init pcibios_init(void)
printk(KERN_INFO "PCI: Probing PCI hardware [mempage %08x]\n",
MEM_PAGING_REG);
- io_offset = pci_ioport_resource.start -
- (pci_ioport_resource.start & 0x00ffffff);
- mem_offset = pci_iomem_resource.start -
- ((pci_iomem_resource.start & 0x03ffffff) | MEM_PAGING_REG);
-
- pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset);
- pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset);
+ pci_add_resource(&resources, &pci_ioport_resource);
+ pci_add_resource(&resources, &pci_iomem_resource);
pci_root_bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL,
&resources);
diff --git a/trunk/arch/parisc/include/asm/pci.h b/trunk/arch/parisc/include/asm/pci.h
index 3234f492d575..2242a5c636c2 100644
--- a/trunk/arch/parisc/include/asm/pci.h
+++ b/trunk/arch/parisc/include/asm/pci.h
@@ -82,8 +82,38 @@ struct pci_hba_data {
#ifdef CONFIG_64BIT
#define PCI_F_EXTEND 0xffffffff00000000UL
+#define PCI_IS_LMMIO(hba,a) pci_is_lmmio(hba,a)
+
+/* We need to know if an address is LMMMIO or GMMIO.
+ * LMMIO requires mangling and GMMIO we must use as-is.
+ */
+static __inline__ int pci_is_lmmio(struct pci_hba_data *hba, unsigned long a)
+{
+ return(((a) & PCI_F_EXTEND) == PCI_F_EXTEND);
+}
+
+/*
+** Convert between PCI (IO_VIEW) addresses and processor (PA_VIEW) addresses.
+** See pci.c for more conversions used by Generic PCI code.
+**
+** Platform characteristics/firmware guarantee that
+** (1) PA_VIEW - IO_VIEW = lmmio_offset for both LMMIO and ELMMIO
+** (2) PA_VIEW == IO_VIEW for GMMIO
+*/
+#define PCI_BUS_ADDR(hba,a) (PCI_IS_LMMIO(hba,a) \
+ ? ((a) - hba->lmmio_space_offset) /* mangle LMMIO */ \
+ : (a)) /* GMMIO */
+#define PCI_HOST_ADDR(hba,a) (((a) & PCI_F_EXTEND) == 0 \
+ ? (a) + hba->lmmio_space_offset \
+ : (a))
+
#else /* !CONFIG_64BIT */
+
+#define PCI_BUS_ADDR(hba,a) (a)
+#define PCI_HOST_ADDR(hba,a) (a)
#define PCI_F_EXTEND 0UL
+#define PCI_IS_LMMIO(hba,a) (1) /* 32-bit doesn't support GMMIO */
+
#endif /* !CONFIG_64BIT */
/*
@@ -215,6 +245,14 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
}
#endif
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res);
+
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region);
+
static inline void pcibios_penalize_isa_irq(int irq, int active)
{
/* We don't need to penalize isa irq's */
diff --git a/trunk/arch/parisc/kernel/pci.c b/trunk/arch/parisc/kernel/pci.c
index 74d544b1cd22..9efd97405317 100644
--- a/trunk/arch/parisc/kernel/pci.c
+++ b/trunk/arch/parisc/kernel/pci.c
@@ -195,6 +195,58 @@ void __init pcibios_init_bus(struct pci_bus *bus)
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl);
}
+/* called by drivers/pci/setup-bus.c:pci_setup_bridge(). */
+void __devinit pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region, struct resource *res)
+{
+#ifdef CONFIG_64BIT
+ struct pci_hba_data *hba = HBA_DATA(dev->bus->bridge->platform_data);
+#endif
+
+ if (res->flags & IORESOURCE_IO) {
+ /*
+ ** I/O space may see busnumbers here. Something
+ ** in the form of 0xbbxxxx where bb is the bus num
+ ** and xxxx is the I/O port space address.
+ ** Remaining address translation are done in the
+ ** PCI Host adapter specific code - ie dino_out8.
+ */
+ region->start = PCI_PORT_ADDR(res->start);
+ region->end = PCI_PORT_ADDR(res->end);
+ } else if (res->flags & IORESOURCE_MEM) {
+ /* Convert MMIO addr to PCI addr (undo global virtualization) */
+ region->start = PCI_BUS_ADDR(hba, res->start);
+ region->end = PCI_BUS_ADDR(hba, res->end);
+ }
+
+ DBG_RES("pcibios_resource_to_bus(%02x %s [%lx,%lx])\n",
+ dev->bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM",
+ region->start, region->end);
+}
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+#ifdef CONFIG_64BIT
+ struct pci_hba_data *hba = HBA_DATA(dev->bus->bridge->platform_data);
+#endif
+
+ if (res->flags & IORESOURCE_MEM) {
+ res->start = PCI_HOST_ADDR(hba, region->start);
+ res->end = PCI_HOST_ADDR(hba, region->end);
+ }
+
+ if (res->flags & IORESOURCE_IO) {
+ res->start = region->start;
+ res->end = region->end;
+ }
+}
+
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+#endif
+
/*
* pcibios align resources() is called every time generic PCI code
* wants to generate a new address. The process of looking for
diff --git a/trunk/arch/powerpc/include/asm/pci.h b/trunk/arch/powerpc/include/asm/pci.h
index 6653f2743c4e..f54b3d26ce9d 100644
--- a/trunk/arch/powerpc/include/asm/pci.h
+++ b/trunk/arch/powerpc/include/asm/pci.h
@@ -154,6 +154,14 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
#endif /* CONFIG_PPC64 */
+extern void pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region,
+ struct resource *res);
+
+extern void pcibios_bus_to_resource(struct pci_dev *dev,
+ struct resource *res,
+ struct pci_bus_region *region);
+
extern void pcibios_claim_one_bus(struct pci_bus *b);
extern void pcibios_finish_adding_to_bus(struct pci_bus *bus);
@@ -182,7 +190,6 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
const struct resource *rsrc,
resource_size_t *start, resource_size_t *end);
-extern resource_size_t pcibios_io_space_offset(struct pci_controller *hose);
extern void pcibios_setup_bus_devices(struct pci_bus *bus);
extern void pcibios_setup_bus_self(struct pci_bus *bus);
extern void pcibios_setup_phb_io_space(struct pci_controller *hose);
diff --git a/trunk/arch/powerpc/include/asm/ppc-pci.h b/trunk/arch/powerpc/include/asm/ppc-pci.h
index 80fa704d410f..e660b37aa7d0 100644
--- a/trunk/arch/powerpc/include/asm/ppc-pci.h
+++ b/trunk/arch/powerpc/include/asm/ppc-pci.h
@@ -45,6 +45,8 @@ extern void init_pci_config_tokens (void);
extern unsigned long get_phb_buid (struct device_node *);
extern int rtas_setup_phb(struct pci_controller *phb);
+extern unsigned long pci_probe_only;
+
#ifdef CONFIG_EEH
void pci_addr_cache_build(void);
diff --git a/trunk/arch/powerpc/kernel/pci-common.c b/trunk/arch/powerpc/kernel/pci-common.c
index 8e78e93c8185..d0373bcb7c9d 100644
--- a/trunk/arch/powerpc/kernel/pci-common.c
+++ b/trunk/arch/powerpc/kernel/pci-common.c
@@ -49,6 +49,9 @@ static int global_phb_number; /* Global phb counter */
/* ISA Memory physical address */
resource_size_t isa_mem_base;
+/* Default PCI flags is 0 on ppc32, modified at boot on ppc64 */
+unsigned int pci_flags = 0;
+
static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
@@ -831,6 +834,60 @@ int pci_proc_domain(struct pci_bus *bus)
return 1;
}
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ resource_size_t offset = 0, mask = (resource_size_t)-1;
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+ if (!hose)
+ return;
+ if (res->flags & IORESOURCE_IO) {
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+ mask = 0xffffffffu;
+ } else if (res->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+
+ region->start = (res->start - offset) & mask;
+ region->end = (res->end - offset) & mask;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ resource_size_t offset = 0, mask = (resource_size_t)-1;
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+ if (!hose)
+ return;
+ if (res->flags & IORESOURCE_IO) {
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+ mask = 0xffffffffu;
+ } else if (res->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+ res->start = (region->start + offset) & mask;
+ res->end = (region->end + offset) & mask;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
+/* Fixup a bus resource into a linux resource */
+static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ resource_size_t offset = 0, mask = (resource_size_t)-1;
+
+ if (res->flags & IORESOURCE_IO) {
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+ mask = 0xffffffffu;
+ } else if (res->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+
+ res->start = (res->start + offset) & mask;
+ res->end = (res->end + offset) & mask;
+}
+
+
/* This header fixup will do the resource fixup for all devices as they are
* probed, but not for bridge ranges
*/
@@ -870,11 +927,18 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
continue;
}
- pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]\n",
+ pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] fixup...\n",
pci_name(dev), i,
(unsigned long long)res->start,\
(unsigned long long)res->end,
(unsigned int)res->flags);
+
+ fixup_resource(res, dev);
+
+ pr_debug("PCI:%s %016llx-%016llx\n",
+ pci_name(dev),
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
}
/* Call machine specific resource fixup */
@@ -976,18 +1040,27 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
continue;
}
- pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x]\n",
+ pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
pci_name(dev), i,
(unsigned long long)res->start,\
(unsigned long long)res->end,
(unsigned int)res->flags);
+ /* Perform fixup */
+ fixup_resource(res, dev);
+
/* Try to detect uninitialized P2P bridge resources,
* and clear them out so they get re-assigned later
*/
if (pcibios_uninitialized_bridge_resource(bus, res)) {
res->flags = 0;
pr_debug("PCI:%s (unassigned)\n", pci_name(dev));
+ } else {
+
+ pr_debug("PCI:%s %016llx-%016llx\n",
+ pci_name(dev),
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
}
}
}
@@ -1477,11 +1550,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return pci_enable_resources(dev, mask);
}
-resource_size_t pcibios_io_space_offset(struct pci_controller *hose)
-{
- return (unsigned long) hose->io_base_virt - _IO_BASE;
-}
-
static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, struct list_head *resources)
{
struct resource *res;
@@ -1506,7 +1574,7 @@ static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, s
(unsigned long long)res->start,
(unsigned long long)res->end,
(unsigned long)res->flags);
- pci_add_resource_offset(resources, res, pcibios_io_space_offset(hose));
+ pci_add_resource(resources, res);
/* Hookup PHB Memory resources */
for (i = 0; i < 3; ++i) {
@@ -1529,7 +1597,7 @@ static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, s
(unsigned long long)res->start,
(unsigned long long)res->end,
(unsigned long)res->flags);
- pci_add_resource_offset(resources, res, hose->pci_mem_offset);
+ pci_add_resource(resources, res);
}
pr_debug("PCI: PHB MEM offset = %016llx\n",
diff --git a/trunk/arch/powerpc/kernel/pci_32.c b/trunk/arch/powerpc/kernel/pci_32.c
index 4b06ec5a502e..fdd1a3d951dc 100644
--- a/trunk/arch/powerpc/kernel/pci_32.c
+++ b/trunk/arch/powerpc/kernel/pci_32.c
@@ -219,9 +219,9 @@ void __devinit pcibios_setup_phb_io_space(struct pci_controller *hose)
struct resource *res = &hose->io_resource;
/* Fixup IO space offset */
- io_offset = pcibios_io_space_offset(hose);
- res->start += io_offset;
- res->end += io_offset;
+ io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+ res->start = (res->start + io_offset) & 0xffffffffu;
+ res->end = (res->end + io_offset) & 0xffffffffu;
}
static int __init pcibios_init(void)
diff --git a/trunk/arch/powerpc/kernel/pci_64.c b/trunk/arch/powerpc/kernel/pci_64.c
index 94a54f61d341..3318d39b7d4c 100644
--- a/trunk/arch/powerpc/kernel/pci_64.c
+++ b/trunk/arch/powerpc/kernel/pci_64.c
@@ -33,6 +33,8 @@
#include
#include
+unsigned long pci_probe_only = 1;
+
/* pci_io_base -- the base address from which io bars are offsets.
* This is the lowest I/O base address (so bar values are always positive),
* and it *must* be the start of ISA space if an ISA bus exists because
@@ -53,6 +55,9 @@ static int __init pcibios_init(void)
*/
ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
+ if (pci_probe_only)
+ pci_add_flags(PCI_PROBE_ONLY);
+
/* On ppc64, we always enable PCI domains and we keep domain 0
* backward compatible in /proc for video cards
*/
@@ -168,7 +173,7 @@ static int __devinit pcibios_map_phb_io_space(struct pci_controller *hose)
return -ENOMEM;
/* Fixup hose IO resource */
- io_virt_offset = pcibios_io_space_offset(hose);
+ io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
hose->io_resource.start += io_virt_offset;
hose->io_resource.end += io_virt_offset;
diff --git a/trunk/arch/powerpc/kernel/pci_of_scan.c b/trunk/arch/powerpc/kernel/pci_of_scan.c
index 89dde171a6fa..b37d0b5a796e 100644
--- a/trunk/arch/powerpc/kernel/pci_of_scan.c
+++ b/trunk/arch/powerpc/kernel/pci_of_scan.c
@@ -75,7 +75,6 @@ static void of_pci_parse_addrs(struct device_node *node, struct pci_dev *dev)
{
u64 base, size;
unsigned int flags;
- struct pci_bus_region region;
struct resource *res;
const u32 *addrs;
u32 i;
@@ -107,11 +106,10 @@ static void of_pci_parse_addrs(struct device_node *node, struct pci_dev *dev)
printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i);
continue;
}
+ res->start = base;
+ res->end = base + size - 1;
res->flags = flags;
res->name = pci_name(dev);
- region.start = base;
- region.end = base + size - 1;
- pcibios_bus_to_resource(dev, res, ®ion);
}
}
@@ -211,7 +209,6 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev)
struct pci_bus *bus;
const u32 *busrange, *ranges;
int len, i, mode;
- struct pci_bus_region region;
struct resource *res;
unsigned int flags;
u64 size;
@@ -273,10 +270,9 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev)
res = bus->resource[i];
++i;
}
+ res->start = of_read_number(&ranges[1], 2);
+ res->end = res->start + size - 1;
res->flags = flags;
- region.start = of_read_number(&ranges[1], 2);
- region.end = region.start + size - 1;
- pcibios_bus_to_resource(dev, res, ®ion);
}
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
bus->number);
diff --git a/trunk/arch/powerpc/kernel/rtas_pci.c b/trunk/arch/powerpc/kernel/rtas_pci.c
index 179af906dcda..517bd86bc3f0 100644
--- a/trunk/arch/powerpc/kernel/rtas_pci.c
+++ b/trunk/arch/powerpc/kernel/rtas_pci.c
@@ -279,7 +279,7 @@ void __init find_and_init_phbs(void)
eeh_dev_phb_init();
/*
- * PCI_PROBE_ONLY and PCI_REASSIGN_ALL_BUS can be set via properties
+ * pci_probe_only and pci_assign_all_buses can be set via properties
* in chosen.
*/
if (of_chosen) {
@@ -287,12 +287,8 @@ void __init find_and_init_phbs(void)
prop = of_get_property(of_chosen,
"linux,pci-probe-only", NULL);
- if (prop) {
- if (*prop)
- pci_add_flags(PCI_PROBE_ONLY);
- else
- pci_clear_flags(PCI_PROBE_ONLY);
- }
+ if (prop)
+ pci_probe_only = *prop;
#ifdef CONFIG_PPC32 /* Will be made generic soon */
prop = of_get_property(of_chosen,
diff --git a/trunk/arch/powerpc/platforms/maple/pci.c b/trunk/arch/powerpc/platforms/maple/pci.c
index 465ee8f5c086..401e3f3f74c8 100644
--- a/trunk/arch/powerpc/platforms/maple/pci.c
+++ b/trunk/arch/powerpc/platforms/maple/pci.c
@@ -620,7 +620,7 @@ void __init maple_pci_init(void)
}
/* Tell pci.c to not change any resource allocations. */
- pci_add_flags(PCI_PROBE_ONLY);
+ pci_probe_only = 1;
}
int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
diff --git a/trunk/arch/powerpc/platforms/pasemi/pci.c b/trunk/arch/powerpc/platforms/pasemi/pci.c
index aa862713258c..b6a0ec45c695 100644
--- a/trunk/arch/powerpc/platforms/pasemi/pci.c
+++ b/trunk/arch/powerpc/platforms/pasemi/pci.c
@@ -229,6 +229,9 @@ void __init pas_pci_init(void)
/* Setup the linkage between OF nodes and PHBs */
pci_devs_phb_init();
+
+ /* Use the common resource allocation mechanism */
+ pci_probe_only = 1;
}
void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset)
diff --git a/trunk/arch/powerpc/platforms/powermac/pci.c b/trunk/arch/powerpc/platforms/powermac/pci.c
index 43bbe1bda939..31a7d3a7ce25 100644
--- a/trunk/arch/powerpc/platforms/powermac/pci.c
+++ b/trunk/arch/powerpc/platforms/powermac/pci.c
@@ -1059,6 +1059,9 @@ void __init pmac_pci_init(void)
}
/* pmac_check_ht_link(); */
+ /* We can allocate missing resources if any */
+ pci_probe_only = 0;
+
#else /* CONFIG_PPC64 */
init_p2pbridge();
init_second_ohare();
diff --git a/trunk/arch/powerpc/platforms/powernv/pci-ioda.c b/trunk/arch/powerpc/platforms/powernv/pci-ioda.c
index fbdd74dac3ac..5e155dfc4320 100644
--- a/trunk/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/trunk/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1299,14 +1299,15 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
/* Setup MSI support */
pnv_pci_init_ioda_msis(phb);
- /* We set both PCI_PROBE_ONLY and PCI_REASSIGN_ALL_RSRC. This is an
+ /* We set both probe_only and PCI_REASSIGN_ALL_RSRC. This is an
* odd combination which essentially means that we skip all resource
* fixups and assignments in the generic code, and do it all
* ourselves here
*/
+ pci_probe_only = 1;
ppc_md.pcibios_fixup_phb = pnv_pci_ioda_fixup_phb;
ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook;
- pci_add_flags(PCI_PROBE_ONLY | PCI_REASSIGN_ALL_RSRC);
+ pci_add_flags(PCI_REASSIGN_ALL_RSRC);
/* Reset IODA tables to a clean state */
rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
diff --git a/trunk/arch/powerpc/platforms/powernv/pci.c b/trunk/arch/powerpc/platforms/powernv/pci.c
index be3cfc5ceabb..214478d781ae 100644
--- a/trunk/arch/powerpc/platforms/powernv/pci.c
+++ b/trunk/arch/powerpc/platforms/powernv/pci.c
@@ -562,7 +562,10 @@ void __init pnv_pci_init(void)
{
struct device_node *np;
- pci_add_flags(PCI_CAN_SKIP_ISA_ALIGN);
+ pci_set_flags(PCI_CAN_SKIP_ISA_ALIGN);
+
+ /* We do not want to just probe */
+ pci_probe_only = 0;
/* OPAL absent, try POPAL first then RTAS detection of PHBs */
if (!firmware_has_feature(FW_FEATURE_OPAL)) {
diff --git a/trunk/arch/powerpc/platforms/pseries/pci_dlpar.c b/trunk/arch/powerpc/platforms/pseries/pci_dlpar.c
index 8b7bafa489c2..fbb21fc3080b 100644
--- a/trunk/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/trunk/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -84,7 +84,7 @@ void pcibios_remove_pci_devices(struct pci_bus *bus)
list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
pr_debug(" * Removing %s...\n", pci_name(dev));
eeh_remove_bus_device(dev);
- pci_stop_and_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
}
}
EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
diff --git a/trunk/arch/powerpc/platforms/pseries/setup.c b/trunk/arch/powerpc/platforms/pseries/setup.c
index 51ecac920dd8..8f137af616af 100644
--- a/trunk/arch/powerpc/platforms/pseries/setup.c
+++ b/trunk/arch/powerpc/platforms/pseries/setup.c
@@ -383,9 +383,6 @@ static void __init pSeries_setup_arch(void)
fwnmi_init();
- /* By default, only probe PCI (can be overriden by rtas_pci) */
- pci_add_flags(PCI_PROBE_ONLY);
-
/* Find and initialize PCI host bridges */
init_pci_config_tokens();
eeh_pseries_init();
diff --git a/trunk/arch/powerpc/platforms/wsp/wsp_pci.c b/trunk/arch/powerpc/platforms/wsp/wsp_pci.c
index 763014cd1e62..d24b3acf858e 100644
--- a/trunk/arch/powerpc/platforms/wsp/wsp_pci.c
+++ b/trunk/arch/powerpc/platforms/wsp/wsp_pci.c
@@ -682,6 +682,7 @@ static int __init wsp_setup_one_phb(struct device_node *np)
/* XXX Force re-assigning of everything for now */
pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC |
PCI_ENABLE_PROC_DOMAINS);
+ pci_probe_only = 0;
/* Calculate how the TCE space is divided */
phb->dma32_base = 0;
diff --git a/trunk/arch/sh/drivers/pci/pci.c b/trunk/arch/sh/drivers/pci/pci.c
index 9d10a3cb8797..1e7b0e2e764d 100644
--- a/trunk/arch/sh/drivers/pci/pci.c
+++ b/trunk/arch/sh/drivers/pci/pci.c
@@ -37,20 +37,11 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose)
static int next_busno;
static int need_domain_info;
LIST_HEAD(resources);
- struct resource *res;
- resource_size_t offset;
int i;
struct pci_bus *bus;
- for (i = 0; i < hose->nr_resources; i++) {
- res = hose->resources + i;
- offset = 0;
- if (res->flags & IORESOURCE_IO)
- offset = hose->io_offset;
- else if (res->flags & IORESOURCE_MEM)
- offset = hose->mem_offset;
- pci_add_resource_offset(&resources, res, offset);
- }
+ for (i = 0; i < hose->nr_resources; i++)
+ pci_add_resource(&resources, hose->resources + i);
bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
&resources);
@@ -152,12 +143,42 @@ static int __init pcibios_init(void)
}
subsys_initcall(pcibios_init);
+static void pcibios_fixup_device_resources(struct pci_dev *dev,
+ struct pci_bus *bus)
+{
+ /* Update device resources. */
+ struct pci_channel *hose = bus->sysdata;
+ unsigned long offset = 0;
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ if (!dev->resource[i].start)
+ continue;
+ if (dev->resource[i].flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (dev->resource[i].flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ dev->resource[i].start += offset;
+ dev->resource[i].end += offset;
+ }
+}
+
/*
* Called after each bus is probed, but before its children
* are examined.
*/
void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{
+ struct pci_dev *dev;
+ struct list_head *ln;
+
+ for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+ dev = pci_dev_b(ln);
+
+ if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ pcibios_fixup_device_resources(dev, bus);
+ }
}
/*
@@ -187,6 +208,36 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
return start;
}
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_channel *hose = dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_channel *hose = dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
+}
+
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
return pci_enable_resources(dev, mask);
@@ -330,6 +381,8 @@ EXPORT_SYMBOL(pci_iounmap);
#endif /* CONFIG_GENERIC_IOMAP */
#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
EXPORT_SYMBOL(PCIBIOS_MIN_IO);
EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
#endif
diff --git a/trunk/arch/sh/include/asm/pci.h b/trunk/arch/sh/include/asm/pci.h
index bff96c2e7d25..cb21e2399dc1 100644
--- a/trunk/arch/sh/include/asm/pci.h
+++ b/trunk/arch/sh/include/asm/pci.h
@@ -114,6 +114,12 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
/* Board-specific fixup routines. */
int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin);
+extern void pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region, struct resource *res);
+
+extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region);
+
#define pci_domain_nr(bus) ((struct pci_channel *)(bus)->sysdata)->index
static inline int pci_proc_domain(struct pci_bus *bus)
diff --git a/trunk/arch/sparc/include/asm/pci_32.h b/trunk/arch/sparc/include/asm/pci_32.h
index dc503297481f..6de7f7bf956a 100644
--- a/trunk/arch/sparc/include/asm/pci_32.h
+++ b/trunk/arch/sparc/include/asm/pci_32.h
@@ -52,6 +52,14 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
* 64Kbytes by the Host controller.
*/
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res);
+
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region);
+
static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
{
return PCI_IRQ_NONE;
diff --git a/trunk/arch/sparc/include/asm/pci_64.h b/trunk/arch/sparc/include/asm/pci_64.h
index 1633b718d3bc..755a4bb6bcd3 100644
--- a/trunk/arch/sparc/include/asm/pci_64.h
+++ b/trunk/arch/sparc/include/asm/pci_64.h
@@ -73,6 +73,14 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state,
int write_combine);
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res);
+
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region);
+
static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
{
return PCI_IRQ_NONE;
diff --git a/trunk/arch/sparc/kernel/leon_pci.c b/trunk/arch/sparc/kernel/leon_pci.c
index aba6b958b2a5..c7bec25fdb1c 100644
--- a/trunk/arch/sparc/kernel/leon_pci.c
+++ b/trunk/arch/sparc/kernel/leon_pci.c
@@ -15,19 +15,14 @@
/* The LEON architecture does not rely on a BIOS or bootloader to setup
* PCI for us. The Linux generic routines are used to setup resources,
- * reset values of configuration-space register settings are preserved.
- *
- * PCI Memory and Prefetchable Memory is direct-mapped. However I/O Space is
- * accessed through a Window which is translated to low 64KB in PCI space, the
- * first 4KB is not used so 60KB is available.
+ * reset values of confuration-space registers settings ae preseved.
*/
void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
{
LIST_HEAD(resources);
struct pci_bus *root_bus;
- pci_add_resource_offset(&resources, &info->io_space,
- info->io_space.start - 0x1000);
+ pci_add_resource(&resources, &info->io_space);
pci_add_resource(&resources, &info->mem_space);
root_bus = pci_scan_root_bus(&ofdev->dev, 0, info->ops, info,
@@ -43,6 +38,44 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
}
}
+/* PCI Memory and Prefetchable Memory is direct-mapped. However I/O Space is
+ * accessed through a Window which is translated to low 64KB in PCI space, the
+ * first 4KB is not used so 60KB is available.
+ *
+ * This function is used by generic code to translate resource addresses into
+ * PCI addresses.
+ */
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct leon_pci_info *info = dev->bus->sysdata;
+
+ region->start = res->start;
+ region->end = res->end;
+
+ if (res->flags & IORESOURCE_IO) {
+ region->start -= (info->io_space.start - 0x1000);
+ region->end -= (info->io_space.start - 0x1000);
+ }
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+/* see pcibios_resource_to_bus() comment */
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct leon_pci_info *info = dev->bus->sysdata;
+
+ res->start = region->start;
+ res->end = region->end;
+
+ if (res->flags & IORESOURCE_IO) {
+ res->start += (info->io_space.start - 0x1000);
+ res->end += (info->io_space.start - 0x1000);
+ }
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
{
struct leon_pci_info *info = pbus->sysdata;
diff --git a/trunk/arch/sparc/kernel/pci.c b/trunk/arch/sparc/kernel/pci.c
index fdaf21811670..bb8bc2e519ac 100644
--- a/trunk/arch/sparc/kernel/pci.c
+++ b/trunk/arch/sparc/kernel/pci.c
@@ -375,6 +375,13 @@ static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
*last_p = last;
}
+static void pci_resource_adjust(struct resource *res,
+ struct resource *root)
+{
+ res->start += root->start;
+ res->end += root->start;
+}
+
/* For PCI bus devices which lack a 'ranges' property we interrogate
* the config space values to set the resources, just like the generic
* Linux PCI probing code does.
@@ -383,8 +390,7 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
struct pci_bus *bus,
struct pci_pbm_info *pbm)
{
- struct pci_bus_region region;
- struct resource *res, res2;
+ struct resource *res;
u8 io_base_lo, io_limit_lo;
u16 mem_base_lo, mem_limit_lo;
unsigned long base, limit;
@@ -406,14 +412,11 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
res = bus->resource[0];
if (base <= limit) {
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
- res2.flags = res->flags;
- region.start = base;
- region.end = limit + 0xfff;
- pcibios_bus_to_resource(dev, &res2, ®ion);
if (!res->start)
- res->start = res2.start;
+ res->start = base;
if (!res->end)
- res->end = res2.end;
+ res->end = limit + 0xfff;
+ pci_resource_adjust(res, &pbm->io_space);
}
pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
@@ -425,9 +428,9 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
if (base <= limit) {
res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
IORESOURCE_MEM);
- region.start = base;
- region.end = limit + 0xfffff;
- pcibios_bus_to_resource(dev, res, ®ion);
+ res->start = base;
+ res->end = limit + 0xfffff;
+ pci_resource_adjust(res, &pbm->mem_space);
}
pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
@@ -456,9 +459,9 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
if (base <= limit) {
res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
IORESOURCE_MEM | IORESOURCE_PREFETCH);
- region.start = base;
- region.end = limit + 0xfffff;
- pcibios_bus_to_resource(dev, res, ®ion);
+ res->start = base;
+ res->end = limit + 0xfffff;
+ pci_resource_adjust(res, &pbm->mem_space);
}
}
@@ -469,7 +472,6 @@ static void __devinit apb_fake_ranges(struct pci_dev *dev,
struct pci_bus *bus,
struct pci_pbm_info *pbm)
{
- struct pci_bus_region region;
struct resource *res;
u32 first, last;
u8 map;
@@ -477,18 +479,18 @@ static void __devinit apb_fake_ranges(struct pci_dev *dev,
pci_read_config_byte(dev, APB_IO_ADDRESS_MAP, &map);
apb_calc_first_last(map, &first, &last);
res = bus->resource[0];
+ res->start = (first << 21);
+ res->end = (last << 21) + ((1 << 21) - 1);
res->flags = IORESOURCE_IO;
- region.start = (first << 21);
- region.end = (last << 21) + ((1 << 21) - 1);
- pcibios_bus_to_resource(dev, res, ®ion);
+ pci_resource_adjust(res, &pbm->io_space);
pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map);
apb_calc_first_last(map, &first, &last);
res = bus->resource[1];
+ res->start = (first << 21);
+ res->end = (last << 21) + ((1 << 21) - 1);
res->flags = IORESOURCE_MEM;
- region.start = (first << 21);
- region.end = (last << 21) + ((1 << 21) - 1);
- pcibios_bus_to_resource(dev, res, ®ion);
+ pci_resource_adjust(res, &pbm->mem_space);
}
static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
@@ -504,7 +506,6 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
struct pci_bus *bus;
const u32 *busrange, *ranges;
int len, i, simba;
- struct pci_bus_region region;
struct resource *res;
unsigned int flags;
u64 size;
@@ -555,6 +556,8 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
}
i = 1;
for (; len >= 32; len -= 32, ranges += 8) {
+ struct resource *root;
+
flags = pci_parse_of_flags(ranges[0]);
size = GET_64BIT(ranges, 6);
if (flags == 0 || size == 0)
@@ -566,6 +569,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
" for bridge %s\n", node->full_name);
continue;
}
+ root = &pbm->io_space;
} else {
if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) {
printk(KERN_ERR "PCI: too many memory ranges"
@@ -574,12 +578,18 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
}
res = bus->resource[i];
++i;
+ root = &pbm->mem_space;
}
+ res->start = GET_64BIT(ranges, 1);
+ res->end = res->start + size - 1;
res->flags = flags;
- region.start = GET_64BIT(ranges, 1);
- region.end = region.start + size - 1;
- pcibios_bus_to_resource(dev, res, ®ion);
+
+ /* Another way to implement this would be to add an of_device
+ * layer routine that can calculate a resource for a given
+ * range property value in a PCI device.
+ */
+ pci_resource_adjust(res, root);
}
after_ranges:
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
@@ -681,10 +691,8 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
printk("PCI: Scanning PBM %s\n", node->full_name);
- pci_add_resource_offset(&resources, &pbm->io_space,
- pbm->io_space.start);
- pci_add_resource_offset(&resources, &pbm->mem_space,
- pbm->mem_space.start);
+ pci_add_resource(&resources, &pbm->io_space);
+ pci_add_resource(&resources, &pbm->mem_space);
bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops,
pbm, &resources);
if (!bus) {
@@ -747,6 +755,46 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return 0;
}
+void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_pbm_info *pbm = pdev->bus->sysdata;
+ struct resource zero_res, *root;
+
+ zero_res.start = 0;
+ zero_res.end = 0;
+ zero_res.flags = res->flags;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &pbm->io_space;
+ else
+ root = &pbm->mem_space;
+
+ pci_resource_adjust(&zero_res, root);
+
+ region->start = res->start - zero_res.start;
+ region->end = res->end - zero_res.start;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_pbm_info *pbm = pdev->bus->sysdata;
+ struct resource *root;
+
+ res->start = region->start;
+ res->end = region->end;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &pbm->io_space;
+ else
+ root = &pbm->mem_space;
+
+ pci_resource_adjust(res, root);
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
char * __devinit pcibios_setup(char *str)
{
return str;
diff --git a/trunk/arch/unicore32/include/asm/pci.h b/trunk/arch/unicore32/include/asm/pci.h
index f5e108f4a151..dd3867727c35 100644
--- a/trunk/arch/unicore32/include/asm/pci.h
+++ b/trunk/arch/unicore32/include/asm/pci.h
@@ -14,7 +14,6 @@
#ifdef __KERNEL__
#include
-#include
#include
#include /* for PCIBIOS_MIN_* */
diff --git a/trunk/arch/unicore32/kernel/pci.c b/trunk/arch/unicore32/kernel/pci.c
index 2fc2b1ba825e..a8f07fe10cad 100644
--- a/trunk/arch/unicore32/kernel/pci.c
+++ b/trunk/arch/unicore32/kernel/pci.c
@@ -21,6 +21,7 @@
#include
static int debug_pci;
+static int use_firmware;
#define CONFIG_CMD(bus, devfn, where) \
(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
@@ -275,7 +276,7 @@ static int __init pci_common_init(void)
pci_fixup_irqs(pci_common_swizzle, pci_puv3_map_irq);
- if (!pci_has_flag(PCI_PROBE_ONLY)) {
+ if (!use_firmware) {
/*
* Size the bridge windows.
*/
@@ -302,7 +303,7 @@ char * __devinit pcibios_setup(char *str)
debug_pci = 1;
return NULL;
} else if (!strcmp(str, "firmware")) {
- pci_add_flags(PCI_PROBE_ONLY);
+ use_firmware = 1;
return NULL;
}
return str;
diff --git a/trunk/arch/x86/kernel/pci-dma.c b/trunk/arch/x86/kernel/pci-dma.c
index 28e5e06fcba4..1c4d769e21ea 100644
--- a/trunk/arch/x86/kernel/pci-dma.c
+++ b/trunk/arch/x86/kernel/pci-dma.c
@@ -262,11 +262,10 @@ rootfs_initcall(pci_iommu_init);
static __devinit void via_no_dac(struct pci_dev *dev)
{
- if (forbid_dac == 0) {
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
dev_info(&dev->dev, "disabling DAC on VIA PCI bridge\n");
forbid_dac = 1;
}
}
-DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID,
- PCI_CLASS_BRIDGE_PCI, 8, via_no_dac);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
#endif
diff --git a/trunk/arch/x86/pci/acpi.c b/trunk/arch/x86/pci/acpi.c
index ed2835e148b5..49a5cb55429b 100644
--- a/trunk/arch/x86/pci/acpi.c
+++ b/trunk/arch/x86/pci/acpi.c
@@ -416,12 +416,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
kfree(sd);
} else {
get_current_resources(device, busnum, domain, &resources);
-
- /*
- * _CRS with no apertures is normal, so only fall back to
- * defaults or native bridge info if we're ignoring _CRS.
- */
- if (!pci_use_crs)
+ if (list_empty(&resources))
x86_pci_root_bus_resources(busnum, &resources);
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources);
diff --git a/trunk/arch/x86/pci/fixup.c b/trunk/arch/x86/pci/fixup.c
index d0e6e403b4f6..6dd89555fbfa 100644
--- a/trunk/arch/x86/pci/fixup.c
+++ b/trunk/arch/x86/pci/fixup.c
@@ -164,11 +164,11 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_
*/
static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev)
{
- if ((dev->device & 0xff00) == 0x2400)
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
+ (dev->device & 0xff00) == 0x2400)
dev->transparent = 1;
}
-DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
- PCI_CLASS_BRIDGE_PCI, 8, pci_fixup_transparent_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge);
/*
* Fixup for C1 Halt Disconnect problem on nForce2 systems.
@@ -322,6 +322,9 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
struct pci_bus *bus;
u16 config;
+ if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+ return;
+
/* Is VGA routed to us? */
bus = pdev->bus;
while (bus) {
@@ -350,8 +353,7 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
}
}
-DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video);
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
static const struct dmi_system_id __devinitconst msi_k8t_dmi_table[] = {
diff --git a/trunk/arch/x86/pci/i386.c b/trunk/arch/x86/pci/i386.c
index 831971e731f7..91821a1a0c3a 100644
--- a/trunk/arch/x86/pci/i386.c
+++ b/trunk/arch/x86/pci/i386.c
@@ -39,87 +39,6 @@
#include
-/*
- * This list of dynamic mappings is for temporarily maintaining
- * original BIOS BAR addresses for possible reinstatement.
- */
-struct pcibios_fwaddrmap {
- struct list_head list;
- struct pci_dev *dev;
- resource_size_t fw_addr[DEVICE_COUNT_RESOURCE];
-};
-
-static LIST_HEAD(pcibios_fwaddrmappings);
-static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock);
-
-/* Must be called with 'pcibios_fwaddrmap_lock' lock held. */
-static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev)
-{
- struct pcibios_fwaddrmap *map;
-
- WARN_ON(!spin_is_locked(&pcibios_fwaddrmap_lock));
-
- list_for_each_entry(map, &pcibios_fwaddrmappings, list)
- if (map->dev == dev)
- return map;
-
- return NULL;
-}
-
-static void
-pcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr)
-{
- unsigned long flags;
- struct pcibios_fwaddrmap *map;
-
- spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
- map = pcibios_fwaddrmap_lookup(dev);
- if (!map) {
- spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
- map = kzalloc(sizeof(*map), GFP_KERNEL);
- if (!map)
- return;
-
- map->dev = pci_dev_get(dev);
- map->fw_addr[idx] = fw_addr;
- INIT_LIST_HEAD(&map->list);
-
- spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
- list_add_tail(&map->list, &pcibios_fwaddrmappings);
- } else
- map->fw_addr[idx] = fw_addr;
- spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
-}
-
-resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
-{
- unsigned long flags;
- struct pcibios_fwaddrmap *map;
- resource_size_t fw_addr = 0;
-
- spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
- map = pcibios_fwaddrmap_lookup(dev);
- if (map)
- fw_addr = map->fw_addr[idx];
- spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
-
- return fw_addr;
-}
-
-static void pcibios_fw_addr_list_del(void)
-{
- unsigned long flags;
- struct pcibios_fwaddrmap *entry, *next;
-
- spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
- list_for_each_entry_safe(entry, next, &pcibios_fwaddrmappings, list) {
- list_del(&entry->list);
- pci_dev_put(entry->dev);
- kfree(entry);
- }
- spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
-}
-
static int
skip_isa_ioresource_align(struct pci_dev *dev) {
@@ -263,8 +182,7 @@ static void __init pcibios_allocate_resources(int pass)
idx, r, disabled, pass);
if (pci_claim_resource(dev, idx) < 0) {
/* We'll assign a new address later */
- pcibios_save_fw_addr(dev,
- idx, r->start);
+ dev->fw_addr[idx] = r->start;
r->end -= r->start;
r->start = 0;
}
@@ -310,7 +228,6 @@ static int __init pcibios_assign_resources(void)
}
pci_assign_unassigned_resources();
- pcibios_fw_addr_list_del();
return 0;
}
diff --git a/trunk/arch/x86/pci/mrst.c b/trunk/arch/x86/pci/mrst.c
index 140942f66b31..cb29191cee58 100644
--- a/trunk/arch/x86/pci/mrst.c
+++ b/trunk/arch/x86/pci/mrst.c
@@ -43,8 +43,6 @@
#define PCI_FIXED_BAR_4_SIZE 0x14
#define PCI_FIXED_BAR_5_SIZE 0x1c
-static int pci_soc_mode = 0;
-
/**
* fixed_bar_cap - return the offset of the fixed BAR cap if found
* @bus: PCI bus
@@ -150,9 +148,7 @@ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
*/
if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE)
return 0;
- if (bus == 0 && (devfn == PCI_DEVFN(2, 0)
- || devfn == PCI_DEVFN(0, 0)
- || devfn == PCI_DEVFN(3, 0)))
+ if (bus == 0 && (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(0, 0)))
return 1;
return 0; /* langwell on others */
}
@@ -235,43 +231,14 @@ struct pci_ops pci_mrst_ops = {
*/
int __init pci_mrst_init(void)
{
- printk(KERN_INFO "Intel MID platform detected, using MID PCI ops\n");
+ printk(KERN_INFO "Moorestown platform detected, using MRST PCI ops\n");
pci_mmcfg_late_init();
pcibios_enable_irq = mrst_pci_irq_enable;
pci_root_ops = pci_mrst_ops;
- pci_soc_mode = 1;
/* Continue with standard init */
return 1;
}
-/* Langwell devices are not true pci devices, they are not subject to 10 ms
- * d3 to d0 delay required by pci spec.
- */
-static void __devinit pci_d3delay_fixup(struct pci_dev *dev)
-{
- /* PCI fixups are effectively decided compile time. If we have a dual
- SoC/non-SoC kernel we don't want to mangle d3 on non SoC devices */
- if (!pci_soc_mode)
- return;
- /* true pci devices in lincroft should allow type 1 access, the rest
- * are langwell fake pci devices.
- */
- if (type1_access_ok(dev->bus->number, dev->devfn, PCI_DEVICE_ID))
- return;
- dev->d3_delay = 0;
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_d3delay_fixup);
-
-static void __devinit mrst_power_off_unused_dev(struct pci_dev *dev)
-{
- pci_set_power_state(dev, PCI_D3cold);
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0801, mrst_power_off_unused_dev);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0809, mrst_power_off_unused_dev);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x080C, mrst_power_off_unused_dev);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0812, mrst_power_off_unused_dev);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0815, mrst_power_off_unused_dev);
-
/*
* Langwell devices reside at fixed offsets, don't try to move them.
*/
@@ -281,9 +248,6 @@ static void __devinit pci_fixed_bar_fixup(struct pci_dev *dev)
u32 size;
int i;
- if (!pci_soc_mode)
- return;
-
/* Must have extended configuration space */
if (dev->cfg_size < PCIE_CAP_OFFSET + 4)
return;
diff --git a/trunk/arch/xtensa/kernel/pci.c b/trunk/arch/xtensa/kernel/pci.c
index eb30e356f5be..61045c192e88 100644
--- a/trunk/arch/xtensa/kernel/pci.c
+++ b/trunk/arch/xtensa/kernel/pci.c
@@ -153,7 +153,7 @@ static void __init pci_controller_apertures(struct pci_controller *pci_ctrl,
}
res->start += io_offset;
res->end += io_offset;
- pci_add_resource_offset(resources, res, io_offset);
+ pci_add_resource(resources, res);
for (i = 0; i < 3; i++) {
res = &pci_ctrl->mem_resources[i];
@@ -200,9 +200,24 @@ subsys_initcall(pcibios_init);
void __init pcibios_fixup_bus(struct pci_bus *bus)
{
+ struct pci_controller *pci_ctrl = bus->sysdata;
+ struct resource *res;
+ unsigned long io_offset;
+ int i;
+
+ io_offset = (unsigned long)pci_ctrl->io_space.base;
if (bus->parent) {
/* This is a subordinate bridge */
pci_read_bridge_bases(bus);
+
+ for (i = 0; i < 4; i++) {
+ if ((res = bus->resource[i]) == NULL || !res->flags)
+ continue;
+ if (io_offset && (res->flags & IORESOURCE_IO)) {
+ res->start += io_offset;
+ res->end += io_offset;
+ }
+ }
}
}
diff --git a/trunk/drivers/hid/hid-core.c b/trunk/drivers/hid/hid-core.c
index 4da66b4b977c..70ca07f10d5c 100644
--- a/trunk/drivers/hid/hid-core.c
+++ b/trunk/drivers/hid/hid-core.c
@@ -2026,16 +2026,6 @@ static bool hid_ignore(struct hid_device *hdev)
if (hdev->product >= USB_DEVICE_ID_LOGITECH_HARMONY_FIRST &&
hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST)
return true;
- /*
- * The Keene FM transmitter USB device has the same USB ID as
- * the Logitech AudioHub Speaker, but it should ignore the hid.
- * Check if the name is that of the Keene device.
- * For reference: the name of the AudioHub is
- * "HOLTEK AudioHub Speaker".
- */
- if (hdev->product == USB_DEVICE_ID_LOGITECH_AUDIOHUB &&
- !strcmp(hdev->name, "HOLTEK B-LINK USB Audio "))
- return true;
break;
case USB_VENDOR_ID_SOUNDGRAPH:
if (hdev->product >= USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST &&
diff --git a/trunk/drivers/hid/hid-ids.h b/trunk/drivers/hid/hid-ids.h
index e39aecb1f9f2..2a5cef2f53a7 100644
--- a/trunk/drivers/hid/hid-ids.h
+++ b/trunk/drivers/hid/hid-ids.h
@@ -471,7 +471,6 @@
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
#define USB_VENDOR_ID_LOGITECH 0x046d
-#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110
#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
diff --git a/trunk/drivers/hwmon/Kconfig b/trunk/drivers/hwmon/Kconfig
index 5b32d56dbb4d..811e6c47e7e6 100644
--- a/trunk/drivers/hwmon/Kconfig
+++ b/trunk/drivers/hwmon/Kconfig
@@ -648,8 +648,7 @@ config SENSORS_LM90
LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A,
Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008,
- Winbond/Nuvoton W83L771W/G/AWG/ASG, Philips SA56004, and GMT G781
- sensor chips.
+ Winbond/Nuvoton W83L771W/G/AWG/ASG and Philips SA56004 sensor chips.
This driver can also be built as a module. If so, the module
will be called lm90.
@@ -813,16 +812,6 @@ config SENSORS_MAX6650
This driver can also be built as a module. If so, the module
will be called max6650.
-config SENSORS_MCP3021
- tristate "Microchip MCP3021"
- depends on I2C && EXPERIMENTAL
- help
- If you say yes here you get support for the MCP3021 chip
- that is a A/D converter (ADC) with 10-bit resolution.
-
- This driver can also be built as a module. If so, the module
- will be called mcp3021.
-
config SENSORS_NTC_THERMISTOR
tristate "NTC thermistor support"
depends on EXPERIMENTAL
@@ -1240,19 +1229,18 @@ config SENSORS_W83795
depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for the Winbond W83795G and
- W83795ADG hardware monitoring chip, including manual fan speed
- control.
+ W83795ADG hardware monitoring chip.
This driver can also be built as a module. If so, the module
will be called w83795.
config SENSORS_W83795_FANCTRL
- boolean "Include automatic fan control support (DANGEROUS)"
+ boolean "Include fan control support (DANGEROUS)"
depends on SENSORS_W83795 && EXPERIMENTAL
default n
help
- If you say yes here, support for automatic fan speed control
- will be included in the driver.
+ If you say yes here, support for the both manual and automatic
+ fan control features will be included in the driver.
This part of the code wasn't carefully reviewed and tested yet,
so enabling this option is strongly discouraged on production
@@ -1370,10 +1358,10 @@ config SENSORS_APPLESMC
the awesome power of applesmc.
config SENSORS_MC13783_ADC
- tristate "Freescale MC13783/MC13892 ADC"
- depends on MFD_MC13XXX
+ tristate "Freescale MC13783 ADC"
+ depends on MFD_MC13783
help
- Support for the A/D converter on MC13783 and MC13892 PMIC.
+ Support for the A/D converter on MC13783 PMIC.
if ACPI
diff --git a/trunk/drivers/hwmon/Makefile b/trunk/drivers/hwmon/Makefile
index 6d3f11f71815..8251ce8cd035 100644
--- a/trunk/drivers/hwmon/Makefile
+++ b/trunk/drivers/hwmon/Makefile
@@ -95,7 +95,6 @@ obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
obj-$(CONFIG_SENSORS_MAX6642) += max6642.o
obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
-obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o
obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
diff --git a/trunk/drivers/hwmon/fam15h_power.c b/trunk/drivers/hwmon/fam15h_power.c
index b7494af1e4a9..523f8fb9e7d9 100644
--- a/trunk/drivers/hwmon/fam15h_power.c
+++ b/trunk/drivers/hwmon/fam15h_power.c
@@ -60,15 +60,15 @@ static ssize_t show_power(struct device *dev,
pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
REG_TDP_RUNNING_AVERAGE, &val);
running_avg_capture = (val >> 4) & 0x3fffff;
- running_avg_capture = sign_extend32(running_avg_capture, 21);
- running_avg_range = (val & 0xf) + 1;
+ running_avg_capture = sign_extend32(running_avg_capture, 22);
+ running_avg_range = val & 0xf;
pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
REG_TDP_LIMIT3, &val);
tdp_limit = val >> 16;
- curr_pwr_watts = (tdp_limit + data->base_tdp) << running_avg_range;
- curr_pwr_watts -= running_avg_capture;
+ curr_pwr_watts = tdp_limit + data->base_tdp -
+ (s32)(running_avg_capture >> (running_avg_range + 1));
curr_pwr_watts *= data->tdp_to_watts;
/*
@@ -78,7 +78,7 @@ static ssize_t show_power(struct device *dev,
* scaling factor 1/(2^16). For conversion we use
* (10^6)/(2^16) = 15625/(2^10)
*/
- curr_pwr_watts = (curr_pwr_watts * 15625) >> (10 + running_avg_range);
+ curr_pwr_watts = (curr_pwr_watts * 15625) >> 10;
return sprintf(buf, "%u\n", (unsigned int) curr_pwr_watts);
}
static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL);
diff --git a/trunk/drivers/hwmon/lm63.c b/trunk/drivers/hwmon/lm63.c
index 602a0f0b0de8..15c05cc83e2c 100644
--- a/trunk/drivers/hwmon/lm63.c
+++ b/trunk/drivers/hwmon/lm63.c
@@ -148,8 +148,45 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
#define UPDATE_INTERVAL(max, rate) \
((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))
+/*
+ * Functions declaration
+ */
+
+static int lm63_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int lm63_remove(struct i2c_client *client);
+
+static struct lm63_data *lm63_update_device(struct device *dev);
+
+static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info);
+static void lm63_init_client(struct i2c_client *client);
+
enum chips { lm63, lm64, lm96163 };
+/*
+ * Driver data (common to all clients)
+ */
+
+static const struct i2c_device_id lm63_id[] = {
+ { "lm63", lm63 },
+ { "lm64", lm64 },
+ { "lm96163", lm96163 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lm63_id);
+
+static struct i2c_driver lm63_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "lm63",
+ },
+ .probe = lm63_probe,
+ .remove = lm63_remove,
+ .id_table = lm63_id,
+ .detect = lm63_detect,
+ .address_list = normal_i2c,
+};
+
/*
* Client data (each client gets its own)
*/
@@ -205,145 +242,6 @@ static inline int lut_temp_from_reg(struct lm63_data *data, int nr)
return data->temp8[nr] * (data->lut_temp_highres ? 500 : 1000);
}
-static inline int lut_temp_to_reg(struct lm63_data *data, long val)
-{
- val -= data->temp2_offset;
- if (data->lut_temp_highres)
- return DIV_ROUND_CLOSEST(SENSORS_LIMIT(val, 0, 127500), 500);
- else
- return DIV_ROUND_CLOSEST(SENSORS_LIMIT(val, 0, 127000), 1000);
-}
-
-/*
- * Update the lookup table register cache.
- * client->update_lock must be held when calling this function.
- */
-static void lm63_update_lut(struct i2c_client *client)
-{
- struct lm63_data *data = i2c_get_clientdata(client);
- int i;
-
- if (time_after(jiffies, data->lut_last_updated + 5 * HZ) ||
- !data->lut_valid) {
- for (i = 0; i < data->lut_size; i++) {
- data->pwm1[1 + i] = i2c_smbus_read_byte_data(client,
- LM63_REG_LUT_PWM(i));
- data->temp8[3 + i] = i2c_smbus_read_byte_data(client,
- LM63_REG_LUT_TEMP(i));
- }
- data->lut_temp_hyst = i2c_smbus_read_byte_data(client,
- LM63_REG_LUT_TEMP_HYST);
-
- data->lut_last_updated = jiffies;
- data->lut_valid = 1;
- }
-}
-
-static struct lm63_data *lm63_update_device(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm63_data *data = i2c_get_clientdata(client);
- unsigned long next_update;
-
- mutex_lock(&data->update_lock);
-
- next_update = data->last_updated
- + msecs_to_jiffies(data->update_interval) + 1;
-
- if (time_after(jiffies, next_update) || !data->valid) {
- if (data->config & 0x04) { /* tachometer enabled */
- /* order matters for fan1_input */
- data->fan[0] = i2c_smbus_read_byte_data(client,
- LM63_REG_TACH_COUNT_LSB) & 0xFC;
- data->fan[0] |= i2c_smbus_read_byte_data(client,
- LM63_REG_TACH_COUNT_MSB) << 8;
- data->fan[1] = (i2c_smbus_read_byte_data(client,
- LM63_REG_TACH_LIMIT_LSB) & 0xFC)
- | (i2c_smbus_read_byte_data(client,
- LM63_REG_TACH_LIMIT_MSB) << 8);
- }
-
- data->pwm1_freq = i2c_smbus_read_byte_data(client,
- LM63_REG_PWM_FREQ);
- if (data->pwm1_freq == 0)
- data->pwm1_freq = 1;
- data->pwm1[0] = i2c_smbus_read_byte_data(client,
- LM63_REG_PWM_VALUE);
-
- data->temp8[0] = i2c_smbus_read_byte_data(client,
- LM63_REG_LOCAL_TEMP);
- data->temp8[1] = i2c_smbus_read_byte_data(client,
- LM63_REG_LOCAL_HIGH);
-
- /* order matters for temp2_input */
- data->temp11[0] = i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_TEMP_MSB) << 8;
- data->temp11[0] |= i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_TEMP_LSB);
- data->temp11[1] = (i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_LOW_MSB) << 8)
- | i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_LOW_LSB);
- data->temp11[2] = (i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_HIGH_MSB) << 8)
- | i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_HIGH_LSB);
- data->temp11[3] = (i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_OFFSET_MSB) << 8)
- | i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_OFFSET_LSB);
-
- if (data->kind == lm96163)
- data->temp11u = (i2c_smbus_read_byte_data(client,
- LM96163_REG_REMOTE_TEMP_U_MSB) << 8)
- | i2c_smbus_read_byte_data(client,
- LM96163_REG_REMOTE_TEMP_U_LSB);
-
- data->temp8[2] = i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_TCRIT);
- data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_TCRIT_HYST);
-
- data->alarms = i2c_smbus_read_byte_data(client,
- LM63_REG_ALERT_STATUS) & 0x7F;
-
- data->last_updated = jiffies;
- data->valid = 1;
- }
-
- lm63_update_lut(client);
-
- mutex_unlock(&data->update_lock);
-
- return data;
-}
-
-/*
- * Trip points in the lookup table should be in ascending order for both
- * temperatures and PWM output values.
- */
-static int lm63_lut_looks_bad(struct i2c_client *client)
-{
- struct lm63_data *data = i2c_get_clientdata(client);
- int i;
-
- mutex_lock(&data->update_lock);
- lm63_update_lut(client);
-
- for (i = 1; i < data->lut_size; i++) {
- if (data->pwm1[1 + i - 1] > data->pwm1[1 + i]
- || data->temp8[3 + i - 1] > data->temp8[3 + i]) {
- dev_warn(&client->dev,
- "Lookup table doesn't look sane (check entries %d and %d)\n",
- i, i + 1);
- break;
- }
- }
- mutex_unlock(&data->update_lock);
-
- return i == data->lut_size ? 0 : 1;
-}
-
/*
* Sysfs callback functions and files
*/
@@ -396,16 +294,13 @@ static ssize_t show_pwm1(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "%d\n", pwm);
}
-static ssize_t set_pwm1(struct device *dev, struct device_attribute *devattr,
+static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
const char *buf, size_t count)
{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
- int nr = attr->index;
unsigned long val;
int err;
- u8 reg;
if (!(data->config_fan & 0x20)) /* register is read-only */
return -EPERM;
@@ -414,13 +309,11 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *devattr,
if (err)
return err;
- reg = nr ? LM63_REG_LUT_PWM(nr - 1) : LM63_REG_PWM_VALUE;
val = SENSORS_LIMIT(val, 0, 255);
-
mutex_lock(&data->update_lock);
- data->pwm1[nr] = data->pwm_highres ? val :
+ data->pwm1[0] = data->pwm_highres ? val :
(val * data->pwm1_freq * 2 + 127) / 255;
- i2c_smbus_write_byte_data(client, reg, data->pwm1[nr]);
+ i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1[0]);
mutex_unlock(&data->update_lock);
return count;
}
@@ -432,41 +325,6 @@ static ssize_t show_pwm1_enable(struct device *dev,
return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2);
}
-static ssize_t set_pwm1_enable(struct device *dev,
- struct device_attribute *dummy,
- const char *buf, size_t count)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm63_data *data = i2c_get_clientdata(client);
- unsigned long val;
- int err;
-
- err = kstrtoul(buf, 10, &val);
- if (err)
- return err;
- if (val < 1 || val > 2)
- return -EINVAL;
-
- /*
- * Only let the user switch to automatic mode if the lookup table
- * looks sane.
- */
- if (val == 2 && lm63_lut_looks_bad(client))
- return -EPERM;
-
- mutex_lock(&data->update_lock);
- data->config_fan = i2c_smbus_read_byte_data(client,
- LM63_REG_CONFIG_FAN);
- if (val == 1)
- data->config_fan |= 0x20;
- else
- data->config_fan &= ~0x20;
- i2c_smbus_write_byte_data(client, LM63_REG_CONFIG_FAN,
- data->config_fan);
- mutex_unlock(&data->update_lock);
- return count;
-}
-
/*
* There are 8bit registers for both local(temp1) and remote(temp2) sensor.
* For remote sensor registers temp2_offset has to be considered,
@@ -509,31 +367,23 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
int nr = attr->index;
+ int reg = nr == 2 ? LM63_REG_REMOTE_TCRIT : LM63_REG_LOCAL_HIGH;
long val;
int err;
int temp;
- u8 reg;
err = kstrtol(buf, 10, &val);
if (err)
return err;
mutex_lock(&data->update_lock);
- switch (nr) {
- case 2:
- reg = LM63_REG_REMOTE_TCRIT;
+ if (nr == 2) {
if (data->remote_unsigned)
temp = TEMP8U_TO_REG(val - data->temp2_offset);
else
temp = TEMP8_TO_REG(val - data->temp2_offset);
- break;
- case 1:
- reg = LM63_REG_LOCAL_HIGH;
+ } else {
temp = TEMP8_TO_REG(val);
- break;
- default: /* lookup table */
- reg = LM63_REG_LUT_TEMP(nr - 3);
- temp = lut_temp_to_reg(data, val);
}
data->temp8[nr] = temp;
i2c_smbus_write_byte_data(client, reg, temp);
@@ -763,78 +613,65 @@ static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
set_fan, 1);
static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1, 0);
-static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
- show_pwm1_enable, set_pwm1_enable);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 1);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 3);
+static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, show_pwm1, NULL, 1);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IRUGO,
+ show_lut_temp, NULL, 3);
static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 3);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 2);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 4);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IRUGO, show_pwm1, NULL, 2);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IRUGO,
+ show_lut_temp, NULL, 4);
static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 4);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 3);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 5);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, show_pwm1, NULL, 3);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IRUGO,
+ show_lut_temp, NULL, 5);
static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 5);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 4);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 6);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IRUGO, show_pwm1, NULL, 4);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IRUGO,
+ show_lut_temp, NULL, 6);
static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 6);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 5);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 7);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IRUGO, show_pwm1, NULL, 5);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IRUGO,
+ show_lut_temp, NULL, 7);
static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 7);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 6);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 8);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IRUGO, show_pwm1, NULL, 6);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IRUGO,
+ show_lut_temp, NULL, 8);
static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 8);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 7);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 9);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IRUGO, show_pwm1, NULL, 7);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IRUGO,
+ show_lut_temp, NULL, 9);
static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 9);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 8);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 10);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IRUGO, show_pwm1, NULL, 8);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IRUGO,
+ show_lut_temp, NULL, 10);
static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 10);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point9_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 9);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 11);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point9_pwm, S_IRUGO, show_pwm1, NULL, 9);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp, S_IRUGO,
+ show_lut_temp, NULL, 11);
static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 11);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point10_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 10);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 12);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point10_pwm, S_IRUGO, show_pwm1, NULL, 10);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp, S_IRUGO,
+ show_lut_temp, NULL, 12);
static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 12);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point11_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 11);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 13);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point11_pwm, S_IRUGO, show_pwm1, NULL, 11);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp, S_IRUGO,
+ show_lut_temp, NULL, 13);
static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 13);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point12_pwm, S_IWUSR | S_IRUGO,
- show_pwm1, set_pwm1, 12);
-static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp, S_IWUSR | S_IRUGO,
- show_lut_temp, set_temp8, 14);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point12_pwm, S_IRUGO, show_pwm1, NULL, 12);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp, S_IRUGO,
+ show_lut_temp, NULL, 14);
static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp_hyst, S_IRUGO,
show_lut_temp_hyst, NULL, 14);
@@ -980,25 +817,28 @@ static const struct attribute_group lm63_group_fan1 = {
*/
/* Return 0 if detection is successful, -ENODEV otherwise */
-static int lm63_detect(struct i2c_client *client,
+static int lm63_detect(struct i2c_client *new_client,
struct i2c_board_info *info)
{
- struct i2c_adapter *adapter = client->adapter;
+ struct i2c_adapter *adapter = new_client->adapter;
u8 man_id, chip_id, reg_config1, reg_config2;
u8 reg_alert_status, reg_alert_mask;
- int address = client->addr;
+ int address = new_client->addr;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
- man_id = i2c_smbus_read_byte_data(client, LM63_REG_MAN_ID);
- chip_id = i2c_smbus_read_byte_data(client, LM63_REG_CHIP_ID);
+ man_id = i2c_smbus_read_byte_data(new_client, LM63_REG_MAN_ID);
+ chip_id = i2c_smbus_read_byte_data(new_client, LM63_REG_CHIP_ID);
- reg_config1 = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
- reg_config2 = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG2);
- reg_alert_status = i2c_smbus_read_byte_data(client,
+ reg_config1 = i2c_smbus_read_byte_data(new_client,
+ LM63_REG_CONFIG1);
+ reg_config2 = i2c_smbus_read_byte_data(new_client,
+ LM63_REG_CONFIG2);
+ reg_alert_status = i2c_smbus_read_byte_data(new_client,
LM63_REG_ALERT_STATUS);
- reg_alert_mask = i2c_smbus_read_byte_data(client, LM63_REG_ALERT_MASK);
+ reg_alert_mask = i2c_smbus_read_byte_data(new_client,
+ LM63_REG_ALERT_MASK);
if (man_id != 0x01 /* National Semiconductor */
|| (reg_config1 & 0x18) != 0x00
@@ -1023,6 +863,74 @@ static int lm63_detect(struct i2c_client *client,
return 0;
}
+static int lm63_probe(struct i2c_client *new_client,
+ const struct i2c_device_id *id)
+{
+ struct lm63_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(new_client, data);
+ data->valid = 0;
+ mutex_init(&data->update_lock);
+
+ /* Set the device type */
+ data->kind = id->driver_data;
+ if (data->kind == lm64)
+ data->temp2_offset = 16000;
+
+ /* Initialize chip */
+ lm63_init_client(new_client);
+
+ /* Register sysfs hooks */
+ err = sysfs_create_group(&new_client->dev.kobj, &lm63_group);
+ if (err)
+ goto exit_free;
+ if (data->config & 0x04) { /* tachometer enabled */
+ err = sysfs_create_group(&new_client->dev.kobj,
+ &lm63_group_fan1);
+ if (err)
+ goto exit_remove_files;
+ }
+ if (data->kind == lm96163) {
+ err = device_create_file(&new_client->dev,
+ &dev_attr_temp2_type);
+ if (err)
+ goto exit_remove_files;
+
+ err = sysfs_create_group(&new_client->dev.kobj,
+ &lm63_group_extra_lut);
+ if (err)
+ goto exit_remove_files;
+ }
+
+ data->hwmon_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ goto exit_remove_files;
+ }
+
+ return 0;
+
+exit_remove_files:
+ sysfs_remove_group(&new_client->dev.kobj, &lm63_group);
+ sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1);
+ if (data->kind == lm96163) {
+ device_remove_file(&new_client->dev, &dev_attr_temp2_type);
+ sysfs_remove_group(&new_client->dev.kobj,
+ &lm63_group_extra_lut);
+ }
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
/*
* Ideally we shouldn't have to initialize anything, since the BIOS
* should have taken care of everything
@@ -1102,110 +1010,114 @@ static void lm63_init_client(struct i2c_client *client)
(data->config_fan & 0x20) ? "manual" : "auto");
}
-static int lm63_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int lm63_remove(struct i2c_client *client)
{
- struct lm63_data *data;
- int err;
-
- data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL);
- if (!data) {
- err = -ENOMEM;
- goto exit;
- }
-
- i2c_set_clientdata(client, data);
- data->valid = 0;
- mutex_init(&data->update_lock);
-
- /* Set the device type */
- data->kind = id->driver_data;
- if (data->kind == lm64)
- data->temp2_offset = 16000;
-
- /* Initialize chip */
- lm63_init_client(client);
-
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &lm63_group);
- if (err)
- goto exit_free;
- if (data->config & 0x04) { /* tachometer enabled */
- err = sysfs_create_group(&client->dev.kobj, &lm63_group_fan1);
- if (err)
- goto exit_remove_files;
- }
- if (data->kind == lm96163) {
- err = device_create_file(&client->dev, &dev_attr_temp2_type);
- if (err)
- goto exit_remove_files;
-
- err = sysfs_create_group(&client->dev.kobj,
- &lm63_group_extra_lut);
- if (err)
- goto exit_remove_files;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
+ struct lm63_data *data = i2c_get_clientdata(client);
-exit_remove_files:
+ hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm63_group);
sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
if (data->kind == lm96163) {
device_remove_file(&client->dev, &dev_attr_temp2_type);
sysfs_remove_group(&client->dev.kobj, &lm63_group_extra_lut);
}
-exit_free:
+
kfree(data);
-exit:
- return err;
+ return 0;
}
-static int lm63_remove(struct i2c_client *client)
+static struct lm63_data *lm63_update_device(struct device *dev)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
+ unsigned long next_update;
+ int i;
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &lm63_group);
- sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
- if (data->kind == lm96163) {
- device_remove_file(&client->dev, &dev_attr_temp2_type);
- sysfs_remove_group(&client->dev.kobj, &lm63_group_extra_lut);
+ mutex_lock(&data->update_lock);
+
+ next_update = data->last_updated
+ + msecs_to_jiffies(data->update_interval) + 1;
+
+ if (time_after(jiffies, next_update) || !data->valid) {
+ if (data->config & 0x04) { /* tachometer enabled */
+ /* order matters for fan1_input */
+ data->fan[0] = i2c_smbus_read_byte_data(client,
+ LM63_REG_TACH_COUNT_LSB) & 0xFC;
+ data->fan[0] |= i2c_smbus_read_byte_data(client,
+ LM63_REG_TACH_COUNT_MSB) << 8;
+ data->fan[1] = (i2c_smbus_read_byte_data(client,
+ LM63_REG_TACH_LIMIT_LSB) & 0xFC)
+ | (i2c_smbus_read_byte_data(client,
+ LM63_REG_TACH_LIMIT_MSB) << 8);
+ }
+
+ data->pwm1_freq = i2c_smbus_read_byte_data(client,
+ LM63_REG_PWM_FREQ);
+ if (data->pwm1_freq == 0)
+ data->pwm1_freq = 1;
+ data->pwm1[0] = i2c_smbus_read_byte_data(client,
+ LM63_REG_PWM_VALUE);
+
+ data->temp8[0] = i2c_smbus_read_byte_data(client,
+ LM63_REG_LOCAL_TEMP);
+ data->temp8[1] = i2c_smbus_read_byte_data(client,
+ LM63_REG_LOCAL_HIGH);
+
+ /* order matters for temp2_input */
+ data->temp11[0] = i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_TEMP_MSB) << 8;
+ data->temp11[0] |= i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_TEMP_LSB);
+ data->temp11[1] = (i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_LOW_MSB) << 8)
+ | i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_LOW_LSB);
+ data->temp11[2] = (i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_HIGH_MSB) << 8)
+ | i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_HIGH_LSB);
+ data->temp11[3] = (i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_OFFSET_MSB) << 8)
+ | i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_OFFSET_LSB);
+
+ if (data->kind == lm96163)
+ data->temp11u = (i2c_smbus_read_byte_data(client,
+ LM96163_REG_REMOTE_TEMP_U_MSB) << 8)
+ | i2c_smbus_read_byte_data(client,
+ LM96163_REG_REMOTE_TEMP_U_LSB);
+
+ data->temp8[2] = i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_TCRIT);
+ data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_TCRIT_HYST);
+
+ data->alarms = i2c_smbus_read_byte_data(client,
+ LM63_REG_ALERT_STATUS) & 0x7F;
+
+ data->last_updated = jiffies;
+ data->valid = 1;
}
- kfree(data);
- return 0;
-}
+ if (time_after(jiffies, data->lut_last_updated + 5 * HZ) ||
+ !data->lut_valid) {
+ for (i = 0; i < data->lut_size; i++) {
+ data->pwm1[1 + i] = i2c_smbus_read_byte_data(client,
+ LM63_REG_LUT_PWM(i));
+ data->temp8[3 + i] = i2c_smbus_read_byte_data(client,
+ LM63_REG_LUT_TEMP(i));
+ }
+ data->lut_temp_hyst = i2c_smbus_read_byte_data(client,
+ LM63_REG_LUT_TEMP_HYST);
-/*
- * Driver data (common to all clients)
- */
+ data->lut_last_updated = jiffies;
+ data->lut_valid = 1;
+ }
-static const struct i2c_device_id lm63_id[] = {
- { "lm63", lm63 },
- { "lm64", lm64 },
- { "lm96163", lm96163 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, lm63_id);
+ mutex_unlock(&data->update_lock);
-static struct i2c_driver lm63_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "lm63",
- },
- .probe = lm63_probe,
- .remove = lm63_remove,
- .id_table = lm63_id,
- .detect = lm63_detect,
- .address_list = normal_i2c,
-};
+ return data;
+}
module_i2c_driver(lm63_driver);
diff --git a/trunk/drivers/hwmon/lm90.c b/trunk/drivers/hwmon/lm90.c
index 22b14a68e35e..248f2b40dfaf 100644
--- a/trunk/drivers/hwmon/lm90.c
+++ b/trunk/drivers/hwmon/lm90.c
@@ -57,9 +57,6 @@
* This driver also supports the SA56004 from Philips. This device is
* pin-compatible with the LM86, the ED/EDP parts are also address-compatible.
*
- * This driver also supports the G781 from GMT. This device is compatible
- * with the ADM1032.
- *
* Since the LM90 was the first chipset supported by this driver, most
* comments will refer to this chipset, but are actually general and
* concern all supported chipsets, unless mentioned otherwise.
@@ -110,7 +107,7 @@ static const unsigned short normal_i2c[] = {
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
- max6646, w83l771, max6696, sa56004, g781 };
+ max6646, w83l771, max6696, sa56004 };
/*
* The LM90 registers
@@ -187,7 +184,6 @@ static const struct i2c_device_id lm90_id[] = {
{ "adm1032", adm1032 },
{ "adt7461", adt7461 },
{ "adt7461a", adt7461 },
- { "g781", g781 },
{ "lm90", lm90 },
{ "lm86", lm86 },
{ "lm89", lm86 },
@@ -233,12 +229,6 @@ static const struct lm90_params lm90_params[] = {
.alert_alarms = 0x7c,
.max_convrate = 10,
},
- [g781] = {
- .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
- | LM90_HAVE_BROKEN_ALERT,
- .alert_alarms = 0x7c,
- .max_convrate = 8,
- },
[lm86] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
.alert_alarms = 0x7b,
@@ -318,24 +308,22 @@ struct lm90_data {
/* registers values */
s8 temp8[8]; /* 0: local low limit
- * 1: local high limit
- * 2: local critical limit
- * 3: remote critical limit
- * 4: local emergency limit (max6659 and max6695/96)
- * 5: remote emergency limit (max6659 and max6695/96)
- * 6: remote 2 critical limit (max6695/96 only)
- * 7: remote 2 emergency limit (max6695/96 only)
- */
+ 1: local high limit
+ 2: local critical limit
+ 3: remote critical limit
+ 4: local emergency limit (max6659 and max6695/96)
+ 5: remote emergency limit (max6659 and max6695/96)
+ 6: remote 2 critical limit (max6695/96 only)
+ 7: remote 2 emergency limit (max6695/96 only) */
s16 temp11[8]; /* 0: remote input
- * 1: remote low limit
- * 2: remote high limit
- * 3: remote offset (except max6646, max6657/58/59,
- * and max6695/96)
- * 4: local input
- * 5: remote 2 input (max6695/96 only)
- * 6: remote 2 low limit (max6695/96 only)
- * 7: remote 2 high limit (max6695/96 only)
- */
+ 1: remote low limit
+ 2: remote high limit
+ 3: remote offset (except max6646, max6657/58/59,
+ and max6695/96)
+ 4: local input
+ 5: remote 2 input (max6695/96 only)
+ 6: remote 2 low limit (max6695/96 only)
+ 7: remote 2 high limit (ma6695/96 only) */
u8 temp_hyst;
u16 alarms; /* bitvector (upper 8 bits for max6695/96) */
};
@@ -545,10 +533,8 @@ static struct lm90_data *lm90_update_device(struct device *dev)
data->alarms |= alarms << 8;
}
- /*
- * Re-enable ALERT# output if it was originally enabled and
- * relevant alarms are all clear
- */
+ /* Re-enable ALERT# output if it was originally enabled and
+ * relevant alarms are all clear */
if ((data->config_orig & 0x80) == 0
&& (data->alarms & data->alert_alarms) == 0) {
u8 config;
@@ -1176,10 +1162,8 @@ static int lm90_detect(struct i2c_client *client,
&& (config1 & 0x3F) == 0x00
&& convrate <= 0x0A) {
name = "adm1032";
- /*
- * The ADM1032 supports PEC, but only if combined
- * transactions are not used.
- */
+ /* The ADM1032 supports PEC, but only if combined
+ transactions are not used. */
if (i2c_check_functionality(adapter,
I2C_FUNC_SMBUS_BYTE))
info->flags |= I2C_CLIENT_PEC;
@@ -1299,13 +1283,6 @@ static int lm90_detect(struct i2c_client *client,
&& convrate <= 0x09) {
name = "sa56004";
}
- } else
- if ((address == 0x4C || address == 0x4D)
- && man_id == 0x47) { /* GMT */
- if (chip_id == 0x01 /* G781 */
- && (config1 & 0x3F) == 0x00
- && convrate <= 0x08)
- name = "g781";
}
if (!name) { /* identification failed */
@@ -1336,15 +1313,6 @@ static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data)
sysfs_remove_group(&dev->kobj, &lm90_group);
}
-static void lm90_restore_conf(struct i2c_client *client, struct lm90_data *data)
-{
- /* Restore initial configuration */
- i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
- data->convrate_orig);
- i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
- data->config_orig);
-}
-
static void lm90_init_client(struct i2c_client *client)
{
u8 config, convrate;
@@ -1414,10 +1382,8 @@ static int lm90_probe(struct i2c_client *client,
client->flags &= ~I2C_CLIENT_PEC;
}
- /*
- * Different devices have different alarm bits triggering the
- * ALERT# output
- */
+ /* Different devices have different alarm bits triggering the
+ * ALERT# output */
data->alert_alarms = lm90_params[data->kind].alert_alarms;
/* Set chip capabilities */
@@ -1433,7 +1399,7 @@ static int lm90_probe(struct i2c_client *client,
/* Register sysfs hooks */
err = sysfs_create_group(&dev->kobj, &lm90_group);
if (err)
- goto exit_restore;
+ goto exit_free;
if (client->flags & I2C_CLIENT_PEC) {
err = device_create_file(dev, &dev_attr_pec);
if (err)
@@ -1472,8 +1438,7 @@ static int lm90_probe(struct i2c_client *client,
exit_remove_files:
lm90_remove_files(client, data);
-exit_restore:
- lm90_restore_conf(client, data);
+exit_free:
kfree(data);
exit:
return err;
@@ -1485,7 +1450,12 @@ static int lm90_remove(struct i2c_client *client)
hwmon_device_unregister(data->hwmon_dev);
lm90_remove_files(client, data);
- lm90_restore_conf(client, data);
+
+ /* Restore initial configuration */
+ i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
+ data->convrate_orig);
+ i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
+ data->config_orig);
kfree(data);
return 0;
@@ -1518,11 +1488,9 @@ static void lm90_alert(struct i2c_client *client, unsigned int flag)
dev_warn(&client->dev,
"temp%d out of range, please check!\n", 3);
- /*
- * Disable ALERT# output, because these chips don't implement
- * SMBus alert correctly; they should only hold the alert line
- * low briefly.
- */
+ /* Disable ALERT# output, because these chips don't implement
+ SMBus alert correctly; they should only hold the alert line
+ low briefly. */
if ((data->flags & LM90_HAVE_BROKEN_ALERT)
&& (alarms & data->alert_alarms)) {
dev_dbg(&client->dev, "Disabling ALERT#\n");
diff --git a/trunk/drivers/hwmon/mc13783-adc.c b/trunk/drivers/hwmon/mc13783-adc.c
index 6c6b240a782e..ef65ab56b094 100644
--- a/trunk/drivers/hwmon/mc13783-adc.c
+++ b/trunk/drivers/hwmon/mc13783-adc.c
@@ -1,5 +1,5 @@
/*
- * Driver for the ADC on Freescale Semiconductor MC13783 and MC13892 PMICs.
+ * Driver for the Freescale Semiconductor MC13783 adc.
*
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2009 Sascha Hauer, Pengutronix
@@ -18,7 +18,7 @@
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include
+#include
#include
#include
#include
@@ -28,30 +28,24 @@
#include
#include
-#define DRIVER_NAME "mc13783-adc"
-
-/* platform device id driver data */
-#define MC13783_ADC_16CHANS 1
-#define MC13783_ADC_BPDIV2 2
+#define MC13783_ADC_NAME "mc13783-adc"
struct mc13783_adc_priv {
struct mc13xxx *mc13xxx;
struct device *hwmon_dev;
- char name[10];
};
static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute
*devattr, char *buf)
{
- struct mc13783_adc_priv *priv = dev_get_drvdata(dev);
-
- return sprintf(buf, "%s\n", priv->name);
+ return sprintf(buf, "mc13783_adc\n");
}
static int mc13783_adc_read(struct device *dev,
struct device_attribute *devattr, unsigned int *val)
{
- struct mc13783_adc_priv *priv = dev_get_drvdata(dev);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
unsigned int channel = attr->index;
unsigned int sample[4];
@@ -74,21 +68,16 @@ static ssize_t mc13783_adc_read_bp(struct device *dev,
struct device_attribute *devattr, char *buf)
{
unsigned val;
- struct platform_device *pdev = to_platform_device(dev);
- kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data;
int ret = mc13783_adc_read(dev, devattr, &val);
if (ret)
return ret;
- if (driver_data & MC13783_ADC_BPDIV2)
- val = DIV_ROUND_CLOSEST(val * 9, 2);
- else
- /*
- * BP (channel 2) reports with offset 2.4V to the actual value
- * to fit the input range of the ADC. unit = 2.25mV = 9/4 mV.
- */
- val = DIV_ROUND_CLOSEST(val * 9, 4) + 2400;
+ /*
+ * BP (channel 2) reports with offset 2.4V to the actual value to fit
+ * the input range of the ADC. unit = 2.25mV = 9/4 mV.
+ */
+ val = DIV_ROUND_CLOSEST(val * 9, 4) + 2400;
return sprintf(buf, "%u\n", val);
}
@@ -125,21 +114,12 @@ static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, mc13783_adc_read_gp, NULL, 13);
static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, mc13783_adc_read_gp, NULL, 14);
static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, mc13783_adc_read_gp, NULL, 15);
-static struct attribute *mc13783_attr_base[] = {
+static struct attribute *mc13783_attr[] = {
&dev_attr_name.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
&sensor_dev_attr_in5_input.dev_attr.attr,
&sensor_dev_attr_in6_input.dev_attr.attr,
&sensor_dev_attr_in7_input.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group mc13783_group_base = {
- .attrs = mc13783_attr_base,
-};
-
-/* these are only used if MC13783_ADC_16CHANS is provided in driver data */
-static struct attribute *mc13783_attr_16chans[] = {
&sensor_dev_attr_in8_input.dev_attr.attr,
&sensor_dev_attr_in9_input.dev_attr.attr,
&sensor_dev_attr_in10_input.dev_attr.attr,
@@ -147,8 +127,8 @@ static struct attribute *mc13783_attr_16chans[] = {
NULL
};
-static const struct attribute_group mc13783_group_16chans = {
- .attrs = mc13783_attr_16chans,
+static const struct attribute_group mc13783_group = {
+ .attrs = mc13783_attr,
};
/* last four channels may be occupied by the touchscreen */
@@ -176,37 +156,24 @@ static int __init mc13783_adc_probe(struct platform_device *pdev)
{
struct mc13783_adc_priv *priv;
int ret;
- const struct platform_device_id *id = platform_get_device_id(pdev);
- char *dash;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
- snprintf(priv->name, ARRAY_SIZE(priv->name), "%s", id->name);
- dash = strchr(priv->name, '-');
- if (dash)
- *dash = '\0';
platform_set_drvdata(pdev, priv);
/* Register sysfs hooks */
- ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_base);
+ ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group);
if (ret)
- goto out_err_create_base;
-
- if (id->driver_data & MC13783_ADC_16CHANS) {
- ret = sysfs_create_group(&pdev->dev.kobj,
- &mc13783_group_16chans);
- if (ret)
- goto out_err_create_16chans;
- }
+ goto out_err_create1;
if (!mc13783_adc_use_touchscreen(pdev)) {
ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts);
if (ret)
- goto out_err_create_ts;
+ goto out_err_create2;
}
priv->hwmon_dev = hwmon_device_register(&pdev->dev);
@@ -217,20 +184,17 @@ static int __init mc13783_adc_probe(struct platform_device *pdev)
goto out_err_register;
}
+
return 0;
out_err_register:
if (!mc13783_adc_use_touchscreen(pdev))
sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts);
-out_err_create_ts:
+out_err_create2:
- if (id->driver_data & MC13783_ADC_16CHANS)
- sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_16chans);
-out_err_create_16chans:
-
- sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_base);
-out_err_create_base:
+ sysfs_remove_group(&pdev->dev.kobj, &mc13783_group);
+out_err_create1:
platform_set_drvdata(pdev, NULL);
kfree(priv);
@@ -241,17 +205,13 @@ static int __init mc13783_adc_probe(struct platform_device *pdev)
static int __devexit mc13783_adc_remove(struct platform_device *pdev)
{
struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
- kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data;
hwmon_device_unregister(priv->hwmon_dev);
if (!mc13783_adc_use_touchscreen(pdev))
sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts);
- if (driver_data & MC13783_ADC_16CHANS)
- sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_16chans);
-
- sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_base);
+ sysfs_remove_group(&pdev->dev.kobj, &mc13783_group);
platform_set_drvdata(pdev, NULL);
kfree(priv);
@@ -259,26 +219,12 @@ static int __devexit mc13783_adc_remove(struct platform_device *pdev)
return 0;
}
-static const struct platform_device_id mc13783_adc_idtable[] = {
- {
- .name = "mc13783-adc",
- .driver_data = MC13783_ADC_16CHANS,
- }, {
- .name = "mc13892-adc",
- .driver_data = MC13783_ADC_BPDIV2,
- }, {
- /* sentinel */
- }
-};
-MODULE_DEVICE_TABLE(platform, mc13783_adc_idtable);
-
static struct platform_driver mc13783_adc_driver = {
- .remove = __devexit_p(mc13783_adc_remove),
+ .remove = __devexit_p(mc13783_adc_remove),
.driver = {
.owner = THIS_MODULE,
- .name = DRIVER_NAME,
+ .name = MC13783_ADC_NAME,
},
- .id_table = mc13783_adc_idtable,
};
static int __init mc13783_adc_init(void)
@@ -297,3 +243,4 @@ module_exit(mc13783_adc_exit);
MODULE_DESCRIPTION("MC13783 ADC driver");
MODULE_AUTHOR("Luotao Fu ");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" MC13783_ADC_NAME);
diff --git a/trunk/drivers/hwmon/mcp3021.c b/trunk/drivers/hwmon/mcp3021.c
deleted file mode 100644
index d0afc0cd3ff4..000000000000
--- a/trunk/drivers/hwmon/mcp3021.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * mcp3021.c - driver for the Microchip MCP3021 chip
- *
- * Copyright (C) 2008-2009, 2012 Freescale Semiconductor, Inc.
- * Author: Mingkai Hu
- *
- * This driver export the value of analog input voltage to sysfs, the
- * voltage unit is mV. Through the sysfs interface, lm-sensors tool
- * can also display the input voltage.
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* Vdd info */
-#define MCP3021_VDD_MAX 5500
-#define MCP3021_VDD_MIN 2700
-#define MCP3021_VDD_REF 3300
-
-/* output format */
-#define MCP3021_SAR_SHIFT 2
-#define MCP3021_SAR_MASK 0x3ff
-
-#define MCP3021_OUTPUT_RES 10 /* 10-bit resolution */
-#define MCP3021_OUTPUT_SCALE 4
-
-/*
- * Client data (each client gets its own)
- */
-struct mcp3021_data {
- struct device *hwmon_dev;
- u32 vdd; /* device power supply */
-};
-
-static int mcp3021_read16(struct i2c_client *client)
-{
- int ret;
- u16 reg;
- __be16 buf;
-
- ret = i2c_master_recv(client, (char *)&buf, 2);
- if (ret < 0)
- return ret;
- if (ret != 2)
- return -EIO;
-
- /* The output code of the MCP3021 is transmitted with MSB first. */
- reg = be16_to_cpu(buf);
-
- /*
- * The ten-bit output code is composed of the lower 4-bit of the
- * first byte and the upper 6-bit of the second byte.
- */
- reg = (reg >> MCP3021_SAR_SHIFT) & MCP3021_SAR_MASK;
-
- return reg;
-}
-
-static inline u16 volts_from_reg(u16 vdd, u16 val)
-{
- if (val == 0)
- return 0;
-
- val = val * MCP3021_OUTPUT_SCALE - MCP3021_OUTPUT_SCALE / 2;
-
- return val * DIV_ROUND_CLOSEST(vdd,
- (1 << MCP3021_OUTPUT_RES) * MCP3021_OUTPUT_SCALE);
-}
-
-static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct mcp3021_data *data = i2c_get_clientdata(client);
- int reg, in_input;
-
- reg = mcp3021_read16(client);
- if (reg < 0)
- return reg;
-
- in_input = volts_from_reg(data->vdd, reg);
- return sprintf(buf, "%d\n", in_input);
-}
-
-static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input, NULL);
-
-static int mcp3021_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- int err;
- struct mcp3021_data *data = NULL;
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
- return -ENODEV;
-
- data = kzalloc(sizeof(struct mcp3021_data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- i2c_set_clientdata(client, data);
-
- if (client->dev.platform_data) {
- data->vdd = *(u32 *)client->dev.platform_data;
- if (data->vdd > MCP3021_VDD_MAX ||
- data->vdd < MCP3021_VDD_MIN) {
- err = -EINVAL;
- goto exit_free;
- }
- } else
- data->vdd = MCP3021_VDD_REF;
-
- err = sysfs_create_file(&client->dev.kobj, &dev_attr_in0_input.attr);
- if (err)
- goto exit_free;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- sysfs_remove_file(&client->dev.kobj, &dev_attr_in0_input.attr);
-exit_free:
- kfree(data);
- return err;
-}
-
-static int mcp3021_remove(struct i2c_client *client)
-{
- struct mcp3021_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_file(&client->dev.kobj, &dev_attr_in0_input.attr);
- kfree(data);
-
- return 0;
-}
-
-static const struct i2c_device_id mcp3021_id[] = {
- { "mcp3021", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, mcp3021_id);
-
-static struct i2c_driver mcp3021_driver = {
- .driver = {
- .name = "mcp3021",
- },
- .probe = mcp3021_probe,
- .remove = mcp3021_remove,
- .id_table = mcp3021_id,
-};
-
-module_i2c_driver(mcp3021_driver);
-
-MODULE_AUTHOR("Mingkai Hu ");
-MODULE_DESCRIPTION("Microchip MCP3021 driver");
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/hwmon/w83795.c b/trunk/drivers/hwmon/w83795.c
index d887cb3b72e8..deb12c982800 100644
--- a/trunk/drivers/hwmon/w83795.c
+++ b/trunk/drivers/hwmon/w83795.c
@@ -72,10 +72,8 @@ MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
#define TEMP_CRIT_HYST 2
#define TEMP_WARN 3
#define TEMP_WARN_HYST 4
-/*
- * only crit and crit_hyst affect real-time alarm status
- * current crit crit_hyst warn warn_hyst
- */
+/* only crit and crit_hyst affect real-time alarm status
+ * current crit crit_hyst warn warn_hyst */
static const u16 W83795_REG_TEMP[][5] = {
{0x21, 0x96, 0x97, 0x98, 0x99}, /* TD1/TR1 */
{0x22, 0x9a, 0x9b, 0x9c, 0x9d}, /* TD2/TR2 */
@@ -356,34 +354,26 @@ struct w83795_data {
u8 temp_mode; /* Bit vector, 0 = TR, 1 = TD */
u8 temp_src[3]; /* Register value */
- u8 enable_dts; /*
- * Enable PECI and SB-TSI,
+ u8 enable_dts; /* Enable PECI and SB-TSI,
* bit 0: =1 enable, =0 disable,
- * bit 1: =1 AMD SB-TSI, =0 Intel PECI
- */
+ * bit 1: =1 AMD SB-TSI, =0 Intel PECI */
u8 has_dts; /* Enable monitor DTS temp */
s8 dts[8]; /* Register value */
u8 dts_read_vrlsb[8]; /* Register value */
s8 dts_ext[4]; /* Register value */
- u8 has_pwm; /*
- * 795g supports 8 pwm, 795adg only supports 2,
+ u8 has_pwm; /* 795g supports 8 pwm, 795adg only supports 2,
* no config register, only affected by chip
- * type
- */
- u8 pwm[8][5]; /*
- * Register value, output, freq, start,
- * non stop, stop time
- */
+ * type */
+ u8 pwm[8][5]; /* Register value, output, freq, start,
+ * non stop, stop time */
u16 clkin; /* CLKIN frequency in kHz */
u8 pwm_fcms[2]; /* Register value */
u8 pwm_tfmr[6]; /* Register value */
u8 pwm_fomc; /* Register value */
- u16 target_speed[8]; /*
- * Register value, target speed for speed
- * cruise
- */
+ u16 target_speed[8]; /* Register value, target speed for speed
+ * cruise */
u8 tol_speed; /* tolerance of target speed */
u8 pwm_temp[6][4]; /* TTTI, CTFS, HCT, HOT */
u8 sf4_reg[6][2][7]; /* 6 temp, temp/dcpwm, 7 registers */
@@ -492,10 +482,8 @@ static void w83795_update_limits(struct i2c_client *client)
/* Read the fan limits */
lsb = 0; /* Silent false gcc warning */
for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
- /*
- * Each register contains LSB for 2 fans, but we want to
- * read it only once to save time
- */
+ /* Each register contains LSB for 2 fans, but we want to
+ * read it only once to save time */
if ((i & 1) == 0 && (data->has_fan & (3 << i)))
lsb = w83795_read(client, W83795_REG_FAN_MIN_LSB(i));
@@ -677,11 +665,9 @@ static struct w83795_data *w83795_update_device(struct device *dev)
w83795_read(client, W83795_REG_PWM(i, PWM_OUTPUT));
}
- /*
- * Update intrusion and alarms
+ /* Update intrusion and alarms
* It is important to read intrusion first, because reading from
- * register SMI STS6 clears the interrupt status temporarily.
- */
+ * register SMI STS6 clears the interrupt status temporarily. */
tmp = w83795_read(client, W83795_REG_ALARM_CTRL);
/* Switch to interrupt status for intrusion if needed */
if (tmp & ALARM_CTRL_RTSACS)
@@ -943,14 +929,6 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
if (val < 1 || val > 2)
return -EINVAL;
-#ifndef CONFIG_SENSORS_W83795_FANCTRL
- if (val > 1) {
- dev_warn(dev, "Automatic fan speed control support disabled\n");
- dev_warn(dev, "Build with CONFIG_SENSORS_W83795_FANCTRL=y if you want it\n");
- return -EOPNOTSUPP;
- }
-#endif
-
mutex_lock(&data->update_lock);
switch (val) {
case 1:
@@ -1617,10 +1595,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
#define NOT_USED -1
-/*
- * Don't change the attribute order, _max, _min and _beep are accessed by index
- * somewhere else in the code
- */
+/* Don't change the attribute order, _max, _min and _beep are accessed by index
+ * somewhere else in the code */
#define SENSOR_ATTR_IN(index) { \
SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL, \
IN_READ, index), \
@@ -1634,10 +1610,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
show_alarm_beep, store_beep, BEEP_ENABLE, \
index + ((index > 14) ? 1 : 0)) }
-/*
- * Don't change the attribute order, _beep is accessed by index
- * somewhere else in the code
- */
+/* Don't change the attribute order, _beep is accessed by index
+ * somewhere else in the code */
#define SENSOR_ATTR_FAN(index) { \
SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan, \
NULL, FAN_INPUT, index - 1), \
@@ -1651,25 +1625,23 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
#define SENSOR_ATTR_PWM(index) { \
SENSOR_ATTR_2(pwm##index, S_IWUSR | S_IRUGO, show_pwm, \
store_pwm, PWM_OUTPUT, index - 1), \
- SENSOR_ATTR_2(pwm##index##_enable, S_IWUSR | S_IRUGO, \
- show_pwm_enable, store_pwm_enable, NOT_USED, index - 1), \
- SENSOR_ATTR_2(pwm##index##_mode, S_IRUGO, \
- show_pwm_mode, NULL, NOT_USED, index - 1), \
- SENSOR_ATTR_2(pwm##index##_freq, S_IWUSR | S_IRUGO, \
- show_pwm, store_pwm, PWM_FREQ, index - 1), \
SENSOR_ATTR_2(pwm##index##_nonstop, S_IWUSR | S_IRUGO, \
show_pwm, store_pwm, PWM_NONSTOP, index - 1), \
SENSOR_ATTR_2(pwm##index##_start, S_IWUSR | S_IRUGO, \
show_pwm, store_pwm, PWM_START, index - 1), \
SENSOR_ATTR_2(pwm##index##_stop_time, S_IWUSR | S_IRUGO, \
show_pwm, store_pwm, PWM_STOP_TIME, index - 1), \
+ SENSOR_ATTR_2(pwm##index##_freq, S_IWUSR | S_IRUGO, \
+ show_pwm, store_pwm, PWM_FREQ, index - 1), \
+ SENSOR_ATTR_2(pwm##index##_enable, S_IWUSR | S_IRUGO, \
+ show_pwm_enable, store_pwm_enable, NOT_USED, index - 1), \
+ SENSOR_ATTR_2(pwm##index##_mode, S_IRUGO, \
+ show_pwm_mode, NULL, NOT_USED, index - 1), \
SENSOR_ATTR_2(fan##index##_target, S_IWUSR | S_IRUGO, \
show_fanin, store_fanin, FANIN_TARGET, index - 1) }
-/*
- * Don't change the attribute order, _beep is accessed by index
- * somewhere else in the code
- */
+/* Don't change the attribute order, _beep is accessed by index
+ * somewhere else in the code */
#define SENSOR_ATTR_DTS(index) { \
SENSOR_ATTR_2(temp##index##_type, S_IRUGO , \
show_dts_mode, NULL, NOT_USED, index - 7), \
@@ -1688,10 +1660,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \
show_alarm_beep, store_beep, BEEP_ENABLE, index + 17) }
-/*
- * Don't change the attribute order, _beep is accessed by index
- * somewhere else in the code
- */
+/* Don't change the attribute order, _beep is accessed by index
+ * somewhere else in the code */
#define SENSOR_ATTR_TEMP(index) { \
SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \
show_temp_mode, store_temp_mode, NOT_USED, index - 1), \
@@ -1897,10 +1867,8 @@ static int w83795_get_device_id(struct i2c_client *client)
device_id = i2c_smbus_read_byte_data(client, W83795_REG_DEVICEID);
- /*
- * Special case for rev. A chips; can't be checked first because later
- * revisions emulate this for compatibility
- */
+ /* Special case for rev. A chips; can't be checked first because later
+ revisions emulate this for compatibility */
if (device_id < 0 || (device_id & 0xf0) != 0x50) {
int alt_id;
@@ -1952,10 +1920,8 @@ static int w83795_detect(struct i2c_client *client,
return -ENODEV;
}
- /*
- * If Nuvoton chip, address of chip and W83795_REG_I2C_ADDR
- * should match
- */
+ /* If Nuvoton chip, address of chip and W83795_REG_I2C_ADDR
+ should match */
if ((bank & 0x07) == 0) {
i2c_addr = i2c_smbus_read_byte_data(client,
W83795_REG_I2C_ADDR);
@@ -1967,12 +1933,10 @@ static int w83795_detect(struct i2c_client *client,
}
}
- /*
- * Check 795 chip type: 795G or 795ADG
- * Usually we don't write to chips during detection, but here we don't
- * quite have the choice; hopefully it's OK, we are about to return
- * success anyway
- */
+ /* Check 795 chip type: 795G or 795ADG
+ Usually we don't write to chips during detection, but here we don't
+ quite have the choice; hopefully it's OK, we are about to return
+ success anyway */
if ((bank & 0x07) != 0)
i2c_smbus_write_byte_data(client, W83795_REG_BANKSEL,
bank & ~0x07);
@@ -1989,14 +1953,6 @@ static int w83795_detect(struct i2c_client *client,
return 0;
}
-#ifdef CONFIG_SENSORS_W83795_FANCTRL
-#define NUM_PWM_ATTRIBUTES ARRAY_SIZE(w83795_pwm[0])
-#define NUM_TEMP_ATTRIBUTES ARRAY_SIZE(w83795_temp[0])
-#else
-#define NUM_PWM_ATTRIBUTES 4
-#define NUM_TEMP_ATTRIBUTES 8
-#endif
-
static int w83795_handle_files(struct device *dev, int (*fn)(struct device *,
const struct device_attribute *))
{
@@ -2050,18 +2006,24 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *,
}
}
+#ifdef CONFIG_SENSORS_W83795_FANCTRL
for (i = 0; i < data->has_pwm; i++) {
- for (j = 0; j < NUM_PWM_ATTRIBUTES; j++) {
+ for (j = 0; j < ARRAY_SIZE(w83795_pwm[0]); j++) {
err = fn(dev, &w83795_pwm[i][j].dev_attr);
if (err)
return err;
}
}
+#endif
for (i = 0; i < ARRAY_SIZE(w83795_temp); i++) {
if (!(data->has_temp & (1 << i)))
continue;
- for (j = 0; j < NUM_TEMP_ATTRIBUTES; j++) {
+#ifdef CONFIG_SENSORS_W83795_FANCTRL
+ for (j = 0; j < ARRAY_SIZE(w83795_temp[0]); j++) {
+#else
+ for (j = 0; j < 8; j++) {
+#endif
if (j == 7 && !data->enable_beep)
continue;
err = fn(dev, &w83795_temp[i][j].dev_attr);
@@ -2221,10 +2183,8 @@ static int w83795_probe(struct i2c_client *client,
/* The W83795G has a dedicated BEEP pin */
data->enable_beep = 1;
} else {
- /*
- * The W83795ADG has a shared pin for OVT# and BEEP, so you
- * can't have both
- */
+ /* The W83795ADG has a shared pin for OVT# and BEEP, so you
+ * can't have both */
tmp = w83795_read(client, W83795_REG_OVT_CFG);
if ((tmp & OVT_CFG_SEL) == 0)
data->enable_beep = 1;
diff --git a/trunk/drivers/i2c/busses/Kconfig b/trunk/drivers/i2c/busses/Kconfig
index 71c1b0a7535c..3101dd59e379 100644
--- a/trunk/drivers/i2c/busses/Kconfig
+++ b/trunk/drivers/i2c/busses/Kconfig
@@ -369,21 +369,6 @@ config I2C_DESIGNWARE_PCI
This driver can also be built as a module. If so, the module
will be called i2c-designware-pci.
-config I2C_EG20T
- tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
- depends on PCI
- help
- This driver is for PCH(Platform controller Hub) I2C of EG20T which
- is an IOH(Input/Output Hub) for x86 embedded processor.
- This driver can access PCH I2C bus device.
-
- This driver also can be used for LAPIS Semiconductor IOH(Input/
- Output Hub), ML7213, ML7223 and ML7831.
- ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is
- for MP(Media Phone) use and ML7831 IOH is for general purpose use.
- ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
- ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
-
config I2C_GPIO
tristate "GPIO-based bitbanging I2C"
depends on GENERIC_GPIO
@@ -645,16 +630,6 @@ config I2C_SIMTEC
This driver can also be built as a module. If so, the module
will be called i2c-simtec.
-config I2C_SIRF
- tristate "CSR SiRFprimaII I2C interface"
- depends on ARCH_PRIMA2
- help
- If you say yes to this option, support will be included for the
- CSR SiRFprimaII I2C interface.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-sirf.
-
config I2C_STU300
tristate "ST Microelectronics DDC I2C interface"
depends on MACH_U300
@@ -706,15 +681,20 @@ config I2C_XILINX
This driver can also be built as a module. If so, the module
will be called xilinx_i2c.
-config I2C_XLR
- tristate "XLR I2C support"
- depends on CPU_XLR
+config I2C_EG20T
+ tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
+ depends on PCI
help
- This driver enables support for the on-chip I2C interface of
- the Netlogic XLR/XLS MIPS processors.
+ This driver is for PCH(Platform controller Hub) I2C of EG20T which
+ is an IOH(Input/Output Hub) for x86 embedded processor.
+ This driver can access PCH I2C bus device.
- This driver can also be built as a module. If so, the module
- will be called i2c-xlr.
+ This driver also can be used for LAPIS Semiconductor IOH(Input/
+ Output Hub), ML7213, ML7223 and ML7831.
+ ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is
+ for MP(Media Phone) use and ML7831 IOH is for general purpose use.
+ ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+ ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
comment "External I2C/SMBus adapter drivers"
diff --git a/trunk/drivers/i2c/busses/Makefile b/trunk/drivers/i2c/busses/Makefile
index 569567b0d027..fba6da60aa0e 100644
--- a/trunk/drivers/i2c/busses/Makefile
+++ b/trunk/drivers/i2c/busses/Makefile
@@ -37,7 +37,6 @@ obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o
i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o
i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
-obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
@@ -64,13 +63,12 @@ obj-$(CONFIG_I2C_S6000) += i2c-s6000.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
-obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
-obj-$(CONFIG_I2C_XLR) += i2c-xlr.o
+obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o
# External I2C/SMBus adapter drivers
obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o
diff --git a/trunk/drivers/i2c/busses/i2c-designware-platdrv.c b/trunk/drivers/i2c/busses/i2c-designware-platdrv.c
index 4ba589ab8614..5244c4724df7 100644
--- a/trunk/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/trunk/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -214,7 +214,7 @@ static int __init dw_i2c_init_driver(void)
{
return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
}
-subsys_initcall(dw_i2c_init_driver);
+module_init(dw_i2c_init_driver);
static void __exit dw_i2c_exit_driver(void)
{
diff --git a/trunk/drivers/i2c/busses/i2c-eg20t.c b/trunk/drivers/i2c/busses/i2c-eg20t.c
index f086131cb1c7..ca8877641040 100644
--- a/trunk/drivers/i2c/busses/i2c-eg20t.c
+++ b/trunk/drivers/i2c/busses/i2c-eg20t.c
@@ -271,36 +271,30 @@ static inline bool ktime_lt(const ktime_t cmp1, const ktime_t cmp2)
/**
* pch_i2c_wait_for_bus_idle() - check the status of bus.
* @adap: Pointer to struct i2c_algo_pch_data.
- * @timeout: waiting time counter (ms).
+ * @timeout: waiting time counter (us).
*/
static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
s32 timeout)
{
void __iomem *p = adap->pch_base_address;
- int schedule = 0;
- unsigned long end = jiffies + msecs_to_jiffies(timeout);
-
- while (ioread32(p + PCH_I2CSR) & I2CMBB_BIT) {
- if (time_after(jiffies, end)) {
- pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
- pch_err(adap, "%s: Timeout Error.return%d\n",
- __func__, -ETIME);
- pch_i2c_init(adap);
+ ktime_t ns_val;
- return -ETIME;
- }
+ if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+ return 0;
- if (!schedule)
- /* Retry after some usecs */
- udelay(5);
- else
- /* Wait a bit more without consuming CPU */
- usleep_range(20, 1000);
+ /* MAX timeout value is timeout*1000*1000nsec */
+ ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
+ do {
+ msleep(20);
+ if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+ return 0;
+ } while (ktime_lt(ktime_get(), ns_val));
- schedule = 1;
- }
+ pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
+ pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
+ pch_i2c_init(adap);
- return 0;
+ return -ETIME;
}
/**
@@ -784,6 +778,8 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *pmsg;
u32 i = 0;
u32 status;
+ u32 msglen;
+ u32 subaddrlen;
s32 ret;
struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
@@ -808,6 +804,12 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
status = pmsg->flags;
pch_dbg(adap,
"After invoking I2C_MODE_SEL :flag= 0x%x\n", status);
+ /* calculate sub address length and message length */
+ /* these are applicable only for buffer mode */
+ subaddrlen = pmsg->buf[0];
+ /* calculate actual message length excluding
+ * the sub address fields */
+ msglen = (pmsg->len) - (subaddrlen + 1);
if ((status & (I2C_M_RD)) != false) {
ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
diff --git a/trunk/drivers/i2c/busses/i2c-imx.c b/trunk/drivers/i2c/busses/i2c-imx.c
index 124d9c594f40..58832e578fff 100644
--- a/trunk/drivers/i2c/busses/i2c-imx.c
+++ b/trunk/drivers/i2c/busses/i2c-imx.c
@@ -149,6 +149,11 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
break;
if (!for_busy && !(temp & I2SR_IBB))
break;
+ if (signal_pending(current)) {
+ dev_dbg(&i2c_imx->adapter.dev,
+ "<%s> I2C Interrupted\n", __func__);
+ return -EINTR;
+ }
if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> I2C bus is busy\n", __func__);
diff --git a/trunk/drivers/i2c/busses/i2c-mpc.c b/trunk/drivers/i2c/busses/i2c-mpc.c
index 206caacd30d7..a8ebb84e23f9 100644
--- a/trunk/drivers/i2c/busses/i2c-mpc.c
+++ b/trunk/drivers/i2c/busses/i2c-mpc.c
@@ -454,7 +454,7 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
}
static int mpc_read(struct mpc_i2c *i2c, int target,
- u8 *data, int length, int restart, bool recv_len)
+ u8 *data, int length, int restart)
{
unsigned timeout = i2c->adap.timeout;
int i, result;
@@ -470,7 +470,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
return result;
if (length) {
- if (length == 1 && !recv_len)
+ if (length == 1)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
else
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA);
@@ -479,46 +479,17 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
}
for (i = 0; i < length; i++) {
- u8 byte;
-
result = i2c_wait(i2c, timeout, 0);
if (result < 0)
return result;
- /*
- * For block reads, we have to know the total length (1st byte)
- * before we can determine if we are done.
- */
- if (i || !recv_len) {
- /* Generate txack on next to last byte */
- if (i == length - 2)
- writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
- | CCR_TXAK);
- /* Do not generate stop on last byte */
- if (i == length - 1)
- writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
- | CCR_MTX);
- }
-
- byte = readb(i2c->base + MPC_I2C_DR);
-
- /*
- * Adjust length if first received byte is length.
- * The length is 1 length byte plus actually data length
- */
- if (i == 0 && recv_len) {
- if (byte == 0 || byte > I2C_SMBUS_BLOCK_MAX)
- return -EPROTO;
- length += byte;
- /*
- * For block reads, generate txack here if data length
- * is 1 byte (total length is 2 bytes).
- */
- if (length == 2)
- writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
- | CCR_TXAK);
- }
- data[i] = byte;
+ /* Generate txack on next to last byte */
+ if (i == length - 2)
+ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
+ /* Do not generate stop on last byte */
+ if (i == length - 1)
+ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX);
+ data[i] = readb(i2c->base + MPC_I2C_DR);
}
return length;
@@ -561,17 +532,12 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
"Doing %s %d bytes to 0x%02x - %d of %d messages\n",
pmsg->flags & I2C_M_RD ? "read" : "write",
pmsg->len, pmsg->addr, i + 1, num);
- if (pmsg->flags & I2C_M_RD) {
- bool recv_len = pmsg->flags & I2C_M_RECV_LEN;
-
- ret = mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i,
- recv_len);
- if (recv_len && ret > 0)
- pmsg->len = ret;
- } else {
+ if (pmsg->flags & I2C_M_RD)
+ ret =
+ mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
+ else
ret =
mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
- }
}
mpc_i2c_stop(i2c);
return (ret < 0) ? ret : num;
@@ -579,8 +545,7 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
static u32 mpc_functionality(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
- | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static const struct i2c_algorithm mpc_algo = {
diff --git a/trunk/drivers/i2c/busses/i2c-s3c2410.c b/trunk/drivers/i2c/busses/i2c-s3c2410.c
index 737f7218a32c..4c1718081685 100644
--- a/trunk/drivers/i2c/busses/i2c-s3c2410.c
+++ b/trunk/drivers/i2c/busses/i2c-s3c2410.c
@@ -31,7 +31,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -565,7 +564,6 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
int retry;
int ret;
- pm_runtime_get_sync(&adap->dev);
clk_enable(i2c->clk);
for (retry = 0; retry < adap->retries; retry++) {
@@ -574,7 +572,6 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
if (ret != -EAGAIN) {
clk_disable(i2c->clk);
- pm_runtime_put_sync(&adap->dev);
return ret;
}
@@ -584,7 +581,6 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
}
clk_disable(i2c->clk);
- pm_runtime_put_sync(&adap->dev);
return -EREMOTEIO;
}
@@ -894,7 +890,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
}
}
- i2c = devm_kzalloc(&pdev->dev, sizeof(struct s3c24xx_i2c), GFP_KERNEL);
+ i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
if (!i2c) {
dev_err(&pdev->dev, "no memory for state\n");
return -ENOMEM;
@@ -1017,9 +1013,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
of_i2c_register_devices(&i2c->adap);
platform_set_drvdata(pdev, i2c);
- pm_runtime_enable(&pdev->dev);
- pm_runtime_enable(&i2c->adap.dev);
-
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
clk_disable(i2c->clk);
return 0;
@@ -1042,6 +1035,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
clk_put(i2c->clk);
err_noclk:
+ kfree(i2c);
return ret;
}
@@ -1054,9 +1048,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
{
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
- pm_runtime_disable(&i2c->adap.dev);
- pm_runtime_disable(&pdev->dev);
-
s3c24xx_i2c_deregister_cpufreq(i2c);
i2c_del_adapter(&i2c->adap);
@@ -1070,6 +1061,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
release_resource(i2c->ioarea);
s3c24xx_i2c_dt_gpio_free(i2c);
kfree(i2c->ioarea);
+ kfree(i2c);
return 0;
}
diff --git a/trunk/drivers/i2c/busses/i2c-sirf.c b/trunk/drivers/i2c/busses/i2c-sirf.c
deleted file mode 100644
index 5574a47792fb..000000000000
--- a/trunk/drivers/i2c/busses/i2c-sirf.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * I2C bus driver for CSR SiRFprimaII
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define SIRFSOC_I2C_CLK_CTRL 0x00
-#define SIRFSOC_I2C_STATUS 0x0C
-#define SIRFSOC_I2C_CTRL 0x10
-#define SIRFSOC_I2C_IO_CTRL 0x14
-#define SIRFSOC_I2C_SDA_DELAY 0x18
-#define SIRFSOC_I2C_CMD_START 0x1C
-#define SIRFSOC_I2C_CMD_BUF 0x30
-#define SIRFSOC_I2C_DATA_BUF 0x80
-
-#define SIRFSOC_I2C_CMD_BUF_MAX 16
-#define SIRFSOC_I2C_DATA_BUF_MAX 16
-
-#define SIRFSOC_I2C_CMD(x) (SIRFSOC_I2C_CMD_BUF + (x)*0x04)
-#define SIRFSOC_I2C_DATA_MASK(x) (0xFF<<(((x)&3)*8))
-#define SIRFSOC_I2C_DATA_SHIFT(x) (((x)&3)*8)
-
-#define SIRFSOC_I2C_DIV_MASK (0xFFFF)
-
-/* I2C status flags */
-#define SIRFSOC_I2C_STAT_BUSY BIT(0)
-#define SIRFSOC_I2C_STAT_TIP BIT(1)
-#define SIRFSOC_I2C_STAT_NACK BIT(2)
-#define SIRFSOC_I2C_STAT_TR_INT BIT(4)
-#define SIRFSOC_I2C_STAT_STOP BIT(6)
-#define SIRFSOC_I2C_STAT_CMD_DONE BIT(8)
-#define SIRFSOC_I2C_STAT_ERR BIT(9)
-#define SIRFSOC_I2C_CMD_INDEX (0x1F<<16)
-
-/* I2C control flags */
-#define SIRFSOC_I2C_RESET BIT(0)
-#define SIRFSOC_I2C_CORE_EN BIT(1)
-#define SIRFSOC_I2C_MASTER_MODE BIT(2)
-#define SIRFSOC_I2C_CMD_DONE_EN BIT(11)
-#define SIRFSOC_I2C_ERR_INT_EN BIT(12)
-
-#define SIRFSOC_I2C_SDA_DELAY_MASK (0xFF)
-#define SIRFSOC_I2C_SCLF_FILTER (3<<8)
-
-#define SIRFSOC_I2C_START_CMD BIT(0)
-
-#define SIRFSOC_I2C_CMD_RP(x) ((x)&0x7)
-#define SIRFSOC_I2C_NACK BIT(3)
-#define SIRFSOC_I2C_WRITE BIT(4)
-#define SIRFSOC_I2C_READ BIT(5)
-#define SIRFSOC_I2C_STOP BIT(6)
-#define SIRFSOC_I2C_START BIT(7)
-
-#define SIRFSOC_I2C_DEFAULT_SPEED 100000
-
-struct sirfsoc_i2c {
- void __iomem *base;
- struct clk *clk;
- u32 cmd_ptr; /* Current position in CMD buffer */
- u8 *buf; /* Buffer passed by user */
- u32 msg_len; /* Message length */
- u32 finished_len; /* number of bytes read/written */
- u32 read_cmd_len; /* number of read cmd sent */
- int msg_read; /* 1 indicates a read message */
- int err_status; /* 1 indicates an error on bus */
-
- u32 sda_delay; /* For suspend/resume */
- u32 clk_div;
- int last; /* Last message in transfer, STOP cmd can be sent */
-
- struct completion done; /* indicates completion of message transfer */
- struct i2c_adapter adapter;
-};
-
-static void i2c_sirfsoc_read_data(struct sirfsoc_i2c *siic)
-{
- u32 data = 0;
- int i;
-
- for (i = 0; i < siic->read_cmd_len; i++) {
- if (!(i & 0x3))
- data = readl(siic->base + SIRFSOC_I2C_DATA_BUF + i);
- siic->buf[siic->finished_len++] =
- (u8)((data & SIRFSOC_I2C_DATA_MASK(i)) >>
- SIRFSOC_I2C_DATA_SHIFT(i));
- }
-}
-
-static void i2c_sirfsoc_queue_cmd(struct sirfsoc_i2c *siic)
-{
- u32 regval;
- int i = 0;
-
- if (siic->msg_read) {
- while (((siic->finished_len + i) < siic->msg_len)
- && (siic->cmd_ptr < SIRFSOC_I2C_CMD_BUF_MAX)) {
- regval = SIRFSOC_I2C_READ | SIRFSOC_I2C_CMD_RP(0);
- if (((siic->finished_len + i) ==
- (siic->msg_len - 1)) && siic->last)
- regval |= SIRFSOC_I2C_STOP | SIRFSOC_I2C_NACK;
- writel(regval,
- siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
- i++;
- }
-
- siic->read_cmd_len = i;
- } else {
- while ((siic->cmd_ptr < SIRFSOC_I2C_CMD_BUF_MAX - 1)
- && (siic->finished_len < siic->msg_len)) {
- regval = SIRFSOC_I2C_WRITE | SIRFSOC_I2C_CMD_RP(0);
- if ((siic->finished_len == (siic->msg_len - 1))
- && siic->last)
- regval |= SIRFSOC_I2C_STOP;
- writel(regval,
- siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
- writel(siic->buf[siic->finished_len++],
- siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
- }
- }
- siic->cmd_ptr = 0;
-
- /* Trigger the transfer */
- writel(SIRFSOC_I2C_START_CMD, siic->base + SIRFSOC_I2C_CMD_START);
-}
-
-static irqreturn_t i2c_sirfsoc_irq(int irq, void *dev_id)
-{
- struct sirfsoc_i2c *siic = (struct sirfsoc_i2c *)dev_id;
- u32 i2c_stat = readl(siic->base + SIRFSOC_I2C_STATUS);
-
- if (i2c_stat & SIRFSOC_I2C_STAT_ERR) {
- /* Error conditions */
- siic->err_status = 1;
- writel(SIRFSOC_I2C_STAT_ERR, siic->base + SIRFSOC_I2C_STATUS);
-
- if (i2c_stat & SIRFSOC_I2C_STAT_NACK)
- dev_err(&siic->adapter.dev, "ACK not received\n");
- else
- dev_err(&siic->adapter.dev, "I2C error\n");
-
- complete(&siic->done);
- } else if (i2c_stat & SIRFSOC_I2C_STAT_CMD_DONE) {
- /* CMD buffer execution complete */
- if (siic->msg_read)
- i2c_sirfsoc_read_data(siic);
- if (siic->finished_len == siic->msg_len)
- complete(&siic->done);
- else /* Fill a new CMD buffer for left data */
- i2c_sirfsoc_queue_cmd(siic);
-
- writel(SIRFSOC_I2C_STAT_CMD_DONE, siic->base + SIRFSOC_I2C_STATUS);
- }
-
- return IRQ_HANDLED;
-}
-
-static void i2c_sirfsoc_set_address(struct sirfsoc_i2c *siic,
- struct i2c_msg *msg)
-{
- unsigned char addr;
- u32 regval = SIRFSOC_I2C_START | SIRFSOC_I2C_CMD_RP(0) | SIRFSOC_I2C_WRITE;
-
- /* no data and last message -> add STOP */
- if (siic->last && (msg->len == 0))
- regval |= SIRFSOC_I2C_STOP;
-
- writel(regval, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
-
- addr = msg->addr << 1; /* Generate address */
- if (msg->flags & I2C_M_RD)
- addr |= 1;
-
- writel(addr, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
-}
-
-static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg)
-{
- u32 regval = readl(siic->base + SIRFSOC_I2C_CTRL);
- /* timeout waiting for the xfer to finish or fail */
- int timeout = msecs_to_jiffies((msg->len + 1) * 50);
- int ret = 0;
-
- i2c_sirfsoc_set_address(siic, msg);
-
- writel(regval | SIRFSOC_I2C_CMD_DONE_EN | SIRFSOC_I2C_ERR_INT_EN,
- siic->base + SIRFSOC_I2C_CTRL);
- i2c_sirfsoc_queue_cmd(siic);
-
- if (wait_for_completion_timeout(&siic->done, timeout) == 0) {
- siic->err_status = 1;
- dev_err(&siic->adapter.dev, "Transfer timeout\n");
- }
-
- writel(regval & ~(SIRFSOC_I2C_CMD_DONE_EN | SIRFSOC_I2C_ERR_INT_EN),
- siic->base + SIRFSOC_I2C_CTRL);
- writel(0, siic->base + SIRFSOC_I2C_CMD_START);
-
- if (siic->err_status) {
- writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET,
- siic->base + SIRFSOC_I2C_CTRL);
- while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET)
- cpu_relax();
-
- ret = -EIO;
- }
-
- return ret;
-}
-
-static u32 i2c_sirfsoc_func(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static int i2c_sirfsoc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
- int num)
-{
- struct sirfsoc_i2c *siic = adap->algo_data;
- int i, ret;
-
- clk_enable(siic->clk);
-
- for (i = 0; i < num; i++) {
- siic->buf = msgs[i].buf;
- siic->msg_len = msgs[i].len;
- siic->msg_read = !!(msgs[i].flags & I2C_M_RD);
- siic->err_status = 0;
- siic->cmd_ptr = 0;
- siic->finished_len = 0;
- siic->last = (i == (num - 1));
-
- ret = i2c_sirfsoc_xfer_msg(siic, &msgs[i]);
- if (ret) {
- clk_disable(siic->clk);
- return ret;
- }
- }
-
- clk_disable(siic->clk);
- return num;
-}
-
-/* I2C algorithms associated with this master controller driver */
-static const struct i2c_algorithm i2c_sirfsoc_algo = {
- .master_xfer = i2c_sirfsoc_xfer,
- .functionality = i2c_sirfsoc_func,
-};
-
-static int __devinit i2c_sirfsoc_probe(struct platform_device *pdev)
-{
- struct sirfsoc_i2c *siic;
- struct i2c_adapter *adap;
- struct resource *mem_res;
- struct clk *clk;
- int bitrate;
- int ctrl_speed;
- int irq;
-
- int err;
- u32 regval;
-
- clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- err = PTR_ERR(clk);
- dev_err(&pdev->dev, "Clock get failed\n");
- goto err_get_clk;
- }
-
- err = clk_prepare(clk);
- if (err) {
- dev_err(&pdev->dev, "Clock prepare failed\n");
- goto err_clk_prep;
- }
-
- err = clk_enable(clk);
- if (err) {
- dev_err(&pdev->dev, "Clock enable failed\n");
- goto err_clk_en;
- }
-
- ctrl_speed = clk_get_rate(clk);
-
- siic = devm_kzalloc(&pdev->dev, sizeof(*siic), GFP_KERNEL);
- if (!siic) {
- dev_err(&pdev->dev, "Can't allocate driver data\n");
- err = -ENOMEM;
- goto out;
- }
- adap = &siic->adapter;
- adap->class = I2C_CLASS_HWMON;
-
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (mem_res == NULL) {
- dev_err(&pdev->dev, "Unable to get MEM resource\n");
- err = -EINVAL;
- goto out;
- }
-
- siic->base = devm_request_and_ioremap(&pdev->dev, mem_res);
- if (siic->base == NULL) {
- dev_err(&pdev->dev, "IO remap failed!\n");
- err = -ENOMEM;
- goto out;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- err = irq;
- goto out;
- }
- err = devm_request_irq(&pdev->dev, irq, i2c_sirfsoc_irq, 0,
- dev_name(&pdev->dev), siic);
- if (err)
- goto out;
-
- adap->algo = &i2c_sirfsoc_algo;
- adap->algo_data = siic;
-
- adap->dev.parent = &pdev->dev;
- adap->nr = pdev->id;
-
- strlcpy(adap->name, "sirfsoc-i2c", sizeof(adap->name));
-
- platform_set_drvdata(pdev, adap);
- init_completion(&siic->done);
-
- /* Controller Initalisation */
-
- writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL);
- while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET)
- cpu_relax();
- writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE,
- siic->base + SIRFSOC_I2C_CTRL);
-
- siic->clk = clk;
-
- err = of_property_read_u32(pdev->dev.of_node,
- "clock-frequency", &bitrate);
- if (err < 0)
- bitrate = SIRFSOC_I2C_DEFAULT_SPEED;
-
- if (bitrate < 100000)
- regval =
- (2 * ctrl_speed) / (2 * bitrate * 11);
- else
- regval = ctrl_speed / (bitrate * 5);
-
- writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL);
- if (regval > 0xFF)
- writel(0xFF, siic->base + SIRFSOC_I2C_SDA_DELAY);
- else
- writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY);
-
- err = i2c_add_numbered_adapter(adap);
- if (err < 0) {
- dev_err(&pdev->dev, "Can't add new i2c adapter\n");
- goto out;
- }
-
- clk_disable(clk);
-
- dev_info(&pdev->dev, " I2C adapter ready to operate\n");
-
- return 0;
-
-out:
- clk_disable(clk);
-err_clk_en:
- clk_unprepare(clk);
-err_clk_prep:
- clk_put(clk);
-err_get_clk:
- return err;
-}
-
-static int __devexit i2c_sirfsoc_remove(struct platform_device *pdev)
-{
- struct i2c_adapter *adapter = platform_get_drvdata(pdev);
- struct sirfsoc_i2c *siic = adapter->algo_data;
-
- writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL);
- i2c_del_adapter(adapter);
- clk_unprepare(siic->clk);
- clk_put(siic->clk);
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int i2c_sirfsoc_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct i2c_adapter *adapter = platform_get_drvdata(pdev);
- struct sirfsoc_i2c *siic = adapter->algo_data;
-
- clk_enable(siic->clk);
- siic->sda_delay = readl(siic->base + SIRFSOC_I2C_SDA_DELAY);
- siic->clk_div = readl(siic->base + SIRFSOC_I2C_CLK_CTRL);
- clk_disable(siic->clk);
- return 0;
-}
-
-static int i2c_sirfsoc_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct i2c_adapter *adapter = platform_get_drvdata(pdev);
- struct sirfsoc_i2c *siic = adapter->algo_data;
-
- clk_enable(siic->clk);
- writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL);
- writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE,
- siic->base + SIRFSOC_I2C_CTRL);
- writel(siic->clk_div, siic->base + SIRFSOC_I2C_CLK_CTRL);
- writel(siic->sda_delay, siic->base + SIRFSOC_I2C_SDA_DELAY);
- clk_disable(siic->clk);
- return 0;
-}
-
-static const struct dev_pm_ops i2c_sirfsoc_pm_ops = {
- .suspend = i2c_sirfsoc_suspend,
- .resume = i2c_sirfsoc_resume,
-};
-#endif
-
-static const struct of_device_id sirfsoc_i2c_of_match[] __devinitconst = {
- { .compatible = "sirf,prima2-i2c", },
- {},
-};
-MODULE_DEVICE_TABLE(of, sirfsoc_i2c_of_match);
-
-static struct platform_driver i2c_sirfsoc_driver = {
- .driver = {
- .name = "sirfsoc_i2c",
- .owner = THIS_MODULE,
-#ifdef CONFIG_PM
- .pm = &i2c_sirfsoc_pm_ops,
-#endif
- .of_match_table = sirfsoc_i2c_of_match,
- },
- .probe = i2c_sirfsoc_probe,
- .remove = __devexit_p(i2c_sirfsoc_remove),
-};
-module_platform_driver(i2c_sirfsoc_driver);
-
-MODULE_DESCRIPTION("SiRF SoC I2C master controller driver");
-MODULE_AUTHOR("Zhiwu Song , "
- "Xiangzhen Ye ");
-MODULE_LICENSE("GPL v2");
diff --git a/trunk/drivers/i2c/busses/i2c-tegra.c b/trunk/drivers/i2c/busses/i2c-tegra.c
index e978635e60f0..0ab4a9548745 100644
--- a/trunk/drivers/i2c/busses/i2c-tegra.c
+++ b/trunk/drivers/i2c/busses/i2c-tegra.c
@@ -457,6 +457,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
int ret;
tegra_i2c_flush_fifos(i2c_dev);
+ i2c_writel(i2c_dev, 0xFF, I2C_INT_STATUS);
if (msg->len == 0)
return -EINVAL;
diff --git a/trunk/drivers/i2c/busses/i2c-versatile.c b/trunk/drivers/i2c/busses/i2c-versatile.c
index f585aead50cc..60556012312f 100644
--- a/trunk/drivers/i2c/busses/i2c-versatile.c
+++ b/trunk/drivers/i2c/busses/i2c-versatile.c
@@ -16,7 +16,6 @@
#include
#include
#include
-#include
#define I2C_CONTROL 0x00
#define I2C_CONTROLS 0x00
@@ -100,7 +99,6 @@ static int i2c_versatile_probe(struct platform_device *dev)
strlcpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name));
i2c->adap.algo_data = &i2c->algo;
i2c->adap.dev.parent = &dev->dev;
- i2c->adap.dev.of_node = dev->dev.of_node;
i2c->algo = i2c_versatile_algo;
i2c->algo.data = i2c;
@@ -113,7 +111,6 @@ static int i2c_versatile_probe(struct platform_device *dev)
ret = i2c_bit_add_bus(&i2c->adap);
if (ret >= 0) {
platform_set_drvdata(dev, i2c);
- of_i2c_register_devices(&i2c->adap);
return 0;
}
@@ -136,19 +133,12 @@ static int i2c_versatile_remove(struct platform_device *dev)
return 0;
}
-static const struct of_device_id i2c_versatile_match[] = {
- { .compatible = "arm,versatile-i2c", },
- {},
-};
-MODULE_DEVICE_TABLE(of, i2c_versatile_match);
-
static struct platform_driver i2c_versatile_driver = {
.probe = i2c_versatile_probe,
.remove = i2c_versatile_remove,
.driver = {
.name = "versatile-i2c",
.owner = THIS_MODULE,
- .of_match_table = i2c_versatile_match,
},
};
diff --git a/trunk/drivers/i2c/busses/i2c-xlr.c b/trunk/drivers/i2c/busses/i2c-xlr.c
deleted file mode 100644
index 96d3fabd8883..000000000000
--- a/trunk/drivers/i2c/busses/i2c-xlr.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright 2011, Netlogic Microsystems Inc.
- * Copyright 2004, Matt Porter
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* XLR I2C REGISTERS */
-#define XLR_I2C_CFG 0x00
-#define XLR_I2C_CLKDIV 0x01
-#define XLR_I2C_DEVADDR 0x02
-#define XLR_I2C_ADDR 0x03
-#define XLR_I2C_DATAOUT 0x04
-#define XLR_I2C_DATAIN 0x05
-#define XLR_I2C_STATUS 0x06
-#define XLR_I2C_STARTXFR 0x07
-#define XLR_I2C_BYTECNT 0x08
-#define XLR_I2C_HDSTATIM 0x09
-
-/* XLR I2C REGISTERS FLAGS */
-#define XLR_I2C_BUS_BUSY 0x01
-#define XLR_I2C_SDOEMPTY 0x02
-#define XLR_I2C_RXRDY 0x04
-#define XLR_I2C_ACK_ERR 0x08
-#define XLR_I2C_ARB_STARTERR 0x30
-
-/* Register Values */
-#define XLR_I2C_CFG_ADDR 0xF8
-#define XLR_I2C_CFG_NOADDR 0xFA
-#define XLR_I2C_STARTXFR_ND 0x02 /* No Data */
-#define XLR_I2C_STARTXFR_RD 0x01 /* Read */
-#define XLR_I2C_STARTXFR_WR 0x00 /* Write */
-
-#define XLR_I2C_TIMEOUT 10 /* timeout per byte in msec */
-
-/*
- * On XLR/XLS, we need to use __raw_ IO to read the I2C registers
- * because they are in the big-endian MMIO area on the SoC.
- *
- * The readl/writel implementation on XLR/XLS byteswaps, because
- * those are for its little-endian PCI space (see arch/mips/Kconfig).
- */
-static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
-{
- __raw_writel(val, base + reg);
-}
-
-static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
-{
- return __raw_readl(base + reg);
-}
-
-struct xlr_i2c_private {
- struct i2c_adapter adap;
- u32 __iomem *iobase;
-};
-
-static int xlr_i2c_tx(struct xlr_i2c_private *priv, u16 len,
- u8 *buf, u16 addr)
-{
- struct i2c_adapter *adap = &priv->adap;
- unsigned long timeout, stoptime, checktime;
- u32 i2c_status;
- int pos, timedout;
- u8 offset, byte;
-
- offset = buf[0];
- xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
-
- timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
- stoptime = jiffies + timeout;
- timedout = 0;
- pos = 1;
-retry:
- if (len == 1) {
- xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
- XLR_I2C_STARTXFR_ND);
- } else {
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
- XLR_I2C_STARTXFR_WR);
- }
-
- while (!timedout) {
- checktime = jiffies;
- i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
-
- if (i2c_status & XLR_I2C_SDOEMPTY) {
- pos++;
- /* need to do a empty dataout after the last byte */
- byte = (pos < len) ? buf[pos] : 0;
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, byte);
-
- /* reset timeout on successful xmit */
- stoptime = jiffies + timeout;
- }
- timedout = time_after(checktime, stoptime);
-
- if (i2c_status & XLR_I2C_ARB_STARTERR) {
- if (timedout)
- break;
- goto retry;
- }
-
- if (i2c_status & XLR_I2C_ACK_ERR)
- return -EIO;
-
- if ((i2c_status & XLR_I2C_BUS_BUSY) == 0 && pos >= len)
- return 0;
- }
- dev_err(&adap->dev, "I2C transmit timeout\n");
- return -ETIMEDOUT;
-}
-
-static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
-{
- struct i2c_adapter *adap = &priv->adap;
- u32 i2c_status;
- unsigned long timeout, stoptime, checktime;
- int nbytes, timedout;
- u8 byte;
-
- xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
-
- timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
- stoptime = jiffies + timeout;
- timedout = 0;
- nbytes = 0;
-retry:
- xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
-
- while (!timedout) {
- checktime = jiffies;
- i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
- if (i2c_status & XLR_I2C_RXRDY) {
- if (nbytes > len)
- return -EIO; /* should not happen */
-
- /* we need to do a dummy datain when nbytes == len */
- byte = xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
- if (nbytes < len)
- buf[nbytes] = byte;
- nbytes++;
-
- /* reset timeout on successful read */
- stoptime = jiffies + timeout;
- }
-
- timedout = time_after(checktime, stoptime);
- if (i2c_status & XLR_I2C_ARB_STARTERR) {
- if (timedout)
- break;
- goto retry;
- }
-
- if (i2c_status & XLR_I2C_ACK_ERR)
- return -EIO;
-
- if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
- return 0;
- }
-
- dev_err(&adap->dev, "I2C receive timeout\n");
- return -ETIMEDOUT;
-}
-
-static int xlr_i2c_xfer(struct i2c_adapter *adap,
- struct i2c_msg *msgs, int num)
-{
- struct i2c_msg *msg;
- int i;
- int ret = 0;
- struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
-
- for (i = 0; ret == 0 && i < num; i++) {
- msg = &msgs[i];
- if (msg->flags & I2C_M_RD)
- ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
- msg->addr);
- else
- ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
- msg->addr);
- }
-
- return (ret != 0) ? ret : num;
-}
-
-static u32 xlr_func(struct i2c_adapter *adap)
-{
- /* Emulate SMBUS over I2C */
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm xlr_i2c_algo = {
- .master_xfer = xlr_i2c_xfer,
- .functionality = xlr_func,
-};
-
-static int __devinit xlr_i2c_probe(struct platform_device *pdev)
-{
- struct xlr_i2c_private *priv;
- struct resource *res;
- int ret;
-
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->iobase = devm_request_and_ioremap(&pdev->dev, res);
- if (!priv->iobase) {
- dev_err(&pdev->dev, "devm_request_and_ioremap failed\n");
- return -EBUSY;
- }
-
- priv->adap.dev.parent = &pdev->dev;
- priv->adap.owner = THIS_MODULE;
- priv->adap.algo_data = priv;
- priv->adap.algo = &xlr_i2c_algo;
- priv->adap.nr = pdev->id;
- priv->adap.class = I2C_CLASS_HWMON;
- snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c");
-
- i2c_set_adapdata(&priv->adap, priv);
- ret = i2c_add_numbered_adapter(&priv->adap);
- if (ret < 0) {
- dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
- return ret;
- }
-
- platform_set_drvdata(pdev, priv);
- dev_info(&priv->adap.dev, "Added I2C Bus.\n");
- return 0;
-}
-
-static int __devexit xlr_i2c_remove(struct platform_device *pdev)
-{
- struct xlr_i2c_private *priv;
-
- priv = platform_get_drvdata(pdev);
- i2c_del_adapter(&priv->adap);
- platform_set_drvdata(pdev, NULL);
- return 0;
-}
-
-static struct platform_driver xlr_i2c_driver = {
- .probe = xlr_i2c_probe,
- .remove = __devexit_p(xlr_i2c_remove),
- .driver = {
- .name = "xlr-i2cbus",
- .owner = THIS_MODULE,
- },
-};
-
-module_platform_driver(xlr_i2c_driver);
-
-MODULE_AUTHOR("Ganesan Ramalingam ");
-MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:xlr-i2cbus");
diff --git a/trunk/drivers/iommu/Kconfig b/trunk/drivers/iommu/Kconfig
index 3bd9fff5c589..6bea6962f8ee 100644
--- a/trunk/drivers/iommu/Kconfig
+++ b/trunk/drivers/iommu/Kconfig
@@ -142,24 +142,4 @@ config OMAP_IOMMU_DEBUG
Say N unless you know you need this.
-config TEGRA_IOMMU_GART
- bool "Tegra GART IOMMU Support"
- depends on ARCH_TEGRA_2x_SOC
- select IOMMU_API
- help
- Enables support for remapping discontiguous physical memory
- shared with the operating system into contiguous I/O virtual
- space through the GART (Graphics Address Relocation Table)
- hardware included on Tegra SoCs.
-
-config TEGRA_IOMMU_SMMU
- bool "Tegra SMMU IOMMU Support"
- depends on ARCH_TEGRA_3x_SOC
- select IOMMU_API
- help
- Enables support for remapping discontiguous physical memory
- shared with the operating system into contiguous I/O virtual
- space through the SMMU (System Memory Management Unit)
- hardware included on Tegra SoCs.
-
endif # IOMMU_SUPPORT
diff --git a/trunk/drivers/iommu/Makefile b/trunk/drivers/iommu/Makefile
index 7ad7a3bc1242..0e36b4934aff 100644
--- a/trunk/drivers/iommu/Makefile
+++ b/trunk/drivers/iommu/Makefile
@@ -8,5 +8,3 @@ obj-$(CONFIG_IRQ_REMAP) += intr_remapping.o
obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
-obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
-obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
diff --git a/trunk/drivers/iommu/amd_iommu_init.c b/trunk/drivers/iommu/amd_iommu_init.c
index c56790375e0f..a35e98ad9725 100644
--- a/trunk/drivers/iommu/amd_iommu_init.c
+++ b/trunk/drivers/iommu/amd_iommu_init.c
@@ -196,8 +196,6 @@ static u32 rlookup_table_size; /* size if the rlookup table */
*/
extern void iommu_flush_all_caches(struct amd_iommu *iommu);
-static int amd_iommu_enable_interrupts(void);
-
static inline void update_last_devid(u16 devid)
{
if (devid > amd_iommu_last_bdf)
@@ -360,6 +358,8 @@ static void iommu_disable(struct amd_iommu *iommu)
*/
static u8 * __init iommu_map_mmio_space(u64 address)
{
+ u8 *ret;
+
if (!request_mem_region(address, MMIO_REGION_LENGTH, "amd_iommu")) {
pr_err("AMD-Vi: Can not reserve memory region %llx for mmio\n",
address);
@@ -367,7 +367,13 @@ static u8 * __init iommu_map_mmio_space(u64 address)
return NULL;
}
- return ioremap_nocache(address, MMIO_REGION_LENGTH);
+ ret = ioremap_nocache(address, MMIO_REGION_LENGTH);
+ if (ret != NULL)
+ return ret;
+
+ release_mem_region(address, MMIO_REGION_LENGTH);
+
+ return NULL;
}
static void __init iommu_unmap_mmio_space(struct amd_iommu *iommu)
@@ -1125,9 +1131,8 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
{
int r;
- r = pci_enable_msi(iommu->dev);
- if (r)
- return r;
+ if (pci_enable_msi(iommu->dev))
+ return 1;
r = request_threaded_irq(iommu->dev->irq,
amd_iommu_int_handler,
@@ -1137,36 +1142,27 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
if (r) {
pci_disable_msi(iommu->dev);
- return r;
+ return 1;
}
iommu->int_enabled = true;
+ iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+ if (iommu->ppr_log != NULL)
+ iommu_feature_enable(iommu, CONTROL_PPFINT_EN);
return 0;
}
static int iommu_init_msi(struct amd_iommu *iommu)
{
- int ret;
-
if (iommu->int_enabled)
- goto enable_faults;
+ return 0;
if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
- ret = iommu_setup_msi(iommu);
- else
- ret = -ENODEV;
-
- if (ret)
- return ret;
+ return iommu_setup_msi(iommu);
-enable_faults:
- iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
-
- if (iommu->ppr_log != NULL)
- iommu_feature_enable(iommu, CONTROL_PPFINT_EN);
-
- return 0;
+ return 1;
}
/****************************************************************************
@@ -1385,6 +1381,7 @@ static void enable_iommus(void)
iommu_enable_ppr_log(iommu);
iommu_enable_gt(iommu);
iommu_set_exclusion_range(iommu);
+ iommu_init_msi(iommu);
iommu_enable(iommu);
iommu_flush_all_caches(iommu);
}
@@ -1412,8 +1409,6 @@ static void amd_iommu_resume(void)
/* re-load the hardware */
enable_iommus();
-
- amd_iommu_enable_interrupts();
}
static int amd_iommu_suspend(void)
@@ -1429,40 +1424,10 @@ static struct syscore_ops amd_iommu_syscore_ops = {
.resume = amd_iommu_resume,
};
-static void __init free_on_init_error(void)
-{
- amd_iommu_uninit_devices();
-
- free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,
- get_order(MAX_DOMAIN_ID/8));
-
- free_pages((unsigned long)amd_iommu_rlookup_table,
- get_order(rlookup_table_size));
-
- free_pages((unsigned long)amd_iommu_alias_table,
- get_order(alias_table_size));
-
- free_pages((unsigned long)amd_iommu_dev_table,
- get_order(dev_table_size));
-
- free_iommu_all();
-
- free_unity_maps();
-
-#ifdef CONFIG_GART_IOMMU
- /*
- * We failed to initialize the AMD IOMMU - try fallback to GART
- * if possible.
- */
- gart_iommu_init();
-
-#endif
-}
-
/*
- * This is the hardware init function for AMD IOMMU in the system.
- * This function is called either from amd_iommu_init or from the interrupt
- * remapping setup code.
+ * This is the core init function for AMD IOMMU hardware in the system.
+ * This function is called from the generic x86 DMA layer initialization
+ * code.
*
* This function basically parses the ACPI table for AMD IOMMU (IVRS)
* three times:
@@ -1481,21 +1446,16 @@ static void __init free_on_init_error(void)
* remapping requirements parsed out of the ACPI table in
* this last pass.
*
- * After everything is set up the IOMMUs are enabled and the necessary
- * hotplug and suspend notifiers are registered.
+ * After that the hardware is initialized and ready to go. In the last
+ * step we do some Linux specific things like registering the driver in
+ * the dma_ops interface and initializing the suspend/resume support
+ * functions. Finally it prints some information about AMD IOMMUs and
+ * the driver state and enables the hardware.
*/
-int __init amd_iommu_init_hardware(void)
+static int __init amd_iommu_init(void)
{
int i, ret = 0;
- if (!amd_iommu_detected)
- return -ENODEV;
-
- if (amd_iommu_dev_table != NULL) {
- /* Hardware already initialized */
- return 0;
- }
-
/*
* First parse ACPI tables to find the largest Bus/Dev/Func
* we need to handle. Upon this information the shared data
@@ -1512,8 +1472,9 @@ int __init amd_iommu_init_hardware(void)
alias_table_size = tbl_size(ALIAS_TABLE_ENTRY_SIZE);
rlookup_table_size = tbl_size(RLOOKUP_TABLE_ENTRY_SIZE);
- /* Device table - directly used by all IOMMUs */
ret = -ENOMEM;
+
+ /* Device table - directly used by all IOMMUs */
amd_iommu_dev_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
get_order(dev_table_size));
if (amd_iommu_dev_table == NULL)
@@ -1585,65 +1546,20 @@ int __init amd_iommu_init_hardware(void)
enable_iommus();
- amd_iommu_init_notifier();
-
- register_syscore_ops(&amd_iommu_syscore_ops);
-
-out:
- return ret;
-
-free:
- free_on_init_error();
-
- return ret;
-}
-
-static int amd_iommu_enable_interrupts(void)
-{
- struct amd_iommu *iommu;
- int ret = 0;
-
- for_each_iommu(iommu) {
- ret = iommu_init_msi(iommu);
- if (ret)
- goto out;
- }
-
-out:
- return ret;
-}
-
-/*
- * This is the core init function for AMD IOMMU hardware in the system.
- * This function is called from the generic x86 DMA layer initialization
- * code.
- *
- * The function calls amd_iommu_init_hardware() to setup and enable the
- * IOMMU hardware if this has not happened yet. After that the driver
- * registers for the DMA-API and for the IOMMU-API as necessary.
- */
-static int __init amd_iommu_init(void)
-{
- int ret = 0;
-
- ret = amd_iommu_init_hardware();
- if (ret)
- goto out;
-
- ret = amd_iommu_enable_interrupts();
- if (ret)
- goto free;
-
if (iommu_pass_through)
ret = amd_iommu_init_passthrough();
else
ret = amd_iommu_init_dma_ops();
if (ret)
- goto free;
+ goto free_disable;
amd_iommu_init_api();
+ amd_iommu_init_notifier();
+
+ register_syscore_ops(&amd_iommu_syscore_ops);
+
if (iommu_pass_through)
goto out;
@@ -1653,14 +1569,39 @@ static int __init amd_iommu_init(void)
printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n");
x86_platform.iommu_shutdown = disable_iommus;
-
out:
return ret;
-free:
+free_disable:
disable_iommus();
- free_on_init_error();
+free:
+ amd_iommu_uninit_devices();
+
+ free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,
+ get_order(MAX_DOMAIN_ID/8));
+
+ free_pages((unsigned long)amd_iommu_rlookup_table,
+ get_order(rlookup_table_size));
+
+ free_pages((unsigned long)amd_iommu_alias_table,
+ get_order(alias_table_size));
+
+ free_pages((unsigned long)amd_iommu_dev_table,
+ get_order(dev_table_size));
+
+ free_iommu_all();
+
+ free_unity_maps();
+
+#ifdef CONFIG_GART_IOMMU
+ /*
+ * We failed to initialize the AMD IOMMU - try fallback to GART
+ * if possible.
+ */
+ gart_iommu_init();
+
+#endif
goto out;
}
diff --git a/trunk/drivers/iommu/amd_iommu_v2.c b/trunk/drivers/iommu/amd_iommu_v2.c
index 036fe9bf157e..8add9f125d3e 100644
--- a/trunk/drivers/iommu/amd_iommu_v2.c
+++ b/trunk/drivers/iommu/amd_iommu_v2.c
@@ -921,16 +921,7 @@ static int __init amd_iommu_v2_init(void)
size_t state_table_size;
int ret;
- pr_info("AMD IOMMUv2 driver by Joerg Roedel \n");
-
- if (!amd_iommu_v2_supported()) {
- pr_info("AMD IOMMUv2 functionality not available on this sytem\n");
- /*
- * Load anyway to provide the symbols to other modules
- * which may use AMD IOMMUv2 optionally.
- */
- return 0;
- }
+ pr_info("AMD IOMMUv2 driver by Joerg Roedel ");
spin_lock_init(&state_lock);
@@ -970,9 +961,6 @@ static void __exit amd_iommu_v2_exit(void)
size_t state_table_size;
int i;
- if (!amd_iommu_v2_supported())
- return;
-
profile_event_unregister(PROFILE_TASK_EXIT, &profile_nb);
amd_iommu_unregister_ppr_notifier(&ppr_nb);
diff --git a/trunk/drivers/iommu/tegra-gart.c b/trunk/drivers/iommu/tegra-gart.c
deleted file mode 100644
index 779306ee7b16..000000000000
--- a/trunk/drivers/iommu/tegra-gart.c
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * IOMMU API for GART in Tegra20
- *
- * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- */
-
-#define pr_fmt(fmt) "%s(): " fmt, __func__
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-/* bitmap of the page sizes currently supported */
-#define GART_IOMMU_PGSIZES (SZ_4K)
-
-#define GART_CONFIG 0x24
-#define GART_ENTRY_ADDR 0x28
-#define GART_ENTRY_DATA 0x2c
-#define GART_ENTRY_PHYS_ADDR_VALID (1 << 31)
-
-#define GART_PAGE_SHIFT 12
-#define GART_PAGE_SIZE (1 << GART_PAGE_SHIFT)
-#define GART_PAGE_MASK \
- (~(GART_PAGE_SIZE - 1) & ~GART_ENTRY_PHYS_ADDR_VALID)
-
-struct gart_client {
- struct device *dev;
- struct list_head list;
-};
-
-struct gart_device {
- void __iomem *regs;
- u32 *savedata;
- u32 page_count; /* total remappable size */
- dma_addr_t iovmm_base; /* offset to vmm_area */
- spinlock_t pte_lock; /* for pagetable */
- struct list_head client;
- spinlock_t client_lock; /* for client list */
- struct device *dev;
-};
-
-static struct gart_device *gart_handle; /* unique for a system */
-
-#define GART_PTE(_pfn) \
- (GART_ENTRY_PHYS_ADDR_VALID | ((_pfn) << PAGE_SHIFT))
-
-/*
- * Any interaction between any block on PPSB and a block on APB or AHB
- * must have these read-back to ensure the APB/AHB bus transaction is
- * complete before initiating activity on the PPSB block.
- */
-#define FLUSH_GART_REGS(gart) ((void)readl((gart)->regs + GART_CONFIG))
-
-#define for_each_gart_pte(gart, iova) \
- for (iova = gart->iovmm_base; \
- iova < gart->iovmm_base + GART_PAGE_SIZE * gart->page_count; \
- iova += GART_PAGE_SIZE)
-
-static inline void gart_set_pte(struct gart_device *gart,
- unsigned long offs, u32 pte)
-{
- writel(offs, gart->regs + GART_ENTRY_ADDR);
- writel(pte, gart->regs + GART_ENTRY_DATA);
-
- dev_dbg(gart->dev, "%s %08lx:%08x\n",
- pte ? "map" : "unmap", offs, pte & GART_PAGE_MASK);
-}
-
-static inline unsigned long gart_read_pte(struct gart_device *gart,
- unsigned long offs)
-{
- unsigned long pte;
-
- writel(offs, gart->regs + GART_ENTRY_ADDR);
- pte = readl(gart->regs + GART_ENTRY_DATA);
-
- return pte;
-}
-
-static void do_gart_setup(struct gart_device *gart, const u32 *data)
-{
- unsigned long iova;
-
- for_each_gart_pte(gart, iova)
- gart_set_pte(gart, iova, data ? *(data++) : 0);
-
- writel(1, gart->regs + GART_CONFIG);
- FLUSH_GART_REGS(gart);
-}
-
-#ifdef DEBUG
-static void gart_dump_table(struct gart_device *gart)
-{
- unsigned long iova;
- unsigned long flags;
-
- spin_lock_irqsave(&gart->pte_lock, flags);
- for_each_gart_pte(gart, iova) {
- unsigned long pte;
-
- pte = gart_read_pte(gart, iova);
-
- dev_dbg(gart->dev, "%s %08lx:%08lx\n",
- (GART_ENTRY_PHYS_ADDR_VALID & pte) ? "v" : " ",
- iova, pte & GART_PAGE_MASK);
- }
- spin_unlock_irqrestore(&gart->pte_lock, flags);
-}
-#else
-static inline void gart_dump_table(struct gart_device *gart)
-{
-}
-#endif
-
-static inline bool gart_iova_range_valid(struct gart_device *gart,
- unsigned long iova, size_t bytes)
-{
- unsigned long iova_start, iova_end, gart_start, gart_end;
-
- iova_start = iova;
- iova_end = iova_start + bytes - 1;
- gart_start = gart->iovmm_base;
- gart_end = gart_start + gart->page_count * GART_PAGE_SIZE - 1;
-
- if (iova_start < gart_start)
- return false;
- if (iova_end > gart_end)
- return false;
- return true;
-}
-
-static int gart_iommu_attach_dev(struct iommu_domain *domain,
- struct device *dev)
-{
- struct gart_device *gart;
- struct gart_client *client, *c;
- int err = 0;
-
- gart = dev_get_drvdata(dev->parent);
- if (!gart)
- return -EINVAL;
- domain->priv = gart;
-
- client = devm_kzalloc(gart->dev, sizeof(*c), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- client->dev = dev;
-
- spin_lock(&gart->client_lock);
- list_for_each_entry(c, &gart->client, list) {
- if (c->dev == dev) {
- dev_err(gart->dev,
- "%s is already attached\n", dev_name(dev));
- err = -EINVAL;
- goto fail;
- }
- }
- list_add(&client->list, &gart->client);
- spin_unlock(&gart->client_lock);
- dev_dbg(gart->dev, "Attached %s\n", dev_name(dev));
- return 0;
-
-fail:
- devm_kfree(gart->dev, client);
- spin_unlock(&gart->client_lock);
- return err;
-}
-
-static void gart_iommu_detach_dev(struct iommu_domain *domain,
- struct device *dev)
-{
- struct gart_device *gart = domain->priv;
- struct gart_client *c;
-
- spin_lock(&gart->client_lock);
-
- list_for_each_entry(c, &gart->client, list) {
- if (c->dev == dev) {
- list_del(&c->list);
- devm_kfree(gart->dev, c);
- dev_dbg(gart->dev, "Detached %s\n", dev_name(dev));
- goto out;
- }
- }
- dev_err(gart->dev, "Couldn't find\n");
-out:
- spin_unlock(&gart->client_lock);
-}
-
-static int gart_iommu_domain_init(struct iommu_domain *domain)
-{
- return 0;
-}
-
-static void gart_iommu_domain_destroy(struct iommu_domain *domain)
-{
- struct gart_device *gart = domain->priv;
-
- if (!gart)
- return;
-
- spin_lock(&gart->client_lock);
- if (!list_empty(&gart->client)) {
- struct gart_client *c;
-
- list_for_each_entry(c, &gart->client, list)
- gart_iommu_detach_dev(domain, c->dev);
- }
- spin_unlock(&gart->client_lock);
- domain->priv = NULL;
-}
-
-static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova,
- phys_addr_t pa, size_t bytes, int prot)
-{
- struct gart_device *gart = domain->priv;
- unsigned long flags;
- unsigned long pfn;
-
- if (!gart_iova_range_valid(gart, iova, bytes))
- return -EINVAL;
-
- spin_lock_irqsave(&gart->pte_lock, flags);
- pfn = __phys_to_pfn(pa);
- if (!pfn_valid(pfn)) {
- dev_err(gart->dev, "Invalid page: %08x\n", pa);
- spin_unlock_irqrestore(&gart->pte_lock, flags);
- return -EINVAL;
- }
- gart_set_pte(gart, iova, GART_PTE(pfn));
- FLUSH_GART_REGS(gart);
- spin_unlock_irqrestore(&gart->pte_lock, flags);
- return 0;
-}
-
-static size_t gart_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
- size_t bytes)
-{
- struct gart_device *gart = domain->priv;
- unsigned long flags;
-
- if (!gart_iova_range_valid(gart, iova, bytes))
- return 0;
-
- spin_lock_irqsave(&gart->pte_lock, flags);
- gart_set_pte(gart, iova, 0);
- FLUSH_GART_REGS(gart);
- spin_unlock_irqrestore(&gart->pte_lock, flags);
- return 0;
-}
-
-static phys_addr_t gart_iommu_iova_to_phys(struct iommu_domain *domain,
- unsigned long iova)
-{
- struct gart_device *gart = domain->priv;
- unsigned long pte;
- phys_addr_t pa;
- unsigned long flags;
-
- if (!gart_iova_range_valid(gart, iova, 0))
- return -EINVAL;
-
- spin_lock_irqsave(&gart->pte_lock, flags);
- pte = gart_read_pte(gart, iova);
- spin_unlock_irqrestore(&gart->pte_lock, flags);
-
- pa = (pte & GART_PAGE_MASK);
- if (!pfn_valid(__phys_to_pfn(pa))) {
- dev_err(gart->dev, "No entry for %08lx:%08x\n", iova, pa);
- gart_dump_table(gart);
- return -EINVAL;
- }
- return pa;
-}
-
-static int gart_iommu_domain_has_cap(struct iommu_domain *domain,
- unsigned long cap)
-{
- return 0;
-}
-
-static struct iommu_ops gart_iommu_ops = {
- .domain_init = gart_iommu_domain_init,
- .domain_destroy = gart_iommu_domain_destroy,
- .attach_dev = gart_iommu_attach_dev,
- .detach_dev = gart_iommu_detach_dev,
- .map = gart_iommu_map,
- .unmap = gart_iommu_unmap,
- .iova_to_phys = gart_iommu_iova_to_phys,
- .domain_has_cap = gart_iommu_domain_has_cap,
- .pgsize_bitmap = GART_IOMMU_PGSIZES,
-};
-
-static int tegra_gart_suspend(struct device *dev)
-{
- struct gart_device *gart = dev_get_drvdata(dev);
- unsigned long iova;
- u32 *data = gart->savedata;
- unsigned long flags;
-
- spin_lock_irqsave(&gart->pte_lock, flags);
- for_each_gart_pte(gart, iova)
- *(data++) = gart_read_pte(gart, iova);
- spin_unlock_irqrestore(&gart->pte_lock, flags);
- return 0;
-}
-
-static int tegra_gart_resume(struct device *dev)
-{
- struct gart_device *gart = dev_get_drvdata(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&gart->pte_lock, flags);
- do_gart_setup(gart, gart->savedata);
- spin_unlock_irqrestore(&gart->pte_lock, flags);
- return 0;
-}
-
-static int tegra_gart_probe(struct platform_device *pdev)
-{
- struct gart_device *gart;
- struct resource *res, *res_remap;
- void __iomem *gart_regs;
- int err;
- struct device *dev = &pdev->dev;
-
- if (gart_handle)
- return -EIO;
-
- BUILD_BUG_ON(PAGE_SHIFT != GART_PAGE_SHIFT);
-
- /* the GART memory aperture is required */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- res_remap = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res || !res_remap) {
- dev_err(dev, "GART memory aperture expected\n");
- return -ENXIO;
- }
-
- gart = devm_kzalloc(dev, sizeof(*gart), GFP_KERNEL);
- if (!gart) {
- dev_err(dev, "failed to allocate gart_device\n");
- return -ENOMEM;
- }
-
- gart_regs = devm_ioremap(dev, res->start, resource_size(res));
- if (!gart_regs) {
- dev_err(dev, "failed to remap GART registers\n");
- err = -ENXIO;
- goto fail;
- }
-
- gart->dev = &pdev->dev;
- spin_lock_init(&gart->pte_lock);
- spin_lock_init(&gart->client_lock);
- INIT_LIST_HEAD(&gart->client);
- gart->regs = gart_regs;
- gart->iovmm_base = (dma_addr_t)res_remap->start;
- gart->page_count = (resource_size(res_remap) >> GART_PAGE_SHIFT);
-
- gart->savedata = vmalloc(sizeof(u32) * gart->page_count);
- if (!gart->savedata) {
- dev_err(dev, "failed to allocate context save area\n");
- err = -ENOMEM;
- goto fail;
- }
-
- platform_set_drvdata(pdev, gart);
- do_gart_setup(gart, NULL);
-
- gart_handle = gart;
- return 0;
-
-fail:
- if (gart_regs)
- devm_iounmap(dev, gart_regs);
- if (gart && gart->savedata)
- vfree(gart->savedata);
- devm_kfree(dev, gart);
- return err;
-}
-
-static int tegra_gart_remove(struct platform_device *pdev)
-{
- struct gart_device *gart = platform_get_drvdata(pdev);
- struct device *dev = gart->dev;
-
- writel(0, gart->regs + GART_CONFIG);
- if (gart->savedata)
- vfree(gart->savedata);
- if (gart->regs)
- devm_iounmap(dev, gart->regs);
- devm_kfree(dev, gart);
- gart_handle = NULL;
- return 0;
-}
-
-const struct dev_pm_ops tegra_gart_pm_ops = {
- .suspend = tegra_gart_suspend,
- .resume = tegra_gart_resume,
-};
-
-static struct platform_driver tegra_gart_driver = {
- .probe = tegra_gart_probe,
- .remove = tegra_gart_remove,
- .driver = {
- .owner = THIS_MODULE,
- .name = "tegra-gart",
- .pm = &tegra_gart_pm_ops,
- },
-};
-
-static int __devinit tegra_gart_init(void)
-{
- bus_set_iommu(&platform_bus_type, &gart_iommu_ops);
- return platform_driver_register(&tegra_gart_driver);
-}
-
-static void __exit tegra_gart_exit(void)
-{
- platform_driver_unregister(&tegra_gart_driver);
-}
-
-subsys_initcall(tegra_gart_init);
-module_exit(tegra_gart_exit);
-
-MODULE_DESCRIPTION("IOMMU API for GART in Tegra20");
-MODULE_AUTHOR("Hiroshi DOYU ");
-MODULE_LICENSE("GPL v2");
diff --git a/trunk/drivers/iommu/tegra-smmu.c b/trunk/drivers/iommu/tegra-smmu.c
deleted file mode 100644
index eb93c821f592..000000000000
--- a/trunk/drivers/iommu/tegra-smmu.c
+++ /dev/null
@@ -1,1034 +0,0 @@
-/*
- * IOMMU API for SMMU in Tegra30
- *
- * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- */
-
-#define pr_fmt(fmt) "%s(): " fmt, __func__
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-
-/* bitmap of the page sizes currently supported */
-#define SMMU_IOMMU_PGSIZES (SZ_4K)
-
-#define SMMU_CONFIG 0x10
-#define SMMU_CONFIG_DISABLE 0
-#define SMMU_CONFIG_ENABLE 1
-
-#define SMMU_TLB_CONFIG 0x14
-#define SMMU_TLB_CONFIG_STATS__MASK (1 << 31)
-#define SMMU_TLB_CONFIG_STATS__ENABLE (1 << 31)
-#define SMMU_TLB_CONFIG_HIT_UNDER_MISS__ENABLE (1 << 29)
-#define SMMU_TLB_CONFIG_ACTIVE_LINES__VALUE 0x10
-#define SMMU_TLB_CONFIG_RESET_VAL 0x20000010
-
-#define SMMU_PTC_CONFIG 0x18
-#define SMMU_PTC_CONFIG_STATS__MASK (1 << 31)
-#define SMMU_PTC_CONFIG_STATS__ENABLE (1 << 31)
-#define SMMU_PTC_CONFIG_CACHE__ENABLE (1 << 29)
-#define SMMU_PTC_CONFIG_INDEX_MAP__PATTERN 0x3f
-#define SMMU_PTC_CONFIG_RESET_VAL 0x2000003f
-
-#define SMMU_PTB_ASID 0x1c
-#define SMMU_PTB_ASID_CURRENT_SHIFT 0
-
-#define SMMU_PTB_DATA 0x20
-#define SMMU_PTB_DATA_RESET_VAL 0
-#define SMMU_PTB_DATA_ASID_NONSECURE_SHIFT 29
-#define SMMU_PTB_DATA_ASID_WRITABLE_SHIFT 30
-#define SMMU_PTB_DATA_ASID_READABLE_SHIFT 31
-
-#define SMMU_TLB_FLUSH 0x30
-#define SMMU_TLB_FLUSH_VA_MATCH_ALL 0
-#define SMMU_TLB_FLUSH_VA_MATCH_SECTION 2
-#define SMMU_TLB_FLUSH_VA_MATCH_GROUP 3
-#define SMMU_TLB_FLUSH_ASID_SHIFT 29
-#define SMMU_TLB_FLUSH_ASID_MATCH_DISABLE 0
-#define SMMU_TLB_FLUSH_ASID_MATCH_ENABLE 1
-#define SMMU_TLB_FLUSH_ASID_MATCH_SHIFT 31
-
-#define SMMU_PTC_FLUSH 0x34
-#define SMMU_PTC_FLUSH_TYPE_ALL 0
-#define SMMU_PTC_FLUSH_TYPE_ADR 1
-#define SMMU_PTC_FLUSH_ADR_SHIFT 4
-
-#define SMMU_ASID_SECURITY 0x38
-
-#define SMMU_STATS_TLB_HIT_COUNT 0x1f0
-#define SMMU_STATS_TLB_MISS_COUNT 0x1f4
-#define SMMU_STATS_PTC_HIT_COUNT 0x1f8
-#define SMMU_STATS_PTC_MISS_COUNT 0x1fc
-
-#define SMMU_TRANSLATION_ENABLE_0 0x228
-#define SMMU_TRANSLATION_ENABLE_1 0x22c
-#define SMMU_TRANSLATION_ENABLE_2 0x230
-
-#define SMMU_AFI_ASID 0x238 /* PCIE */
-#define SMMU_AVPC_ASID 0x23c /* AVP */
-#define SMMU_DC_ASID 0x240 /* Display controller */
-#define SMMU_DCB_ASID 0x244 /* Display controller B */
-#define SMMU_EPP_ASID 0x248 /* Encoder pre-processor */
-#define SMMU_G2_ASID 0x24c /* 2D engine */
-#define SMMU_HC_ASID 0x250 /* Host1x */
-#define SMMU_HDA_ASID 0x254 /* High-def audio */
-#define SMMU_ISP_ASID 0x258 /* Image signal processor */
-#define SMMU_MPE_ASID 0x264 /* MPEG encoder */
-#define SMMU_NV_ASID 0x268 /* (3D) */
-#define SMMU_NV2_ASID 0x26c /* (3D) */
-#define SMMU_PPCS_ASID 0x270 /* AHB */
-#define SMMU_SATA_ASID 0x278 /* SATA */
-#define SMMU_VDE_ASID 0x27c /* Video decoder */
-#define SMMU_VI_ASID 0x280 /* Video input */
-
-#define SMMU_PDE_NEXT_SHIFT 28
-
-/* AHB Arbiter Registers */
-#define AHB_XBAR_CTRL 0xe0
-#define AHB_XBAR_CTRL_SMMU_INIT_DONE_DONE 1
-#define AHB_XBAR_CTRL_SMMU_INIT_DONE_SHIFT 17
-
-#define SMMU_NUM_ASIDS 4
-#define SMMU_TLB_FLUSH_VA_SECTION__MASK 0xffc00000
-#define SMMU_TLB_FLUSH_VA_SECTION__SHIFT 12 /* right shift */
-#define SMMU_TLB_FLUSH_VA_GROUP__MASK 0xffffc000
-#define SMMU_TLB_FLUSH_VA_GROUP__SHIFT 12 /* right shift */
-#define SMMU_TLB_FLUSH_VA(iova, which) \
- ((((iova) & SMMU_TLB_FLUSH_VA_##which##__MASK) >> \
- SMMU_TLB_FLUSH_VA_##which##__SHIFT) | \
- SMMU_TLB_FLUSH_VA_MATCH_##which)
-#define SMMU_PTB_ASID_CUR(n) \
- ((n) << SMMU_PTB_ASID_CURRENT_SHIFT)
-#define SMMU_TLB_FLUSH_ASID_MATCH_disable \
- (SMMU_TLB_FLUSH_ASID_MATCH_DISABLE << \
- SMMU_TLB_FLUSH_ASID_MATCH_SHIFT)
-#define SMMU_TLB_FLUSH_ASID_MATCH__ENABLE \
- (SMMU_TLB_FLUSH_ASID_MATCH_ENABLE << \
- SMMU_TLB_FLUSH_ASID_MATCH_SHIFT)
-
-#define SMMU_PAGE_SHIFT 12
-#define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT)
-
-#define SMMU_PDIR_COUNT 1024
-#define SMMU_PDIR_SIZE (sizeof(unsigned long) * SMMU_PDIR_COUNT)
-#define SMMU_PTBL_COUNT 1024
-#define SMMU_PTBL_SIZE (sizeof(unsigned long) * SMMU_PTBL_COUNT)
-#define SMMU_PDIR_SHIFT 12
-#define SMMU_PDE_SHIFT 12
-#define SMMU_PTE_SHIFT 12
-#define SMMU_PFN_MASK 0x000fffff
-
-#define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
-#define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
-#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22)
-
-#define _READABLE (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT)
-#define _WRITABLE (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT)
-#define _NONSECURE (1 << SMMU_PTB_DATA_ASID_NONSECURE_SHIFT)
-#define _PDE_NEXT (1 << SMMU_PDE_NEXT_SHIFT)
-#define _MASK_ATTR (_READABLE | _WRITABLE | _NONSECURE)
-
-#define _PDIR_ATTR (_READABLE | _WRITABLE | _NONSECURE)
-
-#define _PDE_ATTR (_READABLE | _WRITABLE | _NONSECURE)
-#define _PDE_ATTR_N (_PDE_ATTR | _PDE_NEXT)
-#define _PDE_VACANT(pdn) (((pdn) << 10) | _PDE_ATTR)
-
-#define _PTE_ATTR (_READABLE | _WRITABLE | _NONSECURE)
-#define _PTE_VACANT(addr) (((addr) >> SMMU_PAGE_SHIFT) | _PTE_ATTR)
-
-#define SMMU_MK_PDIR(page, attr) \
- ((page_to_phys(page) >> SMMU_PDIR_SHIFT) | (attr))
-#define SMMU_MK_PDE(page, attr) \
- (unsigned long)((page_to_phys(page) >> SMMU_PDE_SHIFT) | (attr))
-#define SMMU_EX_PTBL_PAGE(pde) \
- pfn_to_page((unsigned long)(pde) & SMMU_PFN_MASK)
-#define SMMU_PFN_TO_PTE(pfn, attr) (unsigned long)((pfn) | (attr))
-
-#define SMMU_ASID_ENABLE(asid) ((asid) | (1 << 31))
-#define SMMU_ASID_DISABLE 0
-#define SMMU_ASID_ASID(n) ((n) & ~SMMU_ASID_ENABLE(0))
-
-#define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1)
-#define smmu_client_disable_hwgrp(c) smmu_client_set_hwgrp(c, 0, 0)
-#define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1)
-#define __smmu_client_disable_hwgrp(c) __smmu_client_set_hwgrp(c, 0, 0)
-
-#define HWGRP_INIT(client) [HWGRP_##client] = SMMU_##client##_ASID
-
-static const u32 smmu_hwgrp_asid_reg[] = {
- HWGRP_INIT(AFI),
- HWGRP_INIT(AVPC),
- HWGRP_INIT(DC),
- HWGRP_INIT(DCB),
- HWGRP_INIT(EPP),
- HWGRP_INIT(G2),
- HWGRP_INIT(HC),
- HWGRP_INIT(HDA),
- HWGRP_INIT(ISP),
- HWGRP_INIT(MPE),
- HWGRP_INIT(NV),
- HWGRP_INIT(NV2),
- HWGRP_INIT(PPCS),
- HWGRP_INIT(SATA),
- HWGRP_INIT(VDE),
- HWGRP_INIT(VI),
-};
-#define HWGRP_ASID_REG(x) (smmu_hwgrp_asid_reg[x])
-
-/*
- * Per client for address space
- */
-struct smmu_client {
- struct device *dev;
- struct list_head list;
- struct smmu_as *as;
- u32 hwgrp;
-};
-
-/*
- * Per address space
- */
-struct smmu_as {
- struct smmu_device *smmu; /* back pointer to container */
- unsigned int asid;
- spinlock_t lock; /* for pagetable */
- struct page *pdir_page;
- unsigned long pdir_attr;
- unsigned long pde_attr;
- unsigned long pte_attr;
- unsigned int *pte_count;
-
- struct list_head client;
- spinlock_t client_lock; /* for client list */
-};
-
-/*
- * Per SMMU device - IOMMU device
- */
-struct smmu_device {
- void __iomem *regs, *regs_ahbarb;
- unsigned long iovmm_base; /* remappable base address */
- unsigned long page_count; /* total remappable size */
- spinlock_t lock;
- char *name;
- struct device *dev;
- int num_as;
- struct smmu_as *as; /* Run-time allocated array */
- struct page *avp_vector_page; /* dummy page shared by all AS's */
-
- /*
- * Register image savers for suspend/resume
- */
- unsigned long translation_enable_0;
- unsigned long translation_enable_1;
- unsigned long translation_enable_2;
- unsigned long asid_security;
-};
-
-static struct smmu_device *smmu_handle; /* unique for a system */
-
-/*
- * SMMU/AHB register accessors
- */
-static inline u32 smmu_read(struct smmu_device *smmu, size_t offs)
-{
- return readl(smmu->regs + offs);
-}
-static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs)
-{
- writel(val, smmu->regs + offs);
-}
-
-static inline u32 ahb_read(struct smmu_device *smmu, size_t offs)
-{
- return readl(smmu->regs_ahbarb + offs);
-}
-static inline void ahb_write(struct smmu_device *smmu, u32 val, size_t offs)
-{
- writel(val, smmu->regs_ahbarb + offs);
-}
-
-#define VA_PAGE_TO_PA(va, page) \
- (page_to_phys(page) + ((unsigned long)(va) & ~PAGE_MASK))
-
-#define FLUSH_CPU_DCACHE(va, page, size) \
- do { \
- unsigned long _pa_ = VA_PAGE_TO_PA(va, page); \
- __cpuc_flush_dcache_area((void *)(va), (size_t)(size)); \
- outer_flush_range(_pa_, _pa_+(size_t)(size)); \
- } while (0)
-
-/*
- * Any interaction between any block on PPSB and a block on APB or AHB
- * must have these read-back barriers to ensure the APB/AHB bus
- * transaction is complete before initiating activity on the PPSB
- * block.
- */
-#define FLUSH_SMMU_REGS(smmu) smmu_read(smmu, SMMU_CONFIG)
-
-#define smmu_client_hwgrp(c) (u32)((c)->dev->platform_data)
-
-static int __smmu_client_set_hwgrp(struct smmu_client *c,
- unsigned long map, int on)
-{
- int i;
- struct smmu_as *as = c->as;
- u32 val, offs, mask = SMMU_ASID_ENABLE(as->asid);
- struct smmu_device *smmu = as->smmu;
-
- WARN_ON(!on && map);
- if (on && !map)
- return -EINVAL;
- if (!on)
- map = smmu_client_hwgrp(c);
-
- for_each_set_bit(i, &map, HWGRP_COUNT) {
- offs = HWGRP_ASID_REG(i);
- val = smmu_read(smmu, offs);
- if (on) {
- if (WARN_ON(val & mask))
- goto err_hw_busy;
- val |= mask;
- } else {
- WARN_ON((val & mask) == mask);
- val &= ~mask;
- }
- smmu_write(smmu, val, offs);
- }
- FLUSH_SMMU_REGS(smmu);
- c->hwgrp = map;
- return 0;
-
-err_hw_busy:
- for_each_set_bit(i, &map, HWGRP_COUNT) {
- offs = HWGRP_ASID_REG(i);
- val = smmu_read(smmu, offs);
- val &= ~mask;
- smmu_write(smmu, val, offs);
- }
- return -EBUSY;
-}
-
-static int smmu_client_set_hwgrp(struct smmu_client *c, u32 map, int on)
-{
- u32 val;
- unsigned long flags;
- struct smmu_as *as = c->as;
- struct smmu_device *smmu = as->smmu;
-
- spin_lock_irqsave(&smmu->lock, flags);
- val = __smmu_client_set_hwgrp(c, map, on);
- spin_unlock_irqrestore(&smmu->lock, flags);
- return val;
-}
-
-/*
- * Flush all TLB entries and all PTC entries
- * Caller must lock smmu
- */
-static void smmu_flush_regs(struct smmu_device *smmu, int enable)
-{
- u32 val;
-
- smmu_write(smmu, SMMU_PTC_FLUSH_TYPE_ALL, SMMU_PTC_FLUSH);
- FLUSH_SMMU_REGS(smmu);
- val = SMMU_TLB_FLUSH_VA_MATCH_ALL |
- SMMU_TLB_FLUSH_ASID_MATCH_disable;
- smmu_write(smmu, val, SMMU_TLB_FLUSH);
-
- if (enable)
- smmu_write(smmu, SMMU_CONFIG_ENABLE, SMMU_CONFIG);
- FLUSH_SMMU_REGS(smmu);
-}
-
-static void smmu_setup_regs(struct smmu_device *smmu)
-{
- int i;
- u32 val;
-
- for (i = 0; i < smmu->num_as; i++) {
- struct smmu_as *as = &smmu->as[i];
- struct smmu_client *c;
-
- smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID);
- val = as->pdir_page ?
- SMMU_MK_PDIR(as->pdir_page, as->pdir_attr) :
- SMMU_PTB_DATA_RESET_VAL;
- smmu_write(smmu, val, SMMU_PTB_DATA);
-
- list_for_each_entry(c, &as->client, list)
- __smmu_client_set_hwgrp(c, c->hwgrp, 1);
- }
-
- smmu_write(smmu, smmu->translation_enable_0, SMMU_TRANSLATION_ENABLE_0);
- smmu_write(smmu, smmu->translation_enable_1, SMMU_TRANSLATION_ENABLE_1);
- smmu_write(smmu, smmu->translation_enable_2, SMMU_TRANSLATION_ENABLE_2);
- smmu_write(smmu, smmu->asid_security, SMMU_ASID_SECURITY);
- smmu_write(smmu, SMMU_TLB_CONFIG_RESET_VAL, SMMU_TLB_CONFIG);
- smmu_write(smmu, SMMU_PTC_CONFIG_RESET_VAL, SMMU_PTC_CONFIG);
-
- smmu_flush_regs(smmu, 1);
-
- val = ahb_read(smmu, AHB_XBAR_CTRL);
- val |= AHB_XBAR_CTRL_SMMU_INIT_DONE_DONE <<
- AHB_XBAR_CTRL_SMMU_INIT_DONE_SHIFT;
- ahb_write(smmu, val, AHB_XBAR_CTRL);
-}
-
-static void flush_ptc_and_tlb(struct smmu_device *smmu,
- struct smmu_as *as, dma_addr_t iova,
- unsigned long *pte, struct page *page, int is_pde)
-{
- u32 val;
- unsigned long tlb_flush_va = is_pde
- ? SMMU_TLB_FLUSH_VA(iova, SECTION)
- : SMMU_TLB_FLUSH_VA(iova, GROUP);
-
- val = SMMU_PTC_FLUSH_TYPE_ADR | VA_PAGE_TO_PA(pte, page);
- smmu_write(smmu, val, SMMU_PTC_FLUSH);
- FLUSH_SMMU_REGS(smmu);
- val = tlb_flush_va |
- SMMU_TLB_FLUSH_ASID_MATCH__ENABLE |
- (as->asid << SMMU_TLB_FLUSH_ASID_SHIFT);
- smmu_write(smmu, val, SMMU_TLB_FLUSH);
- FLUSH_SMMU_REGS(smmu);
-}
-
-static void free_ptbl(struct smmu_as *as, dma_addr_t iova)
-{
- unsigned long pdn = SMMU_ADDR_TO_PDN(iova);
- unsigned long *pdir = (unsigned long *)page_address(as->pdir_page);
-
- if (pdir[pdn] != _PDE_VACANT(pdn)) {
- dev_dbg(as->smmu->dev, "pdn: %lx\n", pdn);
-
- ClearPageReserved(SMMU_EX_PTBL_PAGE(pdir[pdn]));
- __free_page(SMMU_EX_PTBL_PAGE(pdir[pdn]));
- pdir[pdn] = _PDE_VACANT(pdn);
- FLUSH_CPU_DCACHE(&pdir[pdn], as->pdir_page, sizeof pdir[pdn]);
- flush_ptc_and_tlb(as->smmu, as, iova, &pdir[pdn],
- as->pdir_page, 1);
- }
-}
-
-static void free_pdir(struct smmu_as *as)
-{
- unsigned addr;
- int count;
- struct device *dev = as->smmu->dev;
-
- if (!as->pdir_page)
- return;
-
- addr = as->smmu->iovmm_base;
- count = as->smmu->page_count;
- while (count-- > 0) {
- free_ptbl(as, addr);
- addr += SMMU_PAGE_SIZE * SMMU_PTBL_COUNT;
- }
- ClearPageReserved(as->pdir_page);
- __free_page(as->pdir_page);
- as->pdir_page = NULL;
- devm_kfree(dev, as->pte_count);
- as->pte_count = NULL;
-}
-
-/*
- * Maps PTBL for given iova and returns the PTE address
- * Caller must unmap the mapped PTBL returned in *ptbl_page_p
- */
-static unsigned long *locate_pte(struct smmu_as *as,
- dma_addr_t iova, bool allocate,
- struct page **ptbl_page_p,
- unsigned int **count)
-{
- unsigned long ptn = SMMU_ADDR_TO_PFN(iova);
- unsigned long pdn = SMMU_ADDR_TO_PDN(iova);
- unsigned long *pdir = page_address(as->pdir_page);
- unsigned long *ptbl;
-
- if (pdir[pdn] != _PDE_VACANT(pdn)) {
- /* Mapped entry table already exists */
- *ptbl_page_p = SMMU_EX_PTBL_PAGE(pdir[pdn]);
- ptbl = page_address(*ptbl_page_p);
- } else if (!allocate) {
- return NULL;
- } else {
- int pn;
- unsigned long addr = SMMU_PDN_TO_ADDR(pdn);
-
- /* Vacant - allocate a new page table */
- dev_dbg(as->smmu->dev, "New PTBL pdn: %lx\n", pdn);
-
- *ptbl_page_p = alloc_page(GFP_ATOMIC);
- if (!*ptbl_page_p) {
- dev_err(as->smmu->dev,
- "failed to allocate smmu_device page table\n");
- return NULL;
- }
- SetPageReserved(*ptbl_page_p);
- ptbl = (unsigned long *)page_address(*ptbl_page_p);
- for (pn = 0; pn < SMMU_PTBL_COUNT;
- pn++, addr += SMMU_PAGE_SIZE) {
- ptbl[pn] = _PTE_VACANT(addr);
- }
- FLUSH_CPU_DCACHE(ptbl, *ptbl_page_p, SMMU_PTBL_SIZE);
- pdir[pdn] = SMMU_MK_PDE(*ptbl_page_p,
- as->pde_attr | _PDE_NEXT);
- FLUSH_CPU_DCACHE(&pdir[pdn], as->pdir_page, sizeof pdir[pdn]);
- flush_ptc_and_tlb(as->smmu, as, iova, &pdir[pdn],
- as->pdir_page, 1);
- }
- *count = &as->pte_count[pdn];
-
- return &ptbl[ptn % SMMU_PTBL_COUNT];
-}
-
-#ifdef CONFIG_SMMU_SIG_DEBUG
-static void put_signature(struct smmu_as *as,
- dma_addr_t iova, unsigned long pfn)
-{
- struct page *page;
- unsigned long *vaddr;
-
- page = pfn_to_page(pfn);
- vaddr = page_address(page);
- if (!vaddr)
- return;
-
- vaddr[0] = iova;
- vaddr[1] = pfn << PAGE_SHIFT;
- FLUSH_CPU_DCACHE(vaddr, page, sizeof(vaddr[0]) * 2);
-}
-#else
-static inline void put_signature(struct smmu_as *as,
- unsigned long addr, unsigned long pfn)
-{
-}
-#endif
-
-/*
- * Caller must lock/unlock as
- */
-static int alloc_pdir(struct smmu_as *as)
-{
- unsigned long *pdir;
- int pdn;
- u32 val;
- struct smmu_device *smmu = as->smmu;
-
- if (as->pdir_page)
- return 0;
-
- as->pte_count = devm_kzalloc(smmu->dev,
- sizeof(as->pte_count[0]) * SMMU_PDIR_COUNT, GFP_KERNEL);
- if (!as->pte_count) {
- dev_err(smmu->dev,
- "failed to allocate smmu_device PTE cunters\n");
- return -ENOMEM;
- }
- as->pdir_page = alloc_page(GFP_KERNEL | __GFP_DMA);
- if (!as->pdir_page) {
- dev_err(smmu->dev,
- "failed to allocate smmu_device page directory\n");
- devm_kfree(smmu->dev, as->pte_count);
- as->pte_count = NULL;
- return -ENOMEM;
- }
- SetPageReserved(as->pdir_page);
- pdir = page_address(as->pdir_page);
-
- for (pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++)
- pdir[pdn] = _PDE_VACANT(pdn);
- FLUSH_CPU_DCACHE(pdir, as->pdir_page, SMMU_PDIR_SIZE);
- val = SMMU_PTC_FLUSH_TYPE_ADR | VA_PAGE_TO_PA(pdir, as->pdir_page);
- smmu_write(smmu, val, SMMU_PTC_FLUSH);
- FLUSH_SMMU_REGS(as->smmu);
- val = SMMU_TLB_FLUSH_VA_MATCH_ALL |
- SMMU_TLB_FLUSH_ASID_MATCH__ENABLE |
- (as->asid << SMMU_TLB_FLUSH_ASID_SHIFT);
- smmu_write(smmu, val, SMMU_TLB_FLUSH);
- FLUSH_SMMU_REGS(as->smmu);
-
- return 0;
-}
-
-static void __smmu_iommu_unmap(struct smmu_as *as, dma_addr_t iova)
-{
- unsigned long *pte;
- struct page *page;
- unsigned int *count;
-
- pte = locate_pte(as, iova, false, &page, &count);
- if (WARN_ON(!pte))
- return;
-
- if (WARN_ON(*pte == _PTE_VACANT(iova)))
- return;
-
- *pte = _PTE_VACANT(iova);
- FLUSH_CPU_DCACHE(pte, page, sizeof(*pte));
- flush_ptc_and_tlb(as->smmu, as, iova, pte, page, 0);
- if (!--(*count)) {
- free_ptbl(as, iova);
- smmu_flush_regs(as->smmu, 0);
- }
-}
-
-static void __smmu_iommu_map_pfn(struct smmu_as *as, dma_addr_t iova,
- unsigned long pfn)
-{
- struct smmu_device *smmu = as->smmu;
- unsigned long *pte;
- unsigned int *count;
- struct page *page;
-
- pte = locate_pte(as, iova, true, &page, &count);
- if (WARN_ON(!pte))
- return;
-
- if (*pte == _PTE_VACANT(iova))
- (*count)++;
- *pte = SMMU_PFN_TO_PTE(pfn, as->pte_attr);
- if (unlikely((*pte == _PTE_VACANT(iova))))
- (*count)--;
- FLUSH_CPU_DCACHE(pte, page, sizeof(*pte));
- flush_ptc_and_tlb(smmu, as, iova, pte, page, 0);
- put_signature(as, iova, pfn);
-}
-
-static int smmu_iommu_map(struct iommu_domain *domain, unsigned long iova,
- phys_addr_t pa, size_t bytes, int prot)
-{
- struct smmu_as *as = domain->priv;
- unsigned long pfn = __phys_to_pfn(pa);
- unsigned long flags;
-
- dev_dbg(as->smmu->dev, "[%d] %08lx:%08x\n", as->asid, iova, pa);
-
- if (!pfn_valid(pfn))
- return -ENOMEM;
-
- spin_lock_irqsave(&as->lock, flags);
- __smmu_iommu_map_pfn(as, iova, pfn);
- spin_unlock_irqrestore(&as->lock, flags);
- return 0;
-}
-
-static size_t smmu_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
- size_t bytes)
-{
- struct smmu_as *as = domain->priv;
- unsigned long flags;
-
- dev_dbg(as->smmu->dev, "[%d] %08lx\n", as->asid, iova);
-
- spin_lock_irqsave(&as->lock, flags);
- __smmu_iommu_unmap(as, iova);
- spin_unlock_irqrestore(&as->lock, flags);
- return SMMU_PAGE_SIZE;
-}
-
-static phys_addr_t smmu_iommu_iova_to_phys(struct iommu_domain *domain,
- unsigned long iova)
-{
- struct smmu_as *as = domain->priv;
- unsigned long *pte;
- unsigned int *count;
- struct page *page;
- unsigned long pfn;
- unsigned long flags;
-
- spin_lock_irqsave(&as->lock, flags);
-
- pte = locate_pte(as, iova, true, &page, &count);
- pfn = *pte & SMMU_PFN_MASK;
- WARN_ON(!pfn_valid(pfn));
- dev_dbg(as->smmu->dev,
- "iova:%08lx pfn:%08lx asid:%d\n", iova, pfn, as->asid);
-
- spin_unlock_irqrestore(&as->lock, flags);
- return PFN_PHYS(pfn);
-}
-
-static int smmu_iommu_domain_has_cap(struct iommu_domain *domain,
- unsigned long cap)
-{
- return 0;
-}
-
-static int smmu_iommu_attach_dev(struct iommu_domain *domain,
- struct device *dev)
-{
- struct smmu_as *as = domain->priv;
- struct smmu_device *smmu = as->smmu;
- struct smmu_client *client, *c;
- u32 map;
- int err;
-
- client = devm_kzalloc(smmu->dev, sizeof(*c), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- client->dev = dev;
- client->as = as;
- map = (unsigned long)dev->platform_data;
- if (!map)
- return -EINVAL;
-
- err = smmu_client_enable_hwgrp(client, map);
- if (err)
- goto err_hwgrp;
-
- spin_lock(&as->client_lock);
- list_for_each_entry(c, &as->client, list) {
- if (c->dev == dev) {
- dev_err(smmu->dev,
- "%s is already attached\n", dev_name(c->dev));
- err = -EINVAL;
- goto err_client;
- }
- }
- list_add(&client->list, &as->client);
- spin_unlock(&as->client_lock);
-
- /*
- * Reserve "page zero" for AVP vectors using a common dummy
- * page.
- */
- if (map & HWG_AVPC) {
- struct page *page;
-
- page = as->smmu->avp_vector_page;
- __smmu_iommu_map_pfn(as, 0, page_to_pfn(page));
-
- pr_info("Reserve \"page zero\" for AVP vectors using a common dummy\n");
- }
-
- dev_dbg(smmu->dev, "%s is attached\n", dev_name(c->dev));
- return 0;
-
-err_client:
- smmu_client_disable_hwgrp(client);
- spin_unlock(&as->client_lock);
-err_hwgrp:
- devm_kfree(smmu->dev, client);
- return err;
-}
-
-static void smmu_iommu_detach_dev(struct iommu_domain *domain,
- struct device *dev)
-{
- struct smmu_as *as = domain->priv;
- struct smmu_device *smmu = as->smmu;
- struct smmu_client *c;
-
- spin_lock(&as->client_lock);
-
- list_for_each_entry(c, &as->client, list) {
- if (c->dev == dev) {
- smmu_client_disable_hwgrp(c);
- list_del(&c->list);
- devm_kfree(smmu->dev, c);
- c->as = NULL;
- dev_dbg(smmu->dev,
- "%s is detached\n", dev_name(c->dev));
- goto out;
- }
- }
- dev_err(smmu->dev, "Couldn't find %s\n", dev_name(c->dev));
-out:
- spin_unlock(&as->client_lock);
-}
-
-static int smmu_iommu_domain_init(struct iommu_domain *domain)
-{
- int i;
- unsigned long flags;
- struct smmu_as *as;
- struct smmu_device *smmu = smmu_handle;
-
- /* Look for a free AS with lock held */
- for (i = 0; i < smmu->num_as; i++) {
- struct smmu_as *tmp = &smmu->as[i];
-
- spin_lock_irqsave(&tmp->lock, flags);
- if (!tmp->pdir_page) {
- as = tmp;
- goto found;
- }
- spin_unlock_irqrestore(&tmp->lock, flags);
- }
- dev_err(smmu->dev, "no free AS\n");
- return -ENODEV;
-
-found:
- if (alloc_pdir(as) < 0)
- goto err_alloc_pdir;
-
- spin_lock(&smmu->lock);
-
- /* Update PDIR register */
- smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID);
- smmu_write(smmu,
- SMMU_MK_PDIR(as->pdir_page, as->pdir_attr), SMMU_PTB_DATA);
- FLUSH_SMMU_REGS(smmu);
-
- spin_unlock(&smmu->lock);
-
- spin_unlock_irqrestore(&as->lock, flags);
- domain->priv = as;
-
- dev_dbg(smmu->dev, "smmu_as@%p\n", as);
- return 0;
-
-err_alloc_pdir:
- spin_unlock_irqrestore(&as->lock, flags);
- return -ENODEV;
-}
-
-static void smmu_iommu_domain_destroy(struct iommu_domain *domain)
-{
- struct smmu_as *as = domain->priv;
- struct smmu_device *smmu = as->smmu;
- unsigned long flags;
-
- spin_lock_irqsave(&as->lock, flags);
-
- if (as->pdir_page) {
- spin_lock(&smmu->lock);
- smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID);
- smmu_write(smmu, SMMU_PTB_DATA_RESET_VAL, SMMU_PTB_DATA);
- FLUSH_SMMU_REGS(smmu);
- spin_unlock(&smmu->lock);
-
- free_pdir(as);
- }
-
- if (!list_empty(&as->client)) {
- struct smmu_client *c;
-
- list_for_each_entry(c, &as->client, list)
- smmu_iommu_detach_dev(domain, c->dev);
- }
-
- spin_unlock_irqrestore(&as->lock, flags);
-
- domain->priv = NULL;
- dev_dbg(smmu->dev, "smmu_as@%p\n", as);
-}
-
-static struct iommu_ops smmu_iommu_ops = {
- .domain_init = smmu_iommu_domain_init,
- .domain_destroy = smmu_iommu_domain_destroy,
- .attach_dev = smmu_iommu_attach_dev,
- .detach_dev = smmu_iommu_detach_dev,
- .map = smmu_iommu_map,
- .unmap = smmu_iommu_unmap,
- .iova_to_phys = smmu_iommu_iova_to_phys,
- .domain_has_cap = smmu_iommu_domain_has_cap,
- .pgsize_bitmap = SMMU_IOMMU_PGSIZES,
-};
-
-static int tegra_smmu_suspend(struct device *dev)
-{
- struct smmu_device *smmu = dev_get_drvdata(dev);
-
- smmu->translation_enable_0 = smmu_read(smmu, SMMU_TRANSLATION_ENABLE_0);
- smmu->translation_enable_1 = smmu_read(smmu, SMMU_TRANSLATION_ENABLE_1);
- smmu->translation_enable_2 = smmu_read(smmu, SMMU_TRANSLATION_ENABLE_2);
- smmu->asid_security = smmu_read(smmu, SMMU_ASID_SECURITY);
- return 0;
-}
-
-static int tegra_smmu_resume(struct device *dev)
-{
- struct smmu_device *smmu = dev_get_drvdata(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&smmu->lock, flags);
- smmu_setup_regs(smmu);
- spin_unlock_irqrestore(&smmu->lock, flags);
- return 0;
-}
-
-static int tegra_smmu_probe(struct platform_device *pdev)
-{
- struct smmu_device *smmu;
- struct resource *regs, *regs2, *window;
- struct device *dev = &pdev->dev;
- int i, err = 0;
-
- if (smmu_handle)
- return -EIO;
-
- BUILD_BUG_ON(PAGE_SHIFT != SMMU_PAGE_SHIFT);
-
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- regs2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- window = platform_get_resource(pdev, IORESOURCE_MEM, 2);
- if (!regs || !regs2 || !window) {
- dev_err(dev, "No SMMU resources\n");
- return -ENODEV;
- }
-
- smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
- if (!smmu) {
- dev_err(dev, "failed to allocate smmu_device\n");
- return -ENOMEM;
- }
-
- smmu->dev = dev;
- smmu->num_as = SMMU_NUM_ASIDS;
- smmu->iovmm_base = (unsigned long)window->start;
- smmu->page_count = resource_size(window) >> SMMU_PAGE_SHIFT;
- smmu->regs = devm_ioremap(dev, regs->start, resource_size(regs));
- smmu->regs_ahbarb = devm_ioremap(dev, regs2->start,
- resource_size(regs2));
- if (!smmu->regs || !smmu->regs_ahbarb) {
- dev_err(dev, "failed to remap SMMU registers\n");
- err = -ENXIO;
- goto fail;
- }
-
- smmu->translation_enable_0 = ~0;
- smmu->translation_enable_1 = ~0;
- smmu->translation_enable_2 = ~0;
- smmu->asid_security = 0;
-
- smmu->as = devm_kzalloc(dev,
- sizeof(smmu->as[0]) * smmu->num_as, GFP_KERNEL);
- if (!smmu->as) {
- dev_err(dev, "failed to allocate smmu_as\n");
- err = -ENOMEM;
- goto fail;
- }
-
- for (i = 0; i < smmu->num_as; i++) {
- struct smmu_as *as = &smmu->as[i];
-
- as->smmu = smmu;
- as->asid = i;
- as->pdir_attr = _PDIR_ATTR;
- as->pde_attr = _PDE_ATTR;
- as->pte_attr = _PTE_ATTR;
-
- spin_lock_init(&as->lock);
- INIT_LIST_HEAD(&as->client);
- }
- spin_lock_init(&smmu->lock);
- smmu_setup_regs(smmu);
- platform_set_drvdata(pdev, smmu);
-
- smmu->avp_vector_page = alloc_page(GFP_KERNEL);
- if (!smmu->avp_vector_page)
- goto fail;
-
- smmu_handle = smmu;
- return 0;
-
-fail:
- if (smmu->avp_vector_page)
- __free_page(smmu->avp_vector_page);
- if (smmu->regs)
- devm_iounmap(dev, smmu->regs);
- if (smmu->regs_ahbarb)
- devm_iounmap(dev, smmu->regs_ahbarb);
- if (smmu && smmu->as) {
- for (i = 0; i < smmu->num_as; i++) {
- if (smmu->as[i].pdir_page) {
- ClearPageReserved(smmu->as[i].pdir_page);
- __free_page(smmu->as[i].pdir_page);
- }
- }
- devm_kfree(dev, smmu->as);
- }
- devm_kfree(dev, smmu);
- return err;
-}
-
-static int tegra_smmu_remove(struct platform_device *pdev)
-{
- struct smmu_device *smmu = platform_get_drvdata(pdev);
- struct device *dev = smmu->dev;
-
- smmu_write(smmu, SMMU_CONFIG_DISABLE, SMMU_CONFIG);
- platform_set_drvdata(pdev, NULL);
- if (smmu->as) {
- int i;
-
- for (i = 0; i < smmu->num_as; i++)
- free_pdir(&smmu->as[i]);
- devm_kfree(dev, smmu->as);
- }
- if (smmu->avp_vector_page)
- __free_page(smmu->avp_vector_page);
- if (smmu->regs)
- devm_iounmap(dev, smmu->regs);
- if (smmu->regs_ahbarb)
- devm_iounmap(dev, smmu->regs_ahbarb);
- devm_kfree(dev, smmu);
- smmu_handle = NULL;
- return 0;
-}
-
-const struct dev_pm_ops tegra_smmu_pm_ops = {
- .suspend = tegra_smmu_suspend,
- .resume = tegra_smmu_resume,
-};
-
-static struct platform_driver tegra_smmu_driver = {
- .probe = tegra_smmu_probe,
- .remove = tegra_smmu_remove,
- .driver = {
- .owner = THIS_MODULE,
- .name = "tegra-smmu",
- .pm = &tegra_smmu_pm_ops,
- },
-};
-
-static int __devinit tegra_smmu_init(void)
-{
- bus_set_iommu(&platform_bus_type, &smmu_iommu_ops);
- return platform_driver_register(&tegra_smmu_driver);
-}
-
-static void __exit tegra_smmu_exit(void)
-{
- platform_driver_unregister(&tegra_smmu_driver);
-}
-
-subsys_initcall(tegra_smmu_init);
-module_exit(tegra_smmu_exit);
-
-MODULE_DESCRIPTION("IOMMU API for SMMU in Tegra30");
-MODULE_AUTHOR("Hiroshi DOYU ");
-MODULE_LICENSE("GPL v2");
diff --git a/trunk/drivers/media/common/tuners/Makefile b/trunk/drivers/media/common/tuners/Makefile
index f80407eb8998..8295854ab94b 100644
--- a/trunk/drivers/media/common/tuners/Makefile
+++ b/trunk/drivers/media/common/tuners/Makefile
@@ -29,5 +29,5 @@ obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/trunk/drivers/media/common/tuners/max2165.c b/trunk/drivers/media/common/tuners/max2165.c
index ba84936aafd6..cb2c98fbad1b 100644
--- a/trunk/drivers/media/common/tuners/max2165.c
+++ b/trunk/drivers/media/common/tuners/max2165.c
@@ -168,7 +168,7 @@ int fixpt_div32(u32 dividend, u32 divisor, u32 *quotient, u32 *fraction)
int i;
if (0 == divisor)
- return -EINVAL;
+ return -1;
q = dividend / divisor;
remainder = dividend - q * divisor;
@@ -194,13 +194,10 @@ static int max2165_set_rf(struct max2165_priv *priv, u32 freq)
u8 tf_ntch;
u32 t;
u32 quotient, fraction;
- int ret;
/* Set PLL divider according to RF frequency */
- ret = fixpt_div32(freq / 1000, priv->config->osc_clk * 1000,
- "ient, &fraction);
- if (ret != 0)
- return ret;
+ fixpt_div32(freq / 1000, priv->config->osc_clk * 1000,
+ "ient, &fraction);
/* 20-bit fraction */
fraction >>= 12;
diff --git a/trunk/drivers/media/common/tuners/mt2063.c b/trunk/drivers/media/common/tuners/mt2063.c
index 0ed9091ff48e..c89af3cd5eba 100644
--- a/trunk/drivers/media/common/tuners/mt2063.c
+++ b/trunk/drivers/media/common/tuners/mt2063.c
@@ -350,7 +350,7 @@ static int MT2063_Sleep(struct dvb_frontend *fe)
/*
* ToDo: Add code here to implement a OS blocking
*/
- msleep(100);
+ msleep(10);
return 0;
}
@@ -2226,7 +2226,7 @@ static struct dvb_tuner_ops mt2063_ops = {
.info = {
.name = "MT2063 Silicon Tuner",
.frequency_min = 45000000,
- .frequency_max = 865000000,
+ .frequency_max = 850000000,
.frequency_step = 0,
},
diff --git a/trunk/drivers/media/common/tuners/mt2063.h b/trunk/drivers/media/common/tuners/mt2063.h
index 3f5cfd93713f..62d0e8ec4e99 100644
--- a/trunk/drivers/media/common/tuners/mt2063.h
+++ b/trunk/drivers/media/common/tuners/mt2063.h
@@ -23,6 +23,10 @@ static inline struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
return NULL;
}
+int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
+ u32 bw_in,
+ enum MTTune_atv_standard tv_type);
+
/* FIXME: Should use the standard DVB attachment interfaces */
unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe);
unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe);
diff --git a/trunk/drivers/media/common/tuners/tuner-types.c b/trunk/drivers/media/common/tuners/tuner-types.c
index 2da4440c16ee..e13683bab6b3 100644
--- a/trunk/drivers/media/common/tuners/tuner-types.c
+++ b/trunk/drivers/media/common/tuners/tuner-types.c
@@ -1868,10 +1868,6 @@ struct tunertype tuners[] = {
.params = tuner_tena_tnf_5337_params,
.count = ARRAY_SIZE(tuner_tena_tnf_5337_params),
},
- [TUNER_XC5000C] = { /* Xceive 5000C */
- .name = "Xceive 5000C tuner",
- /* see xc5000.c for details */
- },
};
EXPORT_SYMBOL(tuners);
diff --git a/trunk/drivers/media/common/tuners/xc5000.c b/trunk/drivers/media/common/tuners/xc5000.c
index 7f98984e4fad..296df05b8cda 100644
--- a/trunk/drivers/media/common/tuners/xc5000.c
+++ b/trunk/drivers/media/common/tuners/xc5000.c
@@ -49,6 +49,9 @@ static LIST_HEAD(hybrid_tuner_instance_list);
#define dprintk(level, fmt, arg...) if (debug >= level) \
printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
+#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.6.114.fw"
+#define XC5000_DEFAULT_FIRMWARE_SIZE 12401
+
struct xc5000_priv {
struct tuner_i2c_props i2c_props;
struct list_head hybrid_tuner_instance_list;
@@ -59,8 +62,6 @@ struct xc5000_priv {
u8 video_standard;
u8 rf_mode;
u8 radio_input;
-
- int chip_id;
};
/* Misc Defines */
@@ -203,33 +204,6 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
{"FM Radio-INPUT1_MONO", 0x0278, 0x9002}
};
-
-struct xc5000_fw_cfg {
- char *name;
- u16 size;
-};
-
-static const struct xc5000_fw_cfg xc5000a_1_6_114 = {
- .name = "dvb-fe-xc5000-1.6.114.fw",
- .size = 12401,
-};
-
-static const struct xc5000_fw_cfg xc5000c_41_024_5_31875 = {
- .name = "dvb-fe-xc5000c-41.024.5-31875.fw",
- .size = 16503,
-};
-
-static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
-{
- switch (chip_id) {
- default:
- case XC5000A:
- return &xc5000a_1_6_114;
- case XC5000C:
- return &xc5000c_41_024_5_31875;
- }
-}
-
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val);
@@ -578,14 +552,12 @@ static int xc5000_fwupload(struct dvb_frontend *fe)
struct xc5000_priv *priv = fe->tuner_priv;
const struct firmware *fw;
int ret;
- const struct xc5000_fw_cfg *desired_fw =
- xc5000_assign_firmware(priv->chip_id);
/* request the firmware, this will block and timeout */
printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
- desired_fw->name);
+ XC5000_DEFAULT_FIRMWARE);
- ret = request_firmware(&fw, desired_fw->name,
+ ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE,
priv->i2c_props.adap->dev.parent);
if (ret) {
printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
@@ -597,7 +569,7 @@ static int xc5000_fwupload(struct dvb_frontend *fe)
ret = XC_RESULT_SUCCESS;
}
- if (fw->size != desired_fw->size) {
+ if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) {
printk(KERN_ERR "xc5000: firmware incorrect size\n");
ret = XC_RESULT_RESET_FAILURE;
} else {
@@ -1167,13 +1139,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
if (priv->radio_input == 0)
priv->radio_input = cfg->radio_input;
- /* don't override chip id if it's already been set
- unless explicitly specified */
- if ((priv->chip_id == 0) || (cfg->chip_id))
- /* use default chip id if none specified, set to 0 so
- it can be overridden if this is a hybrid driver */
- priv->chip_id = (cfg->chip_id) ? cfg->chip_id : 0;
-
/* Check if firmware has been loaded. It is possible that another
instance of the driver has loaded the firmware.
*/
diff --git a/trunk/drivers/media/common/tuners/xc5000.h b/trunk/drivers/media/common/tuners/xc5000.h
index 3396f8e02b40..e2957451b532 100644
--- a/trunk/drivers/media/common/tuners/xc5000.h
+++ b/trunk/drivers/media/common/tuners/xc5000.h
@@ -27,15 +27,10 @@
struct dvb_frontend;
struct i2c_adapter;
-#define XC5000A 1
-#define XC5000C 2
-
struct xc5000_config {
u8 i2c_address;
u32 if_khz;
u8 radio_input;
-
- int chip_id;
};
/* xc5000 callback command */
diff --git a/trunk/drivers/media/dvb/ddbridge/ddbridge-core.c b/trunk/drivers/media/dvb/ddbridge/ddbridge-core.c
index d88c4aa7d24d..ce4f85849e7b 100644
--- a/trunk/drivers/media/dvb/ddbridge/ddbridge-core.c
+++ b/trunk/drivers/media/dvb/ddbridge/ddbridge-core.c
@@ -578,7 +578,6 @@ static int demod_attach_drxk(struct ddb_input *input)
struct drxk_config config;
memset(&config, 0, sizeof(config));
- config.microcode_name = "drxk_a3.mc";
config.adr = 0x29 + (input->nr & 1);
fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
diff --git a/trunk/drivers/media/dvb/ddbridge/ddbridge.h b/trunk/drivers/media/dvb/ddbridge/ddbridge.h
index 8b1b41d2a52d..6d14893218f4 100644
--- a/trunk/drivers/media/dvb/ddbridge/ddbridge.h
+++ b/trunk/drivers/media/dvb/ddbridge/ddbridge.h
@@ -32,6 +32,8 @@
#include
#include
#include
+#include
+#include
#include
#include "dmxdev.h"
diff --git a/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c b/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c
index 4555baa383b2..fbbe545a74cb 100644
--- a/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -655,8 +655,6 @@ static int dvb_frontend_thread(void *data)
dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
re_tune = true;
fepriv->state = FESTATE_TUNED;
- } else {
- re_tune = false;
}
if (fe->ops.tune)
diff --git a/trunk/drivers/media/dvb/dvb-usb/Kconfig b/trunk/drivers/media/dvb/dvb-usb/Kconfig
index 63bf45679f98..9f203c6767a6 100644
--- a/trunk/drivers/media/dvb/dvb-usb/Kconfig
+++ b/trunk/drivers/media/dvb/dvb-usb/Kconfig
@@ -361,14 +361,6 @@ config DVB_USB_EC168
help
Say Y here to support the E3C EC168 DVB-T USB2.0 receiver.
-config DVB_USB_AZ6007
- tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support"
- depends on DVB_USB
- select DVB_DRXK if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_MT2063 if !DVB_FE_CUSTOMISE
- help
- Say Y here to support theAfatech AF9005 based DVB-T/DVB-C receivers.
-
config DVB_USB_AZ6027
tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support"
depends on DVB_USB
@@ -386,7 +378,6 @@ config DVB_USB_LME2510
select DVB_IX2505V if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_PLL if !DVB_FE_CUSTOMISE
- select DVB_M88RS2000 if !DVB_FE_CUSTOMISE
help
Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 .
@@ -412,13 +403,3 @@ config DVB_USB_MXL111SF
select VIDEO_TVEEPROM
help
Say Y here to support the MxL111SF USB2.0 DTV receiver.
-
-config DVB_USB_RTL28XXU
- tristate "Realtek RTL28xxU DVB USB support"
- depends on DVB_USB && EXPERIMENTAL
- select DVB_RTL2830
- select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
- select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
- select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
- help
- Say Y here to support the Realtek RTL28xxU DVB USB receiver.
diff --git a/trunk/drivers/media/dvb/dvb-usb/Makefile b/trunk/drivers/media/dvb/dvb-usb/Makefile
index b76acb5387e6..26c8b9e57050 100644
--- a/trunk/drivers/media/dvb/dvb-usb/Makefile
+++ b/trunk/drivers/media/dvb/dvb-usb/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o
dvb-usb-opera-objs = opera1.o
obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o
+
dvb-usb-af9005-objs = af9005.o af9005-fe.o
obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o
@@ -87,9 +88,6 @@ obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o
dvb-usb-ec168-objs = ec168.o
obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o
-dvb-usb-az6007-objs = az6007.o
-obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o
-
dvb-usb-az6027-objs = az6027.o
obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o
@@ -107,12 +105,8 @@ obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o
obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o
obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
-dvb-usb-rtl28xxu-objs = rtl28xxu.o
-obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o
-
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
# due to tuner-xc3028
-ccflags-y += -I$(srctree)/drivers/media/common/tuners
-ccflags-y += -I$(srctree)/drivers/media/dvb/ttpci
+ccflags-y += -Idrivers/media/common/tuners
+EXTRA_CFLAGS += -Idrivers/media/dvb/ttpci
diff --git a/trunk/drivers/media/dvb/dvb-usb/af9015.c b/trunk/drivers/media/dvb/dvb-usb/af9015.c
index 7e70ea50ef26..282a43d648df 100644
--- a/trunk/drivers/media/dvb/dvb-usb/af9015.c
+++ b/trunk/drivers/media/dvb/dvb-usb/af9015.c
@@ -1164,41 +1164,6 @@ static int af9015_af9013_sleep(struct dvb_frontend *fe)
return ret;
}
-/* override tuner callbacks for resource locking */
-static int af9015_tuner_init(struct dvb_frontend *fe)
-{
- int ret;
- struct dvb_usb_adapter *adap = fe->dvb->priv;
- struct af9015_state *priv = adap->dev->priv;
-
- if (mutex_lock_interruptible(&adap->dev->usb_mutex))
- return -EAGAIN;
-
- ret = priv->tuner_init[adap->id](fe);
-
- mutex_unlock(&adap->dev->usb_mutex);
-
- return ret;
-}
-
-/* override tuner callbacks for resource locking */
-static int af9015_tuner_sleep(struct dvb_frontend *fe)
-{
- int ret;
- struct dvb_usb_adapter *adap = fe->dvb->priv;
- struct af9015_state *priv = adap->dev->priv;
-
- if (mutex_lock_interruptible(&adap->dev->usb_mutex))
- return -EAGAIN;
-
- ret = priv->tuner_sleep[adap->id](fe);
-
- mutex_unlock(&adap->dev->usb_mutex);
-
- return ret;
-}
-
-
static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
{
int ret;
@@ -1318,7 +1283,6 @@ static struct mxl5007t_config af9015_mxl5007t_config = {
static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
{
int ret;
- struct af9015_state *state = adap->dev->priv;
deb_info("%s:\n", __func__);
switch (af9015_af9013_config[adap->id].tuner) {
@@ -1376,19 +1340,6 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
err("Unknown tuner id:%d",
af9015_af9013_config[adap->id].tuner);
}
-
- if (adap->fe_adap[0].fe->ops.tuner_ops.init) {
- state->tuner_init[adap->id] =
- adap->fe_adap[0].fe->ops.tuner_ops.init;
- adap->fe_adap[0].fe->ops.tuner_ops.init = af9015_tuner_init;
- }
-
- if (adap->fe_adap[0].fe->ops.tuner_ops.sleep) {
- state->tuner_sleep[adap->id] =
- adap->fe_adap[0].fe->ops.tuner_ops.sleep;
- adap->fe_adap[0].fe->ops.tuner_ops.sleep = af9015_tuner_sleep;
- }
-
return ret;
}
diff --git a/trunk/drivers/media/dvb/dvb-usb/af9015.h b/trunk/drivers/media/dvb/dvb-usb/af9015.h
index 2f68419e899b..f619063fa72f 100644
--- a/trunk/drivers/media/dvb/dvb-usb/af9015.h
+++ b/trunk/drivers/media/dvb/dvb-usb/af9015.h
@@ -108,8 +108,6 @@ struct af9015_state {
int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status);
int (*init[2]) (struct dvb_frontend *fe);
int (*sleep[2]) (struct dvb_frontend *fe);
- int (*tuner_init[2]) (struct dvb_frontend *fe);
- int (*tuner_sleep[2]) (struct dvb_frontend *fe);
};
struct af9015_config {
diff --git a/trunk/drivers/media/dvb/dvb-usb/anysee.c b/trunk/drivers/media/dvb/dvb-usb/anysee.c
index 03c28655af1b..cf0c318d6989 100644
--- a/trunk/drivers/media/dvb/dvb-usb/anysee.c
+++ b/trunk/drivers/media/dvb/dvb-usb/anysee.c
@@ -58,7 +58,7 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
u8 *rbuf, u8 rlen)
{
struct anysee_state *state = d->priv;
- int act_len, ret, i;
+ int act_len, ret;
u8 buf[64];
memcpy(&buf[0], sbuf, slen);
@@ -73,52 +73,26 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
/* We need receive one message more after dvb_usb_generic_rw due
to weird transaction flow, which is 1 x send + 2 x receive. */
ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
- if (ret)
- goto error_unlock;
-
- /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32
- * (EPIPE, Broken pipe). Function supports currently msleep() as a
- * parameter but I would not like to use it, since according to
- * Documentation/timers/timers-howto.txt it should not be used such
- * short, under < 20ms, sleeps. Repeating failed message would be
- * better choice as not to add unwanted delays...
- * Fixing that correctly is one of those or both;
- * 1) use repeat if possible
- * 2) add suitable delay
- */
-
- /* get answer, retry few times if error returned */
- for (i = 0; i < 3; i++) {
+ if (!ret) {
/* receive 2nd answer */
ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf),
&act_len, 2000);
-
- if (ret) {
- deb_info("%s: recv bulk message failed: %d",
- __func__, ret);
- } else {
+ if (ret)
+ err("%s: recv bulk message failed: %d", __func__, ret);
+ else {
deb_xfer("<<< ");
debug_dump(buf, rlen, deb_xfer);
if (buf[63] != 0x4f)
deb_info("%s: cmd failed\n", __func__);
-
- break;
}
}
- if (ret) {
- /* all retries failed, it is fatal */
- err("%s: recv bulk message failed: %d", __func__, ret);
- goto error_unlock;
- }
-
/* read request, copy returned data to return buf */
- if (rbuf && rlen)
+ if (!ret && rbuf && rlen)
memcpy(rbuf, buf, rlen);
-error_unlock:
mutex_unlock(&anysee_usb_mutex);
return ret;
diff --git a/trunk/drivers/media/dvb/dvb-usb/az6007.c b/trunk/drivers/media/dvb/dvb-usb/az6007.c
deleted file mode 100644
index 4008b9c50fbd..000000000000
--- a/trunk/drivers/media/dvb/dvb-usb/az6007.c
+++ /dev/null
@@ -1,957 +0,0 @@
-/*
- * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones
- *
- * Copyright (c) Henry Wang
- *
- * This driver was made publicly available by Terratec, at:
- * http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
- * The original driver's license is GPL, as declared with MODULE_LICENSE()
- *
- * Copyright (c) 2010-2011 Mauro Carvalho Chehab
- * Driver modified by in order to work with upstream drxk driver, and
- * tons of bugs got fixed.
- *
- * 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 under 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 "drxk.h"
-#include "mt2063.h"
-#include "dvb_ca_en50221.h"
-
-#define DVB_USB_LOG_PREFIX "az6007"
-#include "dvb-usb.h"
-
-/* debug */
-int dvb_usb_az6007_debug;
-module_param_named(debug, dvb_usb_az6007_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))."
- DVB_USB_DEBUG_STATUS);
-
-#define deb_info(args...) dprintk(dvb_usb_az6007_debug, 0x01, args)
-#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug, 0x02, args)
-#define deb_rc(args...) dprintk(dvb_usb_az6007_debug, 0x04, args)
-#define deb_fe(args...) dprintk(dvb_usb_az6007_debug, 0x08, args)
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/* Known requests (Cypress FX2 firmware + az6007 "private" ones*/
-
-#define FX2_OED 0xb5
-#define AZ6007_READ_DATA 0xb7
-#define AZ6007_I2C_RD 0xb9
-#define AZ6007_POWER 0xbc
-#define AZ6007_I2C_WR 0xbd
-#define FX2_SCON1 0xc0
-#define AZ6007_TS_THROUGH 0xc7
-#define AZ6007_READ_IR 0xb4
-
-struct az6007_device_state {
- struct mutex mutex;
- struct mutex ca_mutex;
- struct dvb_ca_en50221 ca;
- unsigned warm:1;
- int (*gate_ctrl) (struct dvb_frontend *, int);
- unsigned char data[4096];
-};
-
-static struct drxk_config terratec_h7_drxk = {
- .adr = 0x29,
- .parallel_ts = true,
- .dynamic_clk = true,
- .single_master = true,
- .enable_merr_cfg = true,
- .no_i2c_bridge = false,
- .chunk_size = 64,
- .mpeg_out_clk_strength = 0x02,
- .microcode_name = "dvb-usb-terratec-h7-drxk.fw",
-};
-
-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
- struct dvb_usb_adapter *adap = fe->sec_priv;
- struct az6007_device_state *st;
- int status = 0;
-
- deb_info("%s: %s\n", __func__, enable ? "enable" : "disable");
-
- if (!adap)
- return -EINVAL;
-
- st = adap->dev->priv;
-
- if (!st)
- return -EINVAL;
-
- if (enable)
- status = st->gate_ctrl(fe, 1);
- else
- status = st->gate_ctrl(fe, 0);
-
- return status;
-}
-
-static struct mt2063_config az6007_mt2063_config = {
- .tuner_address = 0x60,
- .refclock = 36125000,
-};
-
-static int __az6007_read(struct usb_device *udev, u8 req, u16 value,
- u16 index, u8 *b, int blen)
-{
- int ret;
-
- ret = usb_control_msg(udev,
- usb_rcvctrlpipe(udev, 0),
- req,
- USB_TYPE_VENDOR | USB_DIR_IN,
- value, index, b, blen, 5000);
- if (ret < 0) {
- warn("usb read operation failed. (%d)", ret);
- return -EIO;
- }
-
- deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value,
- index);
- debug_dump(b, blen, deb_xfer);
-
- return ret;
-}
-
-static int az6007_read(struct dvb_usb_device *d, u8 req, u16 value,
- u16 index, u8 *b, int blen)
-{
- struct az6007_device_state *st = d->priv;
- int ret;
-
- if (mutex_lock_interruptible(&st->mutex) < 0)
- return -EAGAIN;
-
- ret = __az6007_read(d->udev, req, value, index, b, blen);
-
- mutex_unlock(&st->mutex);
-
- return ret;
-}
-
-static int __az6007_write(struct usb_device *udev, u8 req, u16 value,
- u16 index, u8 *b, int blen)
-{
- int ret;
-
- deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value,
- index);
- debug_dump(b, blen, deb_xfer);
-
- if (blen > 64) {
- err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n",
- blen);
- return -EOPNOTSUPP;
- }
-
- ret = usb_control_msg(udev,
- usb_sndctrlpipe(udev, 0),
- req,
- USB_TYPE_VENDOR | USB_DIR_OUT,
- value, index, b, blen, 5000);
- if (ret != blen) {
- err("usb write operation failed. (%d)", ret);
- return -EIO;
- }
-
- return 0;
-}
-
-static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value,
- u16 index, u8 *b, int blen)
-{
- struct az6007_device_state *st = d->priv;
- int ret;
-
- if (mutex_lock_interruptible(&st->mutex) < 0)
- return -EAGAIN;
-
- ret = __az6007_write(d->udev, req, value, index, b, blen);
-
- mutex_unlock(&st->mutex);
-
- return ret;
-}
-
-static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
- struct dvb_usb_device *d = adap->dev;
-
- deb_info("%s: %s", __func__, onoff ? "enable" : "disable");
-
- return az6007_write(d, 0xbc, onoff, 0, NULL, 0);
-}
-
-/* remote control stuff (does not work with my box) */
-static int az6007_rc_query(struct dvb_usb_device *d)
-{
- struct az6007_device_state *st = d->priv;
- unsigned code = 0;
-
- az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10);
-
- if (st->data[1] == 0x44)
- return 0;
-
- if ((st->data[1] ^ st->data[2]) == 0xff)
- code = st->data[1];
- else
- code = st->data[1] << 8 | st->data[2];
-
- if ((st->data[3] ^ st->data[4]) == 0xff)
- code = code << 8 | st->data[3];
- else
- code = code << 16 | st->data[3] << 8 | st->data[4];
-
- rc_keydown(d->rc_dev, code, st->data[5]);
-
- return 0;
-}
-
-static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
- int slot,
- int address)
-{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
- int ret;
- u8 req;
- u16 value;
- u16 index;
- int blen;
- u8 *b;
-
- if (slot != 0)
- return -EINVAL;
-
- b = kmalloc(12, GFP_KERNEL);
- if (!b)
- return -ENOMEM;
-
- mutex_lock(&state->ca_mutex);
-
- req = 0xC1;
- value = address;
- index = 0;
- blen = 1;
-
- ret = az6007_read(d, req, value, index, b, blen);
- if (ret < 0) {
- warn("usb in operation failed. (%d)", ret);
- ret = -EINVAL;
- } else {
- ret = b[0];
- }
-
- mutex_unlock(&state->ca_mutex);
- kfree(b);
- return ret;
-}
-
-static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
- int slot,
- int address,
- u8 value)
-{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
- int ret;
- u8 req;
- u16 value1;
- u16 index;
- int blen;
-
- deb_info("%s %d", __func__, slot);
- if (slot != 0)
- return -EINVAL;
-
- mutex_lock(&state->ca_mutex);
- req = 0xC2;
- value1 = address;
- index = value;
- blen = 0;
-
- ret = az6007_write(d, req, value1, index, NULL, blen);
- if (ret != 0)
- warn("usb out operation failed. (%d)", ret);
-
- mutex_unlock(&state->ca_mutex);
- return ret;
-}
-
-static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca,
- int slot,
- u8 address)
-{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
- int ret;
- u8 req;
- u16 value;
- u16 index;
- int blen;
- u8 *b;
-
- if (slot != 0)
- return -EINVAL;
-
- b = kmalloc(12, GFP_KERNEL);
- if (!b)
- return -ENOMEM;
-
- mutex_lock(&state->ca_mutex);
-
- req = 0xC3;
- value = address;
- index = 0;
- blen = 2;
-
- ret = az6007_read(d, req, value, index, b, blen);
- if (ret < 0) {
- warn("usb in operation failed. (%d)", ret);
- ret = -EINVAL;
- } else {
- if (b[0] == 0)
- warn("Read CI IO error");
-
- ret = b[1];
- deb_info("read cam data = %x from 0x%x", b[1], value);
- }
-
- mutex_unlock(&state->ca_mutex);
- kfree(b);
- return ret;
-}
-
-static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca,
- int slot,
- u8 address,
- u8 value)
-{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
- int ret;
- u8 req;
- u16 value1;
- u16 index;
- int blen;
-
- if (slot != 0)
- return -EINVAL;
-
- mutex_lock(&state->ca_mutex);
- req = 0xC4;
- value1 = address;
- index = value;
- blen = 0;
-
- ret = az6007_write(d, req, value1, index, NULL, blen);
- if (ret != 0) {
- warn("usb out operation failed. (%d)", ret);
- goto failed;
- }
-
-failed:
- mutex_unlock(&state->ca_mutex);
- return ret;
-}
-
-static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
-{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-
- int ret;
- u8 req;
- u16 value;
- u16 index;
- int blen;
- u8 *b;
-
- b = kmalloc(12, GFP_KERNEL);
- if (!b)
- return -ENOMEM;
-
- req = 0xC8;
- value = 0;
- index = 0;
- blen = 1;
-
- ret = az6007_read(d, req, value, index, b, blen);
- if (ret < 0) {
- warn("usb in operation failed. (%d)", ret);
- ret = -EIO;
- } else{
- ret = b[0];
- }
- kfree(b);
- return ret;
-}
-
-static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
-{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
- int ret, i;
- u8 req;
- u16 value;
- u16 index;
- int blen;
-
- mutex_lock(&state->ca_mutex);
-
- req = 0xC6;
- value = 1;
- index = 0;
- blen = 0;
-
- ret = az6007_write(d, req, value, index, NULL, blen);
- if (ret != 0) {
- warn("usb out operation failed. (%d)", ret);
- goto failed;
- }
-
- msleep(500);
- req = 0xC6;
- value = 0;
- index = 0;
- blen = 0;
-
- ret = az6007_write(d, req, value, index, NULL, blen);
- if (ret != 0) {
- warn("usb out operation failed. (%d)", ret);
- goto failed;
- }
-
- for (i = 0; i < 15; i++) {
- msleep(100);
-
- if (CI_CamReady(ca, slot)) {
- deb_info("CAM Ready");
- break;
- }
- }
- msleep(5000);
-
-failed:
- mutex_unlock(&state->ca_mutex);
- return ret;
-}
-
-static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
-{
- return 0;
-}
-
-static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
-{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
- int ret;
- u8 req;
- u16 value;
- u16 index;
- int blen;
-
- deb_info("%s", __func__);
- mutex_lock(&state->ca_mutex);
- req = 0xC7;
- value = 1;
- index = 0;
- blen = 0;
-
- ret = az6007_write(d, req, value, index, NULL, blen);
- if (ret != 0) {
- warn("usb out operation failed. (%d)", ret);
- goto failed;
- }
-
-failed:
- mutex_unlock(&state->ca_mutex);
- return ret;
-}
-
-static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
-{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
- int ret;
- u8 req;
- u16 value;
- u16 index;
- int blen;
- u8 *b;
-
- b = kmalloc(12, GFP_KERNEL);
- if (!b)
- return -ENOMEM;
- mutex_lock(&state->ca_mutex);
-
- req = 0xC5;
- value = 0;
- index = 0;
- blen = 1;
-
- ret = az6007_read(d, req, value, index, b, blen);
- if (ret < 0) {
- warn("usb in operation failed. (%d)", ret);
- ret = -EIO;
- } else
- ret = 0;
-
- if (!ret && b[0] == 1) {
- ret = DVB_CA_EN50221_POLL_CAM_PRESENT |
- DVB_CA_EN50221_POLL_CAM_READY;
- }
-
- mutex_unlock(&state->ca_mutex);
- kfree(b);
- return ret;
-}
-
-
-static void az6007_ci_uninit(struct dvb_usb_device *d)
-{
- struct az6007_device_state *state;
-
- deb_info("%s", __func__);
-
- if (NULL == d)
- return;
-
- state = (struct az6007_device_state *)d->priv;
- if (NULL == state)
- return;
-
- if (NULL == state->ca.data)
- return;
-
- dvb_ca_en50221_release(&state->ca);
-
- memset(&state->ca, 0, sizeof(state->ca));
-}
-
-
-static int az6007_ci_init(struct dvb_usb_adapter *a)
-{
- struct dvb_usb_device *d = a->dev;
- struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
- int ret;
-
- deb_info("%s", __func__);
-
- mutex_init(&state->ca_mutex);
-
- state->ca.owner = THIS_MODULE;
- state->ca.read_attribute_mem = az6007_ci_read_attribute_mem;
- state->ca.write_attribute_mem = az6007_ci_write_attribute_mem;
- state->ca.read_cam_control = az6007_ci_read_cam_control;
- state->ca.write_cam_control = az6007_ci_write_cam_control;
- state->ca.slot_reset = az6007_ci_slot_reset;
- state->ca.slot_shutdown = az6007_ci_slot_shutdown;
- state->ca.slot_ts_enable = az6007_ci_slot_ts_enable;
- state->ca.poll_slot_status = az6007_ci_poll_slot_status;
- state->ca.data = d;
-
- ret = dvb_ca_en50221_init(&a->dvb_adap,
- &state->ca,
- 0, /* flags */
- 1);/* n_slots */
- if (ret != 0) {
- err("Cannot initialize CI: Error %d.", ret);
- memset(&state->ca, 0, sizeof(state->ca));
- return ret;
- }
-
- deb_info("CI initialized.");
-
- return 0;
-}
-
-static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
-{
- struct az6007_device_state *st = d->priv;
- int ret;
-
- ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6);
- memcpy(mac, st->data, sizeof(mac));
-
- if (ret > 0)
- deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n",
- __func__, mac[0], mac[1], mac[2],
- mac[3], mac[4], mac[5]);
-
- return ret;
-}
-
-static int az6007_frontend_attach(struct dvb_usb_adapter *adap)
-{
- struct az6007_device_state *st = adap->dev->priv;
-
- deb_info("attaching demod drxk");
-
- adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk,
- &adap->dev->i2c_adap);
- if (!adap->fe_adap[0].fe)
- return -EINVAL;
-
- adap->fe_adap[0].fe->sec_priv = adap;
- st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl;
- adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
-
- az6007_ci_init(adap);
-
- return 0;
-}
-
-static int az6007_tuner_attach(struct dvb_usb_adapter *adap)
-{
- deb_info("attaching tuner mt2063");
-
- /* Attach mt2063 to DVB-C frontend */
- if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
- adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1);
- if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe,
- &az6007_mt2063_config,
- &adap->dev->i2c_adap))
- return -EINVAL;
-
- if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
- adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0);
-
- return 0;
-}
-
-int az6007_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
- struct az6007_device_state *st = d->priv;
- int ret;
-
- deb_info("%s()\n", __func__);
-
- if (!st->warm) {
- mutex_init(&st->mutex);
-
- ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0);
- if (ret < 0)
- return ret;
- msleep(60);
- ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0);
- if (ret < 0)
- return ret;
- msleep(100);
- ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0);
- if (ret < 0)
- return ret;
- msleep(20);
- ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0);
- if (ret < 0)
- return ret;
-
- msleep(400);
- ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0);
- if (ret < 0)
- return ret;
- msleep(150);
- ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0);
- if (ret < 0)
- return ret;
- msleep(430);
- ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0);
- if (ret < 0)
- return ret;
-
- st->warm = true;
-
- return 0;
- }
-
- if (!onoff)
- return 0;
-
- az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0);
- az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0);
-
- return 0;
-}
-
-/* I2C */
-static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
- int num)
-{
- struct dvb_usb_device *d = i2c_get_adapdata(adap);
- struct az6007_device_state *st = d->priv;
- int i, j, len;
- int ret = 0;
- u16 index;
- u16 value;
- int length;
- u8 req, addr;
-
- if (mutex_lock_interruptible(&st->mutex) < 0)
- return -EAGAIN;
-
- for (i = 0; i < num; i++) {
- addr = msgs[i].addr << 1;
- if (((i + 1) < num)
- && (msgs[i].len == 1)
- && (!msgs[i].flags & I2C_M_RD)
- && (msgs[i + 1].flags & I2C_M_RD)
- && (msgs[i].addr == msgs[i + 1].addr)) {
- /*
- * A write + read xfer for the same address, where
- * the first xfer has just 1 byte length.
- * Need to join both into one operation
- */
- if (dvb_usb_az6007_debug & 2)
- printk(KERN_DEBUG
- "az6007 I2C xfer write+read addr=0x%x len=%d/%d: ",
- addr, msgs[i].len, msgs[i + 1].len);
- req = AZ6007_I2C_RD;
- index = msgs[i].buf[0];
- value = addr | (1 << 8);
- length = 6 + msgs[i + 1].len;
- len = msgs[i + 1].len;
- ret = __az6007_read(d->udev, req, value, index,
- st->data, length);
- if (ret >= len) {
- for (j = 0; j < len; j++) {
- msgs[i + 1].buf[j] = st->data[j + 5];
- if (dvb_usb_az6007_debug & 2)
- printk(KERN_CONT
- "0x%02x ",
- msgs[i + 1].buf[j]);
- }
- } else
- ret = -EIO;
- i++;
- } else if (!(msgs[i].flags & I2C_M_RD)) {
- /* write bytes */
- if (dvb_usb_az6007_debug & 2)
- printk(KERN_DEBUG
- "az6007 I2C xfer write addr=0x%x len=%d: ",
- addr, msgs[i].len);
- req = AZ6007_I2C_WR;
- index = msgs[i].buf[0];
- value = addr | (1 << 8);
- length = msgs[i].len - 1;
- len = msgs[i].len - 1;
- if (dvb_usb_az6007_debug & 2)
- printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]);
- for (j = 0; j < len; j++) {
- st->data[j] = msgs[i].buf[j + 1];
- if (dvb_usb_az6007_debug & 2)
- printk(KERN_CONT "0x%02x ",
- st->data[j]);
- }
- ret = __az6007_write(d->udev, req, value, index,
- st->data, length);
- } else {
- /* read bytes */
- if (dvb_usb_az6007_debug & 2)
- printk(KERN_DEBUG
- "az6007 I2C xfer read addr=0x%x len=%d: ",
- addr, msgs[i].len);
- req = AZ6007_I2C_RD;
- index = msgs[i].buf[0];
- value = addr;
- length = msgs[i].len + 6;
- len = msgs[i].len;
- ret = __az6007_read(d->udev, req, value, index,
- st->data, length);
- for (j = 0; j < len; j++) {
- msgs[i].buf[j] = st->data[j + 5];
- if (dvb_usb_az6007_debug & 2)
- printk(KERN_CONT
- "0x%02x ", st->data[j + 5]);
- }
- }
- if (dvb_usb_az6007_debug & 2)
- printk(KERN_CONT "\n");
- if (ret < 0)
- goto err;
- }
-err:
- mutex_unlock(&st->mutex);
-
- if (ret < 0) {
- info("%s ERROR: %i", __func__, ret);
- return ret;
- }
- return num;
-}
-
-static u32 az6007_i2c_func(struct i2c_adapter *adapter)
-{
- return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm az6007_i2c_algo = {
- .master_xfer = az6007_i2c_xfer,
- .functionality = az6007_i2c_func,
-};
-
-int az6007_identify_state(struct usb_device *udev,
- struct dvb_usb_device_properties *props,
- struct dvb_usb_device_description **desc, int *cold)
-{
- int ret;
- u8 *mac;
-
- mac = kmalloc(6, GFP_ATOMIC);
- if (!mac)
- return -ENOMEM;
-
- /* Try to read the mac address */
- ret = __az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6);
- if (ret == 6)
- *cold = 0;
- else
- *cold = 1;
-
- kfree(mac);
-
- if (*cold) {
- __az6007_write(udev, 0x09, 1, 0, NULL, 0);
- __az6007_write(udev, 0x00, 0, 0, NULL, 0);
- __az6007_write(udev, 0x00, 0, 0, NULL, 0);
- }
-
- deb_info("Device is on %s state\n", *cold ? "warm" : "cold");
- return 0;
-}
-
-static struct dvb_usb_device_properties az6007_properties;
-
-static void az6007_usb_disconnect(struct usb_interface *intf)
-{
- struct dvb_usb_device *d = usb_get_intfdata(intf);
- az6007_ci_uninit(d);
- dvb_usb_device_exit(intf);
-}
-
-static int az6007_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- return dvb_usb_device_init(intf, &az6007_properties,
- THIS_MODULE, NULL, adapter_nr);
-}
-
-static struct usb_device_id az6007_usb_table[] = {
- {USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007)},
- {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7)},
- {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2)},
- {0},
-};
-
-MODULE_DEVICE_TABLE(usb, az6007_usb_table);
-
-static struct dvb_usb_device_properties az6007_properties = {
- .caps = DVB_USB_IS_AN_I2C_ADAPTER,
- .usb_ctrl = CYPRESS_FX2,
- .firmware = "dvb-usb-terratec-h7-az6007.fw",
- .no_reconnect = 1,
- .size_of_priv = sizeof(struct az6007_device_state),
- .identify_state = az6007_identify_state,
- .num_adapters = 1,
- .adapter = {
- {
- .num_frontends = 1,
- .fe = {{
- .streaming_ctrl = az6007_streaming_ctrl,
- .tuner_attach = az6007_tuner_attach,
- .frontend_attach = az6007_frontend_attach,
-
- /* parameter for the MPEG2-data transfer */
- .stream = {
- .type = USB_BULK,
- .count = 10,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
- } }
- } },
- .power_ctrl = az6007_power_ctrl,
- .read_mac_address = az6007_read_mac_addr,
-
- .rc.core = {
- .rc_interval = 400,
- .rc_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
- .module_name = "az6007",
- .rc_query = az6007_rc_query,
- .allowed_protos = RC_TYPE_NEC,
- },
- .i2c_algo = &az6007_i2c_algo,
-
- .num_device_descs = 2,
- .devices = {
- { .name = "AzureWave DTV StarBox DVB-T/C USB2.0 (az6007)",
- .cold_ids = { &az6007_usb_table[0], NULL },
- .warm_ids = { NULL },
- },
- { .name = "TerraTec DTV StarBox DVB-T/C USB2.0 (az6007)",
- .cold_ids = { &az6007_usb_table[1], &az6007_usb_table[2], NULL },
- .warm_ids = { NULL },
- },
- { NULL },
- }
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver az6007_usb_driver = {
- .name = "dvb_usb_az6007",
- .probe = az6007_usb_probe,
- .disconnect = az6007_usb_disconnect,
- .id_table = az6007_usb_table,
-};
-
-/* module stuff */
-static int __init az6007_usb_module_init(void)
-{
- int result;
- deb_info("az6007 usb module init\n");
-
- result = usb_register(&az6007_usb_driver);
- if (result) {
- err("usb_register failed. (%d)", result);
- return result;
- }
-
- return 0;
-}
-
-static void __exit az6007_usb_module_exit(void)
-{
- /* deregister this driver from the USB subsystem */
- deb_info("az6007 usb module exit\n");
- usb_deregister(&az6007_usb_driver);
-}
-
-module_init(az6007_usb_module_init);
-module_exit(az6007_usb_module_exit);
-
-MODULE_AUTHOR("Henry Wang ");
-MODULE_AUTHOR("Mauro Carvalho Chehab ");
-MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones");
-MODULE_VERSION("1.1");
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c b/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c
index 02290c60f72f..070e82aa53f5 100644
--- a/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -677,9 +677,11 @@ static void dib0700_rc_urb_completion(struct urb *purb)
u8 toggle;
deb_info("%s()\n", __func__);
+ if (d == NULL)
+ return;
+
if (d->rc_dev == NULL) {
/* This will occur if disable_rc_polling=1 */
- kfree(purb->transfer_buffer);
usb_free_urb(purb);
return;
}
@@ -688,7 +690,6 @@ static void dib0700_rc_urb_completion(struct urb *purb)
if (purb->status < 0) {
deb_info("discontinuing polling\n");
- kfree(purb->transfer_buffer);
usb_free_urb(purb);
return;
}
@@ -783,11 +784,8 @@ int dib0700_rc_setup(struct dvb_usb_device *d)
dib0700_rc_urb_completion, d);
ret = usb_submit_urb(purb, GFP_ATOMIC);
- if (ret) {
+ if (ret)
err("rc submit urb failed\n");
- kfree(purb->transfer_buffer);
- usb_free_urb(purb);
- }
return ret;
}
diff --git a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 397d8f232731..d390ddaa5a53 100644
--- a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -51,7 +51,6 @@
#define USB_VID_PINNACLE 0x2304
#define USB_VID_PCTV 0x2013
#define USB_VID_PIXELVIEW 0x1554
-#define USB_VID_REALTEK 0x0bda
#define USB_VID_TECHNOTREND 0x0b48
#define USB_VID_TERRATEC 0x0ccd
#define USB_VID_TELESTAR 0x10b9
@@ -81,7 +80,6 @@
#define USB_PID_ANSONIC_DVBT_USB 0x6000
#define USB_PID_ANYSEE 0x861f
#define USB_PID_AZUREWAVE_AD_TU700 0x3237
-#define USB_PID_AZUREWAVE_6007 0x0ccd
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
@@ -127,8 +125,6 @@
#define USB_PID_E3C_EC168_3 0xfffb
#define USB_PID_E3C_EC168_4 0x1001
#define USB_PID_E3C_EC168_5 0x1002
-#define USB_PID_FREECOM_DVBT 0x0160
-#define USB_PID_FREECOM_DVBT_2 0x0161
#define USB_PID_UNIWILL_STK7700P 0x6003
#define USB_PID_GENIUS_TVGO_DVB_T03 0x4012
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
@@ -230,8 +226,6 @@
#define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062
#define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078
#define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab
-#define USB_PID_TERRATEC_H7 0x10b4
-#define USB_PID_TERRATEC_H7_2 0x10a3
#define USB_PID_TERRATEC_T3 0x10a0
#define USB_PID_TERRATEC_T5 0x10a1
#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
@@ -255,8 +249,6 @@
#define USB_PID_PCTV_400E 0x020f
#define USB_PID_PCTV_450E 0x0222
#define USB_PID_PCTV_452E 0x021f
-#define USB_PID_REALTEK_RTL2831U 0x2831
-#define USB_PID_REALTEK_RTL2832U 0x2832
#define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007
#define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a
#define USB_PID_NEBULA_DIGITV 0x0201
diff --git a/trunk/drivers/media/dvb/dvb-usb/it913x.c b/trunk/drivers/media/dvb/dvb-usb/it913x.c
index 3b7b102f20ae..9f01cd7a6e3f 100644
--- a/trunk/drivers/media/dvb/dvb-usb/it913x.c
+++ b/trunk/drivers/media/dvb/dvb-usb/it913x.c
@@ -64,7 +64,6 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
struct it913x_state {
u8 id;
struct ite_config it913x_config;
- u8 pid_filter_onoff;
};
struct ite_config it913x_config;
@@ -260,16 +259,15 @@ static u32 it913x_query(struct usb_device *udev, u8 pro)
static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
- struct it913x_state *st = adap->dev->priv;
struct usb_device *udev = adap->dev->udev;
int ret;
u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
- mutex_lock(&adap->dev->i2c_mutex);
-
+ if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+ return -EAGAIN;
deb_info(1, "PID_C (%02x)", onoff);
- ret = it913x_wr_reg(udev, pro, PID_EN, st->pid_filter_onoff);
+ ret = it913x_wr_reg(udev, pro, PID_EN, onoff);
mutex_unlock(&adap->dev->i2c_mutex);
return ret;
@@ -278,13 +276,12 @@ static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
static int it913x_pid_filter(struct dvb_usb_adapter *adap,
int index, u16 pid, int onoff)
{
- struct it913x_state *st = adap->dev->priv;
struct usb_device *udev = adap->dev->udev;
int ret;
u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
- mutex_lock(&adap->dev->i2c_mutex);
-
+ if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+ return -EAGAIN;
deb_info(1, "PID_F (%02x)", onoff);
ret = it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff));
@@ -295,13 +292,6 @@ static int it913x_pid_filter(struct dvb_usb_adapter *adap,
ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
- if (udev->speed == USB_SPEED_HIGH && pid == 0x2000) {
- ret |= it913x_wr_reg(udev, pro, PID_EN, !onoff);
- st->pid_filter_onoff = !onoff;
- } else
- st->pid_filter_onoff =
- adap->fe_adap[adap->active_fe].pid_filtering;
-
mutex_unlock(&adap->dev->i2c_mutex);
return 0;
}
@@ -326,8 +316,8 @@ static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int ret;
u32 reg;
u8 pro;
-
- mutex_lock(&d->i2c_mutex);
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
debug_data_snipet(1, "Message out", msg[0].buf);
deb_info(2, "num of messages %d address %02x", num, msg[0].addr);
@@ -368,7 +358,8 @@ static int it913x_rc_query(struct dvb_usb_device *d)
int ret;
u32 key;
/* Avoid conflict with frontends*/
- mutex_lock(&d->i2c_mutex);
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET,
0, 0, &ibuf[0], sizeof(ibuf));
@@ -397,12 +388,19 @@ static int ite_firmware_select(struct usb_device *udev,
{
int sw;
/* auto switch */
- if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_KWORLD_2)
- sw = IT9137_FW;
- else if (it913x_config.chip_ver == 1)
+ if (le16_to_cpu(udev->descriptor.idProduct) ==
+ USB_PID_ITETECH_IT9135)
sw = IT9135_V1_FW;
- else
+ else if (le16_to_cpu(udev->descriptor.idProduct) ==
+ USB_PID_ITETECH_IT9135_9005)
+ sw = IT9135_V1_FW;
+ else if (le16_to_cpu(udev->descriptor.idProduct) ==
+ USB_PID_ITETECH_IT9135_9006) {
sw = IT9135_V2_FW;
+ if (it913x_config.tuner_id_0 == 0)
+ it913x_config.tuner_id_0 = IT9135_60;
+ } else
+ sw = IT9137_FW;
/* force switch */
if (dvb_usb_it913x_firmware != IT9135_AUTO)
@@ -412,103 +410,41 @@ static int ite_firmware_select(struct usb_device *udev,
case IT9135_V1_FW:
it913x_config.firmware_ver = 1;
it913x_config.adc_x2 = 1;
- it913x_config.read_slevel = false;
props->firmware = fw_it9135_v1;
break;
case IT9135_V2_FW:
it913x_config.firmware_ver = 1;
it913x_config.adc_x2 = 1;
- it913x_config.read_slevel = false;
props->firmware = fw_it9135_v2;
- switch (it913x_config.tuner_id_0) {
- case IT9135_61:
- case IT9135_62:
- break;
- default:
- info("Unknown tuner ID applying default 0x60");
- case IT9135_60:
- it913x_config.tuner_id_0 = IT9135_60;
- }
break;
case IT9137_FW:
default:
it913x_config.firmware_ver = 0;
it913x_config.adc_x2 = 0;
- it913x_config.read_slevel = true;
props->firmware = fw_it9137;
}
return 0;
}
-static void it913x_select_remote(struct usb_device *udev,
- struct dvb_usb_device_properties *props)
-{
- switch (le16_to_cpu(udev->descriptor.idProduct)) {
- case USB_PID_ITETECH_IT9135_9005:
- props->rc.core.rc_codes = RC_MAP_IT913X_V2;
- return;
- default:
- props->rc.core.rc_codes = RC_MAP_IT913X_V1;
- }
- return;
-}
-
#define TS_MPEG_PKT_SIZE 188
#define EP_LOW 21
#define TS_BUFFER_SIZE_PID (EP_LOW*TS_MPEG_PKT_SIZE)
#define EP_HIGH 348
#define TS_BUFFER_SIZE_MAX (EP_HIGH*TS_MPEG_PKT_SIZE)
-static int it913x_select_config(struct usb_device *udev,
- struct dvb_usb_device_properties *props)
+static int it913x_identify_state(struct usb_device *udev,
+ struct dvb_usb_device_properties *props,
+ struct dvb_usb_device_description **desc,
+ int *cold)
{
- int ret = 0, reg;
- bool proprietary_ir = false;
-
- if (it913x_config.chip_ver == 0x02
- && it913x_config.chip_type == 0x9135)
- reg = it913x_read_reg(udev, 0x461d);
- else
- reg = it913x_read_reg(udev, 0x461b);
-
- if (reg < 0)
- return reg;
+ int ret = 0, firm_no;
+ u8 reg, remote;
- if (reg == 0) {
- it913x_config.dual_mode = 0;
- it913x_config.tuner_id_0 = IT9135_38;
- proprietary_ir = true;
- } else {
- /* TS mode */
- reg = it913x_read_reg(udev, 0x49c5);
- if (reg < 0)
- return reg;
- it913x_config.dual_mode = reg;
-
- /* IR mode type */
- reg = it913x_read_reg(udev, 0x49ac);
- if (reg < 0)
- return reg;
- if (reg == 5) {
- info("Remote propriety (raw) mode");
- proprietary_ir = true;
- } else if (reg == 1) {
- info("Remote HID mode NOT SUPPORTED");
- proprietary_ir = false;
- props->rc.core.rc_codes = NULL;
- } else
- props->rc.core.rc_codes = NULL;
-
- /* Tuner_id */
- reg = it913x_read_reg(udev, 0x49d0);
- if (reg < 0)
- return reg;
- it913x_config.tuner_id_0 = reg;
- }
+ firm_no = it913x_return_status(udev);
- if (proprietary_ir)
- it913x_select_remote(udev, props);
+ /* checnk for dual mode */
+ it913x_config.dual_mode = it913x_read_reg(udev, 0x49c5);
if (udev->speed != USB_SPEED_HIGH) {
props->adapter[0].fe[0].pid_filter_count = 5;
@@ -523,6 +459,17 @@ static int it913x_select_config(struct usb_device *udev,
if(props->adapter[0].fe[0].pid_filter_count == 5)
props->adapter[0].fe[0].pid_filter_count = 31;
+ /* TODO different remotes */
+ remote = it913x_read_reg(udev, 0x49ac); /* Remote */
+ if (remote == 0)
+ props->rc.core.rc_codes = NULL;
+
+ /* TODO at the moment tuner_id is always assigned to 0x38 */
+ it913x_config.tuner_id_0 = it913x_read_reg(udev, 0x49d0);
+
+ info("Dual mode=%x Remote=%x Tuner Type=%x", it913x_config.dual_mode
+ , remote, it913x_config.tuner_id_0);
+
/* Select Stream Buffer Size and pid filter option*/
if (pid_filter) {
props->adapter[0].fe[0].stream.u.bulk.buffersize =
@@ -543,29 +490,8 @@ static int it913x_select_config(struct usb_device *udev,
} else
props->num_adapters = 1;
- info("Dual mode=%x Tuner Type=%x", it913x_config.dual_mode,
- it913x_config.tuner_id_0);
-
ret = ite_firmware_select(udev, props);
- return ret;
-}
-
-static int it913x_identify_state(struct usb_device *udev,
- struct dvb_usb_device_properties *props,
- struct dvb_usb_device_description **desc,
- int *cold)
-{
- int ret = 0, firm_no;
- u8 reg;
-
- firm_no = it913x_return_status(udev);
-
- /* Read and select config */
- ret = it913x_select_config(udev, props);
- if (ret < 0)
- return ret;
-
if (firm_no > 0) {
*cold = 0;
return 0;
@@ -612,22 +538,18 @@ static int it913x_identify_state(struct usb_device *udev,
static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
- struct it913x_state *st = adap->dev->priv;
int ret = 0;
u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+ if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+ return -EAGAIN;
deb_info(1, "STM (%02x)", onoff);
- if (!onoff) {
- mutex_lock(&adap->dev->i2c_mutex);
-
+ if (!onoff)
ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
- mutex_unlock(&adap->dev->i2c_mutex);
- st->pid_filter_onoff =
- adap->fe_adap[adap->active_fe].pid_filtering;
- }
+ mutex_unlock(&adap->dev->i2c_mutex);
return ret;
}
@@ -867,7 +789,7 @@ static struct dvb_usb_device_properties it913x_properties = {
.rc_query = it913x_rc_query,
.rc_interval = IT913X_POLL,
.allowed_protos = RC_TYPE_NEC,
- .rc_codes = RC_MAP_IT913X_V1,
+ .rc_codes = RC_MAP_MSI_DIGIVOX_III,
},
.i2c_algo = &it913x_i2c_algo,
.num_device_descs = 5,
@@ -901,5 +823,5 @@ module_usb_driver(it913x_driver);
MODULE_AUTHOR("Malcolm Priestley ");
MODULE_DESCRIPTION("it913x USB 2 Driver");
-MODULE_VERSION("1.27");
+MODULE_VERSION("1.22");
MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/media/dvb/dvb-usb/lmedm04.c b/trunk/drivers/media/dvb/dvb-usb/lmedm04.c
index 5dde06d066ff..291f6b110399 100644
--- a/trunk/drivers/media/dvb/dvb-usb/lmedm04.c
+++ b/trunk/drivers/media/dvb/dvb-usb/lmedm04.c
@@ -77,7 +77,6 @@
#include "stv0299.h"
#include "dvb-pll.h"
#include "z0194a.h"
-#include "m88rs2000.h"
@@ -105,7 +104,7 @@ MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG");
static int pid_filter;
module_param_named(pid, pid_filter, int, 0644);
-MODULE_PARM_DESC(pid, "set default 0=default 1=off 2=on");
+MODULE_PARM_DESC(pid, "set default 0=on 1=off");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
@@ -114,7 +113,6 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#define TUNER_LG 0x1
#define TUNER_S7395 0x2
#define TUNER_S0194 0x3
-#define TUNER_RS2000 0x4
struct lme2510_state {
u8 id;
@@ -123,8 +121,6 @@ struct lme2510_state {
u8 signal_level;
u8 signal_sn;
u8 time_key;
- u8 last_key;
- u8 key_timeout;
u8 i2c_talk_onoff;
u8 i2c_gate;
u8 i2c_tuner_gate_w;
@@ -132,7 +128,6 @@ struct lme2510_state {
u8 i2c_tuner_addr;
u8 stream_on;
u8 pid_size;
- u8 pid_off;
void *buffer;
struct urb *lme_urb;
void *usb_buffer;
@@ -183,8 +178,14 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
/* the read/write capped at 64 */
memcpy(buff, wbuf, (wlen < 64) ? wlen : 64);
+ ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01));
+
ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01);
+ msleep(10);
+
+ ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01));
+
ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ?
rlen : 64 , 0x01);
@@ -198,14 +199,9 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
static int lme2510_stream_restart(struct dvb_usb_device *d)
{
- struct lme2510_state *st = d->priv;
- u8 all_pids[] = LME_ALL_PIDS;
- u8 stream_on[] = LME_ST_ON_W;
+ static u8 stream_on[] = LME_ST_ON_W;
int ret;
- u8 rbuff[1];
- if (st->pid_off)
- ret = lme2510_usb_talk(d, all_pids, sizeof(all_pids),
- rbuff, sizeof(rbuff));
+ u8 rbuff[10];
/*Restart Stream Command*/
ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on),
rbuff, sizeof(rbuff));
@@ -312,14 +308,6 @@ static void lme2510_int_response(struct urb *lme_urb)
((ibuf[2] & 0x01) << 0x03);
}
break;
- case TUNER_RS2000:
- if (ibuf[2] > 0)
- st->signal_lock = 0xff;
- else
- st->signal_lock = 0xf0;
- st->signal_level = ibuf[4];
- st->signal_sn = ibuf[5];
- st->time_key = ibuf[7];
default:
break;
}
@@ -371,20 +359,19 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
struct lme2510_state *st = adap->dev->priv;
- static u8 clear_pid_reg[] = LME_ALL_PIDS;
+ static u8 clear_pid_reg[] = LME_CLEAR_PID;
static u8 rbuf[1];
int ret;
deb_info(1, "PID Clearing Filter");
- mutex_lock(&adap->dev->i2c_mutex);
+ ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
+ if (ret < 0)
+ return -EAGAIN;
- if (!onoff) {
+ if (!onoff)
ret |= lme2510_usb_talk(adap->dev, clear_pid_reg,
sizeof(clear_pid_reg), rbuf, sizeof(rbuf));
- st->pid_off = true;
- } else
- st->pid_off = false;
st->pid_size = 0;
@@ -402,9 +389,11 @@ static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
pid, index, onoff);
if (onoff) {
- mutex_lock(&adap->dev->i2c_mutex);
- ret |= lme2510_enable_pid(adap->dev, index, pid);
- mutex_unlock(&adap->dev->i2c_mutex);
+ ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
+ if (ret < 0)
+ return -EAGAIN;
+ ret |= lme2510_enable_pid(adap->dev, index, pid);
+ mutex_unlock(&adap->dev->i2c_mutex);
}
@@ -436,6 +425,9 @@ static int lme2510_msg(struct dvb_usb_device *d,
int ret = 0;
struct lme2510_state *st = d->priv;
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
if (st->i2c_talk_onoff == 1) {
ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
@@ -464,6 +456,8 @@ static int lme2510_msg(struct dvb_usb_device *d,
st->i2c_talk_onoff = 0;
}
}
+ if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5))
+ msleep(5);
}
break;
case TUNER_S0194:
@@ -478,12 +472,10 @@ static int lme2510_msg(struct dvb_usb_device *d,
}
}
break;
- case TUNER_RS2000:
default:
break;
}
} else {
- /* TODO rewrite this section */
switch (st->tuner_config) {
case TUNER_LG:
switch (wbuf[3]) {
@@ -567,24 +559,6 @@ static int lme2510_msg(struct dvb_usb_device *d,
break;
}
break;
- case TUNER_RS2000:
- switch (wbuf[3]) {
- case 0x8c:
- rbuf[0] = 0x55;
- rbuf[1] = 0xff;
- if (st->last_key == st->time_key) {
- st->key_timeout++;
- if (st->key_timeout > 5)
- rbuf[1] = 0;
- } else
- st->key_timeout = 0;
- st->last_key = st->time_key;
- break;
- default:
- lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
- st->i2c_talk_onoff = 1;
- break;
- }
default:
break;
}
@@ -594,6 +568,8 @@ static int lme2510_msg(struct dvb_usb_device *d,
}
+ mutex_unlock(&d->i2c_mutex);
+
return ret;
}
@@ -608,8 +584,6 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
u16 len;
u8 gate = st->i2c_gate;
- mutex_lock(&d->i2c_mutex);
-
if (gate == 0)
gate = 5;
@@ -648,7 +622,6 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) {
deb_info(1, "i2c transfer failed.");
- mutex_unlock(&d->i2c_mutex);
return -EAGAIN;
}
@@ -661,8 +634,6 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
}
}
}
-
- mutex_unlock(&d->i2c_mutex);
return i;
}
@@ -682,7 +653,7 @@ static int lme2510_identify_state(struct usb_device *udev,
struct dvb_usb_device_description **desc,
int *cold)
{
- if (pid_filter != 2)
+ if (pid_filter > 0)
props->adapter[0].fe[0].caps &=
~DVB_USB_ADAP_NEED_PID_FILTERING;
*cold = 0;
@@ -692,7 +663,7 @@ static int lme2510_identify_state(struct usb_device *udev,
static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
struct lme2510_state *st = adap->dev->priv;
- static u8 clear_reg_3[] = LME_ALL_PIDS;
+ static u8 clear_reg_3[] = LME_CLEAR_PID;
static u8 rbuf[1];
int ret = 0, rlen = sizeof(rbuf);
@@ -704,7 +675,8 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
else {
deb_info(1, "STM Steam Off");
/* mutex is here only to avoid collision with I2C */
- mutex_lock(&adap->dev->i2c_mutex);
+ if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+ return -EAGAIN;
ret = lme2510_usb_talk(adap->dev, clear_reg_3,
sizeof(clear_reg_3), rbuf, rlen);
@@ -809,18 +781,16 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
const char fw_c_s7395[] = "dvb-usb-lme2510c-s7395.fw";
const char fw_c_lg[] = "dvb-usb-lme2510c-lg.fw";
const char fw_c_s0194[] = "dvb-usb-lme2510c-s0194.fw";
- const char fw_c_rs2000[] = "dvb-usb-lme2510c-rs2000.fw";
const char fw_lg[] = "dvb-usb-lme2510-lg.fw";
const char fw_s0194[] = "dvb-usb-lme2510-s0194.fw";
const char *fw_lme;
- int ret = 0, cold_fw;
+ int ret, cold_fw;
cold = (cold > 0) ? (cold & 1) : 0;
cold_fw = !cold;
- switch (le16_to_cpu(udev->descriptor.idProduct)) {
- case 0x1122:
+ if (le16_to_cpu(udev->descriptor.idProduct) == 0x1122) {
switch (dvb_usb_lme2510_firmware) {
default:
dvb_usb_lme2510_firmware = TUNER_S0194;
@@ -843,8 +813,7 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
cold_fw = 0;
break;
}
- break;
- case 0x1120:
+ } else {
switch (dvb_usb_lme2510_firmware) {
default:
dvb_usb_lme2510_firmware = TUNER_S7395;
@@ -873,17 +842,8 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
cold_fw = 0;
break;
}
- break;
- case 0x22f0:
- fw_lme = fw_c_rs2000;
- ret = request_firmware(&fw, fw_lme, &udev->dev);
- dvb_usb_lme2510_firmware = TUNER_RS2000;
- break;
- default:
- fw_lme = fw_c_s7395;
}
-
if (cold_fw) {
info("FRM Loading %s file", fw_lme);
ret = lme2510_download_firmware(udev, fw);
@@ -946,29 +906,6 @@ static struct stv0299_config sharp_z0194_config = {
.set_symbol_rate = sharp_z0194a_set_symbol_rate,
};
-static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe,
- int caller)
-{
- struct dvb_usb_adapter *adap = fe->dvb->priv;
- struct dvb_usb_device *d = adap->dev;
- struct lme2510_state *st = d->priv;
-
- mutex_lock(&d->i2c_mutex);
- if ((st->i2c_talk_onoff == 1) && (st->stream_on & 1)) {
- st->i2c_talk_onoff = 0;
- lme2510_stream_restart(d);
- }
- mutex_unlock(&d->i2c_mutex);
-
- return 0;
-}
-
-static struct m88rs2000_config m88rs2000_config = {
- .demod_addr = 0xd0,
- .tuner_addr = 0xc0,
- .set_ts_params = dm04_rs2000_set_ts_param,
-};
-
static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
fe_sec_voltage_t voltage)
{
@@ -978,7 +915,8 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
static u8 rbuf[1];
int ret = 0, len = 3, rlen = 1;
- mutex_lock(&adap->dev->i2c_mutex);
+ if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+ return -EAGAIN;
switch (voltage) {
case SEC_VOLTAGE_18:
@@ -999,31 +937,12 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
return (ret < 0) ? -ENODEV : 0;
}
-static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe,
- u16 *strength)
-{
- struct dvb_usb_adapter *adap = fe->dvb->priv;
- struct lme2510_state *st = adap->dev->priv;
-
- *strength = (u16)((u32)st->signal_level * 0xffff / 0x7f);
- return 0;
-}
-
-static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
- struct dvb_usb_adapter *adap = fe->dvb->priv;
- struct lme2510_state *st = adap->dev->priv;
-
- *snr = (u16)((u32)st->signal_sn * 0xffff / 0xff);
- return 0;
-}
-
static int lme_name(struct dvb_usb_adapter *adap)
{
struct lme2510_state *st = adap->dev->priv;
const char *desc = adap->dev->desc->name;
char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395",
- " SHARP:BS2F7HZ0194", " RS2000"};
+ " SHARP:BS2F7HZ0194"};
char *name = adap->fe_adap[0].fe->ops.info.name;
strlcpy(name, desc, 128);
@@ -1039,82 +958,60 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
int ret = 0;
st->i2c_talk_onoff = 1;
- switch (le16_to_cpu(adap->dev->udev->descriptor.idProduct)) {
- case 0x1122:
- case 0x1120:
- st->i2c_gate = 4;
- adap->fe_adap[0].fe = dvb_attach(tda10086_attach,
- &tda10086_config, &adap->dev->i2c_adap);
- if (adap->fe_adap[0].fe) {
- info("TUN Found Frontend TDA10086");
- st->i2c_tuner_gate_w = 4;
- st->i2c_tuner_gate_r = 4;
- st->i2c_tuner_addr = 0xc0;
- st->tuner_config = TUNER_LG;
- if (dvb_usb_lme2510_firmware != TUNER_LG) {
- dvb_usb_lme2510_firmware = TUNER_LG;
- ret = lme_firmware_switch(adap->dev->udev, 1);
- }
- break;
- }
- st->i2c_gate = 4;
- adap->fe_adap[0].fe = dvb_attach(stv0299_attach,
- &sharp_z0194_config, &adap->dev->i2c_adap);
- if (adap->fe_adap[0].fe) {
- info("FE Found Stv0299");
- st->i2c_tuner_gate_w = 4;
- st->i2c_tuner_gate_r = 5;
- st->i2c_tuner_addr = 0xc0;
- st->tuner_config = TUNER_S0194;
- if (dvb_usb_lme2510_firmware != TUNER_S0194) {
- dvb_usb_lme2510_firmware = TUNER_S0194;
- ret = lme_firmware_switch(adap->dev->udev, 1);
- }
- break;
+ st->i2c_gate = 4;
+ adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config,
+ &adap->dev->i2c_adap);
+
+ if (adap->fe_adap[0].fe) {
+ info("TUN Found Frontend TDA10086");
+ st->i2c_tuner_gate_w = 4;
+ st->i2c_tuner_gate_r = 4;
+ st->i2c_tuner_addr = 0xc0;
+ st->tuner_config = TUNER_LG;
+ if (dvb_usb_lme2510_firmware != TUNER_LG) {
+ dvb_usb_lme2510_firmware = TUNER_LG;
+ ret = lme_firmware_switch(adap->dev->udev, 1);
}
+ goto end;
+ }
- st->i2c_gate = 5;
- adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config,
+ st->i2c_gate = 4;
+ adap->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
&adap->dev->i2c_adap);
-
- if (adap->fe_adap[0].fe) {
- info("FE Found Stv0288");
- st->i2c_tuner_gate_w = 4;
- st->i2c_tuner_gate_r = 5;
- st->i2c_tuner_addr = 0xc0;
- st->tuner_config = TUNER_S7395;
- if (dvb_usb_lme2510_firmware != TUNER_S7395) {
- dvb_usb_lme2510_firmware = TUNER_S7395;
- ret = lme_firmware_switch(adap->dev->udev, 1);
- }
- break;
+ if (adap->fe_adap[0].fe) {
+ info("FE Found Stv0299");
+ st->i2c_tuner_gate_w = 4;
+ st->i2c_tuner_gate_r = 5;
+ st->i2c_tuner_addr = 0xc0;
+ st->tuner_config = TUNER_S0194;
+ if (dvb_usb_lme2510_firmware != TUNER_S0194) {
+ dvb_usb_lme2510_firmware = TUNER_S0194;
+ ret = lme_firmware_switch(adap->dev->udev, 1);
}
- case 0x22f0:
- st->i2c_gate = 5;
- adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach,
- &m88rs2000_config, &adap->dev->i2c_adap);
+ goto end;
+ }
- if (adap->fe_adap[0].fe) {
- info("FE Found M88RS2000");
- st->i2c_tuner_gate_w = 5;
- st->i2c_tuner_gate_r = 5;
- st->i2c_tuner_addr = 0xc0;
- st->tuner_config = TUNER_RS2000;
- adap->fe_adap[0].fe->ops.read_signal_strength =
- dm04_rs2000_read_signal_strength;
- adap->fe_adap[0].fe->ops.read_snr =
- dm04_rs2000_read_snr;
+ st->i2c_gate = 5;
+ adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe_adap[0].fe) {
+ info("FE Found Stv0288");
+ st->i2c_tuner_gate_w = 4;
+ st->i2c_tuner_gate_r = 5;
+ st->i2c_tuner_addr = 0xc0;
+ st->tuner_config = TUNER_S7395;
+ if (dvb_usb_lme2510_firmware != TUNER_S7395) {
+ dvb_usb_lme2510_firmware = TUNER_S7395;
+ ret = lme_firmware_switch(adap->dev->udev, 1);
}
- break;
+ } else {
+ info("DM04 Not Supported");
+ return -ENODEV;
}
- if (adap->fe_adap[0].fe == NULL) {
- info("DM04/QQBOX Not Powered up or not Supported");
- return -ENODEV;
- }
- if (ret) {
+end: if (ret) {
if (adap->fe_adap[0].fe) {
dvb_frontend_detach(adap->fe_adap[0].fe);
adap->fe_adap[0].fe = NULL;
@@ -1131,7 +1028,7 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
{
struct lme2510_state *st = adap->dev->priv;
- char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"};
+ char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA"};
int ret = 0;
switch (st->tuner_config) {
@@ -1150,9 +1047,6 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
&adap->dev->i2c_adap, DVB_PLL_OPERA1))
ret = st->tuner_config;
break;
- case TUNER_RS2000:
- ret = st->tuner_config;
- break;
default:
break;
}
@@ -1181,9 +1075,10 @@ static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
static u8 lnb_on[] = LNB_ON;
static u8 lnb_off[] = LNB_OFF;
static u8 rbuf[1];
- int ret = 0, len = 3, rlen = 1;
+ int ret, len = 3, rlen = 1;
- mutex_lock(&d->i2c_mutex);
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
if (onoff)
ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
@@ -1241,7 +1136,6 @@ static int lme2510_probe(struct usb_interface *intf,
static struct usb_device_id lme2510_table[] = {
{ USB_DEVICE(0x3344, 0x1122) }, /* LME2510 */
{ USB_DEVICE(0x3344, 0x1120) }, /* LME2510C */
- { USB_DEVICE(0x3344, 0x22f0) }, /* LME2510C RS2000 */
{} /* Terminating entry */
};
@@ -1259,7 +1153,7 @@ static struct dvb_usb_device_properties lme2510_properties = {
DVB_USB_ADAP_NEED_PID_FILTERING|
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.streaming_ctrl = lme2510_streaming_ctrl,
- .pid_filter_count = 32,
+ .pid_filter_count = 15,
.pid_filter = lme2510_pid_filter,
.pid_filter_ctrl = lme2510_pid_filter_ctrl,
.frontend_attach = dm04_lme2510_frontend_attach,
@@ -1310,7 +1204,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
DVB_USB_ADAP_NEED_PID_FILTERING|
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.streaming_ctrl = lme2510_streaming_ctrl,
- .pid_filter_count = 32,
+ .pid_filter_count = 15,
.pid_filter = lme2510_pid_filter,
.pid_filter_ctrl = lme2510_pid_filter_ctrl,
.frontend_attach = dm04_lme2510_frontend_attach,
@@ -1340,14 +1234,11 @@ static struct dvb_usb_device_properties lme2510c_properties = {
.identify_state = lme2510_identify_state,
.i2c_algo = &lme2510_i2c_algo,
.generic_bulk_ctrl_endpoint = 0,
- .num_device_descs = 2,
+ .num_device_descs = 1,
.devices = {
{ "DM04_LME2510C_DVB-S",
{ &lme2510_table[1], NULL },
},
- { "DM04_LME2510C_DVB-S RS2000",
- { &lme2510_table[2], NULL },
- },
}
};
@@ -1404,5 +1295,5 @@ module_usb_driver(lme2510_driver);
MODULE_AUTHOR("Malcolm Priestley ");
MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.99");
+MODULE_VERSION("1.91");
MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/media/dvb/dvb-usb/lmedm04.h b/trunk/drivers/media/dvb/dvb-usb/lmedm04.h
index e9c207205c2f..ab21e2ef53fa 100644
--- a/trunk/drivers/media/dvb/dvb-usb/lmedm04.h
+++ b/trunk/drivers/media/dvb/dvb-usb/lmedm04.h
@@ -41,7 +41,6 @@
#define LME_ST_ON_W {0x06, 0x00}
#define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0}
#define LME_ZERO_PID {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c}
-#define LME_ALL_PIDS {0x03, 0x06, 0x00, 0xff, 0x01, 0x1f, 0x20, 0x81}
/* LNB Voltage
* 07 XX XX
diff --git a/trunk/drivers/media/dvb/dvb-usb/mxl111sf.c b/trunk/drivers/media/dvb/dvb-usb/mxl111sf.c
index 81305de2fea5..38ef0253d3b5 100644
--- a/trunk/drivers/media/dvb/dvb-usb/mxl111sf.c
+++ b/trunk/drivers/media/dvb/dvb-usb/mxl111sf.c
@@ -351,13 +351,15 @@ static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
adap_state->ep6_clockphase,
0, 0);
mxl_fail(ret);
-#if 0
} else {
ret = mxl111sf_disable_656_port(state);
mxl_fail(ret);
-#endif
}
+ mxl111sf_read_reg(state, 0x12, &tmp);
+ tmp &= ~0x04;
+ mxl111sf_write_reg(state, 0x12, tmp);
+
return ret;
}
diff --git a/trunk/drivers/media/dvb/dvb-usb/rtl28xxu.c b/trunk/drivers/media/dvb/dvb-usb/rtl28xxu.c
deleted file mode 100644
index 8f4736a10fc8..000000000000
--- a/trunk/drivers/media/dvb/dvb-usb/rtl28xxu.c
+++ /dev/null
@@ -1,982 +0,0 @@
-/*
- * Realtek RTL28xxU DVB USB driver
- *
- * Copyright (C) 2009 Antti Palosaari
- * Copyright (C) 2011 Antti Palosaari
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "rtl28xxu.h"
-
-#include "rtl2830.h"
-
-#include "qt1010.h"
-#include "mt2060.h"
-#include "mxl5005s.h"
-
-/* debug */
-static int dvb_usb_rtl28xxu_debug;
-module_param_named(debug, dvb_usb_rtl28xxu_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
-{
- int ret;
- unsigned int pipe;
- u8 requesttype;
- u8 *buf;
-
- buf = kmalloc(req->size, GFP_KERNEL);
- if (!buf) {
- ret = -ENOMEM;
- goto err;
- }
-
- if (req->index & CMD_WR_FLAG) {
- /* write */
- memcpy(buf, req->data, req->size);
- requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
- pipe = usb_sndctrlpipe(d->udev, 0);
- } else {
- /* read */
- requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
- pipe = usb_rcvctrlpipe(d->udev, 0);
- }
-
- ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value,
- req->index, buf, req->size, 1000);
- if (ret > 0)
- ret = 0;
-
- deb_dump(0, requesttype, req->value, req->index, buf, req->size,
- deb_xfer);
-
- /* read request, copy returned data to return buf */
- if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
- memcpy(req->data, buf, req->size);
-
- kfree(buf);
-
- if (ret)
- goto err;
-
- return ret;
-err:
- deb_info("%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
-static int rtl2831_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
-{
- struct rtl28xxu_req req;
-
- if (reg < 0x3000)
- req.index = CMD_USB_WR;
- else if (reg < 0x4000)
- req.index = CMD_SYS_WR;
- else
- req.index = CMD_IR_WR;
-
- req.value = reg;
- req.size = len;
- req.data = val;
-
- return rtl28xxu_ctrl_msg(d, &req);
-}
-
-static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
-{
- struct rtl28xxu_req req;
-
- if (reg < 0x3000)
- req.index = CMD_USB_RD;
- else if (reg < 0x4000)
- req.index = CMD_SYS_RD;
- else
- req.index = CMD_IR_RD;
-
- req.value = reg;
- req.size = len;
- req.data = val;
-
- return rtl28xxu_ctrl_msg(d, &req);
-}
-
-static int rtl2831_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val)
-{
- return rtl2831_wr_regs(d, reg, &val, 1);
-}
-
-static int rtl2831_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
-{
- return rtl2831_rd_regs(d, reg, val, 1);
-}
-
-/* I2C */
-static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
- int num)
-{
- int ret;
- struct dvb_usb_device *d = i2c_get_adapdata(adap);
- struct rtl28xxu_priv *priv = d->priv;
- struct rtl28xxu_req req;
-
- /*
- * It is not known which are real I2C bus xfer limits, but testing
- * with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes.
- * TODO: find out RTL2832U lens
- */
-
- /*
- * I2C adapter logic looks rather complicated due to fact it handles
- * three different access methods. Those methods are;
- * 1) integrated demod access
- * 2) old I2C access
- * 3) new I2C access
- *
- * Used method is selected in order 1, 2, 3. Method 3 can handle all
- * requests but there is two reasons why not use it always;
- * 1) It is most expensive, usually two USB messages are needed
- * 2) At least RTL2831U does not support it
- *
- * Method 3 is needed in case of I2C write+read (typical register read)
- * where write is more than one byte.
- */
-
- if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
- return -EAGAIN;
-
- if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
- (msg[1].flags & I2C_M_RD)) {
- if (msg[0].len > 24 || msg[1].len > 24) {
- /* TODO: check msg[0].len max */
- ret = -EOPNOTSUPP;
- goto err_mutex_unlock;
- } else if (msg[0].addr == 0x10) {
- /* method 1 - integrated demod */
- req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
- req.index = CMD_DEMOD_RD | priv->page;
- req.size = msg[1].len;
- req.data = &msg[1].buf[0];
- ret = rtl28xxu_ctrl_msg(d, &req);
- } else if (msg[0].len < 2) {
- /* method 2 - old I2C */
- req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
- req.index = CMD_I2C_RD;
- req.size = msg[1].len;
- req.data = &msg[1].buf[0];
- ret = rtl28xxu_ctrl_msg(d, &req);
- } else {
- /* method 3 - new I2C */
- req.value = (msg[0].addr << 1);
- req.index = CMD_I2C_DA_WR;
- req.size = msg[0].len;
- req.data = msg[0].buf;
- ret = rtl28xxu_ctrl_msg(d, &req);
- if (ret)
- goto err_mutex_unlock;
-
- req.value = (msg[0].addr << 1);
- req.index = CMD_I2C_DA_RD;
- req.size = msg[1].len;
- req.data = msg[1].buf;
- ret = rtl28xxu_ctrl_msg(d, &req);
- }
- } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
- if (msg[0].len > 22) {
- /* TODO: check msg[0].len max */
- ret = -EOPNOTSUPP;
- goto err_mutex_unlock;
- } else if (msg[0].addr == 0x10) {
- /* method 1 - integrated demod */
- if (msg[0].buf[0] == 0x00) {
- /* save demod page for later demod access */
- priv->page = msg[0].buf[1];
- ret = 0;
- } else {
- req.value = (msg[0].buf[0] << 8) |
- (msg[0].addr << 1);
- req.index = CMD_DEMOD_WR | priv->page;
- req.size = msg[0].len-1;
- req.data = &msg[0].buf[1];
- ret = rtl28xxu_ctrl_msg(d, &req);
- }
- } else if (msg[0].len < 23) {
- /* method 2 - old I2C */
- req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
- req.index = CMD_I2C_WR;
- req.size = msg[0].len-1;
- req.data = &msg[0].buf[1];
- ret = rtl28xxu_ctrl_msg(d, &req);
- } else {
- /* method 3 - new I2C */
- req.value = (msg[0].addr << 1);
- req.index = CMD_I2C_DA_WR;
- req.size = msg[0].len;
- req.data = msg[0].buf;
- ret = rtl28xxu_ctrl_msg(d, &req);
- }
- } else {
- ret = -EINVAL;
- }
-
-err_mutex_unlock:
- mutex_unlock(&d->i2c_mutex);
-
- return ret ? ret : num;
-}
-
-static u32 rtl28xxu_i2c_func(struct i2c_adapter *adapter)
-{
- return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm rtl28xxu_i2c_algo = {
- .master_xfer = rtl28xxu_i2c_xfer,
- .functionality = rtl28xxu_i2c_func,
-};
-
-static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = {
- .i2c_addr = 0x10, /* 0x20 */
- .xtal = 28800000,
- .ts_mode = 0,
- .spec_inv = 1,
- .if_dvbt = 36150000,
- .vtop = 0x20,
- .krf = 0x04,
- .agc_targ_val = 0x2d,
-
-};
-
-static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = {
- .i2c_addr = 0x10, /* 0x20 */
- .xtal = 28800000,
- .ts_mode = 0,
- .spec_inv = 1,
- .if_dvbt = 36125000,
- .vtop = 0x20,
- .krf = 0x04,
- .agc_targ_val = 0x2d,
-};
-
-static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = {
- .i2c_addr = 0x10, /* 0x20 */
- .xtal = 28800000,
- .ts_mode = 0,
- .spec_inv = 0,
- .if_dvbt = 4570000,
- .vtop = 0x3f,
- .krf = 0x04,
- .agc_targ_val = 0x3e,
-};
-
-static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
-{
- int ret;
- struct rtl28xxu_priv *priv = adap->dev->priv;
- u8 buf[1];
- struct rtl2830_config *rtl2830_config;
- /* open RTL2831U/RTL2830 I2C gate */
- struct rtl28xxu_req req_gate = { 0x0120, 0x0011, 0x0001, "\x08" };
- /* for MT2060 tuner probe */
- struct rtl28xxu_req req_mt2060 = { 0x00c0, CMD_I2C_RD, 1, buf };
- /* for QT1010 tuner probe */
- struct rtl28xxu_req req_qt1010 = { 0x0fc4, CMD_I2C_RD, 1, buf };
-
- deb_info("%s:\n", __func__);
-
- /*
- * RTL2831U GPIOs
- * =========================================================
- * GPIO0 | tuner#0 | 0 off | 1 on | MXL5005S (?)
- * GPIO2 | LED | 0 off | 1 on |
- * GPIO4 | tuner#1 | 0 on | 1 off | MT2060
- */
-
- /* GPIO direction */
- ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
- if (ret)
- goto err;
-
- /* enable as output GPIO0, GPIO2, GPIO4 */
- ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15);
- if (ret)
- goto err;
-
- /*
- * Probe used tuner. We need to know used tuner before demod attach
- * since there is some demod params needed to set according to tuner.
- */
-
- /* open demod I2C gate */
- ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate);
- if (ret)
- goto err;
-
- /* check QT1010 ID(?) register; reg=0f val=2c */
- ret = rtl28xxu_ctrl_msg(adap->dev, &req_qt1010);
- if (ret == 0 && buf[0] == 0x2c) {
- priv->tuner = TUNER_RTL2830_QT1010;
- rtl2830_config = &rtl28xxu_rtl2830_qt1010_config;
- deb_info("%s: QT1010\n", __func__);
- goto found;
- } else {
- deb_info("%s: QT1010 probe failed=%d - %02x\n",
- __func__, ret, buf[0]);
- }
-
- /* open demod I2C gate */
- ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate);
- if (ret)
- goto err;
-
- /* check MT2060 ID register; reg=00 val=63 */
- ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2060);
- if (ret == 0 && buf[0] == 0x63) {
- priv->tuner = TUNER_RTL2830_MT2060;
- rtl2830_config = &rtl28xxu_rtl2830_mt2060_config;
- deb_info("%s: MT2060\n", __func__);
- goto found;
- } else {
- deb_info("%s: MT2060 probe failed=%d - %02x\n",
- __func__, ret, buf[0]);
- }
-
- /* assume MXL5005S */
- ret = 0;
- priv->tuner = TUNER_RTL2830_MXL5005S;
- rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config;
- deb_info("%s: MXL5005S\n", __func__);
- goto found;
-
-found:
- /* attach demodulator */
- adap->fe_adap[0].fe = dvb_attach(rtl2830_attach, rtl2830_config,
- &adap->dev->i2c_adap);
- if (adap->fe_adap[0].fe == NULL) {
- ret = -ENODEV;
- goto err;
- }
-
- return ret;
-err:
- deb_info("%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
-static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
-{
- int ret;
- struct rtl28xxu_priv *priv = adap->dev->priv;
- u8 buf[1];
- /* open RTL2832U/RTL2832 I2C gate */
- struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"};
- /* close RTL2832U/RTL2832 I2C gate */
- struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"};
- /* for FC2580 tuner probe */
- struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf};
-
- deb_info("%s:\n", __func__);
-
- /* GPIO direction */
- ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
- if (ret)
- goto err;
-
- /* enable as output GPIO0, GPIO2, GPIO4 */
- ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15);
- if (ret)
- goto err;
-
- ret = rtl2831_wr_reg(adap->dev, SYS_DEMOD_CTL, 0xe8);
- if (ret)
- goto err;
-
- /*
- * Probe used tuner. We need to know used tuner before demod attach
- * since there is some demod params needed to set according to tuner.
- */
-
- /* open demod I2C gate */
- ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_open);
- if (ret)
- goto err;
-
- /* check FC2580 ID register; reg=01 val=56 */
- ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580);
- if (ret == 0 && buf[0] == 0x56) {
- priv->tuner = TUNER_RTL2832_FC2580;
- deb_info("%s: FC2580\n", __func__);
- goto found;
- } else {
- deb_info("%s: FC2580 probe failed=%d - %02x\n",
- __func__, ret, buf[0]);
- }
-
- /* close demod I2C gate */
- ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close);
- if (ret)
- goto err;
-
- /* tuner not found */
- ret = -ENODEV;
- goto err;
-
-found:
- /* close demod I2C gate */
- ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close);
- if (ret)
- goto err;
-
- /* attach demodulator */
- /* TODO: */
-
- return ret;
-err:
- deb_info("%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
-static struct qt1010_config rtl28xxu_qt1010_config = {
- .i2c_address = 0x62, /* 0xc4 */
-};
-
-static struct mt2060_config rtl28xxu_mt2060_config = {
- .i2c_address = 0x60, /* 0xc0 */
- .clock_out = 0,
-};
-
-static struct mxl5005s_config rtl28xxu_mxl5005s_config = {
- .i2c_address = 0x63, /* 0xc6 */
- .if_freq = IF_FREQ_4570000HZ,
- .xtal_freq = CRYSTAL_FREQ_16000000HZ,
- .agc_mode = MXL_SINGLE_AGC,
- .tracking_filter = MXL_TF_C_H,
- .rssi_enable = MXL_RSSI_ENABLE,
- .cap_select = MXL_CAP_SEL_ENABLE,
- .div_out = MXL_DIV_OUT_4,
- .clock_out = MXL_CLOCK_OUT_DISABLE,
- .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
- .top = MXL5005S_TOP_25P2,
- .mod_mode = MXL_DIGITAL_MODE,
- .if_mode = MXL_ZERO_IF,
- .AgcMasterByte = 0x00,
-};
-
-static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap)
-{
- int ret;
- struct rtl28xxu_priv *priv = adap->dev->priv;
- struct i2c_adapter *rtl2830_tuner_i2c;
- struct dvb_frontend *fe;
-
- deb_info("%s:\n", __func__);
-
- /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */
- rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe_adap[0].fe);
-
- switch (priv->tuner) {
- case TUNER_RTL2830_QT1010:
- fe = dvb_attach(qt1010_attach, adap->fe_adap[0].fe,
- rtl2830_tuner_i2c, &rtl28xxu_qt1010_config);
- break;
- case TUNER_RTL2830_MT2060:
- fe = dvb_attach(mt2060_attach, adap->fe_adap[0].fe,
- rtl2830_tuner_i2c, &rtl28xxu_mt2060_config,
- 1220);
- break;
- case TUNER_RTL2830_MXL5005S:
- fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
- rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config);
- break;
- default:
- fe = NULL;
- err("unknown tuner=%d", priv->tuner);
- }
-
- if (fe == NULL) {
- ret = -ENODEV;
- goto err;
- }
-
- return 0;
-err:
- deb_info("%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
-static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
-{
- int ret;
- struct rtl28xxu_priv *priv = adap->dev->priv;
- struct dvb_frontend *fe;
-
- deb_info("%s:\n", __func__);
-
- switch (priv->tuner) {
- case TUNER_RTL2832_FC2580:
- /* TODO: */
- fe = NULL;
- break;
- default:
- fe = NULL;
- err("unknown tuner=%d", priv->tuner);
- }
-
- if (fe == NULL) {
- ret = -ENODEV;
- goto err;
- }
-
- return 0;
-err:
- deb_info("%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
-static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
-{
- int ret;
- u8 buf[2], gpio;
-
- deb_info("%s: onoff=%d\n", __func__, onoff);
-
- ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio);
- if (ret)
- goto err;
-
- if (onoff) {
- buf[0] = 0x00;
- buf[1] = 0x00;
- gpio |= 0x04; /* LED on */
- } else {
- buf[0] = 0x10; /* stall EPA */
- buf[1] = 0x02; /* reset EPA */
- gpio &= (~0x04); /* LED off */
- }
-
- ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio);
- if (ret)
- goto err;
-
- ret = rtl2831_wr_regs(adap->dev, USB_EPA_CTL, buf, 2);
- if (ret)
- goto err;
-
- return ret;
-err:
- deb_info("%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
-static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
- int ret;
- u8 gpio, sys0;
-
- deb_info("%s: onoff=%d\n", __func__, onoff);
-
- /* demod adc */
- ret = rtl2831_rd_reg(d, SYS_SYS0, &sys0);
- if (ret)
- goto err;
-
- /* tuner power, read GPIOs */
- ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio);
- if (ret)
- goto err;
-
- deb_info("%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio);
-
- if (onoff) {
- gpio |= 0x01; /* GPIO0 = 1 */
- gpio &= (~0x10); /* GPIO4 = 0 */
- sys0 = sys0 & 0x0f;
- sys0 |= 0xe0;
- } else {
- gpio &= (~0x01); /* GPIO0 = 0 */
- gpio |= 0x10; /* GPIO4 = 1 */
- sys0 = sys0 & (~0xc0);
- }
-
- deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio);
-
- /* demod adc */
- ret = rtl2831_wr_reg(d, SYS_SYS0, sys0);
- if (ret)
- goto err;
-
- /* tuner power, write GPIOs */
- ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, gpio);
- if (ret)
- goto err;
-
- return ret;
-err:
- deb_info("%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
-static int rtl2831u_rc_query(struct dvb_usb_device *d)
-{
- int ret, i;
- struct rtl28xxu_priv *priv = d->priv;
- u8 buf[5];
- u32 rc_code;
- struct rtl28xxu_reg_val rc_nec_tab[] = {
- { 0x3033, 0x80 },
- { 0x3020, 0x43 },
- { 0x3021, 0x16 },
- { 0x3022, 0x16 },
- { 0x3023, 0x5a },
- { 0x3024, 0x2d },
- { 0x3025, 0x16 },
- { 0x3026, 0x01 },
- { 0x3028, 0xb0 },
- { 0x3029, 0x04 },
- { 0x302c, 0x88 },
- { 0x302e, 0x13 },
- { 0x3030, 0xdf },
- { 0x3031, 0x05 },
- };
-
- /* init remote controller */
- if (!priv->rc_active) {
- for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
- ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg,
- rc_nec_tab[i].val);
- if (ret)
- goto err;
- }
- priv->rc_active = true;
- }
-
- ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5);
- if (ret)
- goto err;
-
- if (buf[4] & 0x01) {
- if (buf[2] == (u8) ~buf[3]) {
- if (buf[0] == (u8) ~buf[1]) {
- /* NEC standard (16 bit) */
- rc_code = buf[0] << 8 | buf[2];
- } else {
- /* NEC extended (24 bit) */
- rc_code = buf[0] << 16 |
- buf[1] << 8 | buf[2];
- }
- } else {
- /* NEC full (32 bit) */
- rc_code = buf[0] << 24 | buf[1] << 16 |
- buf[2] << 8 | buf[3];
- }
-
- rc_keydown(d->rc_dev, rc_code, 0);
-
- ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1);
- if (ret)
- goto err;
-
- /* repeated intentionally to avoid extra keypress */
- ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1);
- if (ret)
- goto err;
- }
-
- return ret;
-err:
- deb_info("%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
-static int rtl2832u_rc_query(struct dvb_usb_device *d)
-{
- int ret, i;
- struct rtl28xxu_priv *priv = d->priv;
- u8 buf[128];
- int len;
- struct rtl28xxu_reg_val rc_nec_tab[] = {
- { IR_RX_CTRL, 0x20 },
- { IR_RX_BUF_CTRL, 0x80 },
- { IR_RX_IF, 0xff },
- { IR_RX_IE, 0xff },
- { IR_MAX_DURATION0, 0xd0 },
- { IR_MAX_DURATION1, 0x07 },
- { IR_IDLE_LEN0, 0xc0 },
- { IR_IDLE_LEN1, 0x00 },
- { IR_GLITCH_LEN, 0x03 },
- { IR_RX_CLK, 0x09 },
- { IR_RX_CFG, 0x1c },
- { IR_MAX_H_TOL_LEN, 0x1e },
- { IR_MAX_L_TOL_LEN, 0x1e },
- { IR_RX_CTRL, 0x80 },
- };
-
- /* init remote controller */
- if (!priv->rc_active) {
- for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
- ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg,
- rc_nec_tab[i].val);
- if (ret)
- goto err;
- }
- priv->rc_active = true;
- }
-
- ret = rtl2831_rd_reg(d, IR_RX_IF, &buf[0]);
- if (ret)
- goto err;
-
- if (buf[0] != 0x83)
- goto exit;
-
- ret = rtl2831_rd_reg(d, IR_RX_BC, &buf[0]);
- if (ret)
- goto err;
-
- len = buf[0];
- ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len);
-
- /* TODO: pass raw IR to Kernel IR decoder */
-
- ret = rtl2831_wr_reg(d, IR_RX_IF, 0x03);
- ret = rtl2831_wr_reg(d, IR_RX_BUF_CTRL, 0x80);
- ret = rtl2831_wr_reg(d, IR_RX_CTRL, 0x80);
-
-exit:
- return ret;
-err:
- deb_info("%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
-enum rtl28xxu_usb_table_entry {
- RTL2831U_0BDA_2831,
- RTL2831U_14AA_0160,
- RTL2831U_14AA_0161,
-};
-
-static struct usb_device_id rtl28xxu_table[] = {
- /* RTL2831U */
- [RTL2831U_0BDA_2831] = {
- USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U)},
- [RTL2831U_14AA_0160] = {
- USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT)},
- [RTL2831U_14AA_0161] = {
- USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)},
-
- /* RTL2832U */
- {} /* terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, rtl28xxu_table);
-
-static struct dvb_usb_device_properties rtl28xxu_properties[] = {
- {
- .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
- .usb_ctrl = DEVICE_SPECIFIC,
- .no_reconnect = 1,
-
- .size_of_priv = sizeof(struct rtl28xxu_priv),
-
- .num_adapters = 1,
- .adapter = {
- {
- .num_frontends = 1,
- .fe = {
- {
- .frontend_attach = rtl2831u_frontend_attach,
- .tuner_attach = rtl2831u_tuner_attach,
- .streaming_ctrl = rtl28xxu_streaming_ctrl,
- .stream = {
- .type = USB_BULK,
- .count = 6,
- .endpoint = 0x81,
- .u = {
- .bulk = {
- .buffersize = 8*512,
- }
- }
- }
- }
- }
- }
- },
-
- .power_ctrl = rtl28xxu_power_ctrl,
-
- .rc.core = {
- .protocol = RC_TYPE_NEC,
- .module_name = "rtl28xxu",
- .rc_query = rtl2831u_rc_query,
- .rc_interval = 400,
- .allowed_protos = RC_TYPE_NEC,
- .rc_codes = RC_MAP_EMPTY,
- },
-
- .i2c_algo = &rtl28xxu_i2c_algo,
-
- .num_device_descs = 2,
- .devices = {
- {
- .name = "Realtek RTL2831U reference design",
- .warm_ids = {
- &rtl28xxu_table[RTL2831U_0BDA_2831],
- },
- },
- {
- .name = "Freecom USB2.0 DVB-T",
- .warm_ids = {
- &rtl28xxu_table[RTL2831U_14AA_0160],
- &rtl28xxu_table[RTL2831U_14AA_0161],
- },
- },
- }
- },
- {
- .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
- .usb_ctrl = DEVICE_SPECIFIC,
- .no_reconnect = 1,
-
- .size_of_priv = sizeof(struct rtl28xxu_priv),
-
- .num_adapters = 1,
- .adapter = {
- {
- .num_frontends = 1,
- .fe = {
- {
- .frontend_attach = rtl2832u_frontend_attach,
- .tuner_attach = rtl2832u_tuner_attach,
- .streaming_ctrl = rtl28xxu_streaming_ctrl,
- .stream = {
- .type = USB_BULK,
- .count = 6,
- .endpoint = 0x81,
- .u = {
- .bulk = {
- .buffersize = 8*512,
- }
- }
- }
- }
- }
- }
- },
-
- .power_ctrl = rtl28xxu_power_ctrl,
-
- .rc.core = {
- .protocol = RC_TYPE_NEC,
- .module_name = "rtl28xxu",
- .rc_query = rtl2832u_rc_query,
- .rc_interval = 400,
- .allowed_protos = RC_TYPE_NEC,
- .rc_codes = RC_MAP_EMPTY,
- },
-
- .i2c_algo = &rtl28xxu_i2c_algo,
-
- .num_device_descs = 0, /* disabled as no support for RTL2832 */
- .devices = {
- {
- .name = "Realtek RTL2832U reference design",
- },
- }
- },
-
-};
-
-static int rtl28xxu_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- int ret, i;
- int properties_count = ARRAY_SIZE(rtl28xxu_properties);
- struct dvb_usb_device *d;
-
- deb_info("%s: interface=%d\n", __func__,
- intf->cur_altsetting->desc.bInterfaceNumber);
-
- if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
- return 0;
-
- for (i = 0; i < properties_count; i++) {
- ret = dvb_usb_device_init(intf, &rtl28xxu_properties[i],
- THIS_MODULE, &d, adapter_nr);
- if (ret == 0 || ret != -ENODEV)
- break;
- }
-
- if (ret)
- goto err;
-
- /* init USB endpoints */
- ret = rtl2831_wr_reg(d, USB_SYSCTL_0, 0x09);
- if (ret)
- goto err;
-
- ret = rtl2831_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
- if (ret)
- goto err;
-
- ret = rtl2831_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
- if (ret)
- goto err;
-
- return ret;
-err:
- deb_info("%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
-static struct usb_driver rtl28xxu_driver = {
- .name = "dvb_usb_rtl28xxu",
- .probe = rtl28xxu_probe,
- .disconnect = dvb_usb_device_exit,
- .id_table = rtl28xxu_table,
-};
-
-/* module stuff */
-static int __init rtl28xxu_module_init(void)
-{
- int ret;
-
- deb_info("%s:\n", __func__);
-
- ret = usb_register(&rtl28xxu_driver);
- if (ret)
- err("usb_register failed=%d", ret);
-
- return ret;
-}
-
-static void __exit rtl28xxu_module_exit(void)
-{
- deb_info("%s:\n", __func__);
-
- /* deregister this driver from the USB subsystem */
- usb_deregister(&rtl28xxu_driver);
-}
-
-module_init(rtl28xxu_module_init);
-module_exit(rtl28xxu_module_exit);
-
-MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver");
-MODULE_AUTHOR("Antti Palosaari ");
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/media/dvb/dvb-usb/rtl28xxu.h b/trunk/drivers/media/dvb/dvb-usb/rtl28xxu.h
deleted file mode 100644
index 90f3bb4f4c0e..000000000000
--- a/trunk/drivers/media/dvb/dvb-usb/rtl28xxu.h
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Realtek RTL28xxU DVB USB driver
- *
- * Copyright (C) 2009 Antti Palosaari
- * Copyright (C) 2011 Antti Palosaari
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef RTL28XXU_H
-#define RTL28XXU_H
-
-#define DVB_USB_LOG_PREFIX "rtl28xxu"
-#include "dvb-usb.h"
-
-#define deb_info(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x01, args)
-#define deb_rc(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x02, args)
-#define deb_xfer(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x04, args)
-#define deb_reg(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x08, args)
-#define deb_i2c(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x10, args)
-#define deb_fw(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x20, args)
-
-#define deb_dump(r, t, v, i, b, l, func) { \
- int loop_; \
- func("%02x %02x %02x %02x %02x %02x %02x %02x", \
- t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \
- if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \
- func(" >>> "); \
- else \
- func(" <<< "); \
- for (loop_ = 0; loop_ < l; loop_++) \
- func("%02x ", b[loop_]); \
- func("\n");\
-}
-
-/*
- * USB commands
- * (usb_control_msg() index parameter)
- */
-
-#define DEMOD 0x0000
-#define USB 0x0100
-#define SYS 0x0200
-#define I2C 0x0300
-#define I2C_DA 0x0600
-
-#define CMD_WR_FLAG 0x0010
-#define CMD_DEMOD_RD 0x0000
-#define CMD_DEMOD_WR 0x0010
-#define CMD_USB_RD 0x0100
-#define CMD_USB_WR 0x0110
-#define CMD_SYS_RD 0x0200
-#define CMD_IR_RD 0x0201
-#define CMD_IR_WR 0x0211
-#define CMD_SYS_WR 0x0210
-#define CMD_I2C_RD 0x0300
-#define CMD_I2C_WR 0x0310
-#define CMD_I2C_DA_RD 0x0600
-#define CMD_I2C_DA_WR 0x0610
-
-
-struct rtl28xxu_priv {
- u8 chip_id;
- u8 tuner;
- u8 page; /* integrated demod active register page */
- bool rc_active;
-};
-
-enum rtl28xxu_chip_id {
- CHIP_ID_NONE,
- CHIP_ID_RTL2831U,
- CHIP_ID_RTL2832U,
-};
-
-enum rtl28xxu_tuner {
- TUNER_NONE,
-
- TUNER_RTL2830_QT1010,
- TUNER_RTL2830_MT2060,
- TUNER_RTL2830_MXL5005S,
-
- TUNER_RTL2832_MT2266,
- TUNER_RTL2832_FC2580,
- TUNER_RTL2832_MT2063,
- TUNER_RTL2832_MAX3543,
- TUNER_RTL2832_TUA9001,
- TUNER_RTL2832_MXL5007T,
- TUNER_RTL2832_FC0012,
- TUNER_RTL2832_E4000,
- TUNER_RTL2832_TDA18272,
- TUNER_RTL2832_FC0013,
-};
-
-struct rtl28xxu_req {
- u16 value;
- u16 index;
- u16 size;
- u8 *data;
-};
-
-struct rtl28xxu_reg_val {
- u16 reg;
- u8 val;
-};
-
-/*
- * memory map
- *
- * 0x0000 DEMOD : demodulator
- * 0x2000 USB : SIE, USB endpoint, debug, DMA
- * 0x3000 SYS : system
- * 0xfc00 RC : remote controller (not RTL2831U)
- */
-
-/*
- * USB registers
- */
-/* SIE Control Registers */
-#define USB_SYSCTL 0x2000 /* USB system control */
-#define USB_SYSCTL_0 0x2000 /* USB system control */
-#define USB_SYSCTL_1 0x2001 /* USB system control */
-#define USB_SYSCTL_2 0x2002 /* USB system control */
-#define USB_SYSCTL_3 0x2003 /* USB system control */
-#define USB_IRQSTAT 0x2008 /* SIE interrupt status */
-#define USB_IRQEN 0x200C /* SIE interrupt enable */
-#define USB_CTRL 0x2010 /* USB control */
-#define USB_STAT 0x2014 /* USB status */
-#define USB_DEVADDR 0x2018 /* USB device address */
-#define USB_TEST 0x201C /* USB test mode */
-#define USB_FRAME_NUMBER 0x2020 /* frame number */
-#define USB_FIFO_ADDR 0x2028 /* address of SIE FIFO RAM */
-#define USB_FIFO_CMD 0x202A /* SIE FIFO RAM access command */
-#define USB_FIFO_DATA 0x2030 /* SIE FIFO RAM data */
-/* Endpoint Registers */
-#define EP0_SETUPA 0x20F8 /* EP 0 setup packet lower byte */
-#define EP0_SETUPB 0x20FC /* EP 0 setup packet higher byte */
-#define USB_EP0_CFG 0x2104 /* EP 0 configure */
-#define USB_EP0_CTL 0x2108 /* EP 0 control */
-#define USB_EP0_STAT 0x210C /* EP 0 status */
-#define USB_EP0_IRQSTAT 0x2110 /* EP 0 interrupt status */
-#define USB_EP0_IRQEN 0x2114 /* EP 0 interrupt enable */
-#define USB_EP0_MAXPKT 0x2118 /* EP 0 max packet size */
-#define USB_EP0_BC 0x2120 /* EP 0 FIFO byte counter */
-#define USB_EPA_CFG 0x2144 /* EP A configure */
-#define USB_EPA_CFG_0 0x2144 /* EP A configure */
-#define USB_EPA_CFG_1 0x2145 /* EP A configure */
-#define USB_EPA_CFG_2 0x2146 /* EP A configure */
-#define USB_EPA_CFG_3 0x2147 /* EP A configure */
-#define USB_EPA_CTL 0x2148 /* EP A control */
-#define USB_EPA_CTL_0 0x2148 /* EP A control */
-#define USB_EPA_CTL_1 0x2149 /* EP A control */
-#define USB_EPA_CTL_2 0x214A /* EP A control */
-#define USB_EPA_CTL_3 0x214B /* EP A control */
-#define USB_EPA_STAT 0x214C /* EP A status */
-#define USB_EPA_IRQSTAT 0x2150 /* EP A interrupt status */
-#define USB_EPA_IRQEN 0x2154 /* EP A interrupt enable */
-#define USB_EPA_MAXPKT 0x2158 /* EP A max packet size */
-#define USB_EPA_MAXPKT_0 0x2158 /* EP A max packet size */
-#define USB_EPA_MAXPKT_1 0x2159 /* EP A max packet size */
-#define USB_EPA_MAXPKT_2 0x215A /* EP A max packet size */
-#define USB_EPA_MAXPKT_3 0x215B /* EP A max packet size */
-#define USB_EPA_FIFO_CFG 0x2160 /* EP A FIFO configure */
-#define USB_EPA_FIFO_CFG_0 0x2160 /* EP A FIFO configure */
-#define USB_EPA_FIFO_CFG_1 0x2161 /* EP A FIFO configure */
-#define USB_EPA_FIFO_CFG_2 0x2162 /* EP A FIFO configure */
-#define USB_EPA_FIFO_CFG_3 0x2163 /* EP A FIFO configure */
-/* Debug Registers */
-#define USB_PHYTSTDIS 0x2F04 /* PHY test disable */
-#define USB_TOUT_VAL 0x2F08 /* USB time-out time */
-#define USB_VDRCTRL 0x2F10 /* UTMI vendor signal control */
-#define USB_VSTAIN 0x2F14 /* UTMI vendor signal status in */
-#define USB_VLOADM 0x2F18 /* UTMI load vendor signal status in */
-#define USB_VSTAOUT 0x2F1C /* UTMI vendor signal status out */
-#define USB_UTMI_TST 0x2F80 /* UTMI test */
-#define USB_UTMI_STATUS 0x2F84 /* UTMI status */
-#define USB_TSTCTL 0x2F88 /* test control */
-#define USB_TSTCTL2 0x2F8C /* test control 2 */
-#define USB_PID_FORCE 0x2F90 /* force PID */
-#define USB_PKTERR_CNT 0x2F94 /* packet error counter */
-#define USB_RXERR_CNT 0x2F98 /* RX error counter */
-#define USB_MEM_BIST 0x2F9C /* MEM BIST test */
-#define USB_SLBBIST 0x2FA0 /* self-loop-back BIST */
-#define USB_CNTTEST 0x2FA4 /* counter test */
-#define USB_PHYTST 0x2FC0 /* USB PHY test */
-#define USB_DBGIDX 0x2FF0 /* select individual block debug signal */
-#define USB_DBGMUX 0x2FF4 /* debug signal module mux */
-
-/*
- * SYS registers
- */
-/* demod control registers */
-#define SYS_SYS0 0x3000 /* include DEMOD_CTL, GPO, GPI, GPOE */
-#define SYS_DEMOD_CTL 0x3000 /* control register for DVB-T demodulator */
-/* GPIO registers */
-#define SYS_GPIO_OUT_VAL 0x3001 /* output value of GPIO */
-#define SYS_GPIO_IN_VAL 0x3002 /* input value of GPIO */
-#define SYS_GPIO_OUT_EN 0x3003 /* output enable of GPIO */
-#define SYS_SYS1 0x3004 /* include GPD, SYSINTE, SYSINTS, GP_CFG0 */
-#define SYS_GPIO_DIR 0x3004 /* direction control for GPIO */
-#define SYS_SYSINTE 0x3005 /* system interrupt enable */
-#define SYS_SYSINTS 0x3006 /* system interrupt status */
-#define SYS_GPIO_CFG0 0x3007 /* PAD configuration for GPIO0-GPIO3 */
-#define SYS_SYS2 0x3008 /* include GP_CFG1 and 3 reserved bytes */
-#define SYS_GPIO_CFG1 0x3008 /* PAD configuration for GPIO4 */
-#define SYS_DEMOD_CTL1 0x300B
-
-/* IrDA registers */
-#define SYS_IRRC_PSR 0x3020 /* IR protocol selection */
-#define SYS_IRRC_PER 0x3024 /* IR protocol extension */
-#define SYS_IRRC_SF 0x3028 /* IR sampling frequency */
-#define SYS_IRRC_DPIR 0x302C /* IR data package interval */
-#define SYS_IRRC_CR 0x3030 /* IR control */
-#define SYS_IRRC_RP 0x3034 /* IR read port */
-#define SYS_IRRC_SR 0x3038 /* IR status */
-/* I2C master registers */
-#define SYS_I2CCR 0x3040 /* I2C clock */
-#define SYS_I2CMCR 0x3044 /* I2C master control */
-#define SYS_I2CMSTR 0x3048 /* I2C master SCL timing */
-#define SYS_I2CMSR 0x304C /* I2C master status */
-#define SYS_I2CMFR 0x3050 /* I2C master FIFO */
-
-/*
- * IR registers
- */
-#define IR_RX_BUF 0xFC00
-#define IR_RX_IE 0xFD00
-#define IR_RX_IF 0xFD01
-#define IR_RX_CTRL 0xFD02
-#define IR_RX_CFG 0xFD03
-#define IR_MAX_DURATION0 0xFD04
-#define IR_MAX_DURATION1 0xFD05
-#define IR_IDLE_LEN0 0xFD06
-#define IR_IDLE_LEN1 0xFD07
-#define IR_GLITCH_LEN 0xFD08
-#define IR_RX_BUF_CTRL 0xFD09
-#define IR_RX_BUF_DATA 0xFD0A
-#define IR_RX_BC 0xFD0B
-#define IR_RX_CLK 0xFD0C
-#define IR_RX_C_COUNT_L 0xFD0D
-#define IR_RX_C_COUNT_H 0xFD0E
-#define IR_SUSPEND_CTRL 0xFD10
-#define IR_ERR_TOL_CTRL 0xFD11
-#define IR_UNIT_LEN 0xFD12
-#define IR_ERR_TOL_LEN 0xFD13
-#define IR_MAX_H_TOL_LEN 0xFD14
-#define IR_MAX_L_TOL_LEN 0xFD15
-#define IR_MASK_CTRL 0xFD16
-#define IR_MASK_DATA 0xFD17
-#define IR_RES_MASK_ADDR 0xFD18
-#define IR_RES_MASK_T_LEN 0xFD19
-
-#endif
diff --git a/trunk/drivers/media/dvb/frontends/Kconfig b/trunk/drivers/media/dvb/frontends/Kconfig
index 21246707fbfb..ebb5ed7a7783 100644
--- a/trunk/drivers/media/dvb/frontends/Kconfig
+++ b/trunk/drivers/media/dvb/frontends/Kconfig
@@ -425,13 +425,6 @@ config DVB_CXD2820R
help
Say Y when you want to support this frontend.
-config DVB_RTL2830
- tristate "Realtek RTL2830 DVB-T"
- depends on DVB_CORE && I2C
- default m if DVB_FE_CUSTOMISE
- help
- Say Y when you want to support this frontend.
-
comment "DVB-C (cable) frontends"
depends on DVB_CORE
@@ -705,14 +698,6 @@ config DVB_IT913X_FE
A DVB-T tuner module.
Say Y when you want to support this frontend.
-config DVB_M88RS2000
- tristate "M88RS2000 DVB-S demodulator and tuner"
- depends on DVB_CORE && I2C
- default m if DVB_FE_CUSTOMISE
- help
- A DVB-S tuner module.
- Say Y when you want to support this frontend.
-
comment "Tools to develop new frontends"
config DVB_DUMMY_FE
diff --git a/trunk/drivers/media/dvb/frontends/Makefile b/trunk/drivers/media/dvb/frontends/Makefile
index 86fa808bf589..00a20636df62 100644
--- a/trunk/drivers/media/dvb/frontends/Makefile
+++ b/trunk/drivers/media/dvb/frontends/Makefile
@@ -2,8 +2,8 @@
# Makefile for the kernel DVB frontend device drivers.
#
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core/
-ccflags-y += -I$(srctree)/drivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/common/tuners/
stb0899-objs = stb0899_drv.o stb0899_algo.o
stv0900-objs = stv0900_core.o stv0900_sw.o
@@ -96,6 +96,4 @@ obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
obj-$(CONFIG_DVB_A8293) += a8293.o
obj-$(CONFIG_DVB_TDA10071) += tda10071.o
-obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
-obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
diff --git a/trunk/drivers/media/dvb/frontends/au8522_decoder.c b/trunk/drivers/media/dvb/frontends/au8522_decoder.c
index 55b6390198e3..2b248c12f404 100644
--- a/trunk/drivers/media/dvb/frontends/au8522_decoder.c
+++ b/trunk/drivers/media/dvb/frontends/au8522_decoder.c
@@ -839,4 +839,15 @@ static struct i2c_driver au8522_driver = {
.id_table = au8522_id,
};
-module_i2c_driver(au8522_driver);
+static __init int init_au8522(void)
+{
+ return i2c_add_driver(&au8522_driver);
+}
+
+static __exit void exit_au8522(void)
+{
+ i2c_del_driver(&au8522_driver);
+}
+
+module_init(init_au8522);
+module_exit(exit_au8522);
diff --git a/trunk/drivers/media/dvb/frontends/au8522_dig.c b/trunk/drivers/media/dvb/frontends/au8522_dig.c
index 25f650934c73..c688b95df486 100644
--- a/trunk/drivers/media/dvb/frontends/au8522_dig.c
+++ b/trunk/drivers/media/dvb/frontends/au8522_dig.c
@@ -588,6 +588,11 @@ static int au8522_set_frontend(struct dvb_frontend *fe)
(state->current_modulation == c->modulation))
return 0;
+ au8522_enable_modulation(fe, c->modulation);
+
+ /* Allow the demod to settle */
+ msleep(100);
+
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -599,11 +604,6 @@ static int au8522_set_frontend(struct dvb_frontend *fe)
if (ret < 0)
return ret;
- /* Allow the tuner to settle */
- msleep(100);
-
- au8522_enable_modulation(fe, c->modulation);
-
state->current_frequency = c->frequency;
return 0;
diff --git a/trunk/drivers/media/dvb/frontends/cx22702.c b/trunk/drivers/media/dvb/frontends/cx22702.c
index edc8eafc5c09..faba82485086 100644
--- a/trunk/drivers/media/dvb/frontends/cx22702.c
+++ b/trunk/drivers/media/dvb/frontends/cx22702.c
@@ -502,26 +502,10 @@ static int cx22702_read_signal_strength(struct dvb_frontend *fe,
u16 *signal_strength)
{
struct cx22702_state *state = fe->demodulator_priv;
- u8 reg23;
- /*
- * Experience suggests that the strength signal register works as
- * follows:
- * - In the absence of signal, value is 0xff.
- * - In the presence of a weak signal, bit 7 is set, not sure what
- * the lower 7 bits mean.
- * - In the presence of a strong signal, the register holds a 7-bit
- * value (bit 7 is cleared), with greater values standing for
- * weaker signals.
- */
- reg23 = cx22702_readreg(state, 0x23);
- if (reg23 & 0x80) {
- *signal_strength = 0;
- } else {
- reg23 = ~reg23 & 0x7f;
- /* Scale to 16 bit */
- *signal_strength = (reg23 << 9) | (reg23 << 2) | (reg23 >> 5);
- }
+ u16 rs_ber;
+ rs_ber = cx22702_readreg(state, 0x23);
+ *signal_strength = (rs_ber << 8) | rs_ber;
return 0;
}
diff --git a/trunk/drivers/media/dvb/frontends/dib0090.c b/trunk/drivers/media/dvb/frontends/dib0090.c
index d9fe60b4be48..224d81e85091 100644
--- a/trunk/drivers/media/dvb/frontends/dib0090.c
+++ b/trunk/drivers/media/dvb/frontends/dib0090.c
@@ -519,7 +519,7 @@ static int dib0090_fw_identify(struct dvb_frontend *fe)
return 0;
identification_error:
- return -EIO;
+ return -EIO;;
}
static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
diff --git a/trunk/drivers/media/dvb/frontends/dib9000.c b/trunk/drivers/media/dvb/frontends/dib9000.c
index 80848b4c15d4..863ef3cfab9f 100644
--- a/trunk/drivers/media/dvb/frontends/dib9000.c
+++ b/trunk/drivers/media/dvb/frontends/dib9000.c
@@ -33,7 +33,7 @@ struct i2c_device {
/* lock */
#define DIB_LOCK struct mutex
-#define DibAcquireLock(lock) mutex_lock_interruptible(lock)
+#define DibAcquireLock(lock) do { if (mutex_lock_interruptible(lock) < 0) dprintk("could not get the lock"); } while (0)
#define DibReleaseLock(lock) mutex_unlock(lock)
#define DibInitLock(lock) mutex_init(lock)
#define DibFreeLock(lock)
@@ -446,10 +446,7 @@ static int dib9000_risc_mem_read(struct dib9000_state *state, u8 cmd, u8 * b, u1
if (!state->platform.risc.fw_is_running)
return -EIO;
- if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
+ DibAcquireLock(&state->platform.risc.mem_lock);
dib9000_risc_mem_setup(state, cmd | 0x80);
dib9000_risc_mem_read_chunks(state, b, len);
DibReleaseLock(&state->platform.risc.mem_lock);
@@ -462,10 +459,7 @@ static int dib9000_risc_mem_write(struct dib9000_state *state, u8 cmd, const u8
if (!state->platform.risc.fw_is_running)
return -EIO;
- if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
+ DibAcquireLock(&state->platform.risc.mem_lock);
dib9000_risc_mem_setup(state, cmd);
dib9000_risc_mem_write_chunks(state, b, m->size);
DibReleaseLock(&state->platform.risc.mem_lock);
@@ -537,10 +531,7 @@ static int dib9000_mbx_send_attr(struct dib9000_state *state, u8 id, u16 * data,
if (!state->platform.risc.fw_is_running)
return -EINVAL;
- if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
+ DibAcquireLock(&state->platform.risc.mbx_if_lock);
tmp = MAX_MAILBOX_TRY;
do {
size = dib9000_read_word_attr(state, 1043, attr) & 0xff;
@@ -602,10 +593,7 @@ static u8 dib9000_mbx_read(struct dib9000_state *state, u16 * data, u8 risc_id,
if (!state->platform.risc.fw_is_running)
return 0;
- if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) {
- dprintk("could not get the lock");
- return 0;
- }
+ DibAcquireLock(&state->platform.risc.mbx_if_lock);
if (risc_id == 1)
mc_base = 16;
else
@@ -713,10 +701,7 @@ static int dib9000_mbx_process(struct dib9000_state *state, u16 attr)
if (!state->platform.risc.fw_is_running)
return -1;
- if (DibAcquireLock(&state->platform.risc.mbx_lock) < 0) {
- dprintk("could not get the lock");
- return -1;
- }
+ DibAcquireLock(&state->platform.risc.mbx_lock);
if (dib9000_mbx_count(state, 1, attr)) /* 1=RiscB */
ret = dib9000_mbx_fetch_to_cache(state, attr);
@@ -1193,10 +1178,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe)
struct dibDVBTChannel *ch;
int ret = 0;
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
ret = -EIO;
goto error;
@@ -1678,10 +1660,7 @@ static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2
p[12] = 0;
}
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
- dprintk("could not get the lock");
- return 0;
- }
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p);
@@ -1789,10 +1768,7 @@ int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
return 0;
}
- if (DibAcquireLock(&state->demod_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
+ DibAcquireLock(&state->demod_lock);
val = dib9000_read_word(state, 294 + 1) & 0xffef;
val |= (onoff & 0x1) << 4;
@@ -1824,10 +1800,7 @@ int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
return 0;
}
- if (DibAcquireLock(&state->demod_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
+ DibAcquireLock(&state->demod_lock);
dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
ret = dib9000_write_word(state, 300 + 1 + id,
onoff ? (1 << 13) | pid : 0);
@@ -1875,10 +1848,7 @@ static int dib9000_sleep(struct dvb_frontend *fe)
u8 index_frontend;
int ret = 0;
- if (DibAcquireLock(&state->demod_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
+ DibAcquireLock(&state->demod_lock);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
if (ret < 0)
@@ -1904,12 +1874,8 @@ static int dib9000_get_frontend(struct dvb_frontend *fe)
fe_status_t stat;
int ret = 0;
- if (state->get_frontend_internal == 0) {
- if (DibAcquireLock(&state->demod_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
- }
+ if (state->get_frontend_internal == 0)
+ DibAcquireLock(&state->demod_lock);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
@@ -2012,10 +1978,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe)
}
state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
- if (DibAcquireLock(&state->demod_lock) < 0) {
- dprintk("could not get the lock");
- return 0;
- }
+ DibAcquireLock(&state->demod_lock);
fe->dtv_property_cache.delivery_system = SYS_DVBT;
@@ -2175,10 +2138,7 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
u8 index_frontend;
u16 lock = 0, lock_slave = 0;
- if (DibAcquireLock(&state->demod_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
+ DibAcquireLock(&state->demod_lock);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
@@ -2208,15 +2168,8 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
u16 *c;
int ret = 0;
- if (DibAcquireLock(&state->demod_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
- dprintk("could not get the lock");
- ret = -EINTR;
- goto error;
- }
+ DibAcquireLock(&state->demod_lock);
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
ret = -EIO;
@@ -2243,10 +2196,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
u16 val;
int ret = 0;
- if (DibAcquireLock(&state->demod_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
+ DibAcquireLock(&state->demod_lock);
*strength = 0;
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
@@ -2256,13 +2206,8 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
*strength += val;
}
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
- dprintk("could not get the lock");
- ret = -EINTR;
- goto error;
- }
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
ret = -EIO;
goto error;
}
@@ -2287,14 +2232,9 @@ static u32 dib9000_get_snr(struct dvb_frontend *fe)
u32 n, s, exp;
u16 val;
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
- dprintk("could not get the lock");
- return 0;
- }
- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
- return 0;
- }
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+ return -EIO;
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
@@ -2326,10 +2266,7 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
u8 index_frontend;
u32 snr_master;
- if (DibAcquireLock(&state->demod_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
+ DibAcquireLock(&state->demod_lock);
snr_master = dib9000_get_snr(fe);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
snr_master += dib9000_get_snr(state->fe[index_frontend]);
@@ -2351,17 +2288,9 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
u16 *c = (u16 *)state->i2c_read_buffer;
int ret = 0;
- if (DibAcquireLock(&state->demod_lock) < 0) {
- dprintk("could not get the lock");
- return -EINTR;
- }
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
- dprintk("could not get the lock");
- ret = -EINTR;
- goto error;
- }
+ DibAcquireLock(&state->demod_lock);
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
ret = -EIO;
goto error;
}
diff --git a/trunk/drivers/media/dvb/frontends/drxd_hard.c b/trunk/drivers/media/dvb/frontends/drxd_hard.c
index f380eb43e9d5..7bf39cda83c5 100644
--- a/trunk/drivers/media/dvb/frontends/drxd_hard.c
+++ b/trunk/drivers/media/dvb/frontends/drxd_hard.c
@@ -101,9 +101,9 @@ struct SCfgAgc {
struct SNoiseCal {
int cpOpt;
- short cpNexpOfs;
- short tdCal2k;
- short tdCal8k;
+ u16 cpNexpOfs;
+ u16 tdCal2k;
+ u16 tdCal8k;
};
enum app_env {
diff --git a/trunk/drivers/media/dvb/frontends/drxk.h b/trunk/drivers/media/dvb/frontends/drxk.h
index 9d64e4fea066..020981844a86 100644
--- a/trunk/drivers/media/dvb/frontends/drxk.h
+++ b/trunk/drivers/media/dvb/frontends/drxk.h
@@ -7,19 +7,15 @@
/**
* struct drxk_config - Configure the initial parameters for DRX-K
*
- * @adr: I2C Address of the DRX-K
- * @parallel_ts: True means that the device uses parallel TS,
+ * adr: I2C Address of the DRX-K
+ * parallel_ts: true means that the device uses parallel TS,
* Serial otherwise.
- * @dynamic_clk: True means that the clock will be dynamically
- * adjusted. Static clock otherwise.
- * @enable_merr_cfg: Enable SIO_PDR_PERR_CFG/SIO_PDR_MVAL_CFG.
- * @single_master: Device is on the single master mode
- * @no_i2c_bridge: Don't switch the I2C bridge to talk with tuner
- * @antenna_gpio: GPIO bit used to control the antenna
- * @antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1
+ * single_master: Device is on the single master mode
+ * no_i2c_bridge: Don't switch the I2C bridge to talk with tuner
+ * antenna_gpio: GPIO bit used to control the antenna
+ * antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1
* means that 1=DVBC, 0 = DVBT. Zero means the opposite.
- * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength.
- * @microcode_name: Name of the firmware file with the microcode
+ * microcode_name: Name of the firmware file with the microcode
*
* On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is
* UIO-3.
@@ -29,14 +25,11 @@ struct drxk_config {
bool single_master;
bool no_i2c_bridge;
bool parallel_ts;
- bool dynamic_clk;
- bool enable_merr_cfg;
bool antenna_dvbt;
u16 antenna_gpio;
- u8 mpeg_out_clk_strength;
- int chunk_size;
+ int chunk_size;
const char *microcode_name;
};
diff --git a/trunk/drivers/media/dvb/frontends/drxk_hard.c b/trunk/drivers/media/dvb/frontends/drxk_hard.c
index 36d11756492f..5ab53795bd7a 100644
--- a/trunk/drivers/media/dvb/frontends/drxk_hard.c
+++ b/trunk/drivers/media/dvb/frontends/drxk_hard.c
@@ -90,6 +90,10 @@ bool IsA1WithRomCode(struct drxk_state *state)
#define DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH (0x03)
#endif
+#ifndef DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH
+#define DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH (0x06)
+#endif
+
#define DEFAULT_DRXK_MPEG_LOCK_TIMEOUT 700
#define DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT 500
@@ -645,6 +649,9 @@ static int init_state(struct drxk_state *state)
u32 ulQual83 = DEFAULT_MER_83;
u32 ulQual93 = DEFAULT_MER_93;
+ u32 ulDVBTStaticTSClock = 1;
+ u32 ulDVBCStaticTSClock = 1;
+
u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
@@ -654,6 +661,7 @@ static int init_state(struct drxk_state *state)
u32 ulGPIOCfg = 0x0113;
u32 ulInvertTSClock = 0;
u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH;
+ u32 ulTSClockkStrength = DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH;
u32 ulDVBTBitrate = 50000000;
u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8;
@@ -806,7 +814,8 @@ static int init_state(struct drxk_state *state)
state->m_invertSTR = false; /* If TRUE; invert STR signals */
state->m_invertVAL = false; /* If TRUE; invert VAL signals */
state->m_invertCLK = (ulInvertTSClock != 0); /* If TRUE; invert CLK signals */
-
+ state->m_DVBTStaticCLK = (ulDVBTStaticTSClock != 0);
+ state->m_DVBCStaticCLK = (ulDVBCStaticTSClock != 0);
/* If TRUE; static MPEG clockrate will be used;
otherwise clockrate will adapt to the bitrate of the TS */
@@ -814,6 +823,7 @@ static int init_state(struct drxk_state *state)
state->m_DVBCBitrate = ulDVBCBitrate;
state->m_TSDataStrength = (ulTSDataStrength & 0x07);
+ state->m_TSClockkStrength = (ulTSClockkStrength & 0x07);
/* Maximum bitrate in b/s in case static clockrate is selected */
state->m_mpegTsStaticBitrate = 19392658;
@@ -1178,7 +1188,6 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable)
int status = -1;
u16 sioPdrMclkCfg = 0;
u16 sioPdrMdxCfg = 0;
- u16 err_cfg = 0;
dprintk(1, ": mpeg %s, %s mode\n",
mpegEnable ? "enable" : "disable",
@@ -1244,17 +1253,12 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable)
status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg);
if (status < 0)
goto error;
-
- if (state->enable_merr_cfg)
- err_cfg = sioPdrMdxCfg;
-
- status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg);
+ status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000); /* Disable */
if (status < 0)
goto error;
- status = write16(state, SIO_PDR_MVAL_CFG__A, err_cfg);
+ status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000); /* Disable */
if (status < 0)
goto error;
-
if (state->m_enableParallel == true) {
/* paralel -> enable MD1 to MD7 */
status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg);
@@ -6065,7 +6069,9 @@ static int init_drxk(struct drxk_state *state)
if (status < 0)
goto error;
- if (state->microcode_name)
+ if (!state->microcode_name)
+ load_microcode(state, "drxk_a3.mc");
+ else
load_microcode(state, state->microcode_name);
/* disable token-ring bus through OFDM block for possible ucode upload */
@@ -6316,12 +6322,15 @@ static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_t
switch (p->delivery_system) {
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
- case SYS_DVBT:
sets->min_delay_ms = 3000;
sets->max_drift = 0;
sets->step_size = 0;
return 0;
default:
+ /*
+ * For DVB-T, let it use the default DVB core way, that is:
+ * fepriv->step_size = fe->ops.info.frequency_stepsize * 2
+ */
return -EINVAL;
}
}
@@ -6381,21 +6390,6 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
state->antenna_gpio = config->antenna_gpio;
state->antenna_dvbt = config->antenna_dvbt;
state->m_ChunkSize = config->chunk_size;
- state->enable_merr_cfg = config->enable_merr_cfg;
-
- if (config->dynamic_clk) {
- state->m_DVBTStaticCLK = 0;
- state->m_DVBCStaticCLK = 0;
- } else {
- state->m_DVBTStaticCLK = 1;
- state->m_DVBCStaticCLK = 1;
- }
-
-
- if (config->mpeg_out_clk_strength)
- state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07;
- else
- state->m_TSClockkStrength = 0x06;
if (config->parallel_ts)
state->m_enableParallel = true;
diff --git a/trunk/drivers/media/dvb/frontends/drxk_hard.h b/trunk/drivers/media/dvb/frontends/drxk_hard.h
index 4bbf841de83a..3a58b73eb9b9 100644
--- a/trunk/drivers/media/dvb/frontends/drxk_hard.h
+++ b/trunk/drivers/media/dvb/frontends/drxk_hard.h
@@ -332,7 +332,6 @@ struct drxk_state {
u16 UIO_mask; /* Bits used by UIO */
- bool enable_merr_cfg;
bool single_master;
bool no_i2c_bridge;
bool antenna_dvbt;
diff --git a/trunk/drivers/media/dvb/frontends/it913x-fe-priv.h b/trunk/drivers/media/dvb/frontends/it913x-fe-priv.h
index eb6fd8aebdb3..93b086ea7e1c 100644
--- a/trunk/drivers/media/dvb/frontends/it913x-fe-priv.h
+++ b/trunk/drivers/media/dvb/frontends/it913x-fe-priv.h
@@ -201,11 +201,6 @@ fe_modulation_t fe_con[] = {
QAM_64,
};
-enum {
- PRIORITY_HIGH = 0, /* High-priority stream */
- PRIORITY_LOW, /* Low-priority stream */
-};
-
/* Standard demodulator functions */
static struct it913xset set_solo_fe[] = {
{PRO_LINK, GPIOH5_EN, {0x01}, 0x01},
diff --git a/trunk/drivers/media/dvb/frontends/it913x-fe.c b/trunk/drivers/media/dvb/frontends/it913x-fe.c
index 84df03c29179..ccc36bf2deb4 100644
--- a/trunk/drivers/media/dvb/frontends/it913x-fe.c
+++ b/trunk/drivers/media/dvb/frontends/it913x-fe.c
@@ -57,7 +57,6 @@ struct it913x_fe_state {
u32 frequency;
fe_modulation_t constellation;
fe_transmit_mode_t transmission_mode;
- u8 priority;
u32 crystalFrequency;
u32 adcFrequency;
u8 tuner_type;
@@ -501,87 +500,19 @@ static int it913x_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
return 0;
}
-/* FEC values based on fe_code_rate_t non supported values 0*/
-int it913x_qpsk_pval[] = {0, -93, -91, -90, 0, -89, -88};
-int it913x_16qam_pval[] = {0, -87, -85, -84, 0, -83, -82};
-int it913x_64qam_pval[] = {0, -82, -80, -78, 0, -77, -76};
-
-static int it913x_get_signal_strength(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *p = &fe->dtv_property_cache;
- struct it913x_fe_state *state = fe->demodulator_priv;
- u8 code_rate;
- int ret, temp;
- u8 lna_gain_os;
-
- ret = it913x_read_reg_u8(state, VAR_P_INBAND);
- if (ret < 0)
- return ret;
-
- /* VHF/UHF gain offset */
- if (state->frequency < 300000000)
- lna_gain_os = 7;
- else
- lna_gain_os = 14;
-
- temp = (ret - 100) - lna_gain_os;
-
- if (state->priority == PRIORITY_HIGH)
- code_rate = p->code_rate_HP;
- else
- code_rate = p->code_rate_LP;
-
- if (code_rate >= ARRAY_SIZE(it913x_qpsk_pval))
- return -EINVAL;
-
- deb_info("Reg VAR_P_INBAND:%d Calc Offset Value:%d", ret, temp);
-
- /* Apply FEC offset values*/
- switch (p->modulation) {
- case QPSK:
- temp -= it913x_qpsk_pval[code_rate];
- break;
- case QAM_16:
- temp -= it913x_16qam_pval[code_rate];
- break;
- case QAM_64:
- temp -= it913x_64qam_pval[code_rate];
- break;
- default:
- return -EINVAL;
- }
-
- if (temp < -15)
- ret = 0;
- else if ((-15 <= temp) && (temp < 0))
- ret = (2 * (temp + 15)) / 3;
- else if ((0 <= temp) && (temp < 20))
- ret = 4 * temp + 10;
- else if ((20 <= temp) && (temp < 35))
- ret = (2 * (temp - 20)) / 3 + 90;
- else if (temp >= 35)
- ret = 100;
-
- deb_info("Signal Strength :%d", ret);
-
- return ret;
-}
-
static int it913x_fe_read_signal_strength(struct dvb_frontend *fe,
u16 *strength)
{
struct it913x_fe_state *state = fe->demodulator_priv;
- int ret = 0;
- if (state->config->read_slevel) {
- if (state->it913x_status & FE_HAS_SIGNAL)
- ret = it913x_read_reg_u8(state, SIGNAL_LEVEL);
- } else
- ret = it913x_get_signal_strength(fe);
-
- if (ret >= 0)
- *strength = (u16)((u32)ret * 0xffff / 0x64);
-
- return (ret < 0) ? -ENODEV : 0;
+ int ret = it913x_read_reg_u8(state, SIGNAL_LEVEL);
+ /*SIGNAL_LEVEL always returns 100%! so using FE_HAS_SIGNAL as switch*/
+ if (state->it913x_status & FE_HAS_SIGNAL)
+ ret = (ret * 0xff) / 0x64;
+ else
+ ret = 0x0;
+ ret |= ret << 0x8;
+ *strength = ret;
+ return 0;
}
static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
@@ -675,8 +606,6 @@ static int it913x_fe_get_frontend(struct dvb_frontend *fe)
if (reg[2] < 4)
p->hierarchy = fe_hi[reg[2]];
- state->priority = reg[5];
-
p->code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
p->code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
@@ -1043,5 +972,5 @@ static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
MODULE_DESCRIPTION("it913x Frontend and it9137 tuner");
MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
-MODULE_VERSION("1.15");
+MODULE_VERSION("1.13");
MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/media/dvb/frontends/it913x-fe.h b/trunk/drivers/media/dvb/frontends/it913x-fe.h
index 07fa4594c12b..c4a908e354e0 100644
--- a/trunk/drivers/media/dvb/frontends/it913x-fe.h
+++ b/trunk/drivers/media/dvb/frontends/it913x-fe.h
@@ -34,8 +34,6 @@ struct ite_config {
u8 tuner_id_1;
u8 dual_mode;
u8 adf;
- /* option to read SIGNAL_LEVEL */
- u8 read_slevel;
};
#if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \
@@ -170,8 +168,6 @@ static inline struct dvb_frontend *it913x_fe_attach(
#define EST_SIGNAL_LEVEL 0x004a
#define FREE_BAND 0x004b
#define SUSPEND_FLAG 0x004c
-#define VAR_P_INBAND 0x00f7
-
/* Build in tuner types */
#define IT9137 0x38
#define IT9135_38 0x38
diff --git a/trunk/drivers/media/dvb/frontends/lgdt330x.c b/trunk/drivers/media/dvb/frontends/lgdt330x.c
index e046622df0e4..c990d35a13dc 100644
--- a/trunk/drivers/media/dvb/frontends/lgdt330x.c
+++ b/trunk/drivers/media/dvb/frontends/lgdt330x.c
@@ -104,8 +104,8 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state,
* then reads the data returned for (len) bytes.
*/
-static int i2c_read_demod_bytes(struct lgdt330x_state *state,
- enum I2C_REG reg, u8 *buf, int len)
+static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
+ enum I2C_REG reg, u8* buf, int len)
{
u8 wr [] = { reg };
struct i2c_msg msg [] = {
@@ -118,8 +118,6 @@ static int i2c_read_demod_bytes(struct lgdt330x_state *state,
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) {
printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
- if (ret >= 0)
- ret = -EIO;
} else {
ret = 0;
}
diff --git a/trunk/drivers/media/dvb/frontends/m88rs2000.c b/trunk/drivers/media/dvb/frontends/m88rs2000.c
deleted file mode 100644
index 045ee5a6f7ae..000000000000
--- a/trunk/drivers/media/dvb/frontends/m88rs2000.c
+++ /dev/null
@@ -1,904 +0,0 @@
-/*
- Driver for M88RS2000 demodulator and tuner
-
- Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com)
- Beta Driver
-
- Include various calculation code from DS3000 driver.
- Copyright (C) 2009 Konstantin Dimitrov.
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-#include "dvb_frontend.h"
-#include "m88rs2000.h"
-
-struct m88rs2000_state {
- struct i2c_adapter *i2c;
- const struct m88rs2000_config *config;
- struct dvb_frontend frontend;
- u8 no_lock_count;
- u32 tuner_frequency;
- u32 symbol_rate;
- fe_code_rate_t fec_inner;
- u8 tuner_level;
- int errmode;
-};
-
-static int m88rs2000_debug;
-
-module_param_named(debug, m88rs2000_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
-
-#define dprintk(level, args...) do { \
- if (level & m88rs2000_debug) \
- printk(KERN_DEBUG "m88rs2000-fe: " args); \
-} while (0)
-
-#define deb_info(args...) dprintk(0x01, args)
-#define info(format, arg...) \
- printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg)
-
-static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner,
- u8 reg, u8 data)
-{
- int ret;
- u8 addr = (tuner == 0) ? state->config->tuner_addr :
- state->config->demod_addr;
- u8 buf[] = { reg, data };
- struct i2c_msg msg = {
- .addr = addr,
- .flags = 0,
- .buf = buf,
- .len = 2
- };
-
- ret = i2c_transfer(state->i2c, &msg, 1);
-
- if (ret != 1)
- deb_info("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
- "ret == %i)\n", __func__, reg, data, ret);
-
- return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static int m88rs2000_demod_write(struct m88rs2000_state *state, u8 reg, u8 data)
-{
- return m88rs2000_writereg(state, 1, reg, data);
-}
-
-static int m88rs2000_tuner_write(struct m88rs2000_state *state, u8 reg, u8 data)
-{
- m88rs2000_demod_write(state, 0x81, 0x84);
- udelay(10);
- return m88rs2000_writereg(state, 0, reg, data);
-
-}
-
-static int m88rs2000_write(struct dvb_frontend *fe, const u8 buf[], int len)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
-
- if (len != 2)
- return -EINVAL;
-
- return m88rs2000_writereg(state, 1, buf[0], buf[1]);
-}
-
-static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg)
-{
- int ret;
- u8 b0[] = { reg };
- u8 b1[] = { 0 };
- u8 addr = (tuner == 0) ? state->config->tuner_addr :
- state->config->demod_addr;
- struct i2c_msg msg[] = {
- {
- .addr = addr,
- .flags = 0,
- .buf = b0,
- .len = 1
- }, {
- .addr = addr,
- .flags = I2C_M_RD,
- .buf = b1,
- .len = 1
- }
- };
-
- ret = i2c_transfer(state->i2c, msg, 2);
-
- if (ret != 2)
- deb_info("%s: readreg error (reg == 0x%02x, ret == %i)\n",
- __func__, reg, ret);
-
- return b1[0];
-}
-
-static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg)
-{
- return m88rs2000_readreg(state, 1, reg);
-}
-
-static u8 m88rs2000_tuner_read(struct m88rs2000_state *state, u8 reg)
-{
- m88rs2000_demod_write(state, 0x81, 0x85);
- udelay(10);
- return m88rs2000_readreg(state, 0, reg);
-}
-
-static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
- int ret;
- u32 temp;
- u8 b[3];
-
- if ((srate < 1000000) || (srate > 45000000))
- return -EINVAL;
-
- temp = srate / 1000;
- temp *= 11831;
- temp /= 68;
- temp -= 3;
-
- b[0] = (u8) (temp >> 16) & 0xff;
- b[1] = (u8) (temp >> 8) & 0xff;
- b[2] = (u8) temp & 0xff;
- ret = m88rs2000_demod_write(state, 0x93, b[2]);
- ret |= m88rs2000_demod_write(state, 0x94, b[1]);
- ret |= m88rs2000_demod_write(state, 0x95, b[0]);
-
- deb_info("m88rs2000: m88rs2000_set_symbolrate\n");
- return ret;
-}
-
-static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe,
- struct dvb_diseqc_master_cmd *m)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
-
- int i;
- u8 reg;
- deb_info("%s\n", __func__);
- m88rs2000_demod_write(state, 0x9a, 0x30);
- reg = m88rs2000_demod_read(state, 0xb2);
- reg &= 0x3f;
- m88rs2000_demod_write(state, 0xb2, reg);
- for (i = 0; i < m->msg_len; i++)
- m88rs2000_demod_write(state, 0xb3 + i, m->msg[i]);
-
- reg = m88rs2000_demod_read(state, 0xb1);
- reg &= 0x87;
- reg |= ((m->msg_len - 1) << 3) | 0x07;
- reg &= 0x7f;
- m88rs2000_demod_write(state, 0xb1, reg);
-
- for (i = 0; i < 15; i++) {
- if ((m88rs2000_demod_read(state, 0xb1) & 0x40) == 0x0)
- break;
- msleep(20);
- }
-
- reg = m88rs2000_demod_read(state, 0xb1);
- if ((reg & 0x40) > 0x0) {
- reg &= 0x7f;
- reg |= 0x40;
- m88rs2000_demod_write(state, 0xb1, reg);
- }
-
- reg = m88rs2000_demod_read(state, 0xb2);
- reg &= 0x3f;
- reg |= 0x80;
- m88rs2000_demod_write(state, 0xb2, reg);
- m88rs2000_demod_write(state, 0x9a, 0xb0);
-
-
- return 0;
-}
-
-static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe,
- fe_sec_mini_cmd_t burst)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
- u8 reg0, reg1;
- deb_info("%s\n", __func__);
- m88rs2000_demod_write(state, 0x9a, 0x30);
- msleep(50);
- reg0 = m88rs2000_demod_read(state, 0xb1);
- reg1 = m88rs2000_demod_read(state, 0xb2);
- /* TODO complete this section */
- m88rs2000_demod_write(state, 0xb2, reg1);
- m88rs2000_demod_write(state, 0xb1, reg0);
- m88rs2000_demod_write(state, 0x9a, 0xb0);
-
- return 0;
-}
-
-static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
- u8 reg0, reg1;
- m88rs2000_demod_write(state, 0x9a, 0x30);
- reg0 = m88rs2000_demod_read(state, 0xb1);
- reg1 = m88rs2000_demod_read(state, 0xb2);
-
- reg1 &= 0x3f;
-
- switch (tone) {
- case SEC_TONE_ON:
- reg0 |= 0x4;
- reg0 &= 0xbc;
- break;
- case SEC_TONE_OFF:
- reg1 |= 0x80;
- break;
- default:
- break;
- }
- m88rs2000_demod_write(state, 0xb2, reg1);
- m88rs2000_demod_write(state, 0xb1, reg0);
- m88rs2000_demod_write(state, 0x9a, 0xb0);
- return 0;
-}
-
-struct inittab {
- u8 cmd;
- u8 reg;
- u8 val;
-};
-
-struct inittab m88rs2000_setup[] = {
- {DEMOD_WRITE, 0x9a, 0x30},
- {DEMOD_WRITE, 0x00, 0x01},
- {WRITE_DELAY, 0x19, 0x00},
- {DEMOD_WRITE, 0x00, 0x00},
- {DEMOD_WRITE, 0x9a, 0xb0},
- {DEMOD_WRITE, 0x81, 0xc1},
- {TUNER_WRITE, 0x42, 0x73},
- {TUNER_WRITE, 0x05, 0x07},
- {TUNER_WRITE, 0x20, 0x27},
- {TUNER_WRITE, 0x07, 0x02},
- {TUNER_WRITE, 0x11, 0xff},
- {TUNER_WRITE, 0x60, 0xf9},
- {TUNER_WRITE, 0x08, 0x01},
- {TUNER_WRITE, 0x00, 0x41},
- {DEMOD_WRITE, 0x81, 0x81},
- {DEMOD_WRITE, 0x86, 0xc6},
- {DEMOD_WRITE, 0x9a, 0x30},
- {DEMOD_WRITE, 0xf0, 0x22},
- {DEMOD_WRITE, 0xf1, 0xbf},
- {DEMOD_WRITE, 0xb0, 0x45},
- {DEMOD_WRITE, 0xb2, 0x01}, /* set voltage pin always set 1*/
- {DEMOD_WRITE, 0x9a, 0xb0},
- {0xff, 0xaa, 0xff}
-};
-
-struct inittab m88rs2000_shutdown[] = {
- {DEMOD_WRITE, 0x9a, 0x30},
- {DEMOD_WRITE, 0xb0, 0x00},
- {DEMOD_WRITE, 0xf1, 0x89},
- {DEMOD_WRITE, 0x00, 0x01},
- {DEMOD_WRITE, 0x9a, 0xb0},
- {TUNER_WRITE, 0x00, 0x40},
- {DEMOD_WRITE, 0x81, 0x81},
- {0xff, 0xaa, 0xff}
-};
-
-struct inittab tuner_reset[] = {
- {TUNER_WRITE, 0x42, 0x73},
- {TUNER_WRITE, 0x05, 0x07},
- {TUNER_WRITE, 0x20, 0x27},
- {TUNER_WRITE, 0x07, 0x02},
- {TUNER_WRITE, 0x11, 0xff},
- {TUNER_WRITE, 0x60, 0xf9},
- {TUNER_WRITE, 0x08, 0x01},
- {TUNER_WRITE, 0x00, 0x41},
- {0xff, 0xaa, 0xff}
-};
-
-struct inittab fe_reset[] = {
- {DEMOD_WRITE, 0x00, 0x01},
- {DEMOD_WRITE, 0xf1, 0xbf},
- {DEMOD_WRITE, 0x00, 0x01},
- {DEMOD_WRITE, 0x20, 0x81},
- {DEMOD_WRITE, 0x21, 0x80},
- {DEMOD_WRITE, 0x10, 0x33},
- {DEMOD_WRITE, 0x11, 0x44},
- {DEMOD_WRITE, 0x12, 0x07},
- {DEMOD_WRITE, 0x18, 0x20},
- {DEMOD_WRITE, 0x28, 0x04},
- {DEMOD_WRITE, 0x29, 0x8e},
- {DEMOD_WRITE, 0x3b, 0xff},
- {DEMOD_WRITE, 0x32, 0x10},
- {DEMOD_WRITE, 0x33, 0x02},
- {DEMOD_WRITE, 0x34, 0x30},
- {DEMOD_WRITE, 0x35, 0xff},
- {DEMOD_WRITE, 0x38, 0x50},
- {DEMOD_WRITE, 0x39, 0x68},
- {DEMOD_WRITE, 0x3c, 0x7f},
- {DEMOD_WRITE, 0x3d, 0x0f},
- {DEMOD_WRITE, 0x45, 0x20},
- {DEMOD_WRITE, 0x46, 0x24},
- {DEMOD_WRITE, 0x47, 0x7c},
- {DEMOD_WRITE, 0x48, 0x16},
- {DEMOD_WRITE, 0x49, 0x04},
- {DEMOD_WRITE, 0x4a, 0x01},
- {DEMOD_WRITE, 0x4b, 0x78},
- {DEMOD_WRITE, 0X4d, 0xd2},
- {DEMOD_WRITE, 0x4e, 0x6d},
- {DEMOD_WRITE, 0x50, 0x30},
- {DEMOD_WRITE, 0x51, 0x30},
- {DEMOD_WRITE, 0x54, 0x7b},
- {DEMOD_WRITE, 0x56, 0x09},
- {DEMOD_WRITE, 0x58, 0x59},
- {DEMOD_WRITE, 0x59, 0x37},
- {DEMOD_WRITE, 0x63, 0xfa},
- {0xff, 0xaa, 0xff}
-};
-
-struct inittab fe_trigger[] = {
- {DEMOD_WRITE, 0x97, 0x04},
- {DEMOD_WRITE, 0x99, 0x77},
- {DEMOD_WRITE, 0x9b, 0x64},
- {DEMOD_WRITE, 0x9e, 0x00},
- {DEMOD_WRITE, 0x9f, 0xf8},
- {DEMOD_WRITE, 0xa0, 0x20},
- {DEMOD_WRITE, 0xa1, 0xe0},
- {DEMOD_WRITE, 0xa3, 0x38},
- {DEMOD_WRITE, 0x98, 0xff},
- {DEMOD_WRITE, 0xc0, 0x0f},
- {DEMOD_WRITE, 0x89, 0x01},
- {DEMOD_WRITE, 0x00, 0x00},
- {WRITE_DELAY, 0x0a, 0x00},
- {DEMOD_WRITE, 0x00, 0x01},
- {DEMOD_WRITE, 0x00, 0x00},
- {DEMOD_WRITE, 0x9a, 0xb0},
- {0xff, 0xaa, 0xff}
-};
-
-static int m88rs2000_tab_set(struct m88rs2000_state *state,
- struct inittab *tab)
-{
- int ret = 0;
- u8 i;
- if (tab == NULL)
- return -EINVAL;
-
- for (i = 0; i < 255; i++) {
- switch (tab[i].cmd) {
- case 0x01:
- ret = m88rs2000_demod_write(state, tab[i].reg,
- tab[i].val);
- break;
- case 0x02:
- ret = m88rs2000_tuner_write(state, tab[i].reg,
- tab[i].val);
- break;
- case 0x10:
- if (tab[i].reg > 0)
- mdelay(tab[i].reg);
- break;
- case 0xff:
- if (tab[i].reg == 0xaa && tab[i].val == 0xff)
- return 0;
- case 0x00:
- break;
- default:
- return -EINVAL;
- }
- if (ret < 0)
- return -ENODEV;
- }
- return 0;
-}
-
-static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
-{
- deb_info("%s: %s\n", __func__,
- volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
- volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
-
- return 0;
-}
-
-static int m88rs2000_startup(struct m88rs2000_state *state)
-{
- int ret = 0;
- u8 reg;
-
- reg = m88rs2000_tuner_read(state, 0x00);
- if ((reg & 0x40) == 0)
- ret = -ENODEV;
-
- return ret;
-}
-
-static int m88rs2000_init(struct dvb_frontend *fe)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
- int ret;
-
- deb_info("m88rs2000: init chip\n");
- /* Setup frontend from shutdown/cold */
- ret = m88rs2000_tab_set(state, m88rs2000_setup);
-
- return ret;
-}
-
-static int m88rs2000_sleep(struct dvb_frontend *fe)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
- int ret;
- /* Shutdown the frondend */
- ret = m88rs2000_tab_set(state, m88rs2000_shutdown);
- return ret;
-}
-
-static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
- u8 reg = m88rs2000_demod_read(state, 0x8c);
-
- *status = 0;
-
- if ((reg & 0x7) == 0x7) {
- *status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI
- | FE_HAS_LOCK;
- if (state->config->set_ts_params)
- state->config->set_ts_params(fe, CALL_IS_READ);
- }
- return 0;
-}
-
-/* Extact code for these unknown but lmedm04 driver uses interupt callbacks */
-
-static int m88rs2000_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
- deb_info("m88rs2000_read_ber %d\n", *ber);
- *ber = 0;
- return 0;
-}
-
-static int m88rs2000_read_signal_strength(struct dvb_frontend *fe,
- u16 *strength)
-{
- *strength = 0;
- return 0;
-}
-
-static int m88rs2000_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
- deb_info("m88rs2000_read_snr %d\n", *snr);
- *snr = 0;
- return 0;
-}
-
-static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
- deb_info("m88rs2000_read_ber %d\n", *ucblocks);
- *ucblocks = 0;
- return 0;
-}
-
-static int m88rs2000_tuner_gate_ctrl(struct m88rs2000_state *state, u8 offset)
-{
- int ret;
- ret = m88rs2000_tuner_write(state, 0x51, 0x1f - offset);
- ret |= m88rs2000_tuner_write(state, 0x51, 0x1f);
- ret |= m88rs2000_tuner_write(state, 0x50, offset);
- ret |= m88rs2000_tuner_write(state, 0x50, 0x00);
- msleep(20);
- return ret;
-}
-
-static int m88rs2000_set_tuner_rf(struct dvb_frontend *fe)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
- int reg;
- reg = m88rs2000_tuner_read(state, 0x3d);
- reg &= 0x7f;
- if (reg < 0x16)
- reg = 0xa1;
- else if (reg == 0x16)
- reg = 0x99;
- else
- reg = 0xf9;
-
- m88rs2000_tuner_write(state, 0x60, reg);
- reg = m88rs2000_tuner_gate_ctrl(state, 0x08);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
- return reg;
-}
-
-static int m88rs2000_set_tuner(struct dvb_frontend *fe, u16 *offset)
-{
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct m88rs2000_state *state = fe->demodulator_priv;
- int ret;
- u32 frequency = c->frequency;
- s32 offset_khz;
- s32 tmp;
- u32 symbol_rate = (c->symbol_rate / 1000);
- u32 f3db, gdiv28;
- u16 value, ndiv, lpf_coeff;
- u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf;
- u8 lo = 0x01, div4 = 0x0;
-
- /* Reset Tuner */
- ret = m88rs2000_tab_set(state, tuner_reset);
-
- /* Calculate frequency divider */
- if (frequency < 1060000) {
- lo |= 0x10;
- div4 = 0x1;
- ndiv = (frequency * 14 * 4) / FE_CRYSTAL_KHZ;
- } else
- ndiv = (frequency * 14 * 2) / FE_CRYSTAL_KHZ;
- ndiv = ndiv + ndiv % 2;
- ndiv = ndiv - 1024;
-
- ret = m88rs2000_tuner_write(state, 0x10, 0x80 | lo);
-
- /* Set frequency divider */
- ret |= m88rs2000_tuner_write(state, 0x01, (ndiv >> 8) & 0xf);
- ret |= m88rs2000_tuner_write(state, 0x02, ndiv & 0xff);
-
- ret |= m88rs2000_tuner_write(state, 0x03, 0x06);
- ret |= m88rs2000_tuner_gate_ctrl(state, 0x10);
- if (ret < 0)
- return -ENODEV;
-
- /* Tuner Frequency Range */
- ret = m88rs2000_tuner_write(state, 0x10, lo);
-
- ret |= m88rs2000_tuner_gate_ctrl(state, 0x08);
-
- /* Tuner RF */
- ret |= m88rs2000_set_tuner_rf(fe);
-
- gdiv28 = (FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000;
- ret |= m88rs2000_tuner_write(state, 0x04, gdiv28 & 0xff);
- ret |= m88rs2000_tuner_gate_ctrl(state, 0x04);
- if (ret < 0)
- return -ENODEV;
-
- value = m88rs2000_tuner_read(state, 0x26);
-
- f3db = (symbol_rate * 135) / 200 + 2000;
- f3db += FREQ_OFFSET_LOW_SYM_RATE;
- if (f3db < 7000)
- f3db = 7000;
- if (f3db > 40000)
- f3db = 40000;
-
- gdiv28 = gdiv28 * 207 / (value * 2 + 151);
- mlpf_max = gdiv28 * 135 / 100;
- mlpf_min = gdiv28 * 78 / 100;
- if (mlpf_max > 63)
- mlpf_max = 63;
-
- lpf_coeff = 2766;
-
- nlpf = (f3db * gdiv28 * 2 / lpf_coeff /
- (FE_CRYSTAL_KHZ / 1000) + 1) / 2;
- if (nlpf > 23)
- nlpf = 23;
- if (nlpf < 1)
- nlpf = 1;
-
- lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000)
- * lpf_coeff * 2 / f3db + 1) / 2;
-
- if (lpf_mxdiv < mlpf_min) {
- nlpf++;
- lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000)
- * lpf_coeff * 2 / f3db + 1) / 2;
- }
-
- if (lpf_mxdiv > mlpf_max)
- lpf_mxdiv = mlpf_max;
-
- ret = m88rs2000_tuner_write(state, 0x04, lpf_mxdiv);
- ret |= m88rs2000_tuner_write(state, 0x06, nlpf);
-
- ret |= m88rs2000_tuner_gate_ctrl(state, 0x04);
-
- ret |= m88rs2000_tuner_gate_ctrl(state, 0x01);
-
- msleep(80);
- /* calculate offset assuming 96000kHz*/
- offset_khz = (ndiv - ndiv % 2 + 1024) * FE_CRYSTAL_KHZ
- / 14 / (div4 + 1) / 2;
-
- offset_khz -= frequency;
-
- tmp = offset_khz;
- tmp *= 65536;
-
- tmp = (2 * tmp + 96000) / (2 * 96000);
- if (tmp < 0)
- tmp += 65536;
-
- *offset = tmp & 0xffff;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- return (ret < 0) ? -EINVAL : 0;
-}
-
-static int m88rs2000_set_fec(struct m88rs2000_state *state,
- fe_code_rate_t fec)
-{
- int ret;
- u16 fec_set;
- switch (fec) {
- /* This is not confirmed kept for reference */
-/* case FEC_1_2:
- fec_set = 0x88;
- break;
- case FEC_2_3:
- fec_set = 0x68;
- break;
- case FEC_3_4:
- fec_set = 0x48;
- break;
- case FEC_5_6:
- fec_set = 0x28;
- break;
- case FEC_7_8:
- fec_set = 0x18;
- break; */
- case FEC_AUTO:
- default:
- fec_set = 0x08;
- }
- ret = m88rs2000_demod_write(state, 0x76, fec_set);
-
- return 0;
-}
-
-
-static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state)
-{
- u8 reg;
- m88rs2000_demod_write(state, 0x9a, 0x30);
- reg = m88rs2000_demod_read(state, 0x76);
- m88rs2000_demod_write(state, 0x9a, 0xb0);
-
- switch (reg) {
- case 0x88:
- return FEC_1_2;
- case 0x68:
- return FEC_2_3;
- case 0x48:
- return FEC_3_4;
- case 0x28:
- return FEC_5_6;
- case 0x18:
- return FEC_7_8;
- case 0x08:
- default:
- break;
- }
-
- return FEC_AUTO;
-}
-
-static int m88rs2000_set_frontend(struct dvb_frontend *fe)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- fe_status_t status;
- int i, ret;
- u16 offset = 0;
- u8 reg;
-
- state->no_lock_count = 0;
-
- if (c->delivery_system != SYS_DVBS) {
- deb_info("%s: unsupported delivery "
- "system selected (%d)\n",
- __func__, c->delivery_system);
- return -EOPNOTSUPP;
- }
-
- /* Set Tuner */
- ret = m88rs2000_set_tuner(fe, &offset);
- if (ret < 0)
- return -ENODEV;
-
- ret = m88rs2000_demod_write(state, 0x9a, 0x30);
- /* Unknown usually 0xc6 sometimes 0xc1 */
- reg = m88rs2000_demod_read(state, 0x86);
- ret |= m88rs2000_demod_write(state, 0x86, reg);
- /* Offset lower nibble always 0 */
- ret |= m88rs2000_demod_write(state, 0x9c, (offset >> 8));
- ret |= m88rs2000_demod_write(state, 0x9d, offset & 0xf0);
-
-
- /* Reset Demod */
- ret = m88rs2000_tab_set(state, fe_reset);
- if (ret < 0)
- return -ENODEV;
-
- /* Unknown */
- reg = m88rs2000_demod_read(state, 0x70);
- ret = m88rs2000_demod_write(state, 0x70, reg);
-
- /* Set FEC */
- ret |= m88rs2000_set_fec(state, c->fec_inner);
- ret |= m88rs2000_demod_write(state, 0x85, 0x1);
- ret |= m88rs2000_demod_write(state, 0x8a, 0xbf);
- ret |= m88rs2000_demod_write(state, 0x8d, 0x1e);
- ret |= m88rs2000_demod_write(state, 0x90, 0xf1);
- ret |= m88rs2000_demod_write(state, 0x91, 0x08);
-
- if (ret < 0)
- return -ENODEV;
-
- /* Set Symbol Rate */
- ret = m88rs2000_set_symbolrate(fe, c->symbol_rate);
- if (ret < 0)
- return -ENODEV;
-
- /* Set up Demod */
- ret = m88rs2000_tab_set(state, fe_trigger);
- if (ret < 0)
- return -ENODEV;
-
- for (i = 0; i < 25; i++) {
- u8 reg = m88rs2000_demod_read(state, 0x8c);
- if ((reg & 0x7) == 0x7) {
- status = FE_HAS_LOCK;
- break;
- }
- state->no_lock_count++;
- if (state->no_lock_count > 15) {
- reg = m88rs2000_demod_read(state, 0x70);
- reg ^= 0x4;
- m88rs2000_demod_write(state, 0x70, reg);
- state->no_lock_count = 0;
- }
- if (state->no_lock_count == 20)
- m88rs2000_set_tuner_rf(fe);
- msleep(20);
- }
-
- if (status & FE_HAS_LOCK) {
- state->fec_inner = m88rs2000_get_fec(state);
- /* Uknown suspect SNR level */
- reg = m88rs2000_demod_read(state, 0x65);
- }
-
- state->tuner_frequency = c->frequency;
- state->symbol_rate = c->symbol_rate;
- return 0;
-}
-
-static int m88rs2000_get_frontend(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct m88rs2000_state *state = fe->demodulator_priv;
- c->fec_inner = state->fec_inner;
- c->frequency = state->tuner_frequency;
- c->symbol_rate = state->symbol_rate;
- return 0;
-}
-
-static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
-
- if (enable)
- m88rs2000_demod_write(state, 0x81, 0x84);
- else
- m88rs2000_demod_write(state, 0x81, 0x81);
- udelay(10);
- return 0;
-}
-
-static void m88rs2000_release(struct dvb_frontend *fe)
-{
- struct m88rs2000_state *state = fe->demodulator_priv;
- kfree(state);
-}
-
-static struct dvb_frontend_ops m88rs2000_ops = {
- .delsys = { SYS_DVBS },
- .info = {
- .name = "M88RS2000 DVB-S",
- .frequency_min = 950000,
- .frequency_max = 2150000,
- .frequency_stepsize = 1000, /* kHz for QPSK frontends */
- .frequency_tolerance = 5000,
- .symbol_rate_min = 1000000,
- .symbol_rate_max = 45000000,
- .symbol_rate_tolerance = 500, /* ppm */
- .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
- FE_CAN_QPSK |
- FE_CAN_FEC_AUTO
- },
-
- .release = m88rs2000_release,
- .init = m88rs2000_init,
- .sleep = m88rs2000_sleep,
- .write = m88rs2000_write,
- .i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl,
- .read_status = m88rs2000_read_status,
- .read_ber = m88rs2000_read_ber,
- .read_signal_strength = m88rs2000_read_signal_strength,
- .read_snr = m88rs2000_read_snr,
- .read_ucblocks = m88rs2000_read_ucblocks,
- .diseqc_send_master_cmd = m88rs2000_send_diseqc_msg,
- .diseqc_send_burst = m88rs2000_send_diseqc_burst,
- .set_tone = m88rs2000_set_tone,
- .set_voltage = m88rs2000_set_voltage,
-
- .set_frontend = m88rs2000_set_frontend,
- .get_frontend = m88rs2000_get_frontend,
-};
-
-struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config,
- struct i2c_adapter *i2c)
-{
- struct m88rs2000_state *state = NULL;
-
- /* allocate memory for the internal state */
- state = kzalloc(sizeof(struct m88rs2000_state), GFP_KERNEL);
- if (state == NULL)
- goto error;
-
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- state->tuner_frequency = 0;
- state->symbol_rate = 0;
- state->fec_inner = 0;
-
- if (m88rs2000_startup(state) < 0)
- goto error;
-
- /* create dvb_frontend */
- memcpy(&state->frontend.ops, &m88rs2000_ops,
- sizeof(struct dvb_frontend_ops));
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
- kfree(state);
-
- return NULL;
-}
-EXPORT_SYMBOL(m88rs2000_attach);
-
-MODULE_DESCRIPTION("M88RS2000 DVB-S Demodulator driver");
-MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.13");
-
diff --git a/trunk/drivers/media/dvb/frontends/m88rs2000.h b/trunk/drivers/media/dvb/frontends/m88rs2000.h
deleted file mode 100644
index 59acdb696873..000000000000
--- a/trunk/drivers/media/dvb/frontends/m88rs2000.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- Driver for M88RS2000 demodulator
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef M88RS2000_H
-#define M88RS2000_H
-
-#include
-#include "dvb_frontend.h"
-
-struct m88rs2000_config {
- /* Demodulator i2c address */
- u8 demod_addr;
- /* Tuner address */
- u8 tuner_addr;
-
- u8 *inittab;
-
- /* minimum delay before retuning */
- int min_delay_ms;
-
- int (*set_ts_params)(struct dvb_frontend *, int);
-};
-
-enum {
- CALL_IS_SET_FRONTEND = 0x0,
- CALL_IS_READ,
-};
-
-#if defined(CONFIG_DVB_M88RS2000) || (defined(CONFIG_DVB_M88RS2000_MODULE) && \
- defined(MODULE))
-extern struct dvb_frontend *m88rs2000_attach(
- const struct m88rs2000_config *config, struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *m88rs2000_attach(
- const struct m88rs2000_config *config, struct i2c_adapter *i2c)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-#endif /* CONFIG_DVB_M88RS2000 */
-
-#define FE_CRYSTAL_KHZ 27000
-#define FREQ_OFFSET_LOW_SYM_RATE 3000
-
-enum {
- DEMOD_WRITE = 0x1,
- TUNER_WRITE,
- WRITE_DELAY = 0x10,
-};
-#endif /* M88RS2000_H */
diff --git a/trunk/drivers/media/dvb/frontends/rtl2830.c b/trunk/drivers/media/dvb/frontends/rtl2830.c
deleted file mode 100644
index 45196c5b0736..000000000000
--- a/trunk/drivers/media/dvb/frontends/rtl2830.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Realtek RTL2830 DVB-T demodulator driver
- *
- * Copyright (C) 2011 Antti Palosaari
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-/*
- * Driver implements own I2C-adapter for tuner I2C access. That's since chip
- * have unusual I2C-gate control which closes gate automatically after each
- * I2C transfer. Using own I2C adapter we can workaround that.
- */
-
-#include "rtl2830_priv.h"
-
-int rtl2830_debug;
-module_param_named(debug, rtl2830_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-/* write multiple hardware registers */
-static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
-{
- int ret;
- u8 buf[1+len];
- struct i2c_msg msg[1] = {
- {
- .addr = priv->cfg.i2c_addr,
- .flags = 0,
- .len = 1+len,
- .buf = buf,
- }
- };
-
- buf[0] = reg;
- memcpy(&buf[1], val, len);
-
- ret = i2c_transfer(priv->i2c, msg, 1);
- if (ret == 1) {
- ret = 0;
- } else {
- warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
- ret = -EREMOTEIO;
- }
- return ret;
-}
-
-/* read multiple hardware registers */
-static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
-{
- int ret;
- struct i2c_msg msg[2] = {
- {
- .addr = priv->cfg.i2c_addr,
- .flags = 0,
- .len = 1,
- .buf = ®,
- }, {
- .addr = priv->cfg.i2c_addr,
- .flags = I2C_M_RD,
- .len = len,
- .buf = val,
- }
- };
-
- ret = i2c_transfer(priv->i2c, msg, 2);
- if (ret == 2) {
- ret = 0;
- } else {
- warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
- ret = -EREMOTEIO;
- }
- return ret;
-}
-
-/* write multiple registers */
-static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
-{
- int ret;
- u8 reg2 = (reg >> 0) & 0xff;
- u8 page = (reg >> 8) & 0xff;
-
- /* switch bank if needed */
- if (page != priv->page) {
- ret = rtl2830_wr(priv, 0x00, &page, 1);
- if (ret)
- return ret;
-
- priv->page = page;
- }
-
- return rtl2830_wr(priv, reg2, val, len);
-}
-
-/* read multiple registers */
-static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
-{
- int ret;
- u8 reg2 = (reg >> 0) & 0xff;
- u8 page = (reg >> 8) & 0xff;
-
- /* switch bank if needed */
- if (page != priv->page) {
- ret = rtl2830_wr(priv, 0x00, &page, 1);
- if (ret)
- return ret;
-
- priv->page = page;
- }
-
- return rtl2830_rd(priv, reg2, val, len);
-}
-
-#if 0 /* currently not used */
-/* write single register */
-static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val)
-{
- return rtl2830_wr_regs(priv, reg, &val, 1);
-}
-#endif
-
-/* read single register */
-static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
-{
- return rtl2830_rd_regs(priv, reg, val, 1);
-}
-
-/* write single register with mask */
-int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
-{
- int ret;
- u8 tmp;
-
- /* no need for read if whole reg is written */
- if (mask != 0xff) {
- ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
- if (ret)
- return ret;
-
- val &= mask;
- tmp &= ~mask;
- val |= tmp;
- }
-
- return rtl2830_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register with mask */
-int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
-{
- int ret, i;
- u8 tmp;
-
- ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
- if (ret)
- return ret;
-
- tmp &= mask;
-
- /* find position of the first bit */
- for (i = 0; i < 8; i++) {
- if ((mask >> i) & 0x01)
- break;
- }
- *val = tmp >> i;
-
- return 0;
-}
-
-static int rtl2830_init(struct dvb_frontend *fe)
-{
- struct rtl2830_priv *priv = fe->demodulator_priv;
- int ret, i;
- u64 num;
- u8 buf[3], tmp;
- u32 if_ctl;
- struct rtl2830_reg_val_mask tab[] = {
- { 0x00d, 0x01, 0x03 },
- { 0x00d, 0x10, 0x10 },
- { 0x104, 0x00, 0x1e },
- { 0x105, 0x80, 0x80 },
- { 0x110, 0x02, 0x03 },
- { 0x110, 0x08, 0x0c },
- { 0x17b, 0x00, 0x40 },
- { 0x17d, 0x05, 0x0f },
- { 0x17d, 0x50, 0xf0 },
- { 0x18c, 0x08, 0x0f },
- { 0x18d, 0x00, 0xc0 },
- { 0x188, 0x05, 0x0f },
- { 0x189, 0x00, 0xfc },
- { 0x2d5, 0x02, 0x02 },
- { 0x2f1, 0x02, 0x06 },
- { 0x2f1, 0x20, 0xf8 },
- { 0x16d, 0x00, 0x01 },
- { 0x1a6, 0x00, 0x80 },
- { 0x106, priv->cfg.vtop, 0x3f },
- { 0x107, priv->cfg.krf, 0x3f },
- { 0x112, 0x28, 0xff },
- { 0x103, priv->cfg.agc_targ_val, 0xff },
- { 0x00a, 0x02, 0x07 },
- { 0x140, 0x0c, 0x3c },
- { 0x140, 0x40, 0xc0 },
- { 0x15b, 0x05, 0x07 },
- { 0x15b, 0x28, 0x38 },
- { 0x15c, 0x05, 0x07 },
- { 0x15c, 0x28, 0x38 },
- { 0x115, priv->cfg.spec_inv, 0x01 },
- { 0x16f, 0x01, 0x07 },
- { 0x170, 0x18, 0x38 },
- { 0x172, 0x0f, 0x0f },
- { 0x173, 0x08, 0x38 },
- { 0x175, 0x01, 0x07 },
- { 0x176, 0x00, 0xc0 },
- };
-
- for (i = 0; i < ARRAY_SIZE(tab); i++) {
- ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val,
- tab[i].mask);
- if (ret)
- goto err;
- }
-
- ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2);
- if (ret)
- goto err;
-
- ret = rtl2830_wr_regs(priv, 0x195,
- "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
- if (ret)
- goto err;
-
- num = priv->cfg.if_dvbt % priv->cfg.xtal;
- num *= 0x400000;
- num = div_u64(num, priv->cfg.xtal);
- num = -num;
- if_ctl = num & 0x3fffff;
- dbg("%s: if_ctl=%08x", __func__, if_ctl);
-
- ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
- if (ret)
- goto err;
-
- buf[0] = tmp << 6;
- buf[0] = (if_ctl >> 16) & 0x3f;
- buf[1] = (if_ctl >> 8) & 0xff;
- buf[2] = (if_ctl >> 0) & 0xff;
-
- ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
- if (ret)
- goto err;
-
- /* TODO: spec init */
-
- /* soft reset */
- ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04);
- if (ret)
- goto err;
-
- ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04);
- if (ret)
- goto err;
-
- priv->sleeping = false;
-
- return ret;
-err:
- dbg("%s: failed=%d", __func__, ret);
- return ret;
-}
-
-static int rtl2830_sleep(struct dvb_frontend *fe)
-{
- struct rtl2830_priv *priv = fe->demodulator_priv;
- priv->sleeping = true;
- return 0;
-}
-
-int rtl2830_get_tune_settings(struct dvb_frontend *fe,
- struct dvb_frontend_tune_settings *s)
-{
- s->min_delay_ms = 500;
- s->step_size = fe->ops.info.frequency_stepsize * 2;
- s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
-
- return 0;
-}
-
-static int rtl2830_set_frontend(struct dvb_frontend *fe)
-{
- struct rtl2830_priv *priv = fe->demodulator_priv;
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- int ret, i;
- static u8 bw_params1[3][34] = {
- {
- 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
- 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
- 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
- 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
- }, {
- 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
- 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
- 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
- 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
- }, {
- 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
- 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
- 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
- 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
- },
- };
- static u8 bw_params2[3][6] = {
- {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */
- {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */
- {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */
- };
-
-
- dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__,
- c->frequency, c->bandwidth_hz, c->inversion);
-
- /* program tuner */
- if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe);
-
- switch (c->bandwidth_hz) {
- case 6000000:
- i = 0;
- break;
- case 7000000:
- i = 1;
- break;
- case 8000000:
- i = 2;
- break;
- default:
- dbg("invalid bandwidth");
- return -EINVAL;
- }
-
- ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06);
- if (ret)
- goto err;
-
- /* 1/2 split I2C write */
- ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17);
- if (ret)
- goto err;
-
- /* 2/2 split I2C write */
- ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17);
- if (ret)
- goto err;
-
- ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6);
- if (ret)
- goto err;
-
- return ret;
-err:
- dbg("%s: failed=%d", __func__, ret);
- return ret;
-}
-
-static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
- struct rtl2830_priv *priv = fe->demodulator_priv;
- int ret;
- u8 tmp;
- *status = 0;
-
- if (priv->sleeping)
- return 0;
-
- ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */
- if (ret)
- goto err;
-
- if (tmp == 11) {
- *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
- FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
- } else if (tmp == 10) {
- *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
- FE_HAS_VITERBI;
- }
-
- return ret;
-err:
- dbg("%s: failed=%d", __func__, ret);
- return ret;
-}
-
-static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
- *snr = 0;
- return 0;
-}
-
-static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
- *ber = 0;
- return 0;
-}
-
-static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
- *ucblocks = 0;
- return 0;
-}
-
-static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
- *strength = 0;
- return 0;
-}
-
-static struct dvb_frontend_ops rtl2830_ops;
-
-static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter)
-{
- return I2C_FUNC_I2C;
-}
-
-static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg msg[], int num)
-{
- struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap);
- int ret;
-
- /* open i2c-gate */
- ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08);
- if (ret)
- goto err;
-
- ret = i2c_transfer(priv->i2c, msg, num);
- if (ret < 0)
- warn("tuner i2c failed=%d", ret);
-
- return ret;
-err:
- dbg("%s: failed=%d", __func__, ret);
- return ret;
-}
-
-static struct i2c_algorithm rtl2830_tuner_i2c_algo = {
- .master_xfer = rtl2830_tuner_i2c_xfer,
- .functionality = rtl2830_tuner_i2c_func,
-};
-
-struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe)
-{
- struct rtl2830_priv *priv = fe->demodulator_priv;
- return &priv->tuner_i2c_adapter;
-}
-EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter);
-
-static void rtl2830_release(struct dvb_frontend *fe)
-{
- struct rtl2830_priv *priv = fe->demodulator_priv;
-
- i2c_del_adapter(&priv->tuner_i2c_adapter);
- kfree(priv);
-}
-
-struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
- struct i2c_adapter *i2c)
-{
- struct rtl2830_priv *priv = NULL;
- int ret = 0;
- u8 tmp;
-
- /* allocate memory for the internal state */
- priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL);
- if (priv == NULL)
- goto err;
-
- /* setup the priv */
- priv->i2c = i2c;
- memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config));
-
- /* check if the demod is there */
- ret = rtl2830_rd_reg(priv, 0x000, &tmp);
- if (ret)
- goto err;
-
- /* create dvb_frontend */
- memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops));
- priv->fe.demodulator_priv = priv;
-
- /* create tuner i2c adapter */
- strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter",
- sizeof(priv->tuner_i2c_adapter.name));
- priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
- priv->tuner_i2c_adapter.algo_data = NULL;
- i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
- if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
- err("tuner I2C bus could not be initialized");
- goto err;
- }
-
- priv->sleeping = true;
-
- return &priv->fe;
-err:
- dbg("%s: failed=%d", __func__, ret);
- kfree(priv);
- return NULL;
-}
-EXPORT_SYMBOL(rtl2830_attach);
-
-static struct dvb_frontend_ops rtl2830_ops = {
- .delsys = { SYS_DVBT },
- .info = {
- .name = "Realtek RTL2830 (DVB-T)",
- .caps = FE_CAN_FEC_1_2 |
- FE_CAN_FEC_2_3 |
- FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 |
- FE_CAN_FEC_7_8 |
- FE_CAN_FEC_AUTO |
- FE_CAN_QPSK |
- FE_CAN_QAM_16 |
- FE_CAN_QAM_64 |
- FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO |
- FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO |
- FE_CAN_RECOVER |
- FE_CAN_MUTE_TS
- },
-
- .release = rtl2830_release,
-
- .init = rtl2830_init,
- .sleep = rtl2830_sleep,
-
- .get_tune_settings = rtl2830_get_tune_settings,
-
- .set_frontend = rtl2830_set_frontend,
-
- .read_status = rtl2830_read_status,
- .read_snr = rtl2830_read_snr,
- .read_ber = rtl2830_read_ber,
- .read_ucblocks = rtl2830_read_ucblocks,
- .read_signal_strength = rtl2830_read_signal_strength,
-};
-
-MODULE_AUTHOR("Antti Palosaari ");
-MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/media/dvb/frontends/rtl2830.h b/trunk/drivers/media/dvb/frontends/rtl2830.h
deleted file mode 100644
index 1c6ee91749c2..000000000000
--- a/trunk/drivers/media/dvb/frontends/rtl2830.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Realtek RTL2830 DVB-T demodulator driver
- *
- * Copyright (C) 2011 Antti Palosaari
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef RTL2830_H
-#define RTL2830_H
-
-#include
-
-struct rtl2830_config {
- /*
- * Demodulator I2C address.
- */
- u8 i2c_addr;
-
- /*
- * Xtal frequency.
- * Hz
- * 4000000, 16000000, 25000000, 28800000
- */
- u32 xtal;
-
- /*
- * TS output mode.
- */
- u8 ts_mode;
-
- /*
- * Spectrum inversion.
- */
- bool spec_inv;
-
- /*
- * IFs for all used modes.
- * Hz
- * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000
- */
- u32 if_dvbt;
-
- /*
- */
- u8 vtop;
-
- /*
- */
- u8 krf;
-
- /*
- */
- u8 agc_targ_val;
-};
-
-#if defined(CONFIG_DVB_RTL2830) || \
- (defined(CONFIG_DVB_RTL2830_MODULE) && defined(MODULE))
-extern struct dvb_frontend *rtl2830_attach(
- const struct rtl2830_config *config,
- struct i2c_adapter *i2c
-);
-
-extern struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(
- struct dvb_frontend *fe
-);
-#else
-static inline struct dvb_frontend *rtl2830_attach(
- const struct rtl2830_config *config,
- struct i2c_adapter *i2c
-)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-
-static inline struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(
- struct dvb_frontend *fe
-)
-{
- return NULL;
-}
-#endif
-
-#endif /* RTL2830_H */
diff --git a/trunk/drivers/media/dvb/frontends/rtl2830_priv.h b/trunk/drivers/media/dvb/frontends/rtl2830_priv.h
deleted file mode 100644
index 4a464761b5b8..000000000000
--- a/trunk/drivers/media/dvb/frontends/rtl2830_priv.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Realtek RTL2830 DVB-T demodulator driver
- *
- * Copyright (C) 2011 Antti Palosaari
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef RTL2830_PRIV_H
-#define RTL2830_PRIV_H
-
-#include "dvb_frontend.h"
-#include "rtl2830.h"
-
-#define LOG_PREFIX "rtl2830"
-
-#undef dbg
-#define dbg(f, arg...) \
- if (rtl2830_debug) \
- printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-struct rtl2830_priv {
- struct i2c_adapter *i2c;
- struct dvb_frontend fe;
- struct rtl2830_config cfg;
- struct i2c_adapter tuner_i2c_adapter;
-
- bool sleeping;
-
- u8 page; /* active register page */
-};
-
-struct rtl2830_reg_val_mask {
- u16 reg;
- u8 val;
- u8 mask;
-};
-
-#endif /* RTL2830_PRIV_H */
diff --git a/trunk/drivers/media/dvb/frontends/stb0899_drv.c b/trunk/drivers/media/dvb/frontends/stb0899_drv.c
index dd08f4ac64a8..38565beafe23 100644
--- a/trunk/drivers/media/dvb/frontends/stb0899_drv.c
+++ b/trunk/drivers/media/dvb/frontends/stb0899_drv.c
@@ -67,7 +67,7 @@ static const struct stb0899_tab stb0899_cn_tab[] = {
* Crude linear extrapolation below -84.8dBm and above -8.0dBm.
*/
static const struct stb0899_tab stb0899_dvbsrf_tab[] = {
- { -750, -128 },
+ { -950, -128 },
{ -748, -94 },
{ -745, -92 },
{ -735, -90 },
@@ -131,7 +131,7 @@ static const struct stb0899_tab stb0899_dvbs2rf_tab[] = {
{ -730, 13645 },
{ -750, 13909 },
{ -766, 14153 },
- { -950, 16383 }
+ { -999, 16383 }
};
/* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/
@@ -964,7 +964,6 @@ static int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
int val;
u32 reg;
- *strength = 0;
switch (state->delsys) {
case SYS_DVBS:
case SYS_DSS:
@@ -984,11 +983,11 @@ static int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
break;
case SYS_DVBS2:
if (internal->lock) {
- reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_GAIN);
+ reg = STB0899_READ_S2REG(STB0899_DEMOD, IF_AGC_GAIN);
val = STB0899_GETFIELD(IF_AGC_GAIN, reg);
*strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val);
- *strength += 950;
+ *strength += 750;
dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm",
val & 0x3fff, *strength);
}
@@ -1010,7 +1009,6 @@ static int stb0899_read_snr(struct dvb_frontend *fe, u16 *snr)
u8 buf[2];
u32 reg;
- *snr = 0;
reg = stb0899_read_reg(state, STB0899_VSTATUS);
switch (state->delsys) {
case SYS_DVBS:
@@ -1073,7 +1071,7 @@ static int stb0899_read_status(struct dvb_frontend *fe, enum fe_status *status)
reg = stb0899_read_reg(state, STB0899_VSTATUS);
if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK");
- *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
+ *status |= FE_HAS_CARRIER | FE_HAS_LOCK;
reg = stb0899_read_reg(state, STB0899_PLPARM);
if (STB0899_GETFIELD(VITCURPUN, reg)) {
diff --git a/trunk/drivers/media/dvb/frontends/stv0288.c b/trunk/drivers/media/dvb/frontends/stv0288.c
index 632b25156e4c..fb5548a82208 100644
--- a/trunk/drivers/media/dvb/frontends/stv0288.c
+++ b/trunk/drivers/media/dvb/frontends/stv0288.c
@@ -506,7 +506,7 @@ static int stv0288_set_frontend(struct dvb_frontend *fe)
tda[1] = (unsigned char)tm;
stv0288_writeregI(state, 0x2b, tda[1]);
stv0288_writeregI(state, 0x2c, tda[2]);
- msleep(30);
+ udelay(30);
}
state->tuner_frequency = c->frequency;
state->fec_inner = FEC_AUTO;
diff --git a/trunk/drivers/media/dvb/frontends/tda10071.c b/trunk/drivers/media/dvb/frontends/tda10071.c
index c21bc92d2811..a99205026751 100644
--- a/trunk/drivers/media/dvb/frontends/tda10071.c
+++ b/trunk/drivers/media/dvb/frontends/tda10071.c
@@ -1215,7 +1215,7 @@ struct dvb_frontend *tda10071_attach(const struct tda10071_config *config,
EXPORT_SYMBOL(tda10071_attach);
static struct dvb_frontend_ops tda10071_ops = {
- .delsys = { SYS_DVBS, SYS_DVBS2 },
+ .delsys = { SYS_DVBT, SYS_DVBT2 },
.info = {
.name = "NXP TDA10071",
.frequency_min = 950000,
diff --git a/trunk/drivers/media/dvb/ngene/ngene-cards.c b/trunk/drivers/media/dvb/ngene/ngene-cards.c
index 7539a5d71029..8418c02bcefe 100644
--- a/trunk/drivers/media/dvb/ngene/ngene-cards.c
+++ b/trunk/drivers/media/dvb/ngene/ngene-cards.c
@@ -216,7 +216,6 @@ static int demod_attach_drxk(struct ngene_channel *chan,
struct drxk_config config;
memset(&config, 0, sizeof(config));
- config.microcode_name = "drxk_a3.mc";
config.adr = 0x29 + (chan->number ^ 2);
chan->fe = dvb_attach(drxk_attach, &config, i2c);
diff --git a/trunk/drivers/media/dvb/pt1/pt1.c b/trunk/drivers/media/dvb/pt1/pt1.c
index 15b35c4725f1..b81df5fafe26 100644
--- a/trunk/drivers/media/dvb/pt1/pt1.c
+++ b/trunk/drivers/media/dvb/pt1/pt1.c
@@ -28,7 +28,6 @@
#include
#include
#include
-#include
#include "dvbdev.h"
#include "dvb_demux.h"
@@ -78,8 +77,6 @@ struct pt1 {
struct pt1_adapter *adaps[PT1_NR_ADAPS];
struct pt1_table *tables;
struct task_struct *kthread;
- int table_index;
- int buf_index;
struct mutex lock;
int power;
@@ -93,12 +90,12 @@ struct pt1_adapter {
u8 *buf;
int upacket_count;
int packet_count;
- int st_count;
struct dvb_adapter adap;
struct dvb_demux demux;
int users;
struct dmxdev dmxdev;
+ struct dvb_net net;
struct dvb_frontend *fe;
int (*orig_set_voltage)(struct dvb_frontend *fe,
fe_sec_voltage_t voltage);
@@ -122,7 +119,7 @@ static u32 pt1_read_reg(struct pt1 *pt1, int reg)
return readl(pt1->regs + reg * 4);
}
-static int pt1_nr_tables = 8;
+static int pt1_nr_tables = 64;
module_param_named(nr_tables, pt1_nr_tables, int, 0);
static void pt1_increment_table_count(struct pt1 *pt1)
@@ -267,7 +264,6 @@ static int pt1_filter(struct pt1 *pt1, struct pt1_buffer_page *page)
struct pt1_adapter *adap;
int offset;
u8 *buf;
- int sc;
if (!page->upackets[PT1_NR_UPACKETS - 1])
return 0;
@@ -284,16 +280,6 @@ static int pt1_filter(struct pt1 *pt1, struct pt1_buffer_page *page)
else if (!adap->upacket_count)
continue;
- if (upacket >> 24 & 1)
- printk_ratelimited(KERN_INFO "earth-pt1: device "
- "buffer overflowing. table[%d] buf[%d]\n",
- pt1->table_index, pt1->buf_index);
- sc = upacket >> 26 & 0x7;
- if (adap->st_count != -1 && sc != ((adap->st_count + 1) & 0x7))
- printk_ratelimited(KERN_INFO "earth-pt1: data loss"
- " in streamID(adapter)[%d]\n", index);
- adap->st_count = sc;
-
buf = adap->buf;
offset = adap->packet_count * 188 + adap->upacket_count * 3;
buf[offset] = upacket >> 16;
@@ -317,25 +303,30 @@ static int pt1_filter(struct pt1 *pt1, struct pt1_buffer_page *page)
static int pt1_thread(void *data)
{
struct pt1 *pt1;
+ int table_index;
+ int buf_index;
struct pt1_buffer_page *page;
pt1 = data;
set_freezable();
+ table_index = 0;
+ buf_index = 0;
+
while (!kthread_should_stop()) {
try_to_freeze();
- page = pt1->tables[pt1->table_index].bufs[pt1->buf_index].page;
+ page = pt1->tables[table_index].bufs[buf_index].page;
if (!pt1_filter(pt1, page)) {
schedule_timeout_interruptible((HZ + 999) / 1000);
continue;
}
- if (++pt1->buf_index >= PT1_NR_BUFS) {
+ if (++buf_index >= PT1_NR_BUFS) {
pt1_increment_table_count(pt1);
- pt1->buf_index = 0;
- if (++pt1->table_index >= pt1_nr_tables)
- pt1->table_index = 0;
+ buf_index = 0;
+ if (++table_index >= pt1_nr_tables)
+ table_index = 0;
}
}
@@ -486,60 +477,21 @@ static int pt1_init_tables(struct pt1 *pt1)
return ret;
}
-static int pt1_start_polling(struct pt1 *pt1)
-{
- int ret = 0;
-
- mutex_lock(&pt1->lock);
- if (!pt1->kthread) {
- pt1->kthread = kthread_run(pt1_thread, pt1, "earth-pt1");
- if (IS_ERR(pt1->kthread)) {
- ret = PTR_ERR(pt1->kthread);
- pt1->kthread = NULL;
- }
- }
- mutex_unlock(&pt1->lock);
- return ret;
-}
-
static int pt1_start_feed(struct dvb_demux_feed *feed)
{
struct pt1_adapter *adap;
adap = container_of(feed->demux, struct pt1_adapter, demux);
- if (!adap->users++) {
- int ret;
-
- ret = pt1_start_polling(adap->pt1);
- if (ret)
- return ret;
+ if (!adap->users++)
pt1_set_stream(adap->pt1, adap->index, 1);
- }
return 0;
}
-static void pt1_stop_polling(struct pt1 *pt1)
-{
- int i, count;
-
- mutex_lock(&pt1->lock);
- for (i = 0, count = 0; i < PT1_NR_ADAPS; i++)
- count += pt1->adaps[i]->users;
-
- if (count == 0 && pt1->kthread) {
- kthread_stop(pt1->kthread);
- pt1->kthread = NULL;
- }
- mutex_unlock(&pt1->lock);
-}
-
static int pt1_stop_feed(struct dvb_demux_feed *feed)
{
struct pt1_adapter *adap;
adap = container_of(feed->demux, struct pt1_adapter, demux);
- if (!--adap->users) {
+ if (!--adap->users)
pt1_set_stream(adap->pt1, adap->index, 0);
- pt1_stop_polling(adap->pt1);
- }
return 0;
}
@@ -623,6 +575,7 @@ static int pt1_wakeup(struct dvb_frontend *fe)
static void pt1_free_adapter(struct pt1_adapter *adap)
{
+ dvb_net_release(&adap->net);
adap->demux.dmx.close(&adap->demux.dmx);
dvb_dmxdev_release(&adap->dmxdev);
dvb_dmx_release(&adap->demux);
@@ -663,7 +616,6 @@ pt1_alloc_adapter(struct pt1 *pt1)
adap->buf = buf;
adap->upacket_count = 0;
adap->packet_count = 0;
- adap->st_count = -1;
dvb_adap = &adap->adap;
dvb_adap->priv = adap;
@@ -692,6 +644,8 @@ pt1_alloc_adapter(struct pt1 *pt1)
if (ret < 0)
goto err_dmx_release;
+ dvb_net_init(dvb_adap, &adap->net, &demux->dmx);
+
return adap;
err_dmx_release:
@@ -1066,8 +1020,7 @@ static void __devexit pt1_remove(struct pci_dev *pdev)
pt1 = pci_get_drvdata(pdev);
regs = pt1->regs;
- if (pt1->kthread)
- kthread_stop(pt1->kthread);
+ kthread_stop(pt1->kthread);
pt1_cleanup_tables(pt1);
pt1_cleanup_frontends(pt1);
pt1_disable_ram(pt1);
@@ -1090,6 +1043,7 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
void __iomem *regs;
struct pt1 *pt1;
struct i2c_adapter *i2c_adap;
+ struct task_struct *kthread;
ret = pci_enable_device(pdev);
if (ret < 0)
@@ -1185,8 +1139,17 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret < 0)
goto err_pt1_cleanup_frontends;
+ kthread = kthread_run(pt1_thread, pt1, "pt1");
+ if (IS_ERR(kthread)) {
+ ret = PTR_ERR(kthread);
+ goto err_pt1_cleanup_tables;
+ }
+
+ pt1->kthread = kthread;
return 0;
+err_pt1_cleanup_tables:
+ pt1_cleanup_tables(pt1);
err_pt1_cleanup_frontends:
pt1_cleanup_frontends(pt1);
err_pt1_disable_ram:
diff --git a/trunk/drivers/media/media-devnode.c b/trunk/drivers/media/media-devnode.c
index 421cf73858d3..7b42ace419d9 100644
--- a/trunk/drivers/media/media-devnode.c
+++ b/trunk/drivers/media/media-devnode.c
@@ -312,7 +312,7 @@ static void __exit media_devnode_exit(void)
unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
}
-subsys_initcall(media_devnode_init);
+module_init(media_devnode_init)
module_exit(media_devnode_exit)
MODULE_AUTHOR("Laurent Pinchart ");
diff --git a/trunk/drivers/media/radio/Kconfig b/trunk/drivers/media/radio/Kconfig
index 8db2d7f4b52a..e954781c90bf 100644
--- a/trunk/drivers/media/radio/Kconfig
+++ b/trunk/drivers/media/radio/Kconfig
@@ -43,7 +43,7 @@ config USB_DSBR
config RADIO_MAXIRADIO
tristate "Guillemot MAXI Radio FM 2000 radio"
- depends on VIDEO_V4L2 && PCI && SND
+ depends on VIDEO_V4L2 && PCI
---help---
Choose Y here if you have this radio card. This card may also be
found as Gemtek PCI FM.
@@ -80,16 +80,6 @@ config RADIO_SI4713
To compile this driver as a module, choose M here: the
module will be called radio-si4713.
-config USB_KEENE
- tristate "Keene FM Transmitter USB support"
- depends on USB && VIDEO_V4L2
- ---help---
- Say Y here if you want to connect this type of FM transmitter
- to your computer's USB port.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-keene.
-
config RADIO_TEA5764
tristate "TEA5764 I2C FM radio support"
depends on I2C && VIDEO_V4L2
@@ -177,10 +167,6 @@ menuconfig V4L_RADIO_ISA_DRIVERS
if V4L_RADIO_ISA_DRIVERS
-config RADIO_ISA
- depends on ISA
- tristate
-
config RADIO_CADET
tristate "ADS Cadet AM/FM Tuner"
depends on ISA && VIDEO_V4L2
@@ -188,13 +174,20 @@ config RADIO_CADET
Choose Y here if you have one of these AM/FM radio cards, and then
fill in the port address below.
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ .
+
+ Further documentation on this driver can be found on the WWW at
+ .
+
To compile this driver as a module, choose M here: the
module will be called radio-cadet.
config RADIO_RTRACK
tristate "AIMSlab RadioTrack (aka RadioReveal) support"
depends on ISA && VIDEO_V4L2
- select RADIO_ISA
---help---
Choose Y here if you have one of these FM radio cards, and then fill
in the port address below.
@@ -208,7 +201,11 @@ config RADIO_RTRACK
You must also pass the module a suitable io parameter, 0x248 has
been reported to be used by these cards.
- More information is contained in the file
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ . More information is
+ contained in the file
.
To compile this driver as a module, choose M here: the
@@ -217,7 +214,7 @@ config RADIO_RTRACK
config RADIO_RTRACK_PORT
hex "RadioTrack i/o port (0x20f or 0x30f)"
depends on RADIO_RTRACK=y
- default "30f"
+ default "20f"
help
Enter either 0x30f or 0x20f here. The card default is 0x30f, if you
haven't changed the jumper setting on the card.
@@ -225,14 +222,14 @@ config RADIO_RTRACK_PORT
config RADIO_RTRACK2
tristate "AIMSlab RadioTrack II support"
depends on ISA && VIDEO_V4L2
- select RADIO_ISA
---help---
Choose Y here if you have this FM radio card, and then fill in the
port address below.
- Note: this driver hasn't been tested since a long time due to lack
- of hardware. If you have this hardware, then please contact the
- linux-media mailinglist.
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ .
To compile this driver as a module, choose M here: the
module will be called radio-rtrack2.
@@ -248,11 +245,15 @@ config RADIO_RTRACK2_PORT
config RADIO_AZTECH
tristate "Aztech/Packard Bell Radio"
depends on ISA && VIDEO_V4L2
- select RADIO_ISA
---help---
Choose Y here if you have one of these FM radio cards, and then fill
in the port address below.
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ .
+
To compile this driver as a module, choose M here: the
module will be called radio-aztech.
@@ -268,7 +269,6 @@ config RADIO_AZTECH_PORT
config RADIO_GEMTEK
tristate "GemTek Radio card (or compatible) support"
depends on ISA && VIDEO_V4L2
- select RADIO_ISA
---help---
Choose Y here if you have this FM radio card, and then fill in the
I/O port address and settings below. The following cards either have
@@ -278,21 +278,23 @@ config RADIO_GEMTEK
- Typhoon Radio card (some models)
- Hama Radio card
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ .
+
To compile this driver as a module, choose M here: the
module will be called radio-gemtek.
config RADIO_GEMTEK_PORT
- hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c)"
+ hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0c24c or 0x28c)"
depends on RADIO_GEMTEK=y
default "34c"
help
- Enter either 0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c here. The
- card default is 0x34c, if you haven't changed the jumper setting
- on the card.
-
- On Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O
+ Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is
+ 0x34c, if you haven't changed the jumper setting on the card. On
+ Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O
port is 0x20c, 0x248 or 0x28c.
-
If automatic I/O port probing is enabled this port will be used only
in case of automatic probing failure, ie. as a fallback.
@@ -316,6 +318,11 @@ config RADIO_MIROPCM20
sound card driver "Miro miroSOUND PCM1pro/PCM12/PCM20radio" as this
is required for the radio-miropcm20.
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ .
+
To compile this driver as a module, choose M here: the
module will be called radio-miropcm20.
@@ -325,6 +332,11 @@ config RADIO_SF16FMI
---help---
Choose Y here if you have one of these FM radio cards.
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ .
+
To compile this driver as a module, choose M here: the
module will be called radio-sf16fmi.
@@ -334,35 +346,50 @@ config RADIO_SF16FMR2
---help---
Choose Y here if you have one of these FM radio cards.
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found on the WWW at
+ .
+
To compile this driver as a module, choose M here: the
module will be called radio-sf16fmr2.
config RADIO_TERRATEC
tristate "TerraTec ActiveRadio ISA Standalone"
depends on ISA && VIDEO_V4L2
- select RADIO_ISA
---help---
- Choose Y here if you have this FM radio card.
+ Choose Y here if you have this FM radio card, and then fill in the
+ port address below. (TODO)
- Note: this driver hasn't been tested since a long time due to lack
- of hardware. If you have this hardware, then please contact the
- linux-media mailinglist.
+ Note: This driver is in its early stages. Right now volume and
+ frequency control and muting works at least for me, but
+ unfortunately I have not found anybody who wants to use this card
+ with Linux. So if it is this what YOU are trying to do right now,
+ PLEASE DROP ME A NOTE!! Rolf Offermanns .
+
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ .
To compile this driver as a module, choose M here: the
module will be called radio-terratec.
+config RADIO_TERRATEC_PORT
+ hex "Terratec i/o port (normally 0x590)"
+ depends on RADIO_TERRATEC=y
+ default "590"
+ help
+ Fill in the I/O port of your TerraTec FM radio card. If unsure, go
+ with the default.
+
config RADIO_TRUST
tristate "Trust FM radio card"
depends on ISA && VIDEO_V4L2
- select RADIO_ISA
help
This is a driver for the Trust FM radio cards. Say Y if you have
such a card and want to use it under Linux.
- Note: this driver hasn't been tested since a long time due to lack
- of hardware. If you have this hardware, then please contact the
- linux-media mailinglist.
-
To compile this driver as a module, choose M here: the
module will be called radio-trust.
@@ -377,14 +404,14 @@ config RADIO_TRUST_PORT
config RADIO_TYPHOON
tristate "Typhoon Radio (a.k.a. EcoRadio)"
depends on ISA && VIDEO_V4L2
- select RADIO_ISA
---help---
Choose Y here if you have one of these FM radio cards, and then fill
in the port address and the frequency used for muting below.
- Note: this driver hasn't been tested since a long time due to lack
- of hardware. If you have this hardware, then please contact the
- linux-media mailinglist.
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ .
To compile this driver as a module, choose M here: the
module will be called radio-typhoon.
@@ -411,14 +438,14 @@ config RADIO_TYPHOON_MUTEFREQ
config RADIO_ZOLTRIX
tristate "Zoltrix Radio"
depends on ISA && VIDEO_V4L2
- select RADIO_ISA
---help---
Choose Y here if you have one of these FM radio cards, and then fill
in the port address below.
- Note: this driver hasn't been tested since a long time due to lack
- of hardware. If you have this hardware, then please contact the
- linux-media mailinglist.
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ .
To compile this driver as a module, choose M here: the
module will be called radio-zoltrix.
diff --git a/trunk/drivers/media/radio/Makefile b/trunk/drivers/media/radio/Makefile
index ca8c7d134b95..390daf94d847 100644
--- a/trunk/drivers/media/radio/Makefile
+++ b/trunk/drivers/media/radio/Makefile
@@ -2,7 +2,6 @@
# Makefile for the kernel character device drivers.
#
-obj-$(CONFIG_RADIO_ISA) += radio-isa.o
obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o
obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o
obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o
@@ -21,7 +20,6 @@ obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_RADIO_SI470X) += si470x/
obj-$(CONFIG_USB_MR800) += radio-mr800.o
-obj-$(CONFIG_USB_KEENE) += radio-keene.o
obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o
obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o
obj-$(CONFIG_RADIO_TEF6862) += tef6862.o
diff --git a/trunk/drivers/media/radio/radio-aimslab.c b/trunk/drivers/media/radio/radio-aimslab.c
index 98e0c8c20312..1c3f8440a55c 100644
--- a/trunk/drivers/media/radio/radio-aimslab.c
+++ b/trunk/drivers/media/radio/radio-aimslab.c
@@ -1,13 +1,16 @@
-/*
- * AimsLab RadioTrack (aka RadioVeveal) driver
- *
- * Copyright 1997 M. Kirkwood
- *
- * Converted to the radio-isa framework by Hans Verkuil
+/* radiotrack (radioreveal) driver for Linux radio support
+ * (c) 1997 M. Kirkwood
* Converted to V4L2 API by Mauro Carvalho Chehab
* Converted to new API by Alan Cox
* Various bugfixes and enhancements by Russell Kroll
*
+ * History:
+ * 1999-02-24 Russell Kroll
+ * Fine tuning/VIDEO_TUNER_LOW
+ * Frequency range expanded to start at 87 MHz
+ *
+ * TODO: Allow for more than one of these foolish entities :-)
+ *
* Notes on the hardware (reverse engineered from other peoples'
* reverse engineering of AIMS' code :-)
*
@@ -23,7 +26,6 @@
* wait(a_wee_while);
* out(port, stop_changing_the_volume);
*
- * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool.
*/
#include /* Modules */
@@ -32,179 +34,401 @@
#include /* msleep */
#include /* kernel radio structs */
#include /* outb, outb_p */
-#include
#include
#include
-#include
-#include "radio-isa.h"
-MODULE_AUTHOR("M. Kirkwood");
+MODULE_AUTHOR("M.Kirkwood");
MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.0");
+MODULE_VERSION("0.0.3");
#ifndef CONFIG_RADIO_RTRACK_PORT
#define CONFIG_RADIO_RTRACK_PORT -1
#endif
-#define RTRACK_MAX 2
+static int io = CONFIG_RADIO_RTRACK_PORT;
+static int radio_nr = -1;
-static int io[RTRACK_MAX] = { [0] = CONFIG_RADIO_RTRACK_PORT,
- [1 ... (RTRACK_MAX - 1)] = -1 };
-static int radio_nr[RTRACK_MAX] = { [0 ... (RTRACK_MAX - 1)] = -1 };
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)");
+module_param(radio_nr, int, 0);
-module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "I/O addresses of the RadioTrack card (0x20f or 0x30f)");
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device numbers");
-
-struct rtrack {
- struct radio_isa_card isa;
+struct rtrack
+{
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ int port;
int curvol;
+ unsigned long curfreq;
+ int muted;
+ int io;
+ struct mutex lock;
};
-static struct radio_isa_card *rtrack_alloc(void)
+static struct rtrack rtrack_card;
+
+/* local things */
+
+static void rt_decvol(struct rtrack *rt)
+{
+ outb(0x58, rt->io); /* volume down + sigstr + on */
+ msleep(100);
+ outb(0xd8, rt->io); /* volume steady + sigstr + on */
+}
+
+static void rt_incvol(struct rtrack *rt)
+{
+ outb(0x98, rt->io); /* volume up + sigstr + on */
+ msleep(100);
+ outb(0xd8, rt->io); /* volume steady + sigstr + on */
+}
+
+static void rt_mute(struct rtrack *rt)
+{
+ rt->muted = 1;
+ mutex_lock(&rt->lock);
+ outb(0xd0, rt->io); /* volume steady, off */
+ mutex_unlock(&rt->lock);
+}
+
+static int rt_setvol(struct rtrack *rt, int vol)
{
- struct rtrack *rt = kzalloc(sizeof(struct rtrack), GFP_KERNEL);
+ int i;
+
+ mutex_lock(&rt->lock);
+
+ if (vol == rt->curvol) { /* requested volume = current */
+ if (rt->muted) { /* user is unmuting the card */
+ rt->muted = 0;
+ outb(0xd8, rt->io); /* enable card */
+ }
+ mutex_unlock(&rt->lock);
+ return 0;
+ }
+
+ if (vol == 0) { /* volume = 0 means mute the card */
+ outb(0x48, rt->io); /* volume down but still "on" */
+ msleep(2000); /* make sure it's totally down */
+ outb(0xd0, rt->io); /* volume steady, off */
+ rt->curvol = 0; /* track the volume state! */
+ mutex_unlock(&rt->lock);
+ return 0;
+ }
- if (rt)
- rt->curvol = 0xff;
- return rt ? &rt->isa : NULL;
+ rt->muted = 0;
+ if (vol > rt->curvol)
+ for (i = rt->curvol; i < vol; i++)
+ rt_incvol(rt);
+ else
+ for (i = rt->curvol; i > vol; i--)
+ rt_decvol(rt);
+
+ rt->curvol = vol;
+ mutex_unlock(&rt->lock);
+ return 0;
}
-/* The 128+64 on these outb's is to keep the volume stable while tuning.
- * Without them, the volume _will_ creep up with each frequency change
- * and bit 4 (+16) is to keep the signal strength meter enabled.
+/* the 128+64 on these outb's is to keep the volume stable while tuning
+ * without them, the volume _will_ creep up with each frequency change
+ * and bit 4 (+16) is to keep the signal strength meter enabled
*/
-static void send_0_byte(struct radio_isa_card *isa, int on)
+static void send_0_byte(struct rtrack *rt)
{
- outb_p(128+64+16+on+1, isa->io); /* wr-enable + data low */
- outb_p(128+64+16+on+2+1, isa->io); /* clock */
+ if (rt->curvol == 0 || rt->muted) {
+ outb_p(128+64+16+ 1, rt->io); /* wr-enable + data low */
+ outb_p(128+64+16+2+1, rt->io); /* clock */
+ }
+ else {
+ outb_p(128+64+16+8+ 1, rt->io); /* on + wr-enable + data low */
+ outb_p(128+64+16+8+2+1, rt->io); /* clock */
+ }
msleep(1);
}
-static void send_1_byte(struct radio_isa_card *isa, int on)
+static void send_1_byte(struct rtrack *rt)
{
- outb_p(128+64+16+on+4+1, isa->io); /* wr-enable+data high */
- outb_p(128+64+16+on+4+2+1, isa->io); /* clock */
+ if (rt->curvol == 0 || rt->muted) {
+ outb_p(128+64+16+4 +1, rt->io); /* wr-enable+data high */
+ outb_p(128+64+16+4+2+1, rt->io); /* clock */
+ }
+ else {
+ outb_p(128+64+16+8+4 +1, rt->io); /* on+wr-enable+data high */
+ outb_p(128+64+16+8+4+2+1, rt->io); /* clock */
+ }
+
msleep(1);
}
-static int rtrack_s_frequency(struct radio_isa_card *isa, u32 freq)
+static int rt_setfreq(struct rtrack *rt, unsigned long freq)
{
- int on = v4l2_ctrl_g_ctrl(isa->mute) ? 0 : 8;
int i;
+ mutex_lock(&rt->lock); /* Stop other ops interfering */
+
+ rt->curfreq = freq;
+
+ /* now uses VIDEO_TUNER_LOW for fine tuning */
+
freq += 171200; /* Add 10.7 MHz IF */
freq /= 800; /* Convert to 50 kHz units */
- send_0_byte(isa, on); /* 0: LSB of frequency */
+ send_0_byte(rt); /* 0: LSB of frequency */
for (i = 0; i < 13; i++) /* : frequency bits (1-13) */
if (freq & (1 << i))
- send_1_byte(isa, on);
+ send_1_byte(rt);
else
- send_0_byte(isa, on);
+ send_0_byte(rt);
+
+ send_0_byte(rt); /* 14: test bit - always 0 */
+ send_0_byte(rt); /* 15: test bit - always 0 */
+
+ send_0_byte(rt); /* 16: band data 0 - always 0 */
+ send_0_byte(rt); /* 17: band data 1 - always 0 */
+ send_0_byte(rt); /* 18: band data 2 - always 0 */
+ send_0_byte(rt); /* 19: time base - always 0 */
+
+ send_0_byte(rt); /* 20: spacing (0 = 25 kHz) */
+ send_1_byte(rt); /* 21: spacing (1 = 25 kHz) */
+ send_0_byte(rt); /* 22: spacing (0 = 25 kHz) */
+ send_1_byte(rt); /* 23: AM/FM (FM = 1, always) */
+
+ if (rt->curvol == 0 || rt->muted)
+ outb(0xd0, rt->io); /* volume steady + sigstr */
+ else
+ outb(0xd8, rt->io); /* volume steady + sigstr + on */
+
+ mutex_unlock(&rt->lock);
+
+ return 0;
+}
+
+static int rt_getsigstr(struct rtrack *rt)
+{
+ int sig = 1;
+
+ mutex_lock(&rt->lock);
+ if (inb(rt->io) & 2) /* bit set = no signal present */
+ sig = 0;
+ mutex_unlock(&rt->lock);
+ return sig;
+}
+
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *v)
+{
+ strlcpy(v->driver, "radio-aimslab", sizeof(v->driver));
+ strlcpy(v->card, "RadioTrack", sizeof(v->card));
+ strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
+ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
+{
+ struct rtrack *rt = video_drvdata(file);
- send_0_byte(isa, on); /* 14: test bit - always 0 */
- send_0_byte(isa, on); /* 15: test bit - always 0 */
+ if (v->index > 0)
+ return -EINVAL;
- send_0_byte(isa, on); /* 16: band data 0 - always 0 */
- send_0_byte(isa, on); /* 17: band data 1 - always 0 */
- send_0_byte(isa, on); /* 18: band data 2 - always 0 */
- send_0_byte(isa, on); /* 19: time base - always 0 */
+ strlcpy(v->name, "FM", sizeof(v->name));
+ v->type = V4L2_TUNER_RADIO;
+ v->rangelow = 87 * 16000;
+ v->rangehigh = 108 * 16000;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO;
+ v->capability = V4L2_TUNER_CAP_LOW;
+ v->audmode = V4L2_TUNER_MODE_MONO;
+ v->signal = 0xffff * rt_getsigstr(rt);
+ return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
+{
+ return v->index ? -EINVAL : 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct rtrack *rt = video_drvdata(file);
+
+ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+ return -EINVAL;
+ rt_setfreq(rt, f->frequency);
+ return 0;
+}
- send_0_byte(isa, on); /* 20: spacing (0 = 25 kHz) */
- send_1_byte(isa, on); /* 21: spacing (1 = 25 kHz) */
- send_0_byte(isa, on); /* 22: spacing (0 = 25 kHz) */
- send_1_byte(isa, on); /* 23: AM/FM (FM = 1, always) */
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct rtrack *rt = video_drvdata(file);
- outb(0xd0 + on, isa->io); /* volume steady + sigstr */
+ if (f->tuner != 0)
+ return -EINVAL;
+ f->type = V4L2_TUNER_RADIO;
+ f->frequency = rt->curfreq;
return 0;
}
-static u32 rtrack_g_signal(struct radio_isa_card *isa)
+static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
{
- /* bit set = no signal present */
- return 0xffff * !(inb(isa->io) & 2);
+ switch (qc->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+ case V4L2_CID_AUDIO_VOLUME:
+ return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff);
+ }
+ return -EINVAL;
}
-static int rtrack_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
{
- struct rtrack *rt = container_of(isa, struct rtrack, isa);
- int curvol = rt->curvol;
+ struct rtrack *rt = video_drvdata(file);
- if (mute) {
- outb(0xd0, isa->io); /* volume steady + sigstr + off */
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = rt->muted;
+ return 0;
+ case V4L2_CID_AUDIO_VOLUME:
+ ctrl->value = rt->curvol;
return 0;
}
- if (vol == 0) { /* volume = 0 means mute the card */
- outb(0x48, isa->io); /* volume down but still "on" */
- msleep(curvol * 3); /* make sure it's totally down */
- } else if (curvol < vol) {
- outb(0x98, isa->io); /* volume up + sigstr + on */
- for (; curvol < vol; curvol++)
- udelay(3000);
- } else if (curvol > vol) {
- outb(0x58, isa->io); /* volume down + sigstr + on */
- for (; curvol > vol; curvol--)
- udelay(3000);
+ return -EINVAL;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct rtrack *rt = video_drvdata(file);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (ctrl->value)
+ rt_mute(rt);
+ else
+ rt_setvol(rt, rt->curvol);
+ return 0;
+ case V4L2_CID_AUDIO_VOLUME:
+ rt_setvol(rt, ctrl->value);
+ return 0;
}
- outb(0xd8, isa->io); /* volume steady + sigstr + on */
- rt->curvol = vol;
+ return -EINVAL;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+ *i = 0;
return 0;
}
-/* Mute card - prevents noisy bootups */
-static int rtrack_initialize(struct radio_isa_card *isa)
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
{
- /* this ensures that the volume is all the way up */
- outb(0x90, isa->io); /* volume up but still "on" */
- msleep(3000); /* make sure it's totally up */
- outb(0xc0, isa->io); /* steady volume, mute card */
+ return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ a->index = 0;
+ strlcpy(a->name, "Radio", sizeof(a->name));
+ a->capability = V4L2_AUDCAP_STEREO;
return 0;
}
-static const struct radio_isa_ops rtrack_ops = {
- .alloc = rtrack_alloc,
- .init = rtrack_initialize,
- .s_mute_volume = rtrack_s_mute_volume,
- .s_frequency = rtrack_s_frequency,
- .g_signal = rtrack_g_signal,
+static int vidioc_s_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ return a->index ? -EINVAL : 0;
+}
+
+static const struct v4l2_file_operations rtrack_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = video_ioctl2,
};
-static const int rtrack_ioports[] = { 0x20f, 0x30f };
-
-static struct radio_isa_driver rtrack_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-aimslab",
- },
- },
- .io_params = io,
- .radio_nr_params = radio_nr,
- .io_ports = rtrack_ioports,
- .num_of_io_ports = ARRAY_SIZE(rtrack_ioports),
- .region_size = 2,
- .card = "AIMSlab RadioTrack/RadioReveal",
- .ops = &rtrack_ops,
- .has_stereo = true,
- .max_volume = 0xff,
+static const struct v4l2_ioctl_ops rtrack_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
};
static int __init rtrack_init(void)
{
- return isa_register_driver(&rtrack_driver.driver, RTRACK_MAX);
+ struct rtrack *rt = &rtrack_card;
+ struct v4l2_device *v4l2_dev = &rt->v4l2_dev;
+ int res;
+
+ strlcpy(v4l2_dev->name, "rtrack", sizeof(v4l2_dev->name));
+ rt->io = io;
+
+ if (rt->io == -1) {
+ v4l2_err(v4l2_dev, "you must set an I/O address with io=0x20f or 0x30f\n");
+ return -EINVAL;
+ }
+
+ if (!request_region(rt->io, 2, "rtrack")) {
+ v4l2_err(v4l2_dev, "port 0x%x already in use\n", rt->io);
+ return -EBUSY;
+ }
+
+ res = v4l2_device_register(NULL, v4l2_dev);
+ if (res < 0) {
+ release_region(rt->io, 2);
+ v4l2_err(v4l2_dev, "could not register v4l2_device\n");
+ return res;
+ }
+
+ strlcpy(rt->vdev.name, v4l2_dev->name, sizeof(rt->vdev.name));
+ rt->vdev.v4l2_dev = v4l2_dev;
+ rt->vdev.fops = &rtrack_fops;
+ rt->vdev.ioctl_ops = &rtrack_ioctl_ops;
+ rt->vdev.release = video_device_release_empty;
+ video_set_drvdata(&rt->vdev, rt);
+
+ /* Set up the I/O locking */
+
+ mutex_init(&rt->lock);
+
+ /* mute card - prevents noisy bootups */
+
+ /* this ensures that the volume is all the way down */
+ outb(0x48, rt->io); /* volume down but still "on" */
+ msleep(2000); /* make sure it's totally down */
+ outb(0xc0, rt->io); /* steady volume, mute card */
+
+ if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+ v4l2_device_unregister(&rt->v4l2_dev);
+ release_region(rt->io, 2);
+ return -EINVAL;
+ }
+ v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n");
+
+ return 0;
}
static void __exit rtrack_exit(void)
{
- isa_unregister_driver(&rtrack_driver.driver);
+ struct rtrack *rt = &rtrack_card;
+
+ video_unregister_device(&rt->vdev);
+ v4l2_device_unregister(&rt->v4l2_dev);
+ release_region(rt->io, 2);
}
module_init(rtrack_init);
module_exit(rtrack_exit);
+
diff --git a/trunk/drivers/media/radio/radio-aztech.c b/trunk/drivers/media/radio/radio-aztech.c
index 177bcbd7a7c1..eed7b0840734 100644
--- a/trunk/drivers/media/radio/radio-aztech.c
+++ b/trunk/drivers/media/radio/radio-aztech.c
@@ -1,7 +1,5 @@
-/*
- * radio-aztech.c - Aztech radio card driver
+/* radio-aztech.c - Aztech radio card driver for Linux 2.2
*
- * Converted to the radio-isa framework by Hans Verkuil
* Converted to V4L2 API by Mauro Carvalho Chehab
* Adapted to support the Video for Linux API by
* Russell Kroll . Based on original tuner code by:
@@ -12,7 +10,19 @@
* Scott McGrath (smcgrath@twilight.vtc.vsc.edu)
* William McGrath (wmcgrath@twilight.vtc.vsc.edu)
*
- * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool.
+ * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/
+ * along with more information on the card itself.
+ *
+ * History:
+ * 1999-02-24 Russell Kroll
+ * Fine tuning/VIDEO_TUNER_LOW
+ * Range expanded to 87-108 MHz (from 87.9-107.8)
+ *
+ * Notable changes from the original source:
+ * - includes stripped down to the essentials
+ * - for loops used as delays replaced with udelay()
+ * - #defines removed, changed to static values
+ * - tuning structure changed - no more character arrays, other changes
*/
#include /* Modules */
@@ -21,72 +31,126 @@
#include /* udelay */
#include /* kernel radio structs */
#include /* outb, outb_p */
-#include
#include
#include
-#include
-#include "radio-isa.h"
MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
MODULE_DESCRIPTION("A driver for the Aztech radio card.");
MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.0");
+MODULE_VERSION("0.0.3");
/* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
+
#ifndef CONFIG_RADIO_AZTECH_PORT
#define CONFIG_RADIO_AZTECH_PORT -1
#endif
-#define AZTECH_MAX 2
+static int io = CONFIG_RADIO_AZTECH_PORT;
+static int radio_nr = -1;
+static int radio_wait_time = 1000;
-static int io[AZTECH_MAX] = { [0] = CONFIG_RADIO_AZTECH_PORT,
- [1 ... (AZTECH_MAX - 1)] = -1 };
-static int radio_nr[AZTECH_MAX] = { [0 ... (AZTECH_MAX - 1)] = -1 };
-static const int radio_wait_time = 1000;
+module_param(io, int, 0);
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)");
-module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "I/O addresses of the Aztech card (0x350 or 0x358)");
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device numbers");
-
-struct aztech {
- struct radio_isa_card isa;
+struct aztech
+{
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ int io;
int curvol;
+ unsigned long curfreq;
+ int stereo;
+ struct mutex lock;
};
+static struct aztech aztech_card;
+
+static int volconvert(int level)
+{
+ level >>= 14; /* Map 16bits down to 2 bit */
+ level &= 3;
+
+ /* convert to card-friendly values */
+ switch (level) {
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ case 2:
+ return 4;
+ case 3:
+ return 5;
+ }
+ return 0; /* Quieten gcc */
+}
+
static void send_0_byte(struct aztech *az)
{
udelay(radio_wait_time);
- outb_p(2 + az->curvol, az->isa.io);
- outb_p(64 + 2 + az->curvol, az->isa.io);
+ outb_p(2 + volconvert(az->curvol), az->io);
+ outb_p(64 + 2 + volconvert(az->curvol), az->io);
}
static void send_1_byte(struct aztech *az)
{
- udelay(radio_wait_time);
- outb_p(128 + 2 + az->curvol, az->isa.io);
- outb_p(128 + 64 + 2 + az->curvol, az->isa.io);
+ udelay (radio_wait_time);
+ outb_p(128 + 2 + volconvert(az->curvol), az->io);
+ outb_p(128 + 64 + 2 + volconvert(az->curvol), az->io);
+}
+
+static int az_setvol(struct aztech *az, int vol)
+{
+ mutex_lock(&az->lock);
+ outb(volconvert(vol), az->io);
+ mutex_unlock(&az->lock);
+ return 0;
+}
+
+/* thanks to Michael Dwyer for giving me a dose of clues in
+ * the signal strength department..
+ *
+ * This card has a stereo bit - bit 0 set = mono, not set = stereo
+ * It also has a "signal" bit - bit 1 set = bad signal, not set = good
+ *
+ */
+
+static int az_getsigstr(struct aztech *az)
+{
+ int sig = 1;
+
+ mutex_lock(&az->lock);
+ if (inb(az->io) & 2) /* bit set = no signal present */
+ sig = 0;
+ mutex_unlock(&az->lock);
+ return sig;
}
-static struct radio_isa_card *aztech_alloc(void)
+static int az_getstereo(struct aztech *az)
{
- struct aztech *az = kzalloc(sizeof(*az), GFP_KERNEL);
+ int stereo = 1;
- return az ? &az->isa : NULL;
+ mutex_lock(&az->lock);
+ if (inb(az->io) & 1) /* bit set = mono */
+ stereo = 0;
+ mutex_unlock(&az->lock);
+ return stereo;
}
-static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq)
+static int az_setfreq(struct aztech *az, unsigned long frequency)
{
- struct aztech *az = container_of(isa, struct aztech, isa);
int i;
- freq += 171200; /* Add 10.7 MHz IF */
- freq /= 800; /* Convert to 50 kHz units */
+ mutex_lock(&az->lock);
+
+ az->curfreq = frequency;
+ frequency += 171200; /* Add 10.7 MHz IF */
+ frequency /= 800; /* Convert to 50 kHz units */
send_0_byte(az); /* 0: LSB of frequency */
for (i = 0; i < 13; i++) /* : frequency bits (1-13) */
- if (freq & (1 << i))
+ if (frequency & (1 << i))
send_1_byte(az);
else
send_0_byte(az);
@@ -94,7 +158,7 @@ static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq)
send_0_byte(az); /* 14: test bit - always 0 */
send_0_byte(az); /* 15: test bit - always 0 */
send_0_byte(az); /* 16: band data 0 - always 0 */
- if (isa->stereo) /* 17: stereo (1 to enable) */
+ if (az->stereo) /* 17: stereo (1 to enable) */
send_1_byte(az);
else
send_0_byte(az);
@@ -109,77 +173,225 @@ static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq)
/* latch frequency */
udelay(radio_wait_time);
- outb_p(128 + 64 + az->curvol, az->isa.io);
+ outb_p(128 + 64 + volconvert(az->curvol), az->io);
+
+ mutex_unlock(&az->lock);
return 0;
}
-/* thanks to Michael Dwyer for giving me a dose of clues in
- * the signal strength department..
- *
- * This card has a stereo bit - bit 0 set = mono, not set = stereo
- */
-static u32 aztech_g_rxsubchans(struct radio_isa_card *isa)
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *v)
+{
+ strlcpy(v->driver, "radio-aztech", sizeof(v->driver));
+ strlcpy(v->card, "Aztech Radio", sizeof(v->card));
+ strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
+ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
+{
+ struct aztech *az = video_drvdata(file);
+
+ if (v->index > 0)
+ return -EINVAL;
+
+ strlcpy(v->name, "FM", sizeof(v->name));
+ v->type = V4L2_TUNER_RADIO;
+
+ v->rangelow = 87 * 16000;
+ v->rangehigh = 108 * 16000;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+ v->capability = V4L2_TUNER_CAP_LOW;
+ if (az_getstereo(az))
+ v->audmode = V4L2_TUNER_MODE_STEREO;
+ else
+ v->audmode = V4L2_TUNER_MODE_MONO;
+ v->signal = 0xFFFF * az_getsigstr(az);
+
+ return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
{
- if (inb(isa->io) & 1)
- return V4L2_TUNER_SUB_MONO;
- return V4L2_TUNER_SUB_STEREO;
+ return v->index ? -EINVAL : 0;
}
-static int aztech_s_stereo(struct radio_isa_card *isa, bool stereo)
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
{
- return aztech_s_frequency(isa, isa->freq);
+ *i = 0;
+ return 0;
}
-static int aztech_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
{
- struct aztech *az = container_of(isa, struct aztech, isa);
+ return i ? -EINVAL : 0;
+}
- if (mute)
- vol = 0;
- az->curvol = (vol & 1) + ((vol & 2) << 1);
- outb(az->curvol, isa->io);
+static int vidioc_g_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ a->index = 0;
+ strlcpy(a->name, "Radio", sizeof(a->name));
+ a->capability = V4L2_AUDCAP_STEREO;
return 0;
}
-static const struct radio_isa_ops aztech_ops = {
- .alloc = aztech_alloc,
- .s_mute_volume = aztech_s_mute_volume,
- .s_frequency = aztech_s_frequency,
- .s_stereo = aztech_s_stereo,
- .g_rxsubchans = aztech_g_rxsubchans,
+static int vidioc_s_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ return a->index ? -EINVAL : 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct aztech *az = video_drvdata(file);
+
+ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+ return -EINVAL;
+ az_setfreq(az, f->frequency);
+ return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct aztech *az = video_drvdata(file);
+
+ if (f->tuner != 0)
+ return -EINVAL;
+ f->type = V4L2_TUNER_RADIO;
+ f->frequency = az->curfreq;
+ return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ switch (qc->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+ case V4L2_CID_AUDIO_VOLUME:
+ return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff);
+ }
+ return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct aztech *az = video_drvdata(file);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (az->curvol == 0)
+ ctrl->value = 1;
+ else
+ ctrl->value = 0;
+ return 0;
+ case V4L2_CID_AUDIO_VOLUME:
+ ctrl->value = az->curvol * 6554;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct aztech *az = video_drvdata(file);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (ctrl->value)
+ az_setvol(az, 0);
+ else
+ az_setvol(az, az->curvol);
+ return 0;
+ case V4L2_CID_AUDIO_VOLUME:
+ az_setvol(az, ctrl->value);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static const struct v4l2_file_operations aztech_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = video_ioctl2,
};
-static const int aztech_ioports[] = { 0x350, 0x358 };
-
-static struct radio_isa_driver aztech_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-aztech",
- },
- },
- .io_params = io,
- .radio_nr_params = radio_nr,
- .io_ports = aztech_ioports,
- .num_of_io_ports = ARRAY_SIZE(aztech_ioports),
- .region_size = 2,
- .card = "Aztech Radio",
- .ops = &aztech_ops,
- .has_stereo = true,
- .max_volume = 3,
+static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
};
static int __init aztech_init(void)
{
- return isa_register_driver(&aztech_driver.driver, AZTECH_MAX);
+ struct aztech *az = &aztech_card;
+ struct v4l2_device *v4l2_dev = &az->v4l2_dev;
+ int res;
+
+ strlcpy(v4l2_dev->name, "aztech", sizeof(v4l2_dev->name));
+ az->io = io;
+
+ if (az->io == -1) {
+ v4l2_err(v4l2_dev, "you must set an I/O address with io=0x350 or 0x358\n");
+ return -EINVAL;
+ }
+
+ if (!request_region(az->io, 2, "aztech")) {
+ v4l2_err(v4l2_dev, "port 0x%x already in use\n", az->io);
+ return -EBUSY;
+ }
+
+ res = v4l2_device_register(NULL, v4l2_dev);
+ if (res < 0) {
+ release_region(az->io, 2);
+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+ return res;
+ }
+
+ mutex_init(&az->lock);
+ strlcpy(az->vdev.name, v4l2_dev->name, sizeof(az->vdev.name));
+ az->vdev.v4l2_dev = v4l2_dev;
+ az->vdev.fops = &aztech_fops;
+ az->vdev.ioctl_ops = &aztech_ioctl_ops;
+ az->vdev.release = video_device_release_empty;
+ video_set_drvdata(&az->vdev, az);
+ /* mute card - prevents noisy bootups */
+ outb(0, az->io);
+
+ if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+ v4l2_device_unregister(v4l2_dev);
+ release_region(az->io, 2);
+ return -EINVAL;
+ }
+
+ v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
+ return 0;
}
static void __exit aztech_exit(void)
{
- isa_unregister_driver(&aztech_driver.driver);
+ struct aztech *az = &aztech_card;
+
+ video_unregister_device(&az->vdev);
+ v4l2_device_unregister(&az->v4l2_dev);
+ release_region(az->io, 2);
}
module_init(aztech_init);
diff --git a/trunk/drivers/media/radio/radio-gemtek.c b/trunk/drivers/media/radio/radio-gemtek.c
index 2e639ce6f256..36ce0611c037 100644
--- a/trunk/drivers/media/radio/radio-gemtek.c
+++ b/trunk/drivers/media/radio/radio-gemtek.c
@@ -1,7 +1,4 @@
-/*
- * GemTek radio card driver
- *
- * Copyright 1998 Jonas Munsin
+/* GemTek radio card driver for Linux (C) 1998 Jonas Munsin
*
* GemTek hasn't released any specs on the card, so the protocol had to
* be reverse engineered with dosemu.
@@ -14,12 +11,9 @@
* Converted to new API by Alan Cox
* Various bugfixes and enhancements by Russell Kroll
*
- * Converted to the radio-isa framework by Hans Verkuil
- * Converted to V4L2 API by Mauro Carvalho Chehab
+ * TODO: Allow for more than one of these foolish entities :-)
*
- * Note: this card seems to swap the left and right audio channels!
- *
- * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool.
+ * Converted to V4L2 API by Mauro Carvalho Chehab
*/
#include /* Modules */
@@ -29,10 +23,8 @@
#include /* kernel radio structs */
#include
#include /* outb, outb_p */
-#include
#include
#include
-#include "radio-isa.h"
/*
* Module info.
@@ -41,7 +33,7 @@
MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen ");
MODULE_DESCRIPTION("A driver for the GemTek Radio card.");
MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.0");
+MODULE_VERSION("0.0.4");
/*
* Module params.
@@ -54,29 +46,45 @@ MODULE_VERSION("1.0.0");
#define CONFIG_RADIO_GEMTEK_PROBE 1
#endif
-#define GEMTEK_MAX 4
-
-static bool probe = CONFIG_RADIO_GEMTEK_PROBE;
+static int io = CONFIG_RADIO_GEMTEK_PORT;
+static bool probe = CONFIG_RADIO_GEMTEK_PROBE;
static bool hardmute;
-static int io[GEMTEK_MAX] = { [0] = CONFIG_RADIO_GEMTEK_PORT,
- [1 ... (GEMTEK_MAX - 1)] = -1 };
-static int radio_nr[GEMTEK_MAX] = { [0 ... (GEMTEK_MAX - 1)] = -1 };
+static bool shutdown = 1;
+static bool keepmuted = 1;
+static bool initmute = 1;
+static int radio_nr = -1;
+
+module_param(io, int, 0444);
+MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic "
+ "probing is disabled or fails. The most common I/O ports are: 0x20c "
+ "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to "
+ "work for the combined sound/radiocard).");
module_param(probe, bool, 0444);
-MODULE_PARM_DESC(probe, "Enable automatic device probing.");
+MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most "
+ "common I/O ports used by the card are probed.");
module_param(hardmute, bool, 0644);
-MODULE_PARM_DESC(hardmute, "Enable 'hard muting' by shutting down PLL, may "
+MODULE_PARM_DESC(hardmute, "Enable `hard muting' by shutting down PLL, may "
"reduce static noise.");
-module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "Force I/O ports for the GemTek Radio card if automatic "
- "probing is disabled or fails. The most common I/O ports are: 0x20c "
- "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to "
- "work for the combined sound/radiocard).");
+module_param(shutdown, bool, 0644);
+MODULE_PARM_DESC(shutdown, "Enable shutting down PLL and muting line when "
+ "module is unloaded.");
+
+module_param(keepmuted, bool, 0644);
+MODULE_PARM_DESC(keepmuted, "Keep card muted even when frequency is changed.");
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device numbers");
+module_param(initmute, bool, 0444);
+MODULE_PARM_DESC(initmute, "Mute card when module is loaded.");
+
+module_param(radio_nr, int, 0444);
+
+/*
+ * Functions for controlling the card.
+ */
+#define GEMTEK_LOWFREQ (87*16000)
+#define GEMTEK_HIGHFREQ (108*16000)
/*
* Frequency calculation constants. Intermediate frequency 10.52 MHz (nominal
@@ -100,11 +108,18 @@ MODULE_PARM_DESC(radio_nr, "Radio device numbers");
#define LONG_DELAY 75 /* usec */
struct gemtek {
- struct radio_isa_card isa;
- bool muted;
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ struct mutex lock;
+ unsigned long lastfreq;
+ int muted;
+ int verified;
+ int io;
u32 bu2614data;
};
+static struct gemtek gemtek_card;
+
#define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */
#define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */
#define BU2614_VOID_BITS 4 /* unused */
@@ -151,24 +166,31 @@ struct gemtek {
*/
static void gemtek_bu2614_transmit(struct gemtek *gt)
{
- struct radio_isa_card *isa = >->isa;
int i, bit, q, mute;
+ mutex_lock(>->lock);
+
mute = gt->muted ? GEMTEK_MT : 0x00;
- outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, isa->io);
+ outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io);
+ udelay(SHORT_DELAY);
+ outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io);
udelay(LONG_DELAY);
for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) {
bit = (q & 1) ? GEMTEK_DA : 0;
- outb_p(mute | GEMTEK_CE | bit, isa->io);
+ outb_p(mute | GEMTEK_CE | bit, gt->io);
udelay(SHORT_DELAY);
- outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, isa->io);
+ outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, gt->io);
udelay(SHORT_DELAY);
}
- outb_p(mute | GEMTEK_DA | GEMTEK_CK, isa->io);
+ outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io);
udelay(SHORT_DELAY);
+ outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io);
+ udelay(LONG_DELAY);
+
+ mutex_unlock(>->lock);
}
/*
@@ -176,27 +198,21 @@ static void gemtek_bu2614_transmit(struct gemtek *gt)
*/
static unsigned long gemtek_convfreq(unsigned long freq)
{
- return ((freq << FSCALE) + IF_OFFSET + REF_FREQ / 2) / REF_FREQ;
-}
-
-static struct radio_isa_card *gemtek_alloc(void)
-{
- struct gemtek *gt = kzalloc(sizeof(*gt), GFP_KERNEL);
-
- if (gt)
- gt->muted = true;
- return gt ? >->isa : NULL;
+ return ((freq<muted)
+ return;
- if (hardmute && gt->muted)
- return 0;
+ freq = clamp_val(freq, GEMTEK_LOWFREQ, GEMTEK_HIGHFREQ);
+
+ gt->lastfreq = freq;
+ gt->muted = 0;
gemtek_bu2614_set(gt, BU2614_PORT, 0);
gemtek_bu2614_set(gt, BU2614_FMES, 0);
@@ -204,25 +220,23 @@ static int gemtek_s_frequency(struct radio_isa_card *isa, u32 freq)
gemtek_bu2614_set(gt, BU2614_SWAL, 0);
gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */
gemtek_bu2614_set(gt, BU2614_TEST, 0);
+
gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ);
gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq));
+
gemtek_bu2614_transmit(gt);
- return 0;
}
/*
* Set mute flag.
*/
-static int gemtek_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
+static void gemtek_mute(struct gemtek *gt)
{
- struct gemtek *gt = container_of(isa, struct gemtek, isa);
int i;
- gt->muted = mute;
- if (hardmute) {
- if (!mute)
- return gemtek_s_frequency(isa, isa->freq);
+ gt->muted = 1;
+ if (hardmute) {
/* Turn off PLL, disable data output */
gemtek_bu2614_set(gt, BU2614_PORT, 0);
gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */
@@ -233,85 +247,367 @@ static int gemtek_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF);
gemtek_bu2614_set(gt, BU2614_FREQ, 0);
gemtek_bu2614_transmit(gt);
- return 0;
+ return;
}
+ mutex_lock(>->lock);
+
/* Read bus contents (CE, CK and DA). */
- i = inb_p(isa->io);
+ i = inb_p(gt->io);
/* Write it back with mute flag set. */
- outb_p((i >> 5) | (mute ? GEMTEK_MT : 0), isa->io);
+ outb_p((i >> 5) | GEMTEK_MT, gt->io);
udelay(SHORT_DELAY);
- return 0;
+
+ mutex_unlock(>->lock);
+}
+
+/*
+ * Unset mute flag.
+ */
+static void gemtek_unmute(struct gemtek *gt)
+{
+ int i;
+
+ gt->muted = 0;
+ if (hardmute) {
+ /* Turn PLL back on. */
+ gemtek_setfreq(gt, gt->lastfreq);
+ return;
+ }
+ mutex_lock(>->lock);
+
+ i = inb_p(gt->io);
+ outb_p(i >> 5, gt->io);
+ udelay(SHORT_DELAY);
+
+ mutex_unlock(>->lock);
}
-static u32 gemtek_g_rxsubchans(struct radio_isa_card *isa)
+/*
+ * Get signal strength (= stereo status).
+ */
+static inline int gemtek_getsigstr(struct gemtek *gt)
{
- if (inb_p(isa->io) & GEMTEK_NS)
- return V4L2_TUNER_SUB_MONO;
- return V4L2_TUNER_SUB_STEREO;
+ int sig;
+
+ mutex_lock(>->lock);
+ sig = inb_p(gt->io) & GEMTEK_NS ? 0 : 1;
+ mutex_unlock(>->lock);
+ return sig;
}
/*
* Check if requested card acts like GemTek Radio card.
*/
-static bool gemtek_probe(struct radio_isa_card *isa, int io)
+static int gemtek_verify(struct gemtek *gt, int port)
{
int i, q;
- q = inb_p(io); /* Read bus contents before probing. */
+ if (gt->verified == port)
+ return 1;
+
+ mutex_lock(>->lock);
+
+ q = inb_p(port); /* Read bus contents before probing. */
/* Try to turn on CE, CK and DA respectively and check if card responds
properly. */
for (i = 0; i < 3; ++i) {
- outb_p(1 << i, io);
+ outb_p(1 << i, port);
udelay(SHORT_DELAY);
- if ((inb_p(io) & ~GEMTEK_NS) != (0x17 | (1 << (i + 5))))
- return false;
+ if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) {
+ mutex_unlock(>->lock);
+ return 0;
+ }
}
- outb_p(q >> 5, io); /* Write bus contents back. */
+ outb_p(q >> 5, port); /* Write bus contents back. */
udelay(SHORT_DELAY);
- return true;
+
+ mutex_unlock(>->lock);
+ gt->verified = port;
+
+ return 1;
+}
+
+/*
+ * Automatic probing for card.
+ */
+static int gemtek_probe(struct gemtek *gt)
+{
+ struct v4l2_device *v4l2_dev = >->v4l2_dev;
+ int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c };
+ int i;
+
+ if (!probe) {
+ v4l2_info(v4l2_dev, "Automatic device probing disabled.\n");
+ return -1;
+ }
+
+ v4l2_info(v4l2_dev, "Automatic device probing enabled.\n");
+
+ for (i = 0; i < ARRAY_SIZE(ioports); ++i) {
+ v4l2_info(v4l2_dev, "Trying I/O port 0x%x...\n", ioports[i]);
+
+ if (!request_region(ioports[i], 1, "gemtek-probe")) {
+ v4l2_warn(v4l2_dev, "I/O port 0x%x busy!\n",
+ ioports[i]);
+ continue;
+ }
+
+ if (gemtek_verify(gt, ioports[i])) {
+ v4l2_info(v4l2_dev, "Card found from I/O port "
+ "0x%x!\n", ioports[i]);
+
+ release_region(ioports[i], 1);
+ gt->io = ioports[i];
+ return gt->io;
+ }
+
+ release_region(ioports[i], 1);
+ }
+
+ v4l2_err(v4l2_dev, "Automatic probing failed!\n");
+ return -1;
}
-static const struct radio_isa_ops gemtek_ops = {
- .alloc = gemtek_alloc,
- .probe = gemtek_probe,
- .s_mute_volume = gemtek_s_mute_volume,
- .s_frequency = gemtek_s_frequency,
- .g_rxsubchans = gemtek_g_rxsubchans,
+/*
+ * Video 4 Linux stuff.
+ */
+
+static const struct v4l2_file_operations gemtek_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = video_ioctl2,
};
-static const int gemtek_ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c };
-
-static struct radio_isa_driver gemtek_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-gemtek",
- },
- },
- .io_params = io,
- .radio_nr_params = radio_nr,
- .io_ports = gemtek_ioports,
- .num_of_io_ports = ARRAY_SIZE(gemtek_ioports),
- .region_size = 1,
- .card = "GemTek Radio",
- .ops = &gemtek_ops,
- .has_stereo = true,
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *v)
+{
+ strlcpy(v->driver, "radio-gemtek", sizeof(v->driver));
+ strlcpy(v->card, "GemTek", sizeof(v->card));
+ strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
+ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+{
+ struct gemtek *gt = video_drvdata(file);
+
+ if (v->index > 0)
+ return -EINVAL;
+
+ strlcpy(v->name, "FM", sizeof(v->name));
+ v->type = V4L2_TUNER_RADIO;
+ v->rangelow = GEMTEK_LOWFREQ;
+ v->rangehigh = GEMTEK_HIGHFREQ;
+ v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+ v->signal = 0xffff * gemtek_getsigstr(gt);
+ if (v->signal) {
+ v->audmode = V4L2_TUNER_MODE_STEREO;
+ v->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ } else {
+ v->audmode = V4L2_TUNER_MODE_MONO;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO;
+ }
+ return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+{
+ return (v->index != 0) ? -EINVAL : 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct gemtek *gt = video_drvdata(file);
+
+ if (f->tuner != 0)
+ return -EINVAL;
+ f->type = V4L2_TUNER_RADIO;
+ f->frequency = gt->lastfreq;
+ return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct gemtek *gt = video_drvdata(file);
+
+ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+ return -EINVAL;
+ gemtek_setfreq(gt, f->frequency);
+ return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ switch (qc->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct gemtek *gt = video_drvdata(file);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = gt->muted;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct gemtek *gt = video_drvdata(file);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (ctrl->value)
+ gemtek_mute(gt);
+ else
+ gemtek_unmute(gt);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+ return (i != 0) ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+ a->index = 0;
+ strlcpy(a->name, "Radio", sizeof(a->name));
+ a->capability = V4L2_AUDCAP_STEREO;
+ return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+ return (a->index != 0) ? -EINVAL : 0;
+}
+
+static const struct v4l2_ioctl_ops gemtek_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl
};
+/*
+ * Initialization / cleanup related stuff.
+ */
+
static int __init gemtek_init(void)
{
- gemtek_driver.probe = probe;
- return isa_register_driver(&gemtek_driver.driver, GEMTEK_MAX);
+ struct gemtek *gt = &gemtek_card;
+ struct v4l2_device *v4l2_dev = >->v4l2_dev;
+ int res;
+
+ strlcpy(v4l2_dev->name, "gemtek", sizeof(v4l2_dev->name));
+
+ v4l2_info(v4l2_dev, "GemTek Radio card driver: v0.0.3\n");
+
+ mutex_init(>->lock);
+
+ gt->verified = -1;
+ gt->io = io;
+ gemtek_probe(gt);
+ if (gt->io) {
+ if (!request_region(gt->io, 1, "gemtek")) {
+ v4l2_err(v4l2_dev, "I/O port 0x%x already in use.\n", gt->io);
+ return -EBUSY;
+ }
+
+ if (!gemtek_verify(gt, gt->io))
+ v4l2_warn(v4l2_dev, "Card at I/O port 0x%x does not "
+ "respond properly, check your "
+ "configuration.\n", gt->io);
+ else
+ v4l2_info(v4l2_dev, "Using I/O port 0x%x.\n", gt->io);
+ } else if (probe) {
+ v4l2_err(v4l2_dev, "Automatic probing failed and no "
+ "fixed I/O port defined.\n");
+ return -ENODEV;
+ } else {
+ v4l2_err(v4l2_dev, "Automatic probing disabled but no fixed "
+ "I/O port defined.");
+ return -EINVAL;
+ }
+
+ res = v4l2_device_register(NULL, v4l2_dev);
+ if (res < 0) {
+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+ release_region(gt->io, 1);
+ return res;
+ }
+
+ strlcpy(gt->vdev.name, v4l2_dev->name, sizeof(gt->vdev.name));
+ gt->vdev.v4l2_dev = v4l2_dev;
+ gt->vdev.fops = &gemtek_fops;
+ gt->vdev.ioctl_ops = &gemtek_ioctl_ops;
+ gt->vdev.release = video_device_release_empty;
+ video_set_drvdata(>->vdev, gt);
+
+ /* Set defaults */
+ gt->lastfreq = GEMTEK_LOWFREQ;
+ gt->bu2614data = 0;
+
+ if (initmute)
+ gemtek_mute(gt);
+
+ if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+ v4l2_device_unregister(v4l2_dev);
+ release_region(gt->io, 1);
+ return -EBUSY;
+ }
+
+ return 0;
}
+/*
+ * Module cleanup
+ */
static void __exit gemtek_exit(void)
{
- hardmute = 1; /* Turn off PLL */
- isa_unregister_driver(&gemtek_driver.driver);
+ struct gemtek *gt = &gemtek_card;
+ struct v4l2_device *v4l2_dev = >->v4l2_dev;
+
+ if (shutdown) {
+ hardmute = 1; /* Turn off PLL */
+ gemtek_mute(gt);
+ } else {
+ v4l2_info(v4l2_dev, "Module unloaded but card not muted!\n");
+ }
+
+ video_unregister_device(>->vdev);
+ v4l2_device_unregister(>->v4l2_dev);
+ release_region(gt->io, 1);
}
module_init(gemtek_init);
diff --git a/trunk/drivers/media/radio/radio-isa.c b/trunk/drivers/media/radio/radio-isa.c
deleted file mode 100644
index 06f906351fad..000000000000
--- a/trunk/drivers/media/radio/radio-isa.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Framework for ISA radio drivers.
- * This takes care of all the V4L2 scaffolding, allowing the ISA drivers
- * to concentrate on the actual hardware operation.
- *
- * Copyright (C) 2012 Hans Verkuil
- *
- * 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
-#include
-#include
-
-#include "radio-isa.h"
-
-MODULE_AUTHOR("Hans Verkuil");
-MODULE_DESCRIPTION("A framework for ISA radio drivers.");
-MODULE_LICENSE("GPL");
-
-#define FREQ_LOW (87U * 16000U)
-#define FREQ_HIGH (108U * 16000U)
-
-static int radio_isa_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- struct radio_isa_card *isa = video_drvdata(file);
-
- strlcpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver));
- strlcpy(v->card, isa->drv->card, sizeof(v->card));
- snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
-
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
- v->device_caps = v->capabilities | V4L2_CAP_DEVICE_CAPS;
- return 0;
-}
-
-static int radio_isa_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct radio_isa_card *isa = video_drvdata(file);
- const struct radio_isa_ops *ops = isa->drv->ops;
-
- if (v->index > 0)
- return -EINVAL;
-
- strlcpy(v->name, "FM", sizeof(v->name));
- v->type = V4L2_TUNER_RADIO;
- v->rangelow = FREQ_LOW;
- v->rangehigh = FREQ_HIGH;
- v->capability = V4L2_TUNER_CAP_LOW;
- if (isa->drv->has_stereo)
- v->capability |= V4L2_TUNER_CAP_STEREO;
-
- if (ops->g_rxsubchans)
- v->rxsubchans = ops->g_rxsubchans(isa);
- else
- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- v->audmode = isa->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
- if (ops->g_signal)
- v->signal = ops->g_signal(isa);
- else
- v->signal = (v->rxsubchans & V4L2_TUNER_SUB_STEREO) ?
- 0xffff : 0;
- return 0;
-}
-
-static int radio_isa_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct radio_isa_card *isa = video_drvdata(file);
- const struct radio_isa_ops *ops = isa->drv->ops;
-
- if (v->index)
- return -EINVAL;
- if (ops->s_stereo) {
- isa->stereo = (v->audmode == V4L2_TUNER_MODE_STEREO);
- return ops->s_stereo(isa, isa->stereo);
- }
- return 0;
-}
-
-static int radio_isa_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct radio_isa_card *isa = video_drvdata(file);
- int res;
-
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
- return -EINVAL;
- f->frequency = clamp(f->frequency, FREQ_LOW, FREQ_HIGH);
- res = isa->drv->ops->s_frequency(isa, f->frequency);
- if (res == 0)
- isa->freq = f->frequency;
- return res;
-}
-
-static int radio_isa_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct radio_isa_card *isa = video_drvdata(file);
-
- if (f->tuner != 0)
- return -EINVAL;
- f->type = V4L2_TUNER_RADIO;
- f->frequency = isa->freq;
- return 0;
-}
-
-static int radio_isa_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct radio_isa_card *isa =
- container_of(ctrl->handler, struct radio_isa_card, hdl);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- return isa->drv->ops->s_mute_volume(isa, ctrl->val,
- isa->volume ? isa->volume->val : 0);
- }
- return -EINVAL;
-}
-
-static int radio_isa_log_status(struct file *file, void *priv)
-{
- struct radio_isa_card *isa = video_drvdata(file);
-
- v4l2_info(&isa->v4l2_dev, "I/O Port = 0x%03x\n", isa->io);
- v4l2_ctrl_handler_log_status(&isa->hdl, isa->v4l2_dev.name);
- return 0;
-}
-
-static int radio_isa_subscribe_event(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- if (sub->type == V4L2_EVENT_CTRL)
- return v4l2_event_subscribe(fh, sub, 0);
- return -EINVAL;
-}
-
-static const struct v4l2_ctrl_ops radio_isa_ctrl_ops = {
- .s_ctrl = radio_isa_s_ctrl,
-};
-
-static const struct v4l2_file_operations radio_isa_fops = {
- .owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = v4l2_fh_release,
- .poll = v4l2_ctrl_poll,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops radio_isa_ioctl_ops = {
- .vidioc_querycap = radio_isa_querycap,
- .vidioc_g_tuner = radio_isa_g_tuner,
- .vidioc_s_tuner = radio_isa_s_tuner,
- .vidioc_g_frequency = radio_isa_g_frequency,
- .vidioc_s_frequency = radio_isa_s_frequency,
- .vidioc_log_status = radio_isa_log_status,
- .vidioc_subscribe_event = radio_isa_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-int radio_isa_match(struct device *pdev, unsigned int dev)
-{
- struct radio_isa_driver *drv = pdev->platform_data;
-
- return drv->probe || drv->io_params[dev] >= 0;
-}
-EXPORT_SYMBOL_GPL(radio_isa_match);
-
-static bool radio_isa_valid_io(const struct radio_isa_driver *drv, int io)
-{
- int i;
-
- for (i = 0; i < drv->num_of_io_ports; i++)
- if (drv->io_ports[i] == io)
- return true;
- return false;
-}
-
-int radio_isa_probe(struct device *pdev, unsigned int dev)
-{
- struct radio_isa_driver *drv = pdev->platform_data;
- const struct radio_isa_ops *ops = drv->ops;
- struct v4l2_device *v4l2_dev;
- struct radio_isa_card *isa;
- int res;
-
- isa = drv->ops->alloc();
- if (isa == NULL)
- return -ENOMEM;
- dev_set_drvdata(pdev, isa);
- isa->drv = drv;
- isa->io = drv->io_params[dev];
- v4l2_dev = &isa->v4l2_dev;
- strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name));
-
- if (drv->probe && ops->probe) {
- int i;
-
- for (i = 0; i < drv->num_of_io_ports; ++i) {
- int io = drv->io_ports[i];
-
- if (request_region(io, drv->region_size, v4l2_dev->name)) {
- bool found = ops->probe(isa, io);
-
- release_region(io, drv->region_size);
- if (found) {
- isa->io = io;
- break;
- }
- }
- }
- }
-
- if (!radio_isa_valid_io(drv, isa->io)) {
- int i;
-
- if (isa->io < 0)
- return -ENODEV;
- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x%03x",
- drv->io_ports[0]);
- for (i = 1; i < drv->num_of_io_ports; i++)
- printk(KERN_CONT "/0x%03x", drv->io_ports[i]);
- printk(KERN_CONT ".\n");
- kfree(isa);
- return -EINVAL;
- }
-
- if (!request_region(isa->io, drv->region_size, v4l2_dev->name)) {
- v4l2_err(v4l2_dev, "port 0x%x already in use\n", isa->io);
- kfree(isa);
- return -EBUSY;
- }
-
- res = v4l2_device_register(pdev, v4l2_dev);
- if (res < 0) {
- v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
- goto err_dev_reg;
- }
-
- v4l2_ctrl_handler_init(&isa->hdl, 1);
- isa->mute = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops,
- V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
- if (drv->max_volume)
- isa->volume = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops,
- V4L2_CID_AUDIO_VOLUME, 0, drv->max_volume, 1,
- drv->max_volume);
- v4l2_dev->ctrl_handler = &isa->hdl;
- if (isa->hdl.error) {
- res = isa->hdl.error;
- v4l2_err(v4l2_dev, "Could not register controls\n");
- goto err_hdl;
- }
- if (drv->max_volume)
- v4l2_ctrl_cluster(2, &isa->mute);
- v4l2_dev->ctrl_handler = &isa->hdl;
-
- mutex_init(&isa->lock);
- isa->vdev.lock = &isa->lock;
- strlcpy(isa->vdev.name, v4l2_dev->name, sizeof(isa->vdev.name));
- isa->vdev.v4l2_dev = v4l2_dev;
- isa->vdev.fops = &radio_isa_fops;
- isa->vdev.ioctl_ops = &radio_isa_ioctl_ops;
- isa->vdev.release = video_device_release_empty;
- set_bit(V4L2_FL_USE_FH_PRIO, &isa->vdev.flags);
- video_set_drvdata(&isa->vdev, isa);
- isa->freq = FREQ_LOW;
- isa->stereo = drv->has_stereo;
-
- if (ops->init)
- res = ops->init(isa);
- if (!res)
- res = v4l2_ctrl_handler_setup(&isa->hdl);
- if (!res)
- res = ops->s_frequency(isa, isa->freq);
- if (!res && ops->s_stereo)
- res = ops->s_stereo(isa, isa->stereo);
- if (res < 0) {
- v4l2_err(v4l2_dev, "Could not setup card\n");
- goto err_node_reg;
- }
- res = video_register_device(&isa->vdev, VFL_TYPE_RADIO,
- drv->radio_nr_params[dev]);
- if (res < 0) {
- v4l2_err(v4l2_dev, "Could not register device node\n");
- goto err_node_reg;
- }
-
- v4l2_info(v4l2_dev, "Initialized radio card %s on port 0x%03x\n",
- drv->card, isa->io);
- return 0;
-
-err_node_reg:
- v4l2_ctrl_handler_free(&isa->hdl);
-err_hdl:
- v4l2_device_unregister(&isa->v4l2_dev);
-err_dev_reg:
- release_region(isa->io, drv->region_size);
- kfree(isa);
- return res;
-}
-EXPORT_SYMBOL_GPL(radio_isa_probe);
-
-int radio_isa_remove(struct device *pdev, unsigned int dev)
-{
- struct radio_isa_card *isa = dev_get_drvdata(pdev);
- const struct radio_isa_ops *ops = isa->drv->ops;
-
- ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0);
- video_unregister_device(&isa->vdev);
- v4l2_ctrl_handler_free(&isa->hdl);
- v4l2_device_unregister(&isa->v4l2_dev);
- release_region(isa->io, isa->drv->region_size);
- v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card);
- kfree(isa);
- return 0;
-}
-EXPORT_SYMBOL_GPL(radio_isa_remove);
diff --git a/trunk/drivers/media/radio/radio-isa.h b/trunk/drivers/media/radio/radio-isa.h
deleted file mode 100644
index 8a0ea84d86de..000000000000
--- a/trunk/drivers/media/radio/radio-isa.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Framework for ISA radio drivers.
- * This takes care of all the V4L2 scaffolding, allowing the ISA drivers
- * to concentrate on the actual hardware operation.
- *
- * Copyright (C) 2012 Hans Verkuil
- *
- * 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
- */
-
-#ifndef _RADIO_ISA_H_
-#define _RADIO_ISA_H_
-
-#include
-#include
-#include
-#include
-
-struct radio_isa_driver;
-struct radio_isa_ops;
-
-/* Core structure for radio ISA cards */
-struct radio_isa_card {
- const struct radio_isa_driver *drv;
- struct v4l2_device v4l2_dev;
- struct v4l2_ctrl_handler hdl;
- struct video_device vdev;
- struct mutex lock;
- const struct radio_isa_ops *ops;
- struct { /* mute/volume cluster */
- struct v4l2_ctrl *mute;
- struct v4l2_ctrl *volume;
- };
- /* I/O port */
- int io;
-
- /* Card is in stereo audio mode */
- bool stereo;
- /* Current frequency */
- u32 freq;
-};
-
-struct radio_isa_ops {
- /* Allocate and initialize a radio_isa_card struct */
- struct radio_isa_card *(*alloc)(void);
- /* Probe whether a card is present at the given port */
- bool (*probe)(struct radio_isa_card *isa, int io);
- /* Special card initialization can be done here, this is called after
- * the standard controls are registered, but before they are setup,
- * thus allowing drivers to add their own controls here. */
- int (*init)(struct radio_isa_card *isa);
- /* Set mute and volume. */
- int (*s_mute_volume)(struct radio_isa_card *isa, bool mute, int volume);
- /* Set frequency */
- int (*s_frequency)(struct radio_isa_card *isa, u32 freq);
- /* Set stereo/mono audio mode */
- int (*s_stereo)(struct radio_isa_card *isa, bool stereo);
- /* Get rxsubchans value for VIDIOC_G_TUNER */
- u32 (*g_rxsubchans)(struct radio_isa_card *isa);
- /* Get the signal strength for VIDIOC_G_TUNER */
- u32 (*g_signal)(struct radio_isa_card *isa);
-};
-
-/* Top level structure needed to instantiate the cards */
-struct radio_isa_driver {
- struct isa_driver driver;
- const struct radio_isa_ops *ops;
- /* The module_param_array with the specified I/O ports */
- int *io_params;
- /* The module_param_array with the radio_nr values */
- int *radio_nr_params;
- /* Whether we should probe for possible cards */
- bool probe;
- /* The list of possible I/O ports */
- const int *io_ports;
- /* The size of that list */
- int num_of_io_ports;
- /* The region size to request */
- unsigned region_size;
- /* The name of the card */
- const char *card;
- /* Card can capture stereo audio */
- bool has_stereo;
- /* The maximum volume for the volume control. If 0, then there
- is no volume control possible. */
- int max_volume;
-};
-
-int radio_isa_match(struct device *pdev, unsigned int dev);
-int radio_isa_probe(struct device *pdev, unsigned int dev);
-int radio_isa_remove(struct device *pdev, unsigned int dev);
-
-#endif
diff --git a/trunk/drivers/media/radio/radio-keene.c b/trunk/drivers/media/radio/radio-keene.c
deleted file mode 100644
index 55bd1d2937c8..000000000000
--- a/trunk/drivers/media/radio/radio-keene.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (c) 2012 Hans Verkuil
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* kernel includes */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* driver and module definitions */
-MODULE_AUTHOR("Hans Verkuil ");
-MODULE_DESCRIPTION("Keene FM Transmitter driver");
-MODULE_LICENSE("GPL");
-
-/* Actually, it advertises itself as a Logitech */
-#define USB_KEENE_VENDOR 0x046d
-#define USB_KEENE_PRODUCT 0x0a0e
-
-/* Probably USB_TIMEOUT should be modified in module parameter */
-#define BUFFER_LENGTH 8
-#define USB_TIMEOUT 500
-
-/* Frequency limits in MHz */
-#define FREQ_MIN 76U
-#define FREQ_MAX 108U
-#define FREQ_MUL 16000U
-
-/* USB Device ID List */
-static struct usb_device_id usb_keene_device_table[] = {
- {USB_DEVICE_AND_INTERFACE_INFO(USB_KEENE_VENDOR, USB_KEENE_PRODUCT,
- USB_CLASS_HID, 0, 0) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, usb_keene_device_table);
-
-struct keene_device {
- struct usb_device *usbdev;
- struct usb_interface *intf;
- struct video_device vdev;
- struct v4l2_device v4l2_dev;
- struct v4l2_ctrl_handler hdl;
- struct mutex lock;
-
- u8 *buffer;
- unsigned curfreq;
- u8 tx;
- u8 pa;
- bool stereo;
- bool muted;
- bool preemph_75_us;
-};
-
-static inline struct keene_device *to_keene_dev(struct v4l2_device *v4l2_dev)
-{
- return container_of(v4l2_dev, struct keene_device, v4l2_dev);
-}
-
-/* Set frequency (if non-0), PA, mute and turn on/off the FM transmitter. */
-static int keene_cmd_main(struct keene_device *radio, unsigned freq, bool play)
-{
- unsigned short freq_send = freq ? (freq - 76 * 16000) / 800 : 0;
- int ret;
-
- radio->buffer[0] = 0x00;
- radio->buffer[1] = 0x50;
- radio->buffer[2] = (freq_send >> 8) & 0xff;
- radio->buffer[3] = freq_send & 0xff;
- radio->buffer[4] = radio->pa;
- /* If bit 4 is set, then tune to the frequency.
- If bit 3 is set, then unmute; if bit 2 is set, then mute.
- If bit 1 is set, then enter idle mode; if bit 0 is set,
- then enter transit mode.
- */
- radio->buffer[5] = (radio->muted ? 4 : 8) | (play ? 1 : 2) |
- (freq ? 0x10 : 0);
- radio->buffer[6] = 0x00;
- radio->buffer[7] = 0x00;
-
- ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
- 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
-
- if (ret < 0) {
- dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret);
- return ret;
- }
- if (freq)
- radio->curfreq = freq;
- return 0;
-}
-
-/* Set TX, stereo and preemphasis mode (50 us vs 75 us). */
-static int keene_cmd_set(struct keene_device *radio)
-{
- int ret;
-
- radio->buffer[0] = 0x00;
- radio->buffer[1] = 0x51;
- radio->buffer[2] = radio->tx;
- /* If bit 0 is set, then transmit mono, otherwise stereo.
- If bit 2 is set, then enable 75 us preemphasis, otherwise
- it is 50 us. */
- radio->buffer[3] = (!radio->stereo) | (radio->preemph_75_us ? 4 : 0);
- radio->buffer[4] = 0x00;
- radio->buffer[5] = 0x00;
- radio->buffer[6] = 0x00;
- radio->buffer[7] = 0x00;
-
- ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
- 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
-
- if (ret < 0) {
- dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret);
- return ret;
- }
- return 0;
-}
-
-/* Handle unplugging the device.
- * We call video_unregister_device in any case.
- * The last function called in this procedure is
- * usb_keene_device_release.
- */
-static void usb_keene_disconnect(struct usb_interface *intf)
-{
- struct keene_device *radio = to_keene_dev(usb_get_intfdata(intf));
-
- v4l2_device_get(&radio->v4l2_dev);
- mutex_lock(&radio->lock);
- usb_set_intfdata(intf, NULL);
- video_unregister_device(&radio->vdev);
- v4l2_device_disconnect(&radio->v4l2_dev);
- mutex_unlock(&radio->lock);
- v4l2_device_put(&radio->v4l2_dev);
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- struct keene_device *radio = video_drvdata(file);
-
- strlcpy(v->driver, "radio-keene", sizeof(v->driver));
- strlcpy(v->card, "Keene FM Transmitter", sizeof(v->card));
- usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
- v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_MODULATOR;
- v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
- return 0;
-}
-
-static int vidioc_g_modulator(struct file *file, void *priv,
- struct v4l2_modulator *v)
-{
- struct keene_device *radio = video_drvdata(file);
-
- if (v->index > 0)
- return -EINVAL;
-
- strlcpy(v->name, "FM", sizeof(v->name));
- v->rangelow = FREQ_MIN * FREQ_MUL;
- v->rangehigh = FREQ_MAX * FREQ_MUL;
- v->txsubchans = radio->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
- v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
- return 0;
-}
-
-static int vidioc_s_modulator(struct file *file, void *priv,
- struct v4l2_modulator *v)
-{
- struct keene_device *radio = video_drvdata(file);
-
- if (v->index > 0)
- return -EINVAL;
-
- radio->stereo = (v->txsubchans == V4L2_TUNER_SUB_STEREO);
- return keene_cmd_set(radio);
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct keene_device *radio = video_drvdata(file);
-
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
- return -EINVAL;
- f->frequency = clamp(f->frequency,
- FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
- return keene_cmd_main(radio, f->frequency, true);
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct keene_device *radio = video_drvdata(file);
-
- if (f->tuner != 0)
- return -EINVAL;
- f->type = V4L2_TUNER_RADIO;
- f->frequency = radio->curfreq;
- return 0;
-}
-
-static int keene_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- static const u8 db2tx[] = {
- /* -15, -12, -9, -6, -3, 0 dB */
- 0x03, 0x13, 0x02, 0x12, 0x22, 0x32,
- /* 3, 6, 9, 12, 15, 18 dB */
- 0x21, 0x31, 0x20, 0x30, 0x40, 0x50
- };
- struct keene_device *radio =
- container_of(ctrl->handler, struct keene_device, hdl);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- radio->muted = ctrl->val;
- return keene_cmd_main(radio, 0, true);
-
- case V4L2_CID_TUNE_POWER_LEVEL:
- /* To go from dBuV to the register value we apply the
- following formula: */
- radio->pa = (ctrl->val - 71) * 100 / 62;
- return keene_cmd_main(radio, 0, true);
-
- case V4L2_CID_TUNE_PREEMPHASIS:
- radio->preemph_75_us = ctrl->val == V4L2_PREEMPHASIS_75_uS;
- return keene_cmd_set(radio);
-
- case V4L2_CID_AUDIO_COMPRESSION_GAIN:
- radio->tx = db2tx[(ctrl->val - ctrl->minimum) / ctrl->step];
- return keene_cmd_set(radio);
- }
- return -EINVAL;
-}
-
-static int vidioc_subscribe_event(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- switch (sub->type) {
- case V4L2_EVENT_CTRL:
- return v4l2_event_subscribe(fh, sub, 0);
- default:
- return -EINVAL;
- }
-}
-
-
-/* File system interface */
-static const struct v4l2_file_operations usb_keene_fops = {
- .owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = v4l2_fh_release,
- .poll = v4l2_ctrl_poll,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ctrl_ops keene_ctrl_ops = {
- .s_ctrl = keene_s_ctrl,
-};
-
-static const struct v4l2_ioctl_ops usb_keene_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_g_modulator = vidioc_g_modulator,
- .vidioc_s_modulator = vidioc_s_modulator,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_log_status = v4l2_ctrl_log_status,
- .vidioc_subscribe_event = vidioc_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-static void usb_keene_video_device_release(struct v4l2_device *v4l2_dev)
-{
- struct keene_device *radio = to_keene_dev(v4l2_dev);
-
- /* free rest memory */
- v4l2_ctrl_handler_free(&radio->hdl);
- kfree(radio->buffer);
- kfree(radio);
-}
-
-/* check if the device is present and register with v4l and usb if it is */
-static int usb_keene_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *dev = interface_to_usbdev(intf);
- struct keene_device *radio;
- struct v4l2_ctrl_handler *hdl;
- int retval = 0;
-
- /*
- * The Keene FM transmitter USB device has the same USB ID as
- * the Logitech AudioHub Speaker, but it should ignore the hid.
- * Check if the name is that of the Keene device.
- * If not, then someone connected the AudioHub and we shouldn't
- * attempt to handle this driver.
- * For reference: the product name of the AudioHub is
- * "AudioHub Speaker".
- */
- if (dev->product && strcmp(dev->product, "B-LINK USB Audio "))
- return -ENODEV;
-
- radio = kzalloc(sizeof(struct keene_device), GFP_KERNEL);
- if (radio)
- radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
-
- if (!radio || !radio->buffer) {
- dev_err(&intf->dev, "kmalloc for keene_device failed\n");
- kfree(radio);
- retval = -ENOMEM;
- goto err;
- }
-
- hdl = &radio->hdl;
- v4l2_ctrl_handler_init(hdl, 4);
- v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_MUTE,
- 0, 1, 1, 0);
- v4l2_ctrl_new_std_menu(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS,
- V4L2_PREEMPHASIS_75_uS, 1, V4L2_PREEMPHASIS_50_uS);
- v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_POWER_LEVEL,
- 84, 118, 1, 118);
- v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_GAIN,
- -15, 18, 3, 0);
- radio->pa = 118;
- radio->tx = 0x32;
- radio->stereo = true;
- radio->curfreq = 95.16 * FREQ_MUL;
- if (hdl->error) {
- retval = hdl->error;
-
- v4l2_ctrl_handler_free(hdl);
- goto err_v4l2;
- }
- retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
- if (retval < 0) {
- dev_err(&intf->dev, "couldn't register v4l2_device\n");
- goto err_v4l2;
- }
-
- mutex_init(&radio->lock);
-
- radio->v4l2_dev.ctrl_handler = hdl;
- radio->v4l2_dev.release = usb_keene_video_device_release;
- strlcpy(radio->vdev.name, radio->v4l2_dev.name,
- sizeof(radio->vdev.name));
- radio->vdev.v4l2_dev = &radio->v4l2_dev;
- radio->vdev.fops = &usb_keene_fops;
- radio->vdev.ioctl_ops = &usb_keene_ioctl_ops;
- radio->vdev.lock = &radio->lock;
- radio->vdev.release = video_device_release_empty;
-
- radio->usbdev = interface_to_usbdev(intf);
- radio->intf = intf;
- usb_set_intfdata(intf, &radio->v4l2_dev);
-
- video_set_drvdata(&radio->vdev, radio);
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
-
- retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1);
- if (retval < 0) {
- dev_err(&intf->dev, "could not register video device\n");
- goto err_vdev;
- }
- v4l2_ctrl_handler_setup(hdl);
- dev_info(&intf->dev, "V4L2 device registered as %s\n",
- video_device_node_name(&radio->vdev));
- return 0;
-
-err_vdev:
- v4l2_device_unregister(&radio->v4l2_dev);
-err_v4l2:
- kfree(radio->buffer);
- kfree(radio);
-err:
- return retval;
-}
-
-/* USB subsystem interface */
-static struct usb_driver usb_keene_driver = {
- .name = "radio-keene",
- .probe = usb_keene_probe,
- .disconnect = usb_keene_disconnect,
- .id_table = usb_keene_device_table,
-};
-
-static int __init keene_init(void)
-{
- int retval = usb_register(&usb_keene_driver);
-
- if (retval)
- pr_err(KBUILD_MODNAME
- ": usb_register failed. Error number %d\n", retval);
-
- return retval;
-}
-
-static void __exit keene_exit(void)
-{
- usb_deregister(&usb_keene_driver);
-}
-
-module_init(keene_init);
-module_exit(keene_exit);
-
diff --git a/trunk/drivers/media/radio/radio-maxiradio.c b/trunk/drivers/media/radio/radio-maxiradio.c
index 740a3d5520c7..f872a54cf3d9 100644
--- a/trunk/drivers/media/radio/radio-maxiradio.c
+++ b/trunk/drivers/media/radio/radio-maxiradio.c
@@ -42,37 +42,67 @@
#include
#include
#include
-#include
#include
#include
-#include
-#include
-#include
+
+#define DRIVER_VERSION "0.7.8"
+
MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net");
-MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000.");
+MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio.");
MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.0");
+MODULE_VERSION(DRIVER_VERSION);
static int radio_nr = -1;
-module_param(radio_nr, int, 0644);
-MODULE_PARM_DESC(radio_nr, "Radio device number");
+module_param(radio_nr, int, 0);
-/* TEA5757 pin mappings */
-static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16;
+static int debug;
-static atomic_t maxiradio_instance = ATOMIC_INIT(0);
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+#define dprintk(dev, num, fmt, arg...) \
+ v4l2_dbg(num, debug, &dev->v4l2_dev, fmt, ## arg)
+
+#ifndef PCI_VENDOR_ID_GUILLEMOT
#define PCI_VENDOR_ID_GUILLEMOT 0x5046
+#endif
+
+#ifndef PCI_DEVICE_ID_GUILLEMOT
#define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001
+#endif
+
+
+/* TEA5757 pin mappings */
+static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16;
+
+#define FREQ_LO (87 * 16000)
+#define FREQ_HI (108 * 16000)
+
+#define FREQ_IF 171200 /* 10.7*16000 */
+#define FREQ_STEP 200 /* 12.5*16 */
+
+/* (x==fmhz*16*1000) -> bits */
+#define FREQ2BITS(x) \
+ ((((unsigned int)(x) + FREQ_IF + (FREQ_STEP << 1)) / (FREQ_STEP << 2)) << 2)
+
+#define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF)
+
struct maxiradio
{
- struct snd_tea575x tea;
struct v4l2_device v4l2_dev;
+ struct video_device vdev;
struct pci_dev *pdev;
u16 io; /* base of radio io */
+ u16 muted; /* VIDEO_AUDIO_MUTE */
+ u16 stereo; /* VIDEO_TUNER_STEREO_ON */
+ u16 tuned; /* signal strength (0 or 0xffff) */
+
+ unsigned long freq;
+
+ struct mutex lock;
};
static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev)
@@ -80,41 +110,259 @@ static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev)
return container_of(v4l2_dev, struct maxiradio, v4l2_dev);
}
-static void maxiradio_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
+static void outbit(unsigned long bit, u16 io)
+{
+ int val = power | wren | (bit ? data : 0);
+
+ outb(val, io);
+ udelay(4);
+ outb(val | clk, io);
+ udelay(4);
+ outb(val, io);
+ udelay(4);
+}
+
+static void turn_power(struct maxiradio *dev, int p)
+{
+ if (p != 0) {
+ dprintk(dev, 1, "Radio powered on\n");
+ outb(power, dev->io);
+ } else {
+ dprintk(dev, 1, "Radio powered off\n");
+ outb(0, dev->io);
+ }
+}
+
+static void set_freq(struct maxiradio *dev, u32 freq)
+{
+ unsigned long int si;
+ int bl;
+ int io = dev->io;
+ int val = FREQ2BITS(freq);
+
+ /* TEA5757 shift register bits (see pdf) */
+
+ outbit(0, io); /* 24 search */
+ outbit(1, io); /* 23 search up/down */
+
+ outbit(0, io); /* 22 stereo/mono */
+
+ outbit(0, io); /* 21 band */
+ outbit(0, io); /* 20 band (only 00=FM works I think) */
+
+ outbit(0, io); /* 19 port ? */
+ outbit(0, io); /* 18 port ? */
+
+ outbit(0, io); /* 17 search level */
+ outbit(0, io); /* 16 search level */
+
+ si = 0x8000;
+ for (bl = 1; bl <= 16; bl++) {
+ outbit(val & si, io);
+ si >>= 1;
+ }
+
+ dprintk(dev, 1, "Radio freq set to %d.%02d MHz\n",
+ freq / 16000,
+ freq % 16000 * 100 / 16000);
+
+ turn_power(dev, 1);
+}
+
+static int get_stereo(u16 io)
{
- struct maxiradio *dev = tea->private_data;
- u8 bits = 0;
+ outb(power,io);
+ udelay(4);
- bits |= (pins & TEA575X_DATA) ? data : 0;
- bits |= (pins & TEA575X_CLK) ? clk : 0;
- bits |= (pins & TEA575X_WREN) ? wren : 0;
- bits |= power;
+ return !(inb(io) & mo_st);
+}
- outb(bits, dev->io);
+static int get_tune(u16 io)
+{
+ outb(power+clk,io);
+ udelay(4);
+
+ return !(inb(io) & mo_st);
+}
+
+
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *v)
+{
+ struct maxiradio *dev = video_drvdata(file);
+
+ strlcpy(v->driver, "radio-maxiradio", sizeof(v->driver));
+ strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof(v->card));
+ snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev));
+ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ return 0;
}
-/* Note: this card cannot read out the data of the shift registers,
- only the mono/stereo pin works. */
-static u8 maxiradio_tea575x_get_pins(struct snd_tea575x *tea)
+static int vidioc_g_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
{
- struct maxiradio *dev = tea->private_data;
- u8 bits = inb(dev->io);
+ struct maxiradio *dev = video_drvdata(file);
+
+ if (v->index > 0)
+ return -EINVAL;
+
+ mutex_lock(&dev->lock);
+ strlcpy(v->name, "FM", sizeof(v->name));
+ v->type = V4L2_TUNER_RADIO;
+ v->rangelow = FREQ_LO;
+ v->rangehigh = FREQ_HI;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+ v->capability = V4L2_TUNER_CAP_LOW;
+ if (get_stereo(dev->io))
+ v->audmode = V4L2_TUNER_MODE_STEREO;
+ else
+ v->audmode = V4L2_TUNER_MODE_MONO;
+ v->signal = 0xffff * get_tune(dev->io);
+ mutex_unlock(&dev->lock);
- return ((bits & data) ? TEA575X_DATA : 0) |
- ((bits & mo_st) ? TEA575X_MOST : 0);
+ return 0;
}
-static void maxiradio_tea575x_set_direction(struct snd_tea575x *tea, bool output)
+static int vidioc_s_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
{
+ return v->index ? -EINVAL : 0;
}
-static struct snd_tea575x_ops maxiradio_tea_ops = {
- .set_pins = maxiradio_tea575x_set_pins,
- .get_pins = maxiradio_tea575x_get_pins,
- .set_direction = maxiradio_tea575x_set_direction,
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+ return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ a->index = 0;
+ strlcpy(a->name, "Radio", sizeof(a->name));
+ a->capability = V4L2_AUDCAP_STEREO;
+ return 0;
+}
+
+
+static int vidioc_s_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ return a->index ? -EINVAL : 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct maxiradio *dev = video_drvdata(file);
+
+ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+ return -EINVAL;
+ if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) {
+ dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n",
+ f->frequency / 16000,
+ f->frequency % 16000 * 100 / 16000,
+ FREQ_LO / 16000, FREQ_HI / 16000);
+
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev->lock);
+ dev->freq = f->frequency;
+ set_freq(dev, dev->freq);
+ msleep(125);
+ mutex_unlock(&dev->lock);
+
+ return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct maxiradio *dev = video_drvdata(file);
+
+ if (f->tuner != 0)
+ return -EINVAL;
+ f->type = V4L2_TUNER_RADIO;
+ f->frequency = dev->freq;
+
+ dprintk(dev, 4, "radio freq is %d.%02d MHz",
+ f->frequency / 16000,
+ f->frequency % 16000 * 100 / 16000);
+
+ return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ switch (qc->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+ }
+ return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct maxiradio *dev = video_drvdata(file);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = dev->muted;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct maxiradio *dev = video_drvdata(file);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ mutex_lock(&dev->lock);
+ dev->muted = ctrl->value;
+ if (dev->muted)
+ turn_power(dev, 0);
+ else
+ set_freq(dev, dev->freq);
+ mutex_unlock(&dev->lock);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static const struct v4l2_file_operations maxiradio_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = video_ioctl2,
};
-static int __devinit maxiradio_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+};
+
+static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct maxiradio *dev;
struct v4l2_device *v4l2_dev;
@@ -127,60 +375,63 @@ static int __devinit maxiradio_probe(struct pci_dev *pdev, const struct pci_devi
}
v4l2_dev = &dev->v4l2_dev;
- v4l2_device_set_name(v4l2_dev, "maxiradio", &maxiradio_instance);
+ mutex_init(&dev->lock);
+ dev->pdev = pdev;
+ dev->muted = 1;
+ dev->freq = FREQ_LO;
+
+ strlcpy(v4l2_dev->name, "maxiradio", sizeof(v4l2_dev->name));
retval = v4l2_device_register(&pdev->dev, v4l2_dev);
if (retval < 0) {
v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
goto errfr;
}
- dev->tea.private_data = dev;
- dev->tea.ops = &maxiradio_tea_ops;
- /* The data pin cannot be read. This may be a hardware limitation, or
- we just don't know how to read it. */
- dev->tea.cannot_read_data = true;
- dev->tea.v4l2_dev = v4l2_dev;
- dev->tea.radio_nr = radio_nr;
- strlcpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card));
- snprintf(dev->tea.bus_info, sizeof(dev->tea.bus_info),
- "PCI:%s", pci_name(pdev));
-
- retval = -ENODEV;
if (!request_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0), v4l2_dev->name)) {
- dev_err(&pdev->dev, "can't reserve I/O ports\n");
- goto err_hdl;
+ pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) {
+ v4l2_err(v4l2_dev, "can't reserve I/O ports\n");
+ goto err_out;
}
if (pci_enable_device(pdev))
goto err_out_free_region;
dev->io = pci_resource_start(pdev, 0);
- if (snd_tea575x_init(&dev->tea)) {
- printk(KERN_ERR "radio-maxiradio: Unable to detect TEA575x tuner\n");
+ strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+ dev->vdev.v4l2_dev = v4l2_dev;
+ dev->vdev.fops = &maxiradio_fops;
+ dev->vdev.ioctl_ops = &maxiradio_ioctl_ops;
+ dev->vdev.release = video_device_release_empty;
+ video_set_drvdata(&dev->vdev, dev);
+
+ if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+ v4l2_err(v4l2_dev, "can't register device!");
goto err_out_free_region;
}
+
+ v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n");
+
+ v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n",
+ dev->io);
return 0;
err_out_free_region:
release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-err_hdl:
+err_out:
v4l2_device_unregister(v4l2_dev);
errfr:
kfree(dev);
- return retval;
+ return -ENODEV;
}
-static void __devexit maxiradio_remove(struct pci_dev *pdev)
+static void __devexit maxiradio_remove_one(struct pci_dev *pdev)
{
struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
struct maxiradio *dev = to_maxiradio(v4l2_dev);
- snd_tea575x_exit(&dev->tea);
- /* Turn off power */
- outb(0, dev->io);
- v4l2_device_unregister(v4l2_dev);
+ video_unregister_device(&dev->vdev);
+ v4l2_device_unregister(&dev->v4l2_dev);
release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
}
@@ -195,19 +446,19 @@ MODULE_DEVICE_TABLE(pci, maxiradio_pci_tbl);
static struct pci_driver maxiradio_driver = {
.name = "radio-maxiradio",
.id_table = maxiradio_pci_tbl,
- .probe = maxiradio_probe,
- .remove = __devexit_p(maxiradio_remove),
+ .probe = maxiradio_init_one,
+ .remove = __devexit_p(maxiradio_remove_one),
};
-static int __init maxiradio_init(void)
+static int __init maxiradio_radio_init(void)
{
return pci_register_driver(&maxiradio_driver);
}
-static void __exit maxiradio_exit(void)
+static void __exit maxiradio_radio_exit(void)
{
pci_unregister_driver(&maxiradio_driver);
}
-module_init(maxiradio_init);
-module_exit(maxiradio_exit);
+module_init(maxiradio_radio_init);
+module_exit(maxiradio_radio_exit);
diff --git a/trunk/drivers/media/radio/radio-rtrack2.c b/trunk/drivers/media/radio/radio-rtrack2.c
index b275c5d0fe9a..3628be617ee9 100644
--- a/trunk/drivers/media/radio/radio-rtrack2.c
+++ b/trunk/drivers/media/radio/radio-rtrack2.c
@@ -1,12 +1,11 @@
-/*
- * RadioTrack II driver
- * Copyright 1998 Ben Pfaff
+/* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
*
* Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
* Converted to new API by Alan Cox
* Various bugfixes and enhancements by Russell Kroll
*
- * Converted to the radio-isa framework by Hans Verkuil
+ * TODO: Allow for more than one of these foolish entities :-)
+ *
* Converted to V4L2 API by Mauro Carvalho Chehab
*/
@@ -19,120 +18,323 @@
#include /* outb, outb_p */
#include
#include